about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/ci.yml17
-rw-r--r--.mailmap2
-rw-r--r--Cargo.lock91
-rw-r--r--Cargo.toml2
-rw-r--r--compiler/rustc_ast/src/ast.rs68
-rw-r--r--compiler/rustc_ast/src/ast_traits.rs6
-rw-r--r--compiler/rustc_ast/src/mut_visit.rs656
-rw-r--r--compiler/rustc_ast/src/visit.rs1109
-rw-r--r--compiler/rustc_ast_lowering/src/delegation.rs8
-rw-r--r--compiler/rustc_ast_lowering/src/expr.rs15
-rw-r--r--compiler/rustc_ast_lowering/src/index.rs2
-rw-r--r--compiler/rustc_ast_lowering/src/item.rs42
-rw-r--r--compiler/rustc_ast_lowering/src/lib.rs16
-rw-r--r--compiler/rustc_ast_lowering/src/path.rs8
-rw-r--r--compiler/rustc_ast_passes/src/ast_validation.rs6
-rw-r--r--compiler/rustc_ast_passes/src/feature_gate.rs7
-rw-r--r--compiler/rustc_ast_pretty/src/pprust/state/item.rs8
-rw-r--r--compiler/rustc_attr_parsing/src/attributes/allow_unstable.rs4
-rw-r--r--compiler/rustc_attr_parsing/src/attributes/cfg.rs27
-rw-r--r--compiler/rustc_attr_parsing/src/attributes/deprecation.rs4
-rw-r--r--compiler/rustc_attr_parsing/src/attributes/mod.rs8
-rw-r--r--compiler/rustc_attr_parsing/src/attributes/repr.rs6
-rw-r--r--compiler/rustc_attr_parsing/src/attributes/stability.rs2
-rw-r--r--compiler/rustc_attr_parsing/src/attributes/transparency.rs6
-rw-r--r--compiler/rustc_attr_parsing/src/context.rs62
-rw-r--r--compiler/rustc_attr_parsing/src/parser.rs3
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs24
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/region_name.rs8
-rw-r--r--compiler/rustc_borrowck/src/lib.rs9
-rw-r--r--compiler/rustc_borrowck/src/nll.rs6
-rw-r--r--compiler/rustc_borrowck/src/region_infer/mod.rs12
-rw-r--r--compiler/rustc_borrowck/src/region_infer/opaque_types.rs4
-rw-r--r--compiler/rustc_borrowck/src/region_infer/reverse_sccs.rs13
-rw-r--r--compiler/rustc_borrowck/src/type_check/constraint_conversion.rs2
-rw-r--r--compiler/rustc_borrowck/src/type_check/input_output.rs2
-rw-r--r--compiler/rustc_borrowck/src/type_check/liveness/mod.rs7
-rw-r--r--compiler/rustc_borrowck/src/type_check/liveness/trace.rs71
-rw-r--r--compiler/rustc_borrowck/src/type_check/mod.rs23
-rw-r--r--compiler/rustc_borrowck/src/type_check/opaque_types.rs2
-rw-r--r--compiler/rustc_builtin_macros/Cargo.toml3
-rw-r--r--compiler/rustc_builtin_macros/messages.ftl33
-rw-r--r--compiler/rustc_builtin_macros/src/asm.rs365
-rw-r--r--compiler/rustc_builtin_macros/src/autodiff.rs67
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/clone.rs4
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/cmp/partial_eq.rs215
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs2
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/coerce_pointee.rs2
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/generic/mod.rs11
-rw-r--r--compiler/rustc_builtin_macros/src/errors.rs84
-rw-r--r--compiler/rustc_builtin_macros/src/iter.rs53
-rw-r--r--compiler/rustc_builtin_macros/src/lib.rs11
-rw-r--r--compiler/rustc_builtin_macros/src/test_harness.rs6
-rw-r--r--compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs3
-rw-r--r--compiler/rustc_codegen_gcc/src/abi.rs7
-rw-r--r--compiler/rustc_codegen_gcc/src/base.rs11
-rw-r--r--compiler/rustc_codegen_gcc/src/builder.rs10
-rw-r--r--compiler/rustc_codegen_gcc/src/consts.rs13
-rw-r--r--compiler/rustc_codegen_gcc/src/context.rs4
-rw-r--r--compiler/rustc_codegen_gcc/src/debuginfo.rs4
-rw-r--r--compiler/rustc_codegen_gcc/src/intrinsic/mod.rs97
-rw-r--r--compiler/rustc_codegen_gcc/src/intrinsic/simd.rs87
-rw-r--r--compiler/rustc_codegen_gcc/src/lib.rs6
-rw-r--r--compiler/rustc_codegen_gcc/src/mono_item.rs4
-rw-r--r--compiler/rustc_codegen_llvm/src/abi.rs10
-rw-r--r--compiler/rustc_codegen_llvm/src/back/lto.rs2
-rw-r--r--compiler/rustc_codegen_llvm/src/back/write.rs4
-rw-r--r--compiler/rustc_codegen_llvm/src/base.rs24
-rw-r--r--compiler/rustc_codegen_llvm/src/builder.rs31
-rw-r--r--compiler/rustc_codegen_llvm/src/consts.rs26
-rw-r--r--compiler/rustc_codegen_llvm/src/context.rs22
-rw-r--r--compiler/rustc_codegen_llvm/src/coverageinfo/ffi.rs26
-rw-r--r--compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs9
-rw-r--r--compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/covfun.rs50
-rw-r--r--compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/spans.rs28
-rw-r--r--compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs2
-rw-r--r--compiler/rustc_codegen_llvm/src/debuginfo/mod.rs10
-rw-r--r--compiler/rustc_codegen_llvm/src/intrinsic.rs192
-rw-r--r--compiler/rustc_codegen_llvm/src/lib.rs12
-rw-r--r--compiler/rustc_codegen_llvm/src/llvm/ffi.rs8
-rw-r--r--compiler/rustc_codegen_llvm/src/mono_item.rs4
-rw-r--r--compiler/rustc_codegen_llvm/src/va_arg.rs596
-rw-r--r--compiler/rustc_codegen_ssa/src/back/link.rs132
-rw-r--r--compiler/rustc_codegen_ssa/src/back/lto.rs11
-rw-r--r--compiler/rustc_codegen_ssa/src/back/write.rs18
-rw-r--r--compiler/rustc_codegen_ssa/src/base.rs5
-rw-r--r--compiler/rustc_codegen_ssa/src/common.rs9
-rw-r--r--compiler/rustc_codegen_ssa/src/meth.rs2
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/block.rs377
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/intrinsic.rs157
-rw-r--r--compiler/rustc_codegen_ssa/src/mono_item.rs36
-rw-r--r--compiler/rustc_codegen_ssa/src/traits/backend.rs18
-rw-r--r--compiler/rustc_codegen_ssa/src/traits/builder.rs12
-rw-r--r--compiler/rustc_codegen_ssa/src/traits/debuginfo.rs1
-rw-r--r--compiler/rustc_codegen_ssa/src/traits/declare.rs4
-rw-r--r--compiler/rustc_codegen_ssa/src/traits/intrinsic.rs9
-rw-r--r--compiler/rustc_codegen_ssa/src/traits/misc.rs4
-rw-r--r--compiler/rustc_codegen_ssa/src/traits/mod.rs2
-rw-r--r--compiler/rustc_codegen_ssa/src/traits/statics.rs14
-rw-r--r--compiler/rustc_codegen_ssa/src/traits/type_.rs1
-rw-r--r--compiler/rustc_codegen_ssa/src/traits/write.rs8
-rw-r--r--compiler/rustc_const_eval/messages.ftl3
-rw-r--r--compiler/rustc_const_eval/src/check_consts/check.rs7
-rw-r--r--compiler/rustc_const_eval/src/check_consts/ops.rs23
-rw-r--r--compiler/rustc_const_eval/src/const_eval/dummy_machine.rs9
-rw-r--r--compiler/rustc_const_eval/src/const_eval/eval_queries.rs7
-rw-r--r--compiler/rustc_const_eval/src/const_eval/machine.rs11
-rw-r--r--compiler/rustc_const_eval/src/errors.rs5
-rw-r--r--compiler/rustc_const_eval/src/interpret/call.rs52
-rw-r--r--compiler/rustc_const_eval/src/interpret/intrinsics.rs137
-rw-r--r--compiler/rustc_const_eval/src/interpret/machine.rs20
-rw-r--r--compiler/rustc_const_eval/src/interpret/memory.rs8
-rw-r--r--compiler/rustc_const_eval/src/interpret/operand.rs2
-rw-r--r--compiler/rustc_const_eval/src/interpret/stack.rs62
-rw-r--r--compiler/rustc_const_eval/src/interpret/step.rs2
-rw-r--r--compiler/rustc_const_eval/src/interpret/util.rs2
-rw-r--r--compiler/rustc_const_eval/src/util/type_name.rs2
-rw-r--r--compiler/rustc_data_structures/src/flock.rs13
-rw-r--r--compiler/rustc_data_structures/src/lib.rs3
-rw-r--r--compiler/rustc_data_structures/src/profiling.rs13
-rw-r--r--compiler/rustc_driver_impl/src/lib.rs1
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0658.md12
-rw-r--r--compiler/rustc_error_messages/Cargo.toml4
-rw-r--r--compiler/rustc_errors/src/diagnostic.rs2
-rw-r--r--compiler/rustc_errors/src/lib.rs1
-rw-r--r--compiler/rustc_expand/Cargo.toml3
-rw-r--r--compiler/rustc_expand/src/base.rs2
-rw-r--r--compiler/rustc_expand/src/config.rs3
-rw-r--r--compiler/rustc_expand/src/expand.rs107
-rw-r--r--compiler/rustc_expand/src/lib.rs2
-rw-r--r--compiler/rustc_expand/src/placeholders.rs2
-rw-r--r--compiler/rustc_expand/src/proc_macro.rs2
-rw-r--r--compiler/rustc_expand/src/proc_macro_server.rs16
-rw-r--r--compiler/rustc_feature/src/accepted.rs2
-rw-r--r--compiler/rustc_feature/src/unstable.rs4
-rw-r--r--compiler/rustc_fluent_macro/Cargo.toml4
-rw-r--r--compiler/rustc_hir/src/arena.rs1
-rw-r--r--compiler/rustc_hir/src/def.rs12
-rw-r--r--compiler/rustc_hir/src/hir.rs80
-rw-r--r--compiler/rustc_hir/src/intravisit.rs255
-rw-r--r--compiler/rustc_hir_analysis/src/check/check.rs19
-rw-r--r--compiler/rustc_hir_analysis/src/check/compare_impl_item.rs4
-rw-r--r--compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/check/intrinsic.rs14
-rw-r--r--compiler/rustc_hir_analysis/src/check/wfcheck.rs70
-rw-r--r--compiler/rustc_hir_analysis/src/collect.rs30
-rw-r--r--compiler/rustc_hir_analysis/src/collect/item_bounds.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs10
-rw-r--r--compiler/rustc_hir_analysis/src/collect/type_of.rs8
-rw-r--r--compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs7
-rw-r--r--compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs6
-rw-r--r--compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs8
-rw-r--r--compiler/rustc_hir_analysis/src/hir_wf_check.rs6
-rw-r--r--compiler/rustc_hir_analysis/src/lib.rs4
-rw-r--r--compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs4
-rw-r--r--compiler/rustc_hir_analysis/src/outlives/mod.rs4
-rw-r--r--compiler/rustc_hir_analysis/src/outlives/utils.rs6
-rw-r--r--compiler/rustc_hir_analysis/src/variance/constraints.rs10
-rw-r--r--compiler/rustc_hir_pretty/src/lib.rs40
-rw-r--r--compiler/rustc_hir_typeck/src/cast.rs10
-rw-r--r--compiler/rustc_hir_typeck/src/closure.rs20
-rw-r--r--compiler/rustc_hir_typeck/src/coercion.rs18
-rw-r--r--compiler/rustc_hir_typeck/src/demand.rs4
-rw-r--r--compiler/rustc_hir_typeck/src/expr.rs10
-rw-r--r--compiler/rustc_hir_typeck/src/expr_use_visitor.rs16
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs22
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs27
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs10
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs25
-rw-r--r--compiler/rustc_hir_typeck/src/method/suggest.rs4
-rw-r--r--compiler/rustc_hir_typeck/src/upvar.rs8
-rw-r--r--compiler/rustc_infer/src/infer/at.rs2
-rw-r--r--compiler/rustc_infer/src/infer/canonical/canonicalizer.rs8
-rw-r--r--compiler/rustc_infer/src/infer/canonical/instantiate.rs6
-rw-r--r--compiler/rustc_infer/src/infer/canonical/query_response.rs68
-rw-r--r--compiler/rustc_infer/src/infer/context.rs53
-rw-r--r--compiler/rustc_infer/src/infer/mod.rs23
-rw-r--r--compiler/rustc_infer/src/infer/opaque_types/table.rs6
-rw-r--r--compiler/rustc_infer/src/infer/outlives/obligations.rs55
-rw-r--r--compiler/rustc_infer/src/infer/relate/generalize.rs2
-rw-r--r--compiler/rustc_infer/src/infer/resolve.rs8
-rw-r--r--compiler/rustc_infer/src/infer/snapshot/undo_log.rs4
-rw-r--r--compiler/rustc_interface/src/passes.rs4
-rw-r--r--compiler/rustc_interface/src/tests.rs4
-rw-r--r--compiler/rustc_lint/messages.ftl10
-rw-r--r--compiler/rustc_lint/src/builtin.rs36
-rw-r--r--compiler/rustc_lint/src/default_could_be_derived.rs2
-rw-r--r--compiler/rustc_lint/src/early.rs41
-rw-r--r--compiler/rustc_lint/src/early/diagnostics.rs27
-rw-r--r--compiler/rustc_lint/src/hidden_unicode_codepoints.rs136
-rw-r--r--compiler/rustc_lint/src/impl_trait_overcaptures.rs2
-rw-r--r--compiler/rustc_lint/src/internal.rs20
-rw-r--r--compiler/rustc_lint/src/levels.rs2
-rw-r--r--compiler/rustc_lint/src/lib.rs7
-rw-r--r--compiler/rustc_lint/src/lints.rs114
-rw-r--r--compiler/rustc_lint/src/non_local_def.rs2
-rw-r--r--compiler/rustc_lint/src/nonstandard_style.rs2
-rw-r--r--compiler/rustc_lint/src/transmute.rs278
-rw-r--r--compiler/rustc_lint/src/types.rs62
-rw-r--r--compiler/rustc_lint/src/unqualified_local_imports.rs21
-rw-r--r--compiler/rustc_lint/src/unused.rs35
-rw-r--r--compiler/rustc_lint_defs/src/builtin.rs167
-rw-r--r--compiler/rustc_lint_defs/src/lib.rs86
-rw-r--r--compiler/rustc_llvm/build.rs4
-rw-r--r--compiler/rustc_metadata/Cargo.toml3
-rw-r--r--compiler/rustc_metadata/src/creader.rs20
-rw-r--r--compiler/rustc_metadata/src/lib.rs2
-rw-r--r--compiler/rustc_metadata/src/locator.rs2
-rw-r--r--compiler/rustc_metadata/src/rmeta/decoder.rs2
-rw-r--r--compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs5
-rw-r--r--compiler/rustc_middle/src/hir/map.rs4
-rw-r--r--compiler/rustc_middle/src/hir/place.rs3
-rw-r--r--compiler/rustc_middle/src/lint.rs5
-rw-r--r--compiler/rustc_middle/src/mir/interpret/allocation.rs60
-rw-r--r--compiler/rustc_middle/src/mir/interpret/queries.rs22
-rw-r--r--compiler/rustc_middle/src/mir/interpret/value.rs10
-rw-r--r--compiler/rustc_middle/src/mir/pretty.rs6
-rw-r--r--compiler/rustc_middle/src/mir/statement.rs78
-rw-r--r--compiler/rustc_middle/src/query/mod.rs5
-rw-r--r--compiler/rustc_middle/src/thir/visit.rs26
-rw-r--r--compiler/rustc_middle/src/ty/closure.rs4
-rw-r--r--compiler/rustc_middle/src/ty/consts/int.rs79
-rw-r--r--compiler/rustc_middle/src/ty/context.rs6
-rw-r--r--compiler/rustc_middle/src/ty/erase_regions.rs8
-rw-r--r--compiler/rustc_middle/src/ty/fold.rs4
-rw-r--r--compiler/rustc_middle/src/ty/generic_args.rs30
-rw-r--r--compiler/rustc_middle/src/ty/impls_ty.rs2
-rw-r--r--compiler/rustc_middle/src/ty/mod.rs30
-rw-r--r--compiler/rustc_middle/src/ty/opaque_types.rs6
-rw-r--r--compiler/rustc_middle/src/ty/predicate.rs2
-rw-r--r--compiler/rustc_middle/src/ty/print/pretty.rs6
-rw-r--r--compiler/rustc_middle/src/ty/relate.rs4
-rw-r--r--compiler/rustc_middle/src/ty/structural_impls.rs31
-rw-r--r--compiler/rustc_middle/src/ty/sty.rs6
-rw-r--r--compiler/rustc_middle/src/ty/typeck_results.rs4
-rw-r--r--compiler/rustc_middle/src/ty/util.rs6
-rw-r--r--compiler/rustc_middle/src/ty/vtable.rs2
-rw-r--r--compiler/rustc_mir_build/src/builder/custom/parse/instruction.rs4
-rw-r--r--compiler/rustc_mir_build/src/builder/expr/as_constant.rs6
-rw-r--r--compiler/rustc_mir_build/src/builder/expr/as_place.rs7
-rw-r--r--compiler/rustc_mir_build/src/builder/mod.rs2
-rw-r--r--compiler/rustc_mir_build/src/builder/scope.rs112
-rw-r--r--compiler/rustc_mir_build/src/check_unsafety.rs16
-rw-r--r--compiler/rustc_mir_build/src/thir/cx/expr.rs3
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/check_match.rs35
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs2
-rw-r--r--compiler/rustc_mir_transform/messages.ftl6
-rw-r--r--compiler/rustc_mir_transform/src/check_undefined_transmutes.rs77
-rw-r--r--compiler/rustc_mir_transform/src/check_unnecessary_transmutes.rs136
-rw-r--r--compiler/rustc_mir_transform/src/coverage/spans.rs38
-rw-r--r--compiler/rustc_mir_transform/src/elaborate_drop.rs33
-rw-r--r--compiler/rustc_mir_transform/src/errors.rs27
-rw-r--r--compiler/rustc_mir_transform/src/gvn.rs8
-rw-r--r--compiler/rustc_mir_transform/src/large_enums.rs1
-rw-r--r--compiler/rustc_mir_transform/src/lib.rs4
-rw-r--r--compiler/rustc_mir_transform/src/lower_intrinsics.rs46
-rw-r--r--compiler/rustc_mir_transform/src/match_branches.rs6
-rw-r--r--compiler/rustc_monomorphize/src/collector.rs2
-rw-r--r--compiler/rustc_next_trait_solver/src/canonicalizer.rs93
-rw-r--r--compiler/rustc_next_trait_solver/src/delegate.rs4
-rw-r--r--compiler/rustc_next_trait_solver/src/resolve.rs24
-rw-r--r--compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs26
-rw-r--r--compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs162
-rw-r--r--compiler/rustc_next_trait_solver/src/solve/mod.rs19
-rw-r--r--compiler/rustc_parse/messages.ftl24
-rw-r--r--compiler/rustc_parse/src/errors.rs70
-rw-r--r--compiler/rustc_parse/src/lexer/mod.rs89
-rw-r--r--compiler/rustc_parse/src/parser/asm.rs385
-rw-r--r--compiler/rustc_parse/src/parser/expr.rs54
-rw-r--r--compiler/rustc_parse/src/parser/item.rs6
-rw-r--r--compiler/rustc_parse/src/parser/mod.rs1
-rw-r--r--compiler/rustc_parse/src/parser/stmt.rs15
-rw-r--r--compiler/rustc_passes/src/check_attr.rs14
-rw-r--r--compiler/rustc_passes/src/check_export.rs2
-rw-r--r--compiler/rustc_passes/src/dead.rs256
-rw-r--r--compiler/rustc_passes/src/input_stats.rs10
-rw-r--r--compiler/rustc_passes/src/stability.rs2
-rw-r--r--compiler/rustc_pattern_analysis/src/rustc.rs6
-rw-r--r--compiler/rustc_privacy/src/lib.rs20
-rw-r--r--compiler/rustc_proc_macro/Cargo.toml21
-rw-r--r--compiler/rustc_resolve/src/build_reduced_graph.rs4
-rw-r--r--compiler/rustc_resolve/src/check_unused.rs18
-rw-r--r--compiler/rustc_resolve/src/def_collector.rs4
-rw-r--r--compiler/rustc_resolve/src/diagnostics.rs50
-rw-r--r--compiler/rustc_resolve/src/effective_visibilities.rs4
-rw-r--r--compiler/rustc_resolve/src/late.rs73
-rw-r--r--compiler/rustc_resolve/src/late/diagnostics.rs124
-rw-r--r--compiler/rustc_resolve/src/rustdoc.rs24
-rw-r--r--compiler/rustc_resolve/src/rustdoc/tests.rs50
-rw-r--r--compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs4
-rw-r--r--compiler/rustc_session/src/config.rs5
-rw-r--r--compiler/rustc_session/src/filesearch.rs5
-rw-r--r--compiler/rustc_session/src/options.rs3
-rw-r--r--compiler/rustc_session/src/session.rs5
-rw-r--r--compiler/rustc_smir/src/rustc_smir/alloc.rs2
-rw-r--r--compiler/rustc_smir/src/rustc_smir/convert/ty.rs12
-rw-r--r--compiler/rustc_span/src/analyze_source_file.rs13
-rw-r--r--compiler/rustc_span/src/lib.rs3
-rw-r--r--compiler/rustc_span/src/symbol.rs13
-rw-r--r--compiler/rustc_symbol_mangling/src/export.rs2
-rw-r--r--compiler/rustc_symbol_mangling/src/legacy.rs2
-rw-r--r--compiler/rustc_symbol_mangling/src/v0.rs8
-rw-r--r--compiler/rustc_target/src/spec/base/cygwin.rs5
-rw-r--r--compiler/rustc_target/src/spec/targets/aarch64_apple_darwin.rs1
-rw-r--r--compiler/rustc_target/src/spec/targets/aarch64_pc_windows_gnullvm.rs8
-rw-r--r--compiler/rustc_target/src/spec/targets/x86_64_apple_darwin.rs1
-rw-r--r--compiler/rustc_trait_selection/messages.ftl4
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs10
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs12
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/infer/suggest.rs4
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs17
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs20
-rw-r--r--compiler/rustc_trait_selection/src/errors.rs5
-rw-r--r--compiler/rustc_trait_selection/src/opaque_types.rs2
-rw-r--r--compiler/rustc_trait_selection/src/solve/delegate.rs62
-rw-r--r--compiler/rustc_trait_selection/src/solve/fulfill.rs119
-rw-r--r--compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs24
-rw-r--r--compiler/rustc_trait_selection/src/solve/inspect/analyse.rs18
-rw-r--r--compiler/rustc_trait_selection/src/traits/auto_trait.rs8
-rw-r--r--compiler/rustc_trait_selection/src/traits/fulfill.rs4
-rw-r--r--compiler/rustc_trait_selection/src/traits/mod.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/outlives_bounds.rs21
-rw-r--r--compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs4
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs22
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/mod.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/structural_normalize.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/wf.rs2
-rw-r--r--compiler/rustc_ty_utils/src/opaque_types.rs8
-rw-r--r--compiler/rustc_ty_utils/src/representability.rs4
-rw-r--r--compiler/rustc_ty_utils/src/ty.rs2
-rw-r--r--compiler/rustc_type_ir/src/binder.rs14
-rw-r--r--compiler/rustc_type_ir/src/flags.rs4
-rw-r--r--compiler/rustc_type_ir/src/fold.rs8
-rw-r--r--compiler/rustc_type_ir/src/infer_ctxt.rs7
-rw-r--r--compiler/rustc_type_ir/src/inherent.rs20
-rw-r--r--compiler/rustc_type_ir/src/interner.rs4
-rw-r--r--compiler/rustc_type_ir/src/visit.rs4
-rw-r--r--library/Cargo.lock4
-rw-r--r--library/alloc/Cargo.toml2
-rw-r--r--library/alloc/src/collections/btree/map.rs62
-rw-r--r--library/alloc/src/collections/btree/map/tests.rs74
-rw-r--r--library/alloc/src/collections/btree/set.rs34
-rw-r--r--library/alloc/src/collections/btree/set/tests.rs12
-rw-r--r--library/alloctests/benches/btree/map.rs12
-rw-r--r--library/alloctests/benches/btree/set.rs8
-rw-r--r--library/alloctests/tests/autotraits.rs14
-rw-r--r--library/core/src/alloc/layout.rs1
-rw-r--r--library/core/src/ascii/ascii_char.rs1
-rw-r--r--library/core/src/char/convert.rs1
-rw-r--r--library/core/src/clone.rs39
-rw-r--r--library/core/src/ffi/c_str.rs26
-rw-r--r--library/core/src/hint.rs2
-rw-r--r--library/core/src/intrinsics/bounds.rs39
-rw-r--r--library/core/src/intrinsics/mod.rs158
-rw-r--r--library/core/src/iter/mod.rs2
-rw-r--r--library/core/src/iter/sources.rs3
-rw-r--r--library/core/src/iter/sources/generator.rs29
-rw-r--r--library/core/src/lib.rs3
-rw-r--r--library/core/src/macros/mod.rs43
-rw-r--r--library/core/src/marker.rs2
-rw-r--r--library/core/src/marker/variance.rs8
-rw-r--r--library/core/src/mem/manually_drop.rs2
-rw-r--r--library/core/src/num/dec2flt/mod.rs2
-rw-r--r--library/core/src/num/f128.rs25
-rw-r--r--library/core/src/num/f16.rs25
-rw-r--r--library/core/src/num/f32.rs19
-rw-r--r--library/core/src/num/f64.rs22
-rw-r--r--library/core/src/num/int_macros.rs118
-rw-r--r--library/core/src/num/nonzero.rs2
-rw-r--r--library/core/src/num/uint_macros.rs112
-rw-r--r--library/core/src/ops/index_range.rs1
-rw-r--r--library/core/src/option.rs30
-rw-r--r--library/core/src/primitive_docs.rs4
-rw-r--r--library/core/src/ptr/alignment.rs1
-rw-r--r--library/core/src/ptr/const_ptr.rs149
-rw-r--r--library/core/src/ptr/docs/add.md32
-rw-r--r--library/core/src/ptr/docs/offset.md29
-rw-r--r--library/core/src/ptr/mod.rs76
-rw-r--r--library/core/src/ptr/mut_ptr.rs179
-rw-r--r--library/core/src/ptr/non_null.rs47
-rw-r--r--library/core/src/result.rs37
-rw-r--r--library/core/src/slice/index.rs62
-rw-r--r--library/core/src/slice/mod.rs8
-rw-r--r--library/core/src/slice/raw.rs23
-rw-r--r--library/core/src/str/converts.rs8
-rw-r--r--library/core/src/str/mod.rs4
-rw-r--r--library/core/src/str/traits.rs4
-rw-r--r--library/core/src/sync/atomic.rs23
-rw-r--r--library/core/src/ub_checks.rs6
-rw-r--r--library/coretests/tests/ffi/cstr.rs6
-rw-r--r--library/coretests/tests/floats/f128.rs392
-rw-r--r--library/coretests/tests/floats/f16.rs423
-rw-r--r--library/coretests/tests/floats/f32.rs312
-rw-r--r--library/coretests/tests/floats/f64.rs310
-rw-r--r--library/coretests/tests/floats/mod.rs37
-rw-r--r--library/coretests/tests/lib.rs2
-rw-r--r--library/coretests/tests/num/mod.rs363
-rw-r--r--library/proc_macro/Cargo.toml4
-rw-r--r--library/proc_macro/src/lib.rs3
-rw-r--r--library/std/Cargo.toml2
-rw-r--r--library/std/src/ffi/os_str.rs6
-rw-r--r--library/std/src/fs.rs47
-rw-r--r--library/std/src/fs/tests.rs46
-rw-r--r--library/std/src/lib.rs14
-rw-r--r--library/std/src/num/f128.rs (renamed from library/std/src/f128.rs)2
-rw-r--r--library/std/src/num/f16.rs (renamed from library/std/src/f16.rs)2
-rw-r--r--library/std/src/num/f32.rs (renamed from library/std/src/f32.rs)18
-rw-r--r--library/std/src/num/f64.rs (renamed from library/std/src/f64.rs)18
-rw-r--r--library/std/src/num/mod.rs (renamed from library/std/src/num.rs)0
-rw-r--r--library/std/src/path.rs102
-rw-r--r--library/std/src/sync/once_lock.rs18
-rw-r--r--library/std/src/sync/poison/mutex.rs11
-rw-r--r--library/std/src/sync/poison/rwlock.rs11
-rw-r--r--library/std/src/sync/reentrant_lock.rs11
-rw-r--r--library/std/src/sys/fs/windows.rs10
-rw-r--r--library/std/src/sys/os_str/wtf8.rs6
-rw-r--r--library/std/src/sys/sync/mutex/futex.rs6
-rw-r--r--library/std/src/sys/sync/mutex/pthread.rs8
-rw-r--r--library/std/src/sys/thread_local/key/unix.rs4
-rw-r--r--library/std/src/sys/thread_local/key/windows.rs17
-rw-r--r--library/std/src/sys/thread_local/native/lazy.rs80
-rw-r--r--library/std/tests/path.rs56
-rw-r--r--rust-bors.toml3
-rw-r--r--src/bootstrap/bootstrap.py1
-rw-r--r--src/bootstrap/defaults/bootstrap.library.toml14
-rw-r--r--src/bootstrap/mk/Makefile.in25
-rw-r--r--src/bootstrap/src/bin/rustc.rs57
-rw-r--r--src/bootstrap/src/core/build_steps/check.rs61
-rw-r--r--src/bootstrap/src/core/build_steps/clippy.rs28
-rw-r--r--src/bootstrap/src/core/build_steps/compile.rs169
-rw-r--r--src/bootstrap/src/core/build_steps/dist.rs32
-rw-r--r--src/bootstrap/src/core/build_steps/format.rs8
-rw-r--r--src/bootstrap/src/core/build_steps/install.rs4
-rw-r--r--src/bootstrap/src/core/build_steps/llvm.rs93
-rw-r--r--src/bootstrap/src/core/build_steps/perf.rs8
-rw-r--r--src/bootstrap/src/core/build_steps/run.rs19
-rw-r--r--src/bootstrap/src/core/build_steps/setup.rs24
-rw-r--r--src/bootstrap/src/core/build_steps/test.rs31
-rw-r--r--src/bootstrap/src/core/build_steps/tool.rs27
-rw-r--r--src/bootstrap/src/core/builder/cargo.rs36
-rw-r--r--src/bootstrap/src/core/builder/tests.rs21
-rw-r--r--src/bootstrap/src/core/config/config.rs117
-rw-r--r--src/bootstrap/src/core/download.rs10
-rw-r--r--src/bootstrap/src/lib.rs128
-rw-r--r--src/bootstrap/src/utils/change_tracker.rs13
-rw-r--r--src/bootstrap/src/utils/exec.rs3
-rw-r--r--src/build_helper/src/lib.rs21
-rw-r--r--src/ci/citool/src/jobs.rs2
-rw-r--r--src/ci/citool/src/jobs/tests.rs66
-rw-r--r--src/ci/citool/src/main.rs2
-rw-r--r--src/ci/citool/tests/jobs.rs4
-rw-r--r--src/ci/citool/tests/test-jobs.yml4
-rw-r--r--src/ci/docker/host-aarch64/aarch64-gnu-llvm-19/Dockerfile58
-rw-r--r--src/ci/docker/host-x86_64/mingw-check-1/Dockerfile (renamed from src/ci/docker/host-x86_64/mingw-check/Dockerfile)25
-rwxr-xr-xsrc/ci/docker/host-x86_64/mingw-check-1/check-default-config-profiles.sh (renamed from src/ci/docker/host-x86_64/mingw-check/check-default-config-profiles.sh)0
-rw-r--r--src/ci/docker/host-x86_64/mingw-check-1/reuse-requirements.in (renamed from src/ci/docker/host-x86_64/mingw-check/reuse-requirements.in)0
-rw-r--r--src/ci/docker/host-x86_64/mingw-check-1/reuse-requirements.txt (renamed from src/ci/docker/host-x86_64/mingw-check/reuse-requirements.txt)0
-rwxr-xr-xsrc/ci/docker/host-x86_64/mingw-check-1/validate-error-codes.sh (renamed from src/ci/docker/host-x86_64/mingw-check/validate-error-codes.sh)0
-rwxr-xr-xsrc/ci/docker/host-x86_64/mingw-check-1/validate-toolstate.sh (renamed from src/ci/docker/host-x86_64/mingw-check/validate-toolstate.sh)0
-rw-r--r--src/ci/docker/host-x86_64/mingw-check-2/Dockerfile38
-rw-r--r--src/ci/docker/host-x86_64/mingw-check-tidy/Dockerfile17
-rw-r--r--src/ci/docker/host-x86_64/mingw-check-tidy/eslint.version1
-rw-r--r--src/ci/docker/host-x86_64/x86_64-gnu-distcheck/Dockerfile12
-rw-r--r--src/ci/docker/host-x86_64/x86_64-gnu-nopt/Dockerfile2
-rw-r--r--src/ci/docker/host-x86_64/x86_64-gnu-tools/Dockerfile2
-rwxr-xr-xsrc/ci/docker/host-x86_64/x86_64-gnu-tools/checktools.sh6
-rwxr-xr-xsrc/ci/docker/scripts/x86_64-gnu-llvm.sh4
-rw-r--r--src/ci/github-actions/jobs.yml56
m---------src/doc/book0
m---------src/doc/embedded-book0
m---------src/doc/nomicon0
m---------src/doc/reference0
m---------src/doc/rust-by-example0
-rw-r--r--src/doc/rustc-dev-guide/.mailmap1
-rw-r--r--src/doc/rustc-dev-guide/rust-version2
-rw-r--r--src/doc/rustc-dev-guide/src/appendix/compiler-lecture.md1
-rw-r--r--src/doc/rustc-dev-guide/src/borrow_check/two_phase_borrows.md2
-rw-r--r--src/doc/rustc-dev-guide/src/building/bootstrapping/what-bootstrapping-does.md89
-rw-r--r--src/doc/rustc-dev-guide/src/building/how-to-build-and-run.md13
-rw-r--r--src/doc/rustc-dev-guide/src/building/new-target.md2
-rw-r--r--src/doc/rustc-dev-guide/src/building/suggested.md61
-rw-r--r--src/doc/rustc-dev-guide/src/diagnostics.md162
-rw-r--r--src/doc/rustc-dev-guide/src/early_late_parameters.md3
-rw-r--r--src/doc/rustc-dev-guide/src/fuzzing.md24
-rw-r--r--src/doc/rustc-dev-guide/src/getting-started.md4
-rw-r--r--src/doc/rustc-dev-guide/src/memory.md2
-rw-r--r--src/doc/rustc-dev-guide/src/normalization.md7
-rw-r--r--src/doc/rustc-dev-guide/src/opaque-types-impl-trait-inference.md3
-rw-r--r--src/doc/rustc-dev-guide/src/return-position-impl-trait-in-trait.md2
-rw-r--r--src/doc/rustc-dev-guide/src/rustdoc-internals.md4
-rw-r--r--src/doc/rustc-dev-guide/src/rustdoc.md30
-rw-r--r--src/doc/rustc-dev-guide/src/solve/coinduction.md4
-rw-r--r--src/doc/rustc-dev-guide/src/solve/opaque-types.md4
-rw-r--r--src/doc/rustc-dev-guide/src/tests/ci.md22
-rw-r--r--src/doc/rustc-dev-guide/src/tests/compiletest.md17
-rw-r--r--src/doc/rustc-dev-guide/src/tests/directives.md2
-rw-r--r--src/doc/rustc-dev-guide/src/tests/ui.md9
-rw-r--r--src/doc/rustc-dev-guide/src/ty_module/binders.md9
-rw-r--r--src/doc/rustc-dev-guide/src/ty_module/instantiating_binders.md4
-rw-r--r--src/doc/rustc-dev-guide/src/ty_module/param_ty_const_regions.md12
-rw-r--r--src/doc/rustc-dev-guide/src/typing_parameter_envs.md7
-rw-r--r--src/doc/rustc-dev-guide/triagebot.toml76
-rw-r--r--src/doc/rustc/src/check-cfg/cargo-specifics.md4
-rw-r--r--src/doc/rustc/src/codegen-options/index.md52
-rw-r--r--src/doc/rustc/src/platform-support/x86_64-fortanix-unknown-sgx.md2
-rw-r--r--src/doc/unstable-book/README.md8
-rw-r--r--src/doc/unstable-book/src/compiler-environment-variables.md1
-rw-r--r--src/doc/unstable-book/src/compiler-environment-variables/RUSTC_BOOTSTRAP.md (renamed from src/doc/unstable-book/src/compiler-flags/rustc-bootstrap.md)2
-rw-r--r--src/doc/unstable-book/src/compiler-environment-variables/RUSTC_OVERRIDE_VERSION_STRING.md (renamed from src/doc/unstable-book/src/compiler-flags/rustc-override-version-string.md)0
-rw-r--r--src/doc/unstable-book/src/compiler-flags/allow-features.md2
-rw-r--r--src/doc/unstable-book/src/compiler-flags/no-steal-thir.md7
-rw-r--r--src/doc/unstable-book/src/language-features/repr128.md18
-rw-r--r--src/librustdoc/clean/cfg.rs15
-rw-r--r--src/librustdoc/clean/mod.rs24
-rw-r--r--src/librustdoc/clean/types.rs198
-rw-r--r--src/librustdoc/clean/utils.rs4
-rw-r--r--src/librustdoc/html/format.rs142
-rw-r--r--src/librustdoc/html/highlight.rs45
-rw-r--r--src/librustdoc/html/layout.rs1
-rw-r--r--src/librustdoc/html/markdown.rs8
-rw-r--r--src/librustdoc/html/render/context.rs8
-rw-r--r--src/librustdoc/html/render/mod.rs36
-rw-r--r--src/librustdoc/html/render/print_item.rs382
-rw-r--r--src/librustdoc/html/render/sidebar.rs2
-rw-r--r--src/librustdoc/html/render/write_shared.rs35
-rw-r--r--src/librustdoc/html/templates/item_union.html9
-rw-r--r--src/librustdoc/html/tests.rs22
-rw-r--r--src/librustdoc/html/url_parts_builder.rs1
-rw-r--r--src/librustdoc/json/conversions.rs2
-rw-r--r--src/librustdoc/passes/calculate_doc_coverage.rs2
-rw-r--r--src/librustdoc/passes/check_doc_cfg.rs76
-rw-r--r--src/librustdoc/passes/collect_intra_doc_links.rs36
-rw-r--r--src/librustdoc/passes/mod.rs5
-rw-r--r--src/librustdoc/visit_ast.rs2
-rw-r--r--src/rustdoc-json-types/lib.rs2
-rw-r--r--src/stage0920
m---------src/tools/cargo0
-rw-r--r--src/tools/clippy/Cargo.toml2
-rw-r--r--src/tools/clippy/book/src/development/trait_checking.md4
-rw-r--r--src/tools/clippy/book/src/lint_configuration.md2
-rw-r--r--src/tools/clippy/clippy_config/src/conf.rs2
-rw-r--r--src/tools/clippy/clippy_dev/src/fmt.rs133
-rw-r--r--src/tools/clippy/clippy_dev/src/main.rs2
-rw-r--r--src/tools/clippy/clippy_dev/src/rename_lint.rs20
-rw-r--r--src/tools/clippy/clippy_dev/src/update_lints.rs7
-rw-r--r--src/tools/clippy/clippy_dev/src/utils.rs140
-rw-r--r--src/tools/clippy/clippy_lints/src/arbitrary_source_item_ordering.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/arc_with_non_send_sync.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/dbg_macro.rs122
-rw-r--r--src/tools/clippy/clippy_lints/src/dereference.rs19
-rw-r--r--src/tools/clippy/clippy_lints/src/derive.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/disallowed_types.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/doc/lazy_continuation.rs88
-rw-r--r--src/tools/clippy/clippy_lints/src/doc/markdown.rs56
-rw-r--r--src/tools/clippy/clippy_lints/src/doc/mod.rs27
-rw-r--r--src/tools/clippy/clippy_lints/src/empty_with_brackets.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/enum_clike.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/eta_reduction.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/excessive_bools.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/exhaustive_items.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/field_scoped_visibility_modifiers.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/functions/ref_option.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/functions/result.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/index_refutable_slice.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/item_name_repetitions.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/large_const_arrays.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/large_enum_variant.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/legacy_numeric_constants.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/let_underscore.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/manual_find.rs7
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/manual_flatten.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/while_let_loop.rs103
-rw-r--r--src/tools/clippy/clippy_lints/src/macro_use.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/manual_non_exhaustive.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/manual_unwrap_or.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/redundant_pattern_match.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/significant_drop_in_scrutinee.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/manual_is_variant_and.rs70
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/mod.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/needless_collect.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/or_fun_call.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/unnecessary_sort_by.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/min_ident_chars.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/missing_enforced_import_rename.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/missing_fields_in_debug.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/mut_reference.rs32
-rw-r--r--src/tools/clippy/clippy_lints/src/needless_borrows_for_generic_args.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/needless_for_each.rs32
-rw-r--r--src/tools/clippy/clippy_lints/src/non_send_fields_in_send_ty.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/non_std_lazy_statics.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/only_used_in_recursion.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/operators/assign_op_pattern.rs14
-rw-r--r--src/tools/clippy/clippy_lints/src/operators/mod.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/operators/modulo_arithmetic.rs45
-rw-r--r--src/tools/clippy/clippy_lints/src/panic_unimplemented.rs1
-rw-r--r--src/tools/clippy/clippy_lints/src/partial_pub_fields.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs22
-rw-r--r--src/tools/clippy/clippy_lints/src/pub_underscore_fields.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/redundant_pub_crate.rs23
-rw-r--r--src/tools/clippy/clippy_lints/src/returns.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/significant_drop_tightening.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/trailing_empty_array.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/tuple_array_conversions.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/types/mod.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/unit_return_expecting_ord.rs126
-rw-r--r--src/tools/clippy/clippy_lints/src/unused_trait_names.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/upper_case_acronyms.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/use_self.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/wildcard_imports.rs4
-rw-r--r--src/tools/clippy/clippy_lints_internal/src/msrv_attr_impl.rs2
-rw-r--r--src/tools/clippy/clippy_utils/README.md2
-rw-r--r--src/tools/clippy/clippy_utils/src/ast_utils/mod.rs8
-rw-r--r--src/tools/clippy/clippy_utils/src/check_proc_macro.rs2
-rw-r--r--src/tools/clippy/clippy_utils/src/consts.rs4
-rw-r--r--src/tools/clippy/clippy_utils/src/lib.rs18
-rw-r--r--src/tools/clippy/clippy_utils/src/paths.rs11
-rw-r--r--src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs5
-rw-r--r--src/tools/clippy/clippy_utils/src/sugg.rs4
-rw-r--r--src/tools/clippy/clippy_utils/src/ty/mod.rs10
-rw-r--r--src/tools/clippy/clippy_utils/src/ty/type_certainty/mod.rs2
-rw-r--r--src/tools/clippy/lintcheck/src/input.rs21
-rw-r--r--src/tools/clippy/lintcheck/src/main.rs20
-rw-r--r--src/tools/clippy/lintcheck/src/output.rs6
-rw-r--r--src/tools/clippy/rust-toolchain.toml2
-rw-r--r--src/tools/clippy/rustfmt.toml6
-rw-r--r--src/tools/clippy/tests/headers.rs34
-rw-r--r--src/tools/clippy/tests/ui/assign_ops.fixed31
-rw-r--r--src/tools/clippy/tests/ui/assign_ops.rs31
-rw-r--r--src/tools/clippy/tests/ui/assign_ops.stderr24
-rw-r--r--src/tools/clippy/tests/ui/auxiliary/proc_macro_attr.rs3
-rw-r--r--src/tools/clippy/tests/ui/auxiliary/proc_macro_derive.rs3
-rw-r--r--src/tools/clippy/tests/ui/cast.rs2
-rw-r--r--src/tools/clippy/tests/ui/cast.stderr184
-rw-r--r--src/tools/clippy/tests/ui/crashes/auxiliary/proc_macro_crash.rs3
-rw-r--r--src/tools/clippy/tests/ui/dbg_macro/dbg_macro.fixed16
-rw-r--r--src/tools/clippy/tests/ui/dbg_macro/dbg_macro.rs16
-rw-r--r--src/tools/clippy/tests/ui/dbg_macro/dbg_macro.stderr14
-rw-r--r--src/tools/clippy/tests/ui/doc/doc_markdown-issue_13097.fixed36
-rw-r--r--src/tools/clippy/tests/ui/doc/doc_markdown-issue_13097.rs36
-rw-r--r--src/tools/clippy/tests/ui/doc/doc_markdown-issue_13097.stderr74
-rw-r--r--src/tools/clippy/tests/ui/explicit_deref_methods.fixed6
-rw-r--r--src/tools/clippy/tests/ui/explicit_deref_methods.rs2
-rw-r--r--src/tools/clippy/tests/ui/explicit_deref_methods.stderr22
-rw-r--r--src/tools/clippy/tests/ui/manual_find_fixable.fixed10
-rw-r--r--src/tools/clippy/tests/ui/manual_find_fixable.rs22
-rw-r--r--src/tools/clippy/tests/ui/manual_find_fixable.stderr24
-rw-r--r--src/tools/clippy/tests/ui/manual_flatten.rs7
-rw-r--r--src/tools/clippy/tests/ui/manual_flatten.stderr4
-rw-r--r--src/tools/clippy/tests/ui/manual_is_variant_and.fixed62
-rw-r--r--src/tools/clippy/tests/ui/manual_is_variant_and.rs62
-rw-r--r--src/tools/clippy/tests/ui/manual_is_variant_and.stderr60
-rw-r--r--src/tools/clippy/tests/ui/map_flatten.rs2
-rw-r--r--src/tools/clippy/tests/ui/map_flatten_fixable.fixed1
-rw-r--r--src/tools/clippy/tests/ui/map_flatten_fixable.rs1
-rw-r--r--src/tools/clippy/tests/ui/map_flatten_fixable.stderr18
-rw-r--r--src/tools/clippy/tests/ui/needless_borrow.fixed15
-rw-r--r--src/tools/clippy/tests/ui/needless_borrow.rs15
-rw-r--r--src/tools/clippy/tests/ui/needless_borrow.stderr32
-rw-r--r--src/tools/clippy/tests/ui/needless_for_each_fixable.fixed15
-rw-r--r--src/tools/clippy/tests/ui/needless_for_each_fixable.rs15
-rw-r--r--src/tools/clippy/tests/ui/needless_for_each_fixable.stderr14
-rw-r--r--src/tools/clippy/tests/ui/needless_return.fixed65
-rw-r--r--src/tools/clippy/tests/ui/needless_return.rs65
-rw-r--r--src/tools/clippy/tests/ui/needless_return.stderr98
-rw-r--r--src/tools/clippy/tests/ui/non_expressive_names_error_recovery.fixed (renamed from src/tools/clippy/tests/ui/skip_rustfmt/non_expressive_names_error_recovery.fixed)0
-rw-r--r--src/tools/clippy/tests/ui/non_expressive_names_error_recovery.rs (renamed from src/tools/clippy/tests/ui/skip_rustfmt/non_expressive_names_error_recovery.rs)0
-rw-r--r--src/tools/clippy/tests/ui/non_expressive_names_error_recovery.stderr (renamed from src/tools/clippy/tests/ui/skip_rustfmt/non_expressive_names_error_recovery.stderr)2
-rw-r--r--src/tools/clippy/tests/ui/question_mark.fixed10
-rw-r--r--src/tools/clippy/tests/ui/question_mark.rs10
-rw-r--r--src/tools/clippy/tests/ui/trivially_copy_pass_by_ref.fixed179
-rw-r--r--src/tools/clippy/tests/ui/trivially_copy_pass_by_ref.rs60
-rw-r--r--src/tools/clippy/tests/ui/trivially_copy_pass_by_ref.stderr80
-rw-r--r--src/tools/clippy/tests/ui/while_let_loop.rs86
-rw-r--r--src/tools/clippy/tests/ui/while_let_loop.stderr122
-rw-r--r--src/tools/clippy/triagebot.toml1
-rw-r--r--src/tools/clippy/util/gh-pages/index_template.html2
-rw-r--r--src/tools/clippy/util/gh-pages/script.js12
-rw-r--r--src/tools/generate-copyright/src/cargo_metadata.rs11
-rw-r--r--src/tools/generate-copyright/src/main.rs11
-rw-r--r--src/tools/lint-docs/Cargo.toml1
-rw-r--r--src/tools/lint-docs/src/lib.rs11
-rw-r--r--src/tools/miri/cargo-miri/src/phases.rs2
-rwxr-xr-xsrc/tools/miri/ci/ci.sh17
-rw-r--r--src/tools/miri/miri-script/src/commands.rs49
-rw-r--r--src/tools/miri/rust-version2
-rw-r--r--src/tools/miri/src/alloc/alloc_bytes.rs (renamed from src/tools/miri/src/alloc_bytes.rs)63
-rw-r--r--src/tools/miri/src/alloc/isolated_alloc.rs389
-rw-r--r--src/tools/miri/src/alloc/mod.rs5
-rw-r--r--src/tools/miri/src/alloc_addresses/mod.rs13
-rw-r--r--src/tools/miri/src/bin/miri.rs4
-rw-r--r--src/tools/miri/src/borrow_tracker/tree_borrows/diagnostics.rs2
-rw-r--r--src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs230
-rw-r--r--src/tools/miri/src/borrow_tracker/tree_borrows/perms.rs21
-rw-r--r--src/tools/miri/src/borrow_tracker/tree_borrows/tree.rs144
-rw-r--r--src/tools/miri/src/borrow_tracker/tree_borrows/tree/tests.rs42
-rw-r--r--src/tools/miri/src/concurrency/mod.rs13
-rw-r--r--src/tools/miri/src/concurrency/thread.rs24
-rw-r--r--src/tools/miri/src/diagnostics.rs3
-rw-r--r--src/tools/miri/src/eval.rs19
-rw-r--r--src/tools/miri/src/helpers.rs2
-rw-r--r--src/tools/miri/src/intrinsics/atomic.rs21
-rw-r--r--src/tools/miri/src/intrinsics/mod.rs70
-rw-r--r--src/tools/miri/src/lib.rs8
-rw-r--r--src/tools/miri/src/machine.rs55
-rw-r--r--src/tools/miri/src/range_map.rs22
-rw-r--r--src/tools/miri/src/shims/files.rs14
-rw-r--r--src/tools/miri/src/shims/foreign_items.rs9
-rw-r--r--src/tools/miri/src/shims/unix/fd.rs21
-rw-r--r--src/tools/miri/src/shims/unix/fs.rs13
-rw-r--r--src/tools/miri/src/shims/unix/unnamed_socket.rs96
-rw-r--r--src/tools/miri/src/shims/windows/foreign_items.rs22
-rw-r--r--src/tools/miri/src/shims/windows/handle.rs74
-rw-r--r--src/tools/miri/tests/fail-dep/libc/fcntl_fsetfl_while_blocking.rs20
-rw-r--r--src/tools/miri/tests/fail-dep/libc/fcntl_fsetfl_while_blocking.stderr19
-rw-r--r--src/tools/miri/tests/fail-dep/libc/unsupported_incomplete_function.stderr3
-rw-r--r--src/tools/miri/tests/fail/alloc/no_global_allocator.stderr3
-rw-r--r--src/tools/miri/tests/fail/data_race/stack_pop_race.rs5
-rw-r--r--src/tools/miri/tests/fail/data_race/stack_pop_race.stderr11
-rw-r--r--src/tools/miri/tests/fail/ptr_swap_nonoverlapping.stderr5
-rw-r--r--src/tools/miri/tests/fail/tail_calls/dangling-local-var.stderr4
-rw-r--r--src/tools/miri/tests/fail/tree_borrows/cell-inside-struct.rs33
-rw-r--r--src/tools/miri/tests/fail/tree_borrows/cell-inside-struct.stderr26
-rw-r--r--src/tools/miri/tests/fail/unaligned_pointers/atomic_unaligned.rs3
-rw-r--r--src/tools/miri/tests/fail/unaligned_pointers/atomic_unaligned.stderr4
-rw-r--r--src/tools/miri/tests/fail/unsupported_foreign_function.stderr3
-rw-r--r--src/tools/miri/tests/many-seeds/reentrant-lock.rs2
-rw-r--r--src/tools/miri/tests/native-lib/fail/function_not_in_so.stderr3
-rw-r--r--src/tools/miri/tests/native-lib/fail/private_function.stderr3
-rw-r--r--src/tools/miri/tests/pass-dep/libc/libc-pipe.rs67
-rw-r--r--src/tools/miri/tests/pass-dep/libc/libc-socketpair.rs33
-rw-r--r--src/tools/miri/tests/pass-dep/tokio/file-io.rs10
-rw-r--r--src/tools/miri/tests/pass/alloc-access-tracking.rs4
-rw-r--r--src/tools/miri/tests/pass/both_borrows/basic_aliasing_model.rs20
-rw-r--r--src/tools/miri/tests/pass/btreemap.rs2
-rw-r--r--src/tools/miri/tests/pass/iter_macro.rs22
-rw-r--r--src/tools/miri/tests/pass/shims/fs.rs2
-rw-r--r--src/tools/miri/tests/pass/tree_borrows/cell-alternate-writes.stderr4
-rw-r--r--src/tools/miri/tests/pass/tree_borrows/cell-lazy-write-to-surrounding.rs22
-rw-r--r--src/tools/opt-dist/src/training.rs2
-rw-r--r--src/tools/rust-analyzer/Cargo.lock241
-rw-r--r--src/tools/rust-analyzer/Cargo.toml7
-rw-r--r--src/tools/rust-analyzer/crates/base-db/src/input.rs12
-rw-r--r--src/tools/rust-analyzer/crates/base-db/src/lib.rs4
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/lang_item.rs2
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/builtin_fn_macro.rs18
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/nameres.rs8
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/nameres/assoc.rs4
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/test_db.rs23
-rw-r--r--src/tools/rust-analyzer/crates/hir-expand/src/builtin/fn_macro.rs25
-rw-r--r--src/tools/rust-analyzer/crates/hir-expand/src/files.rs52
-rw-r--r--src/tools/rust-analyzer/crates/hir-expand/src/lib.rs18
-rw-r--r--src/tools/rust-analyzer/crates/hir-expand/src/prettify_macro_expansion_.rs80
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs2
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/expr.rs13
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs24
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/display.rs2
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/infer/closure.rs56
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/inhabitedness.rs23
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim.rs2
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs24
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/test_db.rs22
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/tests/traits.rs27
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/traits.rs5
-rw-r--r--src/tools/rust-analyzer/crates/hir/src/lib.rs53
-rw-r--r--src/tools/rust-analyzer/crates/hir/src/semantics.rs369
-rw-r--r--src/tools/rust-analyzer/crates/hir/src/semantics/child_by_source.rs19
-rw-r--r--src/tools/rust-analyzer/crates/hir/src/semantics/source_to_def.rs24
-rw-r--r--src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs37
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/auto_import.rs38
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_bool_to_enum.rs8
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_named_struct_to_tuple_struct.rs3
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_tuple_struct_to_named_struct.rs3
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/desugar_try_expr.rs281
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_function.rs7
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_mut_trait_impl.rs94
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_new.rs137
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_qualified_name_with_use.rs6
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_try_expr_with_match.rs148
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/unqualify_method_call.rs7
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/lib.rs4
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/tests/generated.rs62
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/context.rs6
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/context/analysis.rs33
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/tests/expression.rs50
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/tests/item.rs38
-rw-r--r--src/tools/rust-analyzer/crates/ide-db/src/imports/insert_use.rs144
-rw-r--r--src/tools/rust-analyzer/crates/ide-db/src/imports/insert_use/tests.rs101
-rw-r--r--src/tools/rust-analyzer/crates/ide-db/src/lib.rs4
-rw-r--r--src/tools/rust-analyzer/crates/ide-db/src/search.rs48
-rw-r--r--src/tools/rust-analyzer/crates/ide-db/src/source_change.rs12
-rw-r--r--src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/json_is_not_rust.rs6
-rw-r--r--src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_unsafe.rs43
-rw-r--r--src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/non_exhaustive_let.rs25
-rw-r--r--src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/type_mismatch.rs14
-rw-r--r--src/tools/rust-analyzer/crates/ide-diagnostics/src/lib.rs181
-rw-r--r--src/tools/rust-analyzer/crates/ide-ssr/src/lib.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide-ssr/src/search.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/expand_macro.rs116
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/goto_definition.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/goto_type_definition.rs4
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/highlight_related.rs31
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/hover.rs3
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/hover/render.rs76
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/hover/tests.rs128
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/lib.rs1
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/references.rs92
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/rename.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/syntax_highlighting.rs2
-rw-r--r--src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs1
-rw-r--r--src/tools/rust-analyzer/crates/mbe/src/tests.rs3
-rw-r--r--src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/rust_analyzer_span.rs4
-rw-r--r--src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/token_id.rs3
-rw-r--r--src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/token_stream.rs11
-rw-r--r--src/tools/rust-analyzer/crates/proc-macro-srv/src/tests/mod.rs2
-rw-r--r--src/tools/rust-analyzer/crates/query-group-macro/tests/logger_db.rs40
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs2
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs5
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/dispatch.rs9
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/integrated_benchmarks.rs20
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/from_proto.rs1
-rw-r--r--src/tools/rust-analyzer/crates/span/src/lib.rs5
-rw-r--r--src/tools/rust-analyzer/crates/syntax-bridge/src/prettify_macro_expansion.rs43
-rw-r--r--src/tools/rust-analyzer/crates/syntax/src/ast/syntax_factory/constructors.rs12
-rw-r--r--src/tools/rust-analyzer/crates/syntax/src/ted.rs14
-rw-r--r--src/tools/rust-analyzer/crates/vfs/src/vfs_path.rs7
-rw-r--r--src/tools/rust-analyzer/docs/book/src/configuration_generated.md9
-rw-r--r--src/tools/rust-analyzer/docs/book/src/other_editors.md24
-rw-r--r--src/tools/rust-analyzer/editors/code/package.json29
-rw-r--r--src/tools/rust-analyzer/xtask/src/codegen.rs4
-rw-r--r--src/tools/rustbook/Cargo.lock14
-rw-r--r--src/tools/rustbook/Cargo.toml2
m---------src/tools/rustc-perf0
-rw-r--r--src/tools/rustfmt/src/items.rs4
-rw-r--r--src/tools/rustfmt/src/lib.rs1
-rw-r--r--src/tools/rustfmt/src/parse/macros/asm.rs2
-rw-r--r--src/tools/rustfmt/src/visitor.rs2
-rw-r--r--src/tools/test-float-parse/Cargo.lock (renamed from src/etc/test-float-parse/Cargo.lock)0
-rw-r--r--src/tools/test-float-parse/Cargo.toml (renamed from src/etc/test-float-parse/Cargo.toml)0
-rw-r--r--src/tools/test-float-parse/README.md (renamed from src/etc/test-float-parse/README.md)0
-rw-r--r--src/tools/test-float-parse/src/gen_/exhaustive.rs (renamed from src/etc/test-float-parse/src/gen_/exhaustive.rs)0
-rw-r--r--src/tools/test-float-parse/src/gen_/exponents.rs (renamed from src/etc/test-float-parse/src/gen_/exponents.rs)0
-rw-r--r--src/tools/test-float-parse/src/gen_/fuzz.rs (renamed from src/etc/test-float-parse/src/gen_/fuzz.rs)0
-rw-r--r--src/tools/test-float-parse/src/gen_/integers.rs (renamed from src/etc/test-float-parse/src/gen_/integers.rs)0
-rw-r--r--src/tools/test-float-parse/src/gen_/long_fractions.rs (renamed from src/etc/test-float-parse/src/gen_/long_fractions.rs)0
-rw-r--r--src/tools/test-float-parse/src/gen_/many_digits.rs (renamed from src/etc/test-float-parse/src/gen_/many_digits.rs)0
-rw-r--r--src/tools/test-float-parse/src/gen_/sparse.rs (renamed from src/etc/test-float-parse/src/gen_/sparse.rs)0
-rw-r--r--src/tools/test-float-parse/src/gen_/spot_checks.rs (renamed from src/etc/test-float-parse/src/gen_/spot_checks.rs)0
-rw-r--r--src/tools/test-float-parse/src/gen_/subnorm.rs (renamed from src/etc/test-float-parse/src/gen_/subnorm.rs)0
-rw-r--r--src/tools/test-float-parse/src/lib.rs (renamed from src/etc/test-float-parse/src/lib.rs)1
-rw-r--r--src/tools/test-float-parse/src/main.rs (renamed from src/etc/test-float-parse/src/main.rs)0
-rw-r--r--src/tools/test-float-parse/src/traits.rs (renamed from src/etc/test-float-parse/src/traits.rs)1
-rw-r--r--src/tools/test-float-parse/src/ui.rs (renamed from src/etc/test-float-parse/src/ui.rs)0
-rw-r--r--src/tools/test-float-parse/src/validate.rs (renamed from src/etc/test-float-parse/src/validate.rs)0
-rw-r--r--src/tools/test-float-parse/src/validate/tests.rs (renamed from src/etc/test-float-parse/src/validate/tests.rs)0
-rw-r--r--src/tools/tidy/Cargo.toml2
-rw-r--r--src/tools/tidy/src/deps.rs2
-rw-r--r--src/tools/tidy/src/issues.txt1
-rw-r--r--src/tools/tidy/src/lib.rs1
-rw-r--r--src/tools/tidy/src/main.rs2
-rw-r--r--src/tools/tidy/src/rustdoc_js.rs99
-rw-r--r--src/tools/unstable-book-gen/src/SUMMARY.md2
-rw-r--r--src/tools/unstable-book-gen/src/main.rs5
-rw-r--r--tests/assembly/aarch64-xray.rs25
-rw-r--r--tests/assembly/x86_64-xray.rs25
-rw-r--r--tests/codegen/align-byval-alignment-mismatch.rs7
-rw-r--r--tests/codegen/autodiff/batched.rs8
-rw-r--r--tests/codegen/autodiff/generic.rs4
-rw-r--r--tests/codegen/autodiff/identical_fnc.rs6
-rw-r--r--tests/codegen/autodiff/inline.rs4
-rw-r--r--tests/codegen/autodiff/scalar.rs4
-rw-r--r--tests/codegen/autodiff/sret.rs4
-rw-r--r--tests/codegen/call-tmps-lifetime.rs68
-rw-r--r--tests/codegen/enum/enum-u128.rs3
-rw-r--r--tests/codegen/issues/issue-98156-const-arg-temp-lifetime.rs27
-rw-r--r--tests/codegen/option-niche-eq.rs11
-rw-r--r--tests/codegen/option-niche-unfixed/option-bool-eq.rs15
-rw-r--r--tests/codegen/thread-local.rs16
-rw-r--r--tests/coverage/async_closure.cov-map21
-rw-r--r--tests/coverage/unused-local-file.coverage7
-rw-r--r--tests/coverage/unused-local-file.rs22
-rw-r--r--tests/crashes/140255.rs3
-rw-r--r--tests/crashes/140281.rs18
-rw-r--r--tests/crashes/140484.rs14
-rw-r--r--tests/crashes/140500.rs14
-rw-r--r--tests/crashes/140683.rs5
-rw-r--r--tests/debuginfo/by-value-non-immediate-argument.rs1
-rw-r--r--tests/debuginfo/msvc-pretty-enums.rs2
-rw-r--r--tests/mir-opt/coverage/branch_match_arms.main.InstrumentCoverage.diff2
-rw-r--r--tests/mir-opt/coverage/instrument_coverage.bar.InstrumentCoverage.diff2
-rw-r--r--tests/mir-opt/coverage/instrument_coverage.main.InstrumentCoverage.diff4
-rw-r--r--tests/mir-opt/coverage/instrument_coverage_cleanup.main.CleanupPostBorrowck.diff4
-rw-r--r--tests/mir-opt/coverage/instrument_coverage_cleanup.main.InstrumentCoverage.diff4
-rw-r--r--tests/mir-opt/dataflow.main.maybe_init.borrowck.dot6
-rw-r--r--tests/mir-opt/dataflow.main.maybe_uninit.borrowck.dot6
-rw-r--r--tests/mir-opt/dataflow.rs2
-rw-r--r--tests/mir-opt/dont_reset_cast_kind_without_updating_operand.test.GVN.32bit.panic-abort.diff2
-rw-r--r--tests/mir-opt/dont_reset_cast_kind_without_updating_operand.test.GVN.64bit.panic-abort.diff2
-rw-r--r--tests/mir-opt/enum_opt.rs2
-rw-r--r--tests/mir-opt/gvn_repeat.repeat_local.GVN.diff18
-rw-r--r--tests/mir-opt/gvn_repeat.repeat_place.GVN.diff17
-rw-r--r--tests/mir-opt/gvn_repeat.rs49
-rw-r--r--tests/mir-opt/inline/unchecked_shifts.rs4
-rw-r--r--tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.Inline.panic-abort.diff2
-rw-r--r--tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.Inline.panic-unwind.diff2
-rw-r--r--tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.PreCodegen.after.panic-abort.mir2
-rw-r--r--tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.PreCodegen.after.panic-unwind.mir2
-rw-r--r--tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_bigger.Inline.panic-abort.diff2
-rw-r--r--tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_bigger.Inline.panic-unwind.diff2
-rw-r--r--tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_bigger.PreCodegen.after.panic-abort.mir2
-rw-r--r--tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_bigger.PreCodegen.after.panic-unwind.mir2
-rw-r--r--tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-abort.diff2
-rw-r--r--tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-unwind.diff2
-rw-r--r--tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.panic-abort.mir2
-rw-r--r--tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.panic-unwind.mir2
-rw-r--r--tests/mir-opt/instsimplify/ub_check.unwrap_unchecked.InstSimplify-after-simplifycfg.diff2
-rw-r--r--tests/mir-opt/lower_intrinsics.rs21
-rw-r--r--tests/mir-opt/lower_intrinsics.slice_get.LowerIntrinsics.panic-abort.diff85
-rw-r--r--tests/mir-opt/lower_intrinsics.slice_get.LowerIntrinsics.panic-unwind.diff85
-rw-r--r--tests/mir-opt/matches_reduce_branches.match_non_int_failed.MatchBranchSimplification.diff29
-rw-r--r--tests/mir-opt/matches_reduce_branches.rs33
-rw-r--r--tests/mir-opt/pre-codegen/checked_ops.checked_shl.PreCodegen.after.panic-abort.mir2
-rw-r--r--tests/mir-opt/pre-codegen/checked_ops.checked_shl.PreCodegen.after.panic-unwind.mir2
-rw-r--r--tests/mir-opt/pre-codegen/duplicate_switch_targets.ub_if_b.PreCodegen.after.mir2
-rw-r--r--tests/mir-opt/pre-codegen/loops.int_range.PreCodegen.after.mir2
-rw-r--r--tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_fat.PreCodegen.after.panic-abort.mir4
-rw-r--r--tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_fat.PreCodegen.after.panic-unwind.mir4
-rw-r--r--tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_thin.PreCodegen.after.panic-abort.mir4
-rw-r--r--tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_thin.PreCodegen.after.panic-unwind.mir4
-rw-r--r--tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-abort.mir2
-rw-r--r--tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-unwind.mir2
-rw-r--r--tests/mir-opt/pre-codegen/range_iter.range_iter_next.PreCodegen.after.panic-abort.mir2
-rw-r--r--tests/mir-opt/pre-codegen/range_iter.range_iter_next.PreCodegen.after.panic-unwind.mir2
-rw-r--r--tests/mir-opt/pre-codegen/slice_index.slice_get_mut_usize.PreCodegen.after.panic-abort.mir22
-rw-r--r--tests/mir-opt/pre-codegen/slice_index.slice_get_mut_usize.PreCodegen.after.panic-unwind.mir22
-rw-r--r--tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-abort.mir16
-rw-r--r--tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-unwind.mir16
-rw-r--r--tests/mir-opt/pre-codegen/slice_index.slice_ptr_get_unchecked_range.PreCodegen.after.panic-abort.mir14
-rw-r--r--tests/mir-opt/pre-codegen/slice_index.slice_ptr_get_unchecked_range.PreCodegen.after.panic-unwind.mir14
-rw-r--r--tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-abort.mir4
-rw-r--r--tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-unwind.mir2
-rw-r--r--tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-abort.mir4
-rw-r--r--tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-unwind.mir4
-rw-r--r--tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-abort.mir2
-rw-r--r--tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-unwind.mir2
-rw-r--r--tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-abort.mir2
-rw-r--r--tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-unwind.mir2
-rw-r--r--tests/mir-opt/pre-codegen/slice_iter.slice_iter_next.PreCodegen.after.panic-abort.mir2
-rw-r--r--tests/mir-opt/pre-codegen/slice_iter.slice_iter_next.PreCodegen.after.panic-unwind.mir2
-rw-r--r--tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-abort.mir2
-rw-r--r--tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-unwind.mir2
-rw-r--r--tests/pretty/autodiff/autodiff_forward.pp2
-rw-r--r--tests/pretty/autodiff/autodiff_forward.rs32
-rw-r--r--tests/pretty/autodiff/autodiff_reverse.pp2
-rw-r--r--tests/pretty/autodiff/autodiff_reverse.rs12
-rw-r--r--tests/pretty/autodiff/inherent_impl.pp2
-rw-r--r--tests/pretty/autodiff/inherent_impl.rs4
-rw-r--r--tests/run-make/c-link-to-rust-va-list-fn/checkrust.rs9
-rw-r--r--tests/run-make/c-link-to-rust-va-list-fn/test.c5
-rw-r--r--tests/run-make/mte-ffi/bar.h2
-rw-r--r--tests/run-make/mte-ffi/bar_float.c4
-rw-r--r--tests/run-make/mte-ffi/bar_int.c2
-rw-r--r--tests/run-make/mte-ffi/bar_string.c3
-rw-r--r--tests/run-make/repr128-dwarf/main.rs2
-rw-r--r--tests/run-make/version-check/rmake.rs13
-rw-r--r--tests/rustdoc-json/enums/discriminant/limits.rs3
-rw-r--r--tests/rustdoc-ui/doc-cfg-check-cfg.cfg_empty.stderr30
-rw-r--r--tests/rustdoc-ui/doc-cfg-check-cfg.rs23
-rw-r--r--tests/rustdoc-ui/doc-cfg.rs4
-rw-r--r--tests/rustdoc-ui/doc-cfg.stderr26
-rw-r--r--tests/rustdoc-ui/intra-doc/bad-link-to-proc-macro.rs21
-rw-r--r--tests/rustdoc-ui/intra-doc/bad-link-to-proc-macro.stderr22
-rw-r--r--tests/rustdoc-ui/issues/issue-91713.stdout2
-rw-r--r--tests/rustdoc/cfg-bool.rs13
-rw-r--r--tests/rustdoc/doctest/ignore-sometimes.rs23
-rw-r--r--tests/rustdoc/intra-doc/link-to-proc-macro.rs13
-rw-r--r--tests/rustdoc/type-alias/repr.rs42
-rw-r--r--tests/rustdoc/type-layout.rs2
-rw-r--r--tests/ui-fulldeps/pprust-expr-roundtrip.rs14
-rw-r--r--tests/ui-fulldeps/pprust-parenthesis-insertion.rs4
-rw-r--r--tests/ui/allocator/auxiliary/helper.rs2
-rw-r--r--tests/ui/asm/cfg-parse-error.rs57
-rw-r--r--tests/ui/asm/cfg-parse-error.stderr39
-rw-r--r--tests/ui/asm/cfg.rs125
-rw-r--r--tests/ui/asm/parse-error.stderr16
-rw-r--r--tests/ui/associated-type-bounds/return-type-notation/path-missing.stderr4
-rw-r--r--tests/ui/associated-types/associated-type-tuple-struct-construction.rs24
-rw-r--r--tests/ui/associated-types/associated-type-tuple-struct-construction.stderr19
-rw-r--r--tests/ui/associated-types/tuple-struct-expr-pat.fixed48
-rw-r--r--tests/ui/associated-types/tuple-struct-expr-pat.rs48
-rw-r--r--tests/ui/associated-types/tuple-struct-expr-pat.stderr97
-rw-r--r--tests/ui/async-await/async-closures/promote-in-body.rs13
-rw-r--r--tests/ui/async-await/async-drop/type-parameter.rs16
-rw-r--r--tests/ui/async-await/async-drop/type-parameter.stderr11
-rw-r--r--tests/ui/async-await/async-drop/unexpected-sort.rs18
-rw-r--r--tests/ui/async-await/async-drop/unexpected-sort.stderr32
-rw-r--r--tests/ui/async-await/async-fn/edition-2015-not-async-bound.rs1
-rw-r--r--tests/ui/async-await/async-fn/edition-2015.rs1
-rw-r--r--tests/ui/async-await/async-fn/edition-2015.stderr8
-rw-r--r--tests/ui/async-await/await-keyword/2015-edition-error-various-positions.rs1
-rw-r--r--tests/ui/async-await/await-keyword/2015-edition-error-various-positions.stderr22
-rw-r--r--tests/ui/async-await/await-keyword/2015-edition-warning.fixed1
-rw-r--r--tests/ui/async-await/await-keyword/2015-edition-warning.rs1
-rw-r--r--tests/ui/async-await/await-keyword/2015-edition-warning.stderr14
-rw-r--r--tests/ui/async-await/dyn/mut-is-pointer-like.stderr24
-rw-r--r--tests/ui/async-await/dyn/works.stderr24
-rw-r--r--tests/ui/async-await/dyn/wrong-size.stderr24
-rw-r--r--tests/ui/async-await/for-await-2015.rs1
-rw-r--r--tests/ui/async-await/in-trait/dyn-compatibility.stderr4
-rw-r--r--tests/ui/async-await/issue-65634-raw-ident-suggestion.edition2015.stderr6
-rw-r--r--tests/ui/async-await/issue-65634-raw-ident-suggestion.edition2018.stderr6
-rw-r--r--tests/ui/async-await/issue-65634-raw-ident-suggestion.rs1
-rw-r--r--tests/ui/async-await/suggest-switching-edition-on-await-cargo.rs1
-rw-r--r--tests/ui/async-await/suggest-switching-edition-on-await-cargo.stderr8
-rw-r--r--tests/ui/async-await/suggest-switching-edition-on-await.rs1
-rw-r--r--tests/ui/async-await/suggest-switching-edition-on-await.stderr8
-rw-r--r--tests/ui/attributes/auxiliary/external-macro-use.rs7
-rw-r--r--tests/ui/attributes/illegal-macro-use.rs15
-rw-r--r--tests/ui/attributes/illegal-macro-use.stderr27
-rw-r--r--tests/ui/attributes/use-extern-crate-named-macro-use.rs11
-rw-r--r--tests/ui/autoderef-full-lval.rs25
-rw-r--r--tests/ui/autodiff/autodiff_illegal.rs60
-rw-r--r--tests/ui/autodiff/autodiff_illegal.stderr83
-rw-r--r--tests/ui/autodiff/auxiliary/my_macro.rs2
-rw-r--r--tests/ui/autodiff/visibility.rs9
-rw-r--r--tests/ui/autodiff/visibility.std_autodiff.stderr26
-rw-r--r--tests/ui/autoref-autoderef/autoderef-box-no-add.rs35
-rw-r--r--tests/ui/autoref-autoderef/autoderef-box-no-add.stderr (renamed from tests/ui/autoderef-full-lval.stderr)4
-rw-r--r--tests/ui/autoref-autoderef/autoderef-vec-to-slice-by-value.rs18
-rw-r--r--tests/ui/auxiliary/delegate_macro.rs6
-rw-r--r--tests/ui/bogus-tag.rs10
-rw-r--r--tests/ui/borrow-by-val-method-receiver.rs14
-rw-r--r--tests/ui/cast/func-pointer-issue-140491.rs7
-rw-r--r--tests/ui/cast/func-pointer-issue-140491.stderr11
-rw-r--r--tests/ui/cfg/cfg-version/syntax.rs152
-rw-r--r--tests/ui/cfg/cfg-version/syntax.stderr188
-rw-r--r--tests/ui/cfg/diagnostics-reexport-2.rs61
-rw-r--r--tests/ui/cfg/diagnostics-reexport-2.stderr88
-rw-r--r--tests/ui/closures/2229_closure_analysis/run_pass/lit-pattern-matching-with-methods.rs4
-rw-r--r--tests/ui/coercion/issue-73886.stderr2
-rw-r--r--tests/ui/coercion/retslot-cast.rs8
-rw-r--r--tests/ui/coercion/retslot-cast.stderr4
-rw-r--r--tests/ui/const-ptr/allowed_slices.rs2
-rw-r--r--tests/ui/const-ptr/forbidden_slices.stderr21
-rw-r--r--tests/ui/const-ptr/out_of_bounds_read.stderr13
-rw-r--r--tests/ui/consts/const-eval/dont_promote_unstable_const_fn.stderr7
-rw-r--r--tests/ui/consts/const-eval/float_methods.rs46
-rw-r--r--tests/ui/consts/const-eval/ptr-to-int-transmute-in-consts-issue-87525.rs25
-rw-r--r--tests/ui/consts/const-eval/ptr-to-int-transmute-in-consts-issue-87525.stderr40
-rw-r--r--tests/ui/consts/const-eval/raw-pointer-ub.rs1
-rw-r--r--tests/ui/consts/const-eval/raw-pointer-ub.stderr6
-rw-r--r--tests/ui/consts/const-eval/ub-ref-ptr.stderr5
-rw-r--r--tests/ui/consts/const-unstable-intrinsic.stderr21
-rw-r--r--tests/ui/consts/const_unsafe_unreachable_ub.rs5
-rw-r--r--tests/ui/consts/const_unsafe_unreachable_ub.stderr6
-rw-r--r--tests/ui/consts/issue-miri-1910.stderr4
-rw-r--r--tests/ui/consts/min_const_fn/min_const_fn_libstd_stability.stderr49
-rw-r--r--tests/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability.stderr21
-rw-r--r--tests/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability2.stderr21
-rw-r--r--tests/ui/consts/min_const_fn/recursive_const_stab_unmarked_crate_imports.stderr7
-rw-r--r--tests/ui/consts/min_const_fn/recursive_const_stab_unstable_if_unmarked.stderr14
-rw-r--r--tests/ui/consts/missing_span_in_backtrace.stderr3
-rw-r--r--tests/ui/consts/offset_ub.stderr33
-rw-r--r--tests/ui/consts/required-consts/interpret-in-promoted.noopt.stderr4
-rw-r--r--tests/ui/consts/required-consts/interpret-in-promoted.opt.stderr4
-rw-r--r--tests/ui/coroutine/auxiliary/xcrate.rs2
-rw-r--r--tests/ui/coroutine/const_gen_fn.rs2
-rw-r--r--tests/ui/coroutine/const_gen_fn.stderr16
-rw-r--r--tests/ui/coroutine/gen_block.none.stderr4
-rw-r--r--tests/ui/delegation/bad-resolve.stderr4
-rw-r--r--tests/ui/delegation/glob-non-fn.stderr4
-rw-r--r--tests/ui/deprecation/deprecation-lint.rs4
-rw-r--r--tests/ui/derives/clone-debug-dead-code.stderr2
-rw-r--r--tests/ui/deriving/deriving-all-codegen.rs30
-rw-r--r--tests/ui/deriving/deriving-all-codegen.stdout165
-rw-r--r--tests/ui/deriving/deriving-in-macro.rs3
-rw-r--r--tests/ui/destructuring-assignment/bad-let-in-destructure.rs13
-rw-r--r--tests/ui/destructuring-assignment/bad-let-in-destructure.stderr10
-rw-r--r--tests/ui/did_you_mean/E0178.rs1
-rw-r--r--tests/ui/did_you_mean/E0178.stderr8
-rw-r--r--tests/ui/did_you_mean/trait-object-reference-without-parens-suggestion.rs2
-rw-r--r--tests/ui/did_you_mean/trait-object-reference-without-parens-suggestion.stderr20
-rw-r--r--tests/ui/dyn-compatibility/almost-supertrait-associated-type.rs1
-rw-r--r--tests/ui/dyn-compatibility/almost-supertrait-associated-type.stderr30
-rw-r--r--tests/ui/dyn-compatibility/associated-consts.rs1
-rw-r--r--tests/ui/dyn-compatibility/associated-consts.stderr19
-rw-r--r--tests/ui/dyn-compatibility/generics.rs2
-rw-r--r--tests/ui/dyn-compatibility/generics.stderr42
-rw-r--r--tests/ui/dyn-compatibility/mention-correct-dyn-incompatible-trait.rs1
-rw-r--r--tests/ui/dyn-compatibility/mention-correct-dyn-incompatible-trait.stderr25
-rw-r--r--tests/ui/dyn-compatibility/mentions-Self.rs2
-rw-r--r--tests/ui/dyn-compatibility/mentions-Self.stderr38
-rw-r--r--tests/ui/dyn-compatibility/no-static.rs1
-rw-r--r--tests/ui/dyn-compatibility/no-static.stderr31
-rw-r--r--tests/ui/dyn-compatibility/sized-2.rs1
-rw-r--r--tests/ui/dyn-compatibility/sized-2.stderr18
-rw-r--r--tests/ui/dyn-compatibility/sized.rs1
-rw-r--r--tests/ui/dyn-compatibility/sized.stderr18
-rw-r--r--tests/ui/dyn-compatibility/taint-const-eval.rs1
-rw-r--r--tests/ui/dyn-compatibility/taint-const-eval.stderr26
-rw-r--r--tests/ui/dyn-drop/dyn-drop.rs3
-rw-r--r--tests/ui/dyn-drop/dyn-drop.stderr14
-rw-r--r--tests/ui/editions/async-block-2015.rs1
-rw-r--r--tests/ui/editions/async-block-2015.stderr8
-rw-r--r--tests/ui/editions/edition-extern-crate-allowed.stderr6
-rw-r--r--tests/ui/enum-discriminant/discriminant_size.rs3
-rw-r--r--tests/ui/enum-discriminant/discriminant_size.stderr11
-rw-r--r--tests/ui/enum-discriminant/issue-43398.stderr11
-rw-r--r--tests/ui/enum-discriminant/issue-70509-partial_eq.rs2
-rw-r--r--tests/ui/enum-discriminant/issue-70509-partial_eq.stderr11
-rw-r--r--tests/ui/enum-discriminant/repr128-get-discriminant-issue-43398.rs (renamed from tests/ui/enum-discriminant/issue-43398.rs)2
-rw-r--r--tests/ui/enum-discriminant/repr128.rs3
-rw-r--r--tests/ui/enum-discriminant/repr128.stderr11
-rw-r--r--tests/ui/ergonomic-clones/async/edition-2015.rs1
-rw-r--r--tests/ui/ergonomic-clones/async/edition-2015.stderr2
-rw-r--r--tests/ui/error-codes/E0657.rs4
-rw-r--r--tests/ui/error-codes/E0657.stderr24
-rw-r--r--tests/ui/error-codes/E0658.rs5
-rw-r--r--tests/ui/error-codes/E0658.stderr11
-rw-r--r--tests/ui/errors/dynless-turbofish-e0191-issue-91997.rs1
-rw-r--r--tests/ui/errors/dynless-turbofish-e0191-issue-91997.stderr4
-rw-r--r--tests/ui/expr/scope.rs1
-rw-r--r--tests/ui/feature-gates/feature-gate-asm_cfg.rs48
-rw-r--r--tests/ui/feature-gates/feature-gate-asm_cfg.stderr57
-rw-r--r--tests/ui/feature-gates/feature-gate-autodiff-use.has_support.stderr8
-rw-r--r--tests/ui/feature-gates/feature-gate-autodiff-use.no_support.stderr12
-rw-r--r--tests/ui/feature-gates/feature-gate-autodiff-use.rs4
-rw-r--r--tests/ui/feature-gates/feature-gate-autodiff.has_support.stderr8
-rw-r--r--tests/ui/feature-gates/feature-gate-autodiff.no_support.stderr8
-rw-r--r--tests/ui/feature-gates/feature-gate-autodiff.rs6
-rw-r--r--tests/ui/feature-gates/feature-gate-cfg-version.rs49
-rw-r--r--tests/ui/feature-gates/feature-gate-cfg-version.stderr204
-rw-r--r--tests/ui/feature-gates/feature-gate-coroutines.e2024.stderr8
-rw-r--r--tests/ui/feature-gates/feature-gate-coroutines.none.stderr8
-rw-r--r--tests/ui/feature-gates/feature-gate-dispatch-from-dyn-missing-impl.rs1
-rw-r--r--tests/ui/feature-gates/feature-gate-dispatch-from-dyn-missing-impl.stderr26
-rw-r--r--tests/ui/feature-gates/feature-gate-repr128.rs6
-rw-r--r--tests/ui/feature-gates/feature-gate-repr128.stderr13
-rw-r--r--tests/ui/feature-gates/feature-gate-yield-expr.stderr2
-rw-r--r--tests/ui/feature-gates/version_check.rs17
-rw-r--r--tests/ui/functions-closures/bare-fn-implements-fn-mut.rs (renamed from tests/ui/bare-fn-implements-fn-mut.rs)4
-rw-r--r--tests/ui/generic-associated-types/gat-in-trait-path.rs1
-rw-r--r--tests/ui/generic-associated-types/gat-in-trait-path.stderr19
-rw-r--r--tests/ui/generic-associated-types/issue-71176.rs1
-rw-r--r--tests/ui/generic-associated-types/issue-71176.stderr20
-rw-r--r--tests/ui/generic-associated-types/issue-76535.rs1
-rw-r--r--tests/ui/generic-associated-types/issue-76535.stderr25
-rw-r--r--tests/ui/generic-associated-types/issue-78671.stderr4
-rw-r--r--tests/ui/generic-associated-types/issue-79422.rs14
-rw-r--r--tests/ui/generic-associated-types/issue-79422.stderr29
-rw-r--r--tests/ui/generic-const-items/def-site-eval.fail.stderr4
-rw-r--r--tests/ui/generic-const-items/def-site-eval.rs7
-rw-r--r--tests/ui/generic-const-items/def-site-predicates-wf.rs9
-rw-r--r--tests/ui/generic-const-items/def-site-predicates-wf.stderr13
-rw-r--r--tests/ui/higher-ranked/higher-ranked-invalid-bounds.rs (renamed from tests/ui/bounds-lifetime.rs)2
-rw-r--r--tests/ui/higher-ranked/higher-ranked-invalid-bounds.stderr (renamed from tests/ui/bounds-lifetime.stderr)10
-rw-r--r--tests/ui/higher-ranked/trait-bounds/span-bug-issue-121597.rs2
-rw-r--r--tests/ui/higher-ranked/trait-bounds/span-bug-issue-121597.stderr41
-rw-r--r--tests/ui/impl-trait/dyn-incompatible-trait-in-return-position-dyn-trait.rs6
-rw-r--r--tests/ui/impl-trait/dyn-incompatible-trait-in-return-position-dyn-trait.stderr28
-rw-r--r--tests/ui/impl-trait/in-trait/dyn-compatibility.rs1
-rw-r--r--tests/ui/impl-trait/in-trait/dyn-compatibility.stderr24
-rw-r--r--tests/ui/impl-trait/in-trait/foreign-dyn-error.stderr4
-rw-r--r--tests/ui/imports/extern-crate-used.stderr7
-rw-r--r--tests/ui/imports/import-glob-crate.rs1
-rw-r--r--tests/ui/instrument-xray/platform-support.rs27
-rw-r--r--tests/ui/instrument-xray/platform-support.unsupported.stderr (renamed from tests/ui/instrument-xray/target-not-supported.stderr)0
-rw-r--r--tests/ui/instrument-xray/target-not-supported.rs10
-rw-r--r--tests/ui/intrinsics/const-eval-select-stability.stderr7
-rw-r--r--tests/ui/intrinsics/intrinsic-atomics.rs6
-rw-r--r--tests/ui/intrinsics/non-integer-atomic.rs18
-rw-r--r--tests/ui/intrinsics/non-integer-atomic.stderr24
-rw-r--r--tests/ui/issues/issue-18959.rs2
-rw-r--r--tests/ui/issues/issue-18959.stderr11
-rw-r--r--tests/ui/issues/issue-19380.rs1
-rw-r--r--tests/ui/issues/issue-19380.stderr27
-rw-r--r--tests/ui/issues/issue-50781.rs1
-rw-r--r--tests/ui/issues/issue-50781.stderr24
-rw-r--r--tests/ui/issues/issue-58734.rs3
-rw-r--r--tests/ui/issues/issue-58734.stderr11
-rw-r--r--tests/ui/iterators/generator.rs24
-rw-r--r--tests/ui/iterators/generator_args.rs24
-rw-r--r--tests/ui/iterators/generator_capture.rs27
-rw-r--r--tests/ui/iterators/generator_capture_.rs26
-rw-r--r--tests/ui/iterators/generator_capture_.stderr25
-rw-r--r--tests/ui/iterators/generator_capture_fail.rs25
-rw-r--r--tests/ui/iterators/generator_capture_fail.stderr20
-rw-r--r--tests/ui/iterators/generator_capture_fnonce.rs32
-rw-r--r--tests/ui/iterators/generator_capture_no_lend.rs30
-rw-r--r--tests/ui/iterators/generator_returned_from_fn.rs63
-rw-r--r--tests/ui/iterators/generator_returned_from_fn.stderr70
-rw-r--r--tests/ui/iterators/iter-macro-not-async-closure-simplified.narrow.stderr18
-rw-r--r--tests/ui/iterators/iter-macro-not-async-closure-simplified.rs29
-rw-r--r--tests/ui/iterators/iter-macro-not-async-closure-simplified.wide.stderr17
-rw-r--r--tests/ui/iterators/iter-macro-not-async-closure.narrow.stderr72
-rw-r--r--tests/ui/iterators/iter-macro-not-async-closure.rs32
-rw-r--r--tests/ui/iterators/iter-macro-not-async-closure.stderr67
-rw-r--r--tests/ui/kindck/kindck-inherited-copy-bound.rs1
-rw-r--r--tests/ui/kindck/kindck-inherited-copy-bound.stderr22
-rw-r--r--tests/ui/lint/dead-code/alias-type-used-as-generic-arg-in-impl.rs19
-rw-r--r--tests/ui/lint/dead-code/issue-41883.stderr2
-rw-r--r--tests/ui/lint/dead-code/multiple-dead-codes-in-the-same-struct.stderr2
-rw-r--r--tests/ui/lint/dead-code/trait-only-used-as-type-bound.rs31
-rw-r--r--tests/ui/lint/lint-ctypes-enum.rs2
-rw-r--r--tests/ui/lint/lint-ctypes-enum.stderr68
-rw-r--r--tests/ui/lint/overflowing-literals-valid.rs (renamed from tests/ui/big-literals.rs)4
-rw-r--r--tests/ui/lint/unnecessary-extern-crate.stderr41
-rw-r--r--tests/ui/lint/unused/lint-unused-extern-crate.stderr15
-rw-r--r--tests/ui/lint/unused/unused-braces-attrs-issue-141549.fixed15
-rw-r--r--tests/ui/lint/unused/unused-braces-attrs-issue-141549.rs15
-rw-r--r--tests/ui/lint/unused/unused-braces-attrs-issue-141549.stderr19
-rw-r--r--tests/ui/lint/wide_pointer_comparisons.stderr150
-rw-r--r--tests/ui/macros/auxiliary/borrowck-error-in-macro.rs10
-rw-r--r--tests/ui/macros/borrowck-error-in-macro.rs8
-rw-r--r--tests/ui/macros/borrowck-error-in-macro.stderr19
-rw-r--r--tests/ui/macros/ice-in-tokenstream-for-contracts-issue-140683.rs13
-rw-r--r--tests/ui/macros/ice-in-tokenstream-for-contracts-issue-140683.stderr34
-rw-r--r--tests/ui/macros/no-close-delim-issue-139248.rs5
-rw-r--r--tests/ui/macros/no-close-delim-issue-139248.stderr16
-rw-r--r--tests/ui/methods/vec-autoderef-autoref.rs (renamed from tests/ui/auto-ref-slice-plus-ref.rs)7
-rw-r--r--tests/ui/methods/vec-autoderef-autoref.stderr (renamed from tests/ui/auto-ref-slice-plus-ref.stderr)16
-rw-r--r--tests/ui/namespace/namespace-mix.stderr4
-rw-r--r--tests/ui/nll/user-annotations/normalizing-user-annotation.rs31
-rw-r--r--tests/ui/not-enough-arguments.rs52
-rw-r--r--tests/ui/not-enough-arguments.stderr94
-rw-r--r--tests/ui/numbers-arithmetic/bitwise-ops-platform.rs (renamed from tests/ui/bitwise.rs)2
-rw-r--r--tests/ui/parser/macro/auxiliary/unicode-control.rs19
-rw-r--r--tests/ui/parser/macro/unicode-control-codepoints-macros.rs49
-rw-r--r--tests/ui/parser/macro/unicode-control-codepoints-macros.stderr57
-rw-r--r--tests/ui/parser/match-arm-comma-typo-issue-140991.fixed24
-rw-r--r--tests/ui/parser/match-arm-comma-typo-issue-140991.rs24
-rw-r--r--tests/ui/parser/match-arm-comma-typo-issue-140991.stderr26
-rw-r--r--tests/ui/parser/unicode-control-codepoints.rs2
-rw-r--r--tests/ui/parser/unicode-control-codepoints.stderr34
-rw-r--r--tests/ui/pattern/pattern-match-arc-move.rs (renamed from tests/ui/bind-by-move.rs)2
-rw-r--r--tests/ui/pattern/pattern-match-invalid-variant.rs19
-rw-r--r--tests/ui/pattern/pattern-match-invalid-variant.stderr (renamed from tests/ui/bogus-tag.stderr)6
-rw-r--r--tests/ui/print-request/emit-warning-print-link-info-without-staticlib.rs5
-rw-r--r--tests/ui/print-request/emit-warning-print-link-info-without-staticlib.stderr6
-rw-r--r--tests/ui/print-request/emit-warning-while-exe-and-print-link-info.rs3
-rw-r--r--tests/ui/print-request/emit-warning-while-exe-and-print-link-info.stderr4
-rw-r--r--tests/ui/print-request/stability.rs1
-rw-r--r--tests/ui/print_type_sizes/niche-filling.rs9
-rw-r--r--tests/ui/print_type_sizes/niche-filling.stdout4
-rw-r--r--tests/ui/proc-macro/no-macro-use-attr.stderr6
-rw-r--r--tests/ui/repeat-expr/copy-check-when-count-inferred-later.rs11
-rw-r--r--tests/ui/repeat-expr/copy-check-when-count-inferred-later.stderr14
-rw-r--r--tests/ui/resolve/extern-crate-lint-issue-141785.rs11
-rw-r--r--tests/ui/resolve/tuple-struct-alias.stderr15
-rw-r--r--tests/ui/rust-2018/extern-crate-idiomatic-in-2018.stderr6
-rw-r--r--tests/ui/rust-2018/issue-54400-unused-extern-crate-attr-span.rs2
-rw-r--r--tests/ui/rust-2018/issue-54400-unused-extern-crate-attr-span.stderr12
-rw-r--r--tests/ui/rust-2018/remove-extern-crate.stderr7
-rw-r--r--tests/ui/rust-2018/removing-extern-crate-malformed-cfg.fixed15
-rw-r--r--tests/ui/rust-2018/removing-extern-crate-malformed-cfg.rs17
-rw-r--r--tests/ui/rust-2018/removing-extern-crate-malformed-cfg.stderr76
-rw-r--r--tests/ui/rust-2018/removing-extern-crate.stderr31
-rw-r--r--tests/ui/self/arbitrary-self-types-dyn-incompatible.rs1
-rw-r--r--tests/ui/self/arbitrary-self-types-dyn-incompatible.stderr26
-rw-r--r--tests/ui/statics/unsizing-wfcheck-issue-127299.rs1
-rw-r--r--tests/ui/statics/unsizing-wfcheck-issue-127299.stderr26
-rw-r--r--tests/ui/stats/input-stats.rs4
-rw-r--r--tests/ui/stats/input-stats.stderr322
-rw-r--r--tests/ui/str/str-static-literal.rs (renamed from tests/ui/bare-static-string.rs)2
-rw-r--r--tests/ui/suggestions/unnamable-types.rs2
-rw-r--r--tests/ui/threads-sendsync/tls-dont-move-after-init.rs37
-rw-r--r--tests/ui/traits/const-traits/staged-api.stderr133
-rw-r--r--tests/ui/traits/issue-20692.rs1
-rw-r--r--tests/ui/traits/issue-20692.stderr23
-rw-r--r--tests/ui/traits/issue-38604.rs2
-rw-r--r--tests/ui/traits/issue-38604.stderr23
-rw-r--r--tests/ui/traits/item-privacy.rs4
-rw-r--r--tests/ui/traits/item-privacy.stderr54
-rw-r--r--tests/ui/traits/next-solver/normalize/normalize-place-elem.rs32
-rw-r--r--tests/ui/traits/non_lifetime_binders/supertrait-dyn-compatibility.rs2
-rw-r--r--tests/ui/traits/non_lifetime_binders/supertrait-dyn-compatibility.stderr39
-rw-r--r--tests/ui/traits/object/canonicalize-fresh-infer-vars-issue-103626.rs2
-rw-r--r--tests/ui/traits/object/canonicalize-fresh-infer-vars-issue-103626.stderr48
-rw-r--r--tests/ui/traits/object/macro-matcher.stderr16
-rw-r--r--tests/ui/traits/object/safety.rs1
-rw-r--r--tests/ui/traits/object/safety.stderr31
-rw-r--r--tests/ui/traits/test-2.rs1
-rw-r--r--tests/ui/traits/test-2.stderr30
-rw-r--r--tests/ui/transmutability/enums/repr/should_handle_all.rs3
-rw-r--r--tests/ui/transmute/unnecessary-transmutation.stderr226
-rw-r--r--tests/ui/type-alias-impl-trait/issue-53678-coroutine-and-const-fn.rs2
-rw-r--r--tests/ui/type/type-parameter-defaults-referencing-Self-ppaux.rs1
-rw-r--r--tests/ui/type/type-parameter-defaults-referencing-Self-ppaux.stderr21
-rw-r--r--tests/ui/typeck/consider-borrowing-141810-1.rs9
-rw-r--r--tests/ui/typeck/consider-borrowing-141810-1.stderr28
-rw-r--r--tests/ui/typeck/consider-borrowing-141810-2.rs8
-rw-r--r--tests/ui/typeck/consider-borrowing-141810-2.stderr19
-rw-r--r--tests/ui/typeck/consider-borrowing-141810-3.rs7
-rw-r--r--tests/ui/typeck/consider-borrowing-141810-3.stderr22
-rw-r--r--tests/ui/typeck/consider-borrowing-141810-4.rs11
-rw-r--r--tests/ui/typeck/consider-borrowing-141810-4.stderr14
-rw-r--r--tests/ui/ufcs/ufcs-partially-resolved.stderr2
-rw-r--r--tests/ui/unsafe-binders/cat-projection.rs24
-rw-r--r--tests/ui/unsafe-binders/unused-lifetimes-2.fixed20
-rw-r--r--tests/ui/unsafe-binders/unused-lifetimes-2.rs20
-rw-r--r--tests/ui/unsafe-binders/unused-lifetimes-2.stderr16
-rw-r--r--tests/ui/unsafe-binders/unused-lifetimes.fixed20
-rw-r--r--tests/ui/unsafe-binders/unused-lifetimes.rs20
-rw-r--r--tests/ui/unsafe-binders/unused-lifetimes.stderr14
-rw-r--r--tests/ui/unsafe/move-out-of-non-copy.rs15
-rw-r--r--tests/ui/unsafe/move-out-of-non-copy.stderr14
-rw-r--r--tests/ui/wf/wf-dyn-incompatible.stderr4
-rw-r--r--triagebot.toml20
1307 files changed, 22314 insertions, 13310 deletions
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 566ae223500..81fb39cdc56 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -34,7 +34,7 @@ concurrency:
   # For a given workflow, if we push to the same branch, cancel all previous builds on that branch.
   # We add an exception for try builds (try branch) and unrolled rollup builds (try-perf), which
   # are all triggered on the same branch, but which should be able to run concurrently.
-  group: ${{ github.workflow }}-${{ ((github.ref == 'refs/heads/try' || github.ref == 'refs/heads/try-perf') && github.sha) || github.ref }}
+  group: ${{ github.workflow }}-${{ ((github.ref == 'refs/heads/try' || github.ref == 'refs/heads/try-perf' || github.ref == 'refs/heads/automation/bors/try') && github.sha) || github.ref }}
   cancel-in-progress: true
 env:
   TOOLSTATE_REPO: "https://github.com/rust-lang-nursery/rust-toolstate"
@@ -46,7 +46,7 @@ jobs:
   # If you want to modify CI jobs, take a look at src/ci/github-actions/jobs.yml.
   calculate_matrix:
     name: Calculate job matrix
-    runs-on: ubuntu-24.04
+    runs-on: ubuntu-24.04-arm
     outputs:
       jobs: ${{ steps.jobs.outputs.jobs }}
       run_type: ${{ steps.jobs.outputs.run_type }}
@@ -79,9 +79,8 @@ jobs:
     # This also ensures that PR CI (which doesn't get write access to S3) works, as it cannot
     # access the environment.
     #
-    # We only enable the environment for the rust-lang/rust repository, so that rust-lang-ci/rust
-    # CI works until we migrate off it (since that repository doesn't contain the environment).
-    environment: ${{ ((github.repository == 'rust-lang/rust' && (github.ref == 'refs/heads/try' || github.ref == 'refs/heads/auto')) && 'bors') || '' }}
+    # We only enable the environment for the rust-lang/rust repository, so that CI works on forks.
+    environment: ${{ ((github.repository == 'rust-lang/rust' && (github.ref == 'refs/heads/try' || github.ref == 'refs/heads/try-perf' || github.ref == 'refs/heads/automation/bors/try' || github.ref == 'refs/heads/auto')) && 'bors') || '' }}
     env:
       CI_JOB_NAME: ${{ matrix.name }}
       CI_JOB_DOC_URL: ${{ matrix.doc_url }}
@@ -234,8 +233,8 @@ jobs:
           fi
           exit ${STATUS}
         env:
-          AWS_ACCESS_KEY_ID: ${{ (github.repository == 'rust-lang/rust' && secrets.CACHES_AWS_ACCESS_KEY_ID) || env.CACHES_AWS_ACCESS_KEY_ID }}
-          AWS_SECRET_ACCESS_KEY: ${{ (github.repository == 'rust-lang/rust' && secrets.CACHES_AWS_SECRET_ACCESS_KEY) || secrets[format('AWS_SECRET_ACCESS_KEY_{0}', env.CACHES_AWS_ACCESS_KEY_ID)] }}
+          AWS_ACCESS_KEY_ID: ${{ secrets.CACHES_AWS_ACCESS_KEY_ID }}
+          AWS_SECRET_ACCESS_KEY: ${{ secrets.CACHES_AWS_SECRET_ACCESS_KEY }}
 
       - name: create github artifacts
         run: src/ci/scripts/create-doc-artifacts.sh
@@ -257,8 +256,8 @@ jobs:
       - name: upload artifacts to S3
         run: src/ci/scripts/upload-artifacts.sh
         env:
-          AWS_ACCESS_KEY_ID: ${{ (github.repository == 'rust-lang/rust' && secrets.ARTIFACTS_AWS_ACCESS_KEY_ID) || env.ARTIFACTS_AWS_ACCESS_KEY_ID }}
-          AWS_SECRET_ACCESS_KEY: ${{ (github.repository == 'rust-lang/rust' && secrets.ARTIFACTS_AWS_SECRET_ACCESS_KEY) || secrets[format('AWS_SECRET_ACCESS_KEY_{0}', env.ARTIFACTS_AWS_ACCESS_KEY_ID)] }}
+          AWS_ACCESS_KEY_ID: ${{ secrets.ARTIFACTS_AWS_ACCESS_KEY_ID }}
+          AWS_SECRET_ACCESS_KEY: ${{ secrets.ARTIFACTS_AWS_SECRET_ACCESS_KEY }}
         # Adding a condition on DEPLOY=1 or DEPLOY_ALT=1 is not needed as all deploy
         # builders *should* have the AWS credentials available. Still, explicitly
         # adding the condition is helpful as this way CI will not silently skip
diff --git a/.mailmap b/.mailmap
index c3ce111bfe3..3b57f88ecab 100644
--- a/.mailmap
+++ b/.mailmap
@@ -653,7 +653,7 @@ Torsten Weber <TorstenWeber12@gmail.com> <torstenweber12@gmail.com>
 Trevor Gross <tmgross@umich.edu> <t.gross35@gmail.com>
 Trevor Gross <tmgross@umich.edu> <tgross@intrepidcs.com>
 Trevor Spiteri <tspiteri@ieee.org> <trevor.spiteri@um.edu.mt>
-Tshepang Mbambo <tshepang@gmail.com>
+Tshepang Mbambo <hopsi@tuta.io> <tshepang@gmail.com>
 Ty Overby <ty@pre-alpha.com>
 Tyler Mandry <tmandry@gmail.com> <tmandry@google.com>
 Tyler Ruckinger <t.ruckinger@gmail.com>
diff --git a/Cargo.lock b/Cargo.lock
index 177ff6594e2..43f5f40925b 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -179,24 +179,11 @@ checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50"
 
 [[package]]
 name = "askama"
-version = "0.13.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5d4744ed2eef2645831b441d8f5459689ade2ab27c854488fbab1fbe94fce1a7"
-dependencies = [
- "askama_derive 0.13.1",
- "itoa",
- "percent-encoding",
- "serde",
- "serde_json",
-]
-
-[[package]]
-name = "askama"
 version = "0.14.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "f75363874b771be265f4ffe307ca705ef6f3baa19011c149da8674a87f1b75c4"
 dependencies = [
- "askama_derive 0.14.0",
+ "askama_derive",
  "itoa",
  "percent-encoding",
  "serde",
@@ -205,28 +192,11 @@ dependencies = [
 
 [[package]]
 name = "askama_derive"
-version = "0.13.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d661e0f57be36a5c14c48f78d09011e67e0cb618f269cca9f2fd8d15b68c46ac"
-dependencies = [
- "askama_parser 0.13.0",
- "basic-toml",
- "memchr",
- "proc-macro2",
- "quote",
- "rustc-hash 2.1.1",
- "serde",
- "serde_derive",
- "syn 2.0.101",
-]
-
-[[package]]
-name = "askama_derive"
 version = "0.14.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "129397200fe83088e8a68407a8e2b1f826cf0086b21ccdb866a722c8bcd3a94f"
 dependencies = [
- "askama_parser 0.14.0",
+ "askama_parser",
  "basic-toml",
  "memchr",
  "proc-macro2",
@@ -239,18 +209,6 @@ dependencies = [
 
 [[package]]
 name = "askama_parser"
-version = "0.13.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cf315ce6524c857bb129ff794935cf6d42c82a6cff60526fe2a63593de4d0d4f"
-dependencies = [
- "memchr",
- "serde",
- "serde_derive",
- "winnow 0.7.10",
-]
-
-[[package]]
-name = "askama_parser"
 version = "0.14.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "d6ab5630b3d5eaf232620167977f95eb51f3432fc76852328774afbd242d4358"
@@ -582,7 +540,7 @@ name = "clippy"
 version = "0.1.89"
 dependencies = [
  "anstream",
- "askama 0.13.1",
+ "askama",
  "cargo_metadata 0.18.1",
  "clippy_config",
  "clippy_lints",
@@ -1259,16 +1217,16 @@ dependencies = [
 
 [[package]]
 name = "fluent-bundle"
-version = "0.15.3"
+version = "0.16.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7fe0a21ee80050c678013f82edf4b705fe2f26f1f9877593d13198612503f493"
+checksum = "01203cb8918f5711e73891b347816d932046f95f54207710bda99beaeb423bf4"
 dependencies = [
  "fluent-langneg",
  "fluent-syntax",
  "intl-memoizer",
  "intl_pluralrules",
- "rustc-hash 1.1.0",
- "self_cell 0.10.3",
+ "rustc-hash 2.1.1",
+ "self_cell",
  "smallvec",
  "unic-langid",
 ]
@@ -1284,11 +1242,12 @@ dependencies = [
 
 [[package]]
 name = "fluent-syntax"
-version = "0.11.1"
+version = "0.12.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2a530c4694a6a8d528794ee9bbd8ba0122e779629ac908d15ad5a7ae7763a33d"
+checksum = "54f0d287c53ffd184d04d8677f590f4ac5379785529e5e08b1c8083acdd5c198"
 dependencies = [
- "thiserror 1.0.69",
+ "memchr",
+ "thiserror 2.0.12",
 ]
 
 [[package]]
@@ -1431,7 +1390,7 @@ name = "generate-copyright"
 version = "0.1.0"
 dependencies = [
  "anyhow",
- "askama 0.14.0",
+ "askama",
  "cargo_metadata 0.18.1",
  "serde",
  "serde_json",
@@ -1934,9 +1893,9 @@ dependencies = [
 
 [[package]]
 name = "intl-memoizer"
-version = "0.5.2"
+version = "0.5.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fe22e020fce238ae18a6d5d8c502ee76a52a6e880d99477657e6acc30ec57bda"
+checksum = "310da2e345f5eb861e7a07ee182262e94975051db9e4223e909ba90f392f163f"
 dependencies = [
  "type-map",
  "unic-langid",
@@ -2170,6 +2129,7 @@ dependencies = [
 name = "lint-docs"
 version = "0.1.0"
 dependencies = [
+ "rustc-literal-escaper",
  "serde_json",
  "tempfile",
  "walkdir",
@@ -3444,6 +3404,7 @@ dependencies = [
  "rustc_macros",
  "rustc_parse",
  "rustc_parse_format",
+ "rustc_proc_macro",
  "rustc_session",
  "rustc_span",
  "rustc_target",
@@ -3733,6 +3694,7 @@ dependencies = [
  "rustc_lint_defs",
  "rustc_macros",
  "rustc_parse",
+ "rustc_proc_macro",
  "rustc_serialize",
  "rustc_session",
  "rustc_span",
@@ -4081,6 +4043,7 @@ dependencies = [
  "rustc_index",
  "rustc_macros",
  "rustc_middle",
+ "rustc_proc_macro",
  "rustc_serialize",
  "rustc_session",
  "rustc_span",
@@ -4338,6 +4301,13 @@ dependencies = [
 ]
 
 [[package]]
+name = "rustc_proc_macro"
+version = "0.0.0"
+dependencies = [
+ "rustc-literal-escaper",
+]
+
+[[package]]
 name = "rustc_query_impl"
 version = "0.0.0"
 dependencies = [
@@ -4664,7 +4634,7 @@ name = "rustdoc"
 version = "0.0.0"
 dependencies = [
  "arrayvec",
- "askama 0.14.0",
+ "askama",
  "base64",
  "expect-test",
  "indexmap",
@@ -4834,15 +4804,6 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
 
 [[package]]
 name = "self_cell"
-version = "0.10.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e14e4d63b804dc0c7ec4a1e52bcb63f02c7ac94476755aa579edac21e01f915d"
-dependencies = [
- "self_cell 1.2.0",
-]
-
-[[package]]
-name = "self_cell"
 version = "1.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "0f7d95a54511e0c7be3f51e8867aa8cf35148d7b9445d44de2f943e2b206e749"
diff --git a/Cargo.toml b/Cargo.toml
index 16ff0f61593..c4d2a06f4cb 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -4,7 +4,6 @@ members = [
 # tidy-alphabetical-start
   "compiler/rustc",
   "src/build_helper",
-  "src/etc/test-float-parse",
   "src/rustc-std-workspace/rustc-std-workspace-alloc",
   "src/rustc-std-workspace/rustc-std-workspace-core",
   "src/rustc-std-workspace/rustc-std-workspace-std",
@@ -41,6 +40,7 @@ members = [
   "src/tools/rustdoc-themes",
   "src/tools/rustfmt",
   "src/tools/suggest-tests",
+  "src/tools/test-float-parse",
   "src/tools/tidy",
   "src/tools/tier-check",
   "src/tools/unicode-table-generator",
diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs
index a16219361c0..5c122ff0bbc 100644
--- a/compiler/rustc_ast/src/ast.rs
+++ b/compiler/rustc_ast/src/ast.rs
@@ -32,7 +32,7 @@ use rustc_data_structures::tagged_ptr::Tag;
 use rustc_macros::{Decodable, Encodable, HashStable_Generic};
 pub use rustc_span::AttrId;
 use rustc_span::source_map::{Spanned, respan};
-use rustc_span::{ErrorGuaranteed, Ident, Span, Symbol, kw, sym};
+use rustc_span::{DUMMY_SP, ErrorGuaranteed, Ident, Span, Symbol, kw, sym};
 use thin_vec::{ThinVec, thin_vec};
 
 pub use crate::format::*;
@@ -1526,6 +1526,19 @@ impl Expr {
                 | ExprKind::Struct(_)
         )
     }
+
+    /// Creates a dummy `P<Expr>`.
+    ///
+    /// Should only be used when it will be replaced afterwards or as a return value when an error was encountered.
+    pub fn dummy() -> P<Expr> {
+        P(Expr {
+            id: DUMMY_NODE_ID,
+            kind: ExprKind::Dummy,
+            span: DUMMY_SP,
+            attrs: ThinVec::new(),
+            tokens: None,
+        })
+    }
 }
 
 #[derive(Clone, Encodable, Decodable, Debug)]
@@ -2452,6 +2465,39 @@ impl TyKind {
             None
         }
     }
+
+    /// Returns `true` if this type is considered a scalar primitive (e.g.,
+    /// `i32`, `u8`, `bool`, etc).
+    ///
+    /// This check is based on **symbol equality** and does **not** remove any
+    /// path prefixes or references. If a type alias or shadowing is present
+    /// (e.g., `type i32 = CustomType;`), this method will still return `true`
+    /// for `i32`, even though it may not refer to the primitive type.
+    pub fn maybe_scalar(&self) -> bool {
+        let Some(ty_sym) = self.is_simple_path() else {
+            // unit type
+            return self.is_unit();
+        };
+        matches!(
+            ty_sym,
+            sym::i8
+                | sym::i16
+                | sym::i32
+                | sym::i64
+                | sym::i128
+                | sym::u8
+                | sym::u16
+                | sym::u32
+                | sym::u64
+                | sym::u128
+                | sym::f16
+                | sym::f32
+                | sym::f64
+                | sym::f128
+                | sym::char
+                | sym::bool
+        )
+    }
 }
 
 /// A pattern type pattern.
@@ -3417,9 +3463,9 @@ impl Item {
             ItemKind::Fn(i) => Some(&i.generics),
             ItemKind::TyAlias(i) => Some(&i.generics),
             ItemKind::TraitAlias(_, generics, _)
-            | ItemKind::Enum(_, _, generics)
-            | ItemKind::Struct(_, _, generics)
-            | ItemKind::Union(_, _, generics) => Some(&generics),
+            | ItemKind::Enum(_, generics, _)
+            | ItemKind::Struct(_, generics, _)
+            | ItemKind::Union(_, generics, _) => Some(&generics),
             ItemKind::Trait(i) => Some(&i.generics),
             ItemKind::Impl(i) => Some(&i.generics),
         }
@@ -3663,15 +3709,15 @@ pub enum ItemKind {
     /// An enum definition (`enum`).
     ///
     /// E.g., `enum Foo<A, B> { C<A>, D<B> }`.
-    Enum(Ident, EnumDef, Generics),
+    Enum(Ident, Generics, EnumDef),
     /// A struct definition (`struct`).
     ///
     /// E.g., `struct Foo<A> { x: A }`.
-    Struct(Ident, VariantData, Generics),
+    Struct(Ident, Generics, VariantData),
     /// A union definition (`union`).
     ///
     /// E.g., `union Foo<A, B> { x: A, y: B }`.
-    Union(Ident, VariantData, Generics),
+    Union(Ident, Generics, VariantData),
     /// A trait declaration (`trait`).
     ///
     /// E.g., `trait Foo { .. }`, `trait Foo<T> { .. }` or `auto trait Foo {}`.
@@ -3688,10 +3734,8 @@ pub enum ItemKind {
     ///
     /// E.g., `foo!(..)`.
     MacCall(P<MacCall>),
-
     /// A macro definition.
     MacroDef(Ident, MacroDef),
-
     /// A single delegation item (`reuse`).
     ///
     /// E.g. `reuse <Type as Trait>::name { target_expr_template }`.
@@ -3767,9 +3811,9 @@ impl ItemKind {
             Self::Fn(box Fn { generics, .. })
             | Self::TyAlias(box TyAlias { generics, .. })
             | Self::Const(box ConstItem { generics, .. })
-            | Self::Enum(_, _, generics)
-            | Self::Struct(_, _, generics)
-            | Self::Union(_, _, generics)
+            | Self::Enum(_, generics, _)
+            | Self::Struct(_, generics, _)
+            | Self::Union(_, generics, _)
             | Self::Trait(box Trait { generics, .. })
             | Self::TraitAlias(_, generics, _)
             | Self::Impl(box Impl { generics, .. }) => Some(generics),
diff --git a/compiler/rustc_ast/src/ast_traits.rs b/compiler/rustc_ast/src/ast_traits.rs
index 21de7ff7719..797ab297319 100644
--- a/compiler/rustc_ast/src/ast_traits.rs
+++ b/compiler/rustc_ast/src/ast_traits.rs
@@ -304,6 +304,7 @@ impl HasAttrs for Stmt {
 }
 
 /// A newtype around an AST node that implements the traits above if the node implements them.
+#[repr(transparent)]
 pub struct AstNodeWrapper<Wrapped, Tag> {
     pub wrapped: Wrapped,
     pub tag: PhantomData<Tag>,
@@ -313,6 +314,11 @@ impl<Wrapped, Tag> AstNodeWrapper<Wrapped, Tag> {
     pub fn new(wrapped: Wrapped, _tag: Tag) -> AstNodeWrapper<Wrapped, Tag> {
         AstNodeWrapper { wrapped, tag: Default::default() }
     }
+
+    pub fn from_mut(wrapped: &mut Wrapped, _tag: Tag) -> &mut AstNodeWrapper<Wrapped, Tag> {
+        // SAFETY: `AstNodeWrapper` is `repr(transparent)` w.r.t `Wrapped`
+        unsafe { &mut *<*mut Wrapped>::cast(wrapped) }
+    }
 }
 
 impl<Wrapped: HasNodeId, Tag> HasNodeId for AstNodeWrapper<Wrapped, Tag> {
diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs
index a90349f318c..08726ee6b41 100644
--- a/compiler/rustc_ast/src/mut_visit.rs
+++ b/compiler/rustc_ast/src/mut_visit.rs
@@ -12,7 +12,6 @@ use std::panic;
 
 use rustc_data_structures::flat_map_in_place::FlatMapInPlace;
 use rustc_data_structures::stack::ensure_sufficient_stack;
-use rustc_span::source_map::Spanned;
 use rustc_span::{Ident, Span};
 use smallvec::{Array, SmallVec, smallvec};
 use thin_vec::ThinVec;
@@ -20,7 +19,7 @@ use thin_vec::ThinVec;
 use crate::ast::*;
 use crate::ptr::P;
 use crate::tokenstream::*;
-use crate::visit::{AssocCtxt, BoundKind, FnCtxt, try_visit};
+use crate::visit::{AssocCtxt, BoundKind, FnCtxt, try_visit, visit_opt, walk_list};
 
 pub trait ExpectOne<A: Array> {
     fn expect_one(self, err: &'static str) -> A::Item;
@@ -33,18 +32,6 @@ impl<A: Array> ExpectOne<A> for SmallVec<A> {
     }
 }
 
-pub trait WalkItemKind {
-    type Ctxt;
-    fn walk(
-        &mut self,
-        span: Span,
-        id: NodeId,
-        visibility: &mut Visibility,
-        ctxt: Self::Ctxt,
-        visitor: &mut impl MutVisitor,
-    );
-}
-
 pub trait MutVisitor: Sized {
     // Methods in this trait have one of three forms:
     //
@@ -52,12 +39,6 @@ pub trait MutVisitor: Sized {
     //   fn flat_map_t(&mut self, t: T) -> SmallVec<[T; 1]>;    // rare
     //   fn filter_map_t(&mut self, t: T) -> Option<T>;         // rarest
     //
-    // Any additions to this trait should happen in form of a call to a public
-    // `noop_*` function that only calls out to the visitor again, not other
-    // `noop_*` functions. This is a necessary API workaround to the problem of
-    // not being able to call out to the super default method in an overridden
-    // default method.
-    //
     // When writing these methods, it is better to use destructuring like this:
     //
     //   fn visit_abc(&mut self, ABC { a, b, c: _ }: &mut ABC) {
@@ -95,7 +76,7 @@ pub trait MutVisitor: Sized {
         walk_use_tree(self, use_tree);
     }
 
-    fn visit_foreign_item(&mut self, ni: &mut P<ForeignItem>) {
+    fn visit_foreign_item(&mut self, ni: &mut ForeignItem) {
         walk_item(self, ni);
     }
 
@@ -103,7 +84,7 @@ pub trait MutVisitor: Sized {
         walk_flat_map_foreign_item(self, ni)
     }
 
-    fn visit_item(&mut self, i: &mut P<Item>) {
+    fn visit_item(&mut self, i: &mut Item) {
         walk_item(self, i);
     }
 
@@ -123,7 +104,7 @@ pub trait MutVisitor: Sized {
         walk_flat_map_field_def(self, fd)
     }
 
-    fn visit_assoc_item(&mut self, i: &mut P<AssocItem>, ctxt: AssocCtxt) {
+    fn visit_assoc_item(&mut self, i: &mut AssocItem, ctxt: AssocCtxt) {
         walk_assoc_item(self, i, ctxt)
     }
 
@@ -135,11 +116,11 @@ pub trait MutVisitor: Sized {
         walk_flat_map_assoc_item(self, i, ctxt)
     }
 
-    fn visit_contract(&mut self, c: &mut P<FnContract>) {
+    fn visit_contract(&mut self, c: &mut FnContract) {
         walk_contract(self, c);
     }
 
-    fn visit_fn_decl(&mut self, d: &mut P<FnDecl>) {
+    fn visit_fn_decl(&mut self, d: &mut FnDecl) {
         walk_fn_decl(self, d);
     }
 
@@ -156,7 +137,7 @@ pub trait MutVisitor: Sized {
         walk_closure_binder(self, b);
     }
 
-    fn visit_block(&mut self, b: &mut P<Block>) {
+    fn visit_block(&mut self, b: &mut Block) {
         walk_block(self, b);
     }
 
@@ -191,7 +172,7 @@ pub trait MutVisitor: Sized {
     }
 
     fn filter_map_expr(&mut self, e: P<Expr>) -> Option<P<Expr>> {
-        noop_filter_map_expr(self, e)
+        walk_filter_map_expr(self, e)
     }
 
     fn visit_generic_arg(&mut self, arg: &mut GenericArg) {
@@ -202,7 +183,7 @@ pub trait MutVisitor: Sized {
         walk_ty(self, t);
     }
 
-    fn visit_ty_pat(&mut self, t: &mut P<TyPat>) {
+    fn visit_ty_pat(&mut self, t: &mut TyPat) {
         walk_ty_pat(self, t);
     }
 
@@ -258,7 +239,7 @@ pub trait MutVisitor: Sized {
         walk_parenthesized_parameter_data(self, p);
     }
 
-    fn visit_local(&mut self, l: &mut P<Local>) {
+    fn visit_local(&mut self, l: &mut Local) {
         walk_local(self, l);
     }
 
@@ -318,10 +299,6 @@ pub trait MutVisitor: Sized {
         walk_precise_capturing_arg(self, arg);
     }
 
-    fn visit_mt(&mut self, mt: &mut MutTy) {
-        walk_mt(self, mt);
-    }
-
     fn visit_expr_field(&mut self, f: &mut ExprField) {
         walk_expr_field(self, f);
     }
@@ -390,17 +367,6 @@ pub trait MutVisitor: Sized {
 
 super::common_visitor_and_walkers!((mut) MutVisitor);
 
-/// Use a map-style function (`FnOnce(T) -> T`) to overwrite a `&mut T`. Useful
-/// when using a `flat_map_*` or `filter_map_*` method within a `visit_`
-/// method.
-//
-// No `noop_` prefix because there isn't a corresponding method in `MutVisitor`.
-pub fn visit_clobber<T: DummyAstNode>(t: &mut T, f: impl FnOnce(T) -> T) {
-    let old_t = std::mem::replace(t, T::dummy());
-    *t = f(old_t);
-}
-
-// No `noop_` prefix because there isn't a corresponding method in `MutVisitor`.
 #[inline]
 fn visit_vec<T, F>(elems: &mut Vec<T>, mut visit_elem: F)
 where
@@ -411,7 +377,6 @@ where
     }
 }
 
-// No `noop_` prefix because there isn't a corresponding method in `MutVisitor`.
 #[inline]
 fn visit_thin_vec<T, F>(elems: &mut ThinVec<T>, mut visit_elem: F)
 where
@@ -422,7 +387,6 @@ where
     }
 }
 
-// No `noop_` prefix because there isn't a corresponding method in `MutVisitor`.
 #[inline]
 fn visit_opt<T, F>(opt: &mut Option<T>, mut visit_elem: F)
 where
@@ -433,30 +397,21 @@ where
     }
 }
 
-// No `noop_` prefix because there isn't a corresponding method in `MutVisitor`.
 fn visit_attrs<T: MutVisitor>(vis: &mut T, attrs: &mut AttrVec) {
     for attr in attrs.iter_mut() {
         vis.visit_attribute(attr);
     }
 }
 
-// No `noop_` prefix because there isn't a corresponding method in `MutVisitor`.
 #[allow(unused)]
 fn visit_exprs<T: MutVisitor>(vis: &mut T, exprs: &mut Vec<P<Expr>>) {
     exprs.flat_map_in_place(|expr| vis.filter_map_expr(expr))
 }
 
-// No `noop_` prefix because there isn't a corresponding method in `MutVisitor`.
 fn visit_thin_exprs<T: MutVisitor>(vis: &mut T, exprs: &mut ThinVec<P<Expr>>) {
     exprs.flat_map_in_place(|expr| vis.filter_map_expr(expr))
 }
 
-// No `noop_` prefix because there isn't a corresponding method in `MutVisitor`.
-fn visit_bounds<T: MutVisitor>(vis: &mut T, bounds: &mut GenericBounds, ctxt: BoundKind) {
-    visit_vec(bounds, |bound| vis.visit_param_bound(bound, ctxt));
-}
-
-// No `noop_` prefix because there isn't a corresponding method in `MutVisitor`.
 fn visit_attr_args<T: MutVisitor>(vis: &mut T, args: &mut AttrArgs) {
     match args {
         AttrArgs::Empty => {}
@@ -468,7 +423,6 @@ fn visit_attr_args<T: MutVisitor>(vis: &mut T, args: &mut AttrArgs) {
     }
 }
 
-// No `noop_` prefix because there isn't a corresponding method in `MutVisitor`.
 fn visit_delim_args<T: MutVisitor>(vis: &mut T, args: &mut DelimArgs) {
     let DelimArgs { dspan, delim: _, tokens: _ } = args;
     let DelimSpan { open, close } = dspan;
@@ -544,60 +498,8 @@ fn walk_assoc_item_constraint<T: MutVisitor>(
     vis.visit_span(span);
 }
 
-pub fn walk_ty<T: MutVisitor>(vis: &mut T, ty: &mut P<Ty>) {
-    let Ty { id, kind, span, tokens: _ } = ty.deref_mut();
-    vis.visit_id(id);
-    match kind {
-        TyKind::Err(_guar) => {}
-        TyKind::Infer | TyKind::ImplicitSelf | TyKind::Dummy | TyKind::Never | TyKind::CVarArgs => {
-        }
-        TyKind::Slice(ty) => vis.visit_ty(ty),
-        TyKind::Ptr(mt) => vis.visit_mt(mt),
-        TyKind::Ref(lt, mt) | TyKind::PinnedRef(lt, mt) => {
-            visit_opt(lt, |lt| vis.visit_lifetime(lt));
-            vis.visit_mt(mt);
-        }
-        TyKind::BareFn(bft) => {
-            let BareFnTy { safety, ext: _, generic_params, decl, decl_span } = bft.deref_mut();
-            visit_safety(vis, safety);
-            generic_params.flat_map_in_place(|param| vis.flat_map_generic_param(param));
-            vis.visit_fn_decl(decl);
-            vis.visit_span(decl_span);
-        }
-        TyKind::UnsafeBinder(binder) => {
-            let UnsafeBinderTy { generic_params, inner_ty } = binder.deref_mut();
-            generic_params.flat_map_in_place(|param| vis.flat_map_generic_param(param));
-            vis.visit_ty(inner_ty);
-        }
-        TyKind::Tup(tys) => visit_thin_vec(tys, |ty| vis.visit_ty(ty)),
-        TyKind::Paren(ty) => vis.visit_ty(ty),
-        TyKind::Pat(ty, pat) => {
-            vis.visit_ty(ty);
-            vis.visit_ty_pat(pat);
-        }
-        TyKind::Path(qself, path) => {
-            vis.visit_qself(qself);
-            vis.visit_path(path);
-        }
-        TyKind::Array(ty, length) => {
-            vis.visit_ty(ty);
-            vis.visit_anon_const(length);
-        }
-        TyKind::Typeof(expr) => vis.visit_anon_const(expr),
-        TyKind::TraitObject(bounds, _syntax) => {
-            visit_vec(bounds, |bound| vis.visit_param_bound(bound, BoundKind::TraitObject))
-        }
-        TyKind::ImplTrait(id, bounds) => {
-            vis.visit_id(id);
-            visit_vec(bounds, |bound| vis.visit_param_bound(bound, BoundKind::Impl));
-        }
-        TyKind::MacCall(mac) => vis.visit_mac_call(mac),
-    }
-    vis.visit_span(span);
-}
-
-pub fn walk_ty_pat<T: MutVisitor>(vis: &mut T, ty: &mut P<TyPat>) {
-    let TyPat { id, kind, span, tokens: _ } = ty.deref_mut();
+pub fn walk_ty_pat<T: MutVisitor>(vis: &mut T, ty: &mut TyPat) {
+    let TyPat { id, kind, span, tokens: _ } = ty;
     vis.visit_id(id);
     match kind {
         TyPatKind::Range(start, end, _include_end) => {
@@ -610,12 +512,6 @@ pub fn walk_ty_pat<T: MutVisitor>(vis: &mut T, ty: &mut P<TyPat>) {
     vis.visit_span(span);
 }
 
-fn walk_foreign_mod<T: MutVisitor>(vis: &mut T, foreign_mod: &mut ForeignMod) {
-    let ForeignMod { extern_span: _, safety, abi: _, items } = foreign_mod;
-    visit_safety(vis, safety);
-    items.flat_map_in_place(|item| vis.flat_map_foreign_item(item));
-}
-
 pub fn walk_variant<T: MutVisitor>(visitor: &mut T, variant: &mut Variant) {
     let Variant { ident, vis, attrs, id, data, disr_expr, span, is_placeholder: _ } = variant;
     visitor.visit_id(id);
@@ -639,13 +535,6 @@ fn walk_ident<T: MutVisitor>(vis: &mut T, Ident { name: _, span }: &mut Ident) {
     vis.visit_span(span);
 }
 
-fn walk_path_segment<T: MutVisitor>(vis: &mut T, segment: &mut PathSegment) {
-    let PathSegment { ident, id, args } = segment;
-    vis.visit_id(id);
-    vis.visit_ident(ident);
-    visit_opt(args, |args| vis.visit_generic_args(args));
-}
-
 fn walk_path<T: MutVisitor>(vis: &mut T, Path { segments, span, tokens: _ }: &mut Path) {
     for segment in segments {
         vis.visit_path_segment(segment);
@@ -694,8 +583,8 @@ fn walk_parenthesized_parameter_data<T: MutVisitor>(vis: &mut T, args: &mut Pare
     vis.visit_span(inputs_span);
 }
 
-fn walk_local<T: MutVisitor>(vis: &mut T, local: &mut P<Local>) {
-    let Local { id, super_, pat, ty, kind, span, colon_sp, attrs, tokens: _ } = local.deref_mut();
+fn walk_local<T: MutVisitor>(vis: &mut T, local: &mut Local) {
+    let Local { id, super_, pat, ty, kind, span, colon_sp, attrs, tokens: _ } = local;
     visit_opt(super_, |sp| vis.visit_span(sp));
     vis.visit_id(id);
     visit_attrs(vis, attrs);
@@ -771,22 +660,6 @@ pub fn walk_flat_map_param<T: MutVisitor>(vis: &mut T, mut param: Param) -> Smal
     smallvec![param]
 }
 
-// No `noop_` prefix because there isn't a corresponding method in `MutVisitor`.
-fn visit_defaultness<T: MutVisitor>(vis: &mut T, defaultness: &mut Defaultness) {
-    match defaultness {
-        Defaultness::Default(span) => vis.visit_span(span),
-        Defaultness::Final => {}
-    }
-}
-
-// No `noop_` prefix because there isn't a corresponding method in `MutVisitor`.
-fn visit_polarity<T: MutVisitor>(vis: &mut T, polarity: &mut ImplPolarity) {
-    match polarity {
-        ImplPolarity::Positive => {}
-        ImplPolarity::Negative(span) => vis.visit_span(span),
-    }
-}
-
 fn walk_closure_binder<T: MutVisitor>(vis: &mut T, binder: &mut ClosureBinder) {
     match binder {
         ClosureBinder::NotPresent => {}
@@ -796,18 +669,6 @@ fn walk_closure_binder<T: MutVisitor>(vis: &mut T, binder: &mut ClosureBinder) {
     }
 }
 
-fn walk_coroutine_kind<T: MutVisitor>(vis: &mut T, coroutine_kind: &mut CoroutineKind) {
-    match coroutine_kind {
-        CoroutineKind::Async { span, closure_id, return_impl_trait_id }
-        | CoroutineKind::Gen { span, closure_id, return_impl_trait_id }
-        | CoroutineKind::AsyncGen { span, closure_id, return_impl_trait_id } => {
-            vis.visit_id(closure_id);
-            vis.visit_id(return_impl_trait_id);
-            vis.visit_span(span);
-        }
-    }
-}
-
 fn walk_fn<T: MutVisitor>(vis: &mut T, kind: FnKind<'_>) {
     match kind {
         FnKind::Fn(
@@ -848,8 +709,8 @@ fn walk_fn<T: MutVisitor>(vis: &mut T, kind: FnKind<'_>) {
     }
 }
 
-fn walk_contract<T: MutVisitor>(vis: &mut T, contract: &mut P<FnContract>) {
-    let FnContract { requires, ensures } = contract.deref_mut();
+fn walk_contract<T: MutVisitor>(vis: &mut T, contract: &mut FnContract) {
+    let FnContract { requires, ensures } = contract;
     if let Some(pred) = requires {
         vis.visit_expr(pred);
     }
@@ -858,8 +719,8 @@ fn walk_contract<T: MutVisitor>(vis: &mut T, contract: &mut P<FnContract>) {
     }
 }
 
-fn walk_fn_decl<T: MutVisitor>(vis: &mut T, decl: &mut P<FnDecl>) {
-    let FnDecl { inputs, output } = decl.deref_mut();
+fn walk_fn_decl<T: MutVisitor>(vis: &mut T, decl: &mut FnDecl) {
+    let FnDecl { inputs, output } = decl;
     inputs.flat_map_in_place(|param| vis.flat_map_param(param));
     vis.visit_fn_ret_ty(output);
 }
@@ -1058,17 +919,6 @@ pub fn walk_flat_map_expr_field<T: MutVisitor>(
     smallvec![f]
 }
 
-fn walk_mt<T: MutVisitor>(vis: &mut T, MutTy { ty, mutbl: _ }: &mut MutTy) {
-    vis.visit_ty(ty);
-}
-
-pub fn walk_block<T: MutVisitor>(vis: &mut T, block: &mut P<Block>) {
-    let Block { id, stmts, rules: _, span, tokens: _ } = block.deref_mut();
-    vis.visit_id(id);
-    stmts.flat_map_in_place(|stmt| vis.flat_map_stmt(stmt));
-    vis.visit_span(span);
-}
-
 pub fn walk_item_kind<K: WalkItemKind>(
     kind: &mut K,
     span: Span,
@@ -1080,242 +930,6 @@ pub fn walk_item_kind<K: WalkItemKind>(
     kind.walk(span, id, visibility, ctxt, vis)
 }
 
-impl WalkItemKind for ItemKind {
-    type Ctxt = ();
-    fn walk(
-        &mut self,
-        span: Span,
-        id: NodeId,
-        visibility: &mut Visibility,
-        _ctxt: Self::Ctxt,
-        vis: &mut impl MutVisitor,
-    ) {
-        match self {
-            ItemKind::ExternCrate(_orig_name, ident) => vis.visit_ident(ident),
-            ItemKind::Use(use_tree) => vis.visit_use_tree(use_tree),
-            ItemKind::Static(box StaticItem {
-                ident,
-                ty,
-                safety: _,
-                mutability: _,
-                expr,
-                define_opaque,
-            }) => {
-                vis.visit_ident(ident);
-                vis.visit_ty(ty);
-                visit_opt(expr, |expr| vis.visit_expr(expr));
-                walk_define_opaques(vis, define_opaque);
-            }
-            ItemKind::Const(item) => {
-                walk_const_item(vis, item);
-            }
-            ItemKind::Fn(func) => {
-                vis.visit_fn(FnKind::Fn(FnCtxt::Free, visibility, &mut *func), span, id);
-            }
-            ItemKind::Mod(safety, ident, mod_kind) => {
-                visit_safety(vis, safety);
-                vis.visit_ident(ident);
-                match mod_kind {
-                    ModKind::Loaded(
-                        items,
-                        _inline,
-                        ModSpans { inner_span, inject_use_span },
-                        _,
-                    ) => {
-                        items.flat_map_in_place(|item| vis.flat_map_item(item));
-                        vis.visit_span(inner_span);
-                        vis.visit_span(inject_use_span);
-                    }
-                    ModKind::Unloaded => {}
-                }
-            }
-            ItemKind::ForeignMod(nm) => vis.visit_foreign_mod(nm),
-            ItemKind::GlobalAsm(asm) => vis.visit_inline_asm(asm),
-            ItemKind::TyAlias(box TyAlias {
-                defaultness,
-                ident,
-                generics,
-                where_clauses,
-                bounds,
-                ty,
-            }) => {
-                visit_defaultness(vis, defaultness);
-                vis.visit_ident(ident);
-                vis.visit_generics(generics);
-                visit_bounds(vis, bounds, BoundKind::Bound);
-                visit_opt(ty, |ty| vis.visit_ty(ty));
-                walk_ty_alias_where_clauses(vis, where_clauses);
-            }
-            ItemKind::Enum(ident, EnumDef { variants }, generics) => {
-                vis.visit_ident(ident);
-                vis.visit_generics(generics);
-                variants.flat_map_in_place(|variant| vis.flat_map_variant(variant));
-            }
-            ItemKind::Struct(ident, variant_data, generics)
-            | ItemKind::Union(ident, variant_data, generics) => {
-                vis.visit_ident(ident);
-                vis.visit_generics(generics);
-                vis.visit_variant_data(variant_data);
-            }
-            ItemKind::Impl(box Impl {
-                defaultness,
-                safety,
-                generics,
-                constness,
-                polarity,
-                of_trait,
-                self_ty,
-                items,
-            }) => {
-                visit_defaultness(vis, defaultness);
-                visit_safety(vis, safety);
-                vis.visit_generics(generics);
-                visit_constness(vis, constness);
-                visit_polarity(vis, polarity);
-                visit_opt(of_trait, |trait_ref| vis.visit_trait_ref(trait_ref));
-                vis.visit_ty(self_ty);
-                items.flat_map_in_place(|item| {
-                    vis.flat_map_assoc_item(item, AssocCtxt::Impl { of_trait: of_trait.is_some() })
-                });
-            }
-            ItemKind::Trait(box Trait { safety, is_auto: _, ident, generics, bounds, items }) => {
-                visit_safety(vis, safety);
-                vis.visit_ident(ident);
-                vis.visit_generics(generics);
-                visit_bounds(vis, bounds, BoundKind::Bound);
-                items.flat_map_in_place(|item| vis.flat_map_assoc_item(item, AssocCtxt::Trait));
-            }
-            ItemKind::TraitAlias(ident, generics, bounds) => {
-                vis.visit_ident(ident);
-                vis.visit_generics(generics);
-                visit_bounds(vis, bounds, BoundKind::Bound);
-            }
-            ItemKind::MacCall(m) => vis.visit_mac_call(m),
-            ItemKind::MacroDef(ident, def) => {
-                vis.visit_ident(ident);
-                vis.visit_macro_def(def)
-            }
-            ItemKind::Delegation(box Delegation {
-                id,
-                qself,
-                path,
-                ident,
-                rename,
-                body,
-                from_glob: _,
-            }) => {
-                vis.visit_id(id);
-                vis.visit_qself(qself);
-                vis.visit_path(path);
-                vis.visit_ident(ident);
-                if let Some(rename) = rename {
-                    vis.visit_ident(rename);
-                }
-                if let Some(body) = body {
-                    vis.visit_block(body);
-                }
-            }
-            ItemKind::DelegationMac(box DelegationMac { qself, prefix, suffixes, body }) => {
-                vis.visit_qself(qself);
-                vis.visit_path(prefix);
-                if let Some(suffixes) = suffixes {
-                    for (ident, rename) in suffixes {
-                        vis.visit_ident(ident);
-                        if let Some(rename) = rename {
-                            vis.visit_ident(rename);
-                        }
-                    }
-                }
-                if let Some(body) = body {
-                    vis.visit_block(body);
-                }
-            }
-        }
-    }
-}
-
-impl WalkItemKind for AssocItemKind {
-    type Ctxt = AssocCtxt;
-    fn walk(
-        &mut self,
-        span: Span,
-        id: NodeId,
-        visibility: &mut Visibility,
-        ctxt: Self::Ctxt,
-        visitor: &mut impl MutVisitor,
-    ) {
-        match self {
-            AssocItemKind::Const(item) => {
-                walk_const_item(visitor, item);
-            }
-            AssocItemKind::Fn(func) => {
-                visitor.visit_fn(FnKind::Fn(FnCtxt::Assoc(ctxt), visibility, &mut *func), span, id);
-            }
-            AssocItemKind::Type(box TyAlias {
-                defaultness,
-                ident,
-                generics,
-                where_clauses,
-                bounds,
-                ty,
-            }) => {
-                visit_defaultness(visitor, defaultness);
-                visitor.visit_ident(ident);
-                visitor.visit_generics(generics);
-                visit_bounds(visitor, bounds, BoundKind::Bound);
-                visit_opt(ty, |ty| visitor.visit_ty(ty));
-                walk_ty_alias_where_clauses(visitor, where_clauses);
-            }
-            AssocItemKind::MacCall(mac) => visitor.visit_mac_call(mac),
-            AssocItemKind::Delegation(box Delegation {
-                id,
-                qself,
-                path,
-                ident,
-                rename,
-                body,
-                from_glob: _,
-            }) => {
-                visitor.visit_id(id);
-                visitor.visit_qself(qself);
-                visitor.visit_path(path);
-                visitor.visit_ident(ident);
-                if let Some(rename) = rename {
-                    visitor.visit_ident(rename);
-                }
-                if let Some(body) = body {
-                    visitor.visit_block(body);
-                }
-            }
-            AssocItemKind::DelegationMac(box DelegationMac { qself, prefix, suffixes, body }) => {
-                visitor.visit_qself(qself);
-                visitor.visit_path(prefix);
-                if let Some(suffixes) = suffixes {
-                    for (ident, rename) in suffixes {
-                        visitor.visit_ident(ident);
-                        if let Some(rename) = rename {
-                            visitor.visit_ident(rename);
-                        }
-                    }
-                }
-                if let Some(body) = body {
-                    visitor.visit_block(body);
-                }
-            }
-        }
-    }
-}
-
-fn walk_const_item<T: MutVisitor>(vis: &mut T, item: &mut ConstItem) {
-    let ConstItem { defaultness, ident, generics, ty, expr, define_opaque } = item;
-    visit_defaultness(vis, defaultness);
-    vis.visit_ident(ident);
-    vis.visit_generics(generics);
-    vis.visit_ty(ty);
-    visit_opt(expr, |expr| vis.visit_expr(expr));
-    walk_define_opaques(vis, define_opaque);
-}
-
 pub fn walk_crate<T: MutVisitor>(vis: &mut T, krate: &mut Crate) {
     let Crate { attrs, items, spans, id, is_placeholder: _ } = krate;
     vis.visit_id(id);
@@ -1326,27 +940,6 @@ pub fn walk_crate<T: MutVisitor>(vis: &mut T, krate: &mut Crate) {
     vis.visit_span(inject_use_span);
 }
 
-pub fn walk_item(visitor: &mut impl MutVisitor, item: &mut P<Item<impl WalkItemKind<Ctxt = ()>>>) {
-    walk_item_ctxt(visitor, item, ())
-}
-
-pub fn walk_assoc_item(visitor: &mut impl MutVisitor, item: &mut P<AssocItem>, ctxt: AssocCtxt) {
-    walk_item_ctxt(visitor, item, ctxt)
-}
-
-fn walk_item_ctxt<K: WalkItemKind>(
-    visitor: &mut impl MutVisitor,
-    item: &mut P<Item<K>>,
-    ctxt: K::Ctxt,
-) {
-    let Item { attrs, id, kind, vis, span, tokens: _ } = item.deref_mut();
-    visitor.visit_id(id);
-    visit_attrs(visitor, attrs);
-    visitor.visit_vis(vis);
-    kind.walk(*span, *id, vis, ctxt, visitor);
-    visitor.visit_span(span);
-}
-
 pub fn walk_flat_map_item(vis: &mut impl MutVisitor, mut item: P<Item>) -> SmallVec<[P<Item>; 1]> {
     vis.visit_item(&mut item);
     smallvec![item]
@@ -1369,104 +962,6 @@ pub fn walk_flat_map_assoc_item(
     smallvec![item]
 }
 
-impl WalkItemKind for ForeignItemKind {
-    type Ctxt = ();
-    fn walk(
-        &mut self,
-        span: Span,
-        id: NodeId,
-        visibility: &mut Visibility,
-        _ctxt: Self::Ctxt,
-        visitor: &mut impl MutVisitor,
-    ) {
-        match self {
-            ForeignItemKind::Static(box StaticItem {
-                ident,
-                ty,
-                mutability: _,
-                expr,
-                safety: _,
-                define_opaque,
-            }) => {
-                visitor.visit_ident(ident);
-                visitor.visit_ty(ty);
-                visit_opt(expr, |expr| visitor.visit_expr(expr));
-                walk_define_opaques(visitor, define_opaque);
-            }
-            ForeignItemKind::Fn(func) => {
-                visitor.visit_fn(FnKind::Fn(FnCtxt::Foreign, visibility, &mut *func), span, id);
-            }
-            ForeignItemKind::TyAlias(box TyAlias {
-                defaultness,
-                ident,
-                generics,
-                where_clauses,
-                bounds,
-                ty,
-            }) => {
-                visit_defaultness(visitor, defaultness);
-                visitor.visit_ident(ident);
-                visitor.visit_generics(generics);
-                visit_bounds(visitor, bounds, BoundKind::Bound);
-                visit_opt(ty, |ty| visitor.visit_ty(ty));
-                walk_ty_alias_where_clauses(visitor, where_clauses);
-            }
-            ForeignItemKind::MacCall(mac) => visitor.visit_mac_call(mac),
-        }
-    }
-}
-
-pub fn walk_pat<T: MutVisitor>(vis: &mut T, pat: &mut P<Pat>) {
-    let Pat { id, kind, span, tokens: _ } = pat.deref_mut();
-    vis.visit_id(id);
-    match kind {
-        PatKind::Err(_guar) => {}
-        PatKind::Missing | PatKind::Wild | PatKind::Rest | PatKind::Never => {}
-        PatKind::Ident(_binding_mode, ident, sub) => {
-            vis.visit_ident(ident);
-            visit_opt(sub, |sub| vis.visit_pat(sub));
-        }
-        PatKind::Expr(e) => vis.visit_expr(e),
-        PatKind::TupleStruct(qself, path, elems) => {
-            vis.visit_qself(qself);
-            vis.visit_path(path);
-            visit_thin_vec(elems, |elem| vis.visit_pat(elem));
-        }
-        PatKind::Path(qself, path) => {
-            vis.visit_qself(qself);
-            vis.visit_path(path);
-        }
-        PatKind::Struct(qself, path, fields, _etc) => {
-            vis.visit_qself(qself);
-            vis.visit_path(path);
-            fields.flat_map_in_place(|field| vis.flat_map_pat_field(field));
-        }
-        PatKind::Box(inner) => vis.visit_pat(inner),
-        PatKind::Deref(inner) => vis.visit_pat(inner),
-        PatKind::Ref(inner, _mutbl) => vis.visit_pat(inner),
-        PatKind::Range(e1, e2, Spanned { span: _, node: _ }) => {
-            visit_opt(e1, |e| vis.visit_expr(e));
-            visit_opt(e2, |e| vis.visit_expr(e));
-            vis.visit_span(span);
-        }
-        PatKind::Guard(p, e) => {
-            vis.visit_pat(p);
-            vis.visit_expr(e);
-        }
-        PatKind::Tuple(elems) | PatKind::Slice(elems) | PatKind::Or(elems) => {
-            visit_thin_vec(elems, |elem| vis.visit_pat(elem))
-        }
-        PatKind::Paren(inner) => vis.visit_pat(inner),
-        PatKind::MacCall(mac) => vis.visit_mac_call(mac),
-    }
-    vis.visit_span(span);
-}
-
-fn walk_anon_const<T: MutVisitor>(vis: &mut T, AnonConst { id, value }: &mut AnonConst) {
-    vis.visit_id(id);
-    vis.visit_expr(value);
-}
-
 fn walk_inline_asm<T: MutVisitor>(vis: &mut T, asm: &mut InlineAsm) {
     // FIXME: Visit spans inside all this currently ignored stuff.
     let InlineAsm {
@@ -1716,11 +1211,9 @@ pub fn walk_expr<T: MutVisitor>(vis: &mut T, Expr { kind, id, span, attrs, token
     vis.visit_span(span);
 }
 
-pub fn noop_filter_map_expr<T: MutVisitor>(vis: &mut T, mut e: P<Expr>) -> Option<P<Expr>> {
-    Some({
-        vis.visit_expr(&mut e);
-        e
-    })
+pub fn walk_filter_map_expr<T: MutVisitor>(vis: &mut T, mut e: P<Expr>) -> Option<P<Expr>> {
+    vis.visit_expr(&mut e);
+    Some(e)
 }
 
 pub fn walk_flat_map_stmt<T: MutVisitor>(
@@ -1786,113 +1279,6 @@ fn walk_capture_by<T: MutVisitor>(vis: &mut T, capture_by: &mut CaptureBy) {
     }
 }
 
-fn walk_define_opaques<T: MutVisitor>(
-    vis: &mut T,
-    define_opaque: &mut Option<ThinVec<(NodeId, Path)>>,
-) {
-    if let Some(define_opaque) = define_opaque {
-        for (id, path) in define_opaque {
-            vis.visit_id(id);
-            vis.visit_path(path)
-        }
-    }
-}
-
-/// Some value for the AST node that is valid but possibly meaningless. Similar
-/// to `Default` but not intended for wide use. The value will never be used
-/// meaningfully, it exists just to support unwinding in `visit_clobber` in the
-/// case where its closure panics.
-pub trait DummyAstNode {
-    fn dummy() -> Self;
-}
-
-impl<T> DummyAstNode for Option<T> {
-    fn dummy() -> Self {
-        Default::default()
-    }
-}
-
-impl<T: DummyAstNode + 'static> DummyAstNode for P<T> {
-    fn dummy() -> Self {
-        P(DummyAstNode::dummy())
-    }
-}
-
-impl DummyAstNode for Item {
-    fn dummy() -> Self {
-        Item {
-            attrs: Default::default(),
-            id: DUMMY_NODE_ID,
-            span: Default::default(),
-            vis: Visibility {
-                kind: VisibilityKind::Public,
-                span: Default::default(),
-                tokens: Default::default(),
-            },
-            kind: ItemKind::ExternCrate(None, Ident::dummy()),
-            tokens: Default::default(),
-        }
-    }
-}
-
-impl DummyAstNode for Expr {
-    fn dummy() -> Self {
-        Expr {
-            id: DUMMY_NODE_ID,
-            kind: ExprKind::Dummy,
-            span: Default::default(),
-            attrs: Default::default(),
-            tokens: Default::default(),
-        }
-    }
-}
-
-impl DummyAstNode for Ty {
-    fn dummy() -> Self {
-        Ty {
-            id: DUMMY_NODE_ID,
-            kind: TyKind::Dummy,
-            span: Default::default(),
-            tokens: Default::default(),
-        }
-    }
-}
-
-impl DummyAstNode for Pat {
-    fn dummy() -> Self {
-        Pat {
-            id: DUMMY_NODE_ID,
-            kind: PatKind::Wild,
-            span: Default::default(),
-            tokens: Default::default(),
-        }
-    }
-}
-
-impl DummyAstNode for Stmt {
-    fn dummy() -> Self {
-        Stmt { id: DUMMY_NODE_ID, kind: StmtKind::Empty, span: Default::default() }
-    }
-}
-
-impl DummyAstNode for Crate {
-    fn dummy() -> Self {
-        Crate {
-            attrs: Default::default(),
-            items: Default::default(),
-            spans: Default::default(),
-            id: DUMMY_NODE_ID,
-            is_placeholder: Default::default(),
-        }
-    }
-}
-
-impl<N: DummyAstNode, T: DummyAstNode> DummyAstNode for crate::ast_traits::AstNodeWrapper<N, T> {
-    fn dummy() -> Self {
-        crate::ast_traits::AstNodeWrapper::new(N::dummy(), T::dummy())
-    }
-}
-
 #[derive(Debug)]
 pub enum FnKind<'a> {
     /// E.g., `fn foo()`, `fn foo(&self)`, or `extern "Abi" fn foo()`.
diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs
index e43d7ae065d..908d9fd4bda 100644
--- a/compiler/rustc_ast/src/visit.rs
+++ b/compiler/rustc_ast/src/visit.rs
@@ -112,18 +112,6 @@ pub enum LifetimeCtxt {
     GenericArg,
 }
 
-pub trait WalkItemKind {
-    type Ctxt;
-    fn walk<'a, V: Visitor<'a>>(
-        &'a self,
-        span: Span,
-        id: NodeId,
-        visibility: &'a Visibility,
-        ctxt: Self::Ctxt,
-        visitor: &mut V,
-    ) -> V::Result;
-}
-
 /// Each method of the `Visitor` trait is a hook to be potentially
 /// overridden. Each method's default implementation recursively visits
 /// the substructure of the input via the corresponding `walk` method;
@@ -141,6 +129,9 @@ pub trait Visitor<'ast>: Sized {
     fn visit_ident(&mut self, _ident: &'ast Ident) -> Self::Result {
         Self::Result::output()
     }
+    fn visit_foreign_mod(&mut self, nm: &'ast ForeignMod) -> Self::Result {
+        walk_foreign_mod(self, nm)
+    }
     fn visit_foreign_item(&mut self, i: &'ast ForeignItem) -> Self::Result {
         walk_item(self, i)
     }
@@ -219,7 +210,7 @@ pub trait Visitor<'ast>: Sized {
         walk_poly_trait_ref(self, t)
     }
     fn visit_variant_data(&mut self, s: &'ast VariantData) -> Self::Result {
-        walk_struct_def(self, s)
+        walk_variant_data(self, s)
     }
     fn visit_field_def(&mut self, s: &'ast FieldDef) -> Self::Result {
         walk_field_def(self, s)
@@ -242,10 +233,13 @@ pub trait Visitor<'ast>: Sized {
     fn visit_mac_call(&mut self, mac: &'ast MacCall) -> Self::Result {
         walk_mac(self, mac)
     }
-    fn visit_mac_def(&mut self, _mac: &'ast MacroDef, _id: NodeId) -> Self::Result {
+    fn visit_id(&mut self, _id: NodeId) -> Self::Result {
         Self::Result::output()
     }
-    fn visit_path(&mut self, path: &'ast Path, _id: NodeId) -> Self::Result {
+    fn visit_macro_def(&mut self, _mac: &'ast MacroDef) -> Self::Result {
+        Self::Result::output()
+    }
+    fn visit_path(&mut self, path: &'ast Path) -> Self::Result {
         walk_path(self, path)
     }
     fn visit_use_tree(
@@ -304,8 +298,8 @@ pub trait Visitor<'ast>: Sized {
     fn visit_capture_by(&mut self, _capture_by: &'ast CaptureBy) -> Self::Result {
         Self::Result::output()
     }
-    fn visit_coroutine_kind(&mut self, _coroutine_kind: &'ast CoroutineKind) -> Self::Result {
-        Self::Result::output()
+    fn visit_coroutine_kind(&mut self, coroutine_kind: &'ast CoroutineKind) -> Self::Result {
+        walk_coroutine_kind(self, coroutine_kind)
     }
     fn visit_fn_decl(&mut self, fn_decl: &'ast FnDecl) -> Self::Result {
         walk_fn_decl(self, fn_decl)
@@ -318,6 +312,18 @@ pub trait Visitor<'ast>: Sized {
 #[macro_export]
 macro_rules! common_visitor_and_walkers {
     ($(($mut: ident))? $Visitor:ident$(<$lt:lifetime>)?) => {
+        pub trait WalkItemKind {
+            type Ctxt;
+            fn walk<$($lt,)? V: $Visitor$(<$lt>)?>(
+                &$($lt)? $($mut)? self,
+                span: Span,
+                id: NodeId,
+                visibility: &$($lt)? $($mut)? Visibility,
+                ctxt: Self::Ctxt,
+                visitor: &mut V,
+            ) $(-> <V as Visitor<$lt>>::Result)?;
+        }
+
         // this is only used by the MutVisitor. We include this symmetry here to make writing other functions easier
         $(${ignore($lt)}
             #[expect(unused, rustc::pass_by_value)]
@@ -325,23 +331,20 @@ macro_rules! common_visitor_and_walkers {
         )?
         fn visit_span<$($lt,)? V: $Visitor$(<$lt>)?>(visitor: &mut V, span: &$($lt)? $($mut)? Span) $(-> <V as Visitor<$lt>>::Result)? {
             $(
-                let _ = stringify!($mut);
+                ${ignore($mut)}
                 visitor.visit_span(span);
             )?
             $(${ignore($lt)}V::Result::output())?
         }
 
-        // this is only used by the MutVisitor. We include this symmetry here to make writing other functions easier
+        /// helper since `Visitor` wants `NodeId` but `MutVisitor` wants `&mut NodeId`
         $(${ignore($lt)}
-            #[expect(unused, rustc::pass_by_value)]
-            #[inline]
+            #[expect(rustc::pass_by_value)]
         )?
+        #[inline]
         fn visit_id<$($lt,)? V: $Visitor$(<$lt>)?>(visitor: &mut V, id: &$($lt)? $($mut)? NodeId) $(-> <V as Visitor<$lt>>::Result)? {
-            $(
-                let _ = stringify!($mut);
-                visitor.visit_id(id);
-            )?
-            $(${ignore($lt)}V::Result::output())?
+            // deref `&NodeId` into `NodeId` only for `Visitor`
+            visitor.visit_id( $(${ignore($lt)} * )? id)
         }
 
         // this is only used by the MutVisitor. We include this symmetry here to make writing other functions easier
@@ -362,6 +365,27 @@ macro_rules! common_visitor_and_walkers {
             }
         }
 
+        fn visit_defaultness<$($lt,)? V: $Visitor$(<$lt>)?>(vis: &mut V, defaultness: &$($lt)? $($mut)? Defaultness) $(-> <V as Visitor<$lt>>::Result)? {
+            match defaultness {
+                Defaultness::Default(span) => visit_span(vis, span),
+                Defaultness::Final => {
+                    $(<V as Visitor<$lt>>::Result::output())?
+                }
+            }
+        }
+
+        fn visit_polarity<$($lt,)? V: $Visitor$(<$lt>)?>(vis: &mut V, polarity: &$($lt)? $($mut)? ImplPolarity) $(-> <V as Visitor<$lt>>::Result)? {
+            match polarity {
+                ImplPolarity::Positive => { $(<V as Visitor<$lt>>::Result::output())? }
+                ImplPolarity::Negative(span) => visit_span(vis, span),
+            }
+        }
+
+        fn visit_bounds<$($lt,)? V: $Visitor$(<$lt>)?>(visitor: &mut V, bounds: &$($lt)? $($mut)? GenericBounds, ctxt: BoundKind) $(-> <V as Visitor<$lt>>::Result)? {
+            walk_list!(visitor, visit_param_bound, bounds, ctxt);
+            $(<V as Visitor<$lt>>::Result::output())?
+        }
+
         pub fn walk_label<$($lt,)? V: $Visitor$(<$lt>)?>(visitor: &mut V, Label { ident }: &$($lt)? $($mut)? Label) $(-> <V as Visitor<$lt>>::Result)? {
             visitor.visit_ident(ident)
         }
@@ -369,9 +393,7 @@ macro_rules! common_visitor_and_walkers {
         pub fn walk_fn_header<$($lt,)? V: $Visitor$(<$lt>)?>(visitor: &mut V, header: &$($lt)? $($mut)? FnHeader) $(-> <V as Visitor<$lt>>::Result)? {
             let FnHeader { safety, coroutine_kind, constness, ext: _ } = header;
             try_visit!(visit_constness(visitor, constness));
-            if let Some(coroutine_kind) = coroutine_kind {
-                try_visit!(visitor.visit_coroutine_kind(coroutine_kind));
-            }
+            visit_opt!(visitor, visit_coroutine_kind, coroutine_kind);
             visit_safety(visitor, safety)
         }
 
@@ -379,6 +401,560 @@ macro_rules! common_visitor_and_walkers {
             try_visit!(visit_id(visitor, id));
             visitor.visit_ident(ident)
         }
+
+        fn walk_item_ctxt<$($lt,)? V: $Visitor$(<$lt>)?, K: WalkItemKind>(
+            visitor: &mut V,
+            item: &$($mut)? $($lt)? Item<K>,
+            ctxt: K::Ctxt,
+        ) $(-> <V as Visitor<$lt>>::Result)? {
+            let Item { attrs, id, kind, vis, span, tokens: _ } = item;
+            try_visit!(visit_id(visitor, id));
+            walk_list!(visitor, visit_attribute, attrs);
+            try_visit!(visitor.visit_vis(vis));
+            try_visit!(kind.walk(*span, *id, vis, ctxt, visitor));
+            visit_span(visitor, span)
+        }
+
+        pub fn walk_item<$($lt,)? V: $Visitor$(<$lt>)?, K: WalkItemKind<Ctxt = ()>>(
+            visitor: &mut V,
+            item: &$($mut)? $($lt)? Item<K>,
+        ) $(-> <V as Visitor<$lt>>::Result)? {
+            walk_item_ctxt(visitor, item, ())
+        }
+
+        pub fn walk_assoc_item<$($lt,)? V: $Visitor$(<$lt>)?>(
+            visitor: &mut V,
+            item: &$($mut)? $($lt)? AssocItem,
+            ctxt: AssocCtxt,
+        ) $(-> <V as Visitor<$lt>>::Result)? {
+            walk_item_ctxt(visitor, item, ctxt)
+        }
+
+        impl WalkItemKind for ItemKind {
+            type Ctxt = ();
+            fn walk<$($lt,)? V: $Visitor$(<$lt>)?>(
+                &$($lt)? $($mut)? self,
+                span: Span,
+                id: NodeId,
+                visibility: &$($lt)? $($mut)? Visibility,
+                _ctxt: Self::Ctxt,
+                vis: &mut V,
+            ) $(-> <V as Visitor<$lt>>::Result)? {
+                match self {
+                    ItemKind::ExternCrate(_orig_name, ident) => vis.visit_ident(ident),
+                    // FIXME(fee1-dead): look into this weird assymetry
+                    ItemKind::Use(use_tree) => vis.visit_use_tree(use_tree$(${ignore($lt)}, id, false)?),
+                    ItemKind::Static(box StaticItem {
+                        ident,
+                        ty,
+                        safety: _,
+                        mutability: _,
+                        expr,
+                        define_opaque,
+                    }) => {
+                        try_visit!(vis.visit_ident(ident));
+                        try_visit!(vis.visit_ty(ty));
+                        visit_opt!(vis, visit_expr, expr);
+                        walk_define_opaques(vis, define_opaque)
+                    }
+                    ItemKind::Const(item) => {
+                        walk_const_item(vis, item)
+                    }
+                    ItemKind::Fn(func) => {
+                        let kind = FnKind::Fn(FnCtxt::Free, visibility, &$($mut)? *func);
+                        vis.visit_fn(kind, span, id)
+                    }
+                    ItemKind::Mod(safety, ident, mod_kind) => {
+                        try_visit!(visit_safety(vis, safety));
+                        try_visit!(vis.visit_ident(ident));
+                        match mod_kind {
+                            ModKind::Loaded(
+                                items,
+                                _inline,
+                                ModSpans { inner_span, inject_use_span },
+                                _,
+                            ) => {
+                                $(${ignore($mut)}
+                                    items.flat_map_in_place(|item| vis.flat_map_item(item));
+                                )?
+                                $(${ignore($lt)}
+                                    walk_list!(vis, visit_item, items);
+                                )?
+                                try_visit!(visit_span(vis, inner_span));
+                                try_visit!(visit_span(vis, inject_use_span));
+                            }
+                            ModKind::Unloaded => {}
+                        }
+                        $(<V as Visitor<$lt>>::Result::output())?
+                    }
+                    ItemKind::ForeignMod(nm) => vis.visit_foreign_mod(nm),
+                    ItemKind::GlobalAsm(asm) => vis.visit_inline_asm(asm),
+                    ItemKind::TyAlias(box TyAlias {
+                        defaultness,
+                        ident,
+                        generics,
+                        $(${ignore($lt)} #[expect(unused)])?
+                        where_clauses,
+                        bounds,
+                        ty,
+                    }) => {
+                        try_visit!(visit_defaultness(vis, defaultness));
+                        try_visit!(vis.visit_ident(ident));
+                        try_visit!(vis.visit_generics(generics));
+                        try_visit!(visit_bounds(vis, bounds, BoundKind::Bound));
+                        visit_opt!(vis, visit_ty, ty);
+                        $(${ignore($mut)}
+                            walk_ty_alias_where_clauses(vis, where_clauses);
+                        )?
+                        $(<V as Visitor<$lt>>::Result::output())?
+                    }
+                    ItemKind::Enum(ident, generics, enum_definition) => {
+                        try_visit!(vis.visit_ident(ident));
+                        try_visit!(vis.visit_generics(generics));
+                        $(${ignore($mut)}
+                            enum_definition.variants.flat_map_in_place(|variant| vis.flat_map_variant(variant));
+                        )?
+                        $(${ignore($lt)}vis.visit_enum_def(enum_definition))?
+                    }
+                    ItemKind::Struct(ident, generics, variant_data)
+                    | ItemKind::Union(ident, generics, variant_data) => {
+                        try_visit!(vis.visit_ident(ident));
+                        try_visit!(vis.visit_generics(generics));
+                        vis.visit_variant_data(variant_data)
+                    }
+                    ItemKind::Impl(box Impl {
+                        defaultness,
+                        safety,
+                        generics,
+                        constness,
+                        polarity,
+                        of_trait,
+                        self_ty,
+                        items,
+                    }) => {
+                        try_visit!(visit_defaultness(vis, defaultness));
+                        try_visit!(visit_safety(vis, safety));
+                        try_visit!(vis.visit_generics(generics));
+                        try_visit!(visit_constness(vis, constness));
+                        try_visit!(visit_polarity(vis, polarity));
+                        visit_opt!(vis, visit_trait_ref, of_trait);
+                        try_visit!(vis.visit_ty(self_ty));
+                        $(${ignore($mut)}
+                            items.flat_map_in_place(|item| {
+                                vis.flat_map_assoc_item(item, AssocCtxt::Impl { of_trait: of_trait.is_some() })
+                            });
+                        )?
+                        $(${ignore($lt)}
+                            walk_list!(
+                                vis,
+                                visit_assoc_item,
+                                items,
+                                AssocCtxt::Impl { of_trait: of_trait.is_some() }
+                            );
+                            <V as Visitor<$lt>>::Result::output()
+                        )?
+                    }
+                    ItemKind::Trait(box Trait { safety, is_auto: _, ident, generics, bounds, items }) => {
+                        try_visit!(visit_safety(vis, safety));
+                        try_visit!(vis.visit_ident(ident));
+                        try_visit!(vis.visit_generics(generics));
+                        try_visit!(visit_bounds(vis, bounds, BoundKind::Bound));
+                        $(${ignore($mut)}
+                            items.flat_map_in_place(|item| {
+                                vis.flat_map_assoc_item(item, AssocCtxt::Trait)
+                            });
+                        )?
+                        $(${ignore($lt)}
+                            walk_list!(vis, visit_assoc_item, items, AssocCtxt::Trait);
+                            <V as Visitor<$lt>>::Result::output()
+                        )?
+                    }
+                    ItemKind::TraitAlias(ident, generics, bounds) => {
+                        try_visit!(vis.visit_ident(ident));
+                        try_visit!(vis.visit_generics(generics));
+                        visit_bounds(vis, bounds, BoundKind::Bound)
+                    }
+                    ItemKind::MacCall(m) => vis.visit_mac_call(m),
+                    ItemKind::MacroDef(ident, def) => {
+                        try_visit!(vis.visit_ident(ident));
+                        vis.visit_macro_def(def)
+                    }
+                    ItemKind::Delegation(box Delegation {
+                        id,
+                        qself,
+                        path,
+                        ident,
+                        rename,
+                        body,
+                        from_glob: _,
+                    }) => {
+                        try_visit!(visit_id(vis, id));
+                        try_visit!(vis.visit_qself(qself));
+                        try_visit!(vis.visit_path(path));
+                        try_visit!(vis.visit_ident(ident));
+                        visit_opt!(vis, visit_ident, rename);
+                        visit_opt!(vis, visit_block, body);
+                        $(<V as Visitor<$lt>>::Result::output())?
+                    }
+                    ItemKind::DelegationMac(box DelegationMac { qself, prefix, suffixes, body }) => {
+                        try_visit!(vis.visit_qself(qself));
+                        try_visit!(vis.visit_path(prefix));
+                        if let Some(suffixes) = suffixes {
+                            for (ident, rename) in suffixes {
+                                try_visit!(vis.visit_ident(ident));
+                                visit_opt!(vis, visit_ident, rename);
+                            }
+                        }
+                        visit_opt!(vis, visit_block, body);
+                        $(<V as Visitor<$lt>>::Result::output())?
+                    }
+                }
+            }
+        }
+
+        fn walk_const_item<$($lt,)? V: $Visitor$(<$lt>)?>(vis: &mut V, item: &$($lt)? $($mut)? ConstItem) $(-> <V as Visitor<$lt>>::Result)? {
+            let ConstItem { defaultness, ident, generics, ty, expr, define_opaque } = item;
+            try_visit!(visit_defaultness(vis, defaultness));
+            try_visit!(vis.visit_ident(ident));
+            try_visit!(vis.visit_generics(generics));
+            try_visit!(vis.visit_ty(ty));
+            visit_opt!(vis, visit_expr, expr);
+            walk_define_opaques(vis, define_opaque)
+        }
+
+        fn walk_foreign_mod<$($lt,)? V: $Visitor$(<$lt>)?>(vis: &mut V, foreign_mod: &$($lt)? $($mut)? ForeignMod) $(-> <V as Visitor<$lt>>::Result)? {
+            let ForeignMod { extern_span: _, safety, abi: _, items } = foreign_mod;
+            try_visit!(visit_safety(vis, safety));
+            $(${ignore($mut)}
+                items.flat_map_in_place(|item| vis.flat_map_foreign_item(item));
+            )?
+            $(
+                walk_list!(vis, visit_foreign_item, items);
+                <V as Visitor<$lt>>::Result::output()
+            )?
+        }
+
+        fn walk_define_opaques<$($lt,)? V: $Visitor$(<$lt>)?>(
+            visitor: &mut V,
+            define_opaque: &$($lt)? $($mut)? Option<ThinVec<(NodeId, Path)>>,
+        ) $(-> <V as Visitor<$lt>>::Result)? {
+            if let Some(define_opaque) = define_opaque {
+                for (id, path) in define_opaque {
+                    try_visit!(visit_id(visitor, id));
+                    try_visit!(visitor.visit_path(path));
+                }
+            }
+            $(<V as Visitor<$lt>>::Result::output())?
+        }
+
+        impl WalkItemKind for AssocItemKind {
+            type Ctxt = AssocCtxt;
+            fn walk<$($lt,)? V: $Visitor$(<$lt>)?>(
+                &$($lt)? $($mut)? self,
+                span: Span,
+                id: NodeId,
+                visibility: &$($lt)? $($mut)? Visibility,
+                ctxt: Self::Ctxt,
+                vis: &mut V,
+            ) $(-> <V as Visitor<$lt>>::Result)? {
+                match self {
+                    AssocItemKind::Const(item) => {
+                        walk_const_item(vis, item)
+                    }
+                    AssocItemKind::Fn(func) => {
+                        vis.visit_fn(FnKind::Fn(FnCtxt::Assoc(ctxt), visibility, &$($mut)? *func), span, id)
+                    }
+                    AssocItemKind::Type(box TyAlias {
+                        generics,
+                        ident,
+                        bounds,
+                        ty,
+                        defaultness,
+                        $(${ignore($lt)} #[expect(unused)])?
+                        where_clauses,
+                    }) => {
+                        try_visit!(visit_defaultness(vis, defaultness));
+                        try_visit!(vis.visit_ident(ident));
+                        try_visit!(vis.visit_generics(generics));
+                        try_visit!(visit_bounds(vis, bounds, BoundKind::Bound));
+                        visit_opt!(vis, visit_ty, ty);
+                        $(${ignore($mut)}
+                            walk_ty_alias_where_clauses(vis, where_clauses);
+                        )?
+                        $(<V as Visitor<$lt>>::Result::output())?
+                    }
+                    AssocItemKind::MacCall(mac) => {
+                        vis.visit_mac_call(mac)
+                    }
+                    AssocItemKind::Delegation(box Delegation {
+                        id,
+                        qself,
+                        path,
+                        ident,
+                        rename,
+                        body,
+                        from_glob: _,
+                    }) => {
+                        try_visit!(visit_id(vis, id));
+                        try_visit!(vis.visit_qself(qself));
+                        try_visit!(vis.visit_path(path));
+                        try_visit!(vis.visit_ident(ident));
+                        visit_opt!(vis, visit_ident, rename);
+                        visit_opt!(vis, visit_block, body);
+                        $(<V as Visitor<$lt>>::Result::output())?
+                    }
+                    AssocItemKind::DelegationMac(box DelegationMac { qself, prefix, suffixes, body }) => {
+                        try_visit!(vis.visit_qself(qself));
+                        try_visit!(vis.visit_path(prefix));
+                        if let Some(suffixes) = suffixes {
+                            for (ident, rename) in suffixes {
+                                try_visit!(vis.visit_ident(ident));
+                                visit_opt!(vis, visit_ident, rename);
+                            }
+                        }
+                        visit_opt!(vis, visit_block, body);
+                        $(<V as Visitor<$lt>>::Result::output())?
+                    }
+                }
+            }
+        }
+
+        impl WalkItemKind for ForeignItemKind {
+            type Ctxt = ();
+            fn walk<$($lt,)? V: $Visitor$(<$lt>)?>(
+                &$($lt)? $($mut)? self,
+                span: Span,
+                id: NodeId,
+                visibility: &$($lt)? $($mut)? Visibility,
+                _ctxt: Self::Ctxt,
+                vis: &mut V,
+            ) $(-> <V as Visitor<$lt>>::Result)? {
+                match self {
+                    ForeignItemKind::Static(box StaticItem {
+                        ident,
+                        ty,
+                        mutability: _,
+                        expr,
+                        safety: _,
+                        define_opaque,
+                    }) => {
+                        try_visit!(vis.visit_ident(ident));
+                        try_visit!(vis.visit_ty(ty));
+                        visit_opt!(vis, visit_expr, expr);
+                        walk_define_opaques(vis, define_opaque)
+                    }
+                    ForeignItemKind::Fn(func) => {
+                        vis.visit_fn(FnKind::Fn(FnCtxt::Foreign, visibility, &$($mut)?*func), span, id)
+                    }
+                    ForeignItemKind::TyAlias(box TyAlias {
+                        defaultness,
+                        ident,
+                        generics,
+                        bounds,
+                        ty,
+                        $(${ignore($lt)} #[expect(unused)])?
+                        where_clauses,
+                    }) => {
+                        try_visit!(visit_defaultness(vis, defaultness));
+                        try_visit!(vis.visit_ident(ident));
+                        try_visit!(vis.visit_generics(generics));
+                        try_visit!(visit_bounds(vis, bounds, BoundKind::Bound));
+                        visit_opt!(vis, visit_ty, ty);
+                        $(${ignore($mut)}
+                            walk_ty_alias_where_clauses(vis, where_clauses);
+                        )?
+                        $(<V as Visitor<$lt>>::Result::output())?
+                    }
+                    ForeignItemKind::MacCall(mac) => {
+                        vis.visit_mac_call(mac)
+                    }
+                }
+            }
+        }
+
+        fn walk_coroutine_kind<$($lt,)? V: $Visitor$(<$lt>)?>(
+            vis: &mut V,
+            coroutine_kind: &$($lt)? $($mut)? CoroutineKind,
+        ) $(-> <V as Visitor<$lt>>::Result)? {
+            match coroutine_kind {
+                CoroutineKind::Async { span, closure_id, return_impl_trait_id }
+                | CoroutineKind::Gen { span, closure_id, return_impl_trait_id }
+                | CoroutineKind::AsyncGen { span, closure_id, return_impl_trait_id } => {
+                    try_visit!(visit_id(vis, closure_id));
+                    try_visit!(visit_id(vis, return_impl_trait_id));
+                    visit_span(vis, span)
+                }
+            }
+        }
+
+        pub fn walk_pat<$($lt,)? V: $Visitor$(<$lt>)?>(
+            vis: &mut V,
+            pattern: &$($lt)? $($mut)? Pat
+        ) $(-> <V as Visitor<$lt>>::Result)? {
+            let Pat { id, kind, span, tokens: _ } = pattern;
+            try_visit!(visit_id(vis, id));
+            match kind {
+                PatKind::Err(_guar) => {}
+                PatKind::Missing | PatKind::Wild | PatKind::Rest | PatKind::Never => {}
+                PatKind::Ident(_bmode, ident, optional_subpattern) => {
+                    try_visit!(vis.visit_ident(ident));
+                    visit_opt!(vis, visit_pat, optional_subpattern);
+                }
+                PatKind::Expr(expression) => try_visit!(vis.visit_expr(expression)),
+                PatKind::TupleStruct(opt_qself, path, elems) => {
+                    try_visit!(vis.visit_qself(opt_qself));
+                    try_visit!(vis.visit_path(path));
+                    walk_list!(vis, visit_pat, elems);
+                }
+                PatKind::Path(opt_qself, path) => {
+                    try_visit!(vis.visit_qself(opt_qself));
+                    try_visit!(vis.visit_path(path))
+                }
+                PatKind::Struct(opt_qself, path, fields, _rest) => {
+                    try_visit!(vis.visit_qself(opt_qself));
+                    try_visit!(vis.visit_path(path));
+
+                    $(
+                        ${ignore($lt)}
+                        walk_list!(vis, visit_pat_field, fields);
+                    )?
+                    $(
+                        ${ignore($mut)}
+                        fields.flat_map_in_place(|field| vis.flat_map_pat_field(field));
+                    )?
+                }
+                PatKind::Box(subpattern) | PatKind::Deref(subpattern) | PatKind::Paren(subpattern) => {
+                    try_visit!(vis.visit_pat(subpattern));
+                }
+                PatKind::Ref(subpattern, _ /*mutbl*/) => {
+                    try_visit!(vis.visit_pat(subpattern));
+                }
+                PatKind::Range(lower_bound, upper_bound, _end) => {
+                    visit_opt!(vis, visit_expr, lower_bound);
+                    visit_opt!(vis, visit_expr, upper_bound);
+                    try_visit!(visit_span(vis, span));
+                }
+                PatKind::Guard(subpattern, guard_condition) => {
+                    try_visit!(vis.visit_pat(subpattern));
+                    try_visit!(vis.visit_expr(guard_condition));
+                }
+                PatKind::Tuple(elems) | PatKind::Slice(elems) | PatKind::Or(elems) => {
+                    walk_list!(vis, visit_pat, elems);
+                }
+                PatKind::MacCall(mac) => try_visit!(vis.visit_mac_call(mac)),
+            }
+            visit_span(vis, span)
+        }
+
+        pub fn walk_anon_const<$($lt,)? V: $Visitor$(<$lt>)?>(
+            vis: &mut V,
+            constant: &$($lt)? $($mut)? AnonConst,
+        ) $(-> <V as Visitor<$lt>>::Result)? {
+            let AnonConst { id, value } = constant;
+            try_visit!(visit_id(vis, id));
+            vis.visit_expr(value)
+        }
+
+        pub fn walk_path_segment<$($lt,)? V: $Visitor$(<$lt>)?>(
+            vis: &mut V,
+            segment: &$($lt)? $($mut)? PathSegment,
+        ) $(-> <V as Visitor<$lt>>::Result)? {
+            let PathSegment { ident, id, args } = segment;
+            try_visit!(visit_id(vis, id));
+            try_visit!(vis.visit_ident(ident));
+            visit_opt!(vis, visit_generic_args, args);
+            $(<V as Visitor<$lt>>::Result::output())?
+        }
+
+        pub fn walk_block<$($lt,)? V: $Visitor$(<$lt>)?>(
+            vis: &mut V,
+            block: &$($lt)? $($mut)? Block
+        ) $(-> <V as Visitor<$lt>>::Result)? {
+            let Block { stmts, id, rules: _, span, tokens: _ } = block;
+            try_visit!(visit_id(vis, id));
+            $(
+                ${ignore($lt)}
+                walk_list!(vis, visit_stmt, stmts);
+            )?
+            $(
+                ${ignore($mut)}
+                stmts.flat_map_in_place(|stmt| vis.flat_map_stmt(stmt));
+            )?
+            visit_span(vis, span)
+        }
+
+
+        pub fn walk_ty<$($lt,)? V: $Visitor$(<$lt>)?>(
+            vis: &mut V, ty: &$($lt)? $($mut)? Ty
+        ) $(-> <V as Visitor<$lt>>::Result)? {
+            let Ty { id, kind, span, tokens: _ } = ty;
+            try_visit!(visit_id(vis, id));
+            match kind {
+                TyKind::Err(_guar) => {}
+                TyKind::Infer | TyKind::ImplicitSelf | TyKind::Dummy | TyKind::Never | TyKind::CVarArgs => {}
+                TyKind::Slice(ty) | TyKind::Paren(ty) => try_visit!(vis.visit_ty(ty)),
+                TyKind::Ptr(MutTy { ty, mutbl: _ }) => try_visit!(vis.visit_ty(ty)),
+                TyKind::Ref(opt_lifetime, MutTy { ty, mutbl: _ })
+                | TyKind::PinnedRef(opt_lifetime, MutTy { ty, mutbl: _ }) => {
+                    // FIXME(fee1-dead) asymmetry
+                    visit_opt!(vis, visit_lifetime, opt_lifetime$(${ignore($lt)}, LifetimeCtxt::Ref)?);
+                    try_visit!(vis.visit_ty(ty));
+                }
+                TyKind::Tup(tuple_element_types) => {
+                    walk_list!(vis, visit_ty, tuple_element_types);
+                }
+                TyKind::BareFn(function_declaration) => {
+                    let BareFnTy { safety, ext: _, generic_params, decl, decl_span } =
+                        &$($mut)? **function_declaration;
+                    visit_safety(vis, safety);
+                    $(
+                        ${ignore($lt)}
+                        walk_list!(vis, visit_generic_param, generic_params);
+                    )?
+                    $(
+                        ${ignore($mut)}
+                        generic_params.flat_map_in_place(|param| vis.flat_map_generic_param(param));
+                    )?
+
+                    try_visit!(vis.visit_fn_decl(decl));
+                    try_visit!(visit_span(vis, decl_span));
+                }
+                TyKind::UnsafeBinder(binder) => {
+                    $(
+                        ${ignore($lt)}
+                        walk_list!(vis, visit_generic_param, &binder.generic_params);
+                    )?
+                    $(
+                        ${ignore($mut)}
+                        binder.generic_params.flat_map_in_place(|param| vis.flat_map_generic_param(param));
+                    )?
+                    try_visit!(vis.visit_ty(&$($mut)?binder.inner_ty));
+                }
+                TyKind::Path(maybe_qself, path) => {
+                    try_visit!(vis.visit_qself(maybe_qself));
+                    try_visit!(vis.visit_path(path));
+                }
+                TyKind::Pat(ty, pat) => {
+                    try_visit!(vis.visit_ty(ty));
+                    try_visit!(vis.visit_ty_pat(pat));
+                }
+                TyKind::Array(ty, length) => {
+                    try_visit!(vis.visit_ty(ty));
+                    try_visit!(vis.visit_anon_const(length));
+                }
+                TyKind::TraitObject(bounds, _syntax) => {
+                    walk_list!(vis, visit_param_bound, bounds, BoundKind::TraitObject);
+                }
+                TyKind::ImplTrait(id, bounds) => {
+                    try_visit!(visit_id(vis, id));
+                    walk_list!(vis, visit_param_bound, bounds, BoundKind::Impl);
+                }
+                TyKind::Typeof(expression) => try_visit!(vis.visit_anon_const(expression)),
+
+                TyKind::MacCall(mac) => try_visit!(vis.visit_mac_call(mac)),
+            }
+            visit_span(vis, span)
+        }
     };
 }
 
@@ -414,164 +990,8 @@ where
 
 pub fn walk_trait_ref<'a, V: Visitor<'a>>(visitor: &mut V, trait_ref: &'a TraitRef) -> V::Result {
     let TraitRef { path, ref_id } = trait_ref;
-    visitor.visit_path(path, *ref_id)
-}
-
-impl WalkItemKind for ItemKind {
-    type Ctxt = ();
-    fn walk<'a, V: Visitor<'a>>(
-        &'a self,
-        span: Span,
-        id: NodeId,
-        vis: &'a Visibility,
-        _ctxt: Self::Ctxt,
-        visitor: &mut V,
-    ) -> V::Result {
-        match self {
-            ItemKind::ExternCrate(_rename, ident) => try_visit!(visitor.visit_ident(ident)),
-            ItemKind::Use(use_tree) => try_visit!(visitor.visit_use_tree(use_tree, id, false)),
-            ItemKind::Static(box StaticItem {
-                ident,
-                ty,
-                safety: _,
-                mutability: _,
-                expr,
-                define_opaque,
-            }) => {
-                try_visit!(visitor.visit_ident(ident));
-                try_visit!(visitor.visit_ty(ty));
-                visit_opt!(visitor, visit_expr, expr);
-                try_visit!(walk_define_opaques(visitor, define_opaque));
-            }
-            ItemKind::Const(box ConstItem {
-                defaultness: _,
-                ident,
-                generics,
-                ty,
-                expr,
-                define_opaque,
-            }) => {
-                try_visit!(visitor.visit_ident(ident));
-                try_visit!(visitor.visit_generics(generics));
-                try_visit!(visitor.visit_ty(ty));
-                visit_opt!(visitor, visit_expr, expr);
-                try_visit!(walk_define_opaques(visitor, define_opaque));
-            }
-            ItemKind::Fn(func) => {
-                let kind = FnKind::Fn(FnCtxt::Free, vis, &*func);
-                try_visit!(visitor.visit_fn(kind, span, id));
-            }
-            ItemKind::Mod(_unsafety, ident, mod_kind) => {
-                try_visit!(visitor.visit_ident(ident));
-                match mod_kind {
-                    ModKind::Loaded(items, _inline, _inner_span, _) => {
-                        walk_list!(visitor, visit_item, items);
-                    }
-                    ModKind::Unloaded => {}
-                }
-            }
-            ItemKind::ForeignMod(ForeignMod { extern_span: _, safety: _, abi: _, items }) => {
-                walk_list!(visitor, visit_foreign_item, items);
-            }
-            ItemKind::GlobalAsm(asm) => try_visit!(visitor.visit_inline_asm(asm)),
-            ItemKind::TyAlias(box TyAlias {
-                generics,
-                ident,
-                bounds,
-                ty,
-                defaultness: _,
-                where_clauses: _,
-            }) => {
-                try_visit!(visitor.visit_ident(ident));
-                try_visit!(visitor.visit_generics(generics));
-                walk_list!(visitor, visit_param_bound, bounds, BoundKind::Bound);
-                visit_opt!(visitor, visit_ty, ty);
-            }
-            ItemKind::Enum(ident, enum_definition, generics) => {
-                try_visit!(visitor.visit_ident(ident));
-                try_visit!(visitor.visit_generics(generics));
-                try_visit!(visitor.visit_enum_def(enum_definition));
-            }
-            ItemKind::Impl(box Impl {
-                defaultness: _,
-                safety: _,
-                generics,
-                constness: _,
-                polarity: _,
-                of_trait,
-                self_ty,
-                items,
-            }) => {
-                try_visit!(visitor.visit_generics(generics));
-                visit_opt!(visitor, visit_trait_ref, of_trait);
-                try_visit!(visitor.visit_ty(self_ty));
-                walk_list!(
-                    visitor,
-                    visit_assoc_item,
-                    items,
-                    AssocCtxt::Impl { of_trait: of_trait.is_some() }
-                );
-            }
-            ItemKind::Struct(ident, struct_definition, generics)
-            | ItemKind::Union(ident, struct_definition, generics) => {
-                try_visit!(visitor.visit_ident(ident));
-                try_visit!(visitor.visit_generics(generics));
-                try_visit!(visitor.visit_variant_data(struct_definition));
-            }
-            ItemKind::Trait(box Trait {
-                safety: _,
-                is_auto: _,
-                ident,
-                generics,
-                bounds,
-                items,
-            }) => {
-                try_visit!(visitor.visit_ident(ident));
-                try_visit!(visitor.visit_generics(generics));
-                walk_list!(visitor, visit_param_bound, bounds, BoundKind::SuperTraits);
-                walk_list!(visitor, visit_assoc_item, items, AssocCtxt::Trait);
-            }
-            ItemKind::TraitAlias(ident, generics, bounds) => {
-                try_visit!(visitor.visit_ident(ident));
-                try_visit!(visitor.visit_generics(generics));
-                walk_list!(visitor, visit_param_bound, bounds, BoundKind::Bound);
-            }
-            ItemKind::MacCall(mac) => try_visit!(visitor.visit_mac_call(mac)),
-            ItemKind::MacroDef(ident, ts) => {
-                try_visit!(visitor.visit_ident(ident));
-                try_visit!(visitor.visit_mac_def(ts, id))
-            }
-            ItemKind::Delegation(box Delegation {
-                id,
-                qself,
-                path,
-                ident,
-                rename,
-                body,
-                from_glob: _,
-            }) => {
-                try_visit!(visitor.visit_qself(qself));
-                try_visit!(visitor.visit_path(path, *id));
-                try_visit!(visitor.visit_ident(ident));
-                visit_opt!(visitor, visit_ident, rename);
-                visit_opt!(visitor, visit_block, body);
-            }
-            ItemKind::DelegationMac(box DelegationMac { qself, prefix, suffixes, body }) => {
-                try_visit!(visitor.visit_qself(qself));
-                try_visit!(visitor.visit_path(prefix, id));
-                if let Some(suffixes) = suffixes {
-                    for (ident, rename) in suffixes {
-                        visitor.visit_ident(ident);
-                        if let Some(rename) = rename {
-                            visitor.visit_ident(rename);
-                        }
-                    }
-                }
-                visit_opt!(visitor, visit_block, body);
-            }
-        }
-        V::Result::output()
-    }
+    try_visit!(visitor.visit_path(path));
+    visitor.visit_id(*ref_id)
 }
 
 pub fn walk_enum_def<'a, V: Visitor<'a>>(
@@ -611,56 +1031,6 @@ pub fn walk_pat_field<'a, V: Visitor<'a>>(visitor: &mut V, fp: &'a PatField) ->
     V::Result::output()
 }
 
-pub fn walk_ty<'a, V: Visitor<'a>>(visitor: &mut V, typ: &'a Ty) -> V::Result {
-    let Ty { id, kind, span: _, tokens: _ } = typ;
-    match kind {
-        TyKind::Slice(ty) | TyKind::Paren(ty) => try_visit!(visitor.visit_ty(ty)),
-        TyKind::Ptr(MutTy { ty, mutbl: _ }) => try_visit!(visitor.visit_ty(ty)),
-        TyKind::Ref(opt_lifetime, MutTy { ty, mutbl: _ })
-        | TyKind::PinnedRef(opt_lifetime, MutTy { ty, mutbl: _ }) => {
-            visit_opt!(visitor, visit_lifetime, opt_lifetime, LifetimeCtxt::Ref);
-            try_visit!(visitor.visit_ty(ty));
-        }
-        TyKind::Tup(tuple_element_types) => {
-            walk_list!(visitor, visit_ty, tuple_element_types);
-        }
-        TyKind::BareFn(function_declaration) => {
-            let BareFnTy { safety: _, ext: _, generic_params, decl, decl_span: _ } =
-                &**function_declaration;
-            walk_list!(visitor, visit_generic_param, generic_params);
-            try_visit!(visitor.visit_fn_decl(decl));
-        }
-        TyKind::UnsafeBinder(binder) => {
-            walk_list!(visitor, visit_generic_param, &binder.generic_params);
-            try_visit!(visitor.visit_ty(&binder.inner_ty));
-        }
-        TyKind::Path(maybe_qself, path) => {
-            try_visit!(visitor.visit_qself(maybe_qself));
-            try_visit!(visitor.visit_path(path, *id));
-        }
-        TyKind::Pat(ty, pat) => {
-            try_visit!(visitor.visit_ty(ty));
-            try_visit!(visitor.visit_ty_pat(pat));
-        }
-        TyKind::Array(ty, length) => {
-            try_visit!(visitor.visit_ty(ty));
-            try_visit!(visitor.visit_anon_const(length));
-        }
-        TyKind::TraitObject(bounds, _syntax) => {
-            walk_list!(visitor, visit_param_bound, bounds, BoundKind::TraitObject);
-        }
-        TyKind::ImplTrait(_id, bounds) => {
-            walk_list!(visitor, visit_param_bound, bounds, BoundKind::Impl);
-        }
-        TyKind::Typeof(expression) => try_visit!(visitor.visit_anon_const(expression)),
-        TyKind::Infer | TyKind::ImplicitSelf | TyKind::Dummy => {}
-        TyKind::Err(_guar) => {}
-        TyKind::MacCall(mac) => try_visit!(visitor.visit_mac_call(mac)),
-        TyKind::Never | TyKind::CVarArgs => {}
-    }
-    V::Result::output()
-}
-
 pub fn walk_ty_pat<'a, V: Visitor<'a>>(visitor: &mut V, tp: &'a TyPat) -> V::Result {
     let TyPat { id: _, kind, span: _, tokens: _ } = tp;
     match kind {
@@ -694,7 +1064,8 @@ pub fn walk_use_tree<'a, V: Visitor<'a>>(
     id: NodeId,
 ) -> V::Result {
     let UseTree { prefix, kind, span: _ } = use_tree;
-    try_visit!(visitor.visit_path(prefix, id));
+    try_visit!(visitor.visit_id(id));
+    try_visit!(visitor.visit_path(prefix));
     match kind {
         UseTreeKind::Simple(rename) => {
             // The extra IDs are handled during AST lowering.
@@ -710,16 +1081,6 @@ pub fn walk_use_tree<'a, V: Visitor<'a>>(
     V::Result::output()
 }
 
-pub fn walk_path_segment<'a, V: Visitor<'a>>(
-    visitor: &mut V,
-    segment: &'a PathSegment,
-) -> V::Result {
-    let PathSegment { ident, id: _, args } = segment;
-    try_visit!(visitor.visit_ident(ident));
-    visit_opt!(visitor, visit_generic_args, args);
-    V::Result::output()
-}
-
 pub fn walk_generic_args<'a, V>(visitor: &mut V, generic_args: &'a GenericArgs) -> V::Result
 where
     V: Visitor<'a>,
@@ -775,101 +1136,6 @@ pub fn walk_assoc_item_constraint<'a, V: Visitor<'a>>(
     V::Result::output()
 }
 
-pub fn walk_pat<'a, V: Visitor<'a>>(visitor: &mut V, pattern: &'a Pat) -> V::Result {
-    let Pat { id, kind, span: _, tokens: _ } = pattern;
-    match kind {
-        PatKind::TupleStruct(opt_qself, path, elems) => {
-            try_visit!(visitor.visit_qself(opt_qself));
-            try_visit!(visitor.visit_path(path, *id));
-            walk_list!(visitor, visit_pat, elems);
-        }
-        PatKind::Path(opt_qself, path) => {
-            try_visit!(visitor.visit_qself(opt_qself));
-            try_visit!(visitor.visit_path(path, *id))
-        }
-        PatKind::Struct(opt_qself, path, fields, _rest) => {
-            try_visit!(visitor.visit_qself(opt_qself));
-            try_visit!(visitor.visit_path(path, *id));
-            walk_list!(visitor, visit_pat_field, fields);
-        }
-        PatKind::Box(subpattern) | PatKind::Deref(subpattern) | PatKind::Paren(subpattern) => {
-            try_visit!(visitor.visit_pat(subpattern));
-        }
-        PatKind::Ref(subpattern, _ /*mutbl*/) => {
-            try_visit!(visitor.visit_pat(subpattern));
-        }
-        PatKind::Ident(_bmode, ident, optional_subpattern) => {
-            try_visit!(visitor.visit_ident(ident));
-            visit_opt!(visitor, visit_pat, optional_subpattern);
-        }
-        PatKind::Expr(expression) => try_visit!(visitor.visit_expr(expression)),
-        PatKind::Range(lower_bound, upper_bound, _end) => {
-            visit_opt!(visitor, visit_expr, lower_bound);
-            visit_opt!(visitor, visit_expr, upper_bound);
-        }
-        PatKind::Guard(subpattern, guard_condition) => {
-            try_visit!(visitor.visit_pat(subpattern));
-            try_visit!(visitor.visit_expr(guard_condition));
-        }
-        PatKind::Missing | PatKind::Wild | PatKind::Rest | PatKind::Never => {}
-        PatKind::Err(_guar) => {}
-        PatKind::Tuple(elems) | PatKind::Slice(elems) | PatKind::Or(elems) => {
-            walk_list!(visitor, visit_pat, elems);
-        }
-        PatKind::MacCall(mac) => try_visit!(visitor.visit_mac_call(mac)),
-    }
-    V::Result::output()
-}
-
-impl WalkItemKind for ForeignItemKind {
-    type Ctxt = ();
-    fn walk<'a, V: Visitor<'a>>(
-        &'a self,
-        span: Span,
-        id: NodeId,
-        vis: &'a Visibility,
-        _ctxt: Self::Ctxt,
-        visitor: &mut V,
-    ) -> V::Result {
-        match self {
-            ForeignItemKind::Static(box StaticItem {
-                ident,
-                ty,
-                mutability: _,
-                expr,
-                safety: _,
-                define_opaque,
-            }) => {
-                try_visit!(visitor.visit_ident(ident));
-                try_visit!(visitor.visit_ty(ty));
-                visit_opt!(visitor, visit_expr, expr);
-                try_visit!(walk_define_opaques(visitor, define_opaque));
-            }
-            ForeignItemKind::Fn(func) => {
-                let kind = FnKind::Fn(FnCtxt::Foreign, vis, &*func);
-                try_visit!(visitor.visit_fn(kind, span, id));
-            }
-            ForeignItemKind::TyAlias(box TyAlias {
-                generics,
-                ident,
-                bounds,
-                ty,
-                defaultness: _,
-                where_clauses: _,
-            }) => {
-                try_visit!(visitor.visit_ident(ident));
-                try_visit!(visitor.visit_generics(generics));
-                walk_list!(visitor, visit_param_bound, bounds, BoundKind::Bound);
-                visit_opt!(visitor, visit_ty, ty);
-            }
-            ForeignItemKind::MacCall(mac) => {
-                try_visit!(visitor.visit_mac_call(mac));
-            }
-        }
-        V::Result::output()
-    }
-}
-
 pub fn walk_param_bound<'a, V: Visitor<'a>>(visitor: &mut V, bound: &'a GenericBound) -> V::Result {
     match bound {
         GenericBound::Trait(trait_ref) => visitor.visit_poly_trait_ref(trait_ref),
@@ -887,7 +1153,10 @@ pub fn walk_precise_capturing_arg<'a, V: Visitor<'a>>(
 ) -> V::Result {
     match arg {
         PreciseCapturingArg::Lifetime(lt) => visitor.visit_lifetime(lt, LifetimeCtxt::GenericArg),
-        PreciseCapturingArg::Arg(path, id) => visitor.visit_path(path, *id),
+        PreciseCapturingArg::Arg(path, id) => {
+            try_visit!(visitor.visit_id(*id));
+            visitor.visit_path(path)
+        }
     }
 }
 
@@ -1028,116 +1297,9 @@ pub fn walk_fn<'a, V: Visitor<'a>>(visitor: &mut V, kind: FnKind<'a>) -> V::Resu
     V::Result::output()
 }
 
-impl WalkItemKind for AssocItemKind {
-    type Ctxt = AssocCtxt;
-    fn walk<'a, V: Visitor<'a>>(
-        &'a self,
-        span: Span,
-        id: NodeId,
-        vis: &'a Visibility,
-        ctxt: Self::Ctxt,
-        visitor: &mut V,
-    ) -> V::Result {
-        match self {
-            AssocItemKind::Const(box ConstItem {
-                defaultness: _,
-                ident,
-                generics,
-                ty,
-                expr,
-                define_opaque,
-            }) => {
-                try_visit!(visitor.visit_ident(ident));
-                try_visit!(visitor.visit_generics(generics));
-                try_visit!(visitor.visit_ty(ty));
-                visit_opt!(visitor, visit_expr, expr);
-                try_visit!(walk_define_opaques(visitor, define_opaque));
-            }
-            AssocItemKind::Fn(func) => {
-                let kind = FnKind::Fn(FnCtxt::Assoc(ctxt), vis, &*func);
-                try_visit!(visitor.visit_fn(kind, span, id));
-            }
-            AssocItemKind::Type(box TyAlias {
-                generics,
-                ident,
-                bounds,
-                ty,
-                defaultness: _,
-                where_clauses: _,
-            }) => {
-                try_visit!(visitor.visit_generics(generics));
-                try_visit!(visitor.visit_ident(ident));
-                walk_list!(visitor, visit_param_bound, bounds, BoundKind::Bound);
-                visit_opt!(visitor, visit_ty, ty);
-            }
-            AssocItemKind::MacCall(mac) => {
-                try_visit!(visitor.visit_mac_call(mac));
-            }
-            AssocItemKind::Delegation(box Delegation {
-                id,
-                qself,
-                path,
-                ident,
-                rename,
-                body,
-                from_glob: _,
-            }) => {
-                try_visit!(visitor.visit_qself(qself));
-                try_visit!(visitor.visit_path(path, *id));
-                try_visit!(visitor.visit_ident(ident));
-                visit_opt!(visitor, visit_ident, rename);
-                visit_opt!(visitor, visit_block, body);
-            }
-            AssocItemKind::DelegationMac(box DelegationMac { qself, prefix, suffixes, body }) => {
-                try_visit!(visitor.visit_qself(qself));
-                try_visit!(visitor.visit_path(prefix, id));
-                if let Some(suffixes) = suffixes {
-                    for (ident, rename) in suffixes {
-                        visitor.visit_ident(ident);
-                        if let Some(rename) = rename {
-                            visitor.visit_ident(rename);
-                        }
-                    }
-                }
-                visit_opt!(visitor, visit_block, body);
-            }
-        }
-        V::Result::output()
-    }
-}
-
-pub fn walk_item<'a, V: Visitor<'a>>(
-    visitor: &mut V,
-    item: &'a Item<impl WalkItemKind<Ctxt = ()>>,
-) -> V::Result {
-    walk_item_ctxt(visitor, item, ())
-}
-
-pub fn walk_assoc_item<'a, V: Visitor<'a>>(
-    visitor: &mut V,
-    item: &'a AssocItem,
-    ctxt: AssocCtxt,
-) -> V::Result {
-    walk_item_ctxt(visitor, item, ctxt)
-}
-
-fn walk_item_ctxt<'a, V: Visitor<'a>, K: WalkItemKind>(
-    visitor: &mut V,
-    item: &'a Item<K>,
-    ctxt: K::Ctxt,
-) -> V::Result {
-    let Item { id, span, vis, attrs, kind, tokens: _ } = item;
-    walk_list!(visitor, visit_attribute, attrs);
-    try_visit!(visitor.visit_vis(vis));
-    try_visit!(kind.walk(*span, *id, vis, ctxt, visitor));
-    V::Result::output()
-}
-
-pub fn walk_struct_def<'a, V: Visitor<'a>>(
-    visitor: &mut V,
-    struct_definition: &'a VariantData,
-) -> V::Result {
-    walk_list!(visitor, visit_field_def, struct_definition.fields());
+pub fn walk_variant_data<'a, V: Visitor<'a>>(visitor: &mut V, data: &'a VariantData) -> V::Result {
+    visit_opt!(visitor, visit_id, data.ctor_node_id());
+    walk_list!(visitor, visit_field_def, data.fields());
     V::Result::output()
 }
 
@@ -1152,12 +1314,6 @@ pub fn walk_field_def<'a, V: Visitor<'a>>(visitor: &mut V, field: &'a FieldDef)
     V::Result::output()
 }
 
-pub fn walk_block<'a, V: Visitor<'a>>(visitor: &mut V, block: &'a Block) -> V::Result {
-    let Block { stmts, id: _, rules: _, span: _, tokens: _ } = block;
-    walk_list!(visitor, visit_stmt, stmts);
-    V::Result::output()
-}
-
 pub fn walk_stmt<'a, V: Visitor<'a>>(visitor: &mut V, statement: &'a Stmt) -> V::Result {
     let Stmt { id: _, kind, span: _ } = statement;
     match kind {
@@ -1176,12 +1332,7 @@ pub fn walk_stmt<'a, V: Visitor<'a>>(visitor: &mut V, statement: &'a Stmt) -> V:
 
 pub fn walk_mac<'a, V: Visitor<'a>>(visitor: &mut V, mac: &'a MacCall) -> V::Result {
     let MacCall { path, args: _ } = mac;
-    visitor.visit_path(path, DUMMY_NODE_ID)
-}
-
-pub fn walk_anon_const<'a, V: Visitor<'a>>(visitor: &mut V, constant: &'a AnonConst) -> V::Result {
-    let AnonConst { id: _, value } = constant;
-    visitor.visit_expr(value)
+    visitor.visit_path(path)
 }
 
 pub fn walk_inline_asm<'a, V: Visitor<'a>>(visitor: &mut V, asm: &'a InlineAsm) -> V::Result {
@@ -1221,7 +1372,8 @@ pub fn walk_inline_asm_sym<'a, V: Visitor<'a>>(
     InlineAsmSym { id, qself, path }: &'a InlineAsmSym,
 ) -> V::Result {
     try_visit!(visitor.visit_qself(qself));
-    visitor.visit_path(path, *id)
+    try_visit!(visitor.visit_id(*id));
+    visitor.visit_path(path)
 }
 
 pub fn walk_format_args<'a, V: Visitor<'a>>(visitor: &mut V, fmt: &'a FormatArgs) -> V::Result {
@@ -1253,7 +1405,8 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) -> V
         ExprKind::Struct(se) => {
             let StructExpr { qself, path, fields, rest } = &**se;
             try_visit!(visitor.visit_qself(qself));
-            try_visit!(visitor.visit_path(path, *id));
+            try_visit!(visitor.visit_id(*id));
+            try_visit!(visitor.visit_path(path));
             walk_list!(visitor, visit_expr_field, fields);
             match rest {
                 StructRest::Base(expr) => try_visit!(visitor.visit_expr(expr)),
@@ -1363,7 +1516,8 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) -> V
         ExprKind::Underscore => {}
         ExprKind::Path(maybe_qself, path) => {
             try_visit!(visitor.visit_qself(maybe_qself));
-            try_visit!(visitor.visit_path(path, *id));
+            try_visit!(visitor.visit_id(*id));
+            try_visit!(visitor.visit_path(path));
         }
         ExprKind::Break(opt_label, opt_expr) => {
             visit_opt!(visitor, visit_label, opt_label);
@@ -1426,7 +1580,8 @@ pub fn walk_vis<'a, V: Visitor<'a>>(visitor: &mut V, vis: &'a Visibility) -> V::
     let Visibility { kind, span: _, tokens: _ } = vis;
     match kind {
         VisibilityKind::Restricted { path, id, shorthand: _ } => {
-            try_visit!(visitor.visit_path(path, *id));
+            try_visit!(visitor.visit_id(*id));
+            try_visit!(visitor.visit_path(path));
         }
         VisibilityKind::Public | VisibilityKind::Inherited => {}
     }
@@ -1439,7 +1594,7 @@ pub fn walk_attribute<'a, V: Visitor<'a>>(visitor: &mut V, attr: &'a Attribute)
         AttrKind::Normal(normal) => {
             let NormalAttr { item, tokens: _ } = &**normal;
             let AttrItem { unsafety: _, path, args, tokens: _ } = item;
-            try_visit!(visitor.visit_path(path, DUMMY_NODE_ID));
+            try_visit!(visitor.visit_path(path));
             try_visit!(walk_attr_args(visitor, args));
         }
         AttrKind::DocComment(_kind, _sym) => {}
@@ -1455,15 +1610,3 @@ pub fn walk_attr_args<'a, V: Visitor<'a>>(visitor: &mut V, args: &'a AttrArgs) -
     }
     V::Result::output()
 }
-
-fn walk_define_opaques<'a, V: Visitor<'a>>(
-    visitor: &mut V,
-    define_opaque: &'a Option<ThinVec<(NodeId, Path)>>,
-) -> V::Result {
-    if let Some(define_opaque) = define_opaque {
-        for (id, path) in define_opaque {
-            try_visit!(visitor.visit_path(path, *id));
-        }
-    }
-    V::Result::output()
-}
diff --git a/compiler/rustc_ast_lowering/src/delegation.rs b/compiler/rustc_ast_lowering/src/delegation.rs
index 93c627f64c9..42d25b512f5 100644
--- a/compiler/rustc_ast_lowering/src/delegation.rs
+++ b/compiler/rustc_ast_lowering/src/delegation.rs
@@ -446,13 +446,7 @@ impl<'a> SelfResolver<'a> {
 }
 
 impl<'ast, 'a> Visitor<'ast> for SelfResolver<'a> {
-    fn visit_path(&mut self, path: &'ast Path, id: NodeId) {
+    fn visit_id(&mut self, id: NodeId) {
         self.try_replace_id(id);
-        visit::walk_path(self, path);
-    }
-
-    fn visit_path_segment(&mut self, seg: &'ast PathSegment) {
-        self.try_replace_id(seg.id);
-        visit::walk_path_segment(self, seg);
     }
 }
diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs
index 9f3aed9216c..537d4a2a6af 100644
--- a/compiler/rustc_ast_lowering/src/expr.rs
+++ b/compiler/rustc_ast_lowering/src/expr.rs
@@ -1,4 +1,3 @@
-use std::assert_matches::assert_matches;
 use std::ops::ControlFlow;
 use std::sync::Arc;
 
@@ -1199,11 +1198,13 @@ impl<'hir> LoweringContext<'_, 'hir> {
         let closure_def_id = self.local_def_id(closure_id);
         let (binder_clause, generic_params) = self.lower_closure_binder(binder);
 
-        assert_matches!(
-            coroutine_kind,
-            CoroutineKind::Async { .. },
-            "only async closures are supported currently"
-        );
+        let coroutine_desugaring = match coroutine_kind {
+            CoroutineKind::Async { .. } => hir::CoroutineDesugaring::Async,
+            CoroutineKind::Gen { .. } => hir::CoroutineDesugaring::Gen,
+            CoroutineKind::AsyncGen { span, .. } => {
+                span_bug!(span, "only async closures and `iter!` closures are supported currently")
+            }
+        };
 
         let body = self.with_new_scopes(fn_decl_span, |this| {
             let inner_decl =
@@ -1247,7 +1248,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
             // Lower this as a `CoroutineClosure`. That will ensure that HIR typeck
             // knows that a `FnDecl` output type like `-> &str` actually means
             // "coroutine that returns &str", rather than directly returning a `&str`.
-            kind: hir::ClosureKind::CoroutineClosure(hir::CoroutineDesugaring::Async),
+            kind: hir::ClosureKind::CoroutineClosure(coroutine_desugaring),
             constness: hir::Constness::NotConst,
         });
         hir::ExprKind::Closure(c)
diff --git a/compiler/rustc_ast_lowering/src/index.rs b/compiler/rustc_ast_lowering/src/index.rs
index 26c0e7e5f82..956cb580d10 100644
--- a/compiler/rustc_ast_lowering/src/index.rs
+++ b/compiler/rustc_ast_lowering/src/index.rs
@@ -164,7 +164,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
     fn visit_item(&mut self, i: &'hir Item<'hir>) {
         debug_assert_eq!(i.owner_id, self.owner);
         self.with_parent(i.hir_id(), |this| {
-            if let ItemKind::Struct(_, struct_def, _) = &i.kind {
+            if let ItemKind::Struct(_, _, struct_def) = &i.kind {
                 // If this is a tuple or unit-like struct, register the constructor.
                 if let Some(ctor_hir_id) = struct_def.ctor_hir_id() {
                     this.insert(i.span, ctor_hir_id, Node::Ctor(struct_def));
diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs
index e98d6c50ee7..d1a2ddbdb34 100644
--- a/compiler/rustc_ast_lowering/src/item.rs
+++ b/compiler/rustc_ast_lowering/src/item.rs
@@ -3,10 +3,11 @@ use rustc_ast::ptr::P;
 use rustc_ast::visit::AssocCtxt;
 use rustc_ast::*;
 use rustc_errors::ErrorGuaranteed;
-use rustc_hir::def::{DefKind, Res};
+use rustc_hir::def::{DefKind, PerNS, Res};
 use rustc_hir::def_id::{CRATE_DEF_ID, LocalDefId};
 use rustc_hir::{self as hir, HirId, LifetimeSource, PredicateOrigin};
 use rustc_index::{IndexSlice, IndexVec};
+use rustc_middle::span_bug;
 use rustc_middle::ty::{ResolverAstLowering, TyCtxt};
 use rustc_span::edit_distance::find_best_match_for_name;
 use rustc_span::{DUMMY_SP, DesugaringKind, Ident, Span, Symbol, kw, sym};
@@ -180,7 +181,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
                 let (ty, body_id) =
                     self.lower_const_item(t, span, e.as_deref(), ImplTraitPosition::StaticTy);
                 self.lower_define_opaque(hir_id, define_opaque);
-                hir::ItemKind::Static(ident, ty, *m, body_id)
+                hir::ItemKind::Static(*m, ident, ty, body_id)
             }
             ItemKind::Const(box ast::ConstItem {
                 ident,
@@ -200,7 +201,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
                     },
                 );
                 self.lower_define_opaque(hir_id, &define_opaque);
-                hir::ItemKind::Const(ident, ty, generics, body_id)
+                hir::ItemKind::Const(ident, generics, ty, body_id)
             }
             ItemKind::Fn(box Fn {
                 sig: FnSig { decl, header, span: fn_sig_span },
@@ -304,9 +305,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
                         ),
                     },
                 );
-                hir::ItemKind::TyAlias(ident, ty, generics)
+                hir::ItemKind::TyAlias(ident, generics, ty)
             }
-            ItemKind::Enum(ident, enum_definition, generics) => {
+            ItemKind::Enum(ident, generics, enum_definition) => {
                 let ident = self.lower_ident(*ident);
                 let (generics, variants) = self.lower_generics(
                     generics,
@@ -318,9 +319,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
                         )
                     },
                 );
-                hir::ItemKind::Enum(ident, hir::EnumDef { variants }, generics)
+                hir::ItemKind::Enum(ident, generics, hir::EnumDef { variants })
             }
-            ItemKind::Struct(ident, struct_def, generics) => {
+            ItemKind::Struct(ident, generics, struct_def) => {
                 let ident = self.lower_ident(*ident);
                 let (generics, struct_def) = self.lower_generics(
                     generics,
@@ -328,9 +329,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
                     ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
                     |this| this.lower_variant_data(hir_id, struct_def),
                 );
-                hir::ItemKind::Struct(ident, struct_def, generics)
+                hir::ItemKind::Struct(ident, generics, struct_def)
             }
-            ItemKind::Union(ident, vdata, generics) => {
+            ItemKind::Union(ident, generics, vdata) => {
                 let ident = self.lower_ident(*ident);
                 let (generics, vdata) = self.lower_generics(
                     generics,
@@ -338,7 +339,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
                     ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
                     |this| this.lower_variant_data(hir_id, vdata),
                 );
-                hir::ItemKind::Union(ident, vdata, generics)
+                hir::ItemKind::Union(ident, generics, vdata)
             }
             ItemKind::Impl(box Impl {
                 safety,
@@ -467,8 +468,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
             ItemKind::Delegation(box delegation) => {
                 let delegation_results = self.lower_delegation(delegation, id, false);
                 hir::ItemKind::Fn {
-                    ident: delegation_results.ident,
                     sig: delegation_results.sig,
+                    ident: delegation_results.ident,
                     generics: delegation_results.generics,
                     body: delegation_results.body_id,
                     has_body: true,
@@ -527,7 +528,22 @@ impl<'hir> LoweringContext<'_, 'hir> {
             }
             UseTreeKind::Glob => {
                 let res = self.expect_full_res(id);
-                let res = smallvec![self.lower_res(res)];
+                let res = self.lower_res(res);
+                // Put the result in the appropriate namespace.
+                let res = match res {
+                    Res::Def(DefKind::Mod | DefKind::Trait, _) => {
+                        PerNS { type_ns: Some(res), value_ns: None, macro_ns: None }
+                    }
+                    Res::Def(DefKind::Enum, _) => {
+                        PerNS { type_ns: None, value_ns: Some(res), macro_ns: None }
+                    }
+                    Res::Err => {
+                        // Propagate the error to all namespaces, just to be sure.
+                        let err = Some(Res::Err);
+                        PerNS { type_ns: err, value_ns: err, macro_ns: err }
+                    }
+                    _ => span_bug!(path.span, "bad glob res {:?}", res),
+                };
                 let path = Path { segments, span: path.span, tokens: None };
                 let path = self.lower_use_path(res, &path, ParamMode::Explicit);
                 hir::ItemKind::Use(path, hir::UseKind::Glob)
@@ -601,7 +617,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
                 } else {
                     // For non-empty lists we can just drop all the data, the prefix is already
                     // present in HIR as a part of nested imports.
-                    self.arena.alloc(hir::UsePath { res: smallvec![], segments: &[], span })
+                    self.arena.alloc(hir::UsePath { res: PerNS::default(), segments: &[], span })
                 };
                 hir::ItemKind::Use(path, hir::UseKind::ListStem)
             }
diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs
index 422e79ca82f..f41627e479f 100644
--- a/compiler/rustc_ast_lowering/src/lib.rs
+++ b/compiler/rustc_ast_lowering/src/lib.rs
@@ -64,7 +64,7 @@ use rustc_middle::ty::{ResolverAstLowering, TyCtxt};
 use rustc_session::parse::{add_feature_diagnostics, feature_err};
 use rustc_span::symbol::{Ident, Symbol, kw, sym};
 use rustc_span::{DUMMY_SP, DesugaringKind, Span};
-use smallvec::{SmallVec, smallvec};
+use smallvec::SmallVec;
 use thin_vec::ThinVec;
 use tracing::{debug, instrument, trace};
 
@@ -705,14 +705,16 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         self.resolver.get_partial_res(id).map_or(Res::Err, |pr| pr.expect_full_res())
     }
 
-    fn lower_import_res(&mut self, id: NodeId, span: Span) -> SmallVec<[Res; 3]> {
-        let res = self.resolver.get_import_res(id).present_items();
-        let res: SmallVec<_> = res.map(|res| self.lower_res(res)).collect();
-        if res.is_empty() {
+    fn lower_import_res(&mut self, id: NodeId, span: Span) -> PerNS<Option<Res>> {
+        let per_ns = self.resolver.get_import_res(id);
+        let per_ns = per_ns.map(|res| res.map(|res| self.lower_res(res)));
+        if per_ns.is_empty() {
+            // Propagate the error to all namespaces, just to be sure.
             self.dcx().span_delayed_bug(span, "no resolution for an import");
-            return smallvec![Res::Err];
+            let err = Some(Res::Err);
+            return PerNS { type_ns: err, value_ns: err, macro_ns: err };
         }
-        res
+        per_ns
     }
 
     fn make_lang_item_qpath(
diff --git a/compiler/rustc_ast_lowering/src/path.rs b/compiler/rustc_ast_lowering/src/path.rs
index 5cda64ce7b4..c80ef275c80 100644
--- a/compiler/rustc_ast_lowering/src/path.rs
+++ b/compiler/rustc_ast_lowering/src/path.rs
@@ -1,13 +1,13 @@
 use std::sync::Arc;
 
 use rustc_ast::{self as ast, *};
-use rustc_hir::def::{DefKind, PartialRes, Res};
+use rustc_hir::def::{DefKind, PartialRes, PerNS, Res};
 use rustc_hir::def_id::DefId;
 use rustc_hir::{self as hir, GenericArg};
 use rustc_middle::{span_bug, ty};
 use rustc_session::parse::add_feature_diagnostics;
 use rustc_span::{BytePos, DUMMY_SP, DesugaringKind, Ident, Span, Symbol, sym};
-use smallvec::{SmallVec, smallvec};
+use smallvec::smallvec;
 use tracing::{debug, instrument};
 
 use super::errors::{
@@ -226,11 +226,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
 
     pub(crate) fn lower_use_path(
         &mut self,
-        res: SmallVec<[Res; 3]>,
+        res: PerNS<Option<Res>>,
         p: &Path,
         param_mode: ParamMode,
     ) -> &'hir hir::UsePath<'hir> {
-        assert!((1..=3).contains(&res.len()));
+        assert!(!res.is_empty());
         self.arena.alloc(hir::UsePath {
             res,
             segments: self.arena.alloc_from_iter(p.segments.iter().map(|segment| {
diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs
index cbf4f2f5eb2..d6fe04d2994 100644
--- a/compiler/rustc_ast_passes/src/ast_validation.rs
+++ b/compiler/rustc_ast_passes/src/ast_validation.rs
@@ -1010,7 +1010,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
                 });
                 self.extern_mod_span = old_item;
             }
-            ItemKind::Enum(_, def, _) => {
+            ItemKind::Enum(_, _, def) => {
                 for variant in &def.variants {
                     self.visibility_not_permitted(
                         &variant.vis,
@@ -1061,7 +1061,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
                 }
                 visit::walk_item(self, item)
             }
-            ItemKind::Struct(ident, vdata, generics) => match vdata {
+            ItemKind::Struct(ident, generics, vdata) => match vdata {
                 VariantData::Struct { fields, .. } => {
                     self.visit_attrs_vis_ident(&item.attrs, &item.vis, ident);
                     self.visit_generics(generics);
@@ -1070,7 +1070,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
                 }
                 _ => visit::walk_item(self, item),
             },
-            ItemKind::Union(ident, vdata, generics) => {
+            ItemKind::Union(ident, generics, vdata) => {
                 if vdata.fields().is_empty() {
                     self.dcx().emit_err(errors::FieldlessUnion { span: item.span });
                 }
diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs
index 915613a3913..3682d25d341 100644
--- a/compiler/rustc_ast_passes/src/feature_gate.rs
+++ b/compiler/rustc_ast_passes/src/feature_gate.rs
@@ -477,11 +477,12 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) {
         for span in spans {
             if (!visitor.features.coroutines() && !span.allows_unstable(sym::coroutines))
                 && (!visitor.features.gen_blocks() && !span.allows_unstable(sym::gen_blocks))
+                && (!visitor.features.yield_expr() && !span.allows_unstable(sym::yield_expr))
             {
                 #[allow(rustc::untranslatable_diagnostic)]
-                // Don't know which of the two features to include in the
-                // error message, so I am arbitrarily picking one.
-                feature_err(&visitor.sess, sym::coroutines, *span, "yield syntax is experimental")
+                // Emit yield_expr as the error, since that will be sufficient. You can think of it
+                // as coroutines and gen_blocks imply yield_expr.
+                feature_err(&visitor.sess, sym::yield_expr, *span, "yield syntax is experimental")
                     .emit();
             }
         }
diff --git a/compiler/rustc_ast_pretty/src/pprust/state/item.rs b/compiler/rustc_ast_pretty/src/pprust/state/item.rs
index 70cf2f2a459..3638eb31c61 100644
--- a/compiler/rustc_ast_pretty/src/pprust/state/item.rs
+++ b/compiler/rustc_ast_pretty/src/pprust/state/item.rs
@@ -298,14 +298,14 @@ impl<'a> State<'a> {
                     *defaultness,
                 );
             }
-            ast::ItemKind::Enum(ident, enum_definition, params) => {
-                self.print_enum_def(enum_definition, params, *ident, item.span, &item.vis);
+            ast::ItemKind::Enum(ident, generics, enum_definition) => {
+                self.print_enum_def(enum_definition, generics, *ident, item.span, &item.vis);
             }
-            ast::ItemKind::Struct(ident, struct_def, generics) => {
+            ast::ItemKind::Struct(ident, generics, struct_def) => {
                 let (cb, ib) = self.head(visibility_qualified(&item.vis, "struct"));
                 self.print_struct(struct_def, generics, *ident, item.span, true, cb, ib);
             }
-            ast::ItemKind::Union(ident, struct_def, generics) => {
+            ast::ItemKind::Union(ident, generics, struct_def) => {
                 let (cb, ib) = self.head(visibility_qualified(&item.vis, "union"));
                 self.print_struct(struct_def, generics, *ident, item.span, true, cb, ib);
             }
diff --git a/compiler/rustc_attr_parsing/src/attributes/allow_unstable.rs b/compiler/rustc_attr_parsing/src/attributes/allow_unstable.rs
index c1d95d07f4c..b9b6ca26119 100644
--- a/compiler/rustc_attr_parsing/src/attributes/allow_unstable.rs
+++ b/compiler/rustc_attr_parsing/src/attributes/allow_unstable.rs
@@ -10,7 +10,7 @@ use crate::session_diagnostics;
 
 pub(crate) struct AllowInternalUnstableParser;
 impl CombineAttributeParser for AllowInternalUnstableParser {
-    const PATH: &'static [rustc_span::Symbol] = &[sym::allow_internal_unstable];
+    const PATH: &'static [Symbol] = &[sym::allow_internal_unstable];
     type Item = (Symbol, Span);
     const CONVERT: ConvertFn<Self::Item> = AttributeKind::AllowInternalUnstable;
 
@@ -24,7 +24,7 @@ impl CombineAttributeParser for AllowInternalUnstableParser {
 
 pub(crate) struct AllowConstFnUnstableParser;
 impl CombineAttributeParser for AllowConstFnUnstableParser {
-    const PATH: &'static [rustc_span::Symbol] = &[sym::rustc_allow_const_fn_unstable];
+    const PATH: &'static [Symbol] = &[sym::rustc_allow_const_fn_unstable];
     type Item = Symbol;
     const CONVERT: ConvertFn<Self::Item> = AttributeKind::AllowConstFnUnstable;
 
diff --git a/compiler/rustc_attr_parsing/src/attributes/cfg.rs b/compiler/rustc_attr_parsing/src/attributes/cfg.rs
index 528f56dfac7..f4d23012af7 100644
--- a/compiler/rustc_attr_parsing/src/attributes/cfg.rs
+++ b/compiler/rustc_attr_parsing/src/attributes/cfg.rs
@@ -4,14 +4,29 @@ use rustc_attr_data_structures::RustcVersion;
 use rustc_feature::{Features, GatedCfg, find_gated_cfg};
 use rustc_session::Session;
 use rustc_session::config::ExpectedValues;
-use rustc_session::lint::BuiltinLintDiag;
 use rustc_session::lint::builtin::UNEXPECTED_CFGS;
+use rustc_session::lint::{BuiltinLintDiag, Lint};
 use rustc_session::parse::feature_err;
 use rustc_span::{Span, Symbol, sym};
 
 use crate::session_diagnostics::{self, UnsupportedLiteralReason};
 use crate::{fluent_generated, parse_version};
 
+/// Emitter of a builtin lint from `cfg_matches`.
+///
+/// Used to support emiting a lint (currently on check-cfg), either:
+///  - as an early buffered lint (in `rustc`)
+///  - or has a "normal" lint from HIR (in `rustdoc`)
+pub trait CfgMatchesLintEmitter {
+    fn emit_span_lint(&self, sess: &Session, lint: &'static Lint, sp: Span, diag: BuiltinLintDiag);
+}
+
+impl CfgMatchesLintEmitter for NodeId {
+    fn emit_span_lint(&self, sess: &Session, lint: &'static Lint, sp: Span, diag: BuiltinLintDiag) {
+        sess.psess.buffer_lint(lint, sp, *self, diag);
+    }
+}
+
 #[derive(Clone, Debug)]
 pub struct Condition {
     pub name: Symbol,
@@ -25,17 +40,17 @@ pub struct Condition {
 pub fn cfg_matches(
     cfg: &MetaItemInner,
     sess: &Session,
-    lint_node_id: NodeId,
+    lint_emitter: impl CfgMatchesLintEmitter,
     features: Option<&Features>,
 ) -> bool {
     eval_condition(cfg, sess, features, &mut |cfg| {
         try_gate_cfg(cfg.name, cfg.span, sess, features);
         match sess.psess.check_config.expecteds.get(&cfg.name) {
             Some(ExpectedValues::Some(values)) if !values.contains(&cfg.value) => {
-                sess.psess.buffer_lint(
+                lint_emitter.emit_span_lint(
+                    sess,
                     UNEXPECTED_CFGS,
                     cfg.span,
-                    lint_node_id,
                     BuiltinLintDiag::UnexpectedCfgValue(
                         (cfg.name, cfg.name_span),
                         cfg.value.map(|v| (v, cfg.value_span.unwrap())),
@@ -43,10 +58,10 @@ pub fn cfg_matches(
                 );
             }
             None if sess.psess.check_config.exhaustive_names => {
-                sess.psess.buffer_lint(
+                lint_emitter.emit_span_lint(
+                    sess,
                     UNEXPECTED_CFGS,
                     cfg.span,
-                    lint_node_id,
                     BuiltinLintDiag::UnexpectedCfgName(
                         (cfg.name, cfg.name_span),
                         cfg.value.map(|v| (v, cfg.value_span.unwrap())),
diff --git a/compiler/rustc_attr_parsing/src/attributes/deprecation.rs b/compiler/rustc_attr_parsing/src/attributes/deprecation.rs
index fb3d5f57d4f..1775770ec68 100644
--- a/compiler/rustc_attr_parsing/src/attributes/deprecation.rs
+++ b/compiler/rustc_attr_parsing/src/attributes/deprecation.rs
@@ -42,9 +42,9 @@ fn get(
 }
 
 impl SingleAttributeParser for DeprecationParser {
-    const PATH: &'static [rustc_span::Symbol] = &[sym::deprecated];
+    const PATH: &'static [Symbol] = &[sym::deprecated];
 
-    fn on_duplicate(cx: &AcceptContext<'_>, first_span: rustc_span::Span) {
+    fn on_duplicate(cx: &AcceptContext<'_>, first_span: Span) {
         // FIXME(jdonszelmann): merge with errors from check_attrs.rs
         cx.emit_err(session_diagnostics::UnusedMultiple {
             this: cx.attr_span,
diff --git a/compiler/rustc_attr_parsing/src/attributes/mod.rs b/compiler/rustc_attr_parsing/src/attributes/mod.rs
index 6ecd6b4d7db..f45cf984f71 100644
--- a/compiler/rustc_attr_parsing/src/attributes/mod.rs
+++ b/compiler/rustc_attr_parsing/src/attributes/mod.rs
@@ -17,7 +17,7 @@
 use std::marker::PhantomData;
 
 use rustc_attr_data_structures::AttributeKind;
-use rustc_span::Span;
+use rustc_span::{Span, Symbol};
 use thin_vec::ThinVec;
 
 use crate::context::{AcceptContext, FinalizeContext};
@@ -33,7 +33,7 @@ pub(crate) mod transparency;
 pub(crate) mod util;
 
 type AcceptFn<T> = fn(&mut T, &AcceptContext<'_>, &ArgParser<'_>);
-type AcceptMapping<T> = &'static [(&'static [rustc_span::Symbol], AcceptFn<T>)];
+type AcceptMapping<T> = &'static [(&'static [Symbol], AcceptFn<T>)];
 
 /// An [`AttributeParser`] is a type which searches for syntactic attributes.
 ///
@@ -72,7 +72,7 @@ pub(crate) trait AttributeParser: Default + 'static {
 /// [`SingleAttributeParser`] can only convert attributes one-to-one, and cannot combine multiple
 /// attributes together like is necessary for `#[stable()]` and `#[unstable()]` for example.
 pub(crate) trait SingleAttributeParser: 'static {
-    const PATH: &'static [rustc_span::Symbol];
+    const PATH: &'static [Symbol];
 
     /// Caled when a duplicate attribute is found.
     ///
@@ -119,7 +119,7 @@ type ConvertFn<E> = fn(ThinVec<E>) -> AttributeKind;
 /// [`CombineAttributeParser`] can only convert a single kind of attribute, and cannot combine multiple
 /// attributes together like is necessary for `#[stable()]` and `#[unstable()]` for example.
 pub(crate) trait CombineAttributeParser: 'static {
-    const PATH: &'static [rustc_span::Symbol];
+    const PATH: &'static [Symbol];
 
     type Item;
     const CONVERT: ConvertFn<Self::Item>;
diff --git a/compiler/rustc_attr_parsing/src/attributes/repr.rs b/compiler/rustc_attr_parsing/src/attributes/repr.rs
index 43dfb85a7c4..ab523ce0038 100644
--- a/compiler/rustc_attr_parsing/src/attributes/repr.rs
+++ b/compiler/rustc_attr_parsing/src/attributes/repr.rs
@@ -1,7 +1,7 @@
 use rustc_abi::Align;
 use rustc_ast::{IntTy, LitIntType, LitKind, UintTy};
 use rustc_attr_data_structures::{AttributeKind, IntType, ReprAttr};
-use rustc_span::{Span, Symbol, sym};
+use rustc_span::{DUMMY_SP, Span, Symbol, sym};
 
 use super::{CombineAttributeParser, ConvertFn};
 use crate::context::AcceptContext;
@@ -21,7 +21,7 @@ pub(crate) struct ReprParser;
 
 impl CombineAttributeParser for ReprParser {
     type Item = (ReprAttr, Span);
-    const PATH: &'static [rustc_span::Symbol] = &[sym::repr];
+    const PATH: &'static [Symbol] = &[sym::repr];
     const CONVERT: ConvertFn<Self::Item> = AttributeKind::Repr;
 
     fn extend<'a>(
@@ -99,7 +99,7 @@ fn parse_repr(cx: &AcceptContext<'_>, param: &MetaItemParser<'_>) -> Option<Repr
     let (name, ident_span) = if let Some(ident) = param.path_without_args().word() {
         (Some(ident.name), ident.span)
     } else {
-        (None, rustc_span::DUMMY_SP)
+        (None, DUMMY_SP)
     };
 
     let args = param.args();
diff --git a/compiler/rustc_attr_parsing/src/attributes/stability.rs b/compiler/rustc_attr_parsing/src/attributes/stability.rs
index cd1f21d92e7..e30d7e7238e 100644
--- a/compiler/rustc_attr_parsing/src/attributes/stability.rs
+++ b/compiler/rustc_attr_parsing/src/attributes/stability.rs
@@ -117,7 +117,7 @@ impl AttributeParser for BodyStabilityParser {
 pub(crate) struct ConstStabilityIndirectParser;
 // FIXME(jdonszelmann): single word attribute group when we have these
 impl SingleAttributeParser for ConstStabilityIndirectParser {
-    const PATH: &'static [rustc_span::Symbol] = &[sym::rustc_const_stable_indirect];
+    const PATH: &'static [Symbol] = &[sym::rustc_const_stable_indirect];
 
     // ignore
     fn on_duplicate(_cx: &AcceptContext<'_>, _first_span: Span) {}
diff --git a/compiler/rustc_attr_parsing/src/attributes/transparency.rs b/compiler/rustc_attr_parsing/src/attributes/transparency.rs
index ce42b0507ed..d229fc09740 100644
--- a/compiler/rustc_attr_parsing/src/attributes/transparency.rs
+++ b/compiler/rustc_attr_parsing/src/attributes/transparency.rs
@@ -1,6 +1,6 @@
 use rustc_attr_data_structures::AttributeKind;
 use rustc_span::hygiene::Transparency;
-use rustc_span::sym;
+use rustc_span::{Span, Symbol, sym};
 
 use super::{AcceptContext, SingleAttributeParser};
 use crate::parser::ArgParser;
@@ -11,9 +11,9 @@ pub(crate) struct TransparencyParser;
 #[allow(rustc::untranslatable_diagnostic)]
 #[allow(rustc::diagnostic_outside_of_impl)]
 impl SingleAttributeParser for TransparencyParser {
-    const PATH: &'static [rustc_span::Symbol] = &[sym::rustc_macro_transparency];
+    const PATH: &'static [Symbol] = &[sym::rustc_macro_transparency];
 
-    fn on_duplicate(cx: &crate::context::AcceptContext<'_>, first_span: rustc_span::Span) {
+    fn on_duplicate(cx: &crate::context::AcceptContext<'_>, first_span: Span) {
         cx.dcx().span_err(vec![first_span, cx.attr_span], "multiple macro transparency attributes");
     }
 
diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs
index 55c3df003fe..1360fc68714 100644
--- a/compiler/rustc_attr_parsing/src/context.rs
+++ b/compiler/rustc_attr_parsing/src/context.rs
@@ -26,12 +26,16 @@ macro_rules! attribute_groups {
     (
         pub(crate) static $name: ident = [$($names: ty),* $(,)?];
     ) => {
-        pub(crate) static $name: LazyLock<(
-            BTreeMap<&'static [Symbol], Vec<Box<dyn Fn(&AcceptContext<'_>, &ArgParser<'_>) + Send + Sync>>>,
-            Vec<Box<dyn Send + Sync + Fn(&FinalizeContext<'_>) -> Option<AttributeKind>>>
-        )> = LazyLock::new(|| {
-            let mut accepts = BTreeMap::<_, Vec<Box<dyn Fn(&AcceptContext<'_>, &ArgParser<'_>) + Send + Sync>>>::new();
-            let mut finalizes = Vec::<Box<dyn Send + Sync + Fn(&FinalizeContext<'_>) -> Option<AttributeKind>>>::new();
+        type Accepts = BTreeMap<
+            &'static [Symbol],
+            Box<dyn Send + Sync + Fn(&AcceptContext<'_>, &ArgParser<'_>)>
+        >;
+        type Finalizes = Vec<
+            Box<dyn Send + Sync + Fn(&FinalizeContext<'_>) -> Option<AttributeKind>>
+        >;
+        pub(crate) static $name: LazyLock<(Accepts, Finalizes)> = LazyLock::new(|| {
+            let mut accepts = Accepts::new();
+            let mut finalizes = Finalizes::new();
             $(
                 {
                     thread_local! {
@@ -39,11 +43,12 @@ macro_rules! attribute_groups {
                     };
 
                     for (k, v) in <$names>::ATTRIBUTES {
-                        accepts.entry(*k).or_default().push(Box::new(|cx, args| {
+                        let old = accepts.insert(*k, Box::new(|cx, args| {
                             STATE_OBJECT.with_borrow_mut(|s| {
                                 v(s, cx, args)
                             })
                         }));
+                        assert!(old.is_none());
                     }
 
                     finalizes.push(Box::new(|cx| {
@@ -110,7 +115,8 @@ impl<'a> Deref for AcceptContext<'a> {
 
 /// Context given to every attribute parser during finalization.
 ///
-/// Gives [`AttributeParser`](crate::attributes::AttributeParser)s enough information to create errors, for example.
+/// Gives [`AttributeParser`](crate::attributes::AttributeParser)s enough information to create
+/// errors, for example.
 pub(crate) struct FinalizeContext<'a> {
     /// The parse context, gives access to the session and the
     /// diagnostics context.
@@ -141,10 +147,9 @@ pub struct AttributeParser<'sess> {
     sess: &'sess Session,
     features: Option<&'sess Features>,
 
-    /// *only* parse attributes with this symbol.
+    /// *Only* parse attributes with this symbol.
     ///
-    /// Used in cases where we want the lowering infrastructure for
-    /// parse just a single attribute.
+    /// Used in cases where we want the lowering infrastructure for parse just a single attribute.
     parse_only: Option<Symbol>,
 
     /// Can be used to instruct parsers to reduce the number of diagnostics it emits.
@@ -157,9 +162,9 @@ impl<'sess> AttributeParser<'sess> {
     /// One example where this is necessary, is to parse `feature` attributes themselves for
     /// example.
     ///
-    /// Try to use this as little as possible. Attributes *should* be lowered during `rustc_ast_lowering`.
-    /// Some attributes require access to features to parse, which would crash if you tried to do so
-    /// through [`parse_limited`](Self::parse_limited).
+    /// Try to use this as little as possible. Attributes *should* be lowered during
+    /// `rustc_ast_lowering`. Some attributes require access to features to parse, which would
+    /// crash if you tried to do so through [`parse_limited`](Self::parse_limited).
     ///
     /// To make sure use is limited, supply a `Symbol` you'd like to parse. Only attributes with
     /// that symbol are picked out of the list of instructions and parsed. Those are returned.
@@ -217,19 +222,18 @@ impl<'sess> AttributeParser<'sess> {
         let group_cx = FinalizeContext { cx: self, target_span };
 
         for attr in attrs {
-            // if we're only looking for a single attribute,
-            // skip all the ones we don't care about
+            // If we're only looking for a single attribute, skip all the ones we don't care about.
             if let Some(expected) = self.parse_only {
                 if !attr.has_name(expected) {
                     continue;
                 }
             }
 
-            // sometimes, for example for `#![doc = include_str!("readme.md")]`,
+            // Sometimes, for example for `#![doc = include_str!("readme.md")]`,
             // doc still contains a non-literal. You might say, when we're lowering attributes
             // that's expanded right? But no, sometimes, when parsing attributes on macros,
             // we already use the lowering logic and these are still there. So, when `omit_doc`
-            // is set we *also* want to ignore these
+            // is set we *also* want to ignore these.
             if omit_doc == OmitDoc::Skip && attr.has_name(sym::doc) {
                 continue;
             }
@@ -263,21 +267,17 @@ impl<'sess> AttributeParser<'sess> {
                     let (path, args) = parser.deconstruct();
                     let parts = path.segments().map(|i| i.name).collect::<Vec<_>>();
 
-                    if let Some(accepts) = ATTRIBUTE_MAPPING.0.get(parts.as_slice()) {
-                        for f in accepts {
-                            let cx = AcceptContext {
-                                group_cx: &group_cx,
-                                attr_span: lower_span(attr.span),
-                            };
+                    if let Some(accept) = ATTRIBUTE_MAPPING.0.get(parts.as_slice()) {
+                        let cx =
+                            AcceptContext { group_cx: &group_cx, attr_span: lower_span(attr.span) };
 
-                            f(&cx, &args)
-                        }
+                        accept(&cx, &args)
                     } else {
-                        // if we're here, we must be compiling a tool attribute... Or someone forgot to
-                        // parse their fancy new attribute. Let's warn them in any case. If you are that
-                        // person, and you really your attribute should remain unparsed, carefully read the
-                        // documentation in this module and if you still think so you can add an exception
-                        // to this assertion.
+                        // If we're here, we must be compiling a tool attribute... Or someone
+                        // forgot to parse their fancy new attribute. Let's warn them in any case.
+                        // If you are that person, and you really think your attribute should
+                        // remain unparsed, carefully read the documentation in this module and if
+                        // you still think so you can add an exception to this assertion.
 
                         // FIXME(jdonszelmann): convert other attributes, and check with this that
                         // we caught em all
diff --git a/compiler/rustc_attr_parsing/src/parser.rs b/compiler/rustc_attr_parsing/src/parser.rs
index 077d953cfa3..f433d3574e1 100644
--- a/compiler/rustc_attr_parsing/src/parser.rs
+++ b/compiler/rustc_attr_parsing/src/parser.rs
@@ -12,8 +12,7 @@ use rustc_ast::{AttrArgs, DelimArgs, Expr, ExprKind, LitKind, MetaItemLit, Norma
 use rustc_ast_pretty::pprust;
 use rustc_errors::DiagCtxtHandle;
 use rustc_hir::{self as hir, AttrPath};
-use rustc_span::symbol::{Ident, kw, sym};
-use rustc_span::{ErrorGuaranteed, Span, Symbol};
+use rustc_span::{ErrorGuaranteed, Ident, Span, Symbol, kw, sym};
 
 pub struct SegmentIterator<'a> {
     offset: usize,
diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
index 56cc4327585..a5c9bad3ac2 100644
--- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
@@ -840,14 +840,22 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
             } else {
                 bug!("not an upvar")
             };
-            err.span_label(
-                *span,
-                format!(
-                    "calling `{}` requires mutable binding due to {}",
-                    self.describe_place(the_place_err).unwrap(),
-                    reason
-                ),
-            );
+            // sometimes we deliberately don't store the name of a place when coming from a macro in
+            // another crate. We generally want to limit those diagnostics a little, to hide
+            // implementation details (such as those from pin!() or format!()). In that case show a
+            // slightly different error message, or none at all if something else happened. In other
+            // cases the message is likely not useful.
+            if let Some(place_name) = self.describe_place(the_place_err) {
+                err.span_label(
+                    *span,
+                    format!("calling `{place_name}` requires mutable binding due to {reason}"),
+                );
+            } else if span.from_expansion() {
+                err.span_label(
+                    *span,
+                    format!("a call in this macro requires a mutable binding due to {reason}",),
+                );
+            }
         }
     }
 
diff --git a/compiler/rustc_borrowck/src/diagnostics/region_name.rs b/compiler/rustc_borrowck/src/diagnostics/region_name.rs
index b08c10983bb..487f78058a8 100644
--- a/compiler/rustc_borrowck/src/diagnostics/region_name.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/region_name.rs
@@ -606,8 +606,8 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> {
         hir_args: &'hir hir::GenericArgs<'hir>,
         search_stack: &mut Vec<(Ty<'tcx>, &'hir hir::Ty<'hir>)>,
     ) -> Option<&'hir hir::Lifetime> {
-        for (kind, hir_arg) in iter::zip(args, hir_args.args) {
-            match (kind.unpack(), hir_arg) {
+        for (arg, hir_arg) in iter::zip(args, hir_args.args) {
+            match (arg.kind(), hir_arg) {
                 (GenericArgKind::Lifetime(r), hir::GenericArg::Lifetime(lt)) => {
                     if r.as_var() == needle_fr {
                         return Some(lt);
@@ -631,7 +631,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> {
                 ) => {
                     self.dcx().span_delayed_bug(
                         hir_arg.span(),
-                        format!("unmatched arg and hir arg: found {kind:?} vs {hir_arg:?}"),
+                        format!("unmatched arg and hir arg: found {arg:?} vs {hir_arg:?}"),
                     );
                 }
             }
@@ -997,7 +997,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> {
     ) -> bool {
         let tcx = self.infcx.tcx;
         ty.walk().any(|arg| {
-            if let ty::GenericArgKind::Type(ty) = arg.unpack()
+            if let ty::GenericArgKind::Type(ty) = arg.kind()
                 && let ty::Param(_) = ty.kind()
             {
                 clauses.iter().any(|pred| {
diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs
index 676cb618b72..2bd0ffd143b 100644
--- a/compiler/rustc_borrowck/src/lib.rs
+++ b/compiler/rustc_borrowck/src/lib.rs
@@ -40,9 +40,7 @@ use rustc_middle::ty::{
     self, ParamEnv, RegionVid, Ty, TyCtxt, TypeFoldable, TypeVisitable, TypingMode, fold_regions,
 };
 use rustc_middle::{bug, span_bug};
-use rustc_mir_dataflow::impls::{
-    EverInitializedPlaces, MaybeInitializedPlaces, MaybeUninitializedPlaces,
-};
+use rustc_mir_dataflow::impls::{EverInitializedPlaces, MaybeUninitializedPlaces};
 use rustc_mir_dataflow::move_paths::{
     InitIndex, InitLocation, LookupResult, MoveData, MovePathIndex,
 };
@@ -324,10 +322,6 @@ fn do_mir_borrowck<'tcx>(
 
     let move_data = MoveData::gather_moves(body, tcx, |_| true);
 
-    let flow_inits = MaybeInitializedPlaces::new(tcx, body, &move_data)
-        .iterate_to_fixpoint(tcx, body, Some("borrowck"))
-        .into_results_cursor(body);
-
     let locals_are_invalidated_at_exit = tcx.hir_body_owner_kind(def).is_fn_or_closure();
     let borrow_set = BorrowSet::build(tcx, body, locals_are_invalidated_at_exit, &move_data);
 
@@ -346,7 +340,6 @@ fn do_mir_borrowck<'tcx>(
         body,
         &promoted,
         &location_table,
-        flow_inits,
         &move_data,
         &borrow_set,
         consumer_options,
diff --git a/compiler/rustc_borrowck/src/nll.rs b/compiler/rustc_borrowck/src/nll.rs
index fe899bb054f..8664e99cae3 100644
--- a/compiler/rustc_borrowck/src/nll.rs
+++ b/compiler/rustc_borrowck/src/nll.rs
@@ -11,8 +11,6 @@ use rustc_middle::mir::pretty::{PrettyPrintMirOptions, dump_mir_with_options};
 use rustc_middle::mir::{Body, PassWhere, Promoted, create_dump_file, dump_enabled, dump_mir};
 use rustc_middle::ty::print::with_no_trimmed_paths;
 use rustc_middle::ty::{self, TyCtxt};
-use rustc_mir_dataflow::ResultsCursor;
-use rustc_mir_dataflow::impls::MaybeInitializedPlaces;
 use rustc_mir_dataflow::move_paths::MoveData;
 use rustc_mir_dataflow::points::DenseLocationMap;
 use rustc_session::config::MirIncludeSpans;
@@ -75,14 +73,13 @@ pub(crate) fn replace_regions_in_mir<'tcx>(
 /// Computes the (non-lexical) regions from the input MIR.
 ///
 /// This may result in errors being reported.
-pub(crate) fn compute_regions<'a, 'tcx>(
+pub(crate) fn compute_regions<'tcx>(
     root_cx: &mut BorrowCheckRootCtxt<'tcx>,
     infcx: &BorrowckInferCtxt<'tcx>,
     universal_regions: UniversalRegions<'tcx>,
     body: &Body<'tcx>,
     promoted: &IndexSlice<Promoted, Body<'tcx>>,
     location_table: &PoloniusLocationTable,
-    flow_inits: ResultsCursor<'a, 'tcx, MaybeInitializedPlaces<'a, 'tcx>>,
     move_data: &MoveData<'tcx>,
     borrow_set: &BorrowSet<'tcx>,
     consumer_options: Option<ConsumerOptions>,
@@ -112,7 +109,6 @@ pub(crate) fn compute_regions<'a, 'tcx>(
         location_table,
         borrow_set,
         &mut polonius_facts,
-        flow_inits,
         move_data,
         Rc::clone(&location_map),
     );
diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs
index b4ff3d66f3d..aa584713593 100644
--- a/compiler/rustc_borrowck/src/region_infer/mod.rs
+++ b/compiler/rustc_borrowck/src/region_infer/mod.rs
@@ -1,3 +1,4 @@
+use std::cell::OnceCell;
 use std::collections::VecDeque;
 use std::rc::Rc;
 
@@ -197,8 +198,8 @@ pub struct RegionInferenceContext<'tcx> {
 
     /// Reverse of the SCC constraint graph --  i.e., an edge `A -> B` exists if
     /// `B: A`. This is used to compute the universal regions that are required
-    /// to outlive a given SCC. Computed lazily.
-    rev_scc_graph: Option<ReverseSccGraph>,
+    /// to outlive a given SCC.
+    rev_scc_graph: OnceCell<ReverseSccGraph>,
 
     /// The "R0 member of [R1..Rn]" constraints, indexed by SCC.
     member_constraints: Rc<MemberConstraintSet<'tcx, ConstraintSccIndex>>,
@@ -502,7 +503,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
             constraint_graph,
             constraint_sccs,
             scc_annotations,
-            rev_scc_graph: None,
+            rev_scc_graph: OnceCell::new(),
             member_constraints,
             member_constraints_applied: Vec::new(),
             universe_causes,
@@ -809,9 +810,6 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         member_constraint_index: NllMemberConstraintIndex,
         choice_regions: &[ty::RegionVid],
     ) {
-        // Lazily compute the reverse graph, we'll need it later.
-        self.compute_reverse_scc_graph();
-
         // Create a mutable vector of the options. We'll try to winnow
         // them down.
         let mut choice_regions: Vec<ty::RegionVid> = choice_regions.to_vec();
@@ -849,7 +847,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         // R0`). Therefore, we need only keep an option `O` if `UB: O`
         // for all UB.
         let universal_region_relations = &self.universal_region_relations;
-        for ub in self.rev_scc_graph.as_ref().unwrap().upper_bounds(scc) {
+        for ub in self.reverse_scc_graph().upper_bounds(scc) {
             debug!(?ub);
             choice_regions.retain(|&o_r| universal_region_relations.outlives(ub, o_r));
         }
diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
index 25cbd579ea1..f0d72085c40 100644
--- a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
+++ b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
@@ -215,9 +215,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
                 // FIXME: We could probably compute the LUB if there is one.
                 let scc = self.constraint_sccs.scc(vid);
                 let upper_bounds: Vec<_> = self
-                    .rev_scc_graph
-                    .as_ref()
-                    .unwrap()
+                    .reverse_scc_graph()
                     .upper_bounds(scc)
                     .filter_map(|vid| self.definitions[vid].external_name)
                     .filter(|r| !r.is_static())
diff --git a/compiler/rustc_borrowck/src/region_infer/reverse_sccs.rs b/compiler/rustc_borrowck/src/region_infer/reverse_sccs.rs
index 8e04791461b..604265f8940 100644
--- a/compiler/rustc_borrowck/src/region_infer/reverse_sccs.rs
+++ b/compiler/rustc_borrowck/src/region_infer/reverse_sccs.rs
@@ -59,13 +59,10 @@ impl ReverseSccGraph {
 }
 
 impl RegionInferenceContext<'_> {
-    /// Compute the reverse SCC-based constraint graph (lazily).
-    pub(super) fn compute_reverse_scc_graph(&mut self) {
-        if self.rev_scc_graph.is_some() {
-            return;
-        }
-
-        self.rev_scc_graph =
-            Some(ReverseSccGraph::compute(&self.constraint_sccs, self.universal_regions()));
+    /// Return the reverse graph of the region SCCs, initialising it if needed.
+    pub(super) fn reverse_scc_graph(&self) -> &ReverseSccGraph {
+        self.rev_scc_graph.get_or_init(|| {
+            ReverseSccGraph::compute(&self.constraint_sccs, self.universal_regions())
+        })
     }
 }
diff --git a/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs
index 57516565147..a1c74672157 100644
--- a/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs
+++ b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs
@@ -148,7 +148,7 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
 
             let mut next_outlives_predicates = vec![];
             for (ty::OutlivesPredicate(k1, r2), constraint_category) in outlives_predicates {
-                match k1.unpack() {
+                match k1.kind() {
                     GenericArgKind::Lifetime(r1) => {
                         let r1_vid = self.to_region_vid(r1);
                         let r2_vid = self.to_region_vid(r2);
diff --git a/compiler/rustc_borrowck/src/type_check/input_output.rs b/compiler/rustc_borrowck/src/type_check/input_output.rs
index c6b29fe36fd..0c46e0c0c22 100644
--- a/compiler/rustc_borrowck/src/type_check/input_output.rs
+++ b/compiler/rustc_borrowck/src/type_check/input_output.rs
@@ -52,7 +52,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
             assert_matches!(
                 self.tcx().coroutine_kind(self.tcx().coroutine_for_closure(mir_def_id)),
                 Some(hir::CoroutineKind::Desugared(
-                    hir::CoroutineDesugaring::Async,
+                    hir::CoroutineDesugaring::Async | hir::CoroutineDesugaring::Gen,
                     hir::CoroutineSource::Closure
                 )),
                 "this needs to be modified if we're lowering non-async closures"
diff --git a/compiler/rustc_borrowck/src/type_check/liveness/mod.rs b/compiler/rustc_borrowck/src/type_check/liveness/mod.rs
index b7a21cf48c8..ca1b850f766 100644
--- a/compiler/rustc_borrowck/src/type_check/liveness/mod.rs
+++ b/compiler/rustc_borrowck/src/type_check/liveness/mod.rs
@@ -5,8 +5,6 @@ use rustc_middle::mir::{Body, Local, Location, SourceInfo};
 use rustc_middle::span_bug;
 use rustc_middle::ty::relate::Relate;
 use rustc_middle::ty::{GenericArgsRef, Region, RegionVid, Ty, TyCtxt, TypeVisitable};
-use rustc_mir_dataflow::ResultsCursor;
-use rustc_mir_dataflow::impls::MaybeInitializedPlaces;
 use rustc_mir_dataflow::move_paths::MoveData;
 use rustc_mir_dataflow::points::DenseLocationMap;
 use tracing::debug;
@@ -28,10 +26,9 @@ mod trace;
 ///
 /// N.B., this computation requires normalization; therefore, it must be
 /// performed before
-pub(super) fn generate<'a, 'tcx>(
+pub(super) fn generate<'tcx>(
     typeck: &mut TypeChecker<'_, 'tcx>,
     location_map: &DenseLocationMap,
-    flow_inits: ResultsCursor<'a, 'tcx, MaybeInitializedPlaces<'a, 'tcx>>,
     move_data: &MoveData<'tcx>,
 ) {
     debug!("liveness::generate");
@@ -58,7 +55,7 @@ pub(super) fn generate<'a, 'tcx>(
     let (relevant_live_locals, boring_locals) =
         compute_relevant_live_locals(typeck.tcx(), &free_regions, typeck.body);
 
-    trace::trace(typeck, location_map, flow_inits, move_data, relevant_live_locals, boring_locals);
+    trace::trace(typeck, location_map, move_data, relevant_live_locals, boring_locals);
 
     // Mark regions that should be live where they appear within rvalues or within a call: like
     // args, regions, and types.
diff --git a/compiler/rustc_borrowck/src/type_check/liveness/trace.rs b/compiler/rustc_borrowck/src/type_check/liveness/trace.rs
index 512288a0f7d..5d30fa71e92 100644
--- a/compiler/rustc_borrowck/src/type_check/liveness/trace.rs
+++ b/compiler/rustc_borrowck/src/type_check/liveness/trace.rs
@@ -7,10 +7,10 @@ use rustc_middle::mir::{BasicBlock, Body, ConstraintCategory, HasLocalDecls, Loc
 use rustc_middle::traits::query::DropckOutlivesResult;
 use rustc_middle::ty::relate::Relate;
 use rustc_middle::ty::{Ty, TyCtxt, TypeVisitable, TypeVisitableExt};
-use rustc_mir_dataflow::ResultsCursor;
 use rustc_mir_dataflow::impls::MaybeInitializedPlaces;
 use rustc_mir_dataflow::move_paths::{HasMoveData, MoveData, MovePathIndex};
 use rustc_mir_dataflow::points::{DenseLocationMap, PointIndex};
+use rustc_mir_dataflow::{Analysis, ResultsCursor};
 use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span};
 use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
 use rustc_trait_selection::traits::ObligationCtxt;
@@ -37,10 +37,9 @@ use crate::type_check::{NormalizeLocation, TypeChecker};
 /// DROP-LIVE set are to the liveness sets for regions found in the
 /// `dropck_outlives` result of the variable's type (in particular,
 /// this respects `#[may_dangle]` annotations).
-pub(super) fn trace<'a, 'tcx>(
+pub(super) fn trace<'tcx>(
     typeck: &mut TypeChecker<'_, 'tcx>,
     location_map: &DenseLocationMap,
-    flow_inits: ResultsCursor<'a, 'tcx, MaybeInitializedPlaces<'a, 'tcx>>,
     move_data: &MoveData<'tcx>,
     relevant_live_locals: Vec<Local>,
     boring_locals: Vec<Local>,
@@ -48,7 +47,7 @@ pub(super) fn trace<'a, 'tcx>(
     let local_use_map = &LocalUseMap::build(&relevant_live_locals, location_map, typeck.body);
     let cx = LivenessContext {
         typeck,
-        flow_inits,
+        flow_inits: None,
         location_map,
         local_use_map,
         move_data,
@@ -65,7 +64,7 @@ pub(super) fn trace<'a, 'tcx>(
 }
 
 /// Contextual state for the type-liveness coroutine.
-struct LivenessContext<'a, 'typeck, 'b, 'tcx> {
+struct LivenessContext<'a, 'typeck, 'tcx> {
     /// Current type-checker, giving us our inference context etc.
     ///
     /// This also stores the body we're currently analyzing.
@@ -81,8 +80,8 @@ struct LivenessContext<'a, 'typeck, 'b, 'tcx> {
     drop_data: FxIndexMap<Ty<'tcx>, DropData<'tcx>>,
 
     /// Results of dataflow tracking which variables (and paths) have been
-    /// initialized.
-    flow_inits: ResultsCursor<'b, 'tcx, MaybeInitializedPlaces<'b, 'tcx>>,
+    /// initialized. Computed lazily when needed by drop-liveness.
+    flow_inits: Option<ResultsCursor<'a, 'tcx, MaybeInitializedPlaces<'a, 'tcx>>>,
 
     /// Index indicating where each variable is assigned, used, or
     /// dropped.
@@ -94,8 +93,8 @@ struct DropData<'tcx> {
     region_constraint_data: Option<&'tcx QueryRegionConstraints<'tcx>>,
 }
 
-struct LivenessResults<'a, 'typeck, 'b, 'tcx> {
-    cx: LivenessContext<'a, 'typeck, 'b, 'tcx>,
+struct LivenessResults<'a, 'typeck, 'tcx> {
+    cx: LivenessContext<'a, 'typeck, 'tcx>,
 
     /// Set of points that define the current local.
     defs: DenseBitSet<PointIndex>,
@@ -116,8 +115,8 @@ struct LivenessResults<'a, 'typeck, 'b, 'tcx> {
     stack: Vec<PointIndex>,
 }
 
-impl<'a, 'typeck, 'b, 'tcx> LivenessResults<'a, 'typeck, 'b, 'tcx> {
-    fn new(cx: LivenessContext<'a, 'typeck, 'b, 'tcx>) -> Self {
+impl<'a, 'typeck, 'tcx> LivenessResults<'a, 'typeck, 'tcx> {
+    fn new(cx: LivenessContext<'a, 'typeck, 'tcx>) -> Self {
         let num_points = cx.location_map.num_points();
         LivenessResults {
             cx,
@@ -459,20 +458,56 @@ impl<'a, 'typeck, 'b, 'tcx> LivenessResults<'a, 'typeck, 'b, 'tcx> {
     }
 }
 
-impl<'tcx> LivenessContext<'_, '_, '_, 'tcx> {
+impl<'a, 'typeck, 'tcx> LivenessContext<'a, 'typeck, 'tcx> {
+    /// Computes the `MaybeInitializedPlaces` dataflow analysis if it hasn't been done already.
+    ///
+    /// In practice, the results of this dataflow analysis are rarely needed but can be expensive to
+    /// compute on big functions, so we compute them lazily as a fast path when:
+    /// - there are relevant live locals
+    /// - there are drop points for these relevant live locals.
+    ///
+    /// This happens as part of the drop-liveness computation: it's the only place checking for
+    /// maybe-initializedness of `MovePathIndex`es.
+    fn flow_inits(&mut self) -> &mut ResultsCursor<'a, 'tcx, MaybeInitializedPlaces<'a, 'tcx>> {
+        self.flow_inits.get_or_insert_with(|| {
+            let tcx = self.typeck.tcx();
+            let body = self.typeck.body;
+            // FIXME: reduce the `MaybeInitializedPlaces` domain to the useful `MovePath`s.
+            //
+            // This dataflow analysis computes maybe-initializedness of all move paths, which
+            // explains why it can be expensive on big functions. But this data is only used in
+            // drop-liveness. Therefore, most of the move paths computed here are ultimately unused,
+            // even if the results are computed lazily and "no relevant live locals with drop
+            // points" is the common case.
+            //
+            // So we only need the ones for 1) relevant live locals 2) that have drop points. That's
+            // a much, much smaller domain: in our benchmarks, when it's not zero (the most likely
+            // case), there are a few dozens compared to e.g. thousands or tens of thousands of
+            // locals and move paths.
+            let flow_inits = MaybeInitializedPlaces::new(tcx, body, self.move_data)
+                .iterate_to_fixpoint(tcx, body, Some("borrowck"))
+                .into_results_cursor(body);
+            flow_inits
+        })
+    }
+}
+
+impl<'tcx> LivenessContext<'_, '_, 'tcx> {
     fn body(&self) -> &Body<'tcx> {
         self.typeck.body
     }
+
     /// Returns `true` if the local variable (or some part of it) is initialized at the current
     /// cursor position. Callers should call one of the `seek` methods immediately before to point
     /// the cursor to the desired location.
-    fn initialized_at_curr_loc(&self, mpi: MovePathIndex) -> bool {
-        let state = self.flow_inits.get();
+    fn initialized_at_curr_loc(&mut self, mpi: MovePathIndex) -> bool {
+        let flow_inits = self.flow_inits();
+        let state = flow_inits.get();
         if state.contains(mpi) {
             return true;
         }
 
-        let move_paths = &self.flow_inits.analysis().move_data().move_paths;
+        let move_paths = &flow_inits.analysis().move_data().move_paths;
         move_paths[mpi].find_descendant(move_paths, |mpi| state.contains(mpi)).is_some()
     }
 
@@ -481,7 +516,8 @@ impl<'tcx> LivenessContext<'_, '_, '_, 'tcx> {
     /// DROP of some local variable will have an effect -- note that
     /// drops, as they may unwind, are always terminators.
     fn initialized_at_terminator(&mut self, block: BasicBlock, mpi: MovePathIndex) -> bool {
-        self.flow_inits.seek_before_primary_effect(self.body().terminator_loc(block));
+        let terminator_location = self.body().terminator_loc(block);
+        self.flow_inits().seek_before_primary_effect(terminator_location);
         self.initialized_at_curr_loc(mpi)
     }
 
@@ -491,7 +527,8 @@ impl<'tcx> LivenessContext<'_, '_, '_, 'tcx> {
     /// **Warning:** Does not account for the result of `Call`
     /// instructions.
     fn initialized_at_exit(&mut self, block: BasicBlock, mpi: MovePathIndex) -> bool {
-        self.flow_inits.seek_after_primary_effect(self.body().terminator_loc(block));
+        let terminator_location = self.body().terminator_loc(block);
+        self.flow_inits().seek_after_primary_effect(terminator_location);
         self.initialized_at_curr_loc(mpi)
     }
 
diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs
index 8c512257120..4f5baeff7c3 100644
--- a/compiler/rustc_borrowck/src/type_check/mod.rs
+++ b/compiler/rustc_borrowck/src/type_check/mod.rs
@@ -30,8 +30,6 @@ use rustc_middle::ty::{
     TypeVisitableExt, UserArgs, UserTypeAnnotationIndex, fold_regions,
 };
 use rustc_middle::{bug, span_bug};
-use rustc_mir_dataflow::ResultsCursor;
-use rustc_mir_dataflow::impls::MaybeInitializedPlaces;
 use rustc_mir_dataflow::move_paths::MoveData;
 use rustc_mir_dataflow::points::DenseLocationMap;
 use rustc_span::def_id::CRATE_DEF_ID;
@@ -97,10 +95,9 @@ mod relate_tys;
 /// - `location_table` -- for datalog polonius, the map between `Location`s and `RichLocation`s
 /// - `borrow_set` -- information about borrows occurring in `body`
 /// - `polonius_facts` -- when using Polonius, this is the generated set of Polonius facts
-/// - `flow_inits` -- results of a maybe-init dataflow analysis
 /// - `move_data` -- move-data constructed when performing the maybe-init dataflow analysis
 /// - `location_map` -- map between MIR `Location` and `PointIndex`
-pub(crate) fn type_check<'a, 'tcx>(
+pub(crate) fn type_check<'tcx>(
     root_cx: &mut BorrowCheckRootCtxt<'tcx>,
     infcx: &BorrowckInferCtxt<'tcx>,
     body: &Body<'tcx>,
@@ -109,7 +106,6 @@ pub(crate) fn type_check<'a, 'tcx>(
     location_table: &PoloniusLocationTable,
     borrow_set: &BorrowSet<'tcx>,
     polonius_facts: &mut Option<PoloniusFacts>,
-    flow_inits: ResultsCursor<'a, 'tcx, MaybeInitializedPlaces<'a, 'tcx>>,
     move_data: &MoveData<'tcx>,
     location_map: Rc<DenseLocationMap>,
 ) -> MirTypeckResults<'tcx> {
@@ -167,7 +163,7 @@ pub(crate) fn type_check<'a, 'tcx>(
     typeck.equate_inputs_and_outputs(&normalized_inputs_and_output);
     typeck.check_signature_annotation();
 
-    liveness::generate(&mut typeck, &location_map, flow_inits, move_data);
+    liveness::generate(&mut typeck, &location_map, move_data);
 
     let opaque_type_values =
         opaque_types::take_opaques_and_register_member_constraints(&mut typeck);
@@ -474,17 +470,18 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
             let projected_ty = curr_projected_ty.projection_ty_core(
                 tcx,
                 proj,
-                |this, field, ()| {
-                    let ty = this.field_ty(tcx, field);
-                    self.structurally_resolve(ty, locations)
-                },
-                |_, _| unreachable!(),
+                |ty| self.structurally_resolve(ty, locations),
+                |ty, variant_index, field, ()| PlaceTy::field_ty(tcx, ty, variant_index, field),
+                |_| unreachable!(),
             );
             curr_projected_ty = projected_ty;
         }
         trace!(?curr_projected_ty);
 
-        let ty = curr_projected_ty.ty;
+        // Need to renormalize `a` as typecheck may have failed to normalize
+        // higher-ranked aliases if normalization was ambiguous due to inference.
+        let a = self.normalize(a, locations);
+        let ty = self.normalize(curr_projected_ty.ty, locations);
         self.relate_types(ty, v.xform(ty::Contravariant), a, locations, category)?;
 
         Ok(())
@@ -1852,7 +1849,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
             | ProjectionElem::Downcast(..) => {}
             ProjectionElem::Field(field, fty) => {
                 let fty = self.normalize(fty, location);
-                let ty = base_ty.field_ty(tcx, field);
+                let ty = PlaceTy::field_ty(tcx, base_ty.ty, base_ty.variant_index, field);
                 let ty = self.normalize(ty, location);
                 debug!(?fty, ?ty);
 
diff --git a/compiler/rustc_borrowck/src/type_check/opaque_types.rs b/compiler/rustc_borrowck/src/type_check/opaque_types.rs
index 341c50c37f6..5a422483eef 100644
--- a/compiler/rustc_borrowck/src/type_check/opaque_types.rs
+++ b/compiler/rustc_borrowck/src/type_check/opaque_types.rs
@@ -221,7 +221,7 @@ fn register_member_constraints<'tcx>(
         .iter()
         .enumerate()
         .filter(|(i, _)| variances[*i] == ty::Invariant)
-        .filter_map(|(_, arg)| match arg.unpack() {
+        .filter_map(|(_, arg)| match arg.kind() {
             GenericArgKind::Lifetime(r) => Some(typeck.to_region_vid(r)),
             GenericArgKind::Type(_) | GenericArgKind::Const(_) => None,
         })
diff --git a/compiler/rustc_builtin_macros/Cargo.toml b/compiler/rustc_builtin_macros/Cargo.toml
index 5c1ae90f729..4c1264c6f1c 100644
--- a/compiler/rustc_builtin_macros/Cargo.toml
+++ b/compiler/rustc_builtin_macros/Cargo.toml
@@ -24,6 +24,9 @@ rustc_lint_defs = { path = "../rustc_lint_defs" }
 rustc_macros = { path = "../rustc_macros" }
 rustc_parse = { path = "../rustc_parse" }
 rustc_parse_format = { path = "../rustc_parse_format" }
+# We must use the proc_macro version that we will compile proc-macros against,
+# not the one from our own sysroot.
+rustc_proc_macro = { path = "../rustc_proc_macro" }
 rustc_session = { path = "../rustc_session" }
 rustc_span = { path = "../rustc_span" }
 rustc_target = { path = "../rustc_target" }
diff --git a/compiler/rustc_builtin_macros/messages.ftl b/compiler/rustc_builtin_macros/messages.ftl
index 73be954cefd..d32e6f1558e 100644
--- a/compiler/rustc_builtin_macros/messages.ftl
+++ b/compiler/rustc_builtin_macros/messages.ftl
@@ -1,6 +1,11 @@
 builtin_macros_alloc_error_must_be_fn = alloc_error_handler must be a function
 builtin_macros_alloc_must_statics = allocators must be statics
 
+builtin_macros_asm_attribute_not_supported =
+    this attribute is not supported on assembly
+builtin_macros_asm_cfg =
+    the `#[cfg(/* ... */)]` and `#[cfg_attr(/* ... */)]` attributes on assembly are unstable
+
 builtin_macros_asm_clobber_abi = clobber_abi
 builtin_macros_asm_clobber_no_reg = asm with `clobber_abi` must specify explicit registers for outputs
 builtin_macros_asm_clobber_outputs = generic outputs
@@ -9,17 +14,6 @@ builtin_macros_asm_duplicate_arg = duplicate argument named `{$name}`
     .label = previously here
     .arg = duplicate argument
 
-builtin_macros_asm_expected_comma = expected token: `,`
-    .label = expected `,`
-
-builtin_macros_asm_expected_other = expected operand, {$is_inline_asm ->
-    [false] options
-    *[true] clobber_abi, options
-    }, or additional template string
-
-builtin_macros_asm_expected_string_literal = expected string literal
-    .label = not a string literal
-
 builtin_macros_asm_explicit_register_name = explicit register arguments cannot have names
 
 builtin_macros_asm_mayunwind = asm labels are not allowed with the `may_unwind` option
@@ -45,17 +39,8 @@ builtin_macros_asm_pure_combine = the `pure` option must be combined with either
 
 builtin_macros_asm_pure_no_output = asm with the `pure` option must have at least one output
 
-builtin_macros_asm_requires_template = requires at least a template string argument
-
-builtin_macros_asm_sym_no_path = expected a path for argument to `sym`
-
-builtin_macros_asm_underscore_input = _ cannot be used for input operands
-
 builtin_macros_asm_unsupported_clobber_abi = `clobber_abi` cannot be used with `{$macro_name}!`
 
-builtin_macros_asm_unsupported_operand = the `{$symbol}` operand cannot be used with `{$macro_name}!`
-    .label = the `{$symbol}` operand is not meaningful for global-scoped inline assembly, remove it
-
 builtin_macros_asm_unsupported_option = the `{$symbol}` option cannot be used with `{$macro_name}!`
     .label = the `{$symbol}` option is not meaningful for global-scoped inline assembly
     .suggestion = remove this option
@@ -71,7 +56,6 @@ builtin_macros_assert_requires_expression = macro requires an expression as an a
 
 builtin_macros_autodiff = autodiff must be applied to function
 builtin_macros_autodiff_missing_config = autodiff requires at least a name and mode
-builtin_macros_autodiff_mode = unknown Mode: `{$mode}`. Use `Forward` or `Reverse`
 builtin_macros_autodiff_mode_activity = {$act} can not be used in {$mode} Mode
 builtin_macros_autodiff_not_build = this rustc version does not support autodiff
 builtin_macros_autodiff_number_activities = expected {$expected} activities, but found {$found}
@@ -162,7 +146,10 @@ builtin_macros_expected_comma_in_list = expected token: `,`
 
 builtin_macros_expected_one_cfg_pattern = expected 1 cfg-pattern
 
-builtin_macros_expected_register_class_or_explicit_register = expected register class or explicit register
+builtin_macros_expected_other = expected operand, {$is_inline_asm ->
+    [false] options
+    *[true] clobber_abi, options
+    }, or additional template string
 
 builtin_macros_export_macro_rules = cannot export macro_rules! macros from a `proc-macro` crate type currently
 
@@ -255,8 +242,6 @@ builtin_macros_no_default_variant = `#[derive(Default)]` on enum with no `#[defa
     .label = this enum needs a unit variant marked with `#[default]`
     .suggestion = make this unit variant default by placing `#[default]` on it
 
-builtin_macros_non_abi = at least one abi must be provided as an argument to `clobber_abi`
-
 builtin_macros_non_exhaustive_default = default variant must be exhaustive
     .label = declared `#[non_exhaustive]` here
     .help = consider a manual implementation of `Default`
diff --git a/compiler/rustc_builtin_macros/src/asm.rs b/compiler/rustc_builtin_macros/src/asm.rs
index 62ee71fecc2..1fb99817222 100644
--- a/compiler/rustc_builtin_macros/src/asm.rs
+++ b/compiler/rustc_builtin_macros/src/asm.rs
@@ -1,4 +1,3 @@
-use ast::token::IdentIsRaw;
 use lint::BuiltinLintDiag;
 use rustc_ast::ptr::P;
 use rustc_ast::tokenstream::TokenStream;
@@ -7,39 +6,16 @@ use rustc_data_structures::fx::{FxHashMap, FxIndexMap};
 use rustc_errors::PResult;
 use rustc_expand::base::*;
 use rustc_index::bit_set::GrowableBitSet;
-use rustc_parse::exp;
-use rustc_parse::parser::{ExpKeywordPair, Parser};
+use rustc_parse::parser::asm::*;
 use rustc_session::lint;
-use rustc_span::{ErrorGuaranteed, InnerSpan, Span, Symbol, kw};
+use rustc_session::parse::feature_err;
+use rustc_span::{ErrorGuaranteed, InnerSpan, Span, Symbol, sym};
 use rustc_target::asm::InlineAsmArch;
 use smallvec::smallvec;
 use {rustc_ast as ast, rustc_parse_format as parse};
 
-use crate::errors;
 use crate::util::{ExprToSpannedString, expr_to_spanned_string};
-
-/// An argument to one of the `asm!` macros. The argument is syntactically valid, but is otherwise
-/// not validated at all.
-pub struct AsmArg {
-    pub kind: AsmArgKind,
-    pub span: Span,
-}
-
-pub enum AsmArgKind {
-    Template(P<ast::Expr>),
-    Operand(Option<Symbol>, ast::InlineAsmOperand),
-    Options(Vec<AsmOption>),
-    ClobberAbi(Vec<(Symbol, Span)>),
-}
-
-pub struct AsmOption {
-    pub symbol: Symbol,
-    pub span: Span,
-    // A bitset, with only the bit for this option's symbol set.
-    pub options: ast::InlineAsmOptions,
-    // Used when suggesting to remove an option.
-    pub span_with_comma: Span,
-}
+use crate::{errors, fluent_generated as fluent};
 
 /// Validated assembly arguments, ready for macro expansion.
 struct ValidatedAsmArgs {
@@ -52,215 +28,6 @@ struct ValidatedAsmArgs {
     pub options_spans: Vec<Span>,
 }
 
-/// Used for better error messages when operand types are used that are not
-/// supported by the current macro (e.g. `in` or `out` for `global_asm!`)
-///
-/// returns
-///
-/// - `Ok(true)` if the current token matches the keyword, and was expected
-/// - `Ok(false)` if the current token does not match the keyword
-/// - `Err(_)` if the current token matches the keyword, but was not expected
-fn eat_operand_keyword<'a>(
-    p: &mut Parser<'a>,
-    exp: ExpKeywordPair,
-    asm_macro: AsmMacro,
-) -> PResult<'a, bool> {
-    if matches!(asm_macro, AsmMacro::Asm) {
-        Ok(p.eat_keyword(exp))
-    } else {
-        let span = p.token.span;
-        if p.eat_keyword_noexpect(exp.kw) {
-            // in gets printed as `r#in` otherwise
-            let symbol = if exp.kw == kw::In { "in" } else { exp.kw.as_str() };
-            Err(p.dcx().create_err(errors::AsmUnsupportedOperand {
-                span,
-                symbol,
-                macro_name: asm_macro.macro_name(),
-            }))
-        } else {
-            Ok(false)
-        }
-    }
-}
-
-fn parse_asm_operand<'a>(
-    p: &mut Parser<'a>,
-    asm_macro: AsmMacro,
-) -> PResult<'a, Option<ast::InlineAsmOperand>> {
-    let dcx = p.dcx();
-
-    Ok(Some(if eat_operand_keyword(p, exp!(In), asm_macro)? {
-        let reg = parse_reg(p)?;
-        if p.eat_keyword(exp!(Underscore)) {
-            let err = dcx.create_err(errors::AsmUnderscoreInput { span: p.token.span });
-            return Err(err);
-        }
-        let expr = p.parse_expr()?;
-        ast::InlineAsmOperand::In { reg, expr }
-    } else if eat_operand_keyword(p, exp!(Out), asm_macro)? {
-        let reg = parse_reg(p)?;
-        let expr = if p.eat_keyword(exp!(Underscore)) { None } else { Some(p.parse_expr()?) };
-        ast::InlineAsmOperand::Out { reg, expr, late: false }
-    } else if eat_operand_keyword(p, exp!(Lateout), asm_macro)? {
-        let reg = parse_reg(p)?;
-        let expr = if p.eat_keyword(exp!(Underscore)) { None } else { Some(p.parse_expr()?) };
-        ast::InlineAsmOperand::Out { reg, expr, late: true }
-    } else if eat_operand_keyword(p, exp!(Inout), asm_macro)? {
-        let reg = parse_reg(p)?;
-        if p.eat_keyword(exp!(Underscore)) {
-            let err = dcx.create_err(errors::AsmUnderscoreInput { span: p.token.span });
-            return Err(err);
-        }
-        let expr = p.parse_expr()?;
-        if p.eat(exp!(FatArrow)) {
-            let out_expr =
-                if p.eat_keyword(exp!(Underscore)) { None } else { Some(p.parse_expr()?) };
-            ast::InlineAsmOperand::SplitInOut { reg, in_expr: expr, out_expr, late: false }
-        } else {
-            ast::InlineAsmOperand::InOut { reg, expr, late: false }
-        }
-    } else if eat_operand_keyword(p, exp!(Inlateout), asm_macro)? {
-        let reg = parse_reg(p)?;
-        if p.eat_keyword(exp!(Underscore)) {
-            let err = dcx.create_err(errors::AsmUnderscoreInput { span: p.token.span });
-            return Err(err);
-        }
-        let expr = p.parse_expr()?;
-        if p.eat(exp!(FatArrow)) {
-            let out_expr =
-                if p.eat_keyword(exp!(Underscore)) { None } else { Some(p.parse_expr()?) };
-            ast::InlineAsmOperand::SplitInOut { reg, in_expr: expr, out_expr, late: true }
-        } else {
-            ast::InlineAsmOperand::InOut { reg, expr, late: true }
-        }
-    } else if eat_operand_keyword(p, exp!(Label), asm_macro)? {
-        let block = p.parse_block()?;
-        ast::InlineAsmOperand::Label { block }
-    } else if p.eat_keyword(exp!(Const)) {
-        let anon_const = p.parse_expr_anon_const()?;
-        ast::InlineAsmOperand::Const { anon_const }
-    } else if p.eat_keyword(exp!(Sym)) {
-        let expr = p.parse_expr()?;
-        let ast::ExprKind::Path(qself, path) = &expr.kind else {
-            let err = dcx.create_err(errors::AsmSymNoPath { span: expr.span });
-            return Err(err);
-        };
-        let sym =
-            ast::InlineAsmSym { id: ast::DUMMY_NODE_ID, qself: qself.clone(), path: path.clone() };
-        ast::InlineAsmOperand::Sym { sym }
-    } else {
-        return Ok(None);
-    }))
-}
-
-// Public for rustfmt.
-pub fn parse_asm_args<'a>(
-    p: &mut Parser<'a>,
-    sp: Span,
-    asm_macro: AsmMacro,
-) -> PResult<'a, Vec<AsmArg>> {
-    let dcx = p.dcx();
-
-    if p.token == token::Eof {
-        return Err(dcx.create_err(errors::AsmRequiresTemplate { span: sp }));
-    }
-
-    let mut args = Vec::new();
-
-    let first_template = p.parse_expr()?;
-    args.push(AsmArg { span: first_template.span, kind: AsmArgKind::Template(first_template) });
-
-    let mut allow_templates = true;
-
-    while p.token != token::Eof {
-        if !p.eat(exp!(Comma)) {
-            if allow_templates {
-                // After a template string, we always expect *only* a comma...
-                return Err(dcx.create_err(errors::AsmExpectedComma { span: p.token.span }));
-            } else {
-                // ...after that delegate to `expect` to also include the other expected tokens.
-                return Err(p.expect(exp!(Comma)).err().unwrap());
-            }
-        }
-
-        // Accept trailing commas.
-        if p.token == token::Eof {
-            break;
-        }
-
-        let span_start = p.token.span;
-
-        // Parse `clobber_abi`.
-        if p.eat_keyword(exp!(ClobberAbi)) {
-            allow_templates = false;
-
-            args.push(AsmArg {
-                kind: AsmArgKind::ClobberAbi(parse_clobber_abi(p)?),
-                span: span_start.to(p.prev_token.span),
-            });
-
-            continue;
-        }
-
-        // Parse `options`.
-        if p.eat_keyword(exp!(Options)) {
-            allow_templates = false;
-
-            args.push(AsmArg {
-                kind: AsmArgKind::Options(parse_options(p, asm_macro)?),
-                span: span_start.to(p.prev_token.span),
-            });
-
-            continue;
-        }
-
-        // Parse operand names.
-        let name = if p.token.is_ident() && p.look_ahead(1, |t| *t == token::Eq) {
-            let (ident, _) = p.token.ident().unwrap();
-            p.bump();
-            p.expect(exp!(Eq))?;
-            allow_templates = false;
-            Some(ident.name)
-        } else {
-            None
-        };
-
-        if let Some(op) = parse_asm_operand(p, asm_macro)? {
-            allow_templates = false;
-
-            args.push(AsmArg {
-                span: span_start.to(p.prev_token.span),
-                kind: AsmArgKind::Operand(name, op),
-            });
-        } else if allow_templates {
-            let template = p.parse_expr()?;
-            // If it can't possibly expand to a string, provide diagnostics here to include other
-            // things it could have been.
-            match template.kind {
-                ast::ExprKind::Lit(token_lit)
-                    if matches!(
-                        token_lit.kind,
-                        token::LitKind::Str | token::LitKind::StrRaw(_)
-                    ) => {}
-                ast::ExprKind::MacCall(..) => {}
-                _ => {
-                    let err = dcx.create_err(errors::AsmExpectedOther {
-                        span: template.span,
-                        is_inline_asm: matches!(asm_macro, AsmMacro::Asm),
-                    });
-                    return Err(err);
-                }
-            }
-
-            args.push(AsmArg { span: template.span, kind: AsmArgKind::Template(template) });
-        } else {
-            p.unexpected_any()?
-        }
-    }
-
-    Ok(args)
-}
-
 fn parse_args<'a>(
     ecx: &ExtCtxt<'a>,
     sp: Span,
@@ -278,6 +45,13 @@ fn validate_asm_args<'a>(
 ) -> PResult<'a, ValidatedAsmArgs> {
     let dcx = ecx.dcx();
 
+    let strip_unconfigured = rustc_expand::config::StripUnconfigured {
+        sess: ecx.sess,
+        features: Some(ecx.ecfg.features),
+        config_tokens: false,
+        lint_node_id: ecx.current_expansion.lint_node_id,
+    };
+
     let mut validated = ValidatedAsmArgs {
         templates: vec![],
         operands: vec![],
@@ -291,6 +65,26 @@ fn validate_asm_args<'a>(
     let mut allow_templates = true;
 
     for arg in args {
+        for attr in arg.attributes.0.iter() {
+            match attr.name() {
+                Some(sym::cfg | sym::cfg_attr) => {
+                    if !ecx.ecfg.features.asm_cfg() {
+                        let span = attr.span();
+                        feature_err(ecx.sess, sym::asm_cfg, span, fluent::builtin_macros_asm_cfg)
+                            .emit();
+                    }
+                }
+                _ => {
+                    ecx.dcx().emit_err(errors::AsmAttributeNotSupported { span: attr.span() });
+                }
+            }
+        }
+
+        // Skip arguments that are configured out.
+        if ecx.ecfg.features.asm_cfg() && strip_unconfigured.configure(arg.attributes).is_none() {
+            continue;
+        }
+
         match arg.kind {
             AsmArgKind::Template(template) => {
                 // The error for the first template is delayed.
@@ -479,103 +273,6 @@ fn validate_asm_args<'a>(
     Ok(validated)
 }
 
-fn parse_options<'a>(p: &mut Parser<'a>, asm_macro: AsmMacro) -> PResult<'a, Vec<AsmOption>> {
-    p.expect(exp!(OpenParen))?;
-
-    let mut asm_options = Vec::new();
-
-    while !p.eat(exp!(CloseParen)) {
-        const OPTIONS: [(ExpKeywordPair, ast::InlineAsmOptions); ast::InlineAsmOptions::COUNT] = [
-            (exp!(Pure), ast::InlineAsmOptions::PURE),
-            (exp!(Nomem), ast::InlineAsmOptions::NOMEM),
-            (exp!(Readonly), ast::InlineAsmOptions::READONLY),
-            (exp!(PreservesFlags), ast::InlineAsmOptions::PRESERVES_FLAGS),
-            (exp!(Noreturn), ast::InlineAsmOptions::NORETURN),
-            (exp!(Nostack), ast::InlineAsmOptions::NOSTACK),
-            (exp!(MayUnwind), ast::InlineAsmOptions::MAY_UNWIND),
-            (exp!(AttSyntax), ast::InlineAsmOptions::ATT_SYNTAX),
-            (exp!(Raw), ast::InlineAsmOptions::RAW),
-        ];
-
-        'blk: {
-            for (exp, options) in OPTIONS {
-                // Gives a more accurate list of expected next tokens.
-                let kw_matched = if asm_macro.is_supported_option(options) {
-                    p.eat_keyword(exp)
-                } else {
-                    p.eat_keyword_noexpect(exp.kw)
-                };
-
-                if kw_matched {
-                    let span = p.prev_token.span;
-                    let span_with_comma =
-                        if p.token == token::Comma { span.to(p.token.span) } else { span };
-
-                    asm_options.push(AsmOption { symbol: exp.kw, span, options, span_with_comma });
-                    break 'blk;
-                }
-            }
-
-            return p.unexpected_any();
-        }
-
-        // Allow trailing commas.
-        if p.eat(exp!(CloseParen)) {
-            break;
-        }
-        p.expect(exp!(Comma))?;
-    }
-
-    Ok(asm_options)
-}
-
-fn parse_clobber_abi<'a>(p: &mut Parser<'a>) -> PResult<'a, Vec<(Symbol, Span)>> {
-    p.expect(exp!(OpenParen))?;
-
-    if p.eat(exp!(CloseParen)) {
-        return Err(p.dcx().create_err(errors::NonABI { span: p.token.span }));
-    }
-
-    let mut new_abis = Vec::new();
-    while !p.eat(exp!(CloseParen)) {
-        match p.parse_str_lit() {
-            Ok(str_lit) => {
-                new_abis.push((str_lit.symbol_unescaped, str_lit.span));
-            }
-            Err(opt_lit) => {
-                let span = opt_lit.map_or(p.token.span, |lit| lit.span);
-                return Err(p.dcx().create_err(errors::AsmExpectedStringLiteral { span }));
-            }
-        };
-
-        // Allow trailing commas
-        if p.eat(exp!(CloseParen)) {
-            break;
-        }
-        p.expect(exp!(Comma))?;
-    }
-
-    Ok(new_abis)
-}
-
-fn parse_reg<'a>(p: &mut Parser<'a>) -> PResult<'a, ast::InlineAsmRegOrRegClass> {
-    p.expect(exp!(OpenParen))?;
-    let result = match p.token.uninterpolate().kind {
-        token::Ident(name, IdentIsRaw::No) => ast::InlineAsmRegOrRegClass::RegClass(name),
-        token::Literal(token::Lit { kind: token::LitKind::Str, symbol, suffix: _ }) => {
-            ast::InlineAsmRegOrRegClass::Reg(symbol)
-        }
-        _ => {
-            return Err(p.dcx().create_err(errors::ExpectedRegisterClassOrExplicitRegister {
-                span: p.token.span,
-            }));
-        }
-    };
-    p.bump();
-    p.expect(exp!(CloseParen))?;
-    Ok(result)
-}
-
 fn expand_preparsed_asm(
     ecx: &mut ExtCtxt<'_>,
     asm_macro: AsmMacro,
diff --git a/compiler/rustc_builtin_macros/src/autodiff.rs b/compiler/rustc_builtin_macros/src/autodiff.rs
index 1ff4fc6aaab..dc3bb8ab52a 100644
--- a/compiler/rustc_builtin_macros/src/autodiff.rs
+++ b/compiler/rustc_builtin_macros/src/autodiff.rs
@@ -86,27 +86,23 @@ mod llvm_enzyme {
         ecx: &mut ExtCtxt<'_>,
         meta_item: &ThinVec<MetaItemInner>,
         has_ret: bool,
+        mode: DiffMode,
     ) -> AutoDiffAttrs {
         let dcx = ecx.sess.dcx();
-        let mode = name(&meta_item[1]);
-        let Ok(mode) = DiffMode::from_str(&mode) else {
-            dcx.emit_err(errors::AutoDiffInvalidMode { span: meta_item[1].span(), mode });
-            return AutoDiffAttrs::error();
-        };
 
         // Now we check, whether the user wants autodiff in batch/vector mode, or scalar mode.
         // If he doesn't specify an integer (=width), we default to scalar mode, thus width=1.
-        let mut first_activity = 2;
+        let mut first_activity = 1;
 
-        let width = if let [_, _, x, ..] = &meta_item[..]
+        let width = if let [_, x, ..] = &meta_item[..]
             && let Some(x) = width(x)
         {
-            first_activity = 3;
+            first_activity = 2;
             match x.try_into() {
                 Ok(x) => x,
                 Err(_) => {
                     dcx.emit_err(errors::AutoDiffInvalidWidth {
-                        span: meta_item[2].span(),
+                        span: meta_item[1].span(),
                         width: x,
                     });
                     return AutoDiffAttrs::error();
@@ -165,6 +161,24 @@ mod llvm_enzyme {
         ts.push(TokenTree::Token(comma.clone(), Spacing::Alone));
     }
 
+    pub(crate) fn expand_forward(
+        ecx: &mut ExtCtxt<'_>,
+        expand_span: Span,
+        meta_item: &ast::MetaItem,
+        item: Annotatable,
+    ) -> Vec<Annotatable> {
+        expand_with_mode(ecx, expand_span, meta_item, item, DiffMode::Forward)
+    }
+
+    pub(crate) fn expand_reverse(
+        ecx: &mut ExtCtxt<'_>,
+        expand_span: Span,
+        meta_item: &ast::MetaItem,
+        item: Annotatable,
+    ) -> Vec<Annotatable> {
+        expand_with_mode(ecx, expand_span, meta_item, item, DiffMode::Reverse)
+    }
+
     /// We expand the autodiff macro to generate a new placeholder function which passes
     /// type-checking and can be called by users. The function body of the placeholder function will
     /// later be replaced on LLVM-IR level, so the design of the body is less important and for now
@@ -198,11 +212,12 @@ mod llvm_enzyme {
     /// ```
     /// FIXME(ZuseZ4): Once autodiff is enabled by default, make this a doc comment which is checked
     /// in CI.
-    pub(crate) fn expand(
+    pub(crate) fn expand_with_mode(
         ecx: &mut ExtCtxt<'_>,
         expand_span: Span,
         meta_item: &ast::MetaItem,
         mut item: Annotatable,
+        mode: DiffMode,
     ) -> Vec<Annotatable> {
         if cfg!(not(llvm_enzyme)) {
             ecx.sess.dcx().emit_err(errors::AutoDiffSupportNotBuild { span: meta_item.span });
@@ -245,29 +260,41 @@ mod llvm_enzyme {
         // create TokenStream from vec elemtents:
         // meta_item doesn't have a .tokens field
         let mut ts: Vec<TokenTree> = vec![];
-        if meta_item_vec.len() < 2 {
-            // At the bare minimum, we need a fnc name and a mode, even for a dummy function with no
-            // input and output args.
+        if meta_item_vec.len() < 1 {
+            // At the bare minimum, we need a fnc name.
             dcx.emit_err(errors::AutoDiffMissingConfig { span: item.span() });
             return vec![item];
         }
 
-        meta_item_inner_to_ts(&meta_item_vec[1], &mut ts);
+        let mode_symbol = match mode {
+            DiffMode::Forward => sym::Forward,
+            DiffMode::Reverse => sym::Reverse,
+            _ => unreachable!("Unsupported mode: {:?}", mode),
+        };
+
+        // Insert mode token
+        let mode_token = Token::new(TokenKind::Ident(mode_symbol, false.into()), Span::default());
+        ts.insert(0, TokenTree::Token(mode_token, Spacing::Joint));
+        ts.insert(
+            1,
+            TokenTree::Token(Token::new(TokenKind::Comma, Span::default()), Spacing::Alone),
+        );
 
         // Now, if the user gave a width (vector aka batch-mode ad), then we copy it.
         // If it is not given, we default to 1 (scalar mode).
         let start_position;
         let kind: LitKind = LitKind::Integer;
         let symbol;
-        if meta_item_vec.len() >= 3
-            && let Some(width) = width(&meta_item_vec[2])
+        if meta_item_vec.len() >= 2
+            && let Some(width) = width(&meta_item_vec[1])
         {
-            start_position = 3;
+            start_position = 2;
             symbol = Symbol::intern(&width.to_string());
         } else {
-            start_position = 2;
+            start_position = 1;
             symbol = sym::integer(1);
         }
+
         let l: Lit = Lit { kind, symbol, suffix: None };
         let t = Token::new(TokenKind::Literal(l), Span::default());
         let comma = Token::new(TokenKind::Comma, Span::default());
@@ -289,7 +316,7 @@ mod llvm_enzyme {
         ts.pop();
         let ts: TokenStream = TokenStream::from_iter(ts);
 
-        let x: AutoDiffAttrs = from_ast(ecx, &meta_item_vec, has_ret);
+        let x: AutoDiffAttrs = from_ast(ecx, &meta_item_vec, has_ret, mode);
         if !x.is_active() {
             // We encountered an error, so we return the original item.
             // This allows us to potentially parse other attributes.
@@ -1017,4 +1044,4 @@ mod llvm_enzyme {
     }
 }
 
-pub(crate) use llvm_enzyme::expand;
+pub(crate) use llvm_enzyme::{expand_forward, expand_reverse};
diff --git a/compiler/rustc_builtin_macros/src/deriving/clone.rs b/compiler/rustc_builtin_macros/src/deriving/clone.rs
index 44cf215c662..69f8c273797 100644
--- a/compiler/rustc_builtin_macros/src/deriving/clone.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/clone.rs
@@ -34,8 +34,8 @@ pub(crate) fn expand_deriving_clone(
     let is_simple;
     match item {
         Annotatable::Item(annitem) => match &annitem.kind {
-            ItemKind::Struct(_, _, Generics { params, .. })
-            | ItemKind::Enum(_, _, Generics { params, .. }) => {
+            ItemKind::Struct(_, Generics { params, .. }, _)
+            | ItemKind::Enum(_, Generics { params, .. }, _) => {
                 let container_id = cx.current_expansion.id.expn_data().parent.expect_local();
                 let has_derive_copy = cx.resolver.has_derive_copy(container_id);
                 if has_derive_copy
diff --git a/compiler/rustc_builtin_macros/src/deriving/cmp/partial_eq.rs b/compiler/rustc_builtin_macros/src/deriving/cmp/partial_eq.rs
index 4b93b3414c7..b1d950b8d89 100644
--- a/compiler/rustc_builtin_macros/src/deriving/cmp/partial_eq.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/cmp/partial_eq.rs
@@ -8,6 +8,8 @@ use crate::deriving::generic::ty::*;
 use crate::deriving::generic::*;
 use crate::deriving::{path_local, path_std};
 
+/// Expands a `#[derive(PartialEq)]` attribute into an implementation for the
+/// target item.
 pub(crate) fn expand_deriving_partial_eq(
     cx: &ExtCtxt<'_>,
     span: Span,
@@ -16,62 +18,6 @@ pub(crate) fn expand_deriving_partial_eq(
     push: &mut dyn FnMut(Annotatable),
     is_const: bool,
 ) {
-    fn cs_eq(cx: &ExtCtxt<'_>, span: Span, substr: &Substructure<'_>) -> BlockOrExpr {
-        let base = true;
-        let expr = cs_fold(
-            true, // use foldl
-            cx,
-            span,
-            substr,
-            |cx, fold| match fold {
-                CsFold::Single(field) => {
-                    let [other_expr] = &field.other_selflike_exprs[..] else {
-                        cx.dcx()
-                            .span_bug(field.span, "not exactly 2 arguments in `derive(PartialEq)`");
-                    };
-
-                    // We received arguments of type `&T`. Convert them to type `T` by stripping
-                    // any leading `&`. This isn't necessary for type checking, but
-                    // it results in better error messages if something goes wrong.
-                    //
-                    // Note: for arguments that look like `&{ x }`, which occur with packed
-                    // structs, this would cause expressions like `{ self.x } == { other.x }`,
-                    // which isn't valid Rust syntax. This wouldn't break compilation because these
-                    // AST nodes are constructed within the compiler. But it would mean that code
-                    // printed by `-Zunpretty=expanded` (or `cargo expand`) would have invalid
-                    // syntax, which would be suboptimal. So we wrap these in parens, giving
-                    // `({ self.x }) == ({ other.x })`, which is valid syntax.
-                    let convert = |expr: &P<Expr>| {
-                        if let ExprKind::AddrOf(BorrowKind::Ref, Mutability::Not, inner) =
-                            &expr.kind
-                        {
-                            if let ExprKind::Block(..) = &inner.kind {
-                                // `&{ x }` form: remove the `&`, add parens.
-                                cx.expr_paren(field.span, inner.clone())
-                            } else {
-                                // `&x` form: remove the `&`.
-                                inner.clone()
-                            }
-                        } else {
-                            expr.clone()
-                        }
-                    };
-                    cx.expr_binary(
-                        field.span,
-                        BinOpKind::Eq,
-                        convert(&field.self_expr),
-                        convert(other_expr),
-                    )
-                }
-                CsFold::Combine(span, expr1, expr2) => {
-                    cx.expr_binary(span, BinOpKind::And, expr1, expr2)
-                }
-                CsFold::Fieldless => cx.expr_bool(span, base),
-            },
-        );
-        BlockOrExpr::new_expr(expr)
-    }
-
     let structural_trait_def = TraitDef {
         span,
         path: path_std!(marker::StructuralPartialEq),
@@ -97,7 +43,9 @@ pub(crate) fn expand_deriving_partial_eq(
         ret_ty: Path(path_local!(bool)),
         attributes: thin_vec![cx.attr_word(sym::inline, span)],
         fieldless_variants_strategy: FieldlessVariantsStrategy::Unify,
-        combine_substructure: combine_substructure(Box::new(|a, b, c| cs_eq(a, b, c))),
+        combine_substructure: combine_substructure(Box::new(|a, b, c| {
+            BlockOrExpr::new_expr(get_substructure_equality_expr(a, b, c))
+        })),
     }];
 
     let trait_def = TraitDef {
@@ -113,3 +61,156 @@ pub(crate) fn expand_deriving_partial_eq(
     };
     trait_def.expand(cx, mitem, item, push)
 }
+
+/// Generates the equality expression for a struct or enum variant when deriving
+/// `PartialEq`.
+///
+/// This function generates an expression that checks if all fields of a struct
+/// or enum variant are equal.
+/// - Scalar fields are compared first for efficiency, followed by compound
+///   fields.
+/// - If there are no fields, returns `true` (fieldless types are always equal).
+///
+/// Whether a field is considered "scalar" is determined by comparing the symbol
+/// of its type to a set of known scalar type symbols (e.g., `i32`, `u8`, etc).
+/// This check is based on the type's symbol.
+///
+/// ### Example 1
+/// ```
+/// #[derive(PartialEq)]
+/// struct i32;
+///
+/// // Here, `field_2` is of type `i32`, but since it's a user-defined type (not
+/// // the primitive), it will not be treated as scalar. The function will still
+/// // check equality of `field_2` first because the symbol matches `i32`.
+/// #[derive(PartialEq)]
+/// struct Struct {
+///     field_1: &'static str,
+///     field_2: i32,
+/// }
+/// ```
+///
+/// ### Example 2
+/// ```
+/// mod ty {
+///     pub type i32 = i32;
+/// }
+///
+/// // Here, `field_2` is of type `ty::i32`, which is a type alias for `i32`.
+/// // However, the function will not reorder the fields because the symbol for
+/// // `ty::i32` does not match the symbol for the primitive `i32`
+/// // ("ty::i32" != "i32").
+/// #[derive(PartialEq)]
+/// struct Struct {
+///     field_1: &'static str,
+///     field_2: ty::i32,
+/// }
+/// ```
+///
+/// For enums, the discriminant is compared first, then the rest of the fields.
+///
+/// # Panics
+///
+/// If called on static or all-fieldless enums/structs, which should not occur
+/// during derive expansion.
+fn get_substructure_equality_expr(
+    cx: &ExtCtxt<'_>,
+    span: Span,
+    substructure: &Substructure<'_>,
+) -> P<Expr> {
+    use SubstructureFields::*;
+
+    match substructure.fields {
+        EnumMatching(.., fields) | Struct(.., fields) => {
+            let combine = move |acc, field| {
+                let rhs = get_field_equality_expr(cx, field);
+                if let Some(lhs) = acc {
+                    // Combine the previous comparison with the current field
+                    // using logical AND.
+                    return Some(cx.expr_binary(field.span, BinOpKind::And, lhs, rhs));
+                }
+                // Start the chain with the first field's comparison.
+                Some(rhs)
+            };
+
+            // First compare scalar fields, then compound fields, combining all
+            // with logical AND.
+            return fields
+                .iter()
+                .filter(|field| !field.maybe_scalar)
+                .fold(fields.iter().filter(|field| field.maybe_scalar).fold(None, combine), combine)
+                // If there are no fields, treat as always equal.
+                .unwrap_or_else(|| cx.expr_bool(span, true));
+        }
+        EnumDiscr(disc, match_expr) => {
+            let lhs = get_field_equality_expr(cx, disc);
+            let Some(match_expr) = match_expr else {
+                return lhs;
+            };
+            // Compare the discriminant first (cheaper), then the rest of the
+            // fields.
+            return cx.expr_binary(disc.span, BinOpKind::And, lhs, match_expr.clone());
+        }
+        StaticEnum(..) => cx.dcx().span_bug(
+            span,
+            "unexpected static enum encountered during `derive(PartialEq)` expansion",
+        ),
+        StaticStruct(..) => cx.dcx().span_bug(
+            span,
+            "unexpected static struct encountered during `derive(PartialEq)` expansion",
+        ),
+        AllFieldlessEnum(..) => cx.dcx().span_bug(
+            span,
+            "unexpected all-fieldless enum encountered during `derive(PartialEq)` expansion",
+        ),
+    }
+}
+
+/// Generates an equality comparison expression for a single struct or enum
+/// field.
+///
+/// This function produces an AST expression that compares the `self` and
+/// `other` values for a field using `==`. It removes any leading references
+/// from both sides for readability. If the field is a block expression, it is
+/// wrapped in parentheses to ensure valid syntax.
+///
+/// # Panics
+///
+/// Panics if there are not exactly two arguments to compare (should be `self`
+/// and `other`).
+fn get_field_equality_expr(cx: &ExtCtxt<'_>, field: &FieldInfo) -> P<Expr> {
+    let [rhs] = &field.other_selflike_exprs[..] else {
+        cx.dcx().span_bug(field.span, "not exactly 2 arguments in `derive(PartialEq)`");
+    };
+
+    cx.expr_binary(
+        field.span,
+        BinOpKind::Eq,
+        wrap_block_expr(cx, peel_refs(&field.self_expr)),
+        wrap_block_expr(cx, peel_refs(rhs)),
+    )
+}
+
+/// Removes all leading immutable references from an expression.
+///
+/// This is used to strip away any number of leading `&` from an expression
+/// (e.g., `&&&T` becomes `T`). Only removes immutable references; mutable
+/// references are preserved.
+fn peel_refs(mut expr: &P<Expr>) -> P<Expr> {
+    while let ExprKind::AddrOf(BorrowKind::Ref, Mutability::Not, inner) = &expr.kind {
+        expr = &inner;
+    }
+    expr.clone()
+}
+
+/// Wraps a block expression in parentheses to ensure valid AST in macro
+/// expansion output.
+///
+/// If the given expression is a block, it is wrapped in parentheses; otherwise,
+/// it is returned unchanged.
+fn wrap_block_expr(cx: &ExtCtxt<'_>, expr: P<Expr>) -> P<Expr> {
+    if matches!(&expr.kind, ExprKind::Block(..)) {
+        return cx.expr_paren(expr.span, expr);
+    }
+    expr
+}
diff --git a/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs b/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs
index aa01da3151e..0a076dd670b 100644
--- a/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs
@@ -21,7 +21,7 @@ pub(crate) fn expand_deriving_partial_ord(
 
     // Order in which to perform matching
     let discr_then_data = if let Annotatable::Item(item) = item
-        && let ItemKind::Enum(_, def, _) = &item.kind
+        && let ItemKind::Enum(_, _, def) = &item.kind
     {
         let dataful: Vec<bool> = def.variants.iter().map(|v| !v.data.fields().is_empty()).collect();
         match dataful.iter().filter(|&&b| b).count() {
diff --git a/compiler/rustc_builtin_macros/src/deriving/coerce_pointee.rs b/compiler/rustc_builtin_macros/src/deriving/coerce_pointee.rs
index 446d8afeedd..0794192621a 100644
--- a/compiler/rustc_builtin_macros/src/deriving/coerce_pointee.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/coerce_pointee.rs
@@ -30,7 +30,7 @@ pub(crate) fn expand_deriving_coerce_pointee(
     item.visit_with(&mut DetectNonGenericPointeeAttr { cx });
 
     let (name_ident, generics) = if let Annotatable::Item(aitem) = item
-        && let ItemKind::Struct(ident, struct_data, g) = &aitem.kind
+        && let ItemKind::Struct(ident, g, struct_data) = &aitem.kind
     {
         if !matches!(
             struct_data,
diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs
index 9aa53f9e4f7..6dd3adf750d 100644
--- a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs
@@ -284,6 +284,7 @@ pub(crate) struct FieldInfo {
     /// The expressions corresponding to references to this field in
     /// the other selflike arguments.
     pub other_selflike_exprs: Vec<P<Expr>>,
+    pub maybe_scalar: bool,
 }
 
 #[derive(Copy, Clone)]
@@ -488,7 +489,7 @@ impl<'a> TraitDef<'a> {
                 );
 
                 let newitem = match &item.kind {
-                    ast::ItemKind::Struct(ident, struct_def, generics) => self.expand_struct_def(
+                    ast::ItemKind::Struct(ident, generics, struct_def) => self.expand_struct_def(
                         cx,
                         struct_def,
                         *ident,
@@ -496,7 +497,7 @@ impl<'a> TraitDef<'a> {
                         from_scratch,
                         is_packed,
                     ),
-                    ast::ItemKind::Enum(ident, enum_def, generics) => {
+                    ast::ItemKind::Enum(ident, generics, enum_def) => {
                         // We ignore `is_packed` here, because `repr(packed)`
                         // enums cause an error later on.
                         //
@@ -504,7 +505,7 @@ impl<'a> TraitDef<'a> {
                         // downstream in blatantly illegal code, so it is fine.
                         self.expand_enum_def(cx, enum_def, *ident, generics, from_scratch)
                     }
-                    ast::ItemKind::Union(ident, struct_def, generics) => {
+                    ast::ItemKind::Union(ident, generics, struct_def) => {
                         if self.supports_unions {
                             self.expand_struct_def(
                                 cx,
@@ -1220,7 +1221,8 @@ impl<'a> MethodDef<'a> {
 
             let self_expr = discr_exprs.remove(0);
             let other_selflike_exprs = discr_exprs;
-            let discr_field = FieldInfo { span, name: None, self_expr, other_selflike_exprs };
+            let discr_field =
+                FieldInfo { span, name: None, self_expr, other_selflike_exprs, maybe_scalar: true };
 
             let discr_let_stmts: ThinVec<_> = iter::zip(&discr_idents, &selflike_args)
                 .map(|(&ident, selflike_arg)| {
@@ -1533,6 +1535,7 @@ impl<'a> TraitDef<'a> {
                     name: struct_field.ident,
                     self_expr,
                     other_selflike_exprs,
+                    maybe_scalar: struct_field.ty.peel_refs().kind.maybe_scalar(),
                 }
             })
             .collect()
diff --git a/compiler/rustc_builtin_macros/src/errors.rs b/compiler/rustc_builtin_macros/src/errors.rs
index b28f7d312d9..3a2e96a5e5a 100644
--- a/compiler/rustc_builtin_macros/src/errors.rs
+++ b/compiler/rustc_builtin_macros/src/errors.rs
@@ -110,13 +110,6 @@ pub(crate) struct ProcMacro {
 }
 
 #[derive(Diagnostic)]
-#[diag(builtin_macros_non_abi)]
-pub(crate) struct NonABI {
-    #[primary_span]
-    pub(crate) span: Span,
-}
-
-#[derive(Diagnostic)]
 #[diag(builtin_macros_trace_macros)]
 pub(crate) struct TraceMacros {
     #[primary_span]
@@ -188,14 +181,6 @@ mod autodiff {
     }
 
     #[derive(Diagnostic)]
-    #[diag(builtin_macros_autodiff_mode)]
-    pub(crate) struct AutoDiffInvalidMode {
-        #[primary_span]
-        pub(crate) span: Span,
-        pub(crate) mode: String,
-    }
-
-    #[derive(Diagnostic)]
     #[diag(builtin_macros_autodiff_width)]
     pub(crate) struct AutoDiffInvalidWidth {
         #[primary_span]
@@ -789,52 +774,13 @@ pub(crate) struct AsmModifierInvalid {
 }
 
 #[derive(Diagnostic)]
-#[diag(builtin_macros_asm_requires_template)]
-pub(crate) struct AsmRequiresTemplate {
-    #[primary_span]
-    pub(crate) span: Span,
-}
-
-#[derive(Diagnostic)]
-#[diag(builtin_macros_asm_expected_comma)]
-pub(crate) struct AsmExpectedComma {
-    #[primary_span]
-    #[label]
-    pub(crate) span: Span,
-}
-
-#[derive(Diagnostic)]
-#[diag(builtin_macros_asm_expected_string_literal)]
-pub(crate) struct AsmExpectedStringLiteral {
+#[diag(builtin_macros_asm_attribute_not_supported)]
+pub(crate) struct AsmAttributeNotSupported {
     #[primary_span]
-    #[label]
     pub(crate) span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(builtin_macros_asm_underscore_input)]
-pub(crate) struct AsmUnderscoreInput {
-    #[primary_span]
-    pub(crate) span: Span,
-}
-
-#[derive(Diagnostic)]
-#[diag(builtin_macros_asm_sym_no_path)]
-pub(crate) struct AsmSymNoPath {
-    #[primary_span]
-    pub(crate) span: Span,
-}
-
-#[derive(Diagnostic)]
-#[diag(builtin_macros_asm_expected_other)]
-pub(crate) struct AsmExpectedOther {
-    #[primary_span]
-    #[label(builtin_macros_asm_expected_other)]
-    pub(crate) span: Span,
-    pub(crate) is_inline_asm: bool,
-}
-
-#[derive(Diagnostic)]
 #[diag(builtin_macros_asm_duplicate_arg)]
 pub(crate) struct AsmDuplicateArg {
     #[primary_span]
@@ -926,16 +872,6 @@ pub(crate) struct AsmUnsupportedOption {
 }
 
 #[derive(Diagnostic)]
-#[diag(builtin_macros_asm_unsupported_operand)]
-pub(crate) struct AsmUnsupportedOperand<'a> {
-    #[primary_span]
-    #[label]
-    pub(crate) span: Span,
-    pub(crate) symbol: &'a str,
-    pub(crate) macro_name: &'static str,
-}
-
-#[derive(Diagnostic)]
 #[diag(builtin_macros_asm_unsupported_clobber_abi)]
 pub(crate) struct AsmUnsupportedClobberAbi {
     #[primary_span]
@@ -958,13 +894,6 @@ pub(crate) struct TestRunnerNargs {
 }
 
 #[derive(Diagnostic)]
-#[diag(builtin_macros_expected_register_class_or_explicit_register)]
-pub(crate) struct ExpectedRegisterClassOrExplicitRegister {
-    #[primary_span]
-    pub(crate) span: Span,
-}
-
-#[derive(Diagnostic)]
 #[diag(builtin_macros_expected_comma_in_list)]
 pub(crate) struct ExpectedCommaInList {
     #[primary_span]
@@ -1027,3 +956,12 @@ pub(crate) struct NonGenericPointee {
     #[primary_span]
     pub span: Span,
 }
+
+#[derive(Diagnostic)]
+#[diag(builtin_macros_expected_other)]
+pub(crate) struct AsmExpectedOther {
+    #[primary_span]
+    #[label(builtin_macros_expected_other)]
+    pub(crate) span: Span,
+    pub(crate) is_inline_asm: bool,
+}
diff --git a/compiler/rustc_builtin_macros/src/iter.rs b/compiler/rustc_builtin_macros/src/iter.rs
new file mode 100644
index 00000000000..7ad83903a1b
--- /dev/null
+++ b/compiler/rustc_builtin_macros/src/iter.rs
@@ -0,0 +1,53 @@
+use rustc_ast::ptr::P;
+use rustc_ast::tokenstream::TokenStream;
+use rustc_ast::{CoroutineKind, DUMMY_NODE_ID, Expr, ast, token};
+use rustc_errors::PResult;
+use rustc_expand::base::{self, DummyResult, ExpandResult, ExtCtxt, MacroExpanderResult};
+use rustc_span::Span;
+
+pub(crate) fn expand<'cx>(
+    cx: &'cx mut ExtCtxt<'_>,
+    sp: Span,
+    tts: TokenStream,
+) -> MacroExpanderResult<'cx> {
+    let closure = match parse_closure(cx, sp, tts) {
+        Ok(parsed) => parsed,
+        Err(err) => {
+            return ExpandResult::Ready(DummyResult::any(sp, err.emit()));
+        }
+    };
+
+    ExpandResult::Ready(base::MacEager::expr(closure))
+}
+
+fn parse_closure<'a>(
+    cx: &mut ExtCtxt<'a>,
+    span: Span,
+    stream: TokenStream,
+) -> PResult<'a, P<Expr>> {
+    let mut closure_parser = cx.new_parser_from_tts(stream);
+
+    let coroutine_kind = Some(CoroutineKind::Gen {
+        span,
+        closure_id: DUMMY_NODE_ID,
+        return_impl_trait_id: DUMMY_NODE_ID,
+    });
+
+    let mut closure = closure_parser.parse_expr()?;
+    match &mut closure.kind {
+        ast::ExprKind::Closure(c) => {
+            if let Some(kind) = c.coroutine_kind {
+                cx.dcx().span_err(kind.span(), "only plain closures allowed in `iter!`");
+            }
+            c.coroutine_kind = coroutine_kind;
+            if closure_parser.token != token::Eof {
+                closure_parser.unexpected()?;
+            }
+            Ok(closure)
+        }
+        _ => {
+            cx.dcx().span_err(closure.span, "`iter!` body must be a closure");
+            Err(closure_parser.unexpected().unwrap_err())
+        }
+    }
+}
diff --git a/compiler/rustc_builtin_macros/src/lib.rs b/compiler/rustc_builtin_macros/src/lib.rs
index 9cd4d17059a..aa52c3bd281 100644
--- a/compiler/rustc_builtin_macros/src/lib.rs
+++ b/compiler/rustc_builtin_macros/src/lib.rs
@@ -5,10 +5,10 @@
 #![allow(internal_features)]
 #![allow(rustc::diagnostic_outside_of_impl)]
 #![allow(rustc::untranslatable_diagnostic)]
+#![cfg_attr(not(bootstrap), feature(autodiff))]
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
 #![doc(rust_logo)]
 #![feature(assert_matches)]
-#![feature(autodiff)]
 #![feature(box_patterns)]
 #![feature(decl_macro)]
 #![feature(if_let_guard)]
@@ -20,8 +20,6 @@
 #![recursion_limit = "256"]
 // tidy-alphabetical-end
 
-extern crate proc_macro;
-
 use std::sync::Arc;
 
 use rustc_expand::base::{MacroExpanderFn, ResolverExpand, SyntaxExtensionKind};
@@ -49,6 +47,7 @@ mod errors;
 mod format;
 mod format_foreign;
 mod global_allocator;
+mod iter;
 mod log_syntax;
 mod pattern_type;
 mod source_util;
@@ -97,6 +96,7 @@ pub fn register_builtin_macros(resolver: &mut dyn ResolverExpand) {
         include: source_util::expand_include,
         include_bytes: source_util::expand_include_bytes,
         include_str: source_util::expand_include_str,
+        iter: iter::expand,
         line: source_util::expand_line,
         log_syntax: log_syntax::expand_log_syntax,
         module_path: source_util::expand_mod,
@@ -112,7 +112,8 @@ pub fn register_builtin_macros(resolver: &mut dyn ResolverExpand) {
 
     register_attr! {
         alloc_error_handler: alloc_error_handler::expand,
-        autodiff: autodiff::expand,
+        autodiff_forward: autodiff::expand_forward,
+        autodiff_reverse: autodiff::expand_reverse,
         bench: test::expand_bench,
         cfg_accessible: cfg_accessible::Expander,
         cfg_eval: cfg_eval::expand,
@@ -139,7 +140,7 @@ pub fn register_builtin_macros(resolver: &mut dyn ResolverExpand) {
         CoercePointee: coerce_pointee::expand_deriving_coerce_pointee,
     }
 
-    let client = proc_macro::bridge::client::Client::expand1(proc_macro::quote);
+    let client = rustc_proc_macro::bridge::client::Client::expand1(rustc_proc_macro::quote);
     register(sym::quote, SyntaxExtensionKind::Bang(Arc::new(BangProcMacro { client })));
     let requires = SyntaxExtensionKind::Attr(Arc::new(contracts::ExpandRequires));
     register(sym::contracts_requires, requires);
diff --git a/compiler/rustc_builtin_macros/src/test_harness.rs b/compiler/rustc_builtin_macros/src/test_harness.rs
index 56a67b0534d..0bc313cbdac 100644
--- a/compiler/rustc_builtin_macros/src/test_harness.rs
+++ b/compiler/rustc_builtin_macros/src/test_harness.rs
@@ -128,9 +128,7 @@ impl<'a> MutVisitor for TestHarnessGenerator<'a> {
         c.items.push(mk_main(&mut self.cx));
     }
 
-    fn visit_item(&mut self, item: &mut P<ast::Item>) {
-        let item = &mut **item;
-
+    fn visit_item(&mut self, item: &mut ast::Item) {
         if let Some(name) = get_test_name(&item) {
             debug!("this is a test item");
 
@@ -193,7 +191,7 @@ struct EntryPointCleaner<'a> {
 }
 
 impl<'a> MutVisitor for EntryPointCleaner<'a> {
-    fn visit_item(&mut self, item: &mut P<ast::Item>) {
+    fn visit_item(&mut self, item: &mut ast::Item) {
         self.depth += 1;
         ast::mut_visit::walk_item(self, item);
         self.depth -= 1;
diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs
index b21ca32c9a2..0de23e55e81 100644
--- a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs
+++ b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs
@@ -870,11 +870,12 @@ fn codegen_regular_intrinsic_call<'tcx>(
             // FIXME use a compiler fence once Cranelift supports it
             fx.bcx.ins().fence();
         }
-        _ if intrinsic.as_str().starts_with("atomic_load") => {
+        sym::atomic_load => {
             intrinsic_args!(fx, args => (ptr); intrinsic);
             let ptr = ptr.load_scalar(fx);
 
             let ty = generic_args.type_at(0);
+            let _ord = generic_args.const_at(1).to_value(); // FIXME: forward this to cranelift once they support that
             match ty.kind() {
                 ty::Uint(UintTy::U128) | ty::Int(IntTy::I128) => {
                     // FIXME implement 128bit atomics
diff --git a/compiler/rustc_codegen_gcc/src/abi.rs b/compiler/rustc_codegen_gcc/src/abi.rs
index ef902055007..3d0c258f576 100644
--- a/compiler/rustc_codegen_gcc/src/abi.rs
+++ b/compiler/rustc_codegen_gcc/src/abi.rs
@@ -13,7 +13,6 @@ use rustc_target::callconv::{ArgAttributes, CastTarget, FnAbi, PassMode};
 
 use crate::builder::Builder;
 use crate::context::CodegenCx;
-use crate::intrinsic::ArgAbiExt;
 use crate::type_of::LayoutGccExt;
 
 impl AbiBuilderMethods for Builder<'_, '_, '_> {
@@ -123,7 +122,7 @@ impl<'gcc, 'tcx> FnAbiGccExt<'gcc, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
             PassMode::Direct(_) | PassMode::Pair(..) => self.ret.layout.immediate_gcc_type(cx),
             PassMode::Cast { ref cast, .. } => cast.gcc_type(cx),
             PassMode::Indirect { .. } => {
-                argument_tys.push(cx.type_ptr_to(self.ret.memory_ty(cx)));
+                argument_tys.push(cx.type_ptr_to(self.ret.layout.gcc_type(cx)));
                 cx.type_void()
             }
         };
@@ -174,13 +173,13 @@ impl<'gcc, 'tcx> FnAbiGccExt<'gcc, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
                 PassMode::Indirect { attrs: _, meta_attrs: None, on_stack: true } => {
                     // This is a "byval" argument, so we don't apply the `restrict` attribute on it.
                     on_stack_param_indices.insert(argument_tys.len());
-                    arg.memory_ty(cx)
+                    arg.layout.gcc_type(cx)
                 }
                 PassMode::Direct(attrs) => {
                     apply_attrs(arg.layout.immediate_gcc_type(cx), &attrs, argument_tys.len())
                 }
                 PassMode::Indirect { attrs, meta_attrs: None, on_stack: false } => {
-                    apply_attrs(cx.type_ptr_to(arg.memory_ty(cx)), &attrs, argument_tys.len())
+                    apply_attrs(cx.type_ptr_to(arg.layout.gcc_type(cx)), &attrs, argument_tys.len())
                 }
                 PassMode::Indirect { attrs, meta_attrs: Some(meta_attrs), on_stack } => {
                     assert!(!on_stack);
diff --git a/compiler/rustc_codegen_gcc/src/base.rs b/compiler/rustc_codegen_gcc/src/base.rs
index a9d7808c833..c105916bbb2 100644
--- a/compiler/rustc_codegen_gcc/src/base.rs
+++ b/compiler/rustc_codegen_gcc/src/base.rs
@@ -219,17 +219,22 @@ pub fn compile_codegen_unit(
 
             let mono_items = cgu.items_in_deterministic_order(tcx);
             for &(mono_item, data) in &mono_items {
-                mono_item.predefine::<Builder<'_, '_, '_>>(&cx, data.linkage, data.visibility);
+                mono_item.predefine::<Builder<'_, '_, '_>>(
+                    &mut cx,
+                    cgu_name.as_str(),
+                    data.linkage,
+                    data.visibility,
+                );
             }
 
             // ... and now that we have everything pre-defined, fill out those definitions.
             for &(mono_item, item_data) in &mono_items {
-                mono_item.define::<Builder<'_, '_, '_>>(&mut cx, item_data);
+                mono_item.define::<Builder<'_, '_, '_>>(&mut cx, cgu_name.as_str(), item_data);
             }
 
             // If this codegen unit contains the main function, also create the
             // wrapper here
-            maybe_create_entry_wrapper::<Builder<'_, '_, '_>>(&cx);
+            maybe_create_entry_wrapper::<Builder<'_, '_, '_>>(&cx, cx.codegen_unit);
 
             // Finalize debuginfo
             if cx.sess().opts.debuginfo != DebugInfo::None {
diff --git a/compiler/rustc_codegen_gcc/src/builder.rs b/compiler/rustc_codegen_gcc/src/builder.rs
index 4e2163201fd..d1fb8d8f9d6 100644
--- a/compiler/rustc_codegen_gcc/src/builder.rs
+++ b/compiler/rustc_codegen_gcc/src/builder.rs
@@ -12,7 +12,7 @@ use rustc_abi::{Align, HasDataLayout, Size, TargetDataLayout, WrappingRange};
 use rustc_apfloat::{Float, Round, Status, ieee};
 use rustc_codegen_ssa::MemFlags;
 use rustc_codegen_ssa::common::{
-    AtomicOrdering, AtomicRmwBinOp, IntPredicate, RealPredicate, SynchronizationScope, TypeKind,
+    AtomicRmwBinOp, IntPredicate, RealPredicate, SynchronizationScope, TypeKind,
 };
 use rustc_codegen_ssa::mir::operand::{OperandRef, OperandValue};
 use rustc_codegen_ssa::mir::place::PlaceRef;
@@ -26,7 +26,7 @@ use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs;
 use rustc_middle::ty::layout::{
     FnAbiError, FnAbiOfHelpers, FnAbiRequest, HasTyCtxt, HasTypingEnv, LayoutError, LayoutOfHelpers,
 };
-use rustc_middle::ty::{self, Instance, Ty, TyCtxt};
+use rustc_middle::ty::{self, AtomicOrdering, Instance, Ty, TyCtxt};
 use rustc_span::Span;
 use rustc_span::def_id::DefId;
 use rustc_target::callconv::FnAbi;
@@ -75,7 +75,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
 
         let load_ordering = match order {
             // TODO(antoyo): does this make sense?
-            AtomicOrdering::AcquireRelease | AtomicOrdering::Release => AtomicOrdering::Acquire,
+            AtomicOrdering::AcqRel | AtomicOrdering::Release => AtomicOrdering::Acquire,
             _ => order,
         };
         let previous_value =
@@ -2474,8 +2474,8 @@ impl ToGccOrdering for AtomicOrdering {
             AtomicOrdering::Relaxed => __ATOMIC_RELAXED, // TODO(antoyo): check if that's the same.
             AtomicOrdering::Acquire => __ATOMIC_ACQUIRE,
             AtomicOrdering::Release => __ATOMIC_RELEASE,
-            AtomicOrdering::AcquireRelease => __ATOMIC_ACQ_REL,
-            AtomicOrdering::SequentiallyConsistent => __ATOMIC_SEQ_CST,
+            AtomicOrdering::AcqRel => __ATOMIC_ACQ_REL,
+            AtomicOrdering::SeqCst => __ATOMIC_SEQ_CST,
         };
         ordering as i32
     }
diff --git a/compiler/rustc_codegen_gcc/src/consts.rs b/compiler/rustc_codegen_gcc/src/consts.rs
index 8aed04c836a..deb13ddf755 100644
--- a/compiler/rustc_codegen_gcc/src/consts.rs
+++ b/compiler/rustc_codegen_gcc/src/consts.rs
@@ -67,7 +67,7 @@ impl<'gcc, 'tcx> StaticCodegenMethods for CodegenCx<'gcc, 'tcx> {
     }
 
     #[cfg_attr(not(feature = "master"), allow(unused_mut))]
-    fn codegen_static(&self, def_id: DefId) {
+    fn codegen_static(&mut self, def_id: DefId) {
         let attrs = self.tcx.codegen_fn_attrs(def_id);
 
         let Ok((value, alloc)) = codegen_static_initializer(self, def_id) else {
@@ -160,19 +160,14 @@ impl<'gcc, 'tcx> StaticCodegenMethods for CodegenCx<'gcc, 'tcx> {
             self.add_used_global(global.to_rvalue());
         }
     }
+}
 
+impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
     /// Add a global value to a list to be stored in the `llvm.used` variable, an array of i8*.
-    fn add_used_global(&self, _global: RValue<'gcc>) {
+    pub fn add_used_global(&mut self, _global: RValue<'gcc>) {
         // TODO(antoyo)
     }
 
-    fn add_compiler_used_global(&self, global: RValue<'gcc>) {
-        // NOTE: seems like GCC does not make the distinction between compiler.used and used.
-        self.add_used_global(global);
-    }
-}
-
-impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
     #[cfg_attr(not(feature = "master"), allow(unused_variables))]
     pub fn add_used_function(&self, function: Function<'gcc>) {
         #[cfg(feature = "master")]
diff --git a/compiler/rustc_codegen_gcc/src/context.rs b/compiler/rustc_codegen_gcc/src/context.rs
index 73718994e64..c6c43201f21 100644
--- a/compiler/rustc_codegen_gcc/src/context.rs
+++ b/compiler/rustc_codegen_gcc/src/context.rs
@@ -470,10 +470,6 @@ impl<'gcc, 'tcx> MiscCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
         self.tcx.sess
     }
 
-    fn codegen_unit(&self) -> &'tcx CodegenUnit<'tcx> {
-        self.codegen_unit
-    }
-
     fn set_frame_pointer_type(&self, _llfn: RValue<'gcc>) {
         // TODO(antoyo)
     }
diff --git a/compiler/rustc_codegen_gcc/src/debuginfo.rs b/compiler/rustc_codegen_gcc/src/debuginfo.rs
index e0597d0030d..3a265fbc64f 100644
--- a/compiler/rustc_codegen_gcc/src/debuginfo.rs
+++ b/compiler/rustc_codegen_gcc/src/debuginfo.rs
@@ -52,10 +52,6 @@ impl<'a, 'gcc, 'tcx> DebugInfoBuilderMethods for Builder<'a, 'gcc, 'tcx> {
     fn clear_dbg_loc(&mut self) {
         self.location = None;
     }
-
-    fn get_dbg_loc(&self) -> Option<Self::DILocation> {
-        self.location
-    }
 }
 
 /// Generate the `debug_context` in an MIR Body.
diff --git a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs
index ba65c8205a5..9e05b8f23aa 100644
--- a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs
+++ b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs
@@ -22,11 +22,11 @@ use rustc_codegen_ssa::traits::{
 };
 use rustc_middle::bug;
 #[cfg(feature = "master")]
-use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt};
-use rustc_middle::ty::layout::{HasTypingEnv, LayoutOf};
+use rustc_middle::ty::layout::FnAbiOf;
+use rustc_middle::ty::layout::LayoutOf;
 use rustc_middle::ty::{self, Instance, Ty};
 use rustc_span::{Span, Symbol, sym};
-use rustc_target::callconv::{ArgAbi, FnAbi, PassMode};
+use rustc_target::callconv::{ArgAbi, PassMode};
 use rustc_target::spec::PanicStrategy;
 
 #[cfg(feature = "master")]
@@ -200,28 +200,15 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc
     fn codegen_intrinsic_call(
         &mut self,
         instance: Instance<'tcx>,
-        fn_abi: &FnAbi<'tcx, Ty<'tcx>>,
         args: &[OperandRef<'tcx, RValue<'gcc>>],
-        llresult: RValue<'gcc>,
+        result: PlaceRef<'tcx, RValue<'gcc>>,
         span: Span,
     ) -> Result<(), Instance<'tcx>> {
         let tcx = self.tcx;
-        let callee_ty = instance.ty(tcx, self.typing_env());
 
-        let (def_id, fn_args) = match *callee_ty.kind() {
-            ty::FnDef(def_id, fn_args) => (def_id, fn_args),
-            _ => bug!("expected fn item type, found {}", callee_ty),
-        };
-
-        let sig = callee_ty.fn_sig(tcx);
-        let sig = tcx.normalize_erasing_late_bound_regions(self.typing_env(), sig);
-        let arg_tys = sig.inputs();
-        let ret_ty = sig.output();
-        let name = tcx.item_name(def_id);
+        let name = tcx.item_name(instance.def_id());
         let name_str = name.as_str();
-
-        let llret_ty = self.layout_of(ret_ty).gcc_type(self);
-        let result = PlaceRef::new_sized(llresult, fn_abi.ret.layout);
+        let fn_args = instance.args;
 
         let simple = get_simple_intrinsic(self, name);
         let simple_func = get_simple_function(self, name);
@@ -271,7 +258,7 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc
                     args[0].immediate(),
                     args[1].immediate(),
                     args[2].immediate(),
-                    llresult,
+                    result,
                 );
                 return Ok(());
             }
@@ -286,17 +273,10 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc
             }
 
             sym::volatile_load | sym::unaligned_volatile_load => {
-                let tp_ty = fn_args.type_at(0);
                 let ptr = args[0].immediate();
-                let layout = self.layout_of(tp_ty);
-                let load = if let PassMode::Cast { cast: ref ty, pad_i32: _ } = fn_abi.ret.mode {
-                    let gcc_ty = ty.gcc_type(self);
-                    self.volatile_load(gcc_ty, ptr)
-                } else {
-                    self.volatile_load(layout.gcc_type(self), ptr)
-                };
+                let load = self.volatile_load(result.layout.gcc_type(self), ptr);
                 // TODO(antoyo): set alignment.
-                if let BackendRepr::Scalar(scalar) = layout.backend_repr {
+                if let BackendRepr::Scalar(scalar) = result.layout.backend_repr {
                     self.to_immediate_scalar(load, scalar)
                 } else {
                     load
@@ -329,8 +309,7 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc
             | sym::rotate_right
             | sym::saturating_add
             | sym::saturating_sub => {
-                let ty = arg_tys[0];
-                match int_type_width_signed(ty, self) {
+                match int_type_width_signed(args[0].layout.ty, self) {
                     Some((width, signed)) => match name {
                         sym::ctlz | sym::cttz => {
                             let func = self.current_func.borrow().expect("func");
@@ -409,7 +388,7 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc
                         tcx.dcx().emit_err(InvalidMonomorphization::BasicIntegerType {
                             span,
                             name,
-                            ty,
+                            ty: args[0].layout.ty,
                         });
                         return Ok(());
                     }
@@ -501,7 +480,14 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc
             }
 
             _ if name_str.starts_with("simd_") => {
-                match generic_simd_intrinsic(self, name, callee_ty, args, ret_ty, llret_ty, span) {
+                match generic_simd_intrinsic(
+                    self,
+                    name,
+                    args,
+                    result.layout.ty,
+                    result.layout.gcc_type(self),
+                    span,
+                ) {
                     Ok(value) => value,
                     Err(()) => return Ok(()),
                 }
@@ -511,16 +497,11 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc
             _ => return Err(Instance::new_raw(instance.def_id(), instance.args)),
         };
 
-        if !fn_abi.ret.is_ignore() {
-            if let PassMode::Cast { cast: ref ty, .. } = fn_abi.ret.mode {
-                let ptr_llty = self.type_ptr_to(ty.gcc_type(self));
-                let ptr = self.pointercast(result.val.llval, ptr_llty);
-                self.store(value, ptr, result.val.align);
-            } else {
-                OperandRef::from_immediate_or_packed_pair(self, value, result.layout)
-                    .val
-                    .store(self, result);
-            }
+        if result.layout.ty.is_bool() {
+            let val = self.from_immediate(value);
+            self.store_to_place(val, result.val);
+        } else if !result.layout.ty.is_unit() {
+            self.store_to_place(value, result.val);
         }
         Ok(())
     }
@@ -543,11 +524,6 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc
         cond
     }
 
-    fn type_test(&mut self, _pointer: Self::Value, _typeid: Self::Value) -> Self::Value {
-        // Unsupported.
-        self.context.new_rvalue_from_int(self.int_type, 0)
-    }
-
     fn type_checked_load(
         &mut self,
         _llvtable: Self::Value,
@@ -585,14 +561,9 @@ impl<'a, 'gcc, 'tcx> ArgAbiBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
     ) {
         arg_abi.store(self, val, dst)
     }
-
-    fn arg_memory_ty(&self, arg_abi: &ArgAbi<'tcx, Ty<'tcx>>) -> Type<'gcc> {
-        arg_abi.memory_ty(self)
-    }
 }
 
 pub trait ArgAbiExt<'gcc, 'tcx> {
-    fn memory_ty(&self, cx: &CodegenCx<'gcc, 'tcx>) -> Type<'gcc>;
     fn store(
         &self,
         bx: &mut Builder<'_, 'gcc, 'tcx>,
@@ -608,12 +579,6 @@ pub trait ArgAbiExt<'gcc, 'tcx> {
 }
 
 impl<'gcc, 'tcx> ArgAbiExt<'gcc, 'tcx> for ArgAbi<'tcx, Ty<'tcx>> {
-    /// Gets the LLVM type for a place of the original Rust type of
-    /// this argument/return, i.e., the result of `type_of::type_of`.
-    fn memory_ty(&self, cx: &CodegenCx<'gcc, 'tcx>) -> Type<'gcc> {
-        self.layout.gcc_type(cx)
-    }
-
     /// Stores a direct/indirect value described by this ArgAbi into a
     /// place for the original Rust type of this argument/return.
     /// Can be used for both storing formal arguments into Rust variables
@@ -1230,14 +1195,13 @@ fn try_intrinsic<'a, 'b, 'gcc, 'tcx>(
     try_func: RValue<'gcc>,
     data: RValue<'gcc>,
     _catch_func: RValue<'gcc>,
-    dest: RValue<'gcc>,
+    dest: PlaceRef<'tcx, RValue<'gcc>>,
 ) {
     if bx.sess().panic_strategy() == PanicStrategy::Abort {
         bx.call(bx.type_void(), None, None, try_func, &[data], None, None);
         // Return 0 unconditionally from the intrinsic call;
         // we can never unwind.
-        let ret_align = bx.tcx.data_layout.i32_align.abi;
-        bx.store(bx.const_i32(0), dest, ret_align);
+        OperandValue::Immediate(bx.const_i32(0)).store(bx, dest);
     } else {
         if wants_msvc_seh(bx.sess()) {
             unimplemented!();
@@ -1261,12 +1225,12 @@ fn try_intrinsic<'a, 'b, 'gcc, 'tcx>(
 // functions in play. By calling a shim we're guaranteed that our shim will have
 // the right personality function.
 #[cfg(feature = "master")]
-fn codegen_gnu_try<'gcc>(
-    bx: &mut Builder<'_, 'gcc, '_>,
+fn codegen_gnu_try<'gcc, 'tcx>(
+    bx: &mut Builder<'_, 'gcc, 'tcx>,
     try_func: RValue<'gcc>,
     data: RValue<'gcc>,
     catch_func: RValue<'gcc>,
-    dest: RValue<'gcc>,
+    dest: PlaceRef<'tcx, RValue<'gcc>>,
 ) {
     let cx: &CodegenCx<'gcc, '_> = bx.cx;
     let (llty, func) = get_rust_try_fn(cx, &mut |mut bx| {
@@ -1322,8 +1286,7 @@ fn codegen_gnu_try<'gcc>(
     // Note that no invoke is used here because by definition this function
     // can't panic (that's what it's catching).
     let ret = bx.call(llty, None, None, func, &[try_func, data, catch_func], None, None);
-    let i32_align = bx.tcx().data_layout.i32_align.abi;
-    bx.store(ret, dest, i32_align);
+    OperandValue::Immediate(ret).store(bx, dest);
 }
 
 // Helper function used to get a handle to the `__rust_try` function used to
diff --git a/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs b/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs
index b897d079249..82ef0d0b13a 100644
--- a/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs
+++ b/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs
@@ -28,7 +28,6 @@ use crate::context::CodegenCx;
 pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
     bx: &mut Builder<'a, 'gcc, 'tcx>,
     name: Symbol,
-    callee_ty: Ty<'tcx>,
     args: &[OperandRef<'tcx, RValue<'gcc>>],
     ret_ty: Ty<'tcx>,
     llret_ty: Type<'gcc>,
@@ -54,24 +53,17 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
         };
     }
 
-    let tcx = bx.tcx();
-    let sig = tcx.normalize_erasing_late_bound_regions(
-        ty::TypingEnv::fully_monomorphized(),
-        callee_ty.fn_sig(tcx),
-    );
-    let arg_tys = sig.inputs();
-
     if name == sym::simd_select_bitmask {
         require_simd!(
-            arg_tys[1],
-            InvalidMonomorphization::SimdArgument { span, name, ty: arg_tys[1] }
+            args[1].layout.ty,
+            InvalidMonomorphization::SimdArgument { span, name, ty: args[1].layout.ty }
         );
-        let (len, _) = arg_tys[1].simd_size_and_type(bx.tcx());
+        let (len, _) = args[1].layout.ty.simd_size_and_type(bx.tcx());
 
         let expected_int_bits = (len.max(8) - 1).next_power_of_two();
         let expected_bytes = len / 8 + ((len % 8 > 0) as u64);
 
-        let mask_ty = arg_tys[0];
+        let mask_ty = args[0].layout.ty;
         let mut mask = match *mask_ty.kind() {
             ty::Int(i) if i.bit_width() == Some(expected_int_bits) => args[0].immediate(),
             ty::Uint(i) if i.bit_width() == Some(expected_int_bits) => args[0].immediate(),
@@ -121,8 +113,11 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
     }
 
     // every intrinsic below takes a SIMD vector as its first argument
-    require_simd!(arg_tys[0], InvalidMonomorphization::SimdInput { span, name, ty: arg_tys[0] });
-    let in_ty = arg_tys[0];
+    require_simd!(
+        args[0].layout.ty,
+        InvalidMonomorphization::SimdInput { span, name, ty: args[0].layout.ty }
+    );
+    let in_ty = args[0].layout.ty;
 
     let comparison = match name {
         sym::simd_eq => Some(BinOp::Eq),
@@ -134,7 +129,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
         _ => None,
     };
 
-    let (in_len, in_elem) = arg_tys[0].simd_size_and_type(bx.tcx());
+    let (in_len, in_elem) = args[0].layout.ty.simd_size_and_type(bx.tcx());
     if let Some(cmp_op) = comparison {
         require_simd!(ret_ty, InvalidMonomorphization::SimdReturn { span, name, ty: ret_ty });
 
@@ -401,13 +396,13 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
     #[cfg(feature = "master")]
     if name == sym::simd_insert || name == sym::simd_insert_dyn {
         require!(
-            in_elem == arg_tys[2],
+            in_elem == args[2].layout.ty,
             InvalidMonomorphization::InsertedType {
                 span,
                 name,
                 in_elem,
                 in_ty,
-                out_ty: arg_tys[2]
+                out_ty: args[2].layout.ty
             }
         );
 
@@ -439,10 +434,10 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
         let m_elem_ty = in_elem;
         let m_len = in_len;
         require_simd!(
-            arg_tys[1],
-            InvalidMonomorphization::SimdArgument { span, name, ty: arg_tys[1] }
+            args[1].layout.ty,
+            InvalidMonomorphization::SimdArgument { span, name, ty: args[1].layout.ty }
         );
-        let (v_len, _) = arg_tys[1].simd_size_and_type(bx.tcx());
+        let (v_len, _) = args[1].layout.ty.simd_size_and_type(bx.tcx());
         require!(
             m_len == v_len,
             InvalidMonomorphization::MismatchedLengths { span, name, m_len, v_len }
@@ -911,18 +906,18 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
         // All types must be simd vector types
         require_simd!(in_ty, InvalidMonomorphization::SimdFirst { span, name, ty: in_ty });
         require_simd!(
-            arg_tys[1],
-            InvalidMonomorphization::SimdSecond { span, name, ty: arg_tys[1] }
+            args[1].layout.ty,
+            InvalidMonomorphization::SimdSecond { span, name, ty: args[1].layout.ty }
         );
         require_simd!(
-            arg_tys[2],
-            InvalidMonomorphization::SimdThird { span, name, ty: arg_tys[2] }
+            args[2].layout.ty,
+            InvalidMonomorphization::SimdThird { span, name, ty: args[2].layout.ty }
         );
         require_simd!(ret_ty, InvalidMonomorphization::SimdReturn { span, name, ty: ret_ty });
 
         // Of the same length:
-        let (out_len, _) = arg_tys[1].simd_size_and_type(bx.tcx());
-        let (out_len2, _) = arg_tys[2].simd_size_and_type(bx.tcx());
+        let (out_len, _) = args[1].layout.ty.simd_size_and_type(bx.tcx());
+        let (out_len2, _) = args[2].layout.ty.simd_size_and_type(bx.tcx());
         require!(
             in_len == out_len,
             InvalidMonomorphization::SecondArgumentLength {
@@ -930,7 +925,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
                 name,
                 in_len,
                 in_ty,
-                arg_ty: arg_tys[1],
+                arg_ty: args[1].layout.ty,
                 out_len
             }
         );
@@ -941,7 +936,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
                 name,
                 in_len,
                 in_ty,
-                arg_ty: arg_tys[2],
+                arg_ty: args[2].layout.ty,
                 out_len: out_len2
             }
         );
@@ -970,8 +965,8 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
 
         // The second argument must be a simd vector with an element type that's a pointer
         // to the element type of the first argument
-        let (_, element_ty0) = arg_tys[0].simd_size_and_type(bx.tcx());
-        let (_, element_ty1) = arg_tys[1].simd_size_and_type(bx.tcx());
+        let (_, element_ty0) = args[0].layout.ty.simd_size_and_type(bx.tcx());
+        let (_, element_ty1) = args[1].layout.ty.simd_size_and_type(bx.tcx());
         let (pointer_count, underlying_ty) = match *element_ty1.kind() {
             ty::RawPtr(p_ty, _) if p_ty == in_elem => {
                 (ptr_count(element_ty1), non_ptr(element_ty1))
@@ -983,7 +978,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
                         span,
                         name,
                         expected_element: element_ty1,
-                        second_arg: arg_tys[1],
+                        second_arg: args[1].layout.ty,
                         in_elem,
                         in_ty,
                         mutability: ExpectedPointerMutability::Not,
@@ -998,7 +993,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
 
         // The element type of the third argument must be an integer type of any width:
         // TODO: also support unsigned integers.
-        let (_, element_ty2) = arg_tys[2].simd_size_and_type(bx.tcx());
+        let (_, element_ty2) = args[2].layout.ty.simd_size_and_type(bx.tcx());
         match *element_ty2.kind() {
             ty::Int(_) => (),
             _ => {
@@ -1030,17 +1025,17 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
         // All types must be simd vector types
         require_simd!(in_ty, InvalidMonomorphization::SimdFirst { span, name, ty: in_ty });
         require_simd!(
-            arg_tys[1],
-            InvalidMonomorphization::SimdSecond { span, name, ty: arg_tys[1] }
+            args[1].layout.ty,
+            InvalidMonomorphization::SimdSecond { span, name, ty: args[1].layout.ty }
         );
         require_simd!(
-            arg_tys[2],
-            InvalidMonomorphization::SimdThird { span, name, ty: arg_tys[2] }
+            args[2].layout.ty,
+            InvalidMonomorphization::SimdThird { span, name, ty: args[2].layout.ty }
         );
 
         // Of the same length:
-        let (element_len1, _) = arg_tys[1].simd_size_and_type(bx.tcx());
-        let (element_len2, _) = arg_tys[2].simd_size_and_type(bx.tcx());
+        let (element_len1, _) = args[1].layout.ty.simd_size_and_type(bx.tcx());
+        let (element_len2, _) = args[2].layout.ty.simd_size_and_type(bx.tcx());
         require!(
             in_len == element_len1,
             InvalidMonomorphization::SecondArgumentLength {
@@ -1048,7 +1043,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
                 name,
                 in_len,
                 in_ty,
-                arg_ty: arg_tys[1],
+                arg_ty: args[1].layout.ty,
                 out_len: element_len1
             }
         );
@@ -1059,7 +1054,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
                 name,
                 in_len,
                 in_ty,
-                arg_ty: arg_tys[2],
+                arg_ty: args[2].layout.ty,
                 out_len: element_len2
             }
         );
@@ -1082,9 +1077,9 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
 
         // The second argument must be a simd vector with an element type that's a pointer
         // to the element type of the first argument
-        let (_, element_ty0) = arg_tys[0].simd_size_and_type(bx.tcx());
-        let (_, element_ty1) = arg_tys[1].simd_size_and_type(bx.tcx());
-        let (_, element_ty2) = arg_tys[2].simd_size_and_type(bx.tcx());
+        let (_, element_ty0) = args[0].layout.ty.simd_size_and_type(bx.tcx());
+        let (_, element_ty1) = args[1].layout.ty.simd_size_and_type(bx.tcx());
+        let (_, element_ty2) = args[2].layout.ty.simd_size_and_type(bx.tcx());
         let (pointer_count, underlying_ty) = match *element_ty1.kind() {
             ty::RawPtr(p_ty, mutbl) if p_ty == in_elem && mutbl == hir::Mutability::Mut => {
                 (ptr_count(element_ty1), non_ptr(element_ty1))
@@ -1096,7 +1091,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
                         span,
                         name,
                         expected_element: element_ty1,
-                        second_arg: arg_tys[1],
+                        second_arg: args[1].layout.ty,
                         in_elem,
                         in_ty,
                         mutability: ExpectedPointerMutability::Mut,
@@ -1194,8 +1189,8 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
                 return_error!(InvalidMonomorphization::ExpectedVectorElementType {
                     span,
                     name,
-                    expected_element: arg_tys[0].simd_size_and_type(bx.tcx()).1,
-                    vector_type: arg_tys[0],
+                    expected_element: args[0].layout.ty.simd_size_and_type(bx.tcx()).1,
+                    vector_type: args[0].layout.ty,
                 });
             }
         };
diff --git a/compiler/rustc_codegen_gcc/src/lib.rs b/compiler/rustc_codegen_gcc/src/lib.rs
index 6994c385fc8..f79ba2dcfc7 100644
--- a/compiler/rustc_codegen_gcc/src/lib.rs
+++ b/compiler/rustc_codegen_gcc/src/lib.rs
@@ -391,7 +391,7 @@ impl WriteBackendMethods for GccCodegenBackend {
         unimplemented!()
     }
 
-    unsafe fn optimize(
+    fn optimize(
         _cgcx: &CodegenContext<Self>,
         _dcx: DiagCtxtHandle<'_>,
         module: &mut ModuleCodegen<Self::Module>,
@@ -409,14 +409,14 @@ impl WriteBackendMethods for GccCodegenBackend {
         Ok(())
     }
 
-    unsafe fn optimize_thin(
+    fn optimize_thin(
         cgcx: &CodegenContext<Self>,
         thin: ThinModule<Self>,
     ) -> Result<ModuleCodegen<Self::Module>, FatalError> {
         back::lto::optimize_thin_module(thin, cgcx)
     }
 
-    unsafe fn codegen(
+    fn codegen(
         cgcx: &CodegenContext<Self>,
         dcx: DiagCtxtHandle<'_>,
         module: ModuleCodegen<Self::Module>,
diff --git a/compiler/rustc_codegen_gcc/src/mono_item.rs b/compiler/rustc_codegen_gcc/src/mono_item.rs
index a2df7b2596f..539e3ac8507 100644
--- a/compiler/rustc_codegen_gcc/src/mono_item.rs
+++ b/compiler/rustc_codegen_gcc/src/mono_item.rs
@@ -16,7 +16,7 @@ use crate::{attributes, base};
 impl<'gcc, 'tcx> PreDefineCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
     #[cfg_attr(not(feature = "master"), allow(unused_variables))]
     fn predefine_static(
-        &self,
+        &mut self,
         def_id: DefId,
         _linkage: Linkage,
         visibility: Visibility,
@@ -42,7 +42,7 @@ impl<'gcc, 'tcx> PreDefineCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
 
     #[cfg_attr(not(feature = "master"), allow(unused_variables))]
     fn predefine_fn(
-        &self,
+        &mut self,
         instance: Instance<'tcx>,
         linkage: Linkage,
         visibility: Visibility,
diff --git a/compiler/rustc_codegen_llvm/src/abi.rs b/compiler/rustc_codegen_llvm/src/abi.rs
index c41b3f7f55c..119cd634f98 100644
--- a/compiler/rustc_codegen_llvm/src/abi.rs
+++ b/compiler/rustc_codegen_llvm/src/abi.rs
@@ -175,7 +175,6 @@ impl LlvmType for CastTarget {
 }
 
 trait ArgAbiExt<'ll, 'tcx> {
-    fn memory_ty(&self, cx: &CodegenCx<'ll, 'tcx>) -> &'ll Type;
     fn store(
         &self,
         bx: &mut Builder<'_, 'll, 'tcx>,
@@ -191,12 +190,6 @@ trait ArgAbiExt<'ll, 'tcx> {
 }
 
 impl<'ll, 'tcx> ArgAbiExt<'ll, 'tcx> for ArgAbi<'tcx, Ty<'tcx>> {
-    /// Gets the LLVM type for a place of the original Rust type of
-    /// this argument/return, i.e., the result of `type_of::type_of`.
-    fn memory_ty(&self, cx: &CodegenCx<'ll, 'tcx>) -> &'ll Type {
-        self.layout.llvm_type(cx)
-    }
-
     /// Stores a direct/indirect value described by this ArgAbi into a
     /// place for the original Rust type of this argument/return.
     /// Can be used for both storing formal arguments into Rust variables
@@ -305,9 +298,6 @@ impl<'ll, 'tcx> ArgAbiBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> {
     ) {
         arg_abi.store(self, val, dst)
     }
-    fn arg_memory_ty(&self, arg_abi: &ArgAbi<'tcx, Ty<'tcx>>) -> &'ll Type {
-        arg_abi.memory_ty(self)
-    }
 }
 
 pub(crate) trait FnAbiLlvmExt<'ll, 'tcx> {
diff --git a/compiler/rustc_codegen_llvm/src/back/lto.rs b/compiler/rustc_codegen_llvm/src/back/lto.rs
index cb329323f5d..ee46b49a094 100644
--- a/compiler/rustc_codegen_llvm/src/back/lto.rs
+++ b/compiler/rustc_codegen_llvm/src/back/lto.rs
@@ -799,7 +799,7 @@ impl Drop for ThinBuffer {
     }
 }
 
-pub(crate) unsafe fn optimize_thin_module(
+pub(crate) fn optimize_thin_module(
     thin_module: ThinModule<LlvmCodegenBackend>,
     cgcx: &CodegenContext<LlvmCodegenBackend>,
 ) -> Result<ModuleCodegen<ModuleLlvm>, FatalError> {
diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs
index 20721c74608..bde6a9cf4bc 100644
--- a/compiler/rustc_codegen_llvm/src/back/write.rs
+++ b/compiler/rustc_codegen_llvm/src/back/write.rs
@@ -704,7 +704,7 @@ pub(crate) unsafe fn llvm_optimize(
 }
 
 // Unsafe due to LLVM calls.
-pub(crate) unsafe fn optimize(
+pub(crate) fn optimize(
     cgcx: &CodegenContext<LlvmCodegenBackend>,
     dcx: DiagCtxtHandle<'_>,
     module: &mut ModuleCodegen<ModuleLlvm>,
@@ -815,7 +815,7 @@ pub(crate) fn link(
     Ok(modules.remove(0))
 }
 
-pub(crate) unsafe fn codegen(
+pub(crate) fn codegen(
     cgcx: &CodegenContext<LlvmCodegenBackend>,
     dcx: DiagCtxtHandle<'_>,
     module: ModuleCodegen<ModuleLlvm>,
diff --git a/compiler/rustc_codegen_llvm/src/base.rs b/compiler/rustc_codegen_llvm/src/base.rs
index e4fac35aa44..5dda836988c 100644
--- a/compiler/rustc_codegen_llvm/src/base.rs
+++ b/compiler/rustc_codegen_llvm/src/base.rs
@@ -86,17 +86,24 @@ pub(crate) fn compile_codegen_unit(
             let mut cx = CodegenCx::new(tcx, cgu, &llvm_module);
             let mono_items = cx.codegen_unit.items_in_deterministic_order(cx.tcx);
             for &(mono_item, data) in &mono_items {
-                mono_item.predefine::<Builder<'_, '_, '_>>(&cx, data.linkage, data.visibility);
+                mono_item.predefine::<Builder<'_, '_, '_>>(
+                    &mut cx,
+                    cgu_name.as_str(),
+                    data.linkage,
+                    data.visibility,
+                );
             }
 
             // ... and now that we have everything pre-defined, fill out those definitions.
             for &(mono_item, item_data) in &mono_items {
-                mono_item.define::<Builder<'_, '_, '_>>(&mut cx, item_data);
+                mono_item.define::<Builder<'_, '_, '_>>(&mut cx, cgu_name.as_str(), item_data);
             }
 
             // If this codegen unit contains the main function, also create the
             // wrapper here
-            if let Some(entry) = maybe_create_entry_wrapper::<Builder<'_, '_, '_>>(&cx) {
+            if let Some(entry) =
+                maybe_create_entry_wrapper::<Builder<'_, '_, '_>>(&cx, cx.codegen_unit)
+            {
                 let attrs = attributes::sanitize_attrs(&cx, SanitizerSet::empty());
                 attributes::apply_to_llfn(entry, llvm::AttributePlace::Function, &attrs);
             }
@@ -108,14 +115,11 @@ pub(crate) fn compile_codegen_unit(
             }
 
             // Create the llvm.used and llvm.compiler.used variables.
-            if !cx.used_statics.borrow().is_empty() {
-                cx.create_used_variable_impl(c"llvm.used", &*cx.used_statics.borrow());
+            if !cx.used_statics.is_empty() {
+                cx.create_used_variable_impl(c"llvm.used", &cx.used_statics);
             }
-            if !cx.compiler_used_statics.borrow().is_empty() {
-                cx.create_used_variable_impl(
-                    c"llvm.compiler.used",
-                    &*cx.compiler_used_statics.borrow(),
-                );
+            if !cx.compiler_used_statics.is_empty() {
+                cx.create_used_variable_impl(c"llvm.compiler.used", &cx.compiler_used_statics);
             }
 
             // Run replace-all-uses-with for statics that need it. This must
diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs
index 5238755c8eb..ec006b59192 100644
--- a/compiler/rustc_codegen_llvm/src/builder.rs
+++ b/compiler/rustc_codegen_llvm/src/builder.rs
@@ -612,7 +612,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
         &mut self,
         ty: &'ll Type,
         ptr: &'ll Value,
-        order: rustc_codegen_ssa::common::AtomicOrdering,
+        order: rustc_middle::ty::AtomicOrdering,
         size: Size,
     ) -> &'ll Value {
         unsafe {
@@ -851,7 +851,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
         &mut self,
         val: &'ll Value,
         ptr: &'ll Value,
-        order: rustc_codegen_ssa::common::AtomicOrdering,
+        order: rustc_middle::ty::AtomicOrdering,
         size: Size,
     ) {
         debug!("Store {:?} -> {:?}", val, ptr);
@@ -1307,8 +1307,8 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
         dst: &'ll Value,
         cmp: &'ll Value,
         src: &'ll Value,
-        order: rustc_codegen_ssa::common::AtomicOrdering,
-        failure_order: rustc_codegen_ssa::common::AtomicOrdering,
+        order: rustc_middle::ty::AtomicOrdering,
+        failure_order: rustc_middle::ty::AtomicOrdering,
         weak: bool,
     ) -> (&'ll Value, &'ll Value) {
         let weak = if weak { llvm::True } else { llvm::False };
@@ -1334,7 +1334,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
         op: rustc_codegen_ssa::common::AtomicRmwBinOp,
         dst: &'ll Value,
         mut src: &'ll Value,
-        order: rustc_codegen_ssa::common::AtomicOrdering,
+        order: rustc_middle::ty::AtomicOrdering,
     ) -> &'ll Value {
         // The only RMW operation that LLVM supports on pointers is compare-exchange.
         let requires_cast_to_int = self.val_ty(src) == self.type_ptr()
@@ -1360,7 +1360,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
 
     fn atomic_fence(
         &mut self,
-        order: rustc_codegen_ssa::common::AtomicOrdering,
+        order: rustc_middle::ty::AtomicOrdering,
         scope: SynchronizationScope,
     ) {
         let single_threaded = match scope {
@@ -1452,9 +1452,15 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
 impl<'ll> StaticBuilderMethods for Builder<'_, 'll, '_> {
     fn get_static(&mut self, def_id: DefId) -> &'ll Value {
         // Forward to the `get_static` method of `CodegenCx`
-        let s = self.cx().get_static(def_id);
-        // Cast to default address space if globals are in a different addrspace
-        self.cx().const_pointercast(s, self.type_ptr())
+        let global = self.cx().get_static(def_id);
+        if self.cx().tcx.is_thread_local_static(def_id) {
+            let pointer = self.call_intrinsic("llvm.threadlocal.address", &[global]);
+            // Cast to default address space if globals are in a different addrspace
+            self.pointercast(pointer, self.type_ptr())
+        } else {
+            // Cast to default address space if globals are in a different addrspace
+            self.cx().const_pointercast(global, self.type_ptr())
+        }
     }
 }
 
@@ -1809,8 +1815,11 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
             let typeid_metadata = self.cx.typeid_metadata(typeid).unwrap();
             let dbg_loc = self.get_dbg_loc();
 
-            // Test whether the function pointer is associated with the type identifier.
-            let cond = self.type_test(llfn, typeid_metadata);
+            // Test whether the function pointer is associated with the type identifier using the
+            // llvm.type.test intrinsic. The LowerTypeTests link-time optimization pass replaces
+            // calls to this intrinsic with code to test type membership.
+            let typeid = self.get_metadata_value(typeid_metadata);
+            let cond = self.call_intrinsic("llvm.type.test", &[llfn, typeid]);
             let bb_pass = self.append_sibling_block("type_test.pass");
             let bb_fail = self.append_sibling_block("type_test.fail");
             self.cond_br(cond, bb_pass, bb_fail);
diff --git a/compiler/rustc_codegen_llvm/src/consts.rs b/compiler/rustc_codegen_llvm/src/consts.rs
index fe2f2027327..4234352c93a 100644
--- a/compiler/rustc_codegen_llvm/src/consts.rs
+++ b/compiler/rustc_codegen_llvm/src/consts.rs
@@ -411,7 +411,7 @@ impl<'ll> CodegenCx<'ll, '_> {
         g
     }
 
-    fn codegen_static_item(&self, def_id: DefId) {
+    fn codegen_static_item(&mut self, def_id: DefId) {
         unsafe {
             assert!(
                 llvm::LLVMGetInitializer(
@@ -557,6 +557,17 @@ impl<'ll> CodegenCx<'ll, '_> {
             }
         }
     }
+
+    /// Add a global value to a list to be stored in the `llvm.used` variable, an array of ptr.
+    pub(crate) fn add_used_global(&mut self, global: &'ll Value) {
+        self.used_statics.push(global);
+    }
+
+    /// Add a global value to a list to be stored in the `llvm.compiler.used` variable,
+    /// an array of ptr.
+    pub(crate) fn add_compiler_used_global(&mut self, global: &'ll Value) {
+        self.compiler_used_statics.push(global);
+    }
 }
 
 impl<'ll> StaticCodegenMethods for CodegenCx<'ll, '_> {
@@ -571,18 +582,7 @@ impl<'ll> StaticCodegenMethods for CodegenCx<'ll, '_> {
         self.const_pointercast(gv, self.type_ptr())
     }
 
-    fn codegen_static(&self, def_id: DefId) {
+    fn codegen_static(&mut self, def_id: DefId) {
         self.codegen_static_item(def_id)
     }
-
-    /// Add a global value to a list to be stored in the `llvm.used` variable, an array of ptr.
-    fn add_used_global(&self, global: &'ll Value) {
-        self.used_statics.borrow_mut().push(global);
-    }
-
-    /// Add a global value to a list to be stored in the `llvm.compiler.used` variable,
-    /// an array of ptr.
-    fn add_compiler_used_global(&self, global: &'ll Value) {
-        self.compiler_used_statics.borrow_mut().push(global);
-    }
 }
diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs
index b0d8e11d1fb..8d6e1d8941b 100644
--- a/compiler/rustc_codegen_llvm/src/context.rs
+++ b/compiler/rustc_codegen_llvm/src/context.rs
@@ -2,7 +2,7 @@ use std::borrow::Borrow;
 use std::cell::{Cell, RefCell};
 use std::ffi::{CStr, c_char, c_uint};
 use std::marker::PhantomData;
-use std::ops::Deref;
+use std::ops::{Deref, DerefMut};
 use std::str;
 
 use rustc_abi::{HasDataLayout, Size, TargetDataLayout, VariantIdx};
@@ -77,6 +77,13 @@ impl<'ll, T: Borrow<SCx<'ll>>> Deref for GenericCx<'ll, T> {
     }
 }
 
+impl<'ll, T: Borrow<SCx<'ll>>> DerefMut for GenericCx<'ll, T> {
+    #[inline]
+    fn deref_mut(&mut self) -> &mut Self::Target {
+        &mut self.0
+    }
+}
+
 pub(crate) type SimpleCx<'ll> = GenericCx<'ll, SCx<'ll>>;
 
 /// There is one `CodegenCx` per codegen unit. Each one has its own LLVM
@@ -110,11 +117,11 @@ pub(crate) struct FullCx<'ll, 'tcx> {
 
     /// Statics that will be placed in the llvm.used variable
     /// See <https://llvm.org/docs/LangRef.html#the-llvm-used-global-variable> for details
-    pub used_statics: RefCell<Vec<&'ll Value>>,
+    pub used_statics: Vec<&'ll Value>,
 
     /// Statics that will be placed in the llvm.compiler.used variable
     /// See <https://llvm.org/docs/LangRef.html#the-llvm-compiler-used-global-variable> for details
-    pub compiler_used_statics: RefCell<Vec<&'ll Value>>,
+    pub compiler_used_statics: Vec<&'ll Value>,
 
     /// Mapping of non-scalar types to llvm types.
     pub type_lowering: RefCell<FxHashMap<(Ty<'tcx>, Option<VariantIdx>), &'ll Type>>,
@@ -606,8 +613,8 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> {
                 const_str_cache: Default::default(),
                 const_globals: Default::default(),
                 statics_to_rauw: RefCell::new(Vec::new()),
-                used_statics: RefCell::new(Vec::new()),
-                compiler_used_statics: RefCell::new(Vec::new()),
+                used_statics: Vec::new(),
+                compiler_used_statics: Vec::new(),
                 type_lowering: Default::default(),
                 scalar_lltypes: Default::default(),
                 coverage_cx,
@@ -801,10 +808,6 @@ impl<'ll, 'tcx> MiscCodegenMethods<'tcx> for CodegenCx<'ll, 'tcx> {
         self.tcx.sess
     }
 
-    fn codegen_unit(&self) -> &'tcx CodegenUnit<'tcx> {
-        self.codegen_unit
-    }
-
     fn set_frame_pointer_type(&self, llfn: &'ll Value) {
         if let Some(attr) = attributes::frame_pointer_type_attr(self) {
             attributes::apply_to_llfn(llfn, llvm::AttributePlace::Function, &[attr]);
@@ -1240,6 +1243,7 @@ impl<'ll> CodegenCx<'ll, '_> {
         }
 
         ifn!("llvm.ptrmask", fn(ptr, t_isize) -> ptr);
+        ifn!("llvm.threadlocal.address", fn(ptr) -> ptr);
 
         None
     }
diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/ffi.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/ffi.rs
index c207df2fb0b..f6000e72840 100644
--- a/compiler/rustc_codegen_llvm/src/coverageinfo/ffi.rs
+++ b/compiler/rustc_codegen_llvm/src/coverageinfo/ffi.rs
@@ -155,20 +155,6 @@ pub(crate) struct Regions {
 impl Regions {
     /// Returns true if none of this structure's tables contain any regions.
     pub(crate) fn has_no_regions(&self) -> bool {
-        // Every region has a span, so if there are no spans then there are no regions.
-        self.all_cov_spans().next().is_none()
-    }
-
-    pub(crate) fn all_cov_spans(&self) -> impl Iterator<Item = &CoverageSpan> {
-        macro_rules! iter_cov_spans {
-            ( $( $regions:expr ),* $(,)? ) => {
-                std::iter::empty()
-                $(
-                    .chain( $regions.iter().map(|region| &region.cov_span) )
-                )*
-            }
-        }
-
         let Self {
             code_regions,
             expansion_regions,
@@ -177,13 +163,11 @@ impl Regions {
             mcdc_decision_regions,
         } = self;
 
-        iter_cov_spans!(
-            code_regions,
-            expansion_regions,
-            branch_regions,
-            mcdc_branch_regions,
-            mcdc_decision_regions,
-        )
+        code_regions.is_empty()
+            && expansion_regions.is_empty()
+            && branch_regions.is_empty()
+            && mcdc_branch_regions.is_empty()
+            && mcdc_decision_regions.is_empty()
     }
 }
 
diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs
index 55b1e728b70..a9be833a643 100644
--- a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs
+++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs
@@ -2,9 +2,7 @@ use std::sync::Arc;
 
 use itertools::Itertools;
 use rustc_abi::Align;
-use rustc_codegen_ssa::traits::{
-    BaseTypeCodegenMethods, ConstCodegenMethods, StaticCodegenMethods,
-};
+use rustc_codegen_ssa::traits::{BaseTypeCodegenMethods, ConstCodegenMethods};
 use rustc_data_structures::fx::FxIndexMap;
 use rustc_index::IndexVec;
 use rustc_middle::ty::TyCtxt;
@@ -27,7 +25,7 @@ mod unused;
 ///
 /// Those sections are then read and understood by LLVM's `llvm-cov` tool,
 /// which is distributed in the `llvm-tools` rustup component.
-pub(crate) fn finalize(cx: &CodegenCx<'_, '_>) {
+pub(crate) fn finalize(cx: &mut CodegenCx<'_, '_>) {
     let tcx = cx.tcx;
 
     // Ensure that LLVM is using a version of the coverage mapping format that
@@ -62,6 +60,7 @@ pub(crate) fn finalize(cx: &CodegenCx<'_, '_>) {
         .sorted_by_cached_key(|&instance| tcx.symbol_name(instance).name)
         .filter_map(|instance| prepare_covfun_record(tcx, instance, true))
         .collect::<Vec<_>>();
+    drop(instances_used);
 
     // In a single designated CGU, also prepare covfun records for functions
     // in this crate that were instrumented for coverage, but are unused.
@@ -206,7 +205,7 @@ impl VirtualFileMapping {
 /// Generates the contents of the covmap record for this CGU, which mostly
 /// consists of a header and a list of filenames. The record is then stored
 /// as a global variable in the `__llvm_covmap` section.
-fn generate_covmap_record<'ll>(cx: &CodegenCx<'ll, '_>, version: u32, filenames_buffer: &[u8]) {
+fn generate_covmap_record<'ll>(cx: &mut CodegenCx<'ll, '_>, version: u32, filenames_buffer: &[u8]) {
     // A covmap record consists of four target-endian u32 values, followed by
     // the encoded filenames table. Two of the header fields are unused in
     // modern versions of the LLVM coverage mapping format, and are always 0.
diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/covfun.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/covfun.rs
index d3a815fabe7..b704cf2b1cd 100644
--- a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/covfun.rs
+++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/covfun.rs
@@ -8,10 +8,7 @@ use std::ffi::CString;
 use std::sync::Arc;
 
 use rustc_abi::Align;
-use rustc_codegen_ssa::traits::{
-    BaseTypeCodegenMethods as _, ConstCodegenMethods, StaticCodegenMethods,
-};
-use rustc_index::IndexVec;
+use rustc_codegen_ssa::traits::{BaseTypeCodegenMethods as _, ConstCodegenMethods};
 use rustc_middle::mir::coverage::{
     BasicCoverageBlock, CovTerm, CoverageIdsInfo, Expression, FunctionCoverageInfo, Mapping,
     MappingKind, Op,
@@ -105,16 +102,6 @@ fn fill_region_tables<'tcx>(
     ids_info: &'tcx CoverageIdsInfo,
     covfun: &mut CovfunRecord<'tcx>,
 ) {
-    // If this function is unused, replace all counters with zero.
-    let counter_for_bcb = |bcb: BasicCoverageBlock| -> ffi::Counter {
-        let term = if covfun.is_used {
-            ids_info.term_for_bcb[bcb].expect("every BCB in a mapping was given a term")
-        } else {
-            CovTerm::Zero
-        };
-        ffi::Counter::from_term(term)
-    };
-
     // Currently a function's mappings must all be in the same file, so use the
     // first mapping's span to determine the file.
     let source_map = tcx.sess.source_map();
@@ -126,12 +113,6 @@ fn fill_region_tables<'tcx>(
 
     let local_file_id = covfun.virtual_file_mapping.push_file(&source_file);
 
-    // If this testing flag is set, add an extra unused entry to the local
-    // file table, to help test the code for detecting unused file IDs.
-    if tcx.sess.coverage_inject_unused_local_file() {
-        covfun.virtual_file_mapping.push_file(&source_file);
-    }
-
     // In rare cases, _all_ of a function's spans are discarded, and coverage
     // codegen needs to handle that gracefully to avoid #133606.
     // It's hard for tests to trigger this organically, so instead we set
@@ -152,6 +133,16 @@ fn fill_region_tables<'tcx>(
     // For each counter/region pair in this function+file, convert it to a
     // form suitable for FFI.
     for &Mapping { ref kind, span } in &fn_cov_info.mappings {
+        // If this function is unused, replace all counters with zero.
+        let counter_for_bcb = |bcb: BasicCoverageBlock| -> ffi::Counter {
+            let term = if covfun.is_used {
+                ids_info.term_for_bcb[bcb].expect("every BCB in a mapping was given a term")
+            } else {
+                CovTerm::Zero
+            };
+            ffi::Counter::from_term(term)
+        };
+
         let Some(coords) = make_coords(span) else { continue };
         let cov_span = coords.make_coverage_span(local_file_id);
 
@@ -184,31 +175,14 @@ fn fill_region_tables<'tcx>(
     }
 }
 
-/// LLVM requires all local file IDs to have at least one mapping region.
-/// If that's not the case, skip this function, to avoid an assertion failure
-/// (or worse) in LLVM.
-fn check_local_file_table(covfun: &CovfunRecord<'_>) -> bool {
-    let mut local_file_id_seen =
-        IndexVec::<u32, _>::from_elem_n(false, covfun.virtual_file_mapping.local_file_table.len());
-    for cov_span in covfun.regions.all_cov_spans() {
-        local_file_id_seen[cov_span.file_id] = true;
-    }
-
-    local_file_id_seen.into_iter().all(|seen| seen)
-}
-
 /// Generates the contents of the covfun record for this function, which
 /// contains the function's coverage mapping data. The record is then stored
 /// as a global variable in the `__llvm_covfun` section.
 pub(crate) fn generate_covfun_record<'tcx>(
-    cx: &CodegenCx<'_, 'tcx>,
+    cx: &mut CodegenCx<'_, 'tcx>,
     global_file_table: &GlobalFileTable,
     covfun: &CovfunRecord<'tcx>,
 ) {
-    if !check_local_file_table(covfun) {
-        return;
-    }
-
     let &CovfunRecord {
         mangled_function_name,
         source_hash,
diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/spans.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/spans.rs
index 574463be7ff..39a59560c9d 100644
--- a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/spans.rs
+++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/spans.rs
@@ -39,10 +39,7 @@ impl Coords {
 /// or other expansions), and if it does happen then skipping a span or function is
 /// better than an ICE or `llvm-cov` failure that the user might have no way to avoid.
 pub(crate) fn make_coords(source_map: &SourceMap, file: &SourceFile, span: Span) -> Option<Coords> {
-    if span.is_empty() {
-        debug_assert!(false, "can't make coords from empty span: {span:?}");
-        return None;
-    }
+    let span = ensure_non_empty_span(source_map, span)?;
 
     let lo = span.lo();
     let hi = span.hi();
@@ -73,6 +70,29 @@ pub(crate) fn make_coords(source_map: &SourceMap, file: &SourceFile, span: Span)
     })
 }
 
+fn ensure_non_empty_span(source_map: &SourceMap, span: Span) -> Option<Span> {
+    if !span.is_empty() {
+        return Some(span);
+    }
+
+    // The span is empty, so try to enlarge it to cover an adjacent '{' or '}'.
+    source_map
+        .span_to_source(span, |src, start, end| try {
+            // Adjusting span endpoints by `BytePos(1)` is normally a bug,
+            // but in this case we have specifically checked that the character
+            // we're skipping over is one of two specific ASCII characters, so
+            // adjusting by exactly 1 byte is correct.
+            if src.as_bytes().get(end).copied() == Some(b'{') {
+                Some(span.with_hi(span.hi() + BytePos(1)))
+            } else if start > 0 && src.as_bytes()[start - 1] == b'}' {
+                Some(span.with_lo(span.lo() - BytePos(1)))
+            } else {
+                None
+            }
+        })
+        .ok()?
+}
+
 /// If `llvm-cov` sees a source region that is improperly ordered (end < start),
 /// it will immediately exit with a fatal error. To prevent that from happening,
 /// discard regions that are improperly ordered, or might be interpreted in a
diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs
index ea7f581a3cb..eefbd7cf6c4 100644
--- a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs
+++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs
@@ -56,7 +56,7 @@ impl<'ll, 'tcx> CguCoverageContext<'ll, 'tcx> {
 }
 
 impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> {
-    pub(crate) fn coverageinfo_finalize(&self) {
+    pub(crate) fn coverageinfo_finalize(&mut self) {
         mapgen::finalize(self)
     }
 
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs
index c5085927923..5ca2505cec4 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs
@@ -147,6 +147,12 @@ pub(crate) fn finalize(cx: &CodegenCx<'_, '_>) {
     }
 }
 
+impl<'ll> Builder<'_, 'll, '_> {
+    pub(crate) fn get_dbg_loc(&self) -> Option<&'ll DILocation> {
+        unsafe { llvm::LLVMGetCurrentDebugLocation2(self.llbuilder) }
+    }
+}
+
 impl<'ll> DebugInfoBuilderMethods for Builder<'_, 'll, '_> {
     // FIXME(eddyb) find a common convention for all of the debuginfo-related
     // names (choose between `dbg`, `debug`, `debuginfo`, `debug_info` etc.).
@@ -209,10 +215,6 @@ impl<'ll> DebugInfoBuilderMethods for Builder<'_, 'll, '_> {
         }
     }
 
-    fn get_dbg_loc(&self) -> Option<&'ll DILocation> {
-        unsafe { llvm::LLVMGetCurrentDebugLocation2(self.llbuilder) }
-    }
-
     fn insert_reference_to_gdb_debug_scripts_section_global(&mut self) {
         gdb::insert_reference_to_gdb_debug_scripts_section_global(self)
     }
diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs
index 5ca57375292..10697b9a71f 100644
--- a/compiler/rustc_codegen_llvm/src/intrinsic.rs
+++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs
@@ -15,11 +15,10 @@ use rustc_middle::ty::{self, GenericArgsRef, Ty};
 use rustc_middle::{bug, span_bug};
 use rustc_span::{Span, Symbol, sym};
 use rustc_symbol_mangling::mangle_internal_symbol;
-use rustc_target::callconv::{FnAbi, PassMode};
 use rustc_target::spec::{HasTargetSpec, PanicStrategy};
 use tracing::debug;
 
-use crate::abi::{FnAbiLlvmExt, LlvmType};
+use crate::abi::FnAbiLlvmExt;
 use crate::builder::Builder;
 use crate::context::CodegenCx;
 use crate::llvm::{self, Metadata};
@@ -165,26 +164,14 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> {
     fn codegen_intrinsic_call(
         &mut self,
         instance: ty::Instance<'tcx>,
-        fn_abi: &FnAbi<'tcx, Ty<'tcx>>,
         args: &[OperandRef<'tcx, &'ll Value>],
-        llresult: &'ll Value,
+        result: PlaceRef<'tcx, &'ll Value>,
         span: Span,
     ) -> Result<(), ty::Instance<'tcx>> {
         let tcx = self.tcx;
-        let callee_ty = instance.ty(tcx, self.typing_env());
 
-        let ty::FnDef(def_id, fn_args) = *callee_ty.kind() else {
-            bug!("expected fn item type, found {}", callee_ty);
-        };
-
-        let sig = callee_ty.fn_sig(tcx);
-        let sig = tcx.normalize_erasing_late_bound_regions(self.typing_env(), sig);
-        let arg_tys = sig.inputs();
-        let ret_ty = sig.output();
-        let name = tcx.item_name(def_id);
-
-        let llret_ty = self.layout_of(ret_ty).llvm_type(self);
-        let result = PlaceRef::new_sized(llresult, fn_abi.ret.layout);
+        let name = tcx.item_name(instance.def_id());
+        let fn_args = instance.args;
 
         let simple = get_simple_intrinsic(self, name);
         let llval = match name {
@@ -255,7 +242,7 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> {
                     args[0].immediate(),
                     args[1].immediate(),
                     args[2].immediate(),
-                    llresult,
+                    result,
                 );
                 return Ok(());
             }
@@ -264,26 +251,26 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> {
                 self.call_intrinsic("llvm.va_copy", &[args[0].immediate(), args[1].immediate()])
             }
             sym::va_arg => {
-                match fn_abi.ret.layout.backend_repr {
+                match result.layout.backend_repr {
                     BackendRepr::Scalar(scalar) => {
                         match scalar.primitive() {
                             Primitive::Int(..) => {
-                                if self.cx().size_of(ret_ty).bytes() < 4 {
+                                if self.cx().size_of(result.layout.ty).bytes() < 4 {
                                     // `va_arg` should not be called on an integer type
                                     // less than 4 bytes in length. If it is, promote
                                     // the integer to an `i32` and truncate the result
                                     // back to the smaller type.
                                     let promoted_result = emit_va_arg(self, args[0], tcx.types.i32);
-                                    self.trunc(promoted_result, llret_ty)
+                                    self.trunc(promoted_result, result.layout.llvm_type(self))
                                 } else {
-                                    emit_va_arg(self, args[0], ret_ty)
+                                    emit_va_arg(self, args[0], result.layout.ty)
                                 }
                             }
                             Primitive::Float(Float::F16) => {
                                 bug!("the va_arg intrinsic does not work with `f16`")
                             }
                             Primitive::Float(Float::F64) | Primitive::Pointer(_) => {
-                                emit_va_arg(self, args[0], ret_ty)
+                                emit_va_arg(self, args[0], result.layout.ty)
                             }
                             // `va_arg` should never be used with the return type f32.
                             Primitive::Float(Float::F32) => {
@@ -299,18 +286,12 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> {
             }
 
             sym::volatile_load | sym::unaligned_volatile_load => {
-                let tp_ty = fn_args.type_at(0);
                 let ptr = args[0].immediate();
-                let load = if let PassMode::Cast { cast: ty, pad_i32: _ } = &fn_abi.ret.mode {
-                    let llty = ty.llvm_type(self);
-                    self.volatile_load(llty, ptr)
-                } else {
-                    self.volatile_load(self.layout_of(tp_ty).llvm_type(self), ptr)
-                };
+                let load = self.volatile_load(result.layout.llvm_type(self), ptr);
                 let align = if name == sym::unaligned_volatile_load {
                     1
                 } else {
-                    self.align_of(tp_ty).bytes() as u32
+                    result.layout.align.abi.bytes() as u32
                 };
                 unsafe {
                     llvm::LLVMSetAlignment(load, align);
@@ -393,7 +374,7 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> {
             | sym::rotate_right
             | sym::saturating_add
             | sym::saturating_sub => {
-                let ty = arg_tys[0];
+                let ty = args[0].layout.ty;
                 if !ty.is_integral() {
                     tcx.dcx().emit_err(InvalidMonomorphization::BasicIntegerType {
                         span,
@@ -412,26 +393,26 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> {
                             &[args[0].immediate(), y],
                         );
 
-                        self.intcast(ret, llret_ty, false)
+                        self.intcast(ret, result.layout.llvm_type(self), false)
                     }
                     sym::ctlz_nonzero => {
                         let y = self.const_bool(true);
                         let llvm_name = &format!("llvm.ctlz.i{width}");
                         let ret = self.call_intrinsic(llvm_name, &[args[0].immediate(), y]);
-                        self.intcast(ret, llret_ty, false)
+                        self.intcast(ret, result.layout.llvm_type(self), false)
                     }
                     sym::cttz_nonzero => {
                         let y = self.const_bool(true);
                         let llvm_name = &format!("llvm.cttz.i{width}");
                         let ret = self.call_intrinsic(llvm_name, &[args[0].immediate(), y]);
-                        self.intcast(ret, llret_ty, false)
+                        self.intcast(ret, result.layout.llvm_type(self), false)
                     }
                     sym::ctpop => {
                         let ret = self.call_intrinsic(
                             &format!("llvm.ctpop.i{width}"),
                             &[args[0].immediate()],
                         );
-                        self.intcast(ret, llret_ty, false)
+                        self.intcast(ret, result.layout.llvm_type(self), false)
                     }
                     sym::bswap => {
                         if width == 8 {
@@ -563,16 +544,16 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> {
                 // Unpack non-power-of-2 #[repr(packed, simd)] arguments.
                 // This gives them the expected layout of a regular #[repr(simd)] vector.
                 let mut loaded_args = Vec::new();
-                for (ty, arg) in arg_tys.iter().zip(args) {
+                for arg in args {
                     loaded_args.push(
                         // #[repr(packed, simd)] vectors are passed like arrays (as references,
                         // with reduced alignment and no padding) rather than as immediates.
                         // We can use a vector load to fix the layout and turn the argument
                         // into an immediate.
-                        if ty.is_simd()
+                        if arg.layout.ty.is_simd()
                             && let OperandValue::Ref(place) = arg.val
                         {
-                            let (size, elem_ty) = ty.simd_size_and_type(self.tcx());
+                            let (size, elem_ty) = arg.layout.ty.simd_size_and_type(self.tcx());
                             let elem_ll_ty = match elem_ty.kind() {
                                 ty::Float(f) => self.type_float_from_ty(*f),
                                 ty::Int(i) => self.type_int_from_ty(*i),
@@ -589,10 +570,10 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> {
                     );
                 }
 
-                let llret_ty = if ret_ty.is_simd()
-                    && let BackendRepr::Memory { .. } = self.layout_of(ret_ty).layout.backend_repr
+                let llret_ty = if result.layout.ty.is_simd()
+                    && let BackendRepr::Memory { .. } = result.layout.backend_repr
                 {
-                    let (size, elem_ty) = ret_ty.simd_size_and_type(self.tcx());
+                    let (size, elem_ty) = result.layout.ty.simd_size_and_type(self.tcx());
                     let elem_ll_ty = match elem_ty.kind() {
                         ty::Float(f) => self.type_float_from_ty(*f),
                         ty::Int(i) => self.type_int_from_ty(*i),
@@ -602,16 +583,15 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> {
                     };
                     self.type_vector(elem_ll_ty, size)
                 } else {
-                    llret_ty
+                    result.layout.llvm_type(self)
                 };
 
                 match generic_simd_intrinsic(
                     self,
                     name,
-                    callee_ty,
                     fn_args,
                     &loaded_args,
-                    ret_ty,
+                    result.layout.ty,
                     llret_ty,
                     span,
                 ) {
@@ -629,14 +609,11 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> {
             }
         };
 
-        if !fn_abi.ret.is_ignore() {
-            if let PassMode::Cast { .. } = &fn_abi.ret.mode {
-                self.store(llval, result.val.llval, result.val.align);
-            } else {
-                OperandRef::from_immediate_or_packed_pair(self, llval, result.layout)
-                    .val
-                    .store(self, result);
-            }
+        if result.layout.ty.is_bool() {
+            let val = self.from_immediate(llval);
+            self.store_to_place(val, result.val);
+        } else if !result.layout.ty.is_unit() {
+            self.store_to_place(llval, result.val);
         }
         Ok(())
     }
@@ -659,13 +636,6 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> {
         }
     }
 
-    fn type_test(&mut self, pointer: Self::Value, typeid: Self::Metadata) -> Self::Value {
-        // Test the called operand using llvm.type.test intrinsic. The LowerTypeTests link-time
-        // optimization pass replaces calls to this intrinsic with code to test type membership.
-        let typeid = self.get_metadata_value(typeid);
-        self.call_intrinsic("llvm.type.test", &[pointer, typeid])
-    }
-
     fn type_checked_load(
         &mut self,
         llvtable: &'ll Value,
@@ -688,20 +658,19 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> {
     }
 }
 
-fn catch_unwind_intrinsic<'ll>(
-    bx: &mut Builder<'_, 'll, '_>,
+fn catch_unwind_intrinsic<'ll, 'tcx>(
+    bx: &mut Builder<'_, 'll, 'tcx>,
     try_func: &'ll Value,
     data: &'ll Value,
     catch_func: &'ll Value,
-    dest: &'ll Value,
+    dest: PlaceRef<'tcx, &'ll Value>,
 ) {
     if bx.sess().panic_strategy() == PanicStrategy::Abort {
         let try_func_ty = bx.type_func(&[bx.type_ptr()], bx.type_void());
         bx.call(try_func_ty, None, None, try_func, &[data], None, None);
         // Return 0 unconditionally from the intrinsic call;
         // we can never unwind.
-        let ret_align = bx.tcx().data_layout.i32_align.abi;
-        bx.store(bx.const_i32(0), dest, ret_align);
+        OperandValue::Immediate(bx.const_i32(0)).store(bx, dest);
     } else if wants_msvc_seh(bx.sess()) {
         codegen_msvc_try(bx, try_func, data, catch_func, dest);
     } else if wants_wasm_eh(bx.sess()) {
@@ -720,12 +689,12 @@ fn catch_unwind_intrinsic<'ll>(
 // instructions are meant to work for all targets, as of the time of this
 // writing, however, LLVM does not recommend the usage of these new instructions
 // as the old ones are still more optimized.
-fn codegen_msvc_try<'ll>(
-    bx: &mut Builder<'_, 'll, '_>,
+fn codegen_msvc_try<'ll, 'tcx>(
+    bx: &mut Builder<'_, 'll, 'tcx>,
     try_func: &'ll Value,
     data: &'ll Value,
     catch_func: &'ll Value,
-    dest: &'ll Value,
+    dest: PlaceRef<'tcx, &'ll Value>,
 ) {
     let (llty, llfn) = get_rust_try_fn(bx, &mut |mut bx| {
         bx.set_personality_fn(bx.eh_personality());
@@ -865,17 +834,16 @@ fn codegen_msvc_try<'ll>(
     // Note that no invoke is used here because by definition this function
     // can't panic (that's what it's catching).
     let ret = bx.call(llty, None, None, llfn, &[try_func, data, catch_func], None, None);
-    let i32_align = bx.tcx().data_layout.i32_align.abi;
-    bx.store(ret, dest, i32_align);
+    OperandValue::Immediate(ret).store(bx, dest);
 }
 
 // WASM's definition of the `rust_try` function.
-fn codegen_wasm_try<'ll>(
-    bx: &mut Builder<'_, 'll, '_>,
+fn codegen_wasm_try<'ll, 'tcx>(
+    bx: &mut Builder<'_, 'll, 'tcx>,
     try_func: &'ll Value,
     data: &'ll Value,
     catch_func: &'ll Value,
-    dest: &'ll Value,
+    dest: PlaceRef<'tcx, &'ll Value>,
 ) {
     let (llty, llfn) = get_rust_try_fn(bx, &mut |mut bx| {
         bx.set_personality_fn(bx.eh_personality());
@@ -939,8 +907,7 @@ fn codegen_wasm_try<'ll>(
     // Note that no invoke is used here because by definition this function
     // can't panic (that's what it's catching).
     let ret = bx.call(llty, None, None, llfn, &[try_func, data, catch_func], None, None);
-    let i32_align = bx.tcx().data_layout.i32_align.abi;
-    bx.store(ret, dest, i32_align);
+    OperandValue::Immediate(ret).store(bx, dest);
 }
 
 // Definition of the standard `try` function for Rust using the GNU-like model
@@ -954,12 +921,12 @@ fn codegen_wasm_try<'ll>(
 // function calling it, and that function may already have other personality
 // functions in play. By calling a shim we're guaranteed that our shim will have
 // the right personality function.
-fn codegen_gnu_try<'ll>(
-    bx: &mut Builder<'_, 'll, '_>,
+fn codegen_gnu_try<'ll, 'tcx>(
+    bx: &mut Builder<'_, 'll, 'tcx>,
     try_func: &'ll Value,
     data: &'ll Value,
     catch_func: &'ll Value,
-    dest: &'ll Value,
+    dest: PlaceRef<'tcx, &'ll Value>,
 ) {
     let (llty, llfn) = get_rust_try_fn(bx, &mut |mut bx| {
         // Codegens the shims described above:
@@ -1006,19 +973,18 @@ fn codegen_gnu_try<'ll>(
     // Note that no invoke is used here because by definition this function
     // can't panic (that's what it's catching).
     let ret = bx.call(llty, None, None, llfn, &[try_func, data, catch_func], None, None);
-    let i32_align = bx.tcx().data_layout.i32_align.abi;
-    bx.store(ret, dest, i32_align);
+    OperandValue::Immediate(ret).store(bx, dest);
 }
 
 // Variant of codegen_gnu_try used for emscripten where Rust panics are
 // implemented using C++ exceptions. Here we use exceptions of a specific type
 // (`struct rust_panic`) to represent Rust panics.
-fn codegen_emcc_try<'ll>(
-    bx: &mut Builder<'_, 'll, '_>,
+fn codegen_emcc_try<'ll, 'tcx>(
+    bx: &mut Builder<'_, 'll, 'tcx>,
     try_func: &'ll Value,
     data: &'ll Value,
     catch_func: &'ll Value,
-    dest: &'ll Value,
+    dest: PlaceRef<'tcx, &'ll Value>,
 ) {
     let (llty, llfn) = get_rust_try_fn(bx, &mut |mut bx| {
         // Codegens the shims described above:
@@ -1089,8 +1055,7 @@ fn codegen_emcc_try<'ll>(
     // Note that no invoke is used here because by definition this function
     // can't panic (that's what it's catching).
     let ret = bx.call(llty, None, None, llfn, &[try_func, data, catch_func], None, None);
-    let i32_align = bx.tcx().data_layout.i32_align.abi;
-    bx.store(ret, dest, i32_align);
+    OperandValue::Immediate(ret).store(bx, dest);
 }
 
 // Helper function to give a Block to a closure to codegen a shim function.
@@ -1167,7 +1132,6 @@ fn get_rust_try_fn<'a, 'll, 'tcx>(
 fn generic_simd_intrinsic<'ll, 'tcx>(
     bx: &mut Builder<'_, 'll, 'tcx>,
     name: Symbol,
-    callee_ty: Ty<'tcx>,
     fn_args: GenericArgsRef<'tcx>,
     args: &[OperandRef<'tcx, &'ll Value>],
     ret_ty: Ty<'tcx>,
@@ -1238,26 +1202,22 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
         bx.trunc(i_xn_msb, bx.type_vector(bx.type_i1(), in_len))
     }
 
-    let tcx = bx.tcx();
-    let sig = tcx.normalize_erasing_late_bound_regions(bx.typing_env(), callee_ty.fn_sig(tcx));
-    let arg_tys = sig.inputs();
-
     // Sanity-check: all vector arguments must be immediates.
     if cfg!(debug_assertions) {
-        for (ty, arg) in arg_tys.iter().zip(args) {
-            if ty.is_simd() {
+        for arg in args {
+            if arg.layout.ty.is_simd() {
                 assert_matches!(arg.val, OperandValue::Immediate(_));
             }
         }
     }
 
     if name == sym::simd_select_bitmask {
-        let (len, _) = require_simd!(arg_tys[1], SimdArgument);
+        let (len, _) = require_simd!(args[1].layout.ty, SimdArgument);
 
         let expected_int_bits = len.max(8).next_power_of_two();
         let expected_bytes = len.div_ceil(8);
 
-        let mask_ty = arg_tys[0];
+        let mask_ty = args[0].layout.ty;
         let mask = match mask_ty.kind() {
             ty::Int(i) if i.bit_width() == Some(expected_int_bits) => args[0].immediate(),
             ty::Uint(i) if i.bit_width() == Some(expected_int_bits) => args[0].immediate(),
@@ -1291,8 +1251,8 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
     }
 
     // every intrinsic below takes a SIMD vector as its first argument
-    let (in_len, in_elem) = require_simd!(arg_tys[0], SimdInput);
-    let in_ty = arg_tys[0];
+    let (in_len, in_elem) = require_simd!(args[0].layout.ty, SimdInput);
+    let in_ty = args[0].layout.ty;
 
     let comparison = match name {
         sym::simd_eq => Some(BinOp::Eq),
@@ -1423,13 +1383,13 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
 
     if name == sym::simd_insert || name == sym::simd_insert_dyn {
         require!(
-            in_elem == arg_tys[2],
+            in_elem == args[2].layout.ty,
             InvalidMonomorphization::InsertedType {
                 span,
                 name,
                 in_elem,
                 in_ty,
-                out_ty: arg_tys[2]
+                out_ty: args[2].layout.ty
             }
         );
 
@@ -1480,7 +1440,7 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
     if name == sym::simd_select {
         let m_elem_ty = in_elem;
         let m_len = in_len;
-        let (v_len, _) = require_simd!(arg_tys[1], SimdArgument);
+        let (v_len, _) = require_simd!(args[1].layout.ty, SimdArgument);
         require!(
             m_len == v_len,
             InvalidMonomorphization::MismatchedLengths { span, name, m_len, v_len }
@@ -1681,9 +1641,9 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
         // The second argument must be a simd vector with an element type that's a pointer
         // to the element type of the first argument
         let (_, element_ty0) = require_simd!(in_ty, SimdFirst);
-        let (out_len, element_ty1) = require_simd!(arg_tys[1], SimdSecond);
+        let (out_len, element_ty1) = require_simd!(args[1].layout.ty, SimdSecond);
         // The element type of the third argument must be a signed integer type of any width:
-        let (out_len2, element_ty2) = require_simd!(arg_tys[2], SimdThird);
+        let (out_len2, element_ty2) = require_simd!(args[2].layout.ty, SimdThird);
         require_simd!(ret_ty, SimdReturn);
 
         // Of the same length:
@@ -1694,7 +1654,7 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
                 name,
                 in_len,
                 in_ty,
-                arg_ty: arg_tys[1],
+                arg_ty: args[1].layout.ty,
                 out_len
             }
         );
@@ -1705,7 +1665,7 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
                 name,
                 in_len,
                 in_ty,
-                arg_ty: arg_tys[2],
+                arg_ty: args[2].layout.ty,
                 out_len: out_len2
             }
         );
@@ -1725,7 +1685,7 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
                 span,
                 name,
                 expected_element: element_ty1,
-                second_arg: arg_tys[1],
+                second_arg: args[1].layout.ty,
                 in_elem,
                 in_ty,
                 mutability: ExpectedPointerMutability::Not,
@@ -1786,10 +1746,10 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
         let (mask_len, mask_elem) = (in_len, in_elem);
 
         // The second argument must be a pointer matching the element type
-        let pointer_ty = arg_tys[1];
+        let pointer_ty = args[1].layout.ty;
 
         // The last argument is a passthrough vector providing values for disabled lanes
-        let values_ty = arg_tys[2];
+        let values_ty = args[2].layout.ty;
         let (values_len, values_elem) = require_simd!(values_ty, SimdThird);
 
         require_simd!(ret_ty, SimdReturn);
@@ -1877,10 +1837,10 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
         let (mask_len, mask_elem) = (in_len, in_elem);
 
         // The second argument must be a pointer matching the element type
-        let pointer_ty = arg_tys[1];
+        let pointer_ty = args[1].layout.ty;
 
         // The last argument specifies the values to store to memory
-        let values_ty = arg_tys[2];
+        let values_ty = args[2].layout.ty;
         let (values_len, values_elem) = require_simd!(values_ty, SimdThird);
 
         // Of the same length:
@@ -1960,8 +1920,8 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
         // The second argument must be a simd vector with an element type that's a pointer
         // to the element type of the first argument
         let (_, element_ty0) = require_simd!(in_ty, SimdFirst);
-        let (element_len1, element_ty1) = require_simd!(arg_tys[1], SimdSecond);
-        let (element_len2, element_ty2) = require_simd!(arg_tys[2], SimdThird);
+        let (element_len1, element_ty1) = require_simd!(args[1].layout.ty, SimdSecond);
+        let (element_len2, element_ty2) = require_simd!(args[2].layout.ty, SimdThird);
 
         // Of the same length:
         require!(
@@ -1971,7 +1931,7 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
                 name,
                 in_len,
                 in_ty,
-                arg_ty: arg_tys[1],
+                arg_ty: args[1].layout.ty,
                 out_len: element_len1
             }
         );
@@ -1982,7 +1942,7 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
                 name,
                 in_len,
                 in_ty,
-                arg_ty: arg_tys[2],
+                arg_ty: args[2].layout.ty,
                 out_len: element_len2
             }
         );
@@ -1997,7 +1957,7 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
                 span,
                 name,
                 expected_element: element_ty1,
-                second_arg: arg_tys[1],
+                second_arg: args[1].layout.ty,
                 in_elem,
                 in_ty,
                 mutability: ExpectedPointerMutability::Mut,
@@ -2519,7 +2479,7 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
         let ptrs = args[0].immediate();
         // The second argument must be a ptr-sized integer.
         // (We don't care about the signedness, this is wrapping anyway.)
-        let (_offsets_len, offsets_elem) = arg_tys[1].simd_size_and_type(bx.tcx());
+        let (_offsets_len, offsets_elem) = args[1].layout.ty.simd_size_and_type(bx.tcx());
         if !matches!(offsets_elem.kind(), ty::Int(ty::IntTy::Isize) | ty::Uint(ty::UintTy::Usize)) {
             span_bug!(
                 span,
@@ -2543,8 +2503,8 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
                 return_error!(InvalidMonomorphization::ExpectedVectorElementType {
                     span,
                     name,
-                    expected_element: arg_tys[0].simd_size_and_type(bx.tcx()).1,
-                    vector_type: arg_tys[0]
+                    expected_element: args[0].layout.ty.simd_size_and_type(bx.tcx()).1,
+                    vector_type: args[0].layout.ty
                 });
             }
         };
diff --git a/compiler/rustc_codegen_llvm/src/lib.rs b/compiler/rustc_codegen_llvm/src/lib.rs
index 5736314b96a..fd376ea8d80 100644
--- a/compiler/rustc_codegen_llvm/src/lib.rs
+++ b/compiler/rustc_codegen_llvm/src/lib.rs
@@ -189,13 +189,13 @@ impl WriteBackendMethods for LlvmCodegenBackend {
     ) -> Result<(Vec<LtoModuleCodegen<Self>>, Vec<WorkProduct>), FatalError> {
         back::lto::run_thin(cgcx, modules, cached_modules)
     }
-    unsafe fn optimize(
+    fn optimize(
         cgcx: &CodegenContext<Self>,
         dcx: DiagCtxtHandle<'_>,
         module: &mut ModuleCodegen<Self::Module>,
         config: &ModuleConfig,
     ) -> Result<(), FatalError> {
-        unsafe { back::write::optimize(cgcx, dcx, module, config) }
+        back::write::optimize(cgcx, dcx, module, config)
     }
     fn optimize_fat(
         cgcx: &CodegenContext<Self>,
@@ -205,19 +205,19 @@ impl WriteBackendMethods for LlvmCodegenBackend {
         let dcx = dcx.handle();
         back::lto::run_pass_manager(cgcx, dcx, module, false)
     }
-    unsafe fn optimize_thin(
+    fn optimize_thin(
         cgcx: &CodegenContext<Self>,
         thin: ThinModule<Self>,
     ) -> Result<ModuleCodegen<Self::Module>, FatalError> {
-        unsafe { back::lto::optimize_thin_module(thin, cgcx) }
+        back::lto::optimize_thin_module(thin, cgcx)
     }
-    unsafe fn codegen(
+    fn codegen(
         cgcx: &CodegenContext<Self>,
         dcx: DiagCtxtHandle<'_>,
         module: ModuleCodegen<Self::Module>,
         config: &ModuleConfig,
     ) -> Result<CompiledModule, FatalError> {
-        unsafe { back::write::codegen(cgcx, dcx, module, config) }
+        back::write::codegen(cgcx, dcx, module, config)
     }
     fn prepare_thin(
         module: ModuleCodegen<Self::Module>,
diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
index 67a66e6ec79..e27fbf94f34 100644
--- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
@@ -426,14 +426,14 @@ pub(crate) enum AtomicOrdering {
 }
 
 impl AtomicOrdering {
-    pub(crate) fn from_generic(ao: rustc_codegen_ssa::common::AtomicOrdering) -> Self {
-        use rustc_codegen_ssa::common::AtomicOrdering as Common;
+    pub(crate) fn from_generic(ao: rustc_middle::ty::AtomicOrdering) -> Self {
+        use rustc_middle::ty::AtomicOrdering as Common;
         match ao {
             Common::Relaxed => Self::Monotonic,
             Common::Acquire => Self::Acquire,
             Common::Release => Self::Release,
-            Common::AcquireRelease => Self::AcquireRelease,
-            Common::SequentiallyConsistent => Self::SequentiallyConsistent,
+            Common::AcqRel => Self::AcquireRelease,
+            Common::SeqCst => Self::SequentiallyConsistent,
         }
     }
 }
diff --git a/compiler/rustc_codegen_llvm/src/mono_item.rs b/compiler/rustc_codegen_llvm/src/mono_item.rs
index fdf62a08065..3f38e1e191b 100644
--- a/compiler/rustc_codegen_llvm/src/mono_item.rs
+++ b/compiler/rustc_codegen_llvm/src/mono_item.rs
@@ -16,7 +16,7 @@ use crate::{base, llvm};
 
 impl<'tcx> PreDefineCodegenMethods<'tcx> for CodegenCx<'_, 'tcx> {
     fn predefine_static(
-        &self,
+        &mut self,
         def_id: DefId,
         linkage: Linkage,
         visibility: Visibility,
@@ -44,7 +44,7 @@ impl<'tcx> PreDefineCodegenMethods<'tcx> for CodegenCx<'_, 'tcx> {
     }
 
     fn predefine_fn(
-        &self,
+        &mut self,
         instance: Instance<'tcx>,
         linkage: Linkage,
         visibility: Visibility,
diff --git a/compiler/rustc_codegen_llvm/src/va_arg.rs b/compiler/rustc_codegen_llvm/src/va_arg.rs
index c216f0f4a09..236568590be 100644
--- a/compiler/rustc_codegen_llvm/src/va_arg.rs
+++ b/compiler/rustc_codegen_llvm/src/va_arg.rs
@@ -1,7 +1,10 @@
-use rustc_abi::{Align, Endian, HasDataLayout, Size};
+use rustc_abi::{Align, BackendRepr, Endian, HasDataLayout, Primitive, Size, TyAndLayout};
+use rustc_codegen_ssa::MemFlags;
 use rustc_codegen_ssa::common::IntPredicate;
 use rustc_codegen_ssa::mir::operand::OperandRef;
-use rustc_codegen_ssa::traits::{BaseTypeCodegenMethods, BuilderMethods, ConstCodegenMethods};
+use rustc_codegen_ssa::traits::{
+    BaseTypeCodegenMethods, BuilderMethods, ConstCodegenMethods, LayoutTypeCodegenMethods,
+};
 use rustc_middle::ty::Ty;
 use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf};
 
@@ -37,6 +40,7 @@ fn emit_direct_ptr_va_arg<'ll, 'tcx>(
     align: Align,
     slot_size: Align,
     allow_higher_align: bool,
+    force_right_adjust: bool,
 ) -> (&'ll Value, Align) {
     let va_list_ty = bx.type_ptr();
     let va_list_addr = list.immediate();
@@ -54,7 +58,10 @@ fn emit_direct_ptr_va_arg<'ll, 'tcx>(
     let next = bx.inbounds_ptradd(addr, full_direct_size);
     bx.store(next, va_list_addr, bx.tcx().data_layout.pointer_align.abi);
 
-    if size.bytes() < slot_size.bytes() && bx.tcx().sess.target.endian == Endian::Big {
+    if size.bytes() < slot_size.bytes()
+        && bx.tcx().sess.target.endian == Endian::Big
+        && force_right_adjust
+    {
         let adjusted_size = bx.cx().const_i32((slot_size.bytes() - size.bytes()) as i32);
         let adjusted = bx.inbounds_ptradd(addr, adjusted_size);
         (adjusted, addr_align)
@@ -63,14 +70,40 @@ fn emit_direct_ptr_va_arg<'ll, 'tcx>(
     }
 }
 
+enum PassMode {
+    Direct,
+    Indirect,
+}
+
+enum SlotSize {
+    Bytes8 = 8,
+    Bytes4 = 4,
+}
+
+enum AllowHigherAlign {
+    No,
+    Yes,
+}
+
+enum ForceRightAdjust {
+    No,
+    Yes,
+}
+
 fn emit_ptr_va_arg<'ll, 'tcx>(
     bx: &mut Builder<'_, 'll, 'tcx>,
     list: OperandRef<'tcx, &'ll Value>,
     target_ty: Ty<'tcx>,
-    indirect: bool,
-    slot_size: Align,
-    allow_higher_align: bool,
+    pass_mode: PassMode,
+    slot_size: SlotSize,
+    allow_higher_align: AllowHigherAlign,
+    force_right_adjust: ForceRightAdjust,
 ) -> &'ll Value {
+    let indirect = matches!(pass_mode, PassMode::Indirect);
+    let allow_higher_align = matches!(allow_higher_align, AllowHigherAlign::Yes);
+    let force_right_adjust = matches!(force_right_adjust, ForceRightAdjust::Yes);
+    let slot_size = Align::from_bytes(slot_size as u64).unwrap();
+
     let layout = bx.cx.layout_of(target_ty);
     let (llty, size, align) = if indirect {
         (
@@ -81,8 +114,15 @@ fn emit_ptr_va_arg<'ll, 'tcx>(
     } else {
         (layout.llvm_type(bx.cx), layout.size, layout.align)
     };
-    let (addr, addr_align) =
-        emit_direct_ptr_va_arg(bx, list, size, align.abi, slot_size, allow_higher_align);
+    let (addr, addr_align) = emit_direct_ptr_va_arg(
+        bx,
+        list,
+        size,
+        align.abi,
+        slot_size,
+        allow_higher_align,
+        force_right_adjust,
+    );
     if indirect {
         let tmp_ret = bx.load(llty, addr, addr_align);
         bx.load(bx.cx.layout_of(target_ty).llvm_type(bx.cx), tmp_ret, align.abi)
@@ -179,8 +219,15 @@ fn emit_aapcs_va_arg<'ll, 'tcx>(
 
     // On Stack block
     bx.switch_to_block(on_stack);
-    let stack_value =
-        emit_ptr_va_arg(bx, list, target_ty, false, Align::from_bytes(8).unwrap(), true);
+    let stack_value = emit_ptr_va_arg(
+        bx,
+        list,
+        target_ty,
+        PassMode::Direct,
+        SlotSize::Bytes8,
+        AllowHigherAlign::Yes,
+        ForceRightAdjust::No,
+    );
     bx.br(end);
 
     bx.switch_to_block(end);
@@ -190,6 +237,150 @@ fn emit_aapcs_va_arg<'ll, 'tcx>(
     val
 }
 
+fn emit_powerpc_va_arg<'ll, 'tcx>(
+    bx: &mut Builder<'_, 'll, 'tcx>,
+    list: OperandRef<'tcx, &'ll Value>,
+    target_ty: Ty<'tcx>,
+) -> &'ll Value {
+    let dl = bx.cx.data_layout();
+
+    // struct __va_list_tag {
+    //   unsigned char gpr;
+    //   unsigned char fpr;
+    //   unsigned short reserved;
+    //   void *overflow_arg_area;
+    //   void *reg_save_area;
+    // };
+    let va_list_addr = list.immediate();
+
+    // Peel off any newtype wrappers.
+    let layout = {
+        let mut layout = bx.cx.layout_of(target_ty);
+
+        while let Some((_, inner)) = layout.non_1zst_field(bx.cx) {
+            layout = inner;
+        }
+
+        layout
+    };
+
+    // Rust does not currently support any powerpc softfloat targets.
+    let target = &bx.cx.tcx.sess.target;
+    let is_soft_float_abi = target.abi == "softfloat";
+    assert!(!is_soft_float_abi);
+
+    // All instances of VaArgSafe are passed directly.
+    let is_indirect = false;
+
+    let (is_i64, is_int, is_f64) = match layout.layout.backend_repr() {
+        BackendRepr::Scalar(scalar) => match scalar.primitive() {
+            rustc_abi::Primitive::Int(integer, _) => (integer.size().bits() == 64, true, false),
+            rustc_abi::Primitive::Float(float) => (false, false, float.size().bits() == 64),
+            rustc_abi::Primitive::Pointer(_) => (false, true, false),
+        },
+        _ => unreachable!("all instances of VaArgSafe are represented as scalars"),
+    };
+
+    let num_regs_addr = if is_int || is_soft_float_abi {
+        va_list_addr // gpr
+    } else {
+        bx.inbounds_ptradd(va_list_addr, bx.const_usize(1)) // fpr
+    };
+
+    let mut num_regs = bx.load(bx.type_i8(), num_regs_addr, dl.i8_align.abi);
+
+    // "Align" the register count when the type is passed as `i64`.
+    if is_i64 || (is_f64 && is_soft_float_abi) {
+        num_regs = bx.add(num_regs, bx.const_u8(1));
+        num_regs = bx.and(num_regs, bx.const_u8(0b1111_1110));
+    }
+
+    let max_regs = 8u8;
+    let use_regs = bx.icmp(IntPredicate::IntULT, num_regs, bx.const_u8(max_regs));
+
+    let in_reg = bx.append_sibling_block("va_arg.in_reg");
+    let in_mem = bx.append_sibling_block("va_arg.in_mem");
+    let end = bx.append_sibling_block("va_arg.end");
+
+    bx.cond_br(use_regs, in_reg, in_mem);
+
+    let reg_addr = {
+        bx.switch_to_block(in_reg);
+
+        let reg_safe_area_ptr = bx.inbounds_ptradd(va_list_addr, bx.cx.const_usize(1 + 1 + 2 + 4));
+        let mut reg_addr = bx.load(bx.type_ptr(), reg_safe_area_ptr, dl.pointer_align.abi);
+
+        // Floating-point registers start after the general-purpose registers.
+        if !is_int && !is_soft_float_abi {
+            reg_addr = bx.inbounds_ptradd(reg_addr, bx.cx.const_usize(32))
+        }
+
+        // Get the address of the saved value by scaling the number of
+        // registers we've used by the number of.
+        let reg_size = if is_int || is_soft_float_abi { 4 } else { 8 };
+        let reg_offset = bx.mul(num_regs, bx.cx().const_u8(reg_size));
+        let reg_addr = bx.inbounds_ptradd(reg_addr, reg_offset);
+
+        // Increase the used-register count.
+        let reg_incr = if is_i64 || (is_f64 && is_soft_float_abi) { 2 } else { 1 };
+        let new_num_regs = bx.add(num_regs, bx.cx.const_u8(reg_incr));
+        bx.store(new_num_regs, num_regs_addr, dl.i8_align.abi);
+
+        bx.br(end);
+
+        reg_addr
+    };
+
+    let mem_addr = {
+        bx.switch_to_block(in_mem);
+
+        bx.store(bx.const_u8(max_regs), num_regs_addr, dl.i8_align.abi);
+
+        // Everything in the overflow area is rounded up to a size of at least 4.
+        let overflow_area_align = Align::from_bytes(4).unwrap();
+
+        let size = if !is_indirect {
+            layout.layout.size.align_to(overflow_area_align)
+        } else {
+            dl.pointer_size
+        };
+
+        let overflow_area_ptr = bx.inbounds_ptradd(va_list_addr, bx.cx.const_usize(1 + 1 + 2));
+        let mut overflow_area = bx.load(bx.type_ptr(), overflow_area_ptr, dl.pointer_align.abi);
+
+        // Round up address of argument to alignment
+        if layout.layout.align.abi > overflow_area_align {
+            overflow_area = round_pointer_up_to_alignment(
+                bx,
+                overflow_area,
+                layout.layout.align.abi,
+                bx.type_ptr(),
+            );
+        }
+
+        let mem_addr = overflow_area;
+
+        // Increase the overflow area.
+        overflow_area = bx.inbounds_ptradd(overflow_area, bx.const_usize(size.bytes()));
+        bx.store(overflow_area, overflow_area_ptr, dl.pointer_align.abi);
+
+        bx.br(end);
+
+        mem_addr
+    };
+
+    // Return the appropriate result.
+    bx.switch_to_block(end);
+    let val_addr = bx.phi(bx.type_ptr(), &[reg_addr, mem_addr], &[in_reg, in_mem]);
+    let val_type = layout.llvm_type(bx);
+    let val_addr = if is_indirect {
+        bx.load(bx.cx.type_ptr(), val_addr, dl.pointer_align.abi)
+    } else {
+        val_addr
+    };
+    bx.load(val_type, val_addr, layout.align.abi)
+}
+
 fn emit_s390x_va_arg<'ll, 'tcx>(
     bx: &mut Builder<'_, 'll, 'tcx>,
     list: OperandRef<'tcx, &'ll Value>,
@@ -278,6 +469,313 @@ fn emit_s390x_va_arg<'ll, 'tcx>(
     bx.load(val_type, val_addr, layout.align.abi)
 }
 
+fn emit_x86_64_sysv64_va_arg<'ll, 'tcx>(
+    bx: &mut Builder<'_, 'll, 'tcx>,
+    list: OperandRef<'tcx, &'ll Value>,
+    target_ty: Ty<'tcx>,
+) -> &'ll Value {
+    let dl = bx.cx.data_layout();
+
+    // Implementation of the systemv x86_64 ABI calling convention for va_args, see
+    // https://gitlab.com/x86-psABIs/x86-64-ABI (section 3.5.7). This implementation is heavily
+    // based on the one in clang.
+
+    // We're able to take some shortcuts because the return type of `va_arg` must implement the
+    // `VaArgSafe` trait. Currently, only pointers, f64, i32, u32, i64 and u64 implement this trait.
+
+    // typedef struct __va_list_tag {
+    //     unsigned int gp_offset;
+    //     unsigned int fp_offset;
+    //     void *overflow_arg_area;
+    //     void *reg_save_area;
+    // } va_list[1];
+    let va_list_addr = list.immediate();
+
+    // Peel off any newtype wrappers.
+    //
+    // The "C" ABI does not unwrap newtypes (see `ReprOptions::inhibit_newtype_abi_optimization`).
+    // Here, we do actually want the unwrapped representation, because that is how LLVM/Clang
+    // pass such types to variadic functions.
+    //
+    // An example of a type that must be unwrapped is `Foo` below. Without the unwrapping, it has
+    // `BackendRepr::Memory`, but we need it to be `BackendRepr::Scalar` to generate correct code.
+    //
+    // ```
+    // #[repr(C)]
+    // struct Empty;
+    //
+    // #[repr(C)]
+    // struct Foo([Empty; 8], i32);
+    // ```
+    let layout = {
+        let mut layout = bx.cx.layout_of(target_ty);
+
+        while let Some((_, inner)) = layout.non_1zst_field(bx.cx) {
+            layout = inner;
+        }
+
+        layout
+    };
+
+    // AMD64-ABI 3.5.7p5: Step 1. Determine whether type may be passed
+    // in the registers. If not go to step 7.
+
+    // AMD64-ABI 3.5.7p5: Step 2. Compute num_gp to hold the number of
+    // general purpose registers needed to pass type and num_fp to hold
+    // the number of floating point registers needed.
+
+    let mut num_gp_registers = 0;
+    let mut num_fp_registers = 0;
+
+    let mut registers_for_primitive = |p| match p {
+        Primitive::Int(integer, _is_signed) => {
+            num_gp_registers += integer.size().bytes().div_ceil(8) as u32;
+        }
+        Primitive::Float(float) => {
+            num_fp_registers += float.size().bytes().div_ceil(16) as u32;
+        }
+        Primitive::Pointer(_) => {
+            num_gp_registers += 1;
+        }
+    };
+
+    match layout.layout.backend_repr() {
+        BackendRepr::Scalar(scalar) => {
+            registers_for_primitive(scalar.primitive());
+        }
+        BackendRepr::ScalarPair(scalar1, scalar2) => {
+            registers_for_primitive(scalar1.primitive());
+            registers_for_primitive(scalar2.primitive());
+        }
+        BackendRepr::SimdVector { .. } => {
+            // Because no instance of VaArgSafe uses a non-scalar `BackendRepr`.
+            unreachable!(
+                "No x86-64 SysV va_arg implementation for {:?}",
+                layout.layout.backend_repr()
+            )
+        }
+        BackendRepr::Memory { .. } => {
+            let mem_addr = x86_64_sysv64_va_arg_from_memory(bx, va_list_addr, layout);
+            return bx.load(layout.llvm_type(bx), mem_addr, layout.align.abi);
+        }
+    };
+
+    // AMD64-ABI 3.5.7p5: Step 3. Verify whether arguments fit into
+    // registers. In the case: l->gp_offset > 48 - num_gp * 8 or
+    // l->fp_offset > 176 - num_fp * 16 go to step 7.
+
+    let unsigned_int_offset = 4;
+    let ptr_offset = 8;
+    let gp_offset_ptr = va_list_addr;
+    let fp_offset_ptr = bx.inbounds_ptradd(va_list_addr, bx.cx.const_usize(unsigned_int_offset));
+
+    let gp_offset_v = bx.load(bx.type_i32(), gp_offset_ptr, Align::from_bytes(8).unwrap());
+    let fp_offset_v = bx.load(bx.type_i32(), fp_offset_ptr, Align::from_bytes(4).unwrap());
+
+    let mut use_regs = bx.const_bool(false);
+
+    if num_gp_registers > 0 {
+        let max_offset_val = 48u32 - num_gp_registers * 8;
+        let fits_in_gp = bx.icmp(IntPredicate::IntULE, gp_offset_v, bx.const_u32(max_offset_val));
+        use_regs = fits_in_gp;
+    }
+
+    if num_fp_registers > 0 {
+        let max_offset_val = 176u32 - num_fp_registers * 16;
+        let fits_in_fp = bx.icmp(IntPredicate::IntULE, fp_offset_v, bx.const_u32(max_offset_val));
+        use_regs = if num_gp_registers > 0 { bx.and(use_regs, fits_in_fp) } else { fits_in_fp };
+    }
+
+    let in_reg = bx.append_sibling_block("va_arg.in_reg");
+    let in_mem = bx.append_sibling_block("va_arg.in_mem");
+    let end = bx.append_sibling_block("va_arg.end");
+
+    bx.cond_br(use_regs, in_reg, in_mem);
+
+    // Emit code to load the value if it was passed in a register.
+    bx.switch_to_block(in_reg);
+
+    // AMD64-ABI 3.5.7p5: Step 4. Fetch type from l->reg_save_area with
+    // an offset of l->gp_offset and/or l->fp_offset. This may require
+    // copying to a temporary location in case the parameter is passed
+    // in different register classes or requires an alignment greater
+    // than 8 for general purpose registers and 16 for XMM registers.
+    //
+    // FIXME(llvm): This really results in shameful code when we end up needing to
+    // collect arguments from different places; often what should result in a
+    // simple assembling of a structure from scattered addresses has many more
+    // loads than necessary. Can we clean this up?
+    let reg_save_area_ptr =
+        bx.inbounds_ptradd(va_list_addr, bx.cx.const_usize(2 * unsigned_int_offset + ptr_offset));
+    let reg_save_area_v = bx.load(bx.type_ptr(), reg_save_area_ptr, dl.pointer_align.abi);
+
+    let reg_addr = match layout.layout.backend_repr() {
+        BackendRepr::Scalar(scalar) => match scalar.primitive() {
+            Primitive::Int(_, _) | Primitive::Pointer(_) => {
+                let reg_addr = bx.inbounds_ptradd(reg_save_area_v, gp_offset_v);
+
+                // Copy into a temporary if the type is more aligned than the register save area.
+                let gp_align = Align::from_bytes(8).unwrap();
+                copy_to_temporary_if_more_aligned(bx, reg_addr, layout, gp_align)
+            }
+            Primitive::Float(_) => bx.inbounds_ptradd(reg_save_area_v, fp_offset_v),
+        },
+        BackendRepr::ScalarPair(scalar1, scalar2) => {
+            let ty_lo = bx.cx().scalar_pair_element_backend_type(layout, 0, false);
+            let ty_hi = bx.cx().scalar_pair_element_backend_type(layout, 1, false);
+
+            let align_lo = layout.field(bx.cx, 0).layout.align().abi;
+            let align_hi = layout.field(bx.cx, 1).layout.align().abi;
+
+            match (scalar1.primitive(), scalar2.primitive()) {
+                (Primitive::Float(_), Primitive::Float(_)) => {
+                    // SSE registers are spaced 16 bytes apart in the register save
+                    // area, we need to collect the two eightbytes together.
+                    // The ABI isn't explicit about this, but it seems reasonable
+                    // to assume that the slots are 16-byte aligned, since the stack is
+                    // naturally 16-byte aligned and the prologue is expected to store
+                    // all the SSE registers to the RSA.
+                    let reg_lo_addr = bx.inbounds_ptradd(reg_save_area_v, fp_offset_v);
+                    let reg_hi_addr = bx.inbounds_ptradd(reg_lo_addr, bx.const_i32(16));
+
+                    let align = layout.layout.align().abi;
+                    let tmp = bx.alloca(layout.layout.size(), align);
+
+                    let reg_lo = bx.load(ty_lo, reg_lo_addr, align_lo);
+                    let reg_hi = bx.load(ty_hi, reg_hi_addr, align_hi);
+
+                    let offset = scalar1.size(bx.cx).align_to(align_hi).bytes();
+                    let field0 = tmp;
+                    let field1 = bx.inbounds_ptradd(tmp, bx.const_u32(offset as u32));
+
+                    bx.store(reg_lo, field0, align);
+                    bx.store(reg_hi, field1, align);
+
+                    tmp
+                }
+                (Primitive::Float(_), _) | (_, Primitive::Float(_)) => {
+                    let gp_addr = bx.inbounds_ptradd(reg_save_area_v, gp_offset_v);
+                    let fp_addr = bx.inbounds_ptradd(reg_save_area_v, fp_offset_v);
+
+                    let (reg_lo_addr, reg_hi_addr) = match scalar1.primitive() {
+                        Primitive::Float(_) => (fp_addr, gp_addr),
+                        Primitive::Int(_, _) | Primitive::Pointer(_) => (gp_addr, fp_addr),
+                    };
+
+                    let tmp = bx.alloca(layout.layout.size(), layout.layout.align().abi);
+
+                    let reg_lo = bx.load(ty_lo, reg_lo_addr, align_lo);
+                    let reg_hi = bx.load(ty_hi, reg_hi_addr, align_hi);
+
+                    let offset = scalar1.size(bx.cx).align_to(align_hi).bytes();
+                    let field0 = tmp;
+                    let field1 = bx.inbounds_ptradd(tmp, bx.const_u32(offset as u32));
+
+                    bx.store(reg_lo, field0, align_lo);
+                    bx.store(reg_hi, field1, align_hi);
+
+                    tmp
+                }
+                (_, _) => {
+                    // Two integer/pointer values are just contiguous in memory.
+                    let reg_addr = bx.inbounds_ptradd(reg_save_area_v, gp_offset_v);
+
+                    // Copy into a temporary if the type is more aligned than the register save area.
+                    let gp_align = Align::from_bytes(8).unwrap();
+                    copy_to_temporary_if_more_aligned(bx, reg_addr, layout, gp_align)
+                }
+            }
+        }
+        // The Previous match on `BackendRepr` means control flow already escaped.
+        BackendRepr::SimdVector { .. } | BackendRepr::Memory { .. } => unreachable!(),
+    };
+
+    // AMD64-ABI 3.5.7p5: Step 5. Set:
+    // l->gp_offset = l->gp_offset + num_gp * 8
+    if num_gp_registers > 0 {
+        let offset = bx.const_u32(num_gp_registers * 8);
+        let sum = bx.add(gp_offset_v, offset);
+        // An alignment of 8 because `__va_list_tag` is 8-aligned and this is its first field.
+        bx.store(sum, gp_offset_ptr, Align::from_bytes(8).unwrap());
+    }
+
+    // l->fp_offset = l->fp_offset + num_fp * 16.
+    if num_fp_registers > 0 {
+        let offset = bx.const_u32(num_fp_registers * 16);
+        let sum = bx.add(fp_offset_v, offset);
+        bx.store(sum, fp_offset_ptr, Align::from_bytes(4).unwrap());
+    }
+
+    bx.br(end);
+
+    bx.switch_to_block(in_mem);
+    let mem_addr = x86_64_sysv64_va_arg_from_memory(bx, va_list_addr, layout);
+    bx.br(end);
+
+    bx.switch_to_block(end);
+
+    let val_type = layout.llvm_type(bx);
+    let val_addr = bx.phi(bx.type_ptr(), &[reg_addr, mem_addr], &[in_reg, in_mem]);
+
+    bx.load(val_type, val_addr, layout.align.abi)
+}
+
+/// Copy into a temporary if the type is more aligned than the register save area.
+fn copy_to_temporary_if_more_aligned<'ll, 'tcx>(
+    bx: &mut Builder<'_, 'll, 'tcx>,
+    reg_addr: &'ll Value,
+    layout: TyAndLayout<'tcx, Ty<'tcx>>,
+    src_align: Align,
+) -> &'ll Value {
+    if layout.layout.align.abi > src_align {
+        let tmp = bx.alloca(layout.layout.size(), layout.layout.align().abi);
+        bx.memcpy(
+            tmp,
+            layout.layout.align.abi,
+            reg_addr,
+            src_align,
+            bx.const_u32(layout.layout.size().bytes() as u32),
+            MemFlags::empty(),
+        );
+        tmp
+    } else {
+        reg_addr
+    }
+}
+
+fn x86_64_sysv64_va_arg_from_memory<'ll, 'tcx>(
+    bx: &mut Builder<'_, 'll, 'tcx>,
+    va_list_addr: &'ll Value,
+    layout: TyAndLayout<'tcx, Ty<'tcx>>,
+) -> &'ll Value {
+    let dl = bx.cx.data_layout();
+
+    let overflow_arg_area_ptr = bx.inbounds_ptradd(va_list_addr, bx.const_usize(8));
+
+    let overflow_arg_area_v = bx.load(bx.type_ptr(), overflow_arg_area_ptr, dl.pointer_align.abi);
+    // AMD64-ABI 3.5.7p5: Step 7. Align l->overflow_arg_area upwards to a 16
+    // byte boundary if alignment needed by type exceeds 8 byte boundary.
+    // It isn't stated explicitly in the standard, but in practice we use
+    // alignment greater than 16 where necessary.
+    if layout.layout.align.abi.bytes() > 8 {
+        unreachable!("all instances of VaArgSafe have an alignment <= 8");
+    }
+
+    // AMD64-ABI 3.5.7p5: Step 8. Fetch type from l->overflow_arg_area.
+    let mem_addr = overflow_arg_area_v;
+
+    // AMD64-ABI 3.5.7p5: Step 9. Set l->overflow_arg_area to:
+    // l->overflow_arg_area + sizeof(type).
+    // AMD64-ABI 3.5.7p5: Step 10. Align l->overflow_arg_area upwards to
+    // an 8 byte boundary.
+    let size_in_bytes = layout.layout.size().bytes();
+    let offset = bx.const_i32(size_in_bytes.next_multiple_of(8) as i32);
+    let overflow_arg_area = bx.inbounds_ptradd(overflow_arg_area_v, offset);
+    bx.store(overflow_arg_area, overflow_arg_area_ptr, dl.pointer_align.abi);
+
+    mem_addr
+}
+
 fn emit_xtensa_va_arg<'ll, 'tcx>(
     bx: &mut Builder<'_, 'll, 'tcx>,
     list: OperandRef<'tcx, &'ll Value>,
@@ -309,8 +807,7 @@ fn emit_xtensa_va_arg<'ll, 'tcx>(
     // (*va).va_ndx
     let va_reg_offset = 4;
     let va_ndx_offset = va_reg_offset + 4;
-    let offset_ptr =
-        bx.inbounds_gep(bx.type_i8(), va_list_addr, &[bx.cx.const_usize(va_ndx_offset)]);
+    let offset_ptr = bx.inbounds_ptradd(va_list_addr, bx.cx.const_usize(va_ndx_offset));
 
     let offset = bx.load(bx.type_i32(), offset_ptr, bx.tcx().data_layout.i32_align.abi);
     let offset = round_up_to_alignment(bx, offset, layout.align.abi);
@@ -331,11 +828,10 @@ fn emit_xtensa_va_arg<'ll, 'tcx>(
     bx.store(offset_next, offset_ptr, bx.tcx().data_layout.pointer_align.abi);
 
     // (*va).va_reg
-    let regsave_area_ptr =
-        bx.inbounds_gep(bx.type_i8(), va_list_addr, &[bx.cx.const_usize(va_reg_offset)]);
+    let regsave_area_ptr = bx.inbounds_ptradd(va_list_addr, bx.cx.const_usize(va_reg_offset));
     let regsave_area =
         bx.load(bx.type_ptr(), regsave_area_ptr, bx.tcx().data_layout.pointer_align.abi);
-    let regsave_value_ptr = bx.inbounds_gep(bx.type_i8(), regsave_area, &[offset]);
+    let regsave_value_ptr = bx.inbounds_ptradd(regsave_area, offset);
     bx.br(end);
 
     bx.switch_to_block(from_stack);
@@ -356,9 +852,9 @@ fn emit_xtensa_va_arg<'ll, 'tcx>(
     bx.store(offset_next_corrected, offset_ptr, bx.tcx().data_layout.pointer_align.abi);
 
     // let stack_value_ptr = unsafe { (*va).va_stk.byte_add(offset_corrected) };
-    let stack_area_ptr = bx.inbounds_gep(bx.type_i8(), va_list_addr, &[bx.cx.const_usize(0)]);
+    let stack_area_ptr = bx.inbounds_ptradd(va_list_addr, bx.cx.const_usize(0));
     let stack_area = bx.load(bx.type_ptr(), stack_area_ptr, bx.tcx().data_layout.pointer_align.abi);
-    let stack_value_ptr = bx.inbounds_gep(bx.type_i8(), stack_area, &[offset_corrected]);
+    let stack_value_ptr = bx.inbounds_ptradd(stack_area, offset_corrected);
     bx.br(end);
 
     bx.switch_to_block(end);
@@ -386,30 +882,62 @@ pub(super) fn emit_va_arg<'ll, 'tcx>(
     // Determine the va_arg implementation to use. The LLVM va_arg instruction
     // is lacking in some instances, so we should only use it as a fallback.
     let target = &bx.cx.tcx.sess.target;
-    let arch = &bx.cx.tcx.sess.target.arch;
-    match &**arch {
-        // Windows x86
-        "x86" if target.is_like_windows => {
-            emit_ptr_va_arg(bx, addr, target_ty, false, Align::from_bytes(4).unwrap(), false)
-        }
-        // Generic x86
-        "x86" => emit_ptr_va_arg(bx, addr, target_ty, false, Align::from_bytes(4).unwrap(), true),
-        // Windows AArch64
-        "aarch64" | "arm64ec" if target.is_like_windows => {
-            emit_ptr_va_arg(bx, addr, target_ty, false, Align::from_bytes(8).unwrap(), false)
-        }
-        // macOS / iOS AArch64
-        "aarch64" if target.is_like_darwin => {
-            emit_ptr_va_arg(bx, addr, target_ty, false, Align::from_bytes(8).unwrap(), true)
+
+    match &*target.arch {
+        "x86" => emit_ptr_va_arg(
+            bx,
+            addr,
+            target_ty,
+            PassMode::Direct,
+            SlotSize::Bytes4,
+            if target.is_like_windows { AllowHigherAlign::No } else { AllowHigherAlign::Yes },
+            ForceRightAdjust::No,
+        ),
+        "aarch64" | "arm64ec" if target.is_like_windows || target.is_like_darwin => {
+            emit_ptr_va_arg(
+                bx,
+                addr,
+                target_ty,
+                PassMode::Direct,
+                SlotSize::Bytes8,
+                if target.is_like_windows { AllowHigherAlign::No } else { AllowHigherAlign::Yes },
+                ForceRightAdjust::No,
+            )
         }
         "aarch64" => emit_aapcs_va_arg(bx, addr, target_ty),
         "s390x" => emit_s390x_va_arg(bx, addr, target_ty),
+        "powerpc" => emit_powerpc_va_arg(bx, addr, target_ty),
+        "powerpc64" | "powerpc64le" => emit_ptr_va_arg(
+            bx,
+            addr,
+            target_ty,
+            PassMode::Direct,
+            SlotSize::Bytes8,
+            AllowHigherAlign::Yes,
+            match &*target.arch {
+                "powerpc64" => ForceRightAdjust::Yes,
+                _ => ForceRightAdjust::No,
+            },
+        ),
         // Windows x86_64
         "x86_64" if target.is_like_windows => {
             let target_ty_size = bx.cx.size_of(target_ty).bytes();
-            let indirect: bool = target_ty_size > 8 || !target_ty_size.is_power_of_two();
-            emit_ptr_va_arg(bx, addr, target_ty, indirect, Align::from_bytes(8).unwrap(), false)
+            emit_ptr_va_arg(
+                bx,
+                addr,
+                target_ty,
+                if target_ty_size > 8 || !target_ty_size.is_power_of_two() {
+                    PassMode::Indirect
+                } else {
+                    PassMode::Direct
+                },
+                SlotSize::Bytes8,
+                AllowHigherAlign::No,
+                ForceRightAdjust::No,
+            )
         }
+        // This includes `target.is_like_darwin`, which on x86_64 targets is like sysv64.
+        "x86_64" => emit_x86_64_sysv64_va_arg(bx, addr, target_ty),
         "xtensa" => emit_xtensa_va_arg(bx, addr, target_ty),
         // For all other architecture/OS combinations fall back to using
         // the LLVM va_arg instruction.
diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs
index c5792da2678..1a39a0c3fda 100644
--- a/compiler/rustc_codegen_ssa/src/back/link.rs
+++ b/compiler/rustc_codegen_ssa/src/back/link.rs
@@ -3,10 +3,10 @@ mod raw_dylib;
 use std::collections::BTreeSet;
 use std::ffi::OsString;
 use std::fs::{File, OpenOptions, read};
-use std::io::{BufWriter, Write};
+use std::io::{BufReader, BufWriter, Write};
 use std::ops::{ControlFlow, Deref};
 use std::path::{Path, PathBuf};
-use std::process::{ExitStatus, Output, Stdio};
+use std::process::{Output, Stdio};
 use std::{env, fmt, fs, io, mem, str};
 
 use cc::windows_registry;
@@ -68,6 +68,23 @@ pub fn ensure_removed(dcx: DiagCtxtHandle<'_>, path: &Path) {
     }
 }
 
+fn check_link_info_print_request(sess: &Session, crate_types: &[CrateType]) {
+    let print_native_static_libs =
+        sess.opts.prints.iter().any(|p| p.kind == PrintKind::NativeStaticLibs);
+    let has_staticlib = crate_types.iter().any(|ct| *ct == CrateType::Staticlib);
+    if print_native_static_libs {
+        if !has_staticlib {
+            sess.dcx()
+                .warn(format!("cannot output linkage information without staticlib crate-type"));
+            sess.dcx()
+                .note(format!("consider `--crate-type staticlib` to print linkage information"));
+        } else if !sess.opts.output_types.should_link() {
+            sess.dcx()
+                .warn(format!("cannot output linkage information when --emit link is not passed"));
+        }
+    }
+}
+
 /// Performs the linkage portion of the compilation phase. This will generate all
 /// of the requested outputs for this compilation session.
 pub fn link_binary(
@@ -167,6 +184,12 @@ pub fn link_binary(
                 );
             }
 
+            if sess.target.binary_format == BinaryFormat::Elf {
+                if let Err(err) = warn_if_linked_with_gold(sess, &out_filename) {
+                    info!(?err, "Error while checking if gold was the linker");
+                }
+            }
+
             if output.is_stdout() {
                 if output.is_tty() {
                     sess.dcx().emit_err(errors::BinaryOutputToTty {
@@ -180,6 +203,8 @@ pub fn link_binary(
         }
     }
 
+    check_link_info_print_request(sess, &codegen_results.crate_info.crate_types);
+
     // Remove the temporary object file and metadata if we aren't saving temps.
     sess.time("link_binary_remove_temps", || {
         // If the user requests that temporaries are saved, don't delete any.
@@ -717,13 +742,10 @@ fn link_natively(
 
     // Invoke the system linker
     info!("{cmd:?}");
-    let retry_on_segfault = env::var("RUSTC_RETRY_LINKER_ON_SEGFAULT").is_ok();
     let unknown_arg_regex =
         Regex::new(r"(unknown|unrecognized) (command line )?(option|argument)").unwrap();
     let mut prog;
-    let mut i = 0;
     loop {
-        i += 1;
         prog = sess.time("run_linker", || exec_linker(sess, &cmd, out_filename, flavor, tmpdir));
         let Ok(ref output) = prog else {
             break;
@@ -839,54 +861,7 @@ fn link_natively(
             continue;
         }
 
-        // Here's a terribly awful hack that really shouldn't be present in any
-        // compiler. Here an environment variable is supported to automatically
-        // retry the linker invocation if the linker looks like it segfaulted.
-        //
-        // Gee that seems odd, normally segfaults are things we want to know
-        // about!  Unfortunately though in rust-lang/rust#38878 we're
-        // experiencing the linker segfaulting on Travis quite a bit which is
-        // causing quite a bit of pain to land PRs when they spuriously fail
-        // due to a segfault.
-        //
-        // The issue #38878 has some more debugging information on it as well,
-        // but this unfortunately looks like it's just a race condition in
-        // macOS's linker with some thread pool working in the background. It
-        // seems that no one currently knows a fix for this so in the meantime
-        // we're left with this...
-        if !retry_on_segfault || i > 3 {
-            break;
-        }
-        let msg_segv = "clang: error: unable to execute command: Segmentation fault: 11";
-        let msg_bus = "clang: error: unable to execute command: Bus error: 10";
-        if out.contains(msg_segv) || out.contains(msg_bus) {
-            warn!(
-                ?cmd, %out,
-                "looks like the linker segfaulted when we tried to call it, \
-                 automatically retrying again",
-            );
-            continue;
-        }
-
-        if is_illegal_instruction(&output.status) {
-            warn!(
-                ?cmd, %out, status = %output.status,
-                "looks like the linker hit an illegal instruction when we \
-                 tried to call it, automatically retrying again.",
-            );
-            continue;
-        }
-
-        #[cfg(unix)]
-        fn is_illegal_instruction(status: &ExitStatus) -> bool {
-            use std::os::unix::prelude::*;
-            status.signal() == Some(libc::SIGILL)
-        }
-
-        #[cfg(not(unix))]
-        fn is_illegal_instruction(_status: &ExitStatus) -> bool {
-            false
-        }
+        break;
     }
 
     match prog {
@@ -3406,3 +3381,54 @@ fn add_lld_args(
         }
     }
 }
+
+// gold has been deprecated with binutils 2.44
+// and is known to behave incorrectly around Rust programs.
+// There have been reports of being unable to bootstrap with gold:
+// https://github.com/rust-lang/rust/issues/139425
+// Additionally, gold miscompiles SHF_GNU_RETAIN sections, which are
+// emitted with `#[used(linker)]`.
+fn warn_if_linked_with_gold(sess: &Session, path: &Path) -> Result<(), Box<dyn std::error::Error>> {
+    use object::read::elf::{FileHeader, SectionHeader};
+    use object::read::{ReadCache, ReadRef, Result};
+    use object::{Endianness, elf};
+
+    fn elf_has_gold_version_note<'a>(
+        elf: &impl FileHeader,
+        data: impl ReadRef<'a>,
+    ) -> Result<bool> {
+        let endian = elf.endian()?;
+
+        let section =
+            elf.sections(endian, data)?.section_by_name(endian, b".note.gnu.gold-version");
+        if let Some((_, section)) = section {
+            if let Some(mut notes) = section.notes(endian, data)? {
+                return Ok(notes.any(|note| {
+                    note.is_ok_and(|note| note.n_type(endian) == elf::NT_GNU_GOLD_VERSION)
+                }));
+            }
+        }
+
+        Ok(false)
+    }
+
+    let data = ReadCache::new(BufReader::new(File::open(path)?));
+
+    let was_linked_with_gold = if sess.target.pointer_width == 64 {
+        let elf = elf::FileHeader64::<Endianness>::parse(&data)?;
+        elf_has_gold_version_note(elf, &data)?
+    } else if sess.target.pointer_width == 32 {
+        let elf = elf::FileHeader32::<Endianness>::parse(&data)?;
+        elf_has_gold_version_note(elf, &data)?
+    } else {
+        return Ok(());
+    };
+
+    if was_linked_with_gold {
+        let mut warn =
+            sess.dcx().struct_warn("the gold linker is deprecated and has known bugs with Rust");
+        warn.help("consider using LLD or ld from GNU binutils instead");
+        warn.emit();
+    }
+    Ok(())
+}
diff --git a/compiler/rustc_codegen_ssa/src/back/lto.rs b/compiler/rustc_codegen_ssa/src/back/lto.rs
index 9fd984b6419..ce6fe8a191b 100644
--- a/compiler/rustc_codegen_ssa/src/back/lto.rs
+++ b/compiler/rustc_codegen_ssa/src/back/lto.rs
@@ -56,12 +56,7 @@ impl<B: WriteBackendMethods> LtoModuleCodegen<B> {
     }
 
     /// Optimize this module within the given codegen context.
-    ///
-    /// This function is unsafe as it'll return a `ModuleCodegen` still
-    /// points to LLVM data structures owned by this `LtoModuleCodegen`.
-    /// It's intended that the module returned is immediately code generated and
-    /// dropped, and then this LTO module is dropped.
-    pub unsafe fn optimize(
+    pub fn optimize(
         self,
         cgcx: &CodegenContext<B>,
     ) -> Result<ModuleCodegen<B::Module>, FatalError> {
@@ -70,7 +65,7 @@ impl<B: WriteBackendMethods> LtoModuleCodegen<B> {
                 B::optimize_fat(cgcx, &mut module)?;
                 Ok(module)
             }
-            LtoModuleCodegen::Thin(thin) => unsafe { B::optimize_thin(cgcx, thin) },
+            LtoModuleCodegen::Thin(thin) => B::optimize_thin(cgcx, thin),
         }
     }
 
@@ -85,7 +80,7 @@ impl<B: WriteBackendMethods> LtoModuleCodegen<B> {
     }
 
     /// Run autodiff on Fat LTO module
-    pub unsafe fn autodiff(
+    pub fn autodiff(
         self,
         cgcx: &CodegenContext<B>,
         diff_fncs: Vec<AutoDiffItem>,
diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs
index 0fd4ed8475b..a41ca8ce28b 100644
--- a/compiler/rustc_codegen_ssa/src/back/write.rs
+++ b/compiler/rustc_codegen_ssa/src/back/write.rs
@@ -383,7 +383,7 @@ pub struct CodegenContext<B: WriteBackendMethods> {
     pub coordinator_send: Sender<Box<dyn Any + Send>>,
     /// `true` if the codegen should be run in parallel.
     ///
-    /// Depends on [`CodegenBackend::supports_parallel()`] and `-Zno_parallel_backend`.
+    /// Depends on [`ExtraBackendMethods::supports_parallel()`] and `-Zno_parallel_backend`.
     pub parallel: bool,
 }
 
@@ -416,8 +416,7 @@ fn generate_lto_work<B: ExtraBackendMethods>(
             B::run_fat_lto(cgcx, needs_fat_lto, import_only_modules).unwrap_or_else(|e| e.raise());
         if cgcx.lto == Lto::Fat && !autodiff.is_empty() {
             let config = cgcx.config(ModuleKind::Regular);
-            module =
-                unsafe { module.autodiff(cgcx, autodiff, config).unwrap_or_else(|e| e.raise()) };
+            module = module.autodiff(cgcx, autodiff, config).unwrap_or_else(|e| e.raise());
         }
         // We are adding a single work item, so the cost doesn't matter.
         vec![(WorkItem::LTO(module), 0)]
@@ -887,9 +886,7 @@ fn execute_optimize_work_item<B: ExtraBackendMethods>(
     let dcx = cgcx.create_dcx();
     let dcx = dcx.handle();
 
-    unsafe {
-        B::optimize(cgcx, dcx, &mut module, module_config)?;
-    }
+    B::optimize(cgcx, dcx, &mut module, module_config)?;
 
     // After we've done the initial round of optimizations we need to
     // decide whether to synchronously codegen this module or ship it
@@ -1020,7 +1017,7 @@ fn execute_lto_work_item<B: ExtraBackendMethods>(
     module: lto::LtoModuleCodegen<B>,
     module_config: &ModuleConfig,
 ) -> Result<WorkItemResult<B>, FatalError> {
-    let module = unsafe { module.optimize(cgcx)? };
+    let module = module.optimize(cgcx)?;
     finish_intra_module_work(cgcx, module, module_config)
 }
 
@@ -1036,7 +1033,7 @@ fn finish_intra_module_work<B: ExtraBackendMethods>(
         || module.kind == ModuleKind::Metadata
         || module.kind == ModuleKind::Allocator
     {
-        let module = unsafe { B::codegen(cgcx, dcx, module, module_config)? };
+        let module = B::codegen(cgcx, dcx, module, module_config)?;
         Ok(WorkItemResult::Finished(module))
     } else {
         Ok(WorkItemResult::NeedsLink(module))
@@ -1725,9 +1722,8 @@ fn start_executing_work<B: ExtraBackendMethods>(
             let dcx = cgcx.create_dcx();
             let dcx = dcx.handle();
             let module = B::run_link(&cgcx, dcx, needs_link).map_err(|_| ())?;
-            let module = unsafe {
-                B::codegen(&cgcx, dcx, module, cgcx.config(ModuleKind::Regular)).map_err(|_| ())?
-            };
+            let module =
+                B::codegen(&cgcx, dcx, module, cgcx.config(ModuleKind::Regular)).map_err(|_| ())?;
             compiled_modules.push(module);
         }
 
diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs
index 1890119dca7..f7863fe4ae2 100644
--- a/compiler/rustc_codegen_ssa/src/base.rs
+++ b/compiler/rustc_codegen_ssa/src/base.rs
@@ -492,6 +492,7 @@ where
 /// users main function.
 pub fn maybe_create_entry_wrapper<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
     cx: &'a Bx::CodegenCx,
+    cgu: &CodegenUnit<'tcx>,
 ) -> Option<Bx::Function> {
     let (main_def_id, entry_type) = cx.tcx().entry_fn(())?;
     let main_is_local = main_def_id.is_local();
@@ -500,10 +501,10 @@ pub fn maybe_create_entry_wrapper<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
     if main_is_local {
         // We want to create the wrapper in the same codegen unit as Rust's main
         // function.
-        if !cx.codegen_unit().contains_item(&MonoItem::Fn(instance)) {
+        if !cgu.contains_item(&MonoItem::Fn(instance)) {
             return None;
         }
-    } else if !cx.codegen_unit().is_primary() {
+    } else if !cgu.is_primary() {
         // We want to create the wrapper only when the codegen unit is the primary one
         return None;
     }
diff --git a/compiler/rustc_codegen_ssa/src/common.rs b/compiler/rustc_codegen_ssa/src/common.rs
index 6d0c9d8d066..ef0d565333e 100644
--- a/compiler/rustc_codegen_ssa/src/common.rs
+++ b/compiler/rustc_codegen_ssa/src/common.rs
@@ -60,15 +60,6 @@ pub enum AtomicRmwBinOp {
 }
 
 #[derive(Copy, Clone, Debug)]
-pub enum AtomicOrdering {
-    Relaxed,
-    Acquire,
-    Release,
-    AcquireRelease,
-    SequentiallyConsistent,
-}
-
-#[derive(Copy, Clone, Debug)]
 pub enum SynchronizationScope {
     SingleThread,
     CrossThread,
diff --git a/compiler/rustc_codegen_ssa/src/meth.rs b/compiler/rustc_codegen_ssa/src/meth.rs
index 399c592432a..3a11ce6befb 100644
--- a/compiler/rustc_codegen_ssa/src/meth.rs
+++ b/compiler/rustc_codegen_ssa/src/meth.rs
@@ -77,7 +77,7 @@ fn dyn_trait_in_self<'tcx>(
     ty: Ty<'tcx>,
 ) -> Option<ty::ExistentialTraitRef<'tcx>> {
     for arg in ty.peel_refs().walk() {
-        if let GenericArgKind::Type(ty) = arg.unpack()
+        if let GenericArgKind::Type(ty) = arg.kind()
             && let ty::Dynamic(data, _, _) = ty.kind()
         {
             // FIXME(arbitrary_self_types): This is likely broken for receivers which
diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs
index 600d6ff6801..1baab62ae43 100644
--- a/compiler/rustc_codegen_ssa/src/mir/block.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/block.rs
@@ -1,6 +1,6 @@
 use std::cmp;
 
-use rustc_abi::{BackendRepr, ExternAbi, HasDataLayout, Reg, WrappingRange};
+use rustc_abi::{BackendRepr, ExternAbi, HasDataLayout, Reg, Size, WrappingRange};
 use rustc_ast as ast;
 use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
 use rustc_data_structures::packed::Pu128;
@@ -11,8 +11,8 @@ use rustc_middle::ty::print::{with_no_trimmed_paths, with_no_visible_paths};
 use rustc_middle::ty::{self, Instance, Ty};
 use rustc_middle::{bug, span_bug};
 use rustc_session::config::OptLevel;
+use rustc_span::Span;
 use rustc_span::source_map::Spanned;
-use rustc_span::{Span, sym};
 use rustc_target::callconv::{ArgAbi, FnAbi, PassMode};
 use tracing::{debug, info};
 
@@ -158,7 +158,7 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> {
         llargs: &[Bx::Value],
         destination: Option<(ReturnDest<'tcx, Bx::Value>, mir::BasicBlock)>,
         mut unwind: mir::UnwindAction,
-        copied_constant_arguments: &[PlaceRef<'tcx, <Bx as BackendTypes>::Value>],
+        lifetime_ends_after_call: &[(Bx::Value, Size)],
         instance: Option<Instance<'tcx>>,
         mergeable_succ: bool,
     ) -> MergingSucc {
@@ -245,8 +245,8 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> {
             if let Some((ret_dest, target)) = destination {
                 bx.switch_to_block(fx.llbb(target));
                 fx.set_debug_loc(bx, self.terminator.source_info);
-                for tmp in copied_constant_arguments {
-                    bx.lifetime_end(tmp.val.llval, tmp.layout.size);
+                for &(tmp, size) in lifetime_ends_after_call {
+                    bx.lifetime_end(tmp, size);
                 }
                 fx.store_return(bx, ret_dest, &fn_abi.ret, invokeret);
             }
@@ -259,8 +259,8 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> {
             }
 
             if let Some((ret_dest, target)) = destination {
-                for tmp in copied_constant_arguments {
-                    bx.lifetime_end(tmp.val.llval, tmp.layout.size);
+                for &(tmp, size) in lifetime_ends_after_call {
+                    bx.lifetime_end(tmp, size);
                 }
                 fx.store_return(bx, ret_dest, &fn_abi.ret, llret);
                 self.funclet_br(fx, bx, target, mergeable_succ)
@@ -827,7 +827,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
         helper: &TerminatorCodegenHelper<'tcx>,
         bx: &mut Bx,
         intrinsic: ty::IntrinsicDef,
-        instance: Option<Instance<'tcx>>,
+        instance: Instance<'tcx>,
         source_info: mir::SourceInfo,
         target: Option<mir::BasicBlock>,
         unwind: mir::UnwindAction,
@@ -836,58 +836,56 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
         // Emit a panic or a no-op for `assert_*` intrinsics.
         // These are intrinsics that compile to panics so that we can get a message
         // which mentions the offending type, even from a const context.
-        if let Some(requirement) = ValidityRequirement::from_intrinsic(intrinsic.name) {
-            let ty = instance.unwrap().args.type_at(0);
-
-            let do_panic = !bx
-                .tcx()
-                .check_validity_requirement((requirement, bx.typing_env().as_query_input(ty)))
-                .expect("expect to have layout during codegen");
-
-            let layout = bx.layout_of(ty);
-
-            Some(if do_panic {
-                let msg_str = with_no_visible_paths!({
-                    with_no_trimmed_paths!({
-                        if layout.is_uninhabited() {
-                            // Use this error even for the other intrinsics as it is more precise.
-                            format!("attempted to instantiate uninhabited type `{ty}`")
-                        } else if requirement == ValidityRequirement::Zero {
-                            format!("attempted to zero-initialize type `{ty}`, which is invalid")
-                        } else {
-                            format!(
-                                "attempted to leave type `{ty}` uninitialized, which is invalid"
-                            )
-                        }
-                    })
-                });
-                let msg = bx.const_str(&msg_str);
+        let Some(requirement) = ValidityRequirement::from_intrinsic(intrinsic.name) else {
+            return None;
+        };
 
-                // Obtain the panic entry point.
-                let (fn_abi, llfn, instance) =
-                    common::build_langcall(bx, Some(source_info.span), LangItem::PanicNounwind);
+        let ty = instance.args.type_at(0);
 
-                // Codegen the actual panic invoke/call.
-                helper.do_call(
-                    self,
-                    bx,
-                    fn_abi,
-                    llfn,
-                    &[msg.0, msg.1],
-                    target.as_ref().map(|bb| (ReturnDest::Nothing, *bb)),
-                    unwind,
-                    &[],
-                    Some(instance),
-                    mergeable_succ,
-                )
-            } else {
-                // a NOP
-                let target = target.unwrap();
-                helper.funclet_br(self, bx, target, mergeable_succ)
-            })
-        } else {
-            None
+        let is_valid = bx
+            .tcx()
+            .check_validity_requirement((requirement, bx.typing_env().as_query_input(ty)))
+            .expect("expect to have layout during codegen");
+
+        if is_valid {
+            // a NOP
+            let target = target.unwrap();
+            return Some(helper.funclet_br(self, bx, target, mergeable_succ));
         }
+
+        let layout = bx.layout_of(ty);
+
+        let msg_str = with_no_visible_paths!({
+            with_no_trimmed_paths!({
+                if layout.is_uninhabited() {
+                    // Use this error even for the other intrinsics as it is more precise.
+                    format!("attempted to instantiate uninhabited type `{ty}`")
+                } else if requirement == ValidityRequirement::Zero {
+                    format!("attempted to zero-initialize type `{ty}`, which is invalid")
+                } else {
+                    format!("attempted to leave type `{ty}` uninitialized, which is invalid")
+                }
+            })
+        });
+        let msg = bx.const_str(&msg_str);
+
+        // Obtain the panic entry point.
+        let (fn_abi, llfn, instance) =
+            common::build_langcall(bx, Some(source_info.span), LangItem::PanicNounwind);
+
+        // Codegen the actual panic invoke/call.
+        Some(helper.do_call(
+            self,
+            bx,
+            fn_abi,
+            llfn,
+            &[msg.0, msg.1],
+            target.as_ref().map(|bb| (ReturnDest::Nothing, *bb)),
+            unwind,
+            &[],
+            Some(instance),
+            mergeable_succ,
+        ))
     }
 
     fn codegen_call_terminator(
@@ -903,42 +901,127 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
         fn_span: Span,
         mergeable_succ: bool,
     ) -> MergingSucc {
-        let source_info = terminator.source_info;
-        let span = source_info.span;
+        let source_info = mir::SourceInfo { span: fn_span, ..terminator.source_info };
 
         // Create the callee. This is a fn ptr or zero-sized and hence a kind of scalar.
         let callee = self.codegen_operand(bx, func);
 
         let (instance, mut llfn) = match *callee.layout.ty.kind() {
-            ty::FnDef(def_id, args) => (
-                Some(ty::Instance::expect_resolve(
+            ty::FnDef(def_id, generic_args) => {
+                let instance = ty::Instance::expect_resolve(
                     bx.tcx(),
                     bx.typing_env(),
                     def_id,
-                    args,
+                    generic_args,
                     fn_span,
-                )),
-                None,
-            ),
+                );
+
+                let instance = match instance.def {
+                    // We don't need AsyncDropGlueCtorShim here because it is not `noop func`,
+                    // it is `func returning noop future`
+                    ty::InstanceKind::DropGlue(_, None) => {
+                        // Empty drop glue; a no-op.
+                        let target = target.unwrap();
+                        return helper.funclet_br(self, bx, target, mergeable_succ);
+                    }
+                    ty::InstanceKind::Intrinsic(def_id) => {
+                        let intrinsic = bx.tcx().intrinsic(def_id).unwrap();
+                        if let Some(merging_succ) = self.codegen_panic_intrinsic(
+                            &helper,
+                            bx,
+                            intrinsic,
+                            instance,
+                            source_info,
+                            target,
+                            unwind,
+                            mergeable_succ,
+                        ) {
+                            return merging_succ;
+                        }
+
+                        let result_layout =
+                            self.cx.layout_of(self.monomorphized_place_ty(destination.as_ref()));
+
+                        let (result, store_in_local) = if result_layout.is_zst() {
+                            (
+                                PlaceRef::new_sized(bx.const_undef(bx.type_ptr()), result_layout),
+                                None,
+                            )
+                        } else if let Some(local) = destination.as_local() {
+                            match self.locals[local] {
+                                LocalRef::Place(dest) => (dest, None),
+                                LocalRef::UnsizedPlace(_) => bug!("return type must be sized"),
+                                LocalRef::PendingOperand => {
+                                    // Currently, intrinsics always need a location to store
+                                    // the result, so we create a temporary `alloca` for the
+                                    // result.
+                                    let tmp = PlaceRef::alloca(bx, result_layout);
+                                    tmp.storage_live(bx);
+                                    (tmp, Some(local))
+                                }
+                                LocalRef::Operand(_) => {
+                                    bug!("place local already assigned to");
+                                }
+                            }
+                        } else {
+                            (self.codegen_place(bx, destination.as_ref()), None)
+                        };
+
+                        if result.val.align < result.layout.align.abi {
+                            // Currently, MIR code generation does not create calls
+                            // that store directly to fields of packed structs (in
+                            // fact, the calls it creates write only to temps).
+                            //
+                            // If someone changes that, please update this code path
+                            // to create a temporary.
+                            span_bug!(self.mir.span, "can't directly store to unaligned value");
+                        }
+
+                        let args: Vec<_> =
+                            args.iter().map(|arg| self.codegen_operand(bx, &arg.node)).collect();
+
+                        match self.codegen_intrinsic_call(bx, instance, &args, result, source_info)
+                        {
+                            Ok(()) => {
+                                if let Some(local) = store_in_local {
+                                    let op = bx.load_operand(result);
+                                    result.storage_dead(bx);
+                                    self.overwrite_local(local, LocalRef::Operand(op));
+                                    self.debug_introduce_local(bx, local);
+                                }
+
+                                return if let Some(target) = target {
+                                    helper.funclet_br(self, bx, target, mergeable_succ)
+                                } else {
+                                    bx.unreachable();
+                                    MergingSucc::False
+                                };
+                            }
+                            Err(instance) => {
+                                if intrinsic.must_be_overridden {
+                                    span_bug!(
+                                        fn_span,
+                                        "intrinsic {} must be overridden by codegen backend, but isn't",
+                                        intrinsic.name,
+                                    );
+                                }
+                                instance
+                            }
+                        }
+                    }
+                    _ => instance,
+                };
+
+                (Some(instance), None)
+            }
             ty::FnPtr(..) => (None, Some(callee.immediate())),
             _ => bug!("{} is not callable", callee.layout.ty),
         };
 
-        let def = instance.map(|i| i.def);
-
-        // We don't need AsyncDropGlueCtorShim here because it is not `noop func`,
-        // it is `func returning noop future`
-        if let Some(ty::InstanceKind::DropGlue(_, None)) = def {
-            // Empty drop glue; a no-op.
-            let target = target.unwrap();
-            return helper.funclet_br(self, bx, target, mergeable_succ);
-        }
-
         // FIXME(eddyb) avoid computing this if possible, when `instance` is
         // available - right now `sig` is only needed for getting the `abi`
         // and figuring out how many extra args were passed to a C-variadic `fn`.
         let sig = callee.layout.ty.fn_sig(bx.tcx());
-        let abi = sig.abi();
 
         let extra_args = &args[sig.inputs().skip_binder().len()..];
         let extra_args = bx.tcx().mk_type_list_from_iter(extra_args.iter().map(|op_arg| {
@@ -954,93 +1037,16 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
         // The arguments we'll be passing. Plus one to account for outptr, if used.
         let arg_count = fn_abi.args.len() + fn_abi.ret.is_indirect() as usize;
 
-        let instance = match def {
-            Some(ty::InstanceKind::Intrinsic(def_id)) => {
-                let intrinsic = bx.tcx().intrinsic(def_id).unwrap();
-                if let Some(merging_succ) = self.codegen_panic_intrinsic(
-                    &helper,
-                    bx,
-                    intrinsic,
-                    instance,
-                    source_info,
-                    target,
-                    unwind,
-                    mergeable_succ,
-                ) {
-                    return merging_succ;
-                }
-
-                let mut llargs = Vec::with_capacity(1);
-                let ret_dest = self.make_return_dest(
-                    bx,
-                    destination,
-                    &fn_abi.ret,
-                    &mut llargs,
-                    Some(intrinsic),
-                );
-                let dest = match ret_dest {
-                    _ if fn_abi.ret.is_indirect() => llargs[0],
-                    ReturnDest::Nothing => bx.const_undef(bx.type_ptr()),
-                    ReturnDest::IndirectOperand(dst, _) | ReturnDest::Store(dst) => dst.val.llval,
-                    ReturnDest::DirectOperand(_) => {
-                        bug!("Cannot use direct operand with an intrinsic call")
-                    }
-                };
-
-                let args: Vec<_> =
-                    args.iter().map(|arg| self.codegen_operand(bx, &arg.node)).collect();
-
-                if matches!(intrinsic, ty::IntrinsicDef { name: sym::caller_location, .. }) {
-                    let location = self
-                        .get_caller_location(bx, mir::SourceInfo { span: fn_span, ..source_info });
-
-                    assert_eq!(llargs, []);
-                    if let ReturnDest::IndirectOperand(tmp, _) = ret_dest {
-                        location.val.store(bx, tmp);
-                    }
-                    self.store_return(bx, ret_dest, &fn_abi.ret, location.immediate());
-                    return helper.funclet_br(self, bx, target.unwrap(), mergeable_succ);
-                }
-
-                let instance = *instance.as_ref().unwrap();
-                match Self::codegen_intrinsic_call(bx, instance, fn_abi, &args, dest, span) {
-                    Ok(()) => {
-                        if let ReturnDest::IndirectOperand(dst, _) = ret_dest {
-                            self.store_return(bx, ret_dest, &fn_abi.ret, dst.val.llval);
-                        }
-
-                        return if let Some(target) = target {
-                            helper.funclet_br(self, bx, target, mergeable_succ)
-                        } else {
-                            bx.unreachable();
-                            MergingSucc::False
-                        };
-                    }
-                    Err(instance) => {
-                        if intrinsic.must_be_overridden {
-                            span_bug!(
-                                span,
-                                "intrinsic {} must be overridden by codegen backend, but isn't",
-                                intrinsic.name,
-                            );
-                        }
-                        Some(instance)
-                    }
-                }
-            }
-            _ => instance,
-        };
-
         let mut llargs = Vec::with_capacity(arg_count);
 
         // We still need to call `make_return_dest` even if there's no `target`, since
         // `fn_abi.ret` could be `PassMode::Indirect`, even if it is uninhabited,
         // and `make_return_dest` adds the return-place indirect pointer to `llargs`.
-        let return_dest = self.make_return_dest(bx, destination, &fn_abi.ret, &mut llargs, None);
+        let return_dest = self.make_return_dest(bx, destination, &fn_abi.ret, &mut llargs);
         let destination = target.map(|target| (return_dest, target));
 
         // Split the rust-call tupled arguments off.
-        let (first_args, untuple) = if abi == ExternAbi::RustCall
+        let (first_args, untuple) = if sig.abi() == ExternAbi::RustCall
             && let Some((tup, args)) = args.split_last()
         {
             (args, Some(tup))
@@ -1048,11 +1054,14 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
             (args, None)
         };
 
-        let mut copied_constant_arguments = vec![];
+        // When generating arguments we sometimes introduce temporary allocations with lifetime
+        // that extend for the duration of a call. Keep track of those allocations and their sizes
+        // to generate `lifetime_end` when the call returns.
+        let mut lifetime_ends_after_call: Vec<(Bx::Value, Size)> = Vec::new();
         'make_args: for (i, arg) in first_args.iter().enumerate() {
             let mut op = self.codegen_operand(bx, &arg.node);
 
-            if let (0, Some(ty::InstanceKind::Virtual(_, idx))) = (i, def) {
+            if let (0, Some(ty::InstanceKind::Virtual(_, idx))) = (i, instance.map(|i| i.def)) {
                 match op.val {
                     Pair(data_ptr, meta) => {
                         // In the case of Rc<Self>, we need to explicitly pass a
@@ -1106,7 +1115,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                         // Make sure that we've actually unwrapped the rcvr down
                         // to a pointer or ref to `dyn* Trait`.
                         if !op.layout.ty.builtin_deref(true).unwrap().is_dyn_star() {
-                            span_bug!(span, "can't codegen a virtual call on {:#?}", op);
+                            span_bug!(fn_span, "can't codegen a virtual call on {:#?}", op);
                         }
                         let place = op.deref(bx.cx());
                         let data_place = place.project_field(bx, 0);
@@ -1122,7 +1131,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                         continue;
                     }
                     _ => {
-                        span_bug!(span, "can't codegen a virtual call on {:#?}", op);
+                        span_bug!(fn_span, "can't codegen a virtual call on {:#?}", op);
                     }
                 }
             }
@@ -1136,12 +1145,18 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                     bx.lifetime_start(tmp.val.llval, tmp.layout.size);
                     op.val.store(bx, tmp);
                     op.val = Ref(tmp.val);
-                    copied_constant_arguments.push(tmp);
+                    lifetime_ends_after_call.push((tmp.val.llval, tmp.layout.size));
                 }
                 _ => {}
             }
 
-            self.codegen_argument(bx, op, &mut llargs, &fn_abi.args[i]);
+            self.codegen_argument(
+                bx,
+                op,
+                &mut llargs,
+                &fn_abi.args[i],
+                &mut lifetime_ends_after_call,
+            );
         }
         let num_untupled = untuple.map(|tup| {
             self.codegen_arguments_untupled(
@@ -1149,6 +1164,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                 &tup.node,
                 &mut llargs,
                 &fn_abi.args[first_args.len()..],
+                &mut lifetime_ends_after_call,
             )
         });
 
@@ -1165,23 +1181,28 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                 mir_args + 1,
                 "#[track_caller] fn's must have 1 more argument in their ABI than in their MIR: {instance:?} {fn_span:?} {fn_abi:?}",
             );
-            let location =
-                self.get_caller_location(bx, mir::SourceInfo { span: fn_span, ..source_info });
+            let location = self.get_caller_location(bx, source_info);
             debug!(
                 "codegen_call_terminator({:?}): location={:?} (fn_span {:?})",
                 terminator, location, fn_span
             );
 
             let last_arg = fn_abi.args.last().unwrap();
-            self.codegen_argument(bx, location, &mut llargs, last_arg);
+            self.codegen_argument(
+                bx,
+                location,
+                &mut llargs,
+                last_arg,
+                &mut lifetime_ends_after_call,
+            );
         }
 
         let fn_ptr = match (instance, llfn) {
             (Some(instance), None) => bx.get_fn_addr(instance),
             (_, Some(llfn)) => llfn,
-            _ => span_bug!(span, "no instance or llfn for call"),
+            _ => span_bug!(fn_span, "no instance or llfn for call"),
         };
-        self.set_debug_loc(bx, mir::SourceInfo { span: fn_span, ..source_info });
+        self.set_debug_loc(bx, source_info);
         helper.do_call(
             self,
             bx,
@@ -1190,7 +1211,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
             &llargs,
             destination,
             unwind,
-            &copied_constant_arguments,
+            &lifetime_ends_after_call,
             instance,
             mergeable_succ,
         )
@@ -1480,6 +1501,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
         op: OperandRef<'tcx, Bx::Value>,
         llargs: &mut Vec<Bx::Value>,
         arg: &ArgAbi<'tcx, Ty<'tcx>>,
+        lifetime_ends_after_call: &mut Vec<(Bx::Value, Size)>,
     ) {
         match arg.mode {
             PassMode::Ignore => return,
@@ -1518,7 +1540,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                         None => arg.layout.align.abi,
                     };
                     let scratch = PlaceValue::alloca(bx, arg.layout.size, required_align);
+                    bx.lifetime_start(scratch.llval, arg.layout.size);
                     op.val.store(bx, scratch.with_type(arg.layout));
+                    lifetime_ends_after_call.push((scratch.llval, arg.layout.size));
                     (scratch.llval, scratch.align, true)
                 }
                 PassMode::Cast { .. } => {
@@ -1539,7 +1563,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                         // alignment requirements may be higher than the type's alignment, so copy
                         // to a higher-aligned alloca.
                         let scratch = PlaceValue::alloca(bx, arg.layout.size, required_align);
+                        bx.lifetime_start(scratch.llval, arg.layout.size);
                         bx.typed_place_copy(scratch, op_place_val, op.layout);
+                        lifetime_ends_after_call.push((scratch.llval, arg.layout.size));
                         (scratch.llval, scratch.align, true)
                     } else {
                         (op_place_val.llval, op_place_val.align, true)
@@ -1621,6 +1647,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
         operand: &mir::Operand<'tcx>,
         llargs: &mut Vec<Bx::Value>,
         args: &[ArgAbi<'tcx, Ty<'tcx>>],
+        lifetime_ends_after_call: &mut Vec<(Bx::Value, Size)>,
     ) -> usize {
         let tuple = self.codegen_operand(bx, operand);
 
@@ -1633,19 +1660,19 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
             for i in 0..tuple.layout.fields.count() {
                 let field_ptr = tuple_ptr.project_field(bx, i);
                 let field = bx.load_operand(field_ptr);
-                self.codegen_argument(bx, field, llargs, &args[i]);
+                self.codegen_argument(bx, field, llargs, &args[i], lifetime_ends_after_call);
             }
         } else {
             // If the tuple is immediate, the elements are as well.
             for i in 0..tuple.layout.fields.count() {
                 let op = tuple.extract_field(self, bx, i);
-                self.codegen_argument(bx, op, llargs, &args[i]);
+                self.codegen_argument(bx, op, llargs, &args[i], lifetime_ends_after_call);
             }
         }
         tuple.layout.fields.count()
     }
 
-    fn get_caller_location(
+    pub(super) fn get_caller_location(
         &mut self,
         bx: &mut Bx,
         source_info: mir::SourceInfo,
@@ -1846,7 +1873,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
         dest: mir::Place<'tcx>,
         fn_ret: &ArgAbi<'tcx, Ty<'tcx>>,
         llargs: &mut Vec<Bx::Value>,
-        intrinsic: Option<ty::IntrinsicDef>,
     ) -> ReturnDest<'tcx, Bx::Value> {
         // If the return is ignored, we can just return a do-nothing `ReturnDest`.
         if fn_ret.is_ignore() {
@@ -1866,13 +1892,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                         tmp.storage_live(bx);
                         llargs.push(tmp.val.llval);
                         ReturnDest::IndirectOperand(tmp, index)
-                    } else if intrinsic.is_some() {
-                        // Currently, intrinsics always need a location to store
-                        // the result, so we create a temporary `alloca` for the
-                        // result.
-                        let tmp = PlaceRef::alloca(bx, fn_ret.layout);
-                        tmp.storage_live(bx);
-                        ReturnDest::IndirectOperand(tmp, index)
                     } else {
                         ReturnDest::DirectOperand(index)
                     };
@@ -1882,7 +1901,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                 }
             }
         } else {
-            self.codegen_place(bx, mir::PlaceRef { local: dest.local, projection: dest.projection })
+            self.codegen_place(bx, dest.as_ref())
         };
         if fn_ret.is_indirect() {
             if dest.val.align < dest.layout.align.abi {
diff --git a/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs b/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs
index b0fcfee2adf..8c6f52084c2 100644
--- a/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs
@@ -1,9 +1,9 @@
 use rustc_abi::WrappingRange;
+use rustc_middle::bug;
+use rustc_middle::mir::SourceInfo;
 use rustc_middle::ty::{self, Ty, TyCtxt};
-use rustc_middle::{bug, span_bug};
 use rustc_session::config::OptLevel;
-use rustc_span::{Span, sym};
-use rustc_target::callconv::{FnAbi, PassMode};
+use rustc_span::sym;
 
 use super::FunctionCx;
 use super::operand::OperandRef;
@@ -52,25 +52,18 @@ fn memset_intrinsic<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
 impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
     /// In the `Err` case, returns the instance that should be called instead.
     pub fn codegen_intrinsic_call(
+        &mut self,
         bx: &mut Bx,
         instance: ty::Instance<'tcx>,
-        fn_abi: &FnAbi<'tcx, Ty<'tcx>>,
         args: &[OperandRef<'tcx, Bx::Value>],
-        llresult: Bx::Value,
-        span: Span,
+        result: PlaceRef<'tcx, Bx::Value>,
+        source_info: SourceInfo,
     ) -> Result<(), ty::Instance<'tcx>> {
-        let callee_ty = instance.ty(bx.tcx(), bx.typing_env());
+        let span = source_info.span;
 
-        let ty::FnDef(def_id, fn_args) = *callee_ty.kind() else {
-            span_bug!(span, "expected fn item type, found {}", callee_ty);
-        };
-
-        let sig = callee_ty.fn_sig(bx.tcx());
-        let sig = bx.tcx().normalize_erasing_late_bound_regions(bx.typing_env(), sig);
-        let arg_tys = sig.inputs();
-        let ret_ty = sig.output();
-        let name = bx.tcx().item_name(def_id);
+        let name = bx.tcx().item_name(instance.def_id());
         let name_str = name.as_str();
+        let fn_args = instance.args;
 
         // If we're swapping something that's *not* an `OperandValue::Ref`,
         // then we can do it directly and avoid the alloca.
@@ -96,8 +89,15 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
             }
         }
 
-        let llret_ty = bx.backend_type(bx.layout_of(ret_ty));
-        let result = PlaceRef::new_sized(llresult, fn_abi.ret.layout);
+        let ret_llval = |bx: &mut Bx, llval| {
+            if result.layout.ty.is_bool() {
+                let val = bx.from_immediate(llval);
+                bx.store_to_place(val, result.val);
+            } else if !result.layout.ty.is_unit() {
+                bx.store_to_place(llval, result.val);
+            }
+            Ok(())
+        };
 
         let llval = match name {
             sym::abort => {
@@ -105,6 +105,12 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                 return Ok(());
             }
 
+            sym::caller_location => {
+                let location = self.get_caller_location(bx, source_info);
+                location.val.store(bx, result);
+                return Ok(());
+            }
+
             sym::va_start => bx.va_start(args[0].immediate()),
             sym::va_end => bx.va_end(args[0].immediate()),
             sym::size_of_val => {
@@ -126,7 +132,11 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                     sym::vtable_align => ty::COMMON_VTABLE_ENTRIES_ALIGN,
                     _ => bug!(),
                 };
-                let value = meth::VirtualIndex::from_index(idx).get_usize(bx, vtable, callee_ty);
+                let value = meth::VirtualIndex::from_index(idx).get_usize(
+                    bx,
+                    vtable,
+                    instance.ty(bx.tcx(), bx.typing_env()),
+                );
                 match name {
                     // Size is always <= isize::MAX.
                     sym::vtable_size => {
@@ -147,7 +157,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
             | sym::type_name
             | sym::variant_count => {
                 let value = bx.tcx().const_eval_instance(bx.typing_env(), instance, span).unwrap();
-                OperandRef::from_const(bx, value, ret_ty).immediate_or_packed_pair(bx)
+                OperandRef::from_const(bx, value, result.layout.ty).immediate_or_packed_pair(bx)
             }
             sym::arith_offset => {
                 let ty = fn_args.type_at(0);
@@ -231,7 +241,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                 bx.or_disjoint(a, b)
             }
             sym::exact_div => {
-                let ty = arg_tys[0];
+                let ty = args[0].layout.ty;
                 match int_type_width_signed(ty, bx.tcx()) {
                     Some((_width, signed)) => {
                         if signed {
@@ -251,7 +261,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                 }
             }
             sym::fadd_fast | sym::fsub_fast | sym::fmul_fast | sym::fdiv_fast | sym::frem_fast => {
-                match float_type_width(arg_tys[0]) {
+                match float_type_width(args[0].layout.ty) {
                     Some(_width) => match name {
                         sym::fadd_fast => bx.fadd_fast(args[0].immediate(), args[1].immediate()),
                         sym::fsub_fast => bx.fsub_fast(args[0].immediate(), args[1].immediate()),
@@ -264,7 +274,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                         bx.tcx().dcx().emit_err(InvalidMonomorphization::BasicFloatType {
                             span,
                             name,
-                            ty: arg_tys[0],
+                            ty: args[0].layout.ty,
                         });
                         return Ok(());
                     }
@@ -274,7 +284,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
             | sym::fsub_algebraic
             | sym::fmul_algebraic
             | sym::fdiv_algebraic
-            | sym::frem_algebraic => match float_type_width(arg_tys[0]) {
+            | sym::frem_algebraic => match float_type_width(args[0].layout.ty) {
                 Some(_width) => match name {
                     sym::fadd_algebraic => {
                         bx.fadd_algebraic(args[0].immediate(), args[1].immediate())
@@ -297,40 +307,80 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                     bx.tcx().dcx().emit_err(InvalidMonomorphization::BasicFloatType {
                         span,
                         name,
-                        ty: arg_tys[0],
+                        ty: args[0].layout.ty,
                     });
                     return Ok(());
                 }
             },
 
             sym::float_to_int_unchecked => {
-                if float_type_width(arg_tys[0]).is_none() {
+                if float_type_width(args[0].layout.ty).is_none() {
                     bx.tcx().dcx().emit_err(InvalidMonomorphization::FloatToIntUnchecked {
                         span,
-                        ty: arg_tys[0],
+                        ty: args[0].layout.ty,
                     });
                     return Ok(());
                 }
-                let Some((_width, signed)) = int_type_width_signed(ret_ty, bx.tcx()) else {
+                let Some((_width, signed)) = int_type_width_signed(result.layout.ty, bx.tcx())
+                else {
                     bx.tcx().dcx().emit_err(InvalidMonomorphization::FloatToIntUnchecked {
                         span,
-                        ty: ret_ty,
+                        ty: result.layout.ty,
                     });
                     return Ok(());
                 };
                 if signed {
-                    bx.fptosi(args[0].immediate(), llret_ty)
+                    bx.fptosi(args[0].immediate(), bx.backend_type(result.layout))
                 } else {
-                    bx.fptoui(args[0].immediate(), llret_ty)
+                    bx.fptoui(args[0].immediate(), bx.backend_type(result.layout))
                 }
             }
 
             // This requires that atomic intrinsics follow a specific naming pattern:
             // "atomic_<operation>[_<ordering>]"
             name if let Some(atomic) = name_str.strip_prefix("atomic_") => {
-                use crate::common::AtomicOrdering::*;
+                use rustc_middle::ty::AtomicOrdering::*;
+
                 use crate::common::{AtomicRmwBinOp, SynchronizationScope};
 
+                let invalid_monomorphization = |ty| {
+                    bx.tcx().dcx().emit_err(InvalidMonomorphization::BasicIntegerType {
+                        span,
+                        name,
+                        ty,
+                    });
+                };
+
+                let parse_const_generic_ordering = |ord: ty::Value<'tcx>| {
+                    let discr = ord.valtree.unwrap_branch()[0].unwrap_leaf();
+                    discr.to_atomic_ordering()
+                };
+
+                // Some intrinsics have the ordering already converted to a const generic parameter, we handle those first.
+                match name {
+                    sym::atomic_load => {
+                        let ty = fn_args.type_at(0);
+                        let ordering = fn_args.const_at(1).to_value();
+                        if !(int_type_width_signed(ty, bx.tcx()).is_some() || ty.is_raw_ptr()) {
+                            invalid_monomorphization(ty);
+                            return Ok(());
+                        }
+                        let layout = bx.layout_of(ty);
+                        let source = args[0].immediate();
+                        let llval = bx.atomic_load(
+                            bx.backend_type(layout),
+                            source,
+                            parse_const_generic_ordering(ordering),
+                            layout.size,
+                        );
+
+                        return ret_llval(bx, llval);
+                    }
+
+                    // The rest falls back to below.
+                    _ => {}
+                }
+
                 let Some((instruction, ordering)) = atomic.split_once('_') else {
                     bx.sess().dcx().emit_fatal(errors::MissingMemoryOrdering);
                 };
@@ -339,19 +389,11 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                     "relaxed" => Relaxed,
                     "acquire" => Acquire,
                     "release" => Release,
-                    "acqrel" => AcquireRelease,
-                    "seqcst" => SequentiallyConsistent,
+                    "acqrel" => AcqRel,
+                    "seqcst" => SeqCst,
                     _ => bx.sess().dcx().emit_fatal(errors::UnknownAtomicOrdering),
                 };
 
-                let invalid_monomorphization = |ty| {
-                    bx.tcx().dcx().emit_err(InvalidMonomorphization::BasicIntegerType {
-                        span,
-                        name,
-                        ty,
-                    });
-                };
-
                 match instruction {
                     "cxchg" | "cxchgweak" => {
                         let Some((success, failure)) = ordering.split_once('_') else {
@@ -384,24 +426,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                         return Ok(());
                     }
 
-                    "load" => {
-                        let ty = fn_args.type_at(0);
-                        if int_type_width_signed(ty, bx.tcx()).is_some() || ty.is_raw_ptr() {
-                            let layout = bx.layout_of(ty);
-                            let size = layout.size;
-                            let source = args[0].immediate();
-                            bx.atomic_load(
-                                bx.backend_type(layout),
-                                source,
-                                parse_ordering(bx, ordering),
-                                size,
-                            )
-                        } else {
-                            invalid_monomorphization(ty);
-                            return Ok(());
-                        }
-                    }
-
                     "store" => {
                         let ty = fn_args.type_at(0);
                         if int_type_width_signed(ty, bx.tcx()).is_some() || ty.is_raw_ptr() {
@@ -528,20 +552,11 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
 
             _ => {
                 // Need to use backend-specific things in the implementation.
-                return bx.codegen_intrinsic_call(instance, fn_abi, args, llresult, span);
+                return bx.codegen_intrinsic_call(instance, args, result, span);
             }
         };
 
-        if !fn_abi.ret.is_ignore() {
-            if let PassMode::Cast { .. } = &fn_abi.ret.mode {
-                bx.store_to_place(llval, result.val);
-            } else {
-                OperandRef::from_immediate_or_packed_pair(bx, llval, result.layout)
-                    .val
-                    .store(bx, result);
-            }
-        }
-        Ok(())
+        ret_llval(bx, llval)
     }
 }
 
diff --git a/compiler/rustc_codegen_ssa/src/mono_item.rs b/compiler/rustc_codegen_ssa/src/mono_item.rs
index c2067e52afe..7b4268abe4b 100644
--- a/compiler/rustc_codegen_ssa/src/mono_item.rs
+++ b/compiler/rustc_codegen_ssa/src/mono_item.rs
@@ -11,11 +11,13 @@ pub trait MonoItemExt<'a, 'tcx> {
     fn define<Bx: BuilderMethods<'a, 'tcx>>(
         &self,
         cx: &'a mut Bx::CodegenCx,
+        cgu_name: &str,
         item_data: MonoItemData,
     );
     fn predefine<Bx: BuilderMethods<'a, 'tcx>>(
         &self,
-        cx: &'a Bx::CodegenCx,
+        cx: &'a mut Bx::CodegenCx,
+        cgu_name: &str,
         linkage: Linkage,
         visibility: Visibility,
     );
@@ -26,14 +28,10 @@ impl<'a, 'tcx: 'a> MonoItemExt<'a, 'tcx> for MonoItem<'tcx> {
     fn define<Bx: BuilderMethods<'a, 'tcx>>(
         &self,
         cx: &'a mut Bx::CodegenCx,
+        cgu_name: &str,
         item_data: MonoItemData,
     ) {
-        debug!(
-            "BEGIN IMPLEMENTING '{} ({})' in cgu {}",
-            self,
-            self.to_raw_string(),
-            cx.codegen_unit().name()
-        );
+        debug!("BEGIN IMPLEMENTING '{} ({})' in cgu {}", self, self.to_raw_string(), cgu_name);
 
         match *self {
             MonoItem::Static(def_id) => {
@@ -56,26 +54,17 @@ impl<'a, 'tcx: 'a> MonoItemExt<'a, 'tcx> for MonoItem<'tcx> {
             }
         }
 
-        debug!(
-            "END IMPLEMENTING '{} ({})' in cgu {}",
-            self,
-            self.to_raw_string(),
-            cx.codegen_unit().name()
-        );
+        debug!("END IMPLEMENTING '{} ({})' in cgu {}", self, self.to_raw_string(), cgu_name);
     }
 
     fn predefine<Bx: BuilderMethods<'a, 'tcx>>(
         &self,
-        cx: &'a Bx::CodegenCx,
+        cx: &'a mut Bx::CodegenCx,
+        cgu_name: &str,
         linkage: Linkage,
         visibility: Visibility,
     ) {
-        debug!(
-            "BEGIN PREDEFINING '{} ({})' in cgu {}",
-            self,
-            self.to_raw_string(),
-            cx.codegen_unit().name()
-        );
+        debug!("BEGIN PREDEFINING '{} ({})' in cgu {}", self, self.to_raw_string(), cgu_name);
 
         let symbol_name = self.symbol_name(cx.tcx()).name;
 
@@ -97,12 +86,7 @@ impl<'a, 'tcx: 'a> MonoItemExt<'a, 'tcx> for MonoItem<'tcx> {
             MonoItem::GlobalAsm(..) => {}
         }
 
-        debug!(
-            "END PREDEFINING '{} ({})' in cgu {}",
-            self,
-            self.to_raw_string(),
-            cx.codegen_unit().name()
-        );
+        debug!("END PREDEFINING '{} ({})' in cgu {}", self, self.to_raw_string(), cgu_name);
     }
 
     fn to_raw_string(&self) -> String {
diff --git a/compiler/rustc_codegen_ssa/src/traits/backend.rs b/compiler/rustc_codegen_ssa/src/traits/backend.rs
index e2f1458d062..95bf3b16685 100644
--- a/compiler/rustc_codegen_ssa/src/traits/backend.rs
+++ b/compiler/rustc_codegen_ssa/src/traits/backend.rs
@@ -21,12 +21,12 @@ use crate::back::write::TargetMachineFactoryFn;
 use crate::{CodegenResults, ModuleCodegen, TargetConfig};
 
 pub trait BackendTypes {
-    type Value: CodegenObject;
+    type Value: CodegenObject + PartialEq;
     type Metadata: CodegenObject;
     type Function: CodegenObject;
 
     type BasicBlock: Copy;
-    type Type: CodegenObject;
+    type Type: CodegenObject + PartialEq;
     type Funclet;
 
     // FIXME(eddyb) find a common convention for all of the debuginfo-related
@@ -97,13 +97,6 @@ pub trait CodegenBackend {
     fn link(&self, sess: &Session, codegen_results: CodegenResults, outputs: &OutputFilenames) {
         link_binary(sess, &ArArchiveBuilderBuilder, codegen_results, outputs);
     }
-
-    /// Returns `true` if this backend can be safely called from multiple threads.
-    ///
-    /// Defaults to `true`.
-    fn supports_parallel(&self) -> bool {
-        true
-    }
 }
 
 pub trait ExtraBackendMethods:
@@ -144,4 +137,11 @@ pub trait ExtraBackendMethods:
     {
         std::thread::Builder::new().name(name).spawn(f)
     }
+
+    /// Returns `true` if this backend can be safely called from multiple threads.
+    ///
+    /// Defaults to `true`.
+    fn supports_parallel(&self) -> bool {
+        true
+    }
 }
diff --git a/compiler/rustc_codegen_ssa/src/traits/builder.rs b/compiler/rustc_codegen_ssa/src/traits/builder.rs
index f66309cf340..7f78bc75695 100644
--- a/compiler/rustc_codegen_ssa/src/traits/builder.rs
+++ b/compiler/rustc_codegen_ssa/src/traits/builder.rs
@@ -4,7 +4,7 @@ use std::ops::Deref;
 use rustc_abi::{Align, Scalar, Size, WrappingRange};
 use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs;
 use rustc_middle::ty::layout::{FnAbiOf, LayoutOf, TyAndLayout};
-use rustc_middle::ty::{Instance, Ty};
+use rustc_middle::ty::{AtomicOrdering, Instance, Ty};
 use rustc_session::config::OptLevel;
 use rustc_span::Span;
 use rustc_target::callconv::FnAbi;
@@ -19,9 +19,7 @@ use super::misc::MiscCodegenMethods;
 use super::type_::{ArgAbiBuilderMethods, BaseTypeCodegenMethods, LayoutTypeCodegenMethods};
 use super::{CodegenMethods, StaticBuilderMethods};
 use crate::MemFlags;
-use crate::common::{
-    AtomicOrdering, AtomicRmwBinOp, IntPredicate, RealPredicate, SynchronizationScope, TypeKind,
-};
+use crate::common::{AtomicRmwBinOp, IntPredicate, RealPredicate, SynchronizationScope, TypeKind};
 use crate::mir::operand::{OperandRef, OperandValue};
 use crate::mir::place::{PlaceRef, PlaceValue};
 
@@ -514,11 +512,11 @@ pub trait BuilderMethods<'a, 'tcx>:
     fn extract_value(&mut self, agg_val: Self::Value, idx: u64) -> Self::Value;
     fn insert_value(&mut self, agg_val: Self::Value, elt: Self::Value, idx: u64) -> Self::Value;
 
-    fn set_personality_fn(&mut self, personality: Self::Value);
+    fn set_personality_fn(&mut self, personality: Self::Function);
 
     // These are used by everyone except msvc
-    fn cleanup_landing_pad(&mut self, pers_fn: Self::Value) -> (Self::Value, Self::Value);
-    fn filter_landing_pad(&mut self, pers_fn: Self::Value) -> (Self::Value, Self::Value);
+    fn cleanup_landing_pad(&mut self, pers_fn: Self::Function) -> (Self::Value, Self::Value);
+    fn filter_landing_pad(&mut self, pers_fn: Self::Function) -> (Self::Value, Self::Value);
     fn resume(&mut self, exn0: Self::Value, exn1: Self::Value);
 
     // These are used only by msvc
diff --git a/compiler/rustc_codegen_ssa/src/traits/debuginfo.rs b/compiler/rustc_codegen_ssa/src/traits/debuginfo.rs
index 30d77c206a5..b9d4950e0ad 100644
--- a/compiler/rustc_codegen_ssa/src/traits/debuginfo.rs
+++ b/compiler/rustc_codegen_ssa/src/traits/debuginfo.rs
@@ -81,7 +81,6 @@ pub trait DebugInfoBuilderMethods: BackendTypes {
     );
     fn set_dbg_loc(&mut self, dbg_loc: Self::DILocation);
     fn clear_dbg_loc(&mut self);
-    fn get_dbg_loc(&self) -> Option<Self::DILocation>;
     fn insert_reference_to_gdb_debug_scripts_section_global(&mut self);
     fn set_var_name(&mut self, value: Self::Value, name: &str);
 }
diff --git a/compiler/rustc_codegen_ssa/src/traits/declare.rs b/compiler/rustc_codegen_ssa/src/traits/declare.rs
index c1edeac31b0..9f735546558 100644
--- a/compiler/rustc_codegen_ssa/src/traits/declare.rs
+++ b/compiler/rustc_codegen_ssa/src/traits/declare.rs
@@ -4,14 +4,14 @@ use rustc_middle::ty::Instance;
 
 pub trait PreDefineCodegenMethods<'tcx> {
     fn predefine_static(
-        &self,
+        &mut self,
         def_id: DefId,
         linkage: Linkage,
         visibility: Visibility,
         symbol_name: &str,
     );
     fn predefine_fn(
-        &self,
+        &mut self,
         instance: Instance<'tcx>,
         linkage: Linkage,
         visibility: Visibility,
diff --git a/compiler/rustc_codegen_ssa/src/traits/intrinsic.rs b/compiler/rustc_codegen_ssa/src/traits/intrinsic.rs
index 88cf8dbf0c5..7d0c6be4c65 100644
--- a/compiler/rustc_codegen_ssa/src/traits/intrinsic.rs
+++ b/compiler/rustc_codegen_ssa/src/traits/intrinsic.rs
@@ -1,9 +1,9 @@
-use rustc_middle::ty::{self, Ty};
+use rustc_middle::ty;
 use rustc_span::Span;
-use rustc_target::callconv::FnAbi;
 
 use super::BackendTypes;
 use crate::mir::operand::OperandRef;
+use crate::mir::place::PlaceRef;
 
 pub trait IntrinsicCallBuilderMethods<'tcx>: BackendTypes {
     /// Remember to add all intrinsics here, in `compiler/rustc_hir_analysis/src/check/mod.rs`,
@@ -14,17 +14,14 @@ pub trait IntrinsicCallBuilderMethods<'tcx>: BackendTypes {
     fn codegen_intrinsic_call(
         &mut self,
         instance: ty::Instance<'tcx>,
-        fn_abi: &FnAbi<'tcx, Ty<'tcx>>,
         args: &[OperandRef<'tcx, Self::Value>],
-        llresult: Self::Value,
+        result: PlaceRef<'tcx, Self::Value>,
         span: Span,
     ) -> Result<(), ty::Instance<'tcx>>;
 
     fn abort(&mut self);
     fn assume(&mut self, val: Self::Value);
     fn expect(&mut self, cond: Self::Value, expected: bool) -> Self::Value;
-    /// Trait method used to test whether a given pointer is associated with a type identifier.
-    fn type_test(&mut self, pointer: Self::Value, typeid: Self::Metadata) -> Self::Value;
     /// Trait method used to load a function while testing if it is associated with a type
     /// identifier.
     fn type_checked_load(
diff --git a/compiler/rustc_codegen_ssa/src/traits/misc.rs b/compiler/rustc_codegen_ssa/src/traits/misc.rs
index 4004947b464..710fab27901 100644
--- a/compiler/rustc_codegen_ssa/src/traits/misc.rs
+++ b/compiler/rustc_codegen_ssa/src/traits/misc.rs
@@ -1,7 +1,6 @@
 use std::cell::RefCell;
 
 use rustc_data_structures::fx::FxHashMap;
-use rustc_middle::mir::mono::CodegenUnit;
 use rustc_middle::ty::{self, Instance, Ty};
 use rustc_session::Session;
 
@@ -20,9 +19,8 @@ pub trait MiscCodegenMethods<'tcx>: BackendTypes {
     }
     fn get_fn(&self, instance: Instance<'tcx>) -> Self::Function;
     fn get_fn_addr(&self, instance: Instance<'tcx>) -> Self::Value;
-    fn eh_personality(&self) -> Self::Value;
+    fn eh_personality(&self) -> Self::Function;
     fn sess(&self) -> &Session;
-    fn codegen_unit(&self) -> &'tcx CodegenUnit<'tcx>;
     fn set_frame_pointer_type(&self, llfn: Self::Function);
     fn apply_target_cpu_attr(&self, llfn: Self::Function);
     /// Declares the extern "C" main function for the entry point. Returns None if the symbol
diff --git a/compiler/rustc_codegen_ssa/src/traits/mod.rs b/compiler/rustc_codegen_ssa/src/traits/mod.rs
index 239857a4298..6d1ac717c0b 100644
--- a/compiler/rustc_codegen_ssa/src/traits/mod.rs
+++ b/compiler/rustc_codegen_ssa/src/traits/mod.rs
@@ -50,7 +50,7 @@ pub use self::type_::{
 };
 pub use self::write::{ModuleBufferMethods, ThinBufferMethods, WriteBackendMethods};
 
-pub trait CodegenObject = Copy + PartialEq + fmt::Debug;
+pub trait CodegenObject = Copy + fmt::Debug;
 
 pub trait CodegenMethods<'tcx> = LayoutOf<'tcx, LayoutOfResult = TyAndLayout<'tcx>>
     + FnAbiOf<'tcx, FnAbiOfResult = &'tcx FnAbi<'tcx, Ty<'tcx>>>
diff --git a/compiler/rustc_codegen_ssa/src/traits/statics.rs b/compiler/rustc_codegen_ssa/src/traits/statics.rs
index ece0ea1b2ea..0e1e445c72f 100644
--- a/compiler/rustc_codegen_ssa/src/traits/statics.rs
+++ b/compiler/rustc_codegen_ssa/src/traits/statics.rs
@@ -5,19 +5,7 @@ use super::BackendTypes;
 
 pub trait StaticCodegenMethods: BackendTypes {
     fn static_addr_of(&self, cv: Self::Value, align: Align, kind: Option<&str>) -> Self::Value;
-    fn codegen_static(&self, def_id: DefId);
-
-    /// Mark the given global value as "used", to prevent the compiler and linker from potentially
-    /// removing a static variable that may otherwise appear unused.
-    fn add_used_global(&self, global: Self::Value);
-
-    /// Same as add_used_global(), but only prevent the compiler from potentially removing an
-    /// otherwise unused symbol. The linker is still permitted to drop it.
-    ///
-    /// This corresponds to the documented semantics of the `#[used]` attribute, although
-    /// on some targets (non-ELF), we may use `add_used_global` for `#[used]` statics
-    /// instead.
-    fn add_compiler_used_global(&self, global: Self::Value);
+    fn codegen_static(&mut self, def_id: DefId);
 }
 
 pub trait StaticBuilderMethods: BackendTypes {
diff --git a/compiler/rustc_codegen_ssa/src/traits/type_.rs b/compiler/rustc_codegen_ssa/src/traits/type_.rs
index 32d9f27d32d..c3fc21a9285 100644
--- a/compiler/rustc_codegen_ssa/src/traits/type_.rs
+++ b/compiler/rustc_codegen_ssa/src/traits/type_.rs
@@ -158,7 +158,6 @@ pub trait ArgAbiBuilderMethods<'tcx>: BackendTypes {
         val: Self::Value,
         dst: PlaceRef<'tcx, Self::Value>,
     );
-    fn arg_memory_ty(&self, arg_abi: &ArgAbi<'tcx, Ty<'tcx>>) -> Self::Type;
 }
 
 pub trait TypeCodegenMethods<'tcx> = DerivedTypeCodegenMethods<'tcx>
diff --git a/compiler/rustc_codegen_ssa/src/traits/write.rs b/compiler/rustc_codegen_ssa/src/traits/write.rs
index c77efdd1728..07a0609fda1 100644
--- a/compiler/rustc_codegen_ssa/src/traits/write.rs
+++ b/compiler/rustc_codegen_ssa/src/traits/write.rs
@@ -6,7 +6,7 @@ use crate::back::lto::{LtoModuleCodegen, SerializedModule, ThinModule};
 use crate::back::write::{CodegenContext, FatLtoInput, ModuleConfig};
 use crate::{CompiledModule, ModuleCodegen};
 
-pub trait WriteBackendMethods: 'static + Sized + Clone {
+pub trait WriteBackendMethods: Clone + 'static {
     type Module: Send + Sync;
     type TargetMachine;
     type TargetMachineError;
@@ -37,7 +37,7 @@ pub trait WriteBackendMethods: 'static + Sized + Clone {
     ) -> Result<(Vec<LtoModuleCodegen<Self>>, Vec<WorkProduct>), FatalError>;
     fn print_pass_timings(&self);
     fn print_statistics(&self);
-    unsafe fn optimize(
+    fn optimize(
         cgcx: &CodegenContext<Self>,
         dcx: DiagCtxtHandle<'_>,
         module: &mut ModuleCodegen<Self::Module>,
@@ -47,11 +47,11 @@ pub trait WriteBackendMethods: 'static + Sized + Clone {
         cgcx: &CodegenContext<Self>,
         llmod: &mut ModuleCodegen<Self::Module>,
     ) -> Result<(), FatalError>;
-    unsafe fn optimize_thin(
+    fn optimize_thin(
         cgcx: &CodegenContext<Self>,
         thin: ThinModule<Self>,
     ) -> Result<ModuleCodegen<Self::Module>, FatalError>;
-    unsafe fn codegen(
+    fn codegen(
         cgcx: &CodegenContext<Self>,
         dcx: DiagCtxtHandle<'_>,
         module: ModuleCodegen<Self::Module>,
diff --git a/compiler/rustc_const_eval/messages.ftl b/compiler/rustc_const_eval/messages.ftl
index abecea13520..51bdd04267c 100644
--- a/compiler/rustc_const_eval/messages.ftl
+++ b/compiler/rustc_const_eval/messages.ftl
@@ -424,8 +424,7 @@ const_eval_unstable_in_stable_exposed =
     .unstable_sugg = if the {$is_function_call2 ->
             [true] caller
             *[false] function
-        } is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do)
-    .bypass_sugg = otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval)
+        } is not (yet) meant to be exposed to stable const contexts, add `#[rustc_const_unstable]`
 
 const_eval_unstable_intrinsic = `{$name}` is not yet stable as a const intrinsic
 const_eval_unstable_intrinsic_suggestion = add `#![feature({$feature})]` to the crate attributes to enable
diff --git a/compiler/rustc_const_eval/src/check_consts/check.rs b/compiler/rustc_const_eval/src/check_consts/check.rs
index b67a3ce03a9..6167f8cd4b5 100644
--- a/compiler/rustc_const_eval/src/check_consts/check.rs
+++ b/compiler/rustc_const_eval/src/check_consts/check.rs
@@ -589,12 +589,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
 
             Rvalue::Aggregate(kind, ..) => {
                 if let AggregateKind::Coroutine(def_id, ..) = kind.as_ref()
-                    && let Some(
-                        coroutine_kind @ hir::CoroutineKind::Desugared(
-                            hir::CoroutineDesugaring::Async,
-                            _,
-                        ),
-                    ) = self.tcx.coroutine_kind(def_id)
+                    && let Some(coroutine_kind) = self.tcx.coroutine_kind(def_id)
                 {
                     self.check_op(ops::Coroutine(coroutine_kind));
                 }
diff --git a/compiler/rustc_const_eval/src/check_consts/ops.rs b/compiler/rustc_const_eval/src/check_consts/ops.rs
index 1e5b98675c4..d701646719a 100644
--- a/compiler/rustc_const_eval/src/check_consts/ops.rs
+++ b/compiler/rustc_const_eval/src/check_consts/ops.rs
@@ -281,7 +281,7 @@ fn build_error_for_const_call<'tcx>(
                 let mut sugg = None;
 
                 if ccx.tcx.is_lang_item(trait_id, LangItem::PartialEq) {
-                    match (args[0].unpack(), args[1].unpack()) {
+                    match (args[0].kind(), args[1].kind()) {
                         (GenericArgKind::Type(self_ty), GenericArgKind::Type(rhs_ty))
                             if self_ty == rhs_ty
                                 && self_ty.is_ref()
@@ -486,24 +486,25 @@ impl<'tcx> NonConstOp<'tcx> for IntrinsicUnstable {
 pub(crate) struct Coroutine(pub hir::CoroutineKind);
 impl<'tcx> NonConstOp<'tcx> for Coroutine {
     fn status_in_item(&self, _: &ConstCx<'_, 'tcx>) -> Status {
-        if let hir::CoroutineKind::Desugared(
-            hir::CoroutineDesugaring::Async,
-            hir::CoroutineSource::Block,
-        ) = self.0
-        {
-            Status::Unstable {
+        match self.0 {
+            hir::CoroutineKind::Desugared(
+                hir::CoroutineDesugaring::Async,
+                hir::CoroutineSource::Block,
+            )
+            // FIXME(coroutines): eventually we want to gate const coroutine coroutines behind a
+            // different feature.
+            | hir::CoroutineKind::Coroutine(_) => Status::Unstable {
                 gate: sym::const_async_blocks,
                 gate_already_checked: false,
                 safe_to_expose_on_stable: false,
                 is_function_call: false,
-            }
-        } else {
-            Status::Forbidden
+            },
+            _ => Status::Forbidden,
         }
     }
 
     fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> Diag<'tcx> {
-        let msg = format!("{:#}s are not allowed in {}s", self.0, ccx.const_kind());
+        let msg = format!("{} are not allowed in {}s", self.0.to_plural_string(), ccx.const_kind());
         if let Status::Unstable { gate, .. } = self.status_in_item(ccx) {
             ccx.tcx.sess.create_feature_err(errors::UnallowedOpInConstContext { span, msg }, gate)
         } else {
diff --git a/compiler/rustc_const_eval/src/const_eval/dummy_machine.rs b/compiler/rustc_const_eval/src/const_eval/dummy_machine.rs
index 46dcebc46e9..b6e2682af36 100644
--- a/compiler/rustc_const_eval/src/const_eval/dummy_machine.rs
+++ b/compiler/rustc_const_eval/src/const_eval/dummy_machine.rs
@@ -90,7 +90,7 @@ impl<'tcx> interpret::Machine<'tcx> for DummyMachine {
         _instance: ty::Instance<'tcx>,
         _abi: &FnAbi<'tcx, Ty<'tcx>>,
         _args: &[interpret::FnArg<'tcx, Self::Provenance>],
-        _destination: &interpret::MPlaceTy<'tcx, Self::Provenance>,
+        _destination: &interpret::PlaceTy<'tcx, Self::Provenance>,
         _target: Option<BasicBlock>,
         _unwind: UnwindAction,
     ) -> interpret::InterpResult<'tcx, Option<(&'tcx Body<'tcx>, ty::Instance<'tcx>)>> {
@@ -108,7 +108,7 @@ impl<'tcx> interpret::Machine<'tcx> for DummyMachine {
         _ecx: &mut InterpCx<'tcx, Self>,
         _instance: ty::Instance<'tcx>,
         _args: &[interpret::OpTy<'tcx, Self::Provenance>],
-        _destination: &interpret::MPlaceTy<'tcx, Self::Provenance>,
+        _destination: &interpret::PlaceTy<'tcx, Self::Provenance>,
         _target: Option<BasicBlock>,
         _unwind: UnwindAction,
     ) -> interpret::InterpResult<'tcx, Option<ty::Instance<'tcx>>> {
@@ -197,4 +197,9 @@ impl<'tcx> interpret::Machine<'tcx> for DummyMachine {
     ) -> &'a mut Vec<interpret::Frame<'tcx, Self::Provenance, Self::FrameExtra>> {
         unimplemented!()
     }
+
+    fn get_default_alloc_params(
+        &self,
+    ) -> <Self::Bytes as rustc_middle::mir::interpret::AllocBytes>::AllocParams {
+    }
 }
diff --git a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs
index ce8eceebdf8..a79ba6a6342 100644
--- a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs
+++ b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs
@@ -71,7 +71,12 @@ fn eval_body_using_ecx<'tcx, R: InterpretationResult<'tcx>>(
 
     // This can't use `init_stack_frame` since `body` is not a function,
     // so computing its ABI would fail. It's also not worth it since there are no arguments to pass.
-    ecx.push_stack_frame_raw(cid.instance, body, &ret, StackPopCleanup::Root { cleanup: false })?;
+    ecx.push_stack_frame_raw(
+        cid.instance,
+        body,
+        &ret.clone().into(),
+        StackPopCleanup::Root { cleanup: false },
+    )?;
     ecx.storage_live_for_always_live_locals()?;
 
     // The main interpreter loop.
diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs
index 7c7daed525b..3922b33ea84 100644
--- a/compiler/rustc_const_eval/src/const_eval/machine.rs
+++ b/compiler/rustc_const_eval/src/const_eval/machine.rs
@@ -22,7 +22,7 @@ use crate::errors::{LongRunning, LongRunningWarn};
 use crate::fluent_generated as fluent;
 use crate::interpret::{
     self, AllocId, AllocInit, AllocRange, ConstAllocation, CtfeProvenance, FnArg, Frame,
-    GlobalAlloc, ImmTy, InterpCx, InterpResult, MPlaceTy, OpTy, Pointer, RangeSet, Scalar,
+    GlobalAlloc, ImmTy, InterpCx, InterpResult, OpTy, PlaceTy, Pointer, RangeSet, Scalar,
     compile_time_machine, interp_ok, throw_exhaust, throw_inval, throw_ub, throw_ub_custom,
     throw_unsup, throw_unsup_format,
 };
@@ -226,7 +226,7 @@ impl<'tcx> CompileTimeInterpCx<'tcx> {
         &mut self,
         instance: ty::Instance<'tcx>,
         args: &[FnArg<'tcx>],
-        _dest: &MPlaceTy<'tcx>,
+        _dest: &PlaceTy<'tcx>,
         _ret: Option<mir::BasicBlock>,
     ) -> InterpResult<'tcx, Option<ty::Instance<'tcx>>> {
         let def_id = instance.def_id();
@@ -343,7 +343,7 @@ impl<'tcx> interpret::Machine<'tcx> for CompileTimeMachine<'tcx> {
         orig_instance: ty::Instance<'tcx>,
         _abi: &FnAbi<'tcx, Ty<'tcx>>,
         args: &[FnArg<'tcx>],
-        dest: &MPlaceTy<'tcx>,
+        dest: &PlaceTy<'tcx>,
         ret: Option<mir::BasicBlock>,
         _unwind: mir::UnwindAction, // unwinding is not supported in consts
     ) -> InterpResult<'tcx, Option<(&'tcx mir::Body<'tcx>, ty::Instance<'tcx>)>> {
@@ -385,7 +385,7 @@ impl<'tcx> interpret::Machine<'tcx> for CompileTimeMachine<'tcx> {
         ecx: &mut InterpCx<'tcx, Self>,
         instance: ty::Instance<'tcx>,
         args: &[OpTy<'tcx>],
-        dest: &MPlaceTy<'tcx, Self::Provenance>,
+        dest: &PlaceTy<'tcx, Self::Provenance>,
         target: Option<mir::BasicBlock>,
         _unwind: mir::UnwindAction,
     ) -> InterpResult<'tcx, Option<ty::Instance<'tcx>>> {
@@ -735,6 +735,9 @@ impl<'tcx> interpret::Machine<'tcx> for CompileTimeMachine<'tcx> {
             Cow::Owned(compute_range())
         }
     }
+
+    fn get_default_alloc_params(&self) -> <Self::Bytes as mir::interpret::AllocBytes>::AllocParams {
+    }
 }
 
 // Please do not add any code below the above `Machine` trait impl. I (oli-obk) plan more cleanups
diff --git a/compiler/rustc_const_eval/src/errors.rs b/compiler/rustc_const_eval/src/errors.rs
index 826ea0e58ec..7c35e47bbf8 100644
--- a/compiler/rustc_const_eval/src/errors.rs
+++ b/compiler/rustc_const_eval/src/errors.rs
@@ -58,11 +58,6 @@ pub(crate) struct UnstableInStableExposed {
         code = "#[rustc_const_unstable(feature = \"...\", issue = \"...\")]\n",
         applicability = "has-placeholders"
     )]
-    #[suggestion(
-        const_eval_bypass_sugg,
-        code = "#[rustc_allow_const_fn_unstable({gate})]\n",
-        applicability = "has-placeholders"
-    )]
     pub attr_span: Span,
 }
 
diff --git a/compiler/rustc_const_eval/src/interpret/call.rs b/compiler/rustc_const_eval/src/interpret/call.rs
index 405208e94f4..789baea0734 100644
--- a/compiler/rustc_const_eval/src/interpret/call.rs
+++ b/compiler/rustc_const_eval/src/interpret/call.rs
@@ -339,7 +339,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
         caller_fn_abi: &FnAbi<'tcx, Ty<'tcx>>,
         args: &[FnArg<'tcx, M::Provenance>],
         with_caller_location: bool,
-        destination: &MPlaceTy<'tcx, M::Provenance>,
+        destination: &PlaceTy<'tcx, M::Provenance>,
         mut stack_pop: StackPopCleanup,
     ) -> InterpResult<'tcx> {
         // Compute callee information.
@@ -487,7 +487,10 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
             }
 
             // Protect return place for in-place return value passing.
-            M::protect_in_place_function_argument(self, &destination)?;
+            // We only need to protect anything if this is actually an in-memory place.
+            if let Left(mplace) = destination.as_mplace_or_local() {
+                M::protect_in_place_function_argument(self, &mplace)?;
+            }
 
             // Don't forget to mark "initially live" locals as live.
             self.storage_live_for_always_live_locals()?;
@@ -512,7 +515,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
         (caller_abi, caller_fn_abi): (ExternAbi, &FnAbi<'tcx, Ty<'tcx>>),
         args: &[FnArg<'tcx, M::Provenance>],
         with_caller_location: bool,
-        destination: &MPlaceTy<'tcx, M::Provenance>,
+        destination: &PlaceTy<'tcx, M::Provenance>,
         target: Option<mir::BasicBlock>,
         unwind: mir::UnwindAction,
     ) -> InterpResult<'tcx> {
@@ -776,10 +779,11 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
         // Note that we are using `pop_stack_frame_raw` and not `return_from_current_stack_frame`,
         // as the latter "executes" the goto to the return block, but we don't want to,
         // only the tail called function should return to the current return block.
-        M::before_stack_pop(self, self.frame())?;
-
-        let StackPopInfo { return_action, return_to_block, return_place } =
-            self.pop_stack_frame_raw(false)?;
+        let StackPopInfo { return_action, return_to_block, return_place } = self
+            .pop_stack_frame_raw(false, |_this, _return_place| {
+                // This function's return value is just discarded, the tail-callee will fill in the return place instead.
+                interp_ok(())
+            })?;
 
         assert_eq!(return_action, ReturnAction::Normal);
 
@@ -850,7 +854,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
             (ExternAbi::Rust, fn_abi),
             &[FnArg::Copy(arg.into())],
             false,
-            &ret,
+            &ret.into(),
             Some(target),
             unwind,
         )
@@ -891,28 +895,16 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
             throw_ub_custom!(fluent::const_eval_unwind_past_top);
         }
 
-        M::before_stack_pop(self, self.frame())?;
-
-        // Copy return value. Must of course happen *before* we deallocate the locals.
-        // Must be *after* `before_stack_pop` as otherwise the return place might still be protected.
-        let copy_ret_result = if !unwinding {
-            let op = self
-                .local_to_op(mir::RETURN_PLACE, None)
-                .expect("return place should always be live");
-            let dest = self.frame().return_place.clone();
-            let res = self.copy_op_allow_transmute(&op, &dest);
-            trace!("return value: {:?}", self.dump_place(&dest.into()));
-            // We delay actually short-circuiting on this error until *after* the stack frame is
-            // popped, since we want this error to be attributed to the caller, whose type defines
-            // this transmute.
-            res
-        } else {
+        // Get out the return value. Must happen *before* the frame is popped as we have to get the
+        // local's value out.
+        let return_op =
+            self.local_to_op(mir::RETURN_PLACE, None).expect("return place should always be live");
+        // Do the actual pop + copy.
+        let stack_pop_info = self.pop_stack_frame_raw(unwinding, |this, return_place| {
+            this.copy_op_allow_transmute(&return_op, return_place)?;
+            trace!("return value: {:?}", this.dump_place(return_place));
             interp_ok(())
-        };
-
-        // All right, now it is time to actually pop the frame.
-        // An error here takes precedence over the copy error.
-        let (stack_pop_info, ()) = self.pop_stack_frame_raw(unwinding).and(copy_ret_result)?;
+        })?;
 
         match stack_pop_info.return_action {
             ReturnAction::Normal => {}
@@ -924,7 +916,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
                 // If we are not doing cleanup, also skip everything else.
                 assert!(self.stack().is_empty(), "only the topmost frame should ever be leaked");
                 assert!(!unwinding, "tried to skip cleanup during unwinding");
-                // Skip machine hook.
+                // Don't jump anywhere.
                 return interp_ok(());
             }
         }
diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs
index 090b2a692cf..64467a90136 100644
--- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs
+++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs
@@ -17,16 +17,16 @@ use tracing::trace;
 use super::memory::MemoryKind;
 use super::util::ensure_monomorphic_enough;
 use super::{
-    Allocation, CheckInAllocMsg, ConstAllocation, GlobalId, ImmTy, InterpCx, InterpResult,
-    MPlaceTy, Machine, OpTy, Pointer, PointerArithmetic, Provenance, Scalar, err_inval,
-    err_ub_custom, err_unsup_format, interp_ok, throw_inval, throw_ub_custom, throw_ub_format,
+    Allocation, CheckInAllocMsg, ConstAllocation, GlobalId, ImmTy, InterpCx, InterpResult, Machine,
+    OpTy, PlaceTy, Pointer, PointerArithmetic, Provenance, Scalar, err_inval, err_ub_custom,
+    err_unsup_format, interp_ok, throw_inval, throw_ub_custom, throw_ub_format,
 };
 use crate::fluent_generated as fluent;
 
 /// Directly returns an `Allocation` containing an absolute path representation of the given type.
 pub(crate) fn alloc_type_name<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> ConstAllocation<'tcx> {
     let path = crate::util::type_name(tcx, ty);
-    let alloc = Allocation::from_bytes_byte_aligned_immutable(path.into_bytes());
+    let alloc = Allocation::from_bytes_byte_aligned_immutable(path.into_bytes(), ());
     tcx.mk_const_alloc(alloc)
 }
 
@@ -112,7 +112,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
         &mut self,
         instance: ty::Instance<'tcx>,
         args: &[OpTy<'tcx, M::Provenance>],
-        dest: &MPlaceTy<'tcx, M::Provenance>,
+        dest: &PlaceTy<'tcx, M::Provenance>,
         ret: Option<mir::BasicBlock>,
     ) -> InterpResult<'tcx, bool> {
         let instance_args = instance.args;
@@ -518,6 +518,103 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
             sym::fabsf64 => self.float_abs_intrinsic::<Double>(args, dest)?,
             sym::fabsf128 => self.float_abs_intrinsic::<Quad>(args, dest)?,
 
+            sym::floorf16 => self.float_round_intrinsic::<Half>(
+                args,
+                dest,
+                rustc_apfloat::Round::TowardNegative,
+            )?,
+            sym::floorf32 => self.float_round_intrinsic::<Single>(
+                args,
+                dest,
+                rustc_apfloat::Round::TowardNegative,
+            )?,
+            sym::floorf64 => self.float_round_intrinsic::<Double>(
+                args,
+                dest,
+                rustc_apfloat::Round::TowardNegative,
+            )?,
+            sym::floorf128 => self.float_round_intrinsic::<Quad>(
+                args,
+                dest,
+                rustc_apfloat::Round::TowardNegative,
+            )?,
+
+            sym::ceilf16 => self.float_round_intrinsic::<Half>(
+                args,
+                dest,
+                rustc_apfloat::Round::TowardPositive,
+            )?,
+            sym::ceilf32 => self.float_round_intrinsic::<Single>(
+                args,
+                dest,
+                rustc_apfloat::Round::TowardPositive,
+            )?,
+            sym::ceilf64 => self.float_round_intrinsic::<Double>(
+                args,
+                dest,
+                rustc_apfloat::Round::TowardPositive,
+            )?,
+            sym::ceilf128 => self.float_round_intrinsic::<Quad>(
+                args,
+                dest,
+                rustc_apfloat::Round::TowardPositive,
+            )?,
+
+            sym::truncf16 => {
+                self.float_round_intrinsic::<Half>(args, dest, rustc_apfloat::Round::TowardZero)?
+            }
+            sym::truncf32 => {
+                self.float_round_intrinsic::<Single>(args, dest, rustc_apfloat::Round::TowardZero)?
+            }
+            sym::truncf64 => {
+                self.float_round_intrinsic::<Double>(args, dest, rustc_apfloat::Round::TowardZero)?
+            }
+            sym::truncf128 => {
+                self.float_round_intrinsic::<Quad>(args, dest, rustc_apfloat::Round::TowardZero)?
+            }
+
+            sym::roundf16 => self.float_round_intrinsic::<Half>(
+                args,
+                dest,
+                rustc_apfloat::Round::NearestTiesToAway,
+            )?,
+            sym::roundf32 => self.float_round_intrinsic::<Single>(
+                args,
+                dest,
+                rustc_apfloat::Round::NearestTiesToAway,
+            )?,
+            sym::roundf64 => self.float_round_intrinsic::<Double>(
+                args,
+                dest,
+                rustc_apfloat::Round::NearestTiesToAway,
+            )?,
+            sym::roundf128 => self.float_round_intrinsic::<Quad>(
+                args,
+                dest,
+                rustc_apfloat::Round::NearestTiesToAway,
+            )?,
+
+            sym::round_ties_even_f16 => self.float_round_intrinsic::<Half>(
+                args,
+                dest,
+                rustc_apfloat::Round::NearestTiesToEven,
+            )?,
+            sym::round_ties_even_f32 => self.float_round_intrinsic::<Single>(
+                args,
+                dest,
+                rustc_apfloat::Round::NearestTiesToEven,
+            )?,
+            sym::round_ties_even_f64 => self.float_round_intrinsic::<Double>(
+                args,
+                dest,
+                rustc_apfloat::Round::NearestTiesToEven,
+            )?,
+            sym::round_ties_even_f128 => self.float_round_intrinsic::<Quad>(
+                args,
+                dest,
+                rustc_apfloat::Round::NearestTiesToEven,
+            )?,
+
             // Unsupported intrinsic: skip the return_to_block below.
             _ => return interp_ok(false),
         }
@@ -587,7 +684,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
         &mut self,
         a: &ImmTy<'tcx, M::Provenance>,
         b: &ImmTy<'tcx, M::Provenance>,
-        dest: &MPlaceTy<'tcx, M::Provenance>,
+        dest: &PlaceTy<'tcx, M::Provenance>,
     ) -> InterpResult<'tcx> {
         assert_eq!(a.layout.ty, b.layout.ty);
         assert_matches!(a.layout.ty.kind(), ty::Int(..) | ty::Uint(..));
@@ -801,7 +898,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
     fn float_min_intrinsic<F>(
         &mut self,
         args: &[OpTy<'tcx, M::Provenance>],
-        dest: &MPlaceTy<'tcx, M::Provenance>,
+        dest: &PlaceTy<'tcx, M::Provenance>,
     ) -> InterpResult<'tcx, ()>
     where
         F: rustc_apfloat::Float + rustc_apfloat::FloatConvert<F> + Into<Scalar<M::Provenance>>,
@@ -822,7 +919,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
     fn float_max_intrinsic<F>(
         &mut self,
         args: &[OpTy<'tcx, M::Provenance>],
-        dest: &MPlaceTy<'tcx, M::Provenance>,
+        dest: &PlaceTy<'tcx, M::Provenance>,
     ) -> InterpResult<'tcx, ()>
     where
         F: rustc_apfloat::Float + rustc_apfloat::FloatConvert<F> + Into<Scalar<M::Provenance>>,
@@ -843,7 +940,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
     fn float_minimum_intrinsic<F>(
         &mut self,
         args: &[OpTy<'tcx, M::Provenance>],
-        dest: &MPlaceTy<'tcx, M::Provenance>,
+        dest: &PlaceTy<'tcx, M::Provenance>,
     ) -> InterpResult<'tcx, ()>
     where
         F: rustc_apfloat::Float + rustc_apfloat::FloatConvert<F> + Into<Scalar<M::Provenance>>,
@@ -859,7 +956,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
     fn float_maximum_intrinsic<F>(
         &mut self,
         args: &[OpTy<'tcx, M::Provenance>],
-        dest: &MPlaceTy<'tcx, M::Provenance>,
+        dest: &PlaceTy<'tcx, M::Provenance>,
     ) -> InterpResult<'tcx, ()>
     where
         F: rustc_apfloat::Float + rustc_apfloat::FloatConvert<F> + Into<Scalar<M::Provenance>>,
@@ -875,7 +972,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
     fn float_copysign_intrinsic<F>(
         &mut self,
         args: &[OpTy<'tcx, M::Provenance>],
-        dest: &MPlaceTy<'tcx, M::Provenance>,
+        dest: &PlaceTy<'tcx, M::Provenance>,
     ) -> InterpResult<'tcx, ()>
     where
         F: rustc_apfloat::Float + rustc_apfloat::FloatConvert<F> + Into<Scalar<M::Provenance>>,
@@ -890,7 +987,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
     fn float_abs_intrinsic<F>(
         &mut self,
         args: &[OpTy<'tcx, M::Provenance>],
-        dest: &MPlaceTy<'tcx, M::Provenance>,
+        dest: &PlaceTy<'tcx, M::Provenance>,
     ) -> InterpResult<'tcx, ()>
     where
         F: rustc_apfloat::Float + rustc_apfloat::FloatConvert<F> + Into<Scalar<M::Provenance>>,
@@ -900,4 +997,20 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
         self.write_scalar(x.abs(), dest)?;
         interp_ok(())
     }
+
+    fn float_round_intrinsic<F>(
+        &mut self,
+        args: &[OpTy<'tcx, M::Provenance>],
+        dest: &PlaceTy<'tcx, M::Provenance>,
+        mode: rustc_apfloat::Round,
+    ) -> InterpResult<'tcx, ()>
+    where
+        F: rustc_apfloat::Float + rustc_apfloat::FloatConvert<F> + Into<Scalar<M::Provenance>>,
+    {
+        let x: F = self.read_scalar(&args[0])?.to_float()?;
+        let res = x.round_to_integral(mode).value;
+        let res = self.adjust_nan(res, &[x]);
+        self.write_scalar(res, dest)?;
+        interp_ok(())
+    }
 }
diff --git a/compiler/rustc_const_eval/src/interpret/machine.rs b/compiler/rustc_const_eval/src/interpret/machine.rs
index d13e17a481a..b9e022c9604 100644
--- a/compiler/rustc_const_eval/src/interpret/machine.rs
+++ b/compiler/rustc_const_eval/src/interpret/machine.rs
@@ -208,7 +208,7 @@ pub trait Machine<'tcx>: Sized {
         instance: ty::Instance<'tcx>,
         abi: &FnAbi<'tcx, Ty<'tcx>>,
         args: &[FnArg<'tcx, Self::Provenance>],
-        destination: &MPlaceTy<'tcx, Self::Provenance>,
+        destination: &PlaceTy<'tcx, Self::Provenance>,
         target: Option<mir::BasicBlock>,
         unwind: mir::UnwindAction,
     ) -> InterpResult<'tcx, Option<(&'tcx mir::Body<'tcx>, ty::Instance<'tcx>)>>;
@@ -220,7 +220,7 @@ pub trait Machine<'tcx>: Sized {
         fn_val: Self::ExtraFnVal,
         abi: &FnAbi<'tcx, Ty<'tcx>>,
         args: &[FnArg<'tcx, Self::Provenance>],
-        destination: &MPlaceTy<'tcx, Self::Provenance>,
+        destination: &PlaceTy<'tcx, Self::Provenance>,
         target: Option<mir::BasicBlock>,
         unwind: mir::UnwindAction,
     ) -> InterpResult<'tcx>;
@@ -234,7 +234,7 @@ pub trait Machine<'tcx>: Sized {
         ecx: &mut InterpCx<'tcx, Self>,
         instance: ty::Instance<'tcx>,
         args: &[OpTy<'tcx, Self::Provenance>],
-        destination: &MPlaceTy<'tcx, Self::Provenance>,
+        destination: &PlaceTy<'tcx, Self::Provenance>,
         target: Option<mir::BasicBlock>,
         unwind: mir::UnwindAction,
     ) -> InterpResult<'tcx, Option<ty::Instance<'tcx>>>;
@@ -536,11 +536,9 @@ pub trait Machine<'tcx>: Sized {
         interp_ok(())
     }
 
-    /// Called just before the return value is copied to the caller-provided return place.
-    fn before_stack_pop(
-        _ecx: &InterpCx<'tcx, Self>,
-        _frame: &Frame<'tcx, Self::Provenance, Self::FrameExtra>,
-    ) -> InterpResult<'tcx> {
+    /// Called just before the frame is removed from the stack (followed by return value copy and
+    /// local cleanup).
+    fn before_stack_pop(_ecx: &mut InterpCx<'tcx, Self>) -> InterpResult<'tcx> {
         interp_ok(())
     }
 
@@ -628,6 +626,10 @@ pub trait Machine<'tcx>: Sized {
         // Default to no caching.
         Cow::Owned(compute_range())
     }
+
+    /// Compute the value passed to the constructors of the `AllocBytes` type for
+    /// abstract machine allocations.
+    fn get_default_alloc_params(&self) -> <Self::Bytes as AllocBytes>::AllocParams;
 }
 
 /// A lot of the flexibility above is just needed for `Miri`, but all "compile-time" machines
@@ -675,7 +677,7 @@ pub macro compile_time_machine(<$tcx: lifetime>) {
         fn_val: !,
         _abi: &FnAbi<$tcx, Ty<$tcx>>,
         _args: &[FnArg<$tcx>],
-        _destination: &MPlaceTy<$tcx, Self::Provenance>,
+        _destination: &PlaceTy<$tcx, Self::Provenance>,
         _target: Option<mir::BasicBlock>,
         _unwind: mir::UnwindAction,
     ) -> InterpResult<$tcx> {
diff --git a/compiler/rustc_const_eval/src/interpret/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs
index 43bf48a9b96..99a4bc1b7d6 100644
--- a/compiler/rustc_const_eval/src/interpret/memory.rs
+++ b/compiler/rustc_const_eval/src/interpret/memory.rs
@@ -233,10 +233,11 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
         kind: MemoryKind<M::MemoryKind>,
         init: AllocInit,
     ) -> InterpResult<'tcx, Pointer<M::Provenance>> {
+        let params = self.machine.get_default_alloc_params();
         let alloc = if M::PANIC_ON_ALLOC_FAIL {
-            Allocation::new(size, align, init)
+            Allocation::new(size, align, init, params)
         } else {
-            Allocation::try_new(size, align, init)?
+            Allocation::try_new(size, align, init, params)?
         };
         self.insert_allocation(alloc, kind)
     }
@@ -248,7 +249,8 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
         kind: MemoryKind<M::MemoryKind>,
         mutability: Mutability,
     ) -> InterpResult<'tcx, Pointer<M::Provenance>> {
-        let alloc = Allocation::from_bytes(bytes, align, mutability);
+        let params = self.machine.get_default_alloc_params();
+        let alloc = Allocation::from_bytes(bytes, align, mutability, params);
         self.insert_allocation(alloc, kind)
     }
 
diff --git a/compiler/rustc_const_eval/src/interpret/operand.rs b/compiler/rustc_const_eval/src/interpret/operand.rs
index 36da9037e43..39755169e6c 100644
--- a/compiler/rustc_const_eval/src/interpret/operand.rs
+++ b/compiler/rustc_const_eval/src/interpret/operand.rs
@@ -310,7 +310,7 @@ impl<'tcx, Prov: Provenance> ImmTy<'tcx, Prov> {
         let ty = tcx.ty_ordering_enum(None);
         let layout =
             tcx.layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(ty)).unwrap();
-        Self::from_scalar(Scalar::from_i8(c as i8), layout)
+        Self::from_scalar(Scalar::Int(c.into()), layout)
     }
 
     pub fn from_pair(a: Self, b: Self, cx: &(impl HasTypingEnv<'tcx> + HasTyCtxt<'tcx>)) -> Self {
diff --git a/compiler/rustc_const_eval/src/interpret/stack.rs b/compiler/rustc_const_eval/src/interpret/stack.rs
index d7b03776bc4..2a2d1bb2754 100644
--- a/compiler/rustc_const_eval/src/interpret/stack.rs
+++ b/compiler/rustc_const_eval/src/interpret/stack.rs
@@ -15,9 +15,9 @@ use rustc_span::Span;
 use tracing::{info_span, instrument, trace};
 
 use super::{
-    AllocId, CtfeProvenance, Immediate, InterpCx, InterpResult, MPlaceTy, Machine, MemPlace,
-    MemPlaceMeta, MemoryKind, Operand, Pointer, Provenance, ReturnAction, Scalar,
-    from_known_layout, interp_ok, throw_ub, throw_unsup,
+    AllocId, CtfeProvenance, Immediate, InterpCx, InterpResult, Machine, MemPlace, MemPlaceMeta,
+    MemoryKind, Operand, PlaceTy, Pointer, Provenance, ReturnAction, Scalar, from_known_layout,
+    interp_ok, throw_ub, throw_unsup,
 };
 use crate::errors;
 
@@ -76,8 +76,10 @@ pub struct Frame<'tcx, Prov: Provenance = CtfeProvenance, Extra = ()> {
     return_to_block: StackPopCleanup,
 
     /// The location where the result of the current stack frame should be written to,
-    /// and its layout in the caller.
-    pub return_place: MPlaceTy<'tcx, Prov>,
+    /// and its layout in the caller. This place is to be interpreted relative to the
+    /// *caller's* stack frame. We use a `PlaceTy` instead of an `MPlaceTy` since this
+    /// avoids having to move *all* return places into Miri's memory.
+    pub return_place: PlaceTy<'tcx, Prov>,
 
     /// The list of locals for this stack frame, stored in order as
     /// `[return_ptr, arguments..., variables..., temporaries...]`.
@@ -129,7 +131,7 @@ pub struct StackPopInfo<'tcx, Prov: Provenance> {
     pub return_to_block: StackPopCleanup,
 
     /// [`return_place`](Frame::return_place) of the popped stack frame.
-    pub return_place: MPlaceTy<'tcx, Prov>,
+    pub return_place: PlaceTy<'tcx, Prov>,
 }
 
 /// State of a local variable including a memoized layout
@@ -353,7 +355,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
         &mut self,
         instance: ty::Instance<'tcx>,
         body: &'tcx mir::Body<'tcx>,
-        return_place: &MPlaceTy<'tcx, M::Provenance>,
+        return_place: &PlaceTy<'tcx, M::Provenance>,
         return_to_block: StackPopCleanup,
     ) -> InterpResult<'tcx> {
         trace!("body: {:#?}", body);
@@ -404,9 +406,10 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
     /// it.
     ///
     /// This also deallocates locals, if necessary.
+    /// `copy_ret_val` gets called after the frame has been taken from the stack but before the locals have been deallocated.
     ///
-    /// [`M::before_stack_pop`] should be called before calling this function.
-    /// [`M::after_stack_pop`] is called by this function automatically.
+    /// [`M::before_stack_pop`] and [`M::after_stack_pop`] are called by this function
+    /// automatically.
     ///
     /// The high-level version of this is `return_from_current_stack_frame`.
     ///
@@ -415,47 +418,44 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
     pub(super) fn pop_stack_frame_raw(
         &mut self,
         unwinding: bool,
+        copy_ret_val: impl FnOnce(&mut Self, &PlaceTy<'tcx, M::Provenance>) -> InterpResult<'tcx>,
     ) -> InterpResult<'tcx, StackPopInfo<'tcx, M::Provenance>> {
-        let cleanup = self.cleanup_current_frame_locals()?;
-
+        M::before_stack_pop(self)?;
         let frame =
             self.stack_mut().pop().expect("tried to pop a stack frame, but there were none");
 
+        // Copy return value (unless we are unwinding).
+        if !unwinding {
+            copy_ret_val(self, &frame.return_place)?;
+        }
+
         let return_to_block = frame.return_to_block;
         let return_place = frame.return_place.clone();
 
-        let return_action;
-        if cleanup {
-            return_action = M::after_stack_pop(self, frame, unwinding)?;
-            assert_ne!(return_action, ReturnAction::NoCleanup);
-        } else {
-            return_action = ReturnAction::NoCleanup;
-        };
-
-        interp_ok(StackPopInfo { return_action, return_to_block, return_place })
-    }
-
-    /// A private helper for [`pop_stack_frame_raw`](InterpCx::pop_stack_frame_raw).
-    /// Returns `true` if cleanup has been done, `false` otherwise.
-    fn cleanup_current_frame_locals(&mut self) -> InterpResult<'tcx, bool> {
         // Cleanup: deallocate locals.
         // Usually we want to clean up (deallocate locals), but in a few rare cases we don't.
         // We do this while the frame is still on the stack, so errors point to the callee.
-        let return_to_block = self.frame().return_to_block;
         let cleanup = match return_to_block {
             StackPopCleanup::Goto { .. } => true,
             StackPopCleanup::Root { cleanup, .. } => cleanup,
         };
 
-        if cleanup {
+        let return_action = if cleanup {
             // We need to take the locals out, since we need to mutate while iterating.
-            let locals = mem::take(&mut self.frame_mut().locals);
-            for local in &locals {
+            for local in &frame.locals {
                 self.deallocate_local(local.value)?;
             }
-        }
 
-        interp_ok(cleanup)
+            // Call the machine hook, which determines the next steps.
+            let return_action = M::after_stack_pop(self, frame, unwinding)?;
+            assert_ne!(return_action, ReturnAction::NoCleanup);
+            return_action
+        } else {
+            // We also skip the machine hook when there's no cleanup. This not a real "pop" anyway.
+            ReturnAction::NoCleanup
+        };
+
+        interp_ok(StackPopInfo { return_action, return_to_block, return_place })
     }
 
     /// In the current stack frame, mark all locals as live that are not arguments and don't have
diff --git a/compiler/rustc_const_eval/src/interpret/step.rs b/compiler/rustc_const_eval/src/interpret/step.rs
index 363ceee1970..975325b0c1e 100644
--- a/compiler/rustc_const_eval/src/interpret/step.rs
+++ b/compiler/rustc_const_eval/src/interpret/step.rs
@@ -506,7 +506,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
                 let EvaluatedCalleeAndArgs { callee, args, fn_sig, fn_abi, with_caller_location } =
                     self.eval_callee_and_args(terminator, func, args)?;
 
-                let destination = self.force_allocation(&self.eval_place(destination)?)?;
+                let destination = self.eval_place(destination)?;
                 self.init_fn_call(
                     callee,
                     (fn_sig.abi, fn_abi),
diff --git a/compiler/rustc_const_eval/src/interpret/util.rs b/compiler/rustc_const_eval/src/interpret/util.rs
index 847905e8343..83a17092619 100644
--- a/compiler/rustc_const_eval/src/interpret/util.rs
+++ b/compiler/rustc_const_eval/src/interpret/util.rs
@@ -38,7 +38,7 @@ pub(crate) fn create_static_alloc<'tcx>(
     static_def_id: LocalDefId,
     layout: TyAndLayout<'tcx>,
 ) -> InterpResult<'tcx, MPlaceTy<'tcx>> {
-    let alloc = Allocation::try_new(layout.size, layout.align.abi, AllocInit::Uninit)?;
+    let alloc = Allocation::try_new(layout.size, layout.align.abi, AllocInit::Uninit, ())?;
     let alloc_id = ecx.tcx.reserve_and_set_static_alloc(static_def_id.into());
     assert_eq!(ecx.machine.static_root_ids, None);
     ecx.machine.static_root_ids = Some((alloc_id, static_def_id));
diff --git a/compiler/rustc_const_eval/src/util/type_name.rs b/compiler/rustc_const_eval/src/util/type_name.rs
index 30e96ae4143..e8f2728a772 100644
--- a/compiler/rustc_const_eval/src/util/type_name.rs
+++ b/compiler/rustc_const_eval/src/util/type_name.rs
@@ -125,7 +125,7 @@ impl<'tcx> Printer<'tcx> for AbsolutePathPrinter<'tcx> {
     ) -> Result<(), PrintError> {
         print_prefix(self)?;
         let args =
-            args.iter().cloned().filter(|arg| !matches!(arg.unpack(), GenericArgKind::Lifetime(_)));
+            args.iter().cloned().filter(|arg| !matches!(arg.kind(), GenericArgKind::Lifetime(_)));
         if args.clone().next().is_some() {
             self.generic_delimiters(|cx| cx.comma_sep(args))
         } else {
diff --git a/compiler/rustc_data_structures/src/flock.rs b/compiler/rustc_data_structures/src/flock.rs
index f33f6b7cac1..60ae7ad115a 100644
--- a/compiler/rustc_data_structures/src/flock.rs
+++ b/compiler/rustc_data_structures/src/flock.rs
@@ -4,7 +4,18 @@
 //! green/native threading. This is just a bare-bones enough solution for
 //! librustdoc, it is not production quality at all.
 
-cfg_select! {
+// cfg(bootstrap)
+macro_rules! cfg_select_dispatch {
+    ($($tokens:tt)*) => {
+        #[cfg(bootstrap)]
+        cfg_match! { $($tokens)* }
+
+        #[cfg(not(bootstrap))]
+        cfg_select! { $($tokens)* }
+    };
+}
+
+cfg_select_dispatch! {
     target_os = "linux" => {
         mod linux;
         use linux as imp;
diff --git a/compiler/rustc_data_structures/src/lib.rs b/compiler/rustc_data_structures/src/lib.rs
index b34a7fdb9e4..b7447e24731 100644
--- a/compiler/rustc_data_structures/src/lib.rs
+++ b/compiler/rustc_data_structures/src/lib.rs
@@ -10,6 +10,8 @@
 #![allow(internal_features)]
 #![allow(rustc::default_hash_types)]
 #![allow(rustc::potential_query_instability)]
+#![cfg_attr(bootstrap, feature(cfg_match))]
+#![cfg_attr(not(bootstrap), feature(cfg_select))]
 #![deny(unsafe_op_in_unsafe_fn)]
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
 #![doc(rust_logo)]
@@ -19,7 +21,6 @@
 #![feature(ascii_char_variants)]
 #![feature(assert_matches)]
 #![feature(auto_traits)]
-#![feature(cfg_select)]
 #![feature(core_intrinsics)]
 #![feature(dropck_eyepatch)]
 #![feature(extend_one)]
diff --git a/compiler/rustc_data_structures/src/profiling.rs b/compiler/rustc_data_structures/src/profiling.rs
index 36649a36070..e3a01e4035c 100644
--- a/compiler/rustc_data_structures/src/profiling.rs
+++ b/compiler/rustc_data_structures/src/profiling.rs
@@ -859,8 +859,19 @@ fn get_thread_id() -> u32 {
     std::thread::current().id().as_u64().get() as u32
 }
 
+// cfg(bootstrap)
+macro_rules! cfg_select_dispatch {
+    ($($tokens:tt)*) => {
+        #[cfg(bootstrap)]
+        cfg_match! { $($tokens)* }
+
+        #[cfg(not(bootstrap))]
+        cfg_select! { $($tokens)* }
+    };
+}
+
 // Memory reporting
-cfg_select! {
+cfg_select_dispatch! {
     windows => {
         pub fn get_resident_set_size() -> Option<usize> {
             use windows::{
diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs
index 056c476d5e1..54a331a4904 100644
--- a/compiler/rustc_driver_impl/src/lib.rs
+++ b/compiler/rustc_driver_impl/src/lib.rs
@@ -12,7 +12,6 @@
 #![feature(decl_macro)]
 #![feature(panic_backtrace_config)]
 #![feature(panic_update_hook)]
-#![feature(result_flattening)]
 #![feature(rustdoc_internals)]
 #![feature(try_blocks)]
 // tidy-alphabetical-end
diff --git a/compiler/rustc_error_codes/src/error_codes/E0658.md b/compiler/rustc_error_codes/src/error_codes/E0658.md
index 24245a38ae0..65c82e4fb6e 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0658.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0658.md
@@ -3,10 +3,7 @@ An unstable feature was used.
 Erroneous code example:
 
 ```compile_fail,E0658
-#[repr(u128)] // error: use of unstable library feature 'repr128'
-enum Foo {
-    Bar(u64),
-}
+use std::intrinsics; // error: use of unstable library feature `core_intrinsics`
 ```
 
 If you're using a stable or a beta version of rustc, you won't be able to use
@@ -17,12 +14,9 @@ If you're using a nightly version of rustc, just add the corresponding feature
 to be able to use it:
 
 ```
-#![feature(repr128)]
+#![feature(core_intrinsics)]
 
-#[repr(u128)] // ok!
-enum Foo {
-    Bar(u64),
-}
+use std::intrinsics; // ok!
 ```
 
 [rustup]: https://rust-lang.github.io/rustup/concepts/channels.html
diff --git a/compiler/rustc_error_messages/Cargo.toml b/compiler/rustc_error_messages/Cargo.toml
index 578af7fc51d..0951859fa53 100644
--- a/compiler/rustc_error_messages/Cargo.toml
+++ b/compiler/rustc_error_messages/Cargo.toml
@@ -5,8 +5,8 @@ edition = "2024"
 
 [dependencies]
 # tidy-alphabetical-start
-fluent-bundle = "0.15.2"
-fluent-syntax = "0.11"
+fluent-bundle = "0.16"
+fluent-syntax = "0.12"
 icu_list = "1.2"
 icu_locid = "1.2"
 icu_provider_adapters = "1.2"
diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs
index 539ecfbb42e..a11f81b55bb 100644
--- a/compiler/rustc_errors/src/diagnostic.rs
+++ b/compiler/rustc_errors/src/diagnostic.rs
@@ -1325,7 +1325,7 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> {
             ));
             self.note("consider using `--verbose` to print the full type name to the console");
         }
-        Box::into_inner(self.diag.take().unwrap())
+        *self.diag.take().unwrap()
     }
 
     /// This method allows us to access the path of the file where "long types" are written to.
diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs
index f8e19e50778..bd421a441f9 100644
--- a/compiler/rustc_errors/src/lib.rs
+++ b/compiler/rustc_errors/src/lib.rs
@@ -12,7 +12,6 @@
 #![feature(array_windows)]
 #![feature(assert_matches)]
 #![feature(associated_type_defaults)]
-#![feature(box_into_inner)]
 #![feature(box_patterns)]
 #![feature(default_field_values)]
 #![feature(error_reporter)]
diff --git a/compiler/rustc_expand/Cargo.toml b/compiler/rustc_expand/Cargo.toml
index e8fd2f54d76..57dd3a3128d 100644
--- a/compiler/rustc_expand/Cargo.toml
+++ b/compiler/rustc_expand/Cargo.toml
@@ -23,6 +23,9 @@ rustc_lexer = { path = "../rustc_lexer" }
 rustc_lint_defs = { path = "../rustc_lint_defs" }
 rustc_macros = { path = "../rustc_macros" }
 rustc_parse = { path = "../rustc_parse" }
+# We must use the proc_macro version that we will compile proc-macros against,
+# not the one from our own sysroot.
+rustc_proc_macro = { path = "../rustc_proc_macro" }
 rustc_serialize = { path = "../rustc_serialize" }
 rustc_session = { path = "../rustc_session" }
 rustc_span = { path = "../rustc_span" }
diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs
index 55751aa4908..2accfba383e 100644
--- a/compiler/rustc_expand/src/base.rs
+++ b/compiler/rustc_expand/src/base.rs
@@ -1424,7 +1424,7 @@ pub fn parse_macro_name_and_helper_attrs(
 /// See #73345 and #83125 for more details.
 /// FIXME(#73933): Remove this eventually.
 fn pretty_printing_compatibility_hack(item: &Item, psess: &ParseSess) {
-    if let ast::ItemKind::Enum(ident, enum_def, _) = &item.kind
+    if let ast::ItemKind::Enum(ident, _, enum_def) = &item.kind
         && ident.name == sym::ProceduralMasqueradeDummyType
         && let [variant] = &*enum_def.variants
         && variant.ident.name == sym::Input
diff --git a/compiler/rustc_expand/src/config.rs b/compiler/rustc_expand/src/config.rs
index 0994813ecb9..c50ab5959e2 100644
--- a/compiler/rustc_expand/src/config.rs
+++ b/compiler/rustc_expand/src/config.rs
@@ -2,7 +2,6 @@
 
 use std::iter;
 
-use rustc_ast::ptr::P;
 use rustc_ast::token::{Delimiter, Token, TokenKind};
 use rustc_ast::tokenstream::{
     AttrTokenStream, AttrTokenTree, LazyAttrTokenStream, Spacing, TokenTree,
@@ -433,7 +432,7 @@ impl<'a> StripUnconfigured<'a> {
     }
 
     #[instrument(level = "trace", skip(self))]
-    pub fn configure_expr(&self, expr: &mut P<ast::Expr>, method_receiver: bool) {
+    pub fn configure_expr(&self, expr: &mut ast::Expr, method_receiver: bool) {
         if !method_receiver {
             for attr in expr.attrs.iter() {
                 self.maybe_emit_expr_attr_err(attr);
diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs
index 81d4d59ee04..82a2719ca96 100644
--- a/compiler/rustc_expand/src/expand.rs
+++ b/compiler/rustc_expand/src/expand.rs
@@ -3,15 +3,14 @@ use std::rc::Rc;
 use std::sync::Arc;
 use std::{iter, mem};
 
-use rustc_ast as ast;
 use rustc_ast::mut_visit::*;
 use rustc_ast::ptr::P;
 use rustc_ast::tokenstream::TokenStream;
 use rustc_ast::visit::{self, AssocCtxt, Visitor, VisitorResult, try_visit, walk_list};
 use rustc_ast::{
-    AssocItemKind, AstNodeWrapper, AttrArgs, AttrStyle, AttrVec, ExprKind, ForeignItemKind,
-    HasAttrs, HasNodeId, Inline, ItemKind, MacStmtStyle, MetaItemInner, MetaItemKind, ModKind,
-    NodeId, PatKind, StmtKind, TyKind, token,
+    self as ast, AssocItemKind, AstNodeWrapper, AttrArgs, AttrStyle, AttrVec, DUMMY_NODE_ID,
+    ExprKind, ForeignItemKind, HasAttrs, HasNodeId, Inline, ItemKind, MacStmtStyle, MetaItemInner,
+    MetaItemKind, ModKind, NodeId, PatKind, StmtKind, TyKind, token,
 };
 use rustc_ast_pretty::pprust;
 use rustc_data_structures::flat_map_in_place::FlatMapInPlace;
@@ -131,13 +130,9 @@ macro_rules! ast_fragments {
             pub(crate) fn mut_visit_with<F: MutVisitor>(&mut self, vis: &mut F) {
                 match self {
                     AstFragment::OptExpr(opt_expr) => {
-                        visit_clobber(opt_expr, |opt_expr| {
-                            if let Some(expr) = opt_expr {
-                                vis.filter_map_expr(expr)
-                            } else {
-                                None
-                            }
-                        });
+                        if let Some(expr) = opt_expr.take() {
+                            *opt_expr = vis.filter_map_expr(expr)
+                        }
                     }
                     AstFragment::MethodReceiverExpr(expr) => vis.visit_method_receiver_expr(expr),
                     $($(AstFragment::$Kind(ast) => vis.$mut_visit_ast(ast),)?)*
@@ -1319,10 +1314,10 @@ impl InvocationCollectorNode for P<ast::Item> {
 
             let mut idents = Vec::new();
             collect_use_tree_leaves(ut, &mut idents);
-            return idents;
+            idents
+        } else {
+            self.kind.ident().into_iter().collect()
         }
-
-        if let Some(ident) = self.kind.ident() { vec![ident] } else { vec![] }
     }
 }
 
@@ -1782,11 +1777,7 @@ impl InvocationCollectorNode for AstNodeWrapper<P<ast::Expr>, OptExprTag> {
 /// This struct is a hack to workaround unstable of `stmt_expr_attributes`.
 /// It can be removed once that feature is stabilized.
 struct MethodReceiverTag;
-impl DummyAstNode for MethodReceiverTag {
-    fn dummy() -> MethodReceiverTag {
-        MethodReceiverTag
-    }
-}
+
 impl InvocationCollectorNode for AstNodeWrapper<P<ast::Expr>, MethodReceiverTag> {
     type OutputTy = Self;
     const KIND: AstFragmentKind = AstFragmentKind::MethodReceiverExpr;
@@ -1852,6 +1843,57 @@ fn build_single_delegations<'a, Node: InvocationCollectorNode>(
     })
 }
 
+/// Required for `visit_node` obtained an owned `Node` from `&mut Node`.
+trait DummyAstNode {
+    fn dummy() -> Self;
+}
+
+impl DummyAstNode for ast::Crate {
+    fn dummy() -> Self {
+        ast::Crate {
+            attrs: Default::default(),
+            items: Default::default(),
+            spans: Default::default(),
+            id: DUMMY_NODE_ID,
+            is_placeholder: Default::default(),
+        }
+    }
+}
+
+impl DummyAstNode for P<ast::Ty> {
+    fn dummy() -> Self {
+        P(ast::Ty {
+            id: DUMMY_NODE_ID,
+            kind: TyKind::Dummy,
+            span: Default::default(),
+            tokens: Default::default(),
+        })
+    }
+}
+
+impl DummyAstNode for P<ast::Pat> {
+    fn dummy() -> Self {
+        P(ast::Pat {
+            id: DUMMY_NODE_ID,
+            kind: PatKind::Wild,
+            span: Default::default(),
+            tokens: Default::default(),
+        })
+    }
+}
+
+impl DummyAstNode for P<ast::Expr> {
+    fn dummy() -> Self {
+        ast::Expr::dummy()
+    }
+}
+
+impl DummyAstNode for AstNodeWrapper<P<ast::Expr>, MethodReceiverTag> {
+    fn dummy() -> Self {
+        AstNodeWrapper::new(ast::Expr::dummy(), MethodReceiverTag)
+    }
+}
+
 struct InvocationCollector<'a, 'b> {
     cx: &'a mut ExtCtxt<'b>,
     invocations: Vec<(Invocation, Option<Arc<SyntaxExtension>>)>,
@@ -2155,18 +2197,19 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
                         self.expand_cfg_attr(node, &attr, pos);
                         continue;
                     }
-                    _ => visit_clobber(node, |node| {
-                        self.collect_attr((attr, pos, derives), node.to_annotatable(), Node::KIND)
+                    _ => {
+                        let n = mem::replace(node, Node::dummy());
+                        *node = self
+                            .collect_attr((attr, pos, derives), n.to_annotatable(), Node::KIND)
                             .make_ast::<Node>()
-                    }),
+                    }
                 },
                 None if node.is_mac_call() => {
-                    visit_clobber(node, |node| {
-                        // Do not clobber unless it's actually a macro (uncommon case).
-                        let (mac, attrs, _) = node.take_mac_call();
-                        self.check_attributes(&attrs, &mac);
-                        self.collect_bang(mac, Node::KIND).make_ast::<Node>()
-                    })
+                    let n = mem::replace(node, Node::dummy());
+                    let (mac, attrs, _) = n.take_mac_call();
+                    self.check_attributes(&attrs, &mac);
+
+                    *node = self.collect_bang(mac, Node::KIND).make_ast::<Node>()
                 }
                 None if node.delegation().is_some() => unreachable!(),
                 None => {
@@ -2293,18 +2336,14 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
     }
 
     fn visit_method_receiver_expr(&mut self, node: &mut P<ast::Expr>) {
-        visit_clobber(node, |node| {
-            let mut wrapper = AstNodeWrapper::new(node, MethodReceiverTag);
-            self.visit_node(&mut wrapper);
-            wrapper.wrapped
-        })
+        self.visit_node(AstNodeWrapper::from_mut(node, MethodReceiverTag))
     }
 
     fn filter_map_expr(&mut self, node: P<ast::Expr>) -> Option<P<ast::Expr>> {
         self.flat_map_node(AstNodeWrapper::new(node, OptExprTag))
     }
 
-    fn visit_block(&mut self, node: &mut P<ast::Block>) {
+    fn visit_block(&mut self, node: &mut ast::Block) {
         let orig_dir_ownership = mem::replace(
             &mut self.cx.current_expansion.dir_ownership,
             DirOwnership::UnownedViaBlock,
diff --git a/compiler/rustc_expand/src/lib.rs b/compiler/rustc_expand/src/lib.rs
index cd744977bb3..35b38d99c70 100644
--- a/compiler/rustc_expand/src/lib.rs
+++ b/compiler/rustc_expand/src/lib.rs
@@ -14,8 +14,6 @@
 #![feature(yeet_expr)]
 // tidy-alphabetical-end
 
-extern crate proc_macro as pm;
-
 mod build;
 mod errors;
 // FIXME(Nilstrieb) Translate macro_rules diagnostics
diff --git a/compiler/rustc_expand/src/placeholders.rs b/compiler/rustc_expand/src/placeholders.rs
index 0136292decb..3dcb20c8c76 100644
--- a/compiler/rustc_expand/src/placeholders.rs
+++ b/compiler/rustc_expand/src/placeholders.rs
@@ -349,7 +349,7 @@ impl MutVisitor for PlaceholderExpander {
     fn filter_map_expr(&mut self, expr: P<ast::Expr>) -> Option<P<ast::Expr>> {
         match expr.kind {
             ast::ExprKind::MacCall(_) => self.remove(expr.id).make_opt_expr(),
-            _ => noop_filter_map_expr(self, expr),
+            _ => walk_filter_map_expr(self, expr),
         }
     }
 
diff --git a/compiler/rustc_expand/src/proc_macro.rs b/compiler/rustc_expand/src/proc_macro.rs
index d5af9849e75..84fbbbef061 100644
--- a/compiler/rustc_expand/src/proc_macro.rs
+++ b/compiler/rustc_expand/src/proc_macro.rs
@@ -1,4 +1,3 @@
-use rustc_ast as ast;
 use rustc_ast::ptr::P;
 use rustc_ast::tokenstream::TokenStream;
 use rustc_errors::ErrorGuaranteed;
@@ -6,6 +5,7 @@ use rustc_parse::parser::{ForceCollect, Parser};
 use rustc_session::config::ProcMacroExecutionStrategy;
 use rustc_span::Span;
 use rustc_span::profiling::SpannedEventArgRecorder;
+use {rustc_ast as ast, rustc_proc_macro as pm};
 
 use crate::base::{self, *};
 use crate::{errors, proc_macro_server};
diff --git a/compiler/rustc_expand/src/proc_macro_server.rs b/compiler/rustc_expand/src/proc_macro_server.rs
index f00201ad202..fb5abaefb57 100644
--- a/compiler/rustc_expand/src/proc_macro_server.rs
+++ b/compiler/rustc_expand/src/proc_macro_server.rs
@@ -1,10 +1,6 @@
 use std::ops::{Bound, Range};
 
 use ast::token::IdentIsRaw;
-use pm::bridge::{
-    DelimSpan, Diagnostic, ExpnGlobals, Group, Ident, LitKind, Literal, Punct, TokenTree, server,
-};
-use pm::{Delimiter, Level};
 use rustc_ast as ast;
 use rustc_ast::token;
 use rustc_ast::tokenstream::{self, DelimSpacing, Spacing, TokenStream};
@@ -15,6 +11,10 @@ use rustc_errors::{Diag, ErrorGuaranteed, MultiSpan, PResult};
 use rustc_parse::lexer::nfc_normalize;
 use rustc_parse::parser::Parser;
 use rustc_parse::{exp, new_parser_from_source_str, source_str_to_stream, unwrap_or_emit_fatal};
+use rustc_proc_macro::bridge::{
+    DelimSpan, Diagnostic, ExpnGlobals, Group, Ident, LitKind, Literal, Punct, TokenTree, server,
+};
+use rustc_proc_macro::{Delimiter, Level};
 use rustc_session::parse::ParseSess;
 use rustc_span::def_id::CrateNum;
 use rustc_span::{BytePos, FileName, Pos, Span, Symbol, sym};
@@ -66,7 +66,7 @@ impl FromInternal<token::LitKind> for LitKind {
             token::CStr => LitKind::CStr,
             token::CStrRaw(n) => LitKind::CStrRaw(n),
             token::Err(_guar) => {
-                // This is the only place a `pm::bridge::LitKind::ErrWithGuar`
+                // This is the only place a `rustc_proc_macro::bridge::LitKind::ErrWithGuar`
                 // is constructed. Note that an `ErrorGuaranteed` is available,
                 // as required. See the comment in `to_internal`.
                 LitKind::ErrWithGuar
@@ -149,7 +149,7 @@ impl FromInternal<(TokenStream, &mut Rustc<'_, '_>)> for Vec<TokenTree<TokenStre
                     }
 
                     trees.push(TokenTree::Group(Group {
-                        delimiter: pm::Delimiter::from_internal(delim),
+                        delimiter: rustc_proc_macro::Delimiter::from_internal(delim),
                         stream: Some(stream),
                         span: DelimSpan {
                             open: span.open,
@@ -270,7 +270,7 @@ impl FromInternal<(TokenStream, &mut Rustc<'_, '_>)> for Vec<TokenTree<TokenStre
                     let stream =
                         TokenStream::token_alone(token::Lifetime(ident.name, is_raw), ident.span);
                     trees.push(TokenTree::Group(Group {
-                        delimiter: pm::Delimiter::None,
+                        delimiter: rustc_proc_macro::Delimiter::None,
                         stream: Some(stream),
                         span: DelimSpan::from_single(span),
                     }))
@@ -302,7 +302,7 @@ impl FromInternal<(TokenStream, &mut Rustc<'_, '_>)> for Vec<TokenTree<TokenStre
                         trees.push(TokenTree::Punct(Punct { ch: b'!', joint: false, span }));
                     }
                     trees.push(TokenTree::Group(Group {
-                        delimiter: pm::Delimiter::Bracket,
+                        delimiter: rustc_proc_macro::Delimiter::Bracket,
                         stream: Some(stream),
                         span: DelimSpan::from_single(span),
                     }));
diff --git a/compiler/rustc_feature/src/accepted.rs b/compiler/rustc_feature/src/accepted.rs
index 820af9ac84b..ffa6ffb40b6 100644
--- a/compiler/rustc_feature/src/accepted.rs
+++ b/compiler/rustc_feature/src/accepted.rs
@@ -360,6 +360,8 @@ declare_features! (
     (accepted, relaxed_adts, "1.19.0", Some(35626)),
     /// Lessens the requirements for structs to implement `Unsize`.
     (accepted, relaxed_struct_unsize, "1.58.0", Some(81793)),
+    /// Allows the `#[repr(i128)]` attribute for enums.
+    (accepted, repr128, "CURRENT_RUSTC_VERSION", Some(56071)),
     /// Allows `repr(align(16))` struct attribute (RFC 1358).
     (accepted, repr_align, "1.25.0", Some(33626)),
     /// Allows using `#[repr(align(X))]` on enums with equivalent semantics
diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs
index 6cdcf451f37..b46eac6d8a6 100644
--- a/compiler/rustc_feature/src/unstable.rs
+++ b/compiler/rustc_feature/src/unstable.rs
@@ -371,6 +371,8 @@ declare_features! (
     (unstable, arbitrary_self_types, "1.23.0", Some(44874)),
     /// Allows inherent and trait methods with arbitrary self types that are raw pointers.
     (unstable, arbitrary_self_types_pointers, "1.83.0", Some(44874)),
+    /// Allows #[cfg(...)] on inline assembly templates and operands.
+    (unstable, asm_cfg, "CURRENT_RUSTC_VERSION", Some(140364)),
     /// Enables experimental inline assembly support for additional architectures.
     (unstable, asm_experimental_arch, "1.58.0", Some(93335)),
     /// Enables experimental register support in inline assembly.
@@ -619,8 +621,6 @@ declare_features! (
     (incomplete, ref_pat_eat_one_layer_2024_structural, "1.81.0", Some(123076)),
     /// Allows using the `#[register_tool]` attribute.
     (unstable, register_tool, "1.41.0", Some(66079)),
-    /// Allows the `#[repr(i128)]` attribute for enums.
-    (incomplete, repr128, "1.16.0", Some(56071)),
     /// Allows `repr(simd)` and importing the various simd intrinsics.
     (unstable, repr_simd, "1.4.0", Some(27731)),
     /// Allows bounding the return type of AFIT/RPITIT.
diff --git a/compiler/rustc_fluent_macro/Cargo.toml b/compiler/rustc_fluent_macro/Cargo.toml
index ce76b2745ea..d7ef4280aef 100644
--- a/compiler/rustc_fluent_macro/Cargo.toml
+++ b/compiler/rustc_fluent_macro/Cargo.toml
@@ -9,8 +9,8 @@ proc-macro = true
 [dependencies]
 # tidy-alphabetical-start
 annotate-snippets = "0.11"
-fluent-bundle = "0.15.2"
-fluent-syntax = "0.11"
+fluent-bundle = "0.16"
+fluent-syntax = "0.12"
 proc-macro2 = "1"
 quote = "1"
 syn = { version = "2", features = ["full"] }
diff --git a/compiler/rustc_hir/src/arena.rs b/compiler/rustc_hir/src/arena.rs
index 88c0d223fd3..b0dff635a9b 100644
--- a/compiler/rustc_hir/src/arena.rs
+++ b/compiler/rustc_hir/src/arena.rs
@@ -8,7 +8,6 @@ macro_rules! arena_types {
             [] asm_template: rustc_ast::InlineAsmTemplatePiece,
             [] attribute: rustc_hir::Attribute,
             [] owner_info: rustc_hir::OwnerInfo<'tcx>,
-            [] use_path: rustc_hir::UsePath<'tcx>,
             [] lit: rustc_hir::Lit,
             [] macro_def: rustc_ast::MacroDef,
         ]);
diff --git a/compiler/rustc_hir/src/def.rs b/compiler/rustc_hir/src/def.rs
index 507c94aca8b..98ec1ccd6ba 100644
--- a/compiler/rustc_hir/src/def.rs
+++ b/compiler/rustc_hir/src/def.rs
@@ -584,7 +584,7 @@ impl<CTX: crate::HashStableContext> ToStableHashKey<CTX> for Namespace {
 }
 
 /// Just a helper ‒ separate structure for each namespace.
-#[derive(Copy, Clone, Default, Debug)]
+#[derive(Copy, Clone, Default, Debug, HashStable_Generic)]
 pub struct PerNS<T> {
     pub value_ns: T,
     pub type_ns: T,
@@ -596,10 +596,16 @@ impl<T> PerNS<T> {
         PerNS { value_ns: f(self.value_ns), type_ns: f(self.type_ns), macro_ns: f(self.macro_ns) }
     }
 
+    /// Note: Do you really want to use this? Often you know which namespace a
+    /// name will belong in, and you can consider just that namespace directly,
+    /// rather than iterating through all of them.
     pub fn into_iter(self) -> IntoIter<T, 3> {
         [self.value_ns, self.type_ns, self.macro_ns].into_iter()
     }
 
+    /// Note: Do you really want to use this? Often you know which namespace a
+    /// name will belong in, and you can consider just that namespace directly,
+    /// rather than iterating through all of them.
     pub fn iter(&self) -> IntoIter<&T, 3> {
         [&self.value_ns, &self.type_ns, &self.macro_ns].into_iter()
     }
@@ -634,6 +640,10 @@ impl<T> PerNS<Option<T>> {
     }
 
     /// Returns an iterator over the items which are `Some`.
+    ///
+    /// Note: Do you really want to use this? Often you know which namespace a
+    /// name will belong in, and you can consider just that namespace directly,
+    /// rather than iterating through all of them.
     pub fn present_items(self) -> impl Iterator<Item = T> {
         [self.type_ns, self.value_ns, self.macro_ns].into_iter().flatten()
     }
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index f63ab303689..433d5f98829 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -30,7 +30,7 @@ use thin_vec::ThinVec;
 use tracing::debug;
 
 use crate::LangItem;
-use crate::def::{CtorKind, DefKind, Res};
+use crate::def::{CtorKind, DefKind, PerNS, Res};
 use crate::def_id::{DefId, LocalDefIdMap};
 pub(crate) use crate::hir_id::{HirId, ItemLocalId, ItemLocalMap, OwnerId};
 use crate::intravisit::{FnKind, VisitorExt};
@@ -347,7 +347,7 @@ pub struct Path<'hir, R = Res> {
 }
 
 /// Up to three resolutions for type, value and macro namespaces.
-pub type UsePath<'hir> = Path<'hir, SmallVec<[Res; 3]>>;
+pub type UsePath<'hir> = Path<'hir, PerNS<Option<Res>>>;
 
 impl Path<'_> {
     pub fn is_global(&self) -> bool {
@@ -2061,12 +2061,19 @@ impl CoroutineKind {
             CoroutineKind::Coroutine(mov) => mov,
         }
     }
-}
 
-impl CoroutineKind {
     pub fn is_fn_like(self) -> bool {
         matches!(self, CoroutineKind::Desugared(_, CoroutineSource::Fn))
     }
+
+    pub fn to_plural_string(&self) -> String {
+        match self {
+            CoroutineKind::Desugared(d, CoroutineSource::Fn) => format!("{d:#}fn bodies"),
+            CoroutineKind::Desugared(d, CoroutineSource::Block) => format!("{d:#}blocks"),
+            CoroutineKind::Desugared(d, CoroutineSource::Closure) => format!("{d:#}closure bodies"),
+            CoroutineKind::Coroutine(_) => "coroutines".to_string(),
+        }
+    }
 }
 
 impl fmt::Display for CoroutineKind {
@@ -2370,6 +2377,10 @@ impl Expr<'_> {
             // Lang item paths cannot currently be local variables or statics.
             ExprKind::Path(QPath::LangItem(..)) => false,
 
+            // Suppress errors for bad expressions.
+            ExprKind::Err(_guar)
+            | ExprKind::Let(&LetExpr { recovered: ast::Recovered::Yes(_guar), .. }) => true,
+
             // Partially qualified paths in expressions can only legally
             // refer to associated items which are always rvalues.
             ExprKind::Path(QPath::TypeRelative(..))
@@ -2401,8 +2412,7 @@ impl Expr<'_> {
             | ExprKind::Binary(..)
             | ExprKind::Yield(..)
             | ExprKind::Cast(..)
-            | ExprKind::DropTemps(..)
-            | ExprKind::Err(_) => false,
+            | ExprKind::DropTemps(..) => false,
         }
     }
 
@@ -4106,11 +4116,11 @@ impl<'hir> Item<'hir> {
 
         expect_use, (&'hir UsePath<'hir>, UseKind), ItemKind::Use(p, uk), (p, *uk);
 
-        expect_static, (Ident, &'hir Ty<'hir>, Mutability, BodyId),
-            ItemKind::Static(ident, ty, mutbl, body), (*ident, ty, *mutbl, *body);
+        expect_static, (Mutability, Ident, &'hir Ty<'hir>, BodyId),
+            ItemKind::Static(mutbl, ident, ty, body), (*mutbl, *ident, ty, *body);
 
-        expect_const, (Ident, &'hir Ty<'hir>, &'hir Generics<'hir>, BodyId),
-            ItemKind::Const(ident, ty, generics, body), (*ident, ty, generics, *body);
+        expect_const, (Ident, &'hir Generics<'hir>, &'hir Ty<'hir>, BodyId),
+            ItemKind::Const(ident, generics, ty, body), (*ident, generics, ty, *body);
 
         expect_fn, (Ident, &FnSig<'hir>, &'hir Generics<'hir>, BodyId),
             ItemKind::Fn { ident, sig, generics, body, .. }, (*ident, sig, generics, *body);
@@ -4125,17 +4135,17 @@ impl<'hir> Item<'hir> {
 
         expect_global_asm, &'hir InlineAsm<'hir>, ItemKind::GlobalAsm { asm, .. }, asm;
 
-        expect_ty_alias, (Ident, &'hir Ty<'hir>, &'hir Generics<'hir>),
-            ItemKind::TyAlias(ident, ty, generics), (*ident, ty, generics);
+        expect_ty_alias, (Ident, &'hir Generics<'hir>, &'hir Ty<'hir>),
+            ItemKind::TyAlias(ident, generics, ty), (*ident, generics, ty);
 
-        expect_enum, (Ident, &EnumDef<'hir>, &'hir Generics<'hir>),
-            ItemKind::Enum(ident, def, generics), (*ident, def, generics);
+        expect_enum, (Ident, &'hir Generics<'hir>, &EnumDef<'hir>),
+            ItemKind::Enum(ident, generics, def), (*ident, generics, def);
 
-        expect_struct, (Ident, &VariantData<'hir>, &'hir Generics<'hir>),
-            ItemKind::Struct(ident, data, generics), (*ident, data, generics);
+        expect_struct, (Ident, &'hir Generics<'hir>, &VariantData<'hir>),
+            ItemKind::Struct(ident, generics, data), (*ident, generics, data);
 
-        expect_union, (Ident, &VariantData<'hir>, &'hir Generics<'hir>),
-            ItemKind::Union(ident, data, generics), (*ident, data, generics);
+        expect_union, (Ident, &'hir Generics<'hir>, &VariantData<'hir>),
+            ItemKind::Union(ident, generics, data), (*ident, generics, data);
 
         expect_trait,
             (
@@ -4278,13 +4288,13 @@ pub enum ItemKind<'hir> {
     Use(&'hir UsePath<'hir>, UseKind),
 
     /// A `static` item.
-    Static(Ident, &'hir Ty<'hir>, Mutability, BodyId),
+    Static(Mutability, Ident, &'hir Ty<'hir>, BodyId),
     /// A `const` item.
-    Const(Ident, &'hir Ty<'hir>, &'hir Generics<'hir>, BodyId),
+    Const(Ident, &'hir Generics<'hir>, &'hir Ty<'hir>, BodyId),
     /// A function declaration.
     Fn {
-        ident: Ident,
         sig: FnSig<'hir>,
+        ident: Ident,
         generics: &'hir Generics<'hir>,
         body: BodyId,
         /// Whether this function actually has a body.
@@ -4309,13 +4319,13 @@ pub enum ItemKind<'hir> {
         fake_body: BodyId,
     },
     /// A type alias, e.g., `type Foo = Bar<u8>`.
-    TyAlias(Ident, &'hir Ty<'hir>, &'hir Generics<'hir>),
+    TyAlias(Ident, &'hir Generics<'hir>, &'hir Ty<'hir>),
     /// An enum definition, e.g., `enum Foo<A, B> { C<A>, D<B> }`.
-    Enum(Ident, EnumDef<'hir>, &'hir Generics<'hir>),
+    Enum(Ident, &'hir Generics<'hir>, EnumDef<'hir>),
     /// A struct definition, e.g., `struct Foo<A> {x: A}`.
-    Struct(Ident, VariantData<'hir>, &'hir Generics<'hir>),
+    Struct(Ident, &'hir Generics<'hir>, VariantData<'hir>),
     /// A union definition, e.g., `union Foo<A, B> {x: A, y: B}`.
-    Union(Ident, VariantData<'hir>, &'hir Generics<'hir>),
+    Union(Ident, &'hir Generics<'hir>, VariantData<'hir>),
     /// A trait definition.
     Trait(IsAuto, Safety, Ident, &'hir Generics<'hir>, GenericBounds<'hir>, &'hir [TraitItemRef]),
     /// A trait alias.
@@ -4352,7 +4362,7 @@ impl ItemKind<'_> {
         match *self {
             ItemKind::ExternCrate(_, ident)
             | ItemKind::Use(_, UseKind::Single(ident))
-            | ItemKind::Static(ident, ..)
+            | ItemKind::Static(_, ident, ..)
             | ItemKind::Const(ident, ..)
             | ItemKind::Fn { ident, .. }
             | ItemKind::Macro(ident, ..)
@@ -4374,11 +4384,11 @@ impl ItemKind<'_> {
     pub fn generics(&self) -> Option<&Generics<'_>> {
         Some(match self {
             ItemKind::Fn { generics, .. }
-            | ItemKind::TyAlias(_, _, generics)
-            | ItemKind::Const(_, _, generics, _)
-            | ItemKind::Enum(_, _, generics)
-            | ItemKind::Struct(_, _, generics)
-            | ItemKind::Union(_, _, generics)
+            | ItemKind::TyAlias(_, generics, _)
+            | ItemKind::Const(_, generics, _, _)
+            | ItemKind::Enum(_, generics, _)
+            | ItemKind::Struct(_, generics, _)
+            | ItemKind::Union(_, generics, _)
             | ItemKind::Trait(_, _, _, generics, _, _)
             | ItemKind::TraitAlias(_, generics, _)
             | ItemKind::Impl(Impl { generics, .. }) => generics,
@@ -4802,9 +4812,9 @@ impl<'hir> Node<'hir> {
     pub fn ty(self) -> Option<&'hir Ty<'hir>> {
         match self {
             Node::Item(it) => match it.kind {
-                ItemKind::TyAlias(_, ty, _)
-                | ItemKind::Static(_, ty, _, _)
-                | ItemKind::Const(_, ty, _, _) => Some(ty),
+                ItemKind::TyAlias(_, _, ty)
+                | ItemKind::Static(_, _, ty, _)
+                | ItemKind::Const(_, _, ty, _) => Some(ty),
                 ItemKind::Impl(impl_item) => Some(&impl_item.self_ty),
                 _ => None,
             },
@@ -4824,7 +4834,7 @@ impl<'hir> Node<'hir> {
 
     pub fn alias_ty(self) -> Option<&'hir Ty<'hir>> {
         match self {
-            Node::Item(Item { kind: ItemKind::TyAlias(_, ty, _), .. }) => Some(ty),
+            Node::Item(Item { kind: ItemKind::TyAlias(_, _, ty), .. }) => Some(ty),
             _ => None,
         }
     }
diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs
index a60de4b1fc3..b9932a7334e 100644
--- a/compiler/rustc_hir/src/intravisit.rs
+++ b/compiler/rustc_hir/src/intravisit.rs
@@ -527,13 +527,15 @@ pub trait VisitorExt<'v>: Visitor<'v> {
 impl<'v, V: Visitor<'v>> VisitorExt<'v> for V {}
 
 pub fn walk_param<'v, V: Visitor<'v>>(visitor: &mut V, param: &'v Param<'v>) -> V::Result {
-    try_visit!(visitor.visit_id(param.hir_id));
-    visitor.visit_pat(param.pat)
+    let Param { hir_id, pat, ty_span: _, span: _ } = param;
+    try_visit!(visitor.visit_id(*hir_id));
+    visitor.visit_pat(pat)
 }
 
 pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item<'v>) -> V::Result {
+    let Item { owner_id: _, kind, span: _, vis_span: _ } = item;
     try_visit!(visitor.visit_id(item.hir_id()));
-    match item.kind {
+    match *kind {
         ItemKind::ExternCrate(orig_name, ident) => {
             visit_opt!(visitor, visit_name, orig_name);
             try_visit!(visitor.visit_ident(ident));
@@ -545,15 +547,15 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item<'v>) -> V::
                 UseKind::Glob | UseKind::ListStem => {}
             }
         }
-        ItemKind::Static(ident, ref typ, _, body) => {
+        ItemKind::Static(_, ident, ref typ, body) => {
             try_visit!(visitor.visit_ident(ident));
             try_visit!(visitor.visit_ty_unambig(typ));
             try_visit!(visitor.visit_nested_body(body));
         }
-        ItemKind::Const(ident, ref typ, ref generics, body) => {
+        ItemKind::Const(ident, ref generics, ref typ, body) => {
             try_visit!(visitor.visit_ident(ident));
-            try_visit!(visitor.visit_ty_unambig(typ));
             try_visit!(visitor.visit_generics(generics));
+            try_visit!(visitor.visit_ty_unambig(typ));
             try_visit!(visitor.visit_nested_body(body));
         }
         ItemKind::Fn { ident, sig, generics, body: body_id, .. } => {
@@ -583,12 +585,12 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item<'v>) -> V::
             // typeck results set correctly.
             try_visit!(visitor.visit_nested_body(fake_body));
         }
-        ItemKind::TyAlias(ident, ref ty, ref generics) => {
+        ItemKind::TyAlias(ident, ref generics, ref ty) => {
             try_visit!(visitor.visit_ident(ident));
-            try_visit!(visitor.visit_ty_unambig(ty));
             try_visit!(visitor.visit_generics(generics));
+            try_visit!(visitor.visit_ty_unambig(ty));
         }
-        ItemKind::Enum(ident, ref enum_definition, ref generics) => {
+        ItemKind::Enum(ident, ref generics, ref enum_definition) => {
             try_visit!(visitor.visit_ident(ident));
             try_visit!(visitor.visit_generics(generics));
             try_visit!(visitor.visit_enum_def(enum_definition));
@@ -609,8 +611,8 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item<'v>) -> V::
             try_visit!(visitor.visit_ty_unambig(self_ty));
             walk_list!(visitor, visit_impl_item_ref, *items);
         }
-        ItemKind::Struct(ident, ref struct_definition, ref generics)
-        | ItemKind::Union(ident, ref struct_definition, ref generics) => {
+        ItemKind::Struct(ident, ref generics, ref struct_definition)
+        | ItemKind::Union(ident, ref generics, ref struct_definition) => {
             try_visit!(visitor.visit_ident(ident));
             try_visit!(visitor.visit_generics(generics));
             try_visit!(visitor.visit_variant_data(struct_definition));
@@ -631,8 +633,9 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item<'v>) -> V::
 }
 
 pub fn walk_body<'v, V: Visitor<'v>>(visitor: &mut V, body: &Body<'v>) -> V::Result {
-    walk_list!(visitor, visit_param, body.params);
-    visitor.visit_expr(body.value)
+    let Body { params, value } = body;
+    walk_list!(visitor, visit_param, *params);
+    visitor.visit_expr(*value)
 }
 
 pub fn walk_ident<'v, V: Visitor<'v>>(visitor: &mut V, ident: Ident) -> V::Result {
@@ -640,7 +643,8 @@ pub fn walk_ident<'v, V: Visitor<'v>>(visitor: &mut V, ident: Ident) -> V::Resul
 }
 
 pub fn walk_mod<'v, V: Visitor<'v>>(visitor: &mut V, module: &'v Mod<'v>) -> V::Result {
-    walk_list!(visitor, visit_nested_item, module.item_ids.iter().copied());
+    let Mod { spans: _, item_ids } = module;
+    walk_list!(visitor, visit_nested_item, item_ids.iter().copied());
     V::Result::output()
 }
 
@@ -648,10 +652,11 @@ pub fn walk_foreign_item<'v, V: Visitor<'v>>(
     visitor: &mut V,
     foreign_item: &'v ForeignItem<'v>,
 ) -> V::Result {
+    let ForeignItem { ident, kind, owner_id: _, span: _, vis_span: _ } = foreign_item;
     try_visit!(visitor.visit_id(foreign_item.hir_id()));
-    try_visit!(visitor.visit_ident(foreign_item.ident));
+    try_visit!(visitor.visit_ident(*ident));
 
-    match foreign_item.kind {
+    match *kind {
         ForeignItemKind::Fn(ref sig, param_idents, ref generics) => {
             try_visit!(visitor.visit_generics(generics));
             try_visit!(visitor.visit_fn_decl(sig.decl));
@@ -670,24 +675,27 @@ pub fn walk_foreign_item<'v, V: Visitor<'v>>(
 pub fn walk_local<'v, V: Visitor<'v>>(visitor: &mut V, local: &'v LetStmt<'v>) -> V::Result {
     // Intentionally visiting the expr first - the initialization expr
     // dominates the local's definition.
-    visit_opt!(visitor, visit_expr, local.init);
-    try_visit!(visitor.visit_id(local.hir_id));
-    try_visit!(visitor.visit_pat(local.pat));
-    visit_opt!(visitor, visit_block, local.els);
-    visit_opt!(visitor, visit_ty_unambig, local.ty);
+    let LetStmt { super_: _, pat, ty, init, els, hir_id, span: _, source: _ } = local;
+    visit_opt!(visitor, visit_expr, *init);
+    try_visit!(visitor.visit_id(*hir_id));
+    try_visit!(visitor.visit_pat(*pat));
+    visit_opt!(visitor, visit_block, *els);
+    visit_opt!(visitor, visit_ty_unambig, *ty);
     V::Result::output()
 }
 
 pub fn walk_block<'v, V: Visitor<'v>>(visitor: &mut V, block: &'v Block<'v>) -> V::Result {
-    try_visit!(visitor.visit_id(block.hir_id));
-    walk_list!(visitor, visit_stmt, block.stmts);
-    visit_opt!(visitor, visit_expr, block.expr);
+    let Block { stmts, expr, hir_id, rules: _, span: _, targeted_by_break: _ } = block;
+    try_visit!(visitor.visit_id(*hir_id));
+    walk_list!(visitor, visit_stmt, *stmts);
+    visit_opt!(visitor, visit_expr, *expr);
     V::Result::output()
 }
 
 pub fn walk_stmt<'v, V: Visitor<'v>>(visitor: &mut V, statement: &'v Stmt<'v>) -> V::Result {
-    try_visit!(visitor.visit_id(statement.hir_id));
-    match statement.kind {
+    let Stmt { kind, hir_id, span: _ } = statement;
+    try_visit!(visitor.visit_id(*hir_id));
+    match *kind {
         StmtKind::Let(ref local) => visitor.visit_local(local),
         StmtKind::Item(item) => visitor.visit_nested_item(item),
         StmtKind::Expr(ref expression) | StmtKind::Semi(ref expression) => {
@@ -697,15 +705,17 @@ pub fn walk_stmt<'v, V: Visitor<'v>>(visitor: &mut V, statement: &'v Stmt<'v>) -
 }
 
 pub fn walk_arm<'v, V: Visitor<'v>>(visitor: &mut V, arm: &'v Arm<'v>) -> V::Result {
-    try_visit!(visitor.visit_id(arm.hir_id));
-    try_visit!(visitor.visit_pat(arm.pat));
-    visit_opt!(visitor, visit_expr, arm.guard);
-    visitor.visit_expr(arm.body)
+    let Arm { hir_id, span: _, pat, guard, body } = arm;
+    try_visit!(visitor.visit_id(*hir_id));
+    try_visit!(visitor.visit_pat(*pat));
+    visit_opt!(visitor, visit_expr, *guard);
+    visitor.visit_expr(*body)
 }
 
 pub fn walk_ty_pat<'v, V: Visitor<'v>>(visitor: &mut V, pattern: &'v TyPat<'v>) -> V::Result {
-    try_visit!(visitor.visit_id(pattern.hir_id));
-    match pattern.kind {
+    let TyPat { kind, hir_id, span: _ } = pattern;
+    try_visit!(visitor.visit_id(*hir_id));
+    match *kind {
         TyPatKind::Range(lower_bound, upper_bound) => {
             try_visit!(visitor.visit_const_arg_unambig(lower_bound));
             try_visit!(visitor.visit_const_arg_unambig(upper_bound));
@@ -717,14 +727,15 @@ pub fn walk_ty_pat<'v, V: Visitor<'v>>(visitor: &mut V, pattern: &'v TyPat<'v>)
 }
 
 pub fn walk_pat<'v, V: Visitor<'v>>(visitor: &mut V, pattern: &'v Pat<'v>) -> V::Result {
-    try_visit!(visitor.visit_id(pattern.hir_id));
-    match pattern.kind {
+    let Pat { hir_id, kind, span, default_binding_modes: _ } = pattern;
+    try_visit!(visitor.visit_id(*hir_id));
+    match *kind {
         PatKind::TupleStruct(ref qpath, children, _) => {
-            try_visit!(visitor.visit_qpath(qpath, pattern.hir_id, pattern.span));
+            try_visit!(visitor.visit_qpath(qpath, *hir_id, *span));
             walk_list!(visitor, visit_pat, children);
         }
         PatKind::Struct(ref qpath, fields, _) => {
-            try_visit!(visitor.visit_qpath(qpath, pattern.hir_id, pattern.span));
+            try_visit!(visitor.visit_qpath(qpath, *hir_id, *span));
             walk_list!(visitor, visit_pat_field, fields);
         }
         PatKind::Or(pats) => walk_list!(visitor, visit_pat, pats),
@@ -760,36 +771,41 @@ pub fn walk_pat<'v, V: Visitor<'v>>(visitor: &mut V, pattern: &'v Pat<'v>) -> V:
 }
 
 pub fn walk_pat_field<'v, V: Visitor<'v>>(visitor: &mut V, field: &'v PatField<'v>) -> V::Result {
-    try_visit!(visitor.visit_id(field.hir_id));
-    try_visit!(visitor.visit_ident(field.ident));
-    visitor.visit_pat(field.pat)
+    let PatField { hir_id, ident, pat, is_shorthand: _, span: _ } = field;
+    try_visit!(visitor.visit_id(*hir_id));
+    try_visit!(visitor.visit_ident(*ident));
+    visitor.visit_pat(*pat)
 }
 
 pub fn walk_pat_expr<'v, V: Visitor<'v>>(visitor: &mut V, expr: &'v PatExpr<'v>) -> V::Result {
-    try_visit!(visitor.visit_id(expr.hir_id));
-    match &expr.kind {
-        PatExprKind::Lit { lit, negated } => visitor.visit_lit(expr.hir_id, lit, *negated),
+    let PatExpr { hir_id, span, kind } = expr;
+    try_visit!(visitor.visit_id(*hir_id));
+    match kind {
+        PatExprKind::Lit { lit, negated } => visitor.visit_lit(*hir_id, lit, *negated),
         PatExprKind::ConstBlock(c) => visitor.visit_inline_const(c),
-        PatExprKind::Path(qpath) => visitor.visit_qpath(qpath, expr.hir_id, expr.span),
+        PatExprKind::Path(qpath) => visitor.visit_qpath(qpath, *hir_id, *span),
     }
 }
 
 pub fn walk_anon_const<'v, V: Visitor<'v>>(visitor: &mut V, constant: &'v AnonConst) -> V::Result {
-    try_visit!(visitor.visit_id(constant.hir_id));
-    visitor.visit_nested_body(constant.body)
+    let AnonConst { hir_id, def_id: _, body, span: _ } = constant;
+    try_visit!(visitor.visit_id(*hir_id));
+    visitor.visit_nested_body(*body)
 }
 
 pub fn walk_inline_const<'v, V: Visitor<'v>>(
     visitor: &mut V,
     constant: &'v ConstBlock,
 ) -> V::Result {
-    try_visit!(visitor.visit_id(constant.hir_id));
-    visitor.visit_nested_body(constant.body)
+    let ConstBlock { hir_id, def_id: _, body } = constant;
+    try_visit!(visitor.visit_id(*hir_id));
+    visitor.visit_nested_body(*body)
 }
 
 pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr<'v>) -> V::Result {
-    try_visit!(visitor.visit_id(expression.hir_id));
-    match expression.kind {
+    let Expr { hir_id, kind, span } = expression;
+    try_visit!(visitor.visit_id(*hir_id));
+    match *kind {
         ExprKind::Array(subexpressions) => {
             walk_list!(visitor, visit_expr, subexpressions);
         }
@@ -801,7 +817,7 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr<'v>)
             try_visit!(visitor.visit_const_arg_unambig(count));
         }
         ExprKind::Struct(ref qpath, fields, ref optional_base) => {
-            try_visit!(visitor.visit_qpath(qpath, expression.hir_id, expression.span));
+            try_visit!(visitor.visit_qpath(qpath, *hir_id, *span));
             walk_list!(visitor, visit_expr_field, fields);
             match optional_base {
                 StructTailExpr::Base(base) => try_visit!(visitor.visit_expr(base)),
@@ -869,7 +885,7 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr<'v>)
             constness: _,
         }) => {
             walk_list!(visitor, visit_generic_param, bound_generic_params);
-            try_visit!(visitor.visit_fn(FnKind::Closure, fn_decl, body, expression.span, def_id));
+            try_visit!(visitor.visit_fn(FnKind::Closure, fn_decl, body, *span, def_id));
         }
         ExprKind::Block(ref block, ref opt_label) => {
             visit_opt!(visitor, visit_label, opt_label);
@@ -892,7 +908,7 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr<'v>)
             try_visit!(visitor.visit_expr(index_expression));
         }
         ExprKind::Path(ref qpath) => {
-            try_visit!(visitor.visit_qpath(qpath, expression.hir_id, expression.span));
+            try_visit!(visitor.visit_qpath(qpath, *hir_id, *span));
         }
         ExprKind::Break(ref destination, ref opt_expr) => {
             visit_opt!(visitor, visit_label, &destination.label);
@@ -906,7 +922,7 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr<'v>)
         }
         ExprKind::Become(ref expr) => try_visit!(visitor.visit_expr(expr)),
         ExprKind::InlineAsm(ref asm) => {
-            try_visit!(visitor.visit_inline_asm(asm, expression.hir_id));
+            try_visit!(visitor.visit_inline_asm(asm, *hir_id));
         }
         ExprKind::OffsetOf(ref container, ref fields) => {
             try_visit!(visitor.visit_ty_unambig(container));
@@ -919,16 +935,17 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr<'v>)
             try_visit!(visitor.visit_expr(expr));
             visit_opt!(visitor, visit_ty_unambig, ty);
         }
-        ExprKind::Lit(lit) => try_visit!(visitor.visit_lit(expression.hir_id, lit, false)),
+        ExprKind::Lit(lit) => try_visit!(visitor.visit_lit(*hir_id, lit, false)),
         ExprKind::Err(_) => {}
     }
     V::Result::output()
 }
 
 pub fn walk_expr_field<'v, V: Visitor<'v>>(visitor: &mut V, field: &'v ExprField<'v>) -> V::Result {
-    try_visit!(visitor.visit_id(field.hir_id));
-    try_visit!(visitor.visit_ident(field.ident));
-    visitor.visit_expr(field.expr)
+    let ExprField { hir_id, ident, expr, span: _, is_shorthand: _ } = field;
+    try_visit!(visitor.visit_id(*hir_id));
+    try_visit!(visitor.visit_ident(*ident));
+    visitor.visit_expr(*expr)
 }
 /// We track whether an infer var is from a [`Ty`], [`ConstArg`], or [`GenericArg`] so that
 /// HIR visitors overriding [`Visitor::visit_infer`] can determine what kind of infer is being visited
@@ -946,7 +963,10 @@ pub fn walk_generic_arg<'v, V: Visitor<'v>>(
         GenericArg::Lifetime(lt) => visitor.visit_lifetime(lt),
         GenericArg::Type(ty) => visitor.visit_ty(ty),
         GenericArg::Const(ct) => visitor.visit_const_arg(ct),
-        GenericArg::Infer(inf) => visitor.visit_infer(inf.hir_id, inf.span, InferKind::Ambig(inf)),
+        GenericArg::Infer(inf) => {
+            let InferArg { hir_id, span } = inf;
+            visitor.visit_infer(*hir_id, *span, InferKind::Ambig(inf))
+        }
     }
 }
 
@@ -954,16 +974,18 @@ pub fn walk_unambig_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty<'v>) ->
     match typ.try_as_ambig_ty() {
         Some(ambig_ty) => visitor.visit_ty(ambig_ty),
         None => {
-            try_visit!(visitor.visit_id(typ.hir_id));
-            visitor.visit_infer(typ.hir_id, typ.span, InferKind::Ty(typ))
+            let Ty { hir_id, span, kind: _ } = typ;
+            try_visit!(visitor.visit_id(*hir_id));
+            visitor.visit_infer(*hir_id, *span, InferKind::Ty(typ))
         }
     }
 }
 
 pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty<'v, AmbigArg>) -> V::Result {
-    try_visit!(visitor.visit_id(typ.hir_id));
+    let Ty { hir_id, span: _, kind } = typ;
+    try_visit!(visitor.visit_id(*hir_id));
 
-    match typ.kind {
+    match *kind {
         TyKind::Slice(ref ty) => try_visit!(visitor.visit_ty_unambig(ty)),
         TyKind::Ptr(ref mutable_type) => try_visit!(visitor.visit_ty_unambig(mutable_type.ty)),
         TyKind::Ref(ref lifetime, ref mutable_type) => {
@@ -1018,8 +1040,9 @@ pub fn walk_const_arg<'v, V: Visitor<'v>>(
     match const_arg.try_as_ambig_ct() {
         Some(ambig_ct) => visitor.visit_const_arg(ambig_ct),
         None => {
-            try_visit!(visitor.visit_id(const_arg.hir_id));
-            visitor.visit_infer(const_arg.hir_id, const_arg.span(), InferKind::Const(const_arg))
+            let ConstArg { hir_id, kind: _ } = const_arg;
+            try_visit!(visitor.visit_id(*hir_id));
+            visitor.visit_infer(*hir_id, const_arg.span(), InferKind::Const(const_arg))
         }
     }
 }
@@ -1028,9 +1051,10 @@ pub fn walk_ambig_const_arg<'v, V: Visitor<'v>>(
     visitor: &mut V,
     const_arg: &'v ConstArg<'v, AmbigArg>,
 ) -> V::Result {
-    try_visit!(visitor.visit_id(const_arg.hir_id));
-    match &const_arg.kind {
-        ConstArgKind::Path(qpath) => visitor.visit_qpath(qpath, const_arg.hir_id, qpath.span()),
+    let ConstArg { hir_id, kind } = const_arg;
+    try_visit!(visitor.visit_id(*hir_id));
+    match kind {
+        ConstArgKind::Path(qpath) => visitor.visit_qpath(qpath, *hir_id, qpath.span()),
         ConstArgKind::Anon(anon) => visitor.visit_anon_const(*anon),
     }
 }
@@ -1039,12 +1063,22 @@ pub fn walk_generic_param<'v, V: Visitor<'v>>(
     visitor: &mut V,
     param: &'v GenericParam<'v>,
 ) -> V::Result {
-    try_visit!(visitor.visit_id(param.hir_id));
-    match param.name {
+    let GenericParam {
+        hir_id,
+        def_id: _,
+        name,
+        span: _,
+        pure_wrt_drop: _,
+        kind,
+        colon_span: _,
+        source: _,
+    } = param;
+    try_visit!(visitor.visit_id(*hir_id));
+    match *name {
         ParamName::Plain(ident) | ParamName::Error(ident) => try_visit!(visitor.visit_ident(ident)),
         ParamName::Fresh => {}
     }
-    match param.kind {
+    match *kind {
         GenericParamKind::Lifetime { .. } => {}
         GenericParamKind::Type { ref default, .. } => {
             visit_opt!(visitor, visit_ty_unambig, default)
@@ -1052,7 +1086,7 @@ pub fn walk_generic_param<'v, V: Visitor<'v>>(
         GenericParamKind::Const { ref ty, ref default, synthetic: _ } => {
             try_visit!(visitor.visit_ty_unambig(ty));
             if let Some(default) = default {
-                try_visit!(visitor.visit_const_param_default(param.hir_id, default));
+                try_visit!(visitor.visit_const_param_default(*hir_id, default));
             }
         }
     }
@@ -1067,8 +1101,15 @@ pub fn walk_const_param_default<'v, V: Visitor<'v>>(
 }
 
 pub fn walk_generics<'v, V: Visitor<'v>>(visitor: &mut V, generics: &'v Generics<'v>) -> V::Result {
-    walk_list!(visitor, visit_generic_param, generics.params);
-    walk_list!(visitor, visit_where_predicate, generics.predicates);
+    let &Generics {
+        params,
+        predicates,
+        has_where_clause_predicates: _,
+        where_clause_span: _,
+        span: _,
+    } = generics;
+    walk_list!(visitor, visit_generic_param, params);
+    walk_list!(visitor, visit_where_predicate, predicates);
     V::Result::output()
 }
 
@@ -1109,8 +1150,10 @@ pub fn walk_fn_decl<'v, V: Visitor<'v>>(
     visitor: &mut V,
     function_declaration: &'v FnDecl<'v>,
 ) -> V::Result {
-    walk_list!(visitor, visit_ty_unambig, function_declaration.inputs);
-    visitor.visit_fn_ret_ty(&function_declaration.output)
+    let FnDecl { inputs, output, c_variadic: _, implicit_self: _, lifetime_elision_allowed: _ } =
+        function_declaration;
+    walk_list!(visitor, visit_ty_unambig, *inputs);
+    visitor.visit_fn_ret_ty(output)
 }
 
 pub fn walk_fn_ret_ty<'v, V: Visitor<'v>>(visitor: &mut V, ret_ty: &'v FnRetTy<'v>) -> V::Result {
@@ -1148,7 +1191,7 @@ pub fn walk_use<'v, V: Visitor<'v>>(
     hir_id: HirId,
 ) -> V::Result {
     let UsePath { segments, ref res, span } = *path;
-    for &res in res {
+    for res in res.present_items() {
         try_visit!(visitor.visit_path(&Path { segments, res, span }, hir_id));
     }
     V::Result::output()
@@ -1264,8 +1307,9 @@ pub fn walk_trait_ref<'v, V: Visitor<'v>>(
     visitor: &mut V,
     trait_ref: &'v TraitRef<'v>,
 ) -> V::Result {
-    try_visit!(visitor.visit_id(trait_ref.hir_ref_id));
-    visitor.visit_path(trait_ref.path, trait_ref.hir_ref_id)
+    let TraitRef { hir_ref_id, path } = trait_ref;
+    try_visit!(visitor.visit_id(*hir_ref_id));
+    visitor.visit_path(*path, *hir_ref_id)
 }
 
 pub fn walk_param_bound<'v, V: Visitor<'v>>(
@@ -1288,7 +1332,10 @@ pub fn walk_precise_capturing_arg<'v, V: Visitor<'v>>(
 ) -> V::Result {
     match *arg {
         PreciseCapturingArg::Lifetime(lt) => visitor.visit_lifetime(lt),
-        PreciseCapturingArg::Param(param) => visitor.visit_id(param.hir_id),
+        PreciseCapturingArg::Param(param) => {
+            let PreciseCapturingNonLifetimeArg { hir_id, ident: _, res: _ } = param;
+            visitor.visit_id(hir_id)
+        }
     }
 }
 
@@ -1296,8 +1343,9 @@ pub fn walk_poly_trait_ref<'v, V: Visitor<'v>>(
     visitor: &mut V,
     trait_ref: &'v PolyTraitRef<'v>,
 ) -> V::Result {
-    walk_list!(visitor, visit_generic_param, trait_ref.bound_generic_params);
-    visitor.visit_trait_ref(&trait_ref.trait_ref)
+    let PolyTraitRef { bound_generic_params, modifiers: _, trait_ref, span: _ } = trait_ref;
+    walk_list!(visitor, visit_generic_param, *bound_generic_params);
+    visitor.visit_trait_ref(trait_ref)
 }
 
 pub fn walk_opaque_ty<'v, V: Visitor<'v>>(visitor: &mut V, opaque: &'v OpaqueTy<'v>) -> V::Result {
@@ -1330,29 +1378,34 @@ pub fn walk_enum_def<'v, V: Visitor<'v>>(
     visitor: &mut V,
     enum_definition: &'v EnumDef<'v>,
 ) -> V::Result {
-    walk_list!(visitor, visit_variant, enum_definition.variants);
+    let EnumDef { variants } = enum_definition;
+    walk_list!(visitor, visit_variant, *variants);
     V::Result::output()
 }
 
 pub fn walk_variant<'v, V: Visitor<'v>>(visitor: &mut V, variant: &'v Variant<'v>) -> V::Result {
-    try_visit!(visitor.visit_ident(variant.ident));
-    try_visit!(visitor.visit_id(variant.hir_id));
-    try_visit!(visitor.visit_variant_data(&variant.data));
-    visit_opt!(visitor, visit_anon_const, &variant.disr_expr);
+    let Variant { ident, hir_id, def_id: _, data, disr_expr, span: _ } = variant;
+    try_visit!(visitor.visit_ident(*ident));
+    try_visit!(visitor.visit_id(*hir_id));
+    try_visit!(visitor.visit_variant_data(data));
+    visit_opt!(visitor, visit_anon_const, disr_expr);
     V::Result::output()
 }
 
 pub fn walk_label<'v, V: Visitor<'v>>(visitor: &mut V, label: &'v Label) -> V::Result {
-    visitor.visit_ident(label.ident)
+    let Label { ident } = label;
+    visitor.visit_ident(*ident)
 }
 
 pub fn walk_inf<'v, V: Visitor<'v>>(visitor: &mut V, inf: &'v InferArg) -> V::Result {
-    visitor.visit_id(inf.hir_id)
+    let InferArg { hir_id, span: _ } = inf;
+    visitor.visit_id(*hir_id)
 }
 
 pub fn walk_lifetime<'v, V: Visitor<'v>>(visitor: &mut V, lifetime: &'v Lifetime) -> V::Result {
-    try_visit!(visitor.visit_id(lifetime.hir_id));
-    visitor.visit_ident(lifetime.ident)
+    let Lifetime { hir_id, ident, kind: _, source: _, syntax: _ } = lifetime;
+    try_visit!(visitor.visit_id(*hir_id));
+    visitor.visit_ident(*ident)
 }
 
 pub fn walk_qpath<'v, V: Visitor<'v>>(
@@ -1374,7 +1427,8 @@ pub fn walk_qpath<'v, V: Visitor<'v>>(
 }
 
 pub fn walk_path<'v, V: Visitor<'v>>(visitor: &mut V, path: &Path<'v>) -> V::Result {
-    walk_list!(visitor, visit_path_segment, path.segments);
+    let Path { segments, span: _, res: _ } = path;
+    walk_list!(visitor, visit_path_segment, *segments);
     V::Result::output()
 }
 
@@ -1382,9 +1436,10 @@ pub fn walk_path_segment<'v, V: Visitor<'v>>(
     visitor: &mut V,
     segment: &'v PathSegment<'v>,
 ) -> V::Result {
-    try_visit!(visitor.visit_ident(segment.ident));
-    try_visit!(visitor.visit_id(segment.hir_id));
-    visit_opt!(visitor, visit_generic_args, segment.args);
+    let PathSegment { ident, hir_id, res: _, args, infer_args: _ } = segment;
+    try_visit!(visitor.visit_ident(*ident));
+    try_visit!(visitor.visit_id(*hir_id));
+    visit_opt!(visitor, visit_generic_args, *args);
     V::Result::output()
 }
 
@@ -1392,8 +1447,9 @@ pub fn walk_generic_args<'v, V: Visitor<'v>>(
     visitor: &mut V,
     generic_args: &'v GenericArgs<'v>,
 ) -> V::Result {
-    walk_list!(visitor, visit_generic_arg, generic_args.args);
-    walk_list!(visitor, visit_assoc_item_constraint, generic_args.constraints);
+    let GenericArgs { args, constraints, parenthesized: _, span_ext: _ } = generic_args;
+    walk_list!(visitor, visit_generic_arg, *args);
+    walk_list!(visitor, visit_assoc_item_constraint, *constraints);
     V::Result::output()
 }
 
@@ -1401,9 +1457,10 @@ pub fn walk_assoc_item_constraint<'v, V: Visitor<'v>>(
     visitor: &mut V,
     constraint: &'v AssocItemConstraint<'v>,
 ) -> V::Result {
-    try_visit!(visitor.visit_id(constraint.hir_id));
-    try_visit!(visitor.visit_ident(constraint.ident));
-    try_visit!(visitor.visit_generic_args(constraint.gen_args));
+    let AssocItemConstraint { hir_id, ident, gen_args, kind: _, span: _ } = constraint;
+    try_visit!(visitor.visit_id(*hir_id));
+    try_visit!(visitor.visit_ident(*ident));
+    try_visit!(visitor.visit_generic_args(*gen_args));
     match constraint.kind {
         AssocItemConstraintKind::Equality { ref term } => match term {
             Term::Ty(ty) => try_visit!(visitor.visit_ty_unambig(ty)),
diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs
index 06814eaefe8..846eacce9e1 100644
--- a/compiler/rustc_hir_analysis/src/check/check.rs
+++ b/compiler/rustc_hir_analysis/src/check/check.rs
@@ -18,7 +18,7 @@ use rustc_middle::middle::resolve_bound_vars::ResolvedArg;
 use rustc_middle::middle::stability::EvalResult;
 use rustc_middle::ty::error::TypeErrorToStringExt;
 use rustc_middle::ty::layout::{LayoutError, MAX_SIMD_LANES};
-use rustc_middle::ty::util::{Discr, IntTypeExt};
+use rustc_middle::ty::util::Discr;
 use rustc_middle::ty::{
     AdtDef, BottomUpFolder, GenericArgKind, RegionKind, TypeFoldable, TypeSuperVisitable,
     TypeVisitable, TypeVisitableExt, fold_regions,
@@ -1385,19 +1385,6 @@ fn check_enum(tcx: TyCtxt<'_>, def_id: LocalDefId) {
         );
     }
 
-    let repr_type_ty = def.repr().discr_type().to_ty(tcx);
-    if repr_type_ty == tcx.types.i128 || repr_type_ty == tcx.types.u128 {
-        if !tcx.features().repr128() {
-            feature_err(
-                &tcx.sess,
-                sym::repr128,
-                tcx.def_span(def_id),
-                "repr with 128-bit type is unstable",
-            )
-            .emit();
-        }
-    }
-
     for v in def.variants() {
         if let ty::VariantDiscr::Explicit(discr_def_id) = v.discr {
             tcx.ensure_ok().typeck(discr_def_id.expect_local());
@@ -1575,7 +1562,7 @@ fn check_type_alias_type_params_are_used<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalD
 
     let mut params_used = DenseBitSet::new_empty(generics.own_params.len());
     for leaf in ty.walk() {
-        if let GenericArgKind::Type(leaf_ty) = leaf.unpack()
+        if let GenericArgKind::Type(leaf_ty) = leaf.kind()
             && let ty::Param(param) = leaf_ty.kind()
         {
             debug!("found use of ty param {:?}", param);
@@ -1700,7 +1687,7 @@ fn opaque_type_cycle_error(tcx: TyCtxt<'_>, opaque_def_id: LocalDefId) -> ErrorG
 
                     let mut label_match = |ty: Ty<'_>, span| {
                         for arg in ty.walk() {
-                            if let ty::GenericArgKind::Type(ty) = arg.unpack()
+                            if let ty::GenericArgKind::Type(ty) = arg.kind()
                                 && let ty::Alias(
                                     ty::Opaque,
                                     ty::AliasTy { def_id: captured_def_id, .. },
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 2ee41e2efbd..47681a78ecc 100644
--- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
+++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
@@ -1231,7 +1231,7 @@ fn check_region_late_boundedness<'tcx>(
     for (id_arg, arg) in
         std::iter::zip(ty::GenericArgs::identity_for_item(tcx, impl_m.def_id), impl_m_args)
     {
-        if let ty::GenericArgKind::Lifetime(r) = arg.unpack()
+        if let ty::GenericArgKind::Lifetime(r) = arg.kind()
             && let ty::ReVar(vid) = r.kind()
             && let r = infcx
                 .inner
@@ -1256,7 +1256,7 @@ fn check_region_late_boundedness<'tcx>(
     for (id_arg, arg) in
         std::iter::zip(ty::GenericArgs::identity_for_item(tcx, trait_m.def_id), trait_m_args)
     {
-        if let ty::GenericArgKind::Lifetime(r) = arg.unpack()
+        if let ty::GenericArgKind::Lifetime(r) = arg.kind()
             && let ty::ReVar(vid) = r.kind()
             && let r = infcx
                 .inner
diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs
index 4973d848959..3db1c40228f 100644
--- a/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs
+++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs
@@ -427,7 +427,7 @@ fn report_mismatched_rpitit_captures<'tcx>(
     };
 
     trait_captured_args
-        .sort_by_cached_key(|arg| !matches!(arg.unpack(), ty::GenericArgKind::Lifetime(_)));
+        .sort_by_cached_key(|arg| !matches!(arg.kind(), ty::GenericArgKind::Lifetime(_)));
     let suggestion = format!("use<{}>", trait_captured_args.iter().join(", "));
 
     tcx.emit_node_span_lint(
diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs
index 9fd158ad154..09610a2f3ec 100644
--- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs
+++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs
@@ -204,24 +204,25 @@ pub(crate) fn check_intrinsic_type(
 
         // Each atomic op has variants with different suffixes (`_seq_cst`, `_acquire`, etc.). Use
         // string ops to strip the suffixes, because the variants all get the same treatment here.
-        let (n_tps, inputs, output) = match split[1] {
+        let (n_tps, n_cts, inputs, output) = match split[1] {
             "cxchg" | "cxchgweak" => (
                 1,
+                0,
                 vec![Ty::new_mut_ptr(tcx, param(0)), param(0), param(0)],
                 Ty::new_tup(tcx, &[param(0), tcx.types.bool]),
             ),
-            "load" => (1, vec![Ty::new_imm_ptr(tcx, param(0))], param(0)),
-            "store" => (1, vec![Ty::new_mut_ptr(tcx, param(0)), param(0)], tcx.types.unit),
+            "load" => (1, 1, vec![Ty::new_imm_ptr(tcx, param(0))], param(0)),
+            "store" => (1, 0, vec![Ty::new_mut_ptr(tcx, param(0)), param(0)], tcx.types.unit),
 
             "xchg" | "xadd" | "xsub" | "and" | "nand" | "or" | "xor" | "max" | "min" | "umax"
-            | "umin" => (1, vec![Ty::new_mut_ptr(tcx, param(0)), param(0)], param(0)),
-            "fence" | "singlethreadfence" => (0, Vec::new(), tcx.types.unit),
+            | "umin" => (1, 0, vec![Ty::new_mut_ptr(tcx, param(0)), param(0)], param(0)),
+            "fence" | "singlethreadfence" => (0, 0, Vec::new(), tcx.types.unit),
             op => {
                 tcx.dcx().emit_err(UnrecognizedAtomicOperation { span, op });
                 return;
             }
         };
-        (n_tps, 0, 0, inputs, output, hir::Safety::Unsafe)
+        (n_tps, 0, n_cts, inputs, output, hir::Safety::Unsafe)
     } else if intrinsic_name == sym::contract_check_ensures {
         // contract_check_ensures::<Ret, C>(Ret, C) -> Ret
         // where C: for<'a> Fn(&'a Ret) -> bool,
@@ -264,6 +265,7 @@ pub(crate) fn check_intrinsic_type(
                 vec![Ty::new_imm_ptr(tcx, param(0)), tcx.types.isize],
                 Ty::new_imm_ptr(tcx, param(0)),
             ),
+            sym::slice_get_unchecked => (3, 0, vec![param(1), tcx.types.usize], param(0)),
             sym::ptr_mask => (
                 1,
                 0,
diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
index 2ec14b2f018..b764b714fe1 100644
--- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs
+++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
@@ -297,34 +297,30 @@ fn check_item<'tcx>(tcx: TyCtxt<'tcx>, item: &'tcx hir::Item<'tcx>) -> Result<()
         hir::ItemKind::Fn { ident, sig, .. } => {
             check_item_fn(tcx, def_id, ident, item.span, sig.decl)
         }
-        hir::ItemKind::Static(_, ty, ..) => {
-            check_item_type(tcx, def_id, ty.span, UnsizedHandling::Forbid)
+        hir::ItemKind::Static(_, _, ty, _) => {
+            check_static_item(tcx, def_id, ty.span, UnsizedHandling::Forbid)
         }
-        hir::ItemKind::Const(_, ty, ..) => {
-            check_item_type(tcx, def_id, ty.span, UnsizedHandling::Forbid)
-        }
-        hir::ItemKind::Struct(_, _, hir_generics) => {
+        hir::ItemKind::Const(_, _, ty, _) => check_const_item(tcx, def_id, ty.span, item.span),
+        hir::ItemKind::Struct(_, generics, _) => {
             let res = check_type_defn(tcx, item, false);
-            check_variances_for_type_defn(tcx, item, hir_generics);
+            check_variances_for_type_defn(tcx, item, generics);
             res
         }
-        hir::ItemKind::Union(_, _, hir_generics) => {
+        hir::ItemKind::Union(_, generics, _) => {
             let res = check_type_defn(tcx, item, true);
-            check_variances_for_type_defn(tcx, item, hir_generics);
+            check_variances_for_type_defn(tcx, item, generics);
             res
         }
-        hir::ItemKind::Enum(_, _, hir_generics) => {
+        hir::ItemKind::Enum(_, generics, _) => {
             let res = check_type_defn(tcx, item, true);
-            check_variances_for_type_defn(tcx, item, hir_generics);
+            check_variances_for_type_defn(tcx, item, generics);
             res
         }
         hir::ItemKind::Trait(..) => check_trait(tcx, item),
         hir::ItemKind::TraitAlias(..) => check_trait(tcx, item),
         // `ForeignItem`s are handled separately.
         hir::ItemKind::ForeignMod { .. } => Ok(()),
-        hir::ItemKind::TyAlias(_, hir_ty, hir_generics)
-            if tcx.type_alias_is_lazy(item.owner_id) =>
-        {
+        hir::ItemKind::TyAlias(_, generics, hir_ty) if tcx.type_alias_is_lazy(item.owner_id) => {
             let res = enter_wf_checking_ctxt(tcx, item.span, def_id, |wfcx| {
                 let ty = tcx.type_of(def_id).instantiate_identity();
                 let item_ty =
@@ -337,7 +333,7 @@ fn check_item<'tcx>(tcx: TyCtxt<'tcx>, item: &'tcx hir::Item<'tcx>) -> Result<()
                 check_where_clauses(wfcx, item.span, def_id);
                 Ok(())
             });
-            check_variances_for_type_defn(tcx, item, hir_generics);
+            check_variances_for_type_defn(tcx, item, generics);
             res
         }
         _ => Ok(()),
@@ -366,7 +362,7 @@ fn check_foreign_item<'tcx>(
             check_item_fn(tcx, def_id, item.ident, item.span, sig.decl)
         }
         hir::ForeignItemKind::Static(ty, ..) => {
-            check_item_type(tcx, def_id, ty.span, UnsizedHandling::AllowIfForeignTail)
+            check_static_item(tcx, def_id, ty.span, UnsizedHandling::AllowIfForeignTail)
         }
         hir::ForeignItemKind::Type => Ok(()),
     }
@@ -742,7 +738,7 @@ fn ty_known_to_outlive<'tcx>(
     region: ty::Region<'tcx>,
 ) -> bool {
     test_region_obligations(tcx, id, param_env, wf_tys, |infcx| {
-        infcx.register_region_obligation(infer::RegionObligation {
+        infcx.register_type_outlives_constraint_inner(infer::TypeOutlivesConstraint {
             sub_region: region,
             sup_type: ty,
             origin: infer::RelateParamBound(DUMMY_SP, ty, None),
@@ -819,7 +815,7 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for GATArgsCollector<'tcx> {
         match t.kind() {
             ty::Alias(ty::Projection, p) if p.def_id == self.gat => {
                 for (idx, arg) in p.args.iter().enumerate() {
-                    match arg.unpack() {
+                    match arg.kind() {
                         GenericArgKind::Lifetime(lt) if !lt.is_bound() => {
                             self.regions.insert((lt, idx));
                         }
@@ -1048,8 +1044,7 @@ fn check_param_wf(tcx: TyCtxt<'_>, param: &hir::GenericParam<'_>) -> Result<(),
                             match ty.kind() {
                                 ty::Adt(adt_def, ..) => adt_def.did().is_local(),
                                 // Arrays and slices use the inner type's `ConstParamTy`.
-                                ty::Array(ty, ..) => ty_is_local(*ty),
-                                ty::Slice(ty) => ty_is_local(*ty),
+                                ty::Array(ty, ..) | ty::Slice(ty) => ty_is_local(*ty),
                                 // `&` references use the inner type's `ConstParamTy`.
                                 // `&mut` are not supported.
                                 ty::Ref(_, ty, ast::Mutability::Not) => ty_is_local(*ty),
@@ -1331,14 +1326,13 @@ enum UnsizedHandling {
     AllowIfForeignTail,
 }
 
-fn check_item_type(
+#[instrument(level = "debug", skip(tcx, ty_span, unsized_handling))]
+fn check_static_item(
     tcx: TyCtxt<'_>,
     item_id: LocalDefId,
     ty_span: Span,
     unsized_handling: UnsizedHandling,
 ) -> Result<(), ErrorGuaranteed> {
-    debug!("check_item_type: {:?}", item_id);
-
     enter_wf_checking_ctxt(tcx, ty_span, item_id, |wfcx| {
         let ty = tcx.type_of(item_id).instantiate_identity();
         let item_ty = wfcx.deeply_normalize(ty_span, Some(WellFormedLoc::Ty(item_id)), ty);
@@ -1388,6 +1382,34 @@ fn check_item_type(
     })
 }
 
+fn check_const_item(
+    tcx: TyCtxt<'_>,
+    def_id: LocalDefId,
+    ty_span: Span,
+    item_span: Span,
+) -> Result<(), ErrorGuaranteed> {
+    enter_wf_checking_ctxt(tcx, ty_span, def_id, |wfcx| {
+        let ty = tcx.type_of(def_id).instantiate_identity();
+        let ty = wfcx.deeply_normalize(ty_span, Some(WellFormedLoc::Ty(def_id)), ty);
+
+        wfcx.register_wf_obligation(ty_span, Some(WellFormedLoc::Ty(def_id)), ty.into());
+        wfcx.register_bound(
+            traits::ObligationCause::new(
+                ty_span,
+                wfcx.body_def_id,
+                ObligationCauseCode::SizedConstOrStatic,
+            ),
+            wfcx.param_env,
+            ty,
+            tcx.require_lang_item(LangItem::Sized, None),
+        );
+
+        check_where_clauses(wfcx, item_span, def_id);
+
+        Ok(())
+    })
+}
+
 #[instrument(level = "debug", skip(tcx, hir_self_ty, hir_trait_ref))]
 fn check_impl<'tcx>(
     tcx: TyCtxt<'tcx>,
@@ -1517,7 +1539,7 @@ fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, span: Span, def_id
             } else {
                 // If we've got a generic const parameter we still want to check its
                 // type is correct in case both it and the param type are fully concrete.
-                let GenericArgKind::Const(ct) = default.unpack() else {
+                let GenericArgKind::Const(ct) = default.kind() else {
                     continue;
                 };
 
diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs
index f5206d9a015..a649e7d67af 100644
--- a/compiler/rustc_hir_analysis/src/collect.rs
+++ b/compiler/rustc_hir_analysis/src/collect.rs
@@ -31,7 +31,7 @@ use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_hir::intravisit::{self, InferKind, Visitor, VisitorExt, walk_generics};
 use rustc_hir::{self as hir, GenericParamKind, HirId, Node, PreciseCapturingArgKind};
 use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
-use rustc_infer::traits::ObligationCause;
+use rustc_infer::traits::{DynCompatibilityViolation, ObligationCause};
 use rustc_middle::hir::nested_filter;
 use rustc_middle::query::Providers;
 use rustc_middle::ty::util::{Discr, IntTypeExt};
@@ -40,7 +40,7 @@ use rustc_middle::{bug, span_bug};
 use rustc_span::{DUMMY_SP, Ident, Span, Symbol, kw, sym};
 use rustc_trait_selection::error_reporting::traits::suggestions::NextTypeParamName;
 use rustc_trait_selection::infer::InferCtxtExt;
-use rustc_trait_selection::traits::ObligationCtxt;
+use rustc_trait_selection::traits::{ObligationCtxt, hir_ty_lowering_dyn_compatibility_violations};
 use tracing::{debug, instrument};
 
 use crate::errors;
@@ -248,13 +248,13 @@ fn reject_placeholder_type_signatures_in_item<'tcx>(
     item: &'tcx hir::Item<'tcx>,
 ) {
     let (generics, suggest) = match &item.kind {
-        hir::ItemKind::Union(_, _, generics)
-        | hir::ItemKind::Enum(_, _, generics)
+        hir::ItemKind::Union(_, generics, _)
+        | hir::ItemKind::Enum(_, generics, _)
         | hir::ItemKind::TraitAlias(_, generics, _)
         | hir::ItemKind::Trait(_, _, _, generics, ..)
         | hir::ItemKind::Impl(hir::Impl { generics, .. })
-        | hir::ItemKind::Struct(_, _, generics) => (generics, true),
-        hir::ItemKind::TyAlias(_, _, generics) => (generics, false),
+        | hir::ItemKind::Struct(_, generics, _) => (generics, true),
+        hir::ItemKind::TyAlias(_, generics, _) => (generics, false),
         // `static`, `fn` and `const` are handled elsewhere to suggest appropriate type.
         _ => return,
     };
@@ -470,9 +470,9 @@ impl<'tcx> HirTyLowerer<'tcx> for ItemCtxt<'tcx> {
                         .tcx
                         .hir_expect_item(self.tcx.hir_get_parent_item(self.hir_id()).def_id);
                     match &item.kind {
-                        hir::ItemKind::Enum(_, _, generics)
-                        | hir::ItemKind::Struct(_, _, generics)
-                        | hir::ItemKind::Union(_, _, generics) => {
+                        hir::ItemKind::Enum(_, generics, _)
+                        | hir::ItemKind::Struct(_, generics, _)
+                        | hir::ItemKind::Union(_, generics, _) => {
                             let lt_name = get_new_lifetime_name(self.tcx, poly_trait_ref, generics);
                             let (lt_sp, sugg) = match generics.params {
                                 [] => (generics.span, format!("<{lt_name}>")),
@@ -625,6 +625,10 @@ impl<'tcx> HirTyLowerer<'tcx> for ItemCtxt<'tcx> {
 
         (input_tys, output_ty)
     }
+
+    fn dyn_compatibility_violations(&self, trait_def_id: DefId) -> Vec<DynCompatibilityViolation> {
+        hir_ty_lowering_dyn_compatibility_violations(self.tcx, trait_def_id)
+    }
 }
 
 /// Synthesize a new lifetime name that doesn't clash with any of the lifetimes already present.
@@ -736,7 +740,7 @@ fn lower_item(tcx: TyCtxt<'_>, item_id: hir::ItemId) {
             tcx.at(it.span).explicit_super_predicates_of(def_id);
             tcx.ensure_ok().predicates_of(def_id);
         }
-        hir::ItemKind::Struct(_, struct_def, _) | hir::ItemKind::Union(_, struct_def, _) => {
+        hir::ItemKind::Struct(_, _, struct_def) | hir::ItemKind::Union(_, _, struct_def) => {
             tcx.ensure_ok().generics_of(def_id);
             tcx.ensure_ok().type_of(def_id);
             tcx.ensure_ok().predicates_of(def_id);
@@ -758,7 +762,7 @@ fn lower_item(tcx: TyCtxt<'_>, item_id: hir::ItemId) {
             tcx.ensure_ok().predicates_of(def_id);
         }
 
-        hir::ItemKind::Static(_, ty, ..) | hir::ItemKind::Const(_, ty, ..) => {
+        hir::ItemKind::Static(_, _, ty, _) | hir::ItemKind::Const(_, _, ty, _) => {
             tcx.ensure_ok().generics_of(def_id);
             tcx.ensure_ok().type_of(def_id);
             tcx.ensure_ok().predicates_of(def_id);
@@ -1089,7 +1093,7 @@ fn adt_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::AdtDef<'_> {
 
     let repr = tcx.repr_options_of_def(def_id);
     let (kind, variants) = match &item.kind {
-        ItemKind::Enum(_, def, _) => {
+        ItemKind::Enum(_, _, def) => {
             let mut distance_from_explicit = 0;
             let variants = def
                 .variants
@@ -1117,7 +1121,7 @@ fn adt_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::AdtDef<'_> {
 
             (AdtKind::Enum, variants)
         }
-        ItemKind::Struct(ident, def, _) | ItemKind::Union(ident, def, _) => {
+        ItemKind::Struct(ident, _, def) | ItemKind::Union(ident, _, def) => {
             let adt_kind = match item.kind {
                 ItemKind::Struct(..) => AdtKind::Struct,
                 _ => AdtKind::Union,
diff --git a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs
index 279b1e82a71..5f1cdeddc19 100644
--- a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs
+++ b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs
@@ -151,7 +151,7 @@ fn remap_gat_vars_and_recurse_into_nested_projections<'tcx>(
     let mut mapping = FxIndexMap::default();
     let generics = tcx.generics_of(assoc_item_def_id);
     for (param, var) in std::iter::zip(&generics.own_params, gat_vars) {
-        let existing = match var.unpack() {
+        let existing = match var.kind() {
             ty::GenericArgKind::Lifetime(re) => {
                 if let ty::RegionKind::ReBound(ty::INNERMOST, bv) = re.kind() {
                     mapping.insert(bv.var, tcx.mk_param_from_def(param))
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 709446d09cd..d45f0475e99 100644
--- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
+++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
@@ -634,11 +634,11 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
                 // These sorts of items have no lifetime parameters at all.
                 intravisit::walk_item(self, item);
             }
-            hir::ItemKind::TyAlias(_, _, generics)
-            | hir::ItemKind::Const(_, _, generics, _)
-            | hir::ItemKind::Enum(_, _, generics)
-            | hir::ItemKind::Struct(_, _, generics)
-            | hir::ItemKind::Union(_, _, generics)
+            hir::ItemKind::TyAlias(_, generics, _)
+            | hir::ItemKind::Const(_, generics, _, _)
+            | hir::ItemKind::Enum(_, generics, _)
+            | hir::ItemKind::Struct(_, generics, _)
+            | hir::ItemKind::Union(_, generics, _)
             | hir::ItemKind::Trait(_, _, _, generics, ..)
             | hir::ItemKind::TraitAlias(_, generics, ..)
             | hir::ItemKind::Impl(&hir::Impl { generics, .. }) => {
diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs
index c20b14df770..141d96b57e5 100644
--- a/compiler/rustc_hir_analysis/src/collect/type_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs
@@ -206,7 +206,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_
         },
 
         Node::Item(item) => match item.kind {
-            ItemKind::Static(ident, ty, .., body_id) => {
+            ItemKind::Static(_, ident, ty, body_id) => {
                 if ty.is_suggestable_infer_ty() {
                     infer_placeholder_type(
                         icx.lowerer(),
@@ -220,7 +220,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_
                     icx.lower_ty(ty)
                 }
             }
-            ItemKind::Const(ident, ty, _, body_id) => {
+            ItemKind::Const(ident, _, ty, body_id) => {
                 if ty.is_suggestable_infer_ty() {
                     infer_placeholder_type(
                         icx.lowerer(),
@@ -234,7 +234,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_
                     icx.lower_ty(ty)
                 }
             }
-            ItemKind::TyAlias(_, self_ty, _) => icx.lower_ty(self_ty),
+            ItemKind::TyAlias(_, _, self_ty) => icx.lower_ty(self_ty),
             ItemKind::Impl(hir::Impl { self_ty, .. }) => match self_ty.find_self_aliases() {
                 spans if spans.len() > 0 => {
                     let guar = tcx
@@ -532,5 +532,5 @@ pub(crate) fn type_alias_is_lazy<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) ->
             }
         }
     }
-    HasTait.visit_ty_unambig(tcx.hir_expect_item(def_id).expect_ty_alias().1).is_break()
+    HasTait.visit_ty_unambig(tcx.hir_expect_item(def_id).expect_ty_alias().2).is_break()
 }
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs
index 9e44b645aca..c7cdf1d5bd2 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs
@@ -11,7 +11,7 @@ use rustc_middle::ty::{
 };
 use rustc_span::{ErrorGuaranteed, Span};
 use rustc_trait_selection::error_reporting::traits::report_dyn_incompatibility;
-use rustc_trait_selection::traits::{self, hir_ty_lowering_dyn_compatibility_violations};
+use rustc_trait_selection::traits;
 use smallvec::{SmallVec, smallvec};
 use tracing::{debug, instrument};
 
@@ -97,8 +97,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
         // to avoid ICEs.
         for (clause, span) in user_written_bounds {
             if let Some(trait_pred) = clause.as_trait_clause() {
-                let violations =
-                    hir_ty_lowering_dyn_compatibility_violations(tcx, trait_pred.def_id());
+                let violations = self.dyn_compatibility_violations(trait_pred.def_id());
                 if !violations.is_empty() {
                     let reported = report_dyn_incompatibility(
                         tcx,
@@ -216,7 +215,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
                         let pred = bound_predicate.rebind(pred);
                         // A `Self` within the original bound will be instantiated with a
                         // `trait_object_dummy_self`, so check for that.
-                        let references_self = match pred.skip_binder().term.unpack() {
+                        let references_self = match pred.skip_binder().term.kind() {
                             ty::TermKind::Ty(ty) => ty.walk().any(|arg| arg == dummy_self.into()),
                             // FIXME(associated_const_equality): We should walk the const instead of not doing anything
                             ty::TermKind::Const(_) => false,
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs
index 1f4692b19f1..9abae33ffdb 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs
@@ -141,7 +141,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
 
         let generics = match tcx.hir_node_by_def_id(parent_item) {
             hir::Node::Item(hir::Item {
-                kind: hir::ItemKind::Struct(_, variant, generics),
+                kind: hir::ItemKind::Struct(_, generics, variant),
                 ..
             }) => {
                 if !variant.fields().iter().any(|field| field.hir_id == parent_hir_id) {
@@ -149,7 +149,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
                 }
                 generics
             }
-            hir::Node::Item(hir::Item { kind: hir::ItemKind::Enum(_, def, generics), .. }) => {
+            hir::Node::Item(hir::Item { kind: hir::ItemKind::Enum(_, generics, def), .. }) => {
                 if !def
                     .variants
                     .iter()
@@ -269,7 +269,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
             hir::Node::Field(field) => {
                 // Enums can't have unsized fields, fields can only have an unsized tail field.
                 if let hir::Node::Item(hir::Item {
-                    kind: hir::ItemKind::Struct(_, variant, _), ..
+                    kind: hir::ItemKind::Struct(_, _, variant), ..
                 }) = tcx.parent_hir_node(field.hir_id)
                     && variant
                         .fields()
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 6b21bbbfcd8..2a37a8bdbd4 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
@@ -33,7 +33,7 @@ use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res};
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_hir::{self as hir, AnonConst, GenericArg, GenericArgs, HirId};
 use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
-use rustc_infer::traits::ObligationCause;
+use rustc_infer::traits::{DynCompatibilityViolation, ObligationCause};
 use rustc_middle::middle::stability::AllowUnstable;
 use rustc_middle::mir::interpret::LitToConstInput;
 use rustc_middle::ty::print::PrintPolyTraitRefExt as _;
@@ -200,6 +200,10 @@ pub trait HirTyLowerer<'tcx> {
     {
         self
     }
+
+    /// Performs minimalistic dyn compat checks outside of bodies, but full within bodies.
+    /// Outside of bodies we could end up in cycles, so we delay most checks to later phases.
+    fn dyn_compatibility_violations(&self, trait_def_id: DefId) -> Vec<DynCompatibilityViolation>;
 }
 
 /// The "qualified self" of an associated item path.
@@ -607,7 +611,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
                         if !infer_args && has_default {
                             // No type parameter provided, but a default exists.
                             if let Some(prev) =
-                                preceding_args.iter().find_map(|arg| match arg.unpack() {
+                                preceding_args.iter().find_map(|arg| match arg.kind() {
                                     GenericArgKind::Type(ty) => ty.error_reported().err(),
                                     _ => None,
                                 })
diff --git a/compiler/rustc_hir_analysis/src/hir_wf_check.rs b/compiler/rustc_hir_analysis/src/hir_wf_check.rs
index 64c1a78bd1c..4633f3951a7 100644
--- a/compiler/rustc_hir_analysis/src/hir_wf_check.rs
+++ b/compiler/rustc_hir_analysis/src/hir_wf_check.rs
@@ -145,9 +145,9 @@ fn diagnostic_hir_wf_check<'tcx>(
                 ref item => bug!("Unexpected TraitItem {:?}", item),
             },
             hir::Node::Item(item) => match item.kind {
-                hir::ItemKind::TyAlias(_, ty, _)
-                | hir::ItemKind::Static(_, ty, _, _)
-                | hir::ItemKind::Const(_, ty, _, _) => vec![ty],
+                hir::ItemKind::TyAlias(_, _, ty)
+                | hir::ItemKind::Static(_, _, ty, _)
+                | hir::ItemKind::Const(_, _, ty, _) => vec![ty],
                 hir::ItemKind::Impl(impl_) => match &impl_.of_trait {
                     Some(t) => t
                         .path
diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs
index 010c6c376fe..a64c24f5455 100644
--- a/compiler/rustc_hir_analysis/src/lib.rs
+++ b/compiler/rustc_hir_analysis/src/lib.rs
@@ -203,7 +203,9 @@ pub fn check_crate(tcx: TyCtxt<'_>) {
                 tcx.ensure_ok().eval_static_initializer(item_def_id);
                 check::maybe_check_static_with_link_section(tcx, item_def_id);
             }
-            DefKind::Const if tcx.generics_of(item_def_id).is_empty() => {
+            DefKind::Const if !tcx.generics_of(item_def_id).own_requires_monomorphization() => {
+                // FIXME(generic_const_items): Passing empty instead of identity args is fishy but
+                //                             seems to be fine for now. Revisit this!
                 let instance = ty::Instance::new_raw(item_def_id.into(), ty::GenericArgs::empty());
                 let cid = GlobalId { instance, promoted: None };
                 let typing_env = ty::TypingEnv::fully_monomorphized();
diff --git a/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs b/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs
index c99eb12efcc..4f35b87be30 100644
--- a/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs
+++ b/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs
@@ -119,7 +119,7 @@ fn insert_required_predicates_to_be_wf<'tcx>(
     explicit_map: &mut ExplicitPredicatesMap<'tcx>,
 ) {
     for arg in ty.walk() {
-        let leaf_ty = match arg.unpack() {
+        let leaf_ty = match arg.kind() {
             GenericArgKind::Type(ty) => ty,
 
             // No predicates from lifetimes or constants, except potentially
@@ -299,7 +299,7 @@ fn check_explicit_predicates<'tcx>(
         // binding) and thus infer an outlives requirement that `X:
         // 'b`.
         if let Some(self_ty) = ignored_self_ty
-            && let GenericArgKind::Type(ty) = outlives_predicate.0.unpack()
+            && let GenericArgKind::Type(ty) = outlives_predicate.0.kind()
             && ty.walk().any(|arg| arg == self_ty.into())
         {
             debug!("skipping self ty = {ty:?}");
diff --git a/compiler/rustc_hir_analysis/src/outlives/mod.rs b/compiler/rustc_hir_analysis/src/outlives/mod.rs
index daa908c8c78..499f5572f47 100644
--- a/compiler/rustc_hir_analysis/src/outlives/mod.rs
+++ b/compiler/rustc_hir_analysis/src/outlives/mod.rs
@@ -69,8 +69,8 @@ fn inferred_outlives_crate(tcx: TyCtxt<'_>, (): ()) -> CratePredicatesMap<'_> {
         .map(|(&def_id, set)| {
             let predicates =
                 &*tcx.arena.alloc_from_iter(set.as_ref().skip_binder().iter().filter_map(
-                    |(ty::OutlivesPredicate(kind1, region2), &span)| {
-                        match kind1.unpack() {
+                    |(ty::OutlivesPredicate(arg1, region2), &span)| {
+                        match arg1.kind() {
                             GenericArgKind::Type(ty1) => Some((
                                 ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(ty1, *region2))
                                     .upcast(tcx),
diff --git a/compiler/rustc_hir_analysis/src/outlives/utils.rs b/compiler/rustc_hir_analysis/src/outlives/utils.rs
index 044fb64ca82..301f5de9424 100644
--- a/compiler/rustc_hir_analysis/src/outlives/utils.rs
+++ b/compiler/rustc_hir_analysis/src/outlives/utils.rs
@@ -14,7 +14,7 @@ pub(crate) type RequiredPredicates<'tcx> =
 /// outlives_component and add it to `required_predicates`
 pub(crate) fn insert_outlives_predicate<'tcx>(
     tcx: TyCtxt<'tcx>,
-    kind: GenericArg<'tcx>,
+    arg: GenericArg<'tcx>,
     outlived_region: Region<'tcx>,
     span: Span,
     required_predicates: &mut RequiredPredicates<'tcx>,
@@ -25,7 +25,7 @@ pub(crate) fn insert_outlives_predicate<'tcx>(
         return;
     }
 
-    match kind.unpack() {
+    match arg.kind() {
         GenericArgKind::Type(ty) => {
             // `T: 'outlived_region` for some type `T`
             // But T could be a lot of things:
@@ -135,7 +135,7 @@ pub(crate) fn insert_outlives_predicate<'tcx>(
             if !is_free_region(r) {
                 return;
             }
-            required_predicates.entry(ty::OutlivesPredicate(kind, outlived_region)).or_insert(span);
+            required_predicates.entry(ty::OutlivesPredicate(arg, outlived_region)).or_insert(span);
         }
 
         GenericArgKind::Const(_) => {
diff --git a/compiler/rustc_hir_analysis/src/variance/constraints.rs b/compiler/rustc_hir_analysis/src/variance/constraints.rs
index 92cfece77c4..960ec7f66ab 100644
--- a/compiler/rustc_hir_analysis/src/variance/constraints.rs
+++ b/compiler/rustc_hir_analysis/src/variance/constraints.rs
@@ -200,8 +200,8 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
         // Trait are always invariant so we can take advantage of that.
         let variance_i = self.invariant(variance);
 
-        for k in args {
-            match k.unpack() {
+        for arg in args {
+            match arg.kind() {
                 GenericArgKind::Lifetime(lt) => {
                     self.add_constraints_from_region(current, lt, variance_i)
                 }
@@ -294,7 +294,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
                 }
 
                 for projection in data.projection_bounds() {
-                    match projection.skip_binder().term.unpack() {
+                    match projection.skip_binder().term.kind() {
                         ty::TermKind::Ty(ty) => {
                             self.add_constraints_from_ty(current, ty, self.invariant);
                         }
@@ -373,7 +373,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
             (None, Some(self.tcx().variances_of(def_id)))
         };
 
-        for (i, k) in args.iter().enumerate() {
+        for (i, arg) in args.iter().enumerate() {
             let variance_decl = if let Some(InferredIndex(start)) = local {
                 // Parameter on an item defined within current crate:
                 // variance not yet inferred, so return a symbolic
@@ -389,7 +389,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
                 "add_constraints_from_args: variance_decl={:?} variance_i={:?}",
                 variance_decl, variance_i
             );
-            match k.unpack() {
+            match arg.kind() {
                 GenericArgKind::Lifetime(lt) => {
                     self.add_constraints_from_region(current, lt, variance_i)
                 }
diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs
index 04f9c831b0a..b23b3125c59 100644
--- a/compiler/rustc_hir_pretty/src/lib.rs
+++ b/compiler/rustc_hir_pretty/src/lib.rs
@@ -477,10 +477,10 @@ impl<'a> State<'a> {
             hir::ForeignItemKind::Fn(sig, arg_idents, generics) => {
                 let (cb, ib) = self.head("");
                 self.print_fn(
-                    sig.decl,
                     sig.header,
                     Some(item.ident.name),
                     generics,
+                    sig.decl,
                     arg_idents,
                     None,
                 );
@@ -593,7 +593,7 @@ impl<'a> State<'a> {
                 self.end(ib);
                 self.end(cb);
             }
-            hir::ItemKind::Static(ident, ty, m, expr) => {
+            hir::ItemKind::Static(m, ident, ty, expr) => {
                 let (cb, ib) = self.head("static");
                 if m.is_mut() {
                     self.word_space("mut");
@@ -609,7 +609,7 @@ impl<'a> State<'a> {
                 self.word(";");
                 self.end(cb);
             }
-            hir::ItemKind::Const(ident, ty, generics, expr) => {
+            hir::ItemKind::Const(ident, generics, ty, expr) => {
                 let (cb, ib) = self.head("const");
                 self.print_ident(ident);
                 self.print_generic_params(generics.params);
@@ -626,7 +626,7 @@ impl<'a> State<'a> {
             }
             hir::ItemKind::Fn { ident, sig, generics, body, .. } => {
                 let (cb, ib) = self.head("");
-                self.print_fn(sig.decl, sig.header, Some(ident.name), generics, &[], Some(body));
+                self.print_fn(sig.header, Some(ident.name), generics, sig.decl, &[], Some(body));
                 self.word(" ");
                 self.end(ib);
                 self.end(cb);
@@ -660,7 +660,7 @@ impl<'a> State<'a> {
                 self.end(cb);
                 self.end(ib);
             }
-            hir::ItemKind::TyAlias(ident, ty, generics) => {
+            hir::ItemKind::TyAlias(ident, generics, ty) => {
                 let (cb, ib) = self.head("type");
                 self.print_ident(ident);
                 self.print_generic_params(generics.params);
@@ -673,16 +673,16 @@ impl<'a> State<'a> {
                 self.word(";");
                 self.end(cb);
             }
-            hir::ItemKind::Enum(ident, ref enum_definition, params) => {
-                self.print_enum_def(enum_definition, params, ident.name, item.span);
+            hir::ItemKind::Enum(ident, generics, ref enum_def) => {
+                self.print_enum_def(ident.name, generics, enum_def, item.span);
             }
-            hir::ItemKind::Struct(ident, ref struct_def, generics) => {
+            hir::ItemKind::Struct(ident, generics, ref struct_def) => {
                 let (cb, ib) = self.head("struct");
-                self.print_struct(struct_def, generics, ident.name, item.span, true, cb, ib);
+                self.print_struct(ident.name, generics, struct_def, item.span, true, cb, ib);
             }
-            hir::ItemKind::Union(ident, ref struct_def, generics) => {
+            hir::ItemKind::Union(ident, generics, ref struct_def) => {
                 let (cb, ib) = self.head("union");
-                self.print_struct(struct_def, generics, ident.name, item.span, true, cb, ib);
+                self.print_struct(ident.name, generics, struct_def, item.span, true, cb, ib);
             }
             hir::ItemKind::Impl(&hir::Impl {
                 constness,
@@ -791,9 +791,9 @@ impl<'a> State<'a> {
 
     fn print_enum_def(
         &mut self,
-        enum_definition: &hir::EnumDef<'_>,
-        generics: &hir::Generics<'_>,
         name: Symbol,
+        generics: &hir::Generics<'_>,
+        enum_def: &hir::EnumDef<'_>,
         span: rustc_span::Span,
     ) {
         let (cb, ib) = self.head("enum");
@@ -801,7 +801,7 @@ impl<'a> State<'a> {
         self.print_generic_params(generics.params);
         self.print_where_clause(generics);
         self.space();
-        self.print_variants(enum_definition.variants, span, cb, ib);
+        self.print_variants(enum_def.variants, span, cb, ib);
     }
 
     fn print_variants(
@@ -834,9 +834,9 @@ impl<'a> State<'a> {
 
     fn print_struct(
         &mut self,
-        struct_def: &hir::VariantData<'_>,
-        generics: &hir::Generics<'_>,
         name: Symbol,
+        generics: &hir::Generics<'_>,
+        struct_def: &hir::VariantData<'_>,
         span: rustc_span::Span,
         print_finalizer: bool,
         cb: BoxMarker,
@@ -886,7 +886,7 @@ impl<'a> State<'a> {
     pub fn print_variant(&mut self, v: &hir::Variant<'_>) {
         let (cb, ib) = self.head("");
         let generics = hir::Generics::empty();
-        self.print_struct(&v.data, generics, v.ident.name, v.span, false, cb, ib);
+        self.print_struct(v.ident.name, generics, &v.data, v.span, false, cb, ib);
         if let Some(ref d) = v.disr_expr {
             self.space();
             self.word_space("=");
@@ -902,7 +902,7 @@ impl<'a> State<'a> {
         arg_idents: &[Option<Ident>],
         body_id: Option<hir::BodyId>,
     ) {
-        self.print_fn(m.decl, m.header, Some(ident.name), generics, arg_idents, body_id);
+        self.print_fn(m.header, Some(ident.name), generics, m.decl, arg_idents, body_id);
     }
 
     fn print_trait_item(&mut self, ti: &hir::TraitItem<'_>) {
@@ -2141,10 +2141,10 @@ impl<'a> State<'a> {
 
     fn print_fn(
         &mut self,
-        decl: &hir::FnDecl<'_>,
         header: hir::FnHeader,
         name: Option<Symbol>,
         generics: &hir::Generics<'_>,
+        decl: &hir::FnDecl<'_>,
         arg_idents: &[Option<Ident>],
         body_id: Option<hir::BodyId>,
     ) {
@@ -2483,7 +2483,6 @@ impl<'a> State<'a> {
         self.print_formal_generic_params(generic_params);
         let generics = hir::Generics::empty();
         self.print_fn(
-            decl,
             hir::FnHeader {
                 safety: safety.into(),
                 abi,
@@ -2492,6 +2491,7 @@ impl<'a> State<'a> {
             },
             name,
             generics,
+            decl,
             arg_idents,
             None,
         );
diff --git a/compiler/rustc_hir_typeck/src/cast.rs b/compiler/rustc_hir_typeck/src/cast.rs
index c044c4f7c37..e144a6ab599 100644
--- a/compiler/rustc_hir_typeck/src/cast.rs
+++ b/compiler/rustc_hir_typeck/src/cast.rs
@@ -408,6 +408,16 @@ impl<'a, 'tcx> CastCheck<'tcx> {
                     self.expr_ty,
                     fcx.ty_to_string(self.cast_ty)
                 );
+
+                if let Ok(snippet) = fcx.tcx.sess.source_map().span_to_snippet(self.expr_span)
+                    && matches!(self.expr.kind, ExprKind::AddrOf(..))
+                {
+                    err.note(format!(
+                        "casting reference expression `{}` because `&` binds tighter than `as`",
+                        snippet
+                    ));
+                }
+
                 let mut sugg = None;
                 let mut sugg_mutref = false;
                 if let ty::Ref(reg, cast_ty, mutbl) = *self.cast_ty.kind() {
diff --git a/compiler/rustc_hir_typeck/src/closure.rs b/compiler/rustc_hir_typeck/src/closure.rs
index b1cb3ef4d79..cd3746be1d1 100644
--- a/compiler/rustc_hir_typeck/src/closure.rs
+++ b/compiler/rustc_hir_typeck/src/closure.rs
@@ -204,14 +204,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 )
             }
             hir::ClosureKind::CoroutineClosure(kind) => {
-                // async closures always return the type ascribed after the `->` (if present),
-                // and yield `()`.
                 let (bound_return_ty, bound_yield_ty) = match kind {
+                    hir::CoroutineDesugaring::Gen => {
+                        // `iter!` closures always return unit and yield the `Iterator::Item` type
+                        // that we have to infer.
+                        (tcx.types.unit, self.infcx.next_ty_var(expr_span))
+                    }
                     hir::CoroutineDesugaring::Async => {
+                        // async closures always return the type ascribed after the `->` (if present),
+                        // and yield `()`.
                         (bound_sig.skip_binder().output(), tcx.types.unit)
                     }
-                    hir::CoroutineDesugaring::Gen | hir::CoroutineDesugaring::AsyncGen => {
-                        todo!("`gen` and `async gen` closures not supported yet")
+                    hir::CoroutineDesugaring::AsyncGen => {
+                        todo!("`async gen` closures not supported yet")
                     }
                 };
                 // Compute all of the variables that will be used to populate the coroutine.
@@ -465,7 +470,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
             if let Some(trait_def_id) = trait_def_id {
                 let found_kind = match closure_kind {
-                    hir::ClosureKind::Closure => self.tcx.fn_trait_kind_from_def_id(trait_def_id),
+                    hir::ClosureKind::Closure
+                    // FIXME(iter_macro): Someday we'll probably want iterator closures instead of
+                    // just using Fn* for iterators.
+                    | hir::ClosureKind::CoroutineClosure(hir::CoroutineDesugaring::Gen) => {
+                        self.tcx.fn_trait_kind_from_def_id(trait_def_id)
+                    }
                     hir::ClosureKind::CoroutineClosure(hir::CoroutineDesugaring::Async) => self
                         .tcx
                         .async_fn_trait_kind_from_def_id(trait_def_id)
diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs
index 4f77594deca..ddc80fab2ce 100644
--- a/compiler/rustc_hir_typeck/src/coercion.rs
+++ b/compiler/rustc_hir_typeck/src/coercion.rs
@@ -47,7 +47,7 @@ use rustc_infer::infer::relate::RelateResult;
 use rustc_infer::infer::{Coercion, DefineOpaqueTypes, InferOk, InferResult};
 use rustc_infer::traits::{
     IfExpressionCause, MatchExpressionArmCause, Obligation, PredicateObligation,
-    PredicateObligations,
+    PredicateObligations, SelectionError,
 };
 use rustc_middle::span_bug;
 use rustc_middle::ty::adjustment::{
@@ -677,7 +677,21 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
                     return Err(TypeError::Mismatch);
                 }
 
-                // Dyn-compatibility violations or miscellaneous.
+                Err(SelectionError::TraitDynIncompatible(_)) => {
+                    // Dyn compatibility errors in coercion will *always* be due to the
+                    // fact that the RHS of the coercion is a non-dyn compatible `dyn Trait`
+                    // writen in source somewhere (otherwise we will never have lowered
+                    // the dyn trait from HIR to middle).
+                    //
+                    // There's no reason to emit yet another dyn compatibility error,
+                    // especially since the span will differ slightly and thus not be
+                    // deduplicated at all!
+                    self.fcx.set_tainted_by_errors(
+                        self.fcx
+                            .dcx()
+                            .span_delayed_bug(self.cause.span, "dyn compatibility during coercion"),
+                    );
+                }
                 Err(err) => {
                     let guar = self.err_ctxt().report_selection_error(
                         obligation.clone(),
diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs
index 8182851a015..152c88ad92a 100644
--- a/compiler/rustc_hir_typeck/src/demand.rs
+++ b/compiler/rustc_hir_typeck/src/demand.rs
@@ -722,8 +722,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     )) => {
                         if let Some(hir::Node::Item(hir::Item {
                             kind:
-                                hir::ItemKind::Static(ident, ty, ..)
-                                | hir::ItemKind::Const(ident, ty, ..),
+                                hir::ItemKind::Static(_, ident, ty, _)
+                                | hir::ItemKind::Const(ident, _, ty, _),
                             ..
                         })) = self.tcx.hir_get_if_local(*def_id)
                         {
diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs
index 1d86f7d223c..082ddac7e5a 100644
--- a/compiler/rustc_hir_typeck/src/expr.rs
+++ b/compiler/rustc_hir_typeck/src/expr.rs
@@ -1793,10 +1793,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         let element_ty = if !args.is_empty() {
             let coerce_to = expected
                 .to_option(self)
-                .and_then(|uty| match *self.try_structurally_resolve_type(expr.span, uty).kind() {
-                    ty::Array(ty, _) | ty::Slice(ty) => Some(ty),
-                    _ => None,
-                })
+                .and_then(|uty| self.try_structurally_resolve_type(expr.span, uty).builtin_index())
                 .unwrap_or_else(|| self.next_ty_var(expr.span));
             let mut coerce = CoerceMany::with_coercion_sites(coerce_to, args);
             assert_eq!(self.diverges.get(), Diverges::Maybe);
@@ -1874,10 +1871,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         }
 
         let uty = match expected {
-            ExpectHasType(uty) => match *uty.kind() {
-                ty::Array(ty, _) | ty::Slice(ty) => Some(ty),
-                _ => None,
-            },
+            ExpectHasType(uty) => uty.builtin_index(),
             _ => None,
         };
 
diff --git a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs
index 3493d359028..20341318828 100644
--- a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs
+++ b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs
@@ -13,6 +13,7 @@ use hir::Expr;
 use hir::def::DefKind;
 use hir::pat_util::EnumerateAndAdjustIterator as _;
 use rustc_abi::{FIRST_VARIANT, FieldIdx, VariantIdx};
+use rustc_ast::UnsafeBinderCastKind;
 use rustc_data_structures::fx::FxIndexMap;
 use rustc_hir::def::{CtorOf, Res};
 use rustc_hir::def_id::LocalDefId;
@@ -1393,10 +1394,18 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
                 self.cat_res(expr.hir_id, expr.span, expr_ty, res)
             }
 
-            // both type ascription and unsafe binder casts don't affect
-            // the place-ness of the subexpression.
+            // type ascription doesn't affect the place-ness of the subexpression.
             hir::ExprKind::Type(e, _) => self.cat_expr(e),
-            hir::ExprKind::UnsafeBinderCast(_, e, _) => self.cat_expr(e),
+
+            hir::ExprKind::UnsafeBinderCast(UnsafeBinderCastKind::Unwrap, e, _) => {
+                let base = self.cat_expr(e)?;
+                Ok(self.cat_projection(
+                    expr.hir_id,
+                    base,
+                    expr_ty,
+                    ProjectionKind::UnwrapUnsafeBinder,
+                ))
+            }
 
             hir::ExprKind::AddrOf(..)
             | hir::ExprKind::Call(..)
@@ -1427,6 +1436,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
             | hir::ExprKind::Repeat(..)
             | hir::ExprKind::InlineAsm(..)
             | hir::ExprKind::OffsetOf(..)
+            | hir::ExprKind::UnsafeBinderCast(UnsafeBinderCastKind::Wrap, ..)
             | hir::ExprKind::Err(_) => Ok(self.cat_rvalue(expr.hir_id, expr_ty)),
         }
     }
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs
index ee0436f73e1..2bc007b3ad4 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs
@@ -80,12 +80,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         let find_param_matching = |matches: &dyn Fn(ty::ParamTerm) -> bool| {
             predicate_args.iter().find_map(|arg| {
                 arg.walk().find_map(|arg| {
-                    if let ty::GenericArgKind::Type(ty) = arg.unpack()
+                    if let ty::GenericArgKind::Type(ty) = arg.kind()
                         && let ty::Param(param_ty) = *ty.kind()
                         && matches(ty::ParamTerm::Ty(param_ty))
                     {
                         Some(arg)
-                    } else if let ty::GenericArgKind::Const(ct) = arg.unpack()
+                    } else if let ty::GenericArgKind::Const(ct) = arg.kind()
                         && let ty::ConstKind::Param(param_ct) = ct.kind()
                         && matches(ty::ParamTerm::Const(param_ct))
                     {
@@ -357,7 +357,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         &self,
         error: &mut traits::FulfillmentError<'tcx>,
         def_id: DefId,
-        param: ty::GenericArg<'tcx>,
+        arg: ty::GenericArg<'tcx>,
         qpath: &hir::QPath<'tcx>,
     ) -> bool {
         match qpath {
@@ -365,7 +365,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 for segment in path.segments.iter().rev() {
                     if let Res::Def(kind, def_id) = segment.res
                         && !matches!(kind, DefKind::Mod | DefKind::ForeignMod)
-                        && self.point_at_generic_if_possible(error, def_id, param, segment)
+                        && self.point_at_generic_if_possible(error, def_id, arg, segment)
                     {
                         return true;
                     }
@@ -373,7 +373,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 // Handle `Self` param specifically, since it's separated in
                 // the path representation
                 if let Some(self_ty) = self_ty
-                    && let ty::GenericArgKind::Type(ty) = param.unpack()
+                    && let ty::GenericArgKind::Type(ty) = arg.kind()
                     && ty == self.tcx.types.self_param
                 {
                     error.obligation.cause.span = self_ty
@@ -384,12 +384,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 }
             }
             hir::QPath::TypeRelative(self_ty, segment) => {
-                if self.point_at_generic_if_possible(error, def_id, param, segment) {
+                if self.point_at_generic_if_possible(error, def_id, arg, segment) {
                     return true;
                 }
                 // Handle `Self` param specifically, since it's separated in
                 // the path representation
-                if let ty::GenericArgKind::Type(ty) = param.unpack()
+                if let ty::GenericArgKind::Type(ty) = arg.kind()
                     && ty == self.tcx.types.self_param
                 {
                     error.obligation.cause.span = self_ty
@@ -424,10 +424,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         // the args list does not, then we should chop off all of the lifetimes,
         // since they're all elided.
         let segment_args = segment.args().args;
-        if matches!(own_args[0].unpack(), ty::GenericArgKind::Lifetime(_))
+        if matches!(own_args[0].kind(), ty::GenericArgKind::Lifetime(_))
             && segment_args.first().is_some_and(|arg| arg.is_ty_or_const())
             && let Some(offset) = own_args.iter().position(|arg| {
-                matches!(arg.unpack(), ty::GenericArgKind::Type(_) | ty::GenericArgKind::Const(_))
+                matches!(arg.kind(), ty::GenericArgKind::Type(_) | ty::GenericArgKind::Const(_))
             })
             && let Some(new_index) = index.checked_sub(offset)
         {
@@ -750,7 +750,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             return Ok(expr);
         }
 
-        let ty::GenericArgKind::Type(in_ty) = in_ty.unpack() else {
+        let ty::GenericArgKind::Type(in_ty) = in_ty.kind() else {
             return Err(expr);
         };
 
@@ -1045,7 +1045,7 @@ fn find_param_in_ty<'tcx>(
         if arg == param_to_point_at {
             return true;
         }
-        if let ty::GenericArgKind::Type(ty) = arg.unpack()
+        if let ty::GenericArgKind::Type(ty) = arg.kind()
             && let ty::Alias(ty::Projection | ty::Inherent, ..) = ty.kind()
         {
             // This logic may seem a bit strange, but typically when
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
index 786d7639a05..59aba6fae5e 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
@@ -1556,25 +1556,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             SuggestionText::Reorder => Some("reorder these arguments".to_string()),
             SuggestionText::DidYouMean => Some("did you mean".to_string()),
         };
-        if let Some(suggestion_text) = suggestion_text {
+        if let Some(suggestion_text) = suggestion_text
+            && !full_call_span.in_external_macro(self.sess().source_map())
+        {
             let source_map = self.sess().source_map();
-            let (mut suggestion, suggestion_span) = if let Some(call_span) =
-                full_call_span.find_ancestor_inside_same_ctxt(error_span)
-            {
-                ("(".to_string(), call_span.shrink_to_hi().to(error_span.shrink_to_hi()))
+            let suggestion_span = if let Some(args_span) = error_span.trim_start(full_call_span) {
+                // Span of the braces, e.g. `(a, b, c)`.
+                args_span
             } else {
-                (
-                    format!(
-                        "{}(",
-                        source_map.span_to_snippet(full_call_span).unwrap_or_else(|_| {
-                            fn_def_id.map_or("".to_string(), |fn_def_id| {
-                                tcx.item_name(fn_def_id).to_string()
-                            })
-                        })
-                    ),
-                    error_span,
-                )
+                // The arg span of a function call that wasn't even given braces
+                // like what might happen with delegation reuse.
+                // e.g. `reuse HasSelf::method;` should suggest `reuse HasSelf::method($args);`.
+                full_call_span.shrink_to_hi()
             };
+            let mut suggestion = "(".to_owned();
             let mut needs_comma = false;
             for (expected_idx, provided_idx) in matched_inputs.iter_enumerated() {
                 if needs_comma {
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs
index ea0adf16b1a..a5c0829b8d9 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs
@@ -14,7 +14,7 @@ use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_hir::{self as hir, HirId, ItemLocalMap};
 use rustc_hir_analysis::hir_ty_lowering::{HirTyLowerer, RegionInferReason};
 use rustc_infer::infer;
-use rustc_infer::traits::Obligation;
+use rustc_infer::traits::{DynCompatibilityViolation, Obligation};
 use rustc_middle::ty::{self, Const, Ty, TyCtxt, TypeVisitableExt};
 use rustc_session::Session;
 use rustc_span::{self, DUMMY_SP, ErrorGuaranteed, Ident, Span, sym};
@@ -81,7 +81,7 @@ pub(crate) struct FnCtxt<'a, 'tcx> {
     /// you get indicates whether any subexpression that was
     /// evaluating up to and including `X` diverged.
     ///
-    /// We currently use this flag only for diagnostic purposes:
+    /// We currently use this flag for the following purposes:
     ///
     /// - To warn about unreachable code: if, after processing a
     ///   sub-expression but before we have applied the effects of the
@@ -94,6 +94,8 @@ pub(crate) struct FnCtxt<'a, 'tcx> {
     ///   warning. This corresponds to something like `{return;
     ///   foo();}` or `{return; 22}`, where we would warn on the
     ///   `foo()` or `22`.
+    /// - To assign the `!` type to block expressions with diverging
+    ///   statements.
     ///
     /// An expression represents dead code if, after checking it,
     /// the diverges flag is set to something other than `Maybe`.
@@ -388,6 +390,10 @@ impl<'tcx> HirTyLowerer<'tcx> for FnCtxt<'_, 'tcx> {
         };
         (input_tys, output_ty)
     }
+
+    fn dyn_compatibility_violations(&self, trait_def_id: DefId) -> Vec<DynCompatibilityViolation> {
+        self.tcx.dyn_compatibility_violations(trait_def_id).to_vec()
+    }
 }
 
 /// The `ty` representation of a user-provided type. Depending on the use-site
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
index 43b662ca453..1c3bc338d85 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
@@ -2713,6 +2713,31 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         ));
                     }
 
+                    // Don't try to suggest ref/deref on an `if` expression, because:
+                    // - The `if` could be part of a desugared `if else` statement,
+                    //   which would create impossible suggestions such as `if ... { ... } else &if { ... } else { ... }`.
+                    // - In general the suggestions it creates such as `&if ... { ... } else { ... }` are not very helpful.
+                    // We try to generate a suggestion such as `if ... { &... } else { &... }` instead.
+                    if let hir::ExprKind::If(_c, then, els) = expr.kind {
+                        // The `then` of a `Expr::If` always contains a block, and that block may have a final expression that we can borrow
+                        // If the block does not have a final expression, it will return () and we do not make a suggestion to borrow that.
+                        let ExprKind::Block(then, _) = then.kind else { return None };
+                        let Some(then) = then.expr else { return None };
+                        let (mut suggs, help, app, verbose, mutref) =
+                            self.suggest_deref_or_ref(then, checked_ty, expected)?;
+
+                        // If there is no `else`, the return type of this `if` will be (), so suggesting to change the `then` block is useless
+                        let els_expr = match els?.kind {
+                            ExprKind::Block(block, _) => block.expr?,
+                            _ => els?,
+                        };
+                        let (else_suggs, ..) =
+                            self.suggest_deref_or_ref(els_expr, checked_ty, expected)?;
+                        suggs.extend(else_suggs);
+
+                        return Some((suggs, help, app, verbose, mutref));
+                    }
+
                     if let Some((sugg, msg)) = self.can_use_as_ref(expr) {
                         return Some((
                             sugg,
diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs
index 7b71f5de756..3eae95d5b73 100644
--- a/compiler/rustc_hir_typeck/src/method/suggest.rs
+++ b/compiler/rustc_hir_typeck/src/method/suggest.rs
@@ -2226,7 +2226,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 let infer_args = self.tcx.mk_args_from_iter(args.into_iter().map(|arg| {
                     if !arg.is_suggestable(self.tcx, true) {
                         has_unsuggestable_args = true;
-                        match arg.unpack() {
+                        match arg.kind() {
                             GenericArgKind::Lifetime(_) => self
                                 .next_region_var(RegionVariableOrigin::MiscVariable(DUMMY_SP))
                                 .into(),
@@ -2843,7 +2843,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 let [first] = ***args else {
                     return;
                 };
-                let ty::GenericArgKind::Type(ty) = first.unpack() else {
+                let ty::GenericArgKind::Type(ty) = first.kind() else {
                     return;
                 };
                 let Ok(pick) = self.lookup_probe_for_diagnostic(
diff --git a/compiler/rustc_hir_typeck/src/upvar.rs b/compiler/rustc_hir_typeck/src/upvar.rs
index 8ab71e5220b..4b2e87f5674 100644
--- a/compiler/rustc_hir_typeck/src/upvar.rs
+++ b/compiler/rustc_hir_typeck/src/upvar.rs
@@ -902,7 +902,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 fn is_field<'a>(p: &&Projection<'a>) -> bool {
                     match p.kind {
                         ProjectionKind::Field(_, _) => true,
-                        ProjectionKind::Deref | ProjectionKind::OpaqueCast => false,
+                        ProjectionKind::Deref
+                        | ProjectionKind::OpaqueCast
+                        | ProjectionKind::UnwrapUnsafeBinder => false,
                         p @ (ProjectionKind::Subslice | ProjectionKind::Index) => {
                             bug!("ProjectionKind {:?} was unexpected", p)
                         }
@@ -2197,7 +2199,8 @@ fn restrict_capture_precision(
             }
             ProjectionKind::Deref => {}
             ProjectionKind::OpaqueCast => {}
-            ProjectionKind::Field(..) => {} // ignore
+            ProjectionKind::Field(..) => {}
+            ProjectionKind::UnwrapUnsafeBinder => {}
         }
     }
 
@@ -2268,6 +2271,7 @@ fn construct_place_string<'tcx>(tcx: TyCtxt<'_>, place: &Place<'tcx>) -> String
             ProjectionKind::Index => String::from("Index"),
             ProjectionKind::Subslice => String::from("Subslice"),
             ProjectionKind::OpaqueCast => String::from("OpaqueCast"),
+            ProjectionKind::UnwrapUnsafeBinder => String::from("UnwrapUnsafeBinder"),
         };
         if i != 0 {
             projections_str.push(',');
diff --git a/compiler/rustc_infer/src/infer/at.rs b/compiler/rustc_infer/src/infer/at.rs
index 2cd67cc4da2..5fe795bd23a 100644
--- a/compiler/rustc_infer/src/infer/at.rs
+++ b/compiler/rustc_infer/src/infer/at.rs
@@ -347,7 +347,7 @@ impl<'tcx> ToTrace<'tcx> for ty::GenericArg<'tcx> {
     fn to_trace(cause: &ObligationCause<'tcx>, a: Self, b: Self) -> TypeTrace<'tcx> {
         TypeTrace {
             cause: cause.clone(),
-            values: match (a.unpack(), b.unpack()) {
+            values: match (a.kind(), b.kind()) {
                 (GenericArgKind::Lifetime(a), GenericArgKind::Lifetime(b)) => {
                     ValuePairs::Regions(ExpectedFound::new(a, b))
                 }
diff --git a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs
index 26ecaebe97f..060447ba720 100644
--- a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs
+++ b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs
@@ -493,6 +493,14 @@ impl<'cx, 'tcx> TypeFolder<TyCtxt<'tcx>> for Canonicalizer<'cx, 'tcx> {
             ct
         }
     }
+
+    fn fold_predicate(&mut self, p: ty::Predicate<'tcx>) -> ty::Predicate<'tcx> {
+        if p.flags().intersects(self.needs_canonical_flags) { p.super_fold_with(self) } else { p }
+    }
+
+    fn fold_clauses(&mut self, c: ty::Clauses<'tcx>) -> ty::Clauses<'tcx> {
+        if c.flags().intersects(self.needs_canonical_flags) { c.super_fold_with(self) } else { c }
+    }
 }
 
 impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> {
diff --git a/compiler/rustc_infer/src/infer/canonical/instantiate.rs b/compiler/rustc_infer/src/infer/canonical/instantiate.rs
index f5ee5702d09..67f13192b52 100644
--- a/compiler/rustc_infer/src/infer/canonical/instantiate.rs
+++ b/compiler/rustc_infer/src/infer/canonical/instantiate.rs
@@ -61,15 +61,15 @@ where
         value
     } else {
         let delegate = FnMutDelegate {
-            regions: &mut |br: ty::BoundRegion| match var_values[br.var].unpack() {
+            regions: &mut |br: ty::BoundRegion| match var_values[br.var].kind() {
                 GenericArgKind::Lifetime(l) => l,
                 r => bug!("{:?} is a region but value is {:?}", br, r),
             },
-            types: &mut |bound_ty: ty::BoundTy| match var_values[bound_ty.var].unpack() {
+            types: &mut |bound_ty: ty::BoundTy| match var_values[bound_ty.var].kind() {
                 GenericArgKind::Type(ty) => ty,
                 r => bug!("{:?} is a type but value is {:?}", bound_ty, r),
             },
-            consts: &mut |bound_ct: ty::BoundVar| match var_values[bound_ct].unpack() {
+            consts: &mut |bound_ct: ty::BoundVar| match var_values[bound_ct].kind() {
                 GenericArgKind::Const(ct) => ct,
                 c => bug!("{:?} is a const but value is {:?}", bound_ct, c),
             },
diff --git a/compiler/rustc_infer/src/infer/canonical/query_response.rs b/compiler/rustc_infer/src/infer/canonical/query_response.rs
index e9cfc96ba50..008ef690008 100644
--- a/compiler/rustc_infer/src/infer/canonical/query_response.rs
+++ b/compiler/rustc_infer/src/infer/canonical/query_response.rs
@@ -12,23 +12,20 @@ use std::iter;
 
 use rustc_index::{Idx, IndexVec};
 use rustc_middle::arena::ArenaAllocatable;
+use rustc_middle::bug;
 use rustc_middle::mir::ConstraintCategory;
 use rustc_middle::ty::{self, BoundVar, GenericArg, GenericArgKind, Ty, TyCtxt, TypeFoldable};
-use rustc_middle::{bug, span_bug};
 use tracing::{debug, instrument};
 
 use crate::infer::canonical::instantiate::{CanonicalExt, instantiate_value};
 use crate::infer::canonical::{
     Canonical, CanonicalQueryResponse, CanonicalVarValues, Certainty, OriginalQueryValues,
-    QueryOutlivesConstraint, QueryRegionConstraints, QueryResponse,
+    QueryRegionConstraints, QueryResponse,
 };
 use crate::infer::region_constraints::{Constraint, RegionConstraintData};
 use crate::infer::{DefineOpaqueTypes, InferCtxt, InferOk, InferResult, SubregionOrigin};
 use crate::traits::query::NoSolution;
-use crate::traits::{
-    Obligation, ObligationCause, PredicateObligation, PredicateObligations, ScrubbedTraitError,
-    TraitEngine,
-};
+use crate::traits::{ObligationCause, PredicateObligations, ScrubbedTraitError, TraitEngine};
 
 impl<'tcx> InferCtxt<'tcx> {
     /// This method is meant to be invoked as the final step of a canonical query
@@ -169,15 +166,13 @@ impl<'tcx> InferCtxt<'tcx> {
     where
         R: Debug + TypeFoldable<TyCtxt<'tcx>>,
     {
-        let InferOk { value: result_args, mut obligations } =
+        let InferOk { value: result_args, obligations } =
             self.query_response_instantiation(cause, param_env, original_values, query_response)?;
 
-        obligations.extend(self.query_outlives_constraints_into_obligations(
-            cause,
-            param_env,
-            &query_response.value.region_constraints.outlives,
-            &result_args,
-        ));
+        for (predicate, _category) in &query_response.value.region_constraints.outlives {
+            let predicate = instantiate_value(self.tcx, &result_args, *predicate);
+            self.register_outlives_constraint(predicate, cause);
+        }
 
         let user_result: R =
             query_response.instantiate_projected(self.tcx, &result_args, |q_r| q_r.value.clone());
@@ -250,7 +245,7 @@ impl<'tcx> InferCtxt<'tcx> {
             let result_value = query_response.instantiate_projected(self.tcx, &result_args, |v| {
                 v.var_values[BoundVar::new(index)]
             });
-            match (original_value.unpack(), result_value.unpack()) {
+            match (original_value.kind(), result_value.kind()) {
                 (GenericArgKind::Lifetime(re1), GenericArgKind::Lifetime(re2))
                     if re1.is_erased() && re2.is_erased() =>
                 {
@@ -407,7 +402,7 @@ impl<'tcx> InferCtxt<'tcx> {
         // [(?A, Vec<?0>), ('static, '?1), (?B, ?0)]
         for (original_value, result_value) in iter::zip(&original_values.var_values, result_values)
         {
-            match result_value.unpack() {
+            match result_value.kind() {
                 GenericArgKind::Type(result_value) => {
                     // e.g., here `result_value` might be `?0` in the example above...
                     if let ty::Bound(debruijn, b) = *result_value.kind() {
@@ -525,47 +520,6 @@ impl<'tcx> InferCtxt<'tcx> {
         self.unify_canonical_vars(cause, param_env, original_values, instantiated_query_response)
     }
 
-    /// Converts the region constraints resulting from a query into an
-    /// iterator of obligations.
-    fn query_outlives_constraints_into_obligations(
-        &self,
-        cause: &ObligationCause<'tcx>,
-        param_env: ty::ParamEnv<'tcx>,
-        uninstantiated_region_constraints: &[QueryOutlivesConstraint<'tcx>],
-        result_args: &CanonicalVarValues<'tcx>,
-    ) -> impl Iterator<Item = PredicateObligation<'tcx>> {
-        uninstantiated_region_constraints.iter().map(move |&constraint| {
-            let predicate = instantiate_value(self.tcx, result_args, constraint);
-            self.query_outlives_constraint_to_obligation(predicate, cause.clone(), param_env)
-        })
-    }
-
-    pub fn query_outlives_constraint_to_obligation(
-        &self,
-        (predicate, _): QueryOutlivesConstraint<'tcx>,
-        cause: ObligationCause<'tcx>,
-        param_env: ty::ParamEnv<'tcx>,
-    ) -> Obligation<'tcx, ty::Predicate<'tcx>> {
-        let ty::OutlivesPredicate(k1, r2) = predicate;
-
-        let atom = match k1.unpack() {
-            GenericArgKind::Lifetime(r1) => ty::PredicateKind::Clause(
-                ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(r1, r2)),
-            ),
-            GenericArgKind::Type(t1) => ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(
-                ty::OutlivesPredicate(t1, r2),
-            )),
-            GenericArgKind::Const(..) => {
-                // Consts cannot outlive one another, so we don't expect to
-                // encounter this branch.
-                span_bug!(cause.span, "unexpected const outlives {:?}", predicate);
-            }
-        };
-        let predicate = ty::Binder::dummy(atom);
-
-        Obligation::new(self.tcx, cause, param_env, predicate)
-    }
-
     /// Given two sets of values for the same set of canonical variables, unify them.
     /// The second set is produced lazily by supplying indices from the first set.
     fn unify_canonical_vars(
@@ -579,7 +533,7 @@ impl<'tcx> InferCtxt<'tcx> {
         for (index, value1) in variables1.var_values.iter().enumerate() {
             let value2 = variables2(BoundVar::new(index));
 
-            match (value1.unpack(), value2.unpack()) {
+            match (value1.kind(), value2.kind()) {
                 (GenericArgKind::Type(v1), GenericArgKind::Type(v2)) => {
                     obligations.extend(
                         self.at(cause, param_env)
diff --git a/compiler/rustc_infer/src/infer/context.rs b/compiler/rustc_infer/src/infer/context.rs
index 359b9da11ce..f7c702d321b 100644
--- a/compiler/rustc_infer/src/infer/context.rs
+++ b/compiler/rustc_infer/src/infer/context.rs
@@ -89,6 +89,57 @@ impl<'tcx> rustc_type_ir::InferCtxtLike for InferCtxt<'tcx> {
         self.inner.borrow_mut().unwrap_region_constraints().opportunistic_resolve_var(self.tcx, vid)
     }
 
+    fn is_changed_arg(&self, arg: ty::GenericArg<'tcx>) -> bool {
+        match arg.kind() {
+            ty::GenericArgKind::Lifetime(_) => {
+                // Lifetimes should not change affect trait selection.
+                false
+            }
+            ty::GenericArgKind::Type(ty) => {
+                if let ty::Infer(infer_ty) = *ty.kind() {
+                    match infer_ty {
+                        ty::InferTy::TyVar(vid) => {
+                            !self.probe_ty_var(vid).is_err_and(|_| self.root_var(vid) == vid)
+                        }
+                        ty::InferTy::IntVar(vid) => {
+                            let mut inner = self.inner.borrow_mut();
+                            !matches!(
+                                inner.int_unification_table().probe_value(vid),
+                                ty::IntVarValue::Unknown
+                                    if inner.int_unification_table().find(vid) == vid
+                            )
+                        }
+                        ty::InferTy::FloatVar(vid) => {
+                            let mut inner = self.inner.borrow_mut();
+                            !matches!(
+                                inner.float_unification_table().probe_value(vid),
+                                ty::FloatVarValue::Unknown
+                                    if inner.float_unification_table().find(vid) == vid
+                            )
+                        }
+                        ty::InferTy::FreshTy(_)
+                        | ty::InferTy::FreshIntTy(_)
+                        | ty::InferTy::FreshFloatTy(_) => true,
+                    }
+                } else {
+                    true
+                }
+            }
+            ty::GenericArgKind::Const(ct) => {
+                if let ty::ConstKind::Infer(infer_ct) = ct.kind() {
+                    match infer_ct {
+                        ty::InferConst::Var(vid) => !self
+                            .probe_const_var(vid)
+                            .is_err_and(|_| self.root_const_var(vid) == vid),
+                        ty::InferConst::Fresh(_) => true,
+                    }
+                } else {
+                    true
+                }
+            }
+        }
+    }
+
     fn next_region_infer(&self) -> ty::Region<'tcx> {
         self.next_region_var(RegionVariableOrigin::MiscVariable(DUMMY_SP))
     }
@@ -214,7 +265,7 @@ impl<'tcx> rustc_type_ir::InferCtxtLike for InferCtxt<'tcx> {
     }
 
     fn register_ty_outlives(&self, ty: Ty<'tcx>, r: ty::Region<'tcx>, span: Span) {
-        self.register_region_obligation_with_cause(ty, r, &ObligationCause::dummy_with_span(span));
+        self.register_type_outlives_constraint(ty, r, &ObligationCause::dummy_with_span(span));
     }
 
     type OpaqueTypeStorageEntries = OpaqueTypeStorageEntries;
diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs
index b408d76010d..96e03e3bea5 100644
--- a/compiler/rustc_infer/src/infer/mod.rs
+++ b/compiler/rustc_infer/src/infer/mod.rs
@@ -150,7 +150,7 @@ pub struct InferCtxtInner<'tcx> {
     /// for each body-id in this map, which will process the
     /// obligations within. This is expected to be done 'late enough'
     /// that all type inference variables have been bound and so forth.
-    region_obligations: Vec<RegionObligation<'tcx>>,
+    region_obligations: Vec<TypeOutlivesConstraint<'tcx>>,
 
     /// Caches for opaque type inference.
     opaque_type_storage: OpaqueTypeStorage<'tcx>,
@@ -173,7 +173,7 @@ impl<'tcx> InferCtxtInner<'tcx> {
     }
 
     #[inline]
-    pub fn region_obligations(&self) -> &[RegionObligation<'tcx>] {
+    pub fn region_obligations(&self) -> &[TypeOutlivesConstraint<'tcx>] {
         &self.region_obligations
     }
 
@@ -488,7 +488,7 @@ impl fmt::Display for FixupError {
 
 /// See the `region_obligations` field for more information.
 #[derive(Clone, Debug)]
-pub struct RegionObligation<'tcx> {
+pub struct TypeOutlivesConstraint<'tcx> {
     pub sub_region: ty::Region<'tcx>,
     pub sup_type: Ty<'tcx>,
     pub origin: SubregionOrigin<'tcx>,
@@ -738,19 +738,6 @@ impl<'tcx> InferCtxt<'tcx> {
         })
     }
 
-    pub fn region_outlives_predicate(
-        &self,
-        cause: &traits::ObligationCause<'tcx>,
-        predicate: ty::PolyRegionOutlivesPredicate<'tcx>,
-    ) {
-        self.enter_forall(predicate, |ty::OutlivesPredicate(r_a, r_b)| {
-            let origin = SubregionOrigin::from_obligation_cause(cause, || {
-                RelateRegionParamBound(cause.span, None)
-            });
-            self.sub_regions(origin, r_b, r_a); // `b : a` ==> `a <= b`
-        })
-    }
-
     /// Number of type variables created so far.
     pub fn num_ty_vars(&self) -> usize {
         self.inner.borrow_mut().type_variables().num_vars()
@@ -1385,7 +1372,7 @@ impl<'tcx> TyOrConstInferVar {
     /// for types other than `ty::Infer(_)` (or `InferTy::Fresh*`) and
     /// for constants other than `ty::ConstKind::Infer(_)` (or `InferConst::Fresh`).
     pub fn maybe_from_generic_arg(arg: GenericArg<'tcx>) -> Option<Self> {
-        match arg.unpack() {
+        match arg.kind() {
             GenericArgKind::Type(ty) => Self::maybe_from_ty(ty),
             GenericArgKind::Const(ct) => Self::maybe_from_const(ct),
             GenericArgKind::Lifetime(_) => None,
@@ -1396,7 +1383,7 @@ impl<'tcx> TyOrConstInferVar {
     /// for types other than `ty::Infer(_)` (or `InferTy::Fresh*`) and
     /// for constants other than `ty::ConstKind::Infer(_)` (or `InferConst::Fresh`).
     pub fn maybe_from_term(term: Term<'tcx>) -> Option<Self> {
-        match term.unpack() {
+        match term.kind() {
             TermKind::Ty(ty) => Self::maybe_from_ty(ty),
             TermKind::Const(ct) => Self::maybe_from_const(ct),
         }
diff --git a/compiler/rustc_infer/src/infer/opaque_types/table.rs b/compiler/rustc_infer/src/infer/opaque_types/table.rs
index 46752840e1b..ab65da3913d 100644
--- a/compiler/rustc_infer/src/infer/opaque_types/table.rs
+++ b/compiler/rustc_infer/src/infer/opaque_types/table.rs
@@ -24,6 +24,12 @@ pub struct OpaqueTypeStorageEntries {
     duplicate_entries: usize,
 }
 
+impl rustc_type_ir::inherent::OpaqueTypeStorageEntries for OpaqueTypeStorageEntries {
+    fn needs_reevaluation(self, canonicalized: usize) -> bool {
+        self.opaque_types != canonicalized
+    }
+}
+
 impl<'tcx> OpaqueTypeStorage<'tcx> {
     #[instrument(level = "debug")]
     pub(crate) fn remove(
diff --git a/compiler/rustc_infer/src/infer/outlives/obligations.rs b/compiler/rustc_infer/src/infer/outlives/obligations.rs
index 5fd98e35e5c..10827c9fd03 100644
--- a/compiler/rustc_infer/src/infer/outlives/obligations.rs
+++ b/compiler/rustc_infer/src/infer/outlives/obligations.rs
@@ -76,23 +76,56 @@ use crate::infer::outlives::env::RegionBoundPairs;
 use crate::infer::outlives::verify::VerifyBoundCx;
 use crate::infer::resolve::OpportunisticRegionResolver;
 use crate::infer::snapshot::undo_log::UndoLog;
-use crate::infer::{self, GenericKind, InferCtxt, RegionObligation, SubregionOrigin, VerifyBound};
+use crate::infer::{
+    self, GenericKind, InferCtxt, SubregionOrigin, TypeOutlivesConstraint, VerifyBound,
+};
 use crate::traits::{ObligationCause, ObligationCauseCode};
 
 impl<'tcx> InferCtxt<'tcx> {
+    pub fn register_outlives_constraint(
+        &self,
+        ty::OutlivesPredicate(arg, r2): ty::OutlivesPredicate<'tcx, ty::GenericArg<'tcx>>,
+        cause: &ObligationCause<'tcx>,
+    ) {
+        match arg.kind() {
+            ty::GenericArgKind::Lifetime(r1) => {
+                self.register_region_outlives_constraint(ty::OutlivesPredicate(r1, r2), cause);
+            }
+            ty::GenericArgKind::Type(ty1) => {
+                self.register_type_outlives_constraint(ty1, r2, cause);
+            }
+            ty::GenericArgKind::Const(_) => unreachable!(),
+        }
+    }
+
+    pub fn register_region_outlives_constraint(
+        &self,
+        ty::OutlivesPredicate(r_a, r_b): ty::RegionOutlivesPredicate<'tcx>,
+        cause: &ObligationCause<'tcx>,
+    ) {
+        let origin = SubregionOrigin::from_obligation_cause(cause, || {
+            SubregionOrigin::RelateRegionParamBound(cause.span, None)
+        });
+        // `'a: 'b` ==> `'b <= 'a`
+        self.sub_regions(origin, r_b, r_a);
+    }
+
     /// Registers that the given region obligation must be resolved
     /// from within the scope of `body_id`. These regions are enqueued
     /// and later processed by regionck, when full type information is
     /// available (see `region_obligations` field for more
     /// information).
     #[instrument(level = "debug", skip(self))]
-    pub fn register_region_obligation(&self, obligation: RegionObligation<'tcx>) {
+    pub fn register_type_outlives_constraint_inner(
+        &self,
+        obligation: TypeOutlivesConstraint<'tcx>,
+    ) {
         let mut inner = self.inner.borrow_mut();
-        inner.undo_log.push(UndoLog::PushRegionObligation);
+        inner.undo_log.push(UndoLog::PushTypeOutlivesConstraint);
         inner.region_obligations.push(obligation);
     }
 
-    pub fn register_region_obligation_with_cause(
+    pub fn register_type_outlives_constraint(
         &self,
         sup_type: Ty<'tcx>,
         sub_region: Region<'tcx>,
@@ -124,11 +157,15 @@ impl<'tcx> InferCtxt<'tcx> {
             )
         });
 
-        self.register_region_obligation(RegionObligation { sup_type, sub_region, origin });
+        self.register_type_outlives_constraint_inner(TypeOutlivesConstraint {
+            sup_type,
+            sub_region,
+            origin,
+        });
     }
 
     /// Trait queries just want to pass back type obligations "as is"
-    pub fn take_registered_region_obligations(&self) -> Vec<RegionObligation<'tcx>> {
+    pub fn take_registered_region_obligations(&self) -> Vec<TypeOutlivesConstraint<'tcx>> {
         std::mem::take(&mut self.inner.borrow_mut().region_obligations)
     }
 
@@ -166,7 +203,7 @@ impl<'tcx> InferCtxt<'tcx> {
                 );
             }
 
-            for RegionObligation { sup_type, sub_region, origin } in my_region_obligations {
+            for TypeOutlivesConstraint { sup_type, sub_region, origin } in my_region_obligations {
                 let outlives = ty::Binder::dummy(ty::OutlivesPredicate(sup_type, sub_region));
                 let ty::OutlivesPredicate(sup_type, sub_region) =
                     deeply_normalize_ty(outlives, origin.clone())
@@ -466,8 +503,8 @@ where
         opt_variances: Option<&[ty::Variance]>,
     ) {
         let constraint = origin.to_constraint_category();
-        for (index, k) in args.iter().enumerate() {
-            match k.unpack() {
+        for (index, arg) in args.iter().enumerate() {
+            match arg.kind() {
                 GenericArgKind::Lifetime(lt) => {
                     let variance = if let Some(variances) = opt_variances {
                         variances[index]
diff --git a/compiler/rustc_infer/src/infer/relate/generalize.rs b/compiler/rustc_infer/src/infer/relate/generalize.rs
index 210b8f37d88..0e17b100276 100644
--- a/compiler/rustc_infer/src/infer/relate/generalize.rs
+++ b/compiler/rustc_infer/src/infer/relate/generalize.rs
@@ -329,7 +329,7 @@ struct Generalizer<'me, 'tcx> {
 impl<'tcx> Generalizer<'_, 'tcx> {
     /// Create an error that corresponds to the term kind in `root_term`
     fn cyclic_term_error(&self) -> TypeError<'tcx> {
-        match self.root_term.unpack() {
+        match self.root_term.kind() {
             ty::TermKind::Ty(ty) => TypeError::CyclicTy(ty),
             ty::TermKind::Const(ct) => TypeError::CyclicConst(ct),
         }
diff --git a/compiler/rustc_infer/src/infer/resolve.rs b/compiler/rustc_infer/src/infer/resolve.rs
index 4b0ace8c554..a95f24b5b95 100644
--- a/compiler/rustc_infer/src/infer/resolve.rs
+++ b/compiler/rustc_infer/src/infer/resolve.rs
@@ -55,6 +55,14 @@ impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for OpportunisticVarResolver<'a, 'tcx> {
             ct.super_fold_with(self)
         }
     }
+
+    fn fold_predicate(&mut self, p: ty::Predicate<'tcx>) -> ty::Predicate<'tcx> {
+        if !p.has_non_region_infer() { p } else { p.super_fold_with(self) }
+    }
+
+    fn fold_clauses(&mut self, c: ty::Clauses<'tcx>) -> ty::Clauses<'tcx> {
+        if !c.has_non_region_infer() { c } else { c.super_fold_with(self) }
+    }
 }
 
 /// The opportunistic region resolver opportunistically resolves regions
diff --git a/compiler/rustc_infer/src/infer/snapshot/undo_log.rs b/compiler/rustc_infer/src/infer/snapshot/undo_log.rs
index b7412d3d6a6..6193f35f3eb 100644
--- a/compiler/rustc_infer/src/infer/snapshot/undo_log.rs
+++ b/compiler/rustc_infer/src/infer/snapshot/undo_log.rs
@@ -26,7 +26,7 @@ pub(crate) enum UndoLog<'tcx> {
     RegionConstraintCollector(region_constraints::UndoLog<'tcx>),
     RegionUnificationTable(sv::UndoLog<ut::Delegate<RegionVidKey<'tcx>>>),
     ProjectionCache(traits::UndoLog<'tcx>),
-    PushRegionObligation,
+    PushTypeOutlivesConstraint,
 }
 
 macro_rules! impl_from {
@@ -72,7 +72,7 @@ impl<'tcx> Rollback<UndoLog<'tcx>> for InferCtxtInner<'tcx> {
                 self.region_constraint_storage.as_mut().unwrap().unification_table.reverse(undo)
             }
             UndoLog::ProjectionCache(undo) => self.projection_cache.reverse(undo),
-            UndoLog::PushRegionObligation => {
+            UndoLog::PushTypeOutlivesConstraint => {
                 self.region_obligations.pop();
             }
         }
diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs
index 75d92ae7a2e..5bc7559d29a 100644
--- a/compiler/rustc_interface/src/passes.rs
+++ b/compiler/rustc_interface/src/passes.rs
@@ -1012,10 +1012,6 @@ fn run_required_analyses(tcx: TyCtxt<'_>) {
             {
                 tcx.ensure_ok().mir_drops_elaborated_and_const_checked(def_id);
             }
-        });
-    });
-    sess.time("coroutine_obligations", || {
-        tcx.par_hir_body_owners(|def_id| {
             if tcx.is_coroutine(def_id.to_def_id()) {
                 tcx.ensure_ok().mir_coroutine_witnesses(def_id);
                 let _ = tcx.ensure_ok().check_coroutine_obligations(
diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs
index 20e081d3360..558f13a832c 100644
--- a/compiler/rustc_interface/src/tests.rs
+++ b/compiler/rustc_interface/src/tests.rs
@@ -715,6 +715,7 @@ fn test_unstable_options_tracking_hash() {
     untracked!(no_analysis, true);
     untracked!(no_leak_check, true);
     untracked!(no_parallel_backend, true);
+    untracked!(no_steal_thir, true);
     untracked!(parse_crate_root_only, true);
     // `pre_link_arg` is omitted because it just forwards to `pre_link_args`.
     untracked!(pre_link_args, vec![String::from("abc"), String::from("def")]);
@@ -776,8 +777,7 @@ fn test_unstable_options_tracking_hash() {
         CoverageOptions {
             level: CoverageLevel::Mcdc,
             no_mir_spans: true,
-            discard_all_spans_in_codegen: true,
-            inject_unused_local_file: true,
+            discard_all_spans_in_codegen: true
         }
     );
     tracked!(crate_attr, vec!["abc".to_string()]);
diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl
index 7fdf26bf3af..17485a838f3 100644
--- a/compiler/rustc_lint/messages.ftl
+++ b/compiler/rustc_lint/messages.ftl
@@ -13,6 +13,8 @@ lint_ambiguous_negative_literals = `-` has lower precedence than method calls, w
 lint_ambiguous_wide_pointer_comparisons = ambiguous wide pointer comparison, the comparison includes metadata which may not be expected
     .addr_metadata_suggestion = use explicit `std::ptr::eq` method to compare metadata and addresses
     .addr_suggestion = use `std::ptr::addr_eq` or untyped pointers to only compare their addresses
+    .cast_suggestion = use untyped pointers to only compare their addresses
+    .expect_suggestion = or expect the lint to compare the pointers metadata and addresses
 
 lint_associated_const_elided_lifetime = {$elided ->
         [true] `&` without an explicit lifetime name cannot be used here
@@ -805,6 +807,11 @@ lint_type_ir_inherent_usage = do not use `rustc_type_ir::inherent` unless you're
 lint_type_ir_trait_usage = do not use `rustc_type_ir::Interner` or `rustc_type_ir::InferCtxtLike` unless you're inside of the trait solver
     .note = the method or struct you're looking for is likely defined somewhere else downstream in the compiler
 
+lint_undefined_transmute = pointers cannot be transmuted to integers during const eval
+    .note = at compile-time, pointers do not have an integer value
+    .note2 = avoiding this restriction via `union` or raw pointers leads to compile-time undefined behavior
+    .help = for more information, see https://doc.rust-lang.org/std/mem/fn.transmute.html
+
 lint_undropped_manually_drops = calls to `std::mem::drop` with `std::mem::ManuallyDrop` instead of the inner value does nothing
     .label = argument has type `{$arg_ty}`
     .suggestion = use `std::mem::ManuallyDrop::into_inner` to get the inner value
@@ -953,7 +960,8 @@ lint_unused_doc_comment = unused doc comment
     .help = to document an item produced by a macro, the macro must produce the documentation as part of its expansion
 
 lint_unused_extern_crate = unused extern crate
-    .suggestion = remove it
+    .label = unused
+    .suggestion = remove the unused `extern crate`
 
 lint_unused_import_braces = braces around {$node} is unnecessary
 
diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs
index 95e31e4af1e..47b80135bae 100644
--- a/compiler/rustc_lint/src/builtin.rs
+++ b/compiler/rustc_lint/src/builtin.rs
@@ -545,22 +545,22 @@ impl<'tcx> LateLintPass<'tcx> for MissingCopyImplementations {
             return;
         }
         let (def, ty) = match item.kind {
-            hir::ItemKind::Struct(_, _, ast_generics) => {
-                if !ast_generics.params.is_empty() {
+            hir::ItemKind::Struct(_, generics, _) => {
+                if !generics.params.is_empty() {
                     return;
                 }
                 let def = cx.tcx.adt_def(item.owner_id);
                 (def, Ty::new_adt(cx.tcx, def, ty::List::empty()))
             }
-            hir::ItemKind::Union(_, _, ast_generics) => {
-                if !ast_generics.params.is_empty() {
+            hir::ItemKind::Union(_, generics, _) => {
+                if !generics.params.is_empty() {
                     return;
                 }
                 let def = cx.tcx.adt_def(item.owner_id);
                 (def, Ty::new_adt(cx.tcx, def, ty::List::empty()))
             }
-            hir::ItemKind::Enum(_, _, ast_generics) => {
-                if !ast_generics.params.is_empty() {
+            hir::ItemKind::Enum(_, generics, _) => {
+                if !generics.params.is_empty() {
                     return;
                 }
                 let def = cx.tcx.adt_def(item.owner_id);
@@ -1422,7 +1422,7 @@ impl TypeAliasBounds {
 
 impl<'tcx> LateLintPass<'tcx> for TypeAliasBounds {
     fn check_item(&mut self, cx: &LateContext<'_>, item: &hir::Item<'_>) {
-        let hir::ItemKind::TyAlias(_, hir_ty, generics) = item.kind else { return };
+        let hir::ItemKind::TyAlias(_, generics, hir_ty) = item.kind else { return };
 
         // There must not be a where clause.
         if generics.predicates.is_empty() {
@@ -2125,9 +2125,9 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitOutlivesRequirements {
         use rustc_middle::middle::resolve_bound_vars::ResolvedArg;
 
         let def_id = item.owner_id.def_id;
-        if let hir::ItemKind::Struct(_, _, hir_generics)
-        | hir::ItemKind::Enum(_, _, hir_generics)
-        | hir::ItemKind::Union(_, _, hir_generics) = item.kind
+        if let hir::ItemKind::Struct(_, generics, _)
+        | hir::ItemKind::Enum(_, generics, _)
+        | hir::ItemKind::Union(_, generics, _) = item.kind
         {
             let inferred_outlives = cx.tcx.inferred_outlives_of(def_id);
             if inferred_outlives.is_empty() {
@@ -2135,7 +2135,7 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitOutlivesRequirements {
             }
 
             let ty_generics = cx.tcx.generics_of(def_id);
-            let num_where_predicates = hir_generics
+            let num_where_predicates = generics
                 .predicates
                 .iter()
                 .filter(|predicate| predicate.kind.in_where_clause())
@@ -2145,7 +2145,7 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitOutlivesRequirements {
             let mut lint_spans = Vec::new();
             let mut where_lint_spans = Vec::new();
             let mut dropped_where_predicate_count = 0;
-            for (i, where_predicate) in hir_generics.predicates.iter().enumerate() {
+            for (i, where_predicate) in generics.predicates.iter().enumerate() {
                 let (relevant_lifetimes, bounds, predicate_span, in_where_clause) =
                     match where_predicate.kind {
                         hir::WherePredicateKind::RegionPredicate(predicate) => {
@@ -2228,7 +2228,7 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitOutlivesRequirements {
                     } else if i + 1 < num_where_predicates {
                         // If all the bounds on a predicate were inferable and there are
                         // further predicates, we want to eat the trailing comma.
-                        let next_predicate_span = hir_generics.predicates[i + 1].span;
+                        let next_predicate_span = generics.predicates[i + 1].span;
                         if next_predicate_span.from_expansion() {
                             where_lint_spans.push(predicate_span);
                         } else {
@@ -2237,7 +2237,7 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitOutlivesRequirements {
                         }
                     } else {
                         // Eat the optional trailing comma after the last predicate.
-                        let where_span = hir_generics.where_clause_span;
+                        let where_span = generics.where_clause_span;
                         if where_span.from_expansion() {
                             where_lint_spans.push(predicate_span);
                         } else {
@@ -2255,18 +2255,18 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitOutlivesRequirements {
 
             // If all predicates in where clause are inferable, drop the entire clause
             // (including the `where`)
-            if hir_generics.has_where_clause_predicates
+            if generics.has_where_clause_predicates
                 && dropped_where_predicate_count == num_where_predicates
             {
-                let where_span = hir_generics.where_clause_span;
+                let where_span = generics.where_clause_span;
                 // Extend the where clause back to the closing `>` of the
                 // generics, except for tuple struct, which have the `where`
                 // after the fields of the struct.
                 let full_where_span =
-                    if let hir::ItemKind::Struct(_, hir::VariantData::Tuple(..), _) = item.kind {
+                    if let hir::ItemKind::Struct(_, _, hir::VariantData::Tuple(..)) = item.kind {
                         where_span
                     } else {
-                        hir_generics.span.shrink_to_hi().to(where_span)
+                        generics.span.shrink_to_hi().to(where_span)
                     };
 
                 // Due to macro expansions, the `full_where_span` might not actually contain all
diff --git a/compiler/rustc_lint/src/default_could_be_derived.rs b/compiler/rustc_lint/src/default_could_be_derived.rs
index 78d129642dc..7734f441df2 100644
--- a/compiler/rustc_lint/src/default_could_be_derived.rs
+++ b/compiler/rustc_lint/src/default_could_be_derived.rs
@@ -95,8 +95,8 @@ impl<'tcx> LateLintPass<'tcx> for DefaultCouldBeDerived {
                 kind:
                     hir::ItemKind::Struct(
                         _,
-                        hir::VariantData::Struct { fields, recovered: _ },
                         _generics,
+                        hir::VariantData::Struct { fields, recovered: _ },
                     ),
                 ..
             })) => fields.iter().map(|f| (f.ident.name, f)).collect::<FxHashMap<_, _>>(),
diff --git a/compiler/rustc_lint/src/early.rs b/compiler/rustc_lint/src/early.rs
index f9601fa5ef1..4978f293ab7 100644
--- a/compiler/rustc_lint/src/early.rs
+++ b/compiler/rustc_lint/src/early.rs
@@ -18,7 +18,7 @@ use tracing::debug;
 use crate::context::{EarlyContext, LintContext, LintStore};
 use crate::passes::{EarlyLintPass, EarlyLintPassObject};
 
-mod diagnostics;
+pub(super) mod diagnostics;
 
 macro_rules! lint_callback { ($cx:expr, $f:ident, $($args:expr),*) => ({
     $cx.pass.$f(&$cx.context, $($args),*);
@@ -40,7 +40,7 @@ impl<'ecx, 'tcx, T: EarlyLintPass> EarlyContextAndPass<'ecx, 'tcx, T> {
         for early_lint in self.context.buffered.take(id) {
             let BufferedEarlyLint { span, node_id: _, lint_id, diagnostic } = early_lint;
             self.context.opt_span_lint(lint_id.lint, span, |diag| {
-                diagnostics::decorate_lint(self.context.sess(), self.tcx, diagnostic, diag);
+                diagnostics::decorate_builtin_lint(self.context.sess(), self.tcx, diagnostic, diag);
             });
         }
     }
@@ -74,8 +74,8 @@ impl<'ecx, 'tcx, T: EarlyLintPass> EarlyContextAndPass<'ecx, 'tcx, T> {
 impl<'ast, 'ecx, 'tcx, T: EarlyLintPass> ast_visit::Visitor<'ast>
     for EarlyContextAndPass<'ecx, 'tcx, T>
 {
-    fn visit_coroutine_kind(&mut self, coroutine_kind: &'ast ast::CoroutineKind) -> Self::Result {
-        self.check_id(coroutine_kind.closure_id());
+    fn visit_id(&mut self, id: rustc_ast::NodeId) {
+        self.check_id(id);
     }
 
     fn visit_param(&mut self, param: &'ast ast::Param) {
@@ -101,7 +101,6 @@ impl<'ast, 'ecx, 'tcx, T: EarlyLintPass> ast_visit::Visitor<'ast>
 
     fn visit_pat(&mut self, p: &'ast ast::Pat) {
         lint_callback!(self, check_pat, p);
-        self.check_id(p.id);
         ast_visit::walk_pat(self, p);
         lint_callback!(self, check_pat_post, p);
     }
@@ -112,11 +111,6 @@ impl<'ast, 'ecx, 'tcx, T: EarlyLintPass> ast_visit::Visitor<'ast>
         });
     }
 
-    fn visit_anon_const(&mut self, c: &'ast ast::AnonConst) {
-        self.check_id(c.id);
-        ast_visit::walk_anon_const(self, c);
-    }
-
     fn visit_expr(&mut self, e: &'ast ast::Expr) {
         self.with_lint_attrs(e.id, &e.attrs, |cx| {
             lint_callback!(cx, check_expr, e);
@@ -157,13 +151,6 @@ impl<'ast, 'ecx, 'tcx, T: EarlyLintPass> ast_visit::Visitor<'ast>
         ast_visit::walk_fn(self, fk);
     }
 
-    fn visit_variant_data(&mut self, s: &'ast ast::VariantData) {
-        if let Some(ctor_node_id) = s.ctor_node_id() {
-            self.check_id(ctor_node_id);
-        }
-        ast_visit::walk_struct_def(self, s);
-    }
-
     fn visit_field_def(&mut self, s: &'ast ast::FieldDef) {
         self.with_lint_attrs(s.id, &s.attrs, |cx| {
             ast_visit::walk_field_def(cx, s);
@@ -179,7 +166,6 @@ impl<'ast, 'ecx, 'tcx, T: EarlyLintPass> ast_visit::Visitor<'ast>
 
     fn visit_ty(&mut self, t: &'ast ast::Ty) {
         lint_callback!(self, check_ty, t);
-        self.check_id(t.id);
         ast_visit::walk_ty(self, t);
     }
 
@@ -196,7 +182,6 @@ impl<'ast, 'ecx, 'tcx, T: EarlyLintPass> ast_visit::Visitor<'ast>
 
     fn visit_block(&mut self, b: &'ast ast::Block) {
         lint_callback!(self, check_block, b);
-        self.check_id(b.id);
         ast_visit::walk_block(self, b);
     }
 
@@ -257,29 +242,13 @@ impl<'ast, 'ecx, 'tcx, T: EarlyLintPass> ast_visit::Visitor<'ast>
         });
     }
 
-    fn visit_lifetime(&mut self, lt: &'ast ast::Lifetime, _: ast_visit::LifetimeCtxt) {
-        self.check_id(lt.id);
-        ast_visit::walk_lifetime(self, lt);
-    }
-
-    fn visit_path(&mut self, p: &'ast ast::Path, id: ast::NodeId) {
-        self.check_id(id);
-        ast_visit::walk_path(self, p);
-    }
-
-    fn visit_path_segment(&mut self, s: &'ast ast::PathSegment) {
-        self.check_id(s.id);
-        ast_visit::walk_path_segment(self, s);
-    }
-
     fn visit_attribute(&mut self, attr: &'ast ast::Attribute) {
         lint_callback!(self, check_attribute, attr);
         ast_visit::walk_attribute(self, attr);
     }
 
-    fn visit_mac_def(&mut self, mac: &'ast ast::MacroDef, id: ast::NodeId) {
+    fn visit_macro_def(&mut self, mac: &'ast ast::MacroDef) {
         lint_callback!(self, check_mac_def, mac);
-        self.check_id(id);
     }
 
     fn visit_mac_call(&mut self, mac: &'ast ast::MacCall) {
diff --git a/compiler/rustc_lint/src/early/diagnostics.rs b/compiler/rustc_lint/src/early/diagnostics.rs
index 40ca9e05d95..71b621e8d20 100644
--- a/compiler/rustc_lint/src/early/diagnostics.rs
+++ b/compiler/rustc_lint/src/early/diagnostics.rs
@@ -18,7 +18,7 @@ use crate::lints::{self, ElidedNamedLifetime};
 
 mod check_cfg;
 
-pub(super) fn decorate_lint(
+pub fn decorate_builtin_lint(
     sess: &Session,
     tcx: Option<TyCtxt<'_>>,
     diagnostic: BuiltinLintDiag,
@@ -187,6 +187,27 @@ pub(super) fn decorate_lint(
                 lints::ReservedMultihash { suggestion }.decorate_lint(diag);
             }
         }
+        BuiltinLintDiag::HiddenUnicodeCodepoints {
+            label,
+            count,
+            span_label,
+            labels,
+            escape,
+            spans,
+        } => {
+            lints::HiddenUnicodeCodepointsDiag {
+                label: &label,
+                count,
+                span_label,
+                labels: labels.map(|spans| lints::HiddenUnicodeCodepointsDiagLabels { spans }),
+                sub: if escape {
+                    lints::HiddenUnicodeCodepointsDiagSub::Escape { spans }
+                } else {
+                    lints::HiddenUnicodeCodepointsDiagSub::NoEscape { spans }
+                },
+            }
+            .decorate_lint(diag);
+        }
         BuiltinLintDiag::UnusedBuiltinAttribute { attr_name, macro_name, invoc_span } => {
             lints::UnusedBuiltinAttribute { invoc_span, attr_name, macro_name }.decorate_lint(diag);
         }
@@ -292,8 +313,8 @@ pub(super) fn decorate_lint(
         BuiltinLintDiag::ByteSliceInPackedStructWithDerive { ty } => {
             lints::ByteSliceInPackedStructWithDerive { ty }.decorate_lint(diag);
         }
-        BuiltinLintDiag::UnusedExternCrate { removal_span } => {
-            lints::UnusedExternCrate { removal_span }.decorate_lint(diag);
+        BuiltinLintDiag::UnusedExternCrate { span, removal_span } => {
+            lints::UnusedExternCrate { span, removal_span }.decorate_lint(diag);
         }
         BuiltinLintDiag::ExternCrateNotIdiomatic { vis_span, ident_span } => {
             let suggestion_span = vis_span.between(ident_span);
diff --git a/compiler/rustc_lint/src/hidden_unicode_codepoints.rs b/compiler/rustc_lint/src/hidden_unicode_codepoints.rs
deleted file mode 100644
index 491c2826baa..00000000000
--- a/compiler/rustc_lint/src/hidden_unicode_codepoints.rs
+++ /dev/null
@@ -1,136 +0,0 @@
-use ast::util::unicode::{TEXT_FLOW_CONTROL_CHARS, contains_text_flow_control_chars};
-use rustc_ast as ast;
-use rustc_session::{declare_lint, declare_lint_pass};
-use rustc_span::{BytePos, Span, Symbol};
-
-use crate::lints::{
-    HiddenUnicodeCodepointsDiag, HiddenUnicodeCodepointsDiagLabels, HiddenUnicodeCodepointsDiagSub,
-};
-use crate::{EarlyContext, EarlyLintPass, LintContext};
-
-declare_lint! {
-    #[allow(text_direction_codepoint_in_literal)]
-    /// The `text_direction_codepoint_in_literal` lint detects Unicode codepoints that change the
-    /// visual representation of text on screen in a way that does not correspond to their on
-    /// memory representation.
-    ///
-    /// ### Explanation
-    ///
-    /// The unicode characters `\u{202A}`, `\u{202B}`, `\u{202D}`, `\u{202E}`, `\u{2066}`,
-    /// `\u{2067}`, `\u{2068}`, `\u{202C}` and `\u{2069}` make the flow of text on screen change
-    /// its direction on software that supports these codepoints. This makes the text "abc" display
-    /// as "cba" on screen. By leveraging software that supports these, people can write specially
-    /// crafted literals that make the surrounding code seem like it's performing one action, when
-    /// in reality it is performing another. Because of this, we proactively lint against their
-    /// presence to avoid surprises.
-    ///
-    /// ### Example
-    ///
-    /// ```rust,compile_fail
-    /// #![deny(text_direction_codepoint_in_literal)]
-    /// fn main() {
-    ///     println!("{:?}", '‮');
-    /// }
-    /// ```
-    ///
-    /// {{produces}}
-    ///
-    pub TEXT_DIRECTION_CODEPOINT_IN_LITERAL,
-    Deny,
-    "detect special Unicode codepoints that affect the visual representation of text on screen, \
-     changing the direction in which text flows",
-}
-
-declare_lint_pass!(HiddenUnicodeCodepoints => [TEXT_DIRECTION_CODEPOINT_IN_LITERAL]);
-
-impl HiddenUnicodeCodepoints {
-    fn lint_text_direction_codepoint(
-        &self,
-        cx: &EarlyContext<'_>,
-        text: Symbol,
-        span: Span,
-        padding: u32,
-        point_at_inner_spans: bool,
-        label: &str,
-    ) {
-        // Obtain the `Span`s for each of the forbidden chars.
-        let spans: Vec<_> = text
-            .as_str()
-            .char_indices()
-            .filter_map(|(i, c)| {
-                TEXT_FLOW_CONTROL_CHARS.contains(&c).then(|| {
-                    let lo = span.lo() + BytePos(i as u32 + padding);
-                    (c, span.with_lo(lo).with_hi(lo + BytePos(c.len_utf8() as u32)))
-                })
-            })
-            .collect();
-
-        let count = spans.len();
-        let labels = point_at_inner_spans
-            .then_some(HiddenUnicodeCodepointsDiagLabels { spans: spans.clone() });
-        let sub = if point_at_inner_spans && !spans.is_empty() {
-            HiddenUnicodeCodepointsDiagSub::Escape { spans }
-        } else {
-            HiddenUnicodeCodepointsDiagSub::NoEscape { spans }
-        };
-
-        cx.emit_span_lint(
-            TEXT_DIRECTION_CODEPOINT_IN_LITERAL,
-            span,
-            HiddenUnicodeCodepointsDiag { label, count, span_label: span, labels, sub },
-        );
-    }
-
-    fn check_literal(
-        &mut self,
-        cx: &EarlyContext<'_>,
-        text: Symbol,
-        lit_kind: ast::token::LitKind,
-        span: Span,
-        label: &'static str,
-    ) {
-        if !contains_text_flow_control_chars(text.as_str()) {
-            return;
-        }
-        let (padding, point_at_inner_spans) = match lit_kind {
-            // account for `"` or `'`
-            ast::token::LitKind::Str | ast::token::LitKind::Char => (1, true),
-            // account for `c"`
-            ast::token::LitKind::CStr => (2, true),
-            // account for `r###"`
-            ast::token::LitKind::StrRaw(n) => (n as u32 + 2, true),
-            // account for `cr###"`
-            ast::token::LitKind::CStrRaw(n) => (n as u32 + 3, true),
-            // suppress bad literals.
-            ast::token::LitKind::Err(_) => return,
-            // Be conservative just in case new literals do support these.
-            _ => (0, false),
-        };
-        self.lint_text_direction_codepoint(cx, text, span, padding, point_at_inner_spans, label);
-    }
-}
-
-impl EarlyLintPass for HiddenUnicodeCodepoints {
-    fn check_attribute(&mut self, cx: &EarlyContext<'_>, attr: &ast::Attribute) {
-        if let ast::AttrKind::DocComment(_, comment) = attr.kind {
-            if contains_text_flow_control_chars(comment.as_str()) {
-                self.lint_text_direction_codepoint(cx, comment, attr.span, 0, false, "doc comment");
-            }
-        }
-    }
-
-    #[inline]
-    fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &ast::Expr) {
-        // byte strings are already handled well enough by `EscapeError::NonAsciiCharInByteString`
-        match &expr.kind {
-            ast::ExprKind::Lit(token_lit) => {
-                self.check_literal(cx, token_lit.symbol, token_lit.kind, expr.span, "literal");
-            }
-            ast::ExprKind::FormatArgs(args) => {
-                let (lit_kind, text) = args.uncooked_fmt_str;
-                self.check_literal(cx, text, lit_kind, args.span, "format string");
-            }
-            _ => {}
-        };
-    }
-}
diff --git a/compiler/rustc_lint/src/impl_trait_overcaptures.rs b/compiler/rustc_lint/src/impl_trait_overcaptures.rs
index a8f45d043be..8124d7f7c86 100644
--- a/compiler/rustc_lint/src/impl_trait_overcaptures.rs
+++ b/compiler/rustc_lint/src/impl_trait_overcaptures.rs
@@ -461,7 +461,7 @@ fn extract_def_id_from_arg<'tcx>(
     generics: &'tcx ty::Generics,
     arg: ty::GenericArg<'tcx>,
 ) -> DefId {
-    match arg.unpack() {
+    match arg.kind() {
         ty::GenericArgKind::Lifetime(re) => match re.kind() {
             ty::ReEarlyParam(ebr) => generics.region_param(ebr, tcx).def_id,
             ty::ReBound(
diff --git a/compiler/rustc_lint/src/internal.rs b/compiler/rustc_lint/src/internal.rs
index 1d4be24ea9f..1805a674d68 100644
--- a/compiler/rustc_lint/src/internal.rs
+++ b/compiler/rustc_lint/src/internal.rs
@@ -328,16 +328,19 @@ impl<'tcx> LateLintPass<'tcx> for TypeIr {
     fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'tcx>) {
         let rustc_hir::ItemKind::Use(path, kind) = item.kind else { return };
 
-        let is_mod_inherent = |def_id| cx.tcx.is_diagnostic_item(sym::type_ir_inherent, def_id);
+        let is_mod_inherent = |res: Res| {
+            res.opt_def_id()
+                .is_some_and(|def_id| cx.tcx.is_diagnostic_item(sym::type_ir_inherent, def_id))
+        };
 
         // Path segments except for the final.
-        if let Some(seg) =
-            path.segments.iter().find(|seg| seg.res.opt_def_id().is_some_and(is_mod_inherent))
-        {
+        if let Some(seg) = path.segments.iter().find(|seg| is_mod_inherent(seg.res)) {
             cx.emit_span_lint(USAGE_OF_TYPE_IR_INHERENT, seg.ident.span, TypeIrInherentUsage);
         }
         // Final path resolutions, like `use rustc_type_ir::inherent`
-        else if path.res.iter().any(|res| res.opt_def_id().is_some_and(is_mod_inherent)) {
+        else if let Some(type_ns) = path.res.type_ns
+            && is_mod_inherent(type_ns)
+        {
             cx.emit_span_lint(
                 USAGE_OF_TYPE_IR_INHERENT,
                 path.segments.last().unwrap().ident.span,
@@ -346,13 +349,12 @@ impl<'tcx> LateLintPass<'tcx> for TypeIr {
         }
 
         let (lo, hi, snippet) = match path.segments {
-            [.., penultimate, segment]
-                if penultimate.res.opt_def_id().is_some_and(is_mod_inherent) =>
-            {
+            [.., penultimate, segment] if is_mod_inherent(penultimate.res) => {
                 (segment.ident.span, item.kind.ident().unwrap().span, "*")
             }
             [.., segment]
-                if path.res.iter().flat_map(Res::opt_def_id).any(is_mod_inherent)
+                if let Some(type_ns) = path.res.type_ns
+                    && is_mod_inherent(type_ns)
                     && let rustc_hir::UseKind::Single(ident) = kind =>
             {
                 let (lo, snippet) =
diff --git a/compiler/rustc_lint/src/levels.rs b/compiler/rustc_lint/src/levels.rs
index 00775647ac6..c52dbd892bf 100644
--- a/compiler/rustc_lint/src/levels.rs
+++ b/compiler/rustc_lint/src/levels.rs
@@ -126,7 +126,7 @@ fn lints_that_dont_need_to_run(tcx: TyCtxt<'_>, (): ()) -> UnordSet<LintId> {
         .filter(|lint| {
             // Lints that show up in future-compat reports must always be run.
             let has_future_breakage =
-                lint.future_incompatible.is_some_and(|fut| fut.reason.has_future_breakage());
+                lint.future_incompatible.is_some_and(|fut| fut.report_in_deps);
             !has_future_breakage && !lint.eval_always
         })
         .filter(|lint| {
diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs
index 4ff586a79a6..0a52e42e442 100644
--- a/compiler/rustc_lint/src/lib.rs
+++ b/compiler/rustc_lint/src/lib.rs
@@ -48,7 +48,6 @@ mod errors;
 mod expect;
 mod for_loops_over_fallibles;
 mod foreign_modules;
-pub mod hidden_unicode_codepoints;
 mod if_let_rescope;
 mod impl_trait_overcaptures;
 mod internal;
@@ -75,6 +74,7 @@ mod reference_casting;
 mod shadowed_into_iter;
 mod static_mut_refs;
 mod traits;
+mod transmute;
 mod types;
 mod unit_bindings;
 mod unqualified_local_imports;
@@ -91,7 +91,6 @@ use deref_into_dyn_supertrait::*;
 use drop_forget_useless::*;
 use enum_intrinsics_non_enums::EnumIntrinsicsNonEnums;
 use for_loops_over_fallibles::*;
-use hidden_unicode_codepoints::*;
 use if_let_rescope::IfLetRescope;
 use impl_trait_overcaptures::ImplTraitOvercaptures;
 use internal::*;
@@ -118,6 +117,7 @@ use shadowed_into_iter::ShadowedIntoIter;
 pub use shadowed_into_iter::{ARRAY_INTO_ITER, BOXED_SLICE_INTO_ITER};
 use static_mut_refs::*;
 use traits::*;
+use transmute::CheckTransmutes;
 use types::*;
 use unit_bindings::*;
 use unqualified_local_imports::*;
@@ -126,6 +126,7 @@ use unused::*;
 #[rustfmt::skip]
 pub use builtin::{MissingDoc, SoftLints};
 pub use context::{CheckLintNameResult, EarlyContext, LateContext, LintContext, LintStore};
+pub use early::diagnostics::decorate_builtin_lint;
 pub use early::{EarlyCheckNode, check_ast_node};
 pub use late::{check_crate, late_lint_mod, unerased_lint_store};
 pub use levels::LintLevelsBuilder;
@@ -174,7 +175,6 @@ early_lint_methods!(
             DeprecatedAttr: DeprecatedAttr::default(),
             WhileTrue: WhileTrue,
             NonAsciiIdents: NonAsciiIdents,
-            HiddenUnicodeCodepoints: HiddenUnicodeCodepoints,
             IncompleteInternalFeatures: IncompleteInternalFeatures,
             RedundantSemicolons: RedundantSemicolons,
             UnusedDocComment: UnusedDocComment,
@@ -245,6 +245,7 @@ late_lint_methods!(
             IfLetRescope: IfLetRescope::default(),
             StaticMutRefs: StaticMutRefs,
             UnqualifiedLocalImports: UnqualifiedLocalImports,
+            CheckTransmutes: CheckTransmutes,
         ]
     ]
 );
diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs
index af8fa8ffa1f..10d0e2c93a8 100644
--- a/compiler/rustc_lint/src/lints.rs
+++ b/compiler/rustc_lint/src/lints.rs
@@ -1782,13 +1782,20 @@ pub(crate) enum InvalidNanComparisonsSuggestion {
 #[derive(LintDiagnostic)]
 pub(crate) enum AmbiguousWidePointerComparisons<'a> {
     #[diag(lint_ambiguous_wide_pointer_comparisons)]
-    Spanful {
+    SpanfulEq {
         #[subdiagnostic]
         addr_suggestion: AmbiguousWidePointerComparisonsAddrSuggestion<'a>,
         #[subdiagnostic]
         addr_metadata_suggestion: Option<AmbiguousWidePointerComparisonsAddrMetadataSuggestion<'a>>,
     },
     #[diag(lint_ambiguous_wide_pointer_comparisons)]
+    SpanfulCmp {
+        #[subdiagnostic]
+        cast_suggestion: AmbiguousWidePointerComparisonsCastSuggestion<'a>,
+        #[subdiagnostic]
+        expect_suggestion: AmbiguousWidePointerComparisonsExpectSuggestion<'a>,
+    },
+    #[diag(lint_ambiguous_wide_pointer_comparisons)]
     #[help(lint_addr_metadata_suggestion)]
     #[help(lint_addr_suggestion)]
     Spanless,
@@ -1816,48 +1823,67 @@ pub(crate) struct AmbiguousWidePointerComparisonsAddrMetadataSuggestion<'a> {
 }
 
 #[derive(Subdiagnostic)]
-pub(crate) enum AmbiguousWidePointerComparisonsAddrSuggestion<'a> {
-    #[multipart_suggestion(
-        lint_addr_suggestion,
-        style = "verbose",
-        // FIXME(#53934): make machine-applicable again
-        applicability = "maybe-incorrect"
-    )]
-    AddrEq {
-        ne: &'a str,
-        deref_left: &'a str,
-        deref_right: &'a str,
-        l_modifiers: &'a str,
-        r_modifiers: &'a str,
-        #[suggestion_part(code = "{ne}std::ptr::addr_eq({deref_left}")]
-        left: Span,
-        #[suggestion_part(code = "{l_modifiers}, {deref_right}")]
-        middle: Span,
-        #[suggestion_part(code = "{r_modifiers})")]
-        right: Span,
-    },
-    #[multipart_suggestion(
-        lint_addr_suggestion,
-        style = "verbose",
-        // FIXME(#53934): make machine-applicable again
-        applicability = "maybe-incorrect"
+#[multipart_suggestion(
+    lint_addr_suggestion,
+    style = "verbose",
+    // FIXME(#53934): make machine-applicable again
+    applicability = "maybe-incorrect"
+)]
+pub(crate) struct AmbiguousWidePointerComparisonsAddrSuggestion<'a> {
+    pub(crate) ne: &'a str,
+    pub(crate) deref_left: &'a str,
+    pub(crate) deref_right: &'a str,
+    pub(crate) l_modifiers: &'a str,
+    pub(crate) r_modifiers: &'a str,
+    #[suggestion_part(code = "{ne}std::ptr::addr_eq({deref_left}")]
+    pub(crate) left: Span,
+    #[suggestion_part(code = "{l_modifiers}, {deref_right}")]
+    pub(crate) middle: Span,
+    #[suggestion_part(code = "{r_modifiers})")]
+    pub(crate) right: Span,
+}
+
+#[derive(Subdiagnostic)]
+#[multipart_suggestion(
+    lint_cast_suggestion,
+    style = "verbose",
+    // FIXME(#53934): make machine-applicable again
+    applicability = "maybe-incorrect"
+)]
+pub(crate) struct AmbiguousWidePointerComparisonsCastSuggestion<'a> {
+    pub(crate) deref_left: &'a str,
+    pub(crate) deref_right: &'a str,
+    pub(crate) paren_left: &'a str,
+    pub(crate) paren_right: &'a str,
+    pub(crate) l_modifiers: &'a str,
+    pub(crate) r_modifiers: &'a str,
+    #[suggestion_part(code = "({deref_left}")]
+    pub(crate) left_before: Option<Span>,
+    #[suggestion_part(code = "{l_modifiers}{paren_left}.cast::<()>()")]
+    pub(crate) left_after: Span,
+    #[suggestion_part(code = "({deref_right}")]
+    pub(crate) right_before: Option<Span>,
+    #[suggestion_part(code = "{r_modifiers}{paren_right}.cast::<()>()")]
+    pub(crate) right_after: Span,
+}
+
+#[derive(Subdiagnostic)]
+#[multipart_suggestion(
+    lint_expect_suggestion,
+    style = "verbose",
+    // FIXME(#53934): make machine-applicable again
+    applicability = "maybe-incorrect"
+)]
+pub(crate) struct AmbiguousWidePointerComparisonsExpectSuggestion<'a> {
+    pub(crate) paren_left: &'a str,
+    pub(crate) paren_right: &'a str,
+    // FIXME(#127436): Adjust once resolved
+    #[suggestion_part(
+        code = r#"{{ #[expect(ambiguous_wide_pointer_comparisons, reason = "...")] {paren_left}"#
     )]
-    Cast {
-        deref_left: &'a str,
-        deref_right: &'a str,
-        paren_left: &'a str,
-        paren_right: &'a str,
-        l_modifiers: &'a str,
-        r_modifiers: &'a str,
-        #[suggestion_part(code = "({deref_left}")]
-        left_before: Option<Span>,
-        #[suggestion_part(code = "{l_modifiers}{paren_left}.cast::<()>()")]
-        left_after: Span,
-        #[suggestion_part(code = "({deref_right}")]
-        right_before: Option<Span>,
-        #[suggestion_part(code = "{r_modifiers}{paren_right}.cast::<()>()")]
-        right_after: Span,
-    },
+    pub(crate) before: Span,
+    #[suggestion_part(code = "{paren_right} }}")]
+    pub(crate) after: Span,
 }
 
 #[derive(LintDiagnostic)]
@@ -3051,7 +3077,9 @@ pub(crate) struct ByteSliceInPackedStructWithDerive {
 #[derive(LintDiagnostic)]
 #[diag(lint_unused_extern_crate)]
 pub(crate) struct UnusedExternCrate {
-    #[suggestion(code = "", applicability = "machine-applicable")]
+    #[label]
+    pub span: Span,
+    #[suggestion(code = "", applicability = "machine-applicable", style = "verbose")]
     pub removal_span: Span,
 }
 
diff --git a/compiler/rustc_lint/src/non_local_def.rs b/compiler/rustc_lint/src/non_local_def.rs
index 9ed11d9cc82..b877f909fc0 100644
--- a/compiler/rustc_lint/src/non_local_def.rs
+++ b/compiler/rustc_lint/src/non_local_def.rs
@@ -183,7 +183,7 @@ impl<'tcx> LateLintPass<'tcx> for NonLocalDefinitions {
                     && parent_opt_item_name != Some(kw::Underscore)
                     && let Some(parent) = parent.as_local()
                     && let Node::Item(item) = cx.tcx.hir_node_by_def_id(parent)
-                    && let ItemKind::Const(ident, ty, _, _) = item.kind
+                    && let ItemKind::Const(ident, _, ty, _) = item.kind
                     && let TyKind::Tup(&[]) = ty.kind
                 {
                     Some(ident.span)
diff --git a/compiler/rustc_lint/src/nonstandard_style.rs b/compiler/rustc_lint/src/nonstandard_style.rs
index 048d377b78f..31c18074466 100644
--- a/compiler/rustc_lint/src/nonstandard_style.rs
+++ b/compiler/rustc_lint/src/nonstandard_style.rs
@@ -513,7 +513,7 @@ impl<'tcx> LateLintPass<'tcx> for NonUpperCaseGlobals {
     fn check_item(&mut self, cx: &LateContext<'_>, it: &hir::Item<'_>) {
         let attrs = cx.tcx.hir_attrs(it.hir_id());
         match it.kind {
-            hir::ItemKind::Static(ident, ..)
+            hir::ItemKind::Static(_, ident, ..)
                 if !ast::attr::contains_name(attrs, sym::no_mangle) =>
             {
                 NonUpperCaseGlobals::check_upper_case(cx, "static variable", &ident);
diff --git a/compiler/rustc_lint/src/transmute.rs b/compiler/rustc_lint/src/transmute.rs
new file mode 100644
index 00000000000..bc1d4587d07
--- /dev/null
+++ b/compiler/rustc_lint/src/transmute.rs
@@ -0,0 +1,278 @@
+use rustc_errors::Applicability;
+use rustc_hir::def::{DefKind, Res};
+use rustc_hir::def_id::LocalDefId;
+use rustc_hir::{self as hir};
+use rustc_macros::LintDiagnostic;
+use rustc_middle::ty::{self, Ty};
+use rustc_session::{declare_lint, impl_lint_pass};
+use rustc_span::sym;
+
+use crate::{LateContext, LateLintPass};
+
+declare_lint! {
+    /// The `ptr_to_integer_transmute_in_consts` lint detects pointer to integer
+    /// transmute in const functions and associated constants.
+    ///
+    /// ### Example
+    ///
+    /// ```rust
+    /// const fn foo(ptr: *const u8) -> usize {
+    ///    unsafe {
+    ///        std::mem::transmute::<*const u8, usize>(ptr)
+    ///    }
+    /// }
+    /// ```
+    ///
+    /// {{produces}}
+    ///
+    /// ### Explanation
+    ///
+    /// Transmuting pointers to integers in a `const` context is undefined behavior.
+    /// Any attempt to use the resulting integer will abort const-evaluation.
+    ///
+    /// But sometimes the compiler might not emit an error for pointer to integer transmutes
+    /// inside const functions and associated consts because they are evaluated only when referenced.
+    /// Therefore, this lint serves as an extra layer of defense to prevent any undefined behavior
+    /// from compiling without any warnings or errors.
+    ///
+    /// See [std::mem::transmute] in the reference for more details.
+    ///
+    /// [std::mem::transmute]: https://doc.rust-lang.org/std/mem/fn.transmute.html
+    pub PTR_TO_INTEGER_TRANSMUTE_IN_CONSTS,
+    Warn,
+    "detects pointer to integer transmutes in const functions and associated constants",
+}
+
+declare_lint! {
+    /// The `unnecessary_transmutes` lint detects transmutations that have safer alternatives.
+    ///
+    /// ### Example
+    ///
+    /// ```rust
+    /// fn bytes_at_home(x: [u8; 4]) -> u32 {
+    ///   unsafe { std::mem::transmute(x) }
+    /// }
+    /// ```
+    ///
+    /// {{produces}}
+    ///
+    /// ### Explanation
+    ///
+    /// Using an explicit method is preferable over calls to
+    /// [`transmute`](https://doc.rust-lang.org/std/mem/fn.transmute.html) as
+    /// they more clearly communicate the intent, are easier to review, and
+    /// are less likely to accidentally result in unsoundness.
+    pub UNNECESSARY_TRANSMUTES,
+    Warn,
+    "detects transmutes that can also be achieved by other operations"
+}
+
+pub(crate) struct CheckTransmutes;
+
+impl_lint_pass!(CheckTransmutes => [PTR_TO_INTEGER_TRANSMUTE_IN_CONSTS, UNNECESSARY_TRANSMUTES]);
+
+impl<'tcx> LateLintPass<'tcx> for CheckTransmutes {
+    fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'tcx>) {
+        let hir::ExprKind::Call(callee, [arg]) = expr.kind else {
+            return;
+        };
+        let hir::ExprKind::Path(qpath) = callee.kind else {
+            return;
+        };
+        let Res::Def(DefKind::Fn, def_id) = cx.qpath_res(&qpath, callee.hir_id) else {
+            return;
+        };
+        if !cx.tcx.is_intrinsic(def_id, sym::transmute) {
+            return;
+        };
+        let body_owner_def_id = cx.tcx.hir_enclosing_body_owner(expr.hir_id);
+        let const_context = cx.tcx.hir_body_const_context(body_owner_def_id);
+        let args = cx.typeck_results().node_args(callee.hir_id);
+
+        let src = args.type_at(0);
+        let dst = args.type_at(1);
+
+        check_ptr_transmute_in_const(cx, expr, body_owner_def_id, const_context, src, dst);
+        check_unnecessary_transmute(cx, expr, callee, arg, const_context, src, dst);
+    }
+}
+
+/// Check for transmutes that exhibit undefined behavior.
+/// For example, transmuting pointers to integers in a const context.
+///
+/// Why do we consider const functions and associated constants only?
+///
+/// Generally, undefined behavior in const items are handled by the evaluator.
+/// But, const functions and associated constants are evaluated only when referenced.
+/// This can result in undefined behavior in a library going unnoticed until
+/// the function or constant is actually used.
+///
+/// Therefore, we only consider const functions and associated constants here and leave
+/// other const items to be handled by the evaluator.
+fn check_ptr_transmute_in_const<'tcx>(
+    cx: &LateContext<'tcx>,
+    expr: &'tcx hir::Expr<'tcx>,
+    body_owner_def_id: LocalDefId,
+    const_context: Option<hir::ConstContext>,
+    src: Ty<'tcx>,
+    dst: Ty<'tcx>,
+) {
+    if matches!(const_context, Some(hir::ConstContext::ConstFn))
+        || matches!(cx.tcx.def_kind(body_owner_def_id), DefKind::AssocConst)
+    {
+        if src.is_raw_ptr() && dst.is_integral() {
+            cx.tcx.emit_node_span_lint(
+                PTR_TO_INTEGER_TRANSMUTE_IN_CONSTS,
+                expr.hir_id,
+                expr.span,
+                UndefinedTransmuteLint,
+            );
+        }
+    }
+}
+
+/// Check for transmutes that overlap with stdlib methods.
+/// For example, transmuting `[u8; 4]` to `u32`.
+///
+/// We chose not to lint u8 -> bool transmutes, see #140431.
+fn check_unnecessary_transmute<'tcx>(
+    cx: &LateContext<'tcx>,
+    expr: &'tcx hir::Expr<'tcx>,
+    callee: &'tcx hir::Expr<'tcx>,
+    arg: &'tcx hir::Expr<'tcx>,
+    const_context: Option<hir::ConstContext>,
+    src: Ty<'tcx>,
+    dst: Ty<'tcx>,
+) {
+    let callee_span = callee.span.find_ancestor_inside(expr.span).unwrap_or(callee.span);
+    let (sugg, help) = match (src.kind(), dst.kind()) {
+        // dont check the length; transmute does that for us.
+        // [u8; _] => primitive
+        (ty::Array(t, _), ty::Uint(_) | ty::Float(_) | ty::Int(_))
+            if *t.kind() == ty::Uint(ty::UintTy::U8) =>
+        {
+            (
+                Some(vec![(callee_span, format!("{dst}::from_ne_bytes"))]),
+                Some(
+                    "there's also `from_le_bytes` and `from_be_bytes` if you expect a particular byte order",
+                ),
+            )
+        }
+        // primitive => [u8; _]
+        (ty::Uint(_) | ty::Float(_) | ty::Int(_), ty::Array(t, _))
+            if *t.kind() == ty::Uint(ty::UintTy::U8) =>
+        {
+            (
+                Some(vec![(callee_span, format!("{src}::to_ne_bytes"))]),
+                Some(
+                    "there's also `to_le_bytes` and `to_be_bytes` if you expect a particular byte order",
+                ),
+            )
+        }
+        // char → u32
+        (ty::Char, ty::Uint(ty::UintTy::U32)) => {
+            (Some(vec![(callee_span, "u32::from".to_string())]), None)
+        }
+        // char (→ u32) → i32
+        (ty::Char, ty::Int(ty::IntTy::I32)) => (
+            Some(vec![
+                (callee_span, "u32::from".to_string()),
+                (expr.span.shrink_to_hi(), ".cast_signed()".to_string()),
+            ]),
+            None,
+        ),
+        // u32 → char
+        (ty::Uint(ty::UintTy::U32), ty::Char) => (
+            Some(vec![(callee_span, "char::from_u32_unchecked".to_string())]),
+            Some("consider using `char::from_u32(…).unwrap()`"),
+        ),
+        // i32 → char
+        (ty::Int(ty::IntTy::I32), ty::Char) => (
+            Some(vec![
+                (callee_span, "char::from_u32_unchecked(i32::cast_unsigned".to_string()),
+                (expr.span.shrink_to_hi(), ")".to_string()),
+            ]),
+            Some("consider using `char::from_u32(i32::cast_unsigned(…)).unwrap()`"),
+        ),
+        // uNN → iNN
+        (ty::Uint(_), ty::Int(_)) => {
+            (Some(vec![(callee_span, format!("{src}::cast_signed"))]), None)
+        }
+        // iNN → uNN
+        (ty::Int(_), ty::Uint(_)) => {
+            (Some(vec![(callee_span, format!("{src}::cast_unsigned"))]), None)
+        }
+        // fNN → usize, isize
+        (ty::Float(_), ty::Uint(ty::UintTy::Usize) | ty::Int(ty::IntTy::Isize)) => (
+            Some(vec![
+                (callee_span, format!("{src}::to_bits")),
+                (expr.span.shrink_to_hi(), format!(" as {dst}")),
+            ]),
+            None,
+        ),
+        // fNN (→ uNN) → iNN
+        (ty::Float(_), ty::Int(..)) => (
+            Some(vec![
+                (callee_span, format!("{src}::to_bits")),
+                (expr.span.shrink_to_hi(), ".cast_signed()".to_string()),
+            ]),
+            None,
+        ),
+        // fNN → uNN
+        (ty::Float(_), ty::Uint(..)) => {
+            (Some(vec![(callee_span, format!("{src}::to_bits"))]), None)
+        }
+        // xsize → fNN
+        (ty::Uint(ty::UintTy::Usize) | ty::Int(ty::IntTy::Isize), ty::Float(_)) => (
+            Some(vec![
+                (callee_span, format!("{dst}::from_bits")),
+                (arg.span.shrink_to_hi(), " as _".to_string()),
+            ]),
+            None,
+        ),
+        // iNN (→ uNN) → fNN
+        (ty::Int(_), ty::Float(_)) => (
+            Some(vec![
+                (callee_span, format!("{dst}::from_bits({src}::cast_unsigned")),
+                (expr.span.shrink_to_hi(), ")".to_string()),
+            ]),
+            None,
+        ),
+        // uNN → fNN
+        (ty::Uint(_), ty::Float(_)) => {
+            (Some(vec![(callee_span, format!("{dst}::from_bits"))]), None)
+        }
+        // bool → x8 in const context since `From::from` is not const yet
+        // FIXME: Consider arg expr's precedence to avoid parentheses.
+        // FIXME(const_traits): Remove this when `From::from` is constified.
+        (ty::Bool, ty::Int(..) | ty::Uint(..)) if const_context.is_some() => (
+            Some(vec![
+                (callee_span, "".to_string()),
+                (expr.span.shrink_to_hi(), format!(" as {dst}")),
+            ]),
+            None,
+        ),
+        // bool → x8 using `x8::from`
+        (ty::Bool, ty::Int(..) | ty::Uint(..)) => {
+            (Some(vec![(callee_span, format!("{dst}::from"))]), None)
+        }
+        _ => return,
+    };
+
+    cx.tcx.node_span_lint(UNNECESSARY_TRANSMUTES, expr.hir_id, expr.span, |diag| {
+        diag.primary_message("unnecessary transmute");
+        if let Some(sugg) = sugg {
+            diag.multipart_suggestion("replace this with", sugg, Applicability::MachineApplicable);
+        }
+        if let Some(help) = help {
+            diag.help(help);
+        }
+    });
+}
+
+#[derive(LintDiagnostic)]
+#[diag(lint_undefined_transmute)]
+#[note]
+#[note(lint_note2)]
+#[help]
+pub(crate) struct UndefinedTransmuteLint;
diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs
index f1c06dfe6ce..77dc6335113 100644
--- a/compiler/rustc_lint/src/types.rs
+++ b/compiler/rustc_lint/src/types.rs
@@ -24,7 +24,8 @@ mod improper_ctypes;
 
 use crate::lints::{
     AmbiguousWidePointerComparisons, AmbiguousWidePointerComparisonsAddrMetadataSuggestion,
-    AmbiguousWidePointerComparisonsAddrSuggestion, AtomicOrderingFence, AtomicOrderingLoad,
+    AmbiguousWidePointerComparisonsAddrSuggestion, AmbiguousWidePointerComparisonsCastSuggestion,
+    AmbiguousWidePointerComparisonsExpectSuggestion, AtomicOrderingFence, AtomicOrderingLoad,
     AtomicOrderingStore, ImproperCTypes, InvalidAtomicOrderingDiag, InvalidNanComparisons,
     InvalidNanComparisonsSuggestion, UnpredictableFunctionPointerComparisons,
     UnpredictableFunctionPointerComparisonsSuggestion, UnusedComparisons, UsesPowerAlignment,
@@ -362,6 +363,7 @@ fn lint_wide_pointer<'tcx>(
     let ne = if cmpop == ComparisonOp::BinOp(hir::BinOpKind::Ne) { "!" } else { "" };
     let is_eq_ne = matches!(cmpop, ComparisonOp::BinOp(hir::BinOpKind::Eq | hir::BinOpKind::Ne));
     let is_dyn_comparison = l_inner_ty_is_dyn && r_inner_ty_is_dyn;
+    let via_method_call = matches!(&e.kind, ExprKind::MethodCall(..) | ExprKind::Call(..));
 
     let left = e.span.shrink_to_lo().until(l_span.shrink_to_lo());
     let middle = l_span.shrink_to_hi().until(r_span.shrink_to_lo());
@@ -376,21 +378,21 @@ fn lint_wide_pointer<'tcx>(
     cx.emit_span_lint(
         AMBIGUOUS_WIDE_POINTER_COMPARISONS,
         e.span,
-        AmbiguousWidePointerComparisons::Spanful {
-            addr_metadata_suggestion: (is_eq_ne && !is_dyn_comparison).then(|| {
-                AmbiguousWidePointerComparisonsAddrMetadataSuggestion {
-                    ne,
-                    deref_left,
-                    deref_right,
-                    l_modifiers,
-                    r_modifiers,
-                    left,
-                    middle,
-                    right,
-                }
-            }),
-            addr_suggestion: if is_eq_ne {
-                AmbiguousWidePointerComparisonsAddrSuggestion::AddrEq {
+        if is_eq_ne {
+            AmbiguousWidePointerComparisons::SpanfulEq {
+                addr_metadata_suggestion: (!is_dyn_comparison).then(|| {
+                    AmbiguousWidePointerComparisonsAddrMetadataSuggestion {
+                        ne,
+                        deref_left,
+                        deref_right,
+                        l_modifiers,
+                        r_modifiers,
+                        left,
+                        middle,
+                        right,
+                    }
+                }),
+                addr_suggestion: AmbiguousWidePointerComparisonsAddrSuggestion {
                     ne,
                     deref_left,
                     deref_right,
@@ -399,9 +401,11 @@ fn lint_wide_pointer<'tcx>(
                     left,
                     middle,
                     right,
-                }
-            } else {
-                AmbiguousWidePointerComparisonsAddrSuggestion::Cast {
+                },
+            }
+        } else {
+            AmbiguousWidePointerComparisons::SpanfulCmp {
+                cast_suggestion: AmbiguousWidePointerComparisonsCastSuggestion {
                     deref_left,
                     deref_right,
                     l_modifiers,
@@ -412,8 +416,14 @@ fn lint_wide_pointer<'tcx>(
                     left_after: l_span.shrink_to_hi(),
                     right_before: (r_ty_refs != 0).then_some(r_span.shrink_to_lo()),
                     right_after: r_span.shrink_to_hi(),
-                }
-            },
+                },
+                expect_suggestion: AmbiguousWidePointerComparisonsExpectSuggestion {
+                    paren_left: if via_method_call { "" } else { "(" },
+                    paren_right: if via_method_call { "" } else { ")" },
+                    before: e.span.shrink_to_lo(),
+                    after: e.span.shrink_to_hi(),
+                },
+            }
         },
     );
 }
@@ -1700,7 +1710,7 @@ impl ImproperCTypesDefinitions {
             && cx.tcx.sess.target.os == "aix"
             && !adt_def.all_fields().next().is_none()
         {
-            let struct_variant_data = item.expect_struct().1;
+            let struct_variant_data = item.expect_struct().2;
             for field_def in struct_variant_data.fields().iter().skip(1) {
                 // Struct fields (after the first field) are checked for the
                 // power alignment rule, as fields after the first are likely
@@ -1725,9 +1735,9 @@ impl ImproperCTypesDefinitions {
 impl<'tcx> LateLintPass<'tcx> for ImproperCTypesDefinitions {
     fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'tcx>) {
         match item.kind {
-            hir::ItemKind::Static(_, ty, ..)
-            | hir::ItemKind::Const(_, ty, ..)
-            | hir::ItemKind::TyAlias(_, ty, ..) => {
+            hir::ItemKind::Static(_, _, ty, _)
+            | hir::ItemKind::Const(_, _, ty, _)
+            | hir::ItemKind::TyAlias(_, _, ty) => {
                 self.check_ty_maybe_containing_foreign_fnptr(
                     cx,
                     ty,
@@ -1794,7 +1804,7 @@ declare_lint_pass!(VariantSizeDifferences => [VARIANT_SIZE_DIFFERENCES]);
 
 impl<'tcx> LateLintPass<'tcx> for VariantSizeDifferences {
     fn check_item(&mut self, cx: &LateContext<'_>, it: &hir::Item<'_>) {
-        if let hir::ItemKind::Enum(_, ref enum_definition, _) = it.kind {
+        if let hir::ItemKind::Enum(_, _, ref enum_definition) = it.kind {
             let t = cx.tcx.type_of(it.owner_id).instantiate_identity();
             let ty = cx.tcx.erase_regions(t);
             let Ok(layout) = cx.layout_of(ty) else { return };
diff --git a/compiler/rustc_lint/src/unqualified_local_imports.rs b/compiler/rustc_lint/src/unqualified_local_imports.rs
index 50c5119285f..0076cae3cff 100644
--- a/compiler/rustc_lint/src/unqualified_local_imports.rs
+++ b/compiler/rustc_lint/src/unqualified_local_imports.rs
@@ -1,4 +1,3 @@
-use rustc_hir::def::{DefKind, Res};
 use rustc_hir::{self as hir};
 use rustc_session::{declare_lint, declare_lint_pass};
 use rustc_span::kw;
@@ -47,17 +46,15 @@ declare_lint_pass!(UnqualifiedLocalImports => [UNQUALIFIED_LOCAL_IMPORTS]);
 impl<'tcx> LateLintPass<'tcx> for UnqualifiedLocalImports {
     fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'tcx>) {
         let hir::ItemKind::Use(path, _kind) = item.kind else { return };
-        // `path` has three resolutions for the type, module, value namespaces.
-        // Check if any of them qualifies: local crate, and not a macro.
-        // (Macros can't be imported any other way so we don't complain about them.)
-        let is_local_import = |res: &Res| {
-            matches!(
-                res,
-                hir::def::Res::Def(def_kind, def_id)
-                    if def_id.is_local() && !matches!(def_kind, DefKind::Macro(_)),
-            )
-        };
-        if !path.res.iter().any(is_local_import) {
+        // Check the type and value namespace resolutions for a local crate.
+        let is_local_import = matches!(
+            path.res.type_ns,
+            Some(hir::def::Res::Def(_, def_id)) if def_id.is_local()
+        ) || matches!(
+            path.res.value_ns,
+            Some(hir::def::Res::Def(_, def_id)) if def_id.is_local()
+        );
+        if !is_local_import {
             return;
         }
         // So this does refer to something local. Let's check whether it starts with `self`,
diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs
index 50a27d7e84f..1620f425794 100644
--- a/compiler/rustc_lint/src/unused.rs
+++ b/compiler/rustc_lint/src/unused.rs
@@ -1,8 +1,7 @@
 use std::iter;
 
-use rustc_ast as ast;
 use rustc_ast::util::{classify, parser};
-use rustc_ast::{ExprKind, StmtKind};
+use rustc_ast::{self as ast, ExprKind, HasAttrs as _, StmtKind};
 use rustc_errors::{MultiSpan, pluralize};
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::DefId;
@@ -780,26 +779,30 @@ trait UnusedDelimLint {
         right_pos: Option<BytePos>,
         is_kw: bool,
     ) {
-        let spans = match value.kind {
-            ast::ExprKind::Block(ref block, None) if let [stmt] = block.stmts.as_slice() => stmt
-                .span
-                .find_ancestor_inside(value.span)
-                .map(|span| (value.span.with_hi(span.lo()), value.span.with_lo(span.hi()))),
+        let span_with_attrs = match value.kind {
+            ast::ExprKind::Block(ref block, None) if let [stmt] = block.stmts.as_slice() => {
+                // For the statements with attributes, like `{ #[allow()] println!("Hello!") }`,
+                // the span should contains the attributes, or the suggestion will remove them.
+                if let Some(attr_lo) = stmt.attrs().iter().map(|attr| attr.span.lo()).min() {
+                    stmt.span.with_lo(attr_lo)
+                } else {
+                    stmt.span
+                }
+            }
             ast::ExprKind::Paren(ref expr) => {
                 // For the expr with attributes, like `let _ = (#[inline] || println!("Hello!"));`,
                 // the span should contains the attributes, or the suggestion will remove them.
-                let expr_span_with_attrs =
-                    if let Some(attr_lo) = expr.attrs.iter().map(|attr| attr.span.lo()).min() {
-                        expr.span.with_lo(attr_lo)
-                    } else {
-                        expr.span
-                    };
-                expr_span_with_attrs.find_ancestor_inside(value.span).map(|expr_span| {
-                    (value.span.with_hi(expr_span.lo()), value.span.with_lo(expr_span.hi()))
-                })
+                if let Some(attr_lo) = expr.attrs.iter().map(|attr| attr.span.lo()).min() {
+                    expr.span.with_lo(attr_lo)
+                } else {
+                    expr.span
+                }
             }
             _ => return,
         };
+        let spans = span_with_attrs
+            .find_ancestor_inside(value.span)
+            .map(|span| (value.span.with_hi(span.lo()), value.span.with_lo(span.hi())));
         let keep_space = (
             left_pos.is_some_and(|s| s >= value.span.lo()),
             right_pos.is_some_and(|s| s <= value.span.hi()),
diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs
index b8d242bad86..1b14157c5f0 100644
--- a/compiler/rustc_lint_defs/src/builtin.rs
+++ b/compiler/rustc_lint_defs/src/builtin.rs
@@ -79,7 +79,6 @@ declare_lint_pass! {
         PRIVATE_BOUNDS,
         PRIVATE_INTERFACES,
         PROC_MACRO_DERIVE_RESOLUTION_FALLBACK,
-        PTR_TO_INTEGER_TRANSMUTE_IN_CONSTS,
         PUB_USE_OF_PRIVATE_EXTERN_CRATE,
         REDUNDANT_IMPORTS,
         REDUNDANT_LIFETIMES,
@@ -104,6 +103,7 @@ declare_lint_pass! {
         TAIL_EXPR_DROP_ORDER,
         TEST_UNSTABLE_LINT,
         TEXT_DIRECTION_CODEPOINT_IN_COMMENT,
+        TEXT_DIRECTION_CODEPOINT_IN_LITERAL,
         TRIVIAL_CASTS,
         TRIVIAL_NUMERIC_CASTS,
         TYVAR_BEHIND_RAW_POINTER,
@@ -118,7 +118,6 @@ declare_lint_pass! {
         UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES,
         UNNAMEABLE_TEST_ITEMS,
         UNNAMEABLE_TYPES,
-        UNNECESSARY_TRANSMUTES,
         UNREACHABLE_CODE,
         UNREACHABLE_PATTERNS,
         UNSAFE_ATTR_OUTSIDE_UNSAFE,
@@ -179,8 +178,9 @@ declare_lint! {
     Warn,
     "applying forbid to lint-groups",
     @future_incompatible = FutureIncompatibleInfo {
-        reason: FutureIncompatibilityReason::FutureReleaseErrorReportInDeps,
+        reason: FutureIncompatibilityReason::FutureReleaseError,
         reference: "issue #81670 <https://github.com/rust-lang/rust/issues/81670>",
+        report_in_deps: true,
     };
 }
 
@@ -215,7 +215,7 @@ declare_lint! {
     Deny,
     "ill-formed attribute inputs that were previously accepted and used in practice",
     @future_incompatible = FutureIncompatibleInfo {
-        reason: FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps,
+        reason: FutureIncompatibilityReason::FutureReleaseError,
         reference: "issue #57571 <https://github.com/rust-lang/rust/issues/57571>",
     };
     crate_level_only
@@ -252,8 +252,9 @@ declare_lint! {
     Deny,
     "conflicts between `#[repr(..)]` hints that were previously accepted and used in practice",
     @future_incompatible = FutureIncompatibleInfo {
-        reason: FutureIncompatibilityReason::FutureReleaseErrorReportInDeps,
+        reason: FutureIncompatibilityReason::FutureReleaseError,
         reference: "issue #68585 <https://github.com/rust-lang/rust/issues/68585>",
+        report_in_deps: true,
     };
 }
 
@@ -1241,8 +1242,9 @@ declare_lint! {
     Deny,
     "detect public re-exports of private extern crates",
     @future_incompatible = FutureIncompatibleInfo {
-        reason: FutureIncompatibilityReason::FutureReleaseErrorReportInDeps,
+        reason: FutureIncompatibilityReason::FutureReleaseError,
         reference: "issue #127909 <https://github.com/rust-lang/rust/issues/127909>",
+        report_in_deps: true,
     };
 }
 
@@ -1271,8 +1273,9 @@ declare_lint! {
     Deny,
     "type parameter default erroneously allowed in invalid location",
     @future_incompatible = FutureIncompatibleInfo {
-        reason: FutureIncompatibilityReason::FutureReleaseErrorReportInDeps,
+        reason: FutureIncompatibilityReason::FutureReleaseError,
         reference: "issue #36887 <https://github.com/rust-lang/rust/issues/36887>",
+        report_in_deps: true,
     };
 }
 
@@ -1410,7 +1413,7 @@ declare_lint! {
     Deny,
     "patterns in functions without body were erroneously allowed",
     @future_incompatible = FutureIncompatibleInfo {
-        reason: FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps,
+        reason: FutureIncompatibilityReason::FutureReleaseError,
         reference: "issue #35203 <https://github.com/rust-lang/rust/issues/35203>",
     };
 }
@@ -1454,8 +1457,9 @@ declare_lint! {
     Deny,
     "detects missing fragment specifiers in unused `macro_rules!` patterns",
     @future_incompatible = FutureIncompatibleInfo {
-        reason: FutureIncompatibilityReason::FutureReleaseErrorReportInDeps,
+        reason: FutureIncompatibilityReason::FutureReleaseError,
         reference: "issue #40107 <https://github.com/rust-lang/rust/issues/40107>",
+        report_in_deps: true,
     };
 }
 
@@ -1496,7 +1500,7 @@ declare_lint! {
     Warn,
     "detects generic lifetime arguments in path segments with late bound lifetime parameters",
     @future_incompatible = FutureIncompatibleInfo {
-        reason: FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps,
+        reason: FutureIncompatibilityReason::FutureReleaseError,
         reference: "issue #42868 <https://github.com/rust-lang/rust/issues/42868>",
     };
 }
@@ -2123,8 +2127,9 @@ declare_lint! {
     Deny,
     "detects proc macro derives using inaccessible names from parent modules",
     @future_incompatible = FutureIncompatibleInfo {
-        reason: FutureIncompatibilityReason::FutureReleaseErrorReportInDeps,
+        reason: FutureIncompatibilityReason::FutureReleaseError,
         reference: "issue #83583 <https://github.com/rust-lang/rust/issues/83583>",
+        report_in_deps: true,
     };
 }
 
@@ -2226,7 +2231,7 @@ declare_lint! {
     "macro-expanded `macro_export` macros from the current crate \
      cannot be referred to by absolute paths",
     @future_incompatible = FutureIncompatibleInfo {
-        reason: FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps,
+        reason: FutureIncompatibilityReason::FutureReleaseError,
         reference: "issue #52234 <https://github.com/rust-lang/rust/issues/52234>",
     };
     crate_level_only
@@ -2347,7 +2352,7 @@ declare_lint! {
     Deny,
     "ambiguous associated items",
     @future_incompatible = FutureIncompatibleInfo {
-        reason: FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps,
+        reason: FutureIncompatibilityReason::FutureReleaseError,
         reference: "issue #57644 <https://github.com/rust-lang/rust/issues/57644>",
     };
 }
@@ -2363,8 +2368,9 @@ declare_lint! {
     Deny,
     "a feature gate that doesn't break dependent crates",
     @future_incompatible = FutureIncompatibleInfo {
-        reason: FutureIncompatibilityReason::FutureReleaseErrorReportInDeps,
+        reason: FutureIncompatibilityReason::FutureReleaseError,
         reference: "issue #64266 <https://github.com/rust-lang/rust/issues/64266>",
+        report_in_deps: true,
     };
 }
 
@@ -2675,7 +2681,7 @@ declare_lint! {
     Warn,
     "detects a generic constant is used in a type without a emitting a warning",
     @future_incompatible = FutureIncompatibleInfo {
-        reason: FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps,
+        reason: FutureIncompatibilityReason::FutureReleaseError,
         reference: "issue #76200 <https://github.com/rust-lang/rust/issues/76200>",
     };
 }
@@ -2734,7 +2740,7 @@ declare_lint! {
     Warn,
     "uninhabited static",
     @future_incompatible = FutureIncompatibleInfo {
-        reason: FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps,
+        reason: FutureIncompatibilityReason::FutureReleaseError,
         reference: "issue #74840 <https://github.com/rust-lang/rust/issues/74840>",
     };
 }
@@ -2867,7 +2873,7 @@ declare_lint! {
     Warn,
     "detect unsupported use of `Self` from outer item",
     @future_incompatible = FutureIncompatibleInfo {
-        reason: FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps,
+        reason: FutureIncompatibilityReason::FutureReleaseError,
         reference: "issue #124186 <https://github.com/rust-lang/rust/issues/124186>",
     };
 }
@@ -2913,8 +2919,9 @@ declare_lint! {
     Warn,
     "trailing semicolon in macro body used as expression",
     @future_incompatible = FutureIncompatibleInfo {
-        reason: FutureIncompatibilityReason::FutureReleaseErrorReportInDeps,
+        reason: FutureIncompatibilityReason::FutureReleaseError,
         reference: "issue #79813 <https://github.com/rust-lang/rust/issues/79813>",
+        report_in_deps: true,
     };
 }
 
@@ -2960,7 +2967,7 @@ declare_lint! {
     Warn,
     "detects derive helper attributes that are used before they are introduced",
     @future_incompatible = FutureIncompatibleInfo {
-        reason: FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps,
+        reason: FutureIncompatibilityReason::FutureReleaseError,
         reference: "issue #79202 <https://github.com/rust-lang/rust/issues/79202>",
     };
 }
@@ -3127,7 +3134,7 @@ declare_lint! {
     Warn,
     "transparent type contains an external ZST that is marked #[non_exhaustive] or contains private fields",
     @future_incompatible = FutureIncompatibleInfo {
-        reason: FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps,
+        reason: FutureIncompatibilityReason::FutureReleaseError,
         reference: "issue #78586 <https://github.com/rust-lang/rust/issues/78586>",
     };
 }
@@ -3178,7 +3185,7 @@ declare_lint! {
     Warn,
     "unstable syntax can change at any point in the future, causing a hard error!",
     @future_incompatible = FutureIncompatibleInfo {
-        reason: FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps,
+        reason: FutureIncompatibilityReason::FutureReleaseError,
         reference: "issue #65860 <https://github.com/rust-lang/rust/issues/65860>",
     };
 }
@@ -3686,8 +3693,9 @@ declare_lint! {
     Warn,
     "use of unsupported calling convention for function pointer",
     @future_incompatible = FutureIncompatibleInfo {
-        reason: FutureIncompatibilityReason::FutureReleaseErrorReportInDeps,
+        reason: FutureIncompatibilityReason::FutureReleaseError,
         reference: "issue #130260 <https://github.com/rust-lang/rust/issues/130260>",
+        report_in_deps: true,
     };
 }
 
@@ -3784,7 +3792,6 @@ declare_lint! {
 }
 
 declare_lint! {
-    #[allow(text_direction_codepoint_in_literal)]
     /// The `text_direction_codepoint_in_comment` lint detects Unicode codepoints in comments that
     /// change the visual representation of text on screen in a way that does not correspond to
     /// their on memory representation.
@@ -3794,7 +3801,7 @@ declare_lint! {
     /// ```rust,compile_fail
     /// #![deny(text_direction_codepoint_in_comment)]
     /// fn main() {
-    ///     println!("{:?}"); // '‮');
+    #[doc = "    println!(\"{:?}\"); // '\u{202E}');"]
     /// }
     /// ```
     ///
@@ -3809,7 +3816,43 @@ declare_lint! {
     /// their use.
     pub TEXT_DIRECTION_CODEPOINT_IN_COMMENT,
     Deny,
-    "invisible directionality-changing codepoints in comment"
+    "invisible directionality-changing codepoints in comment",
+    crate_level_only
+}
+
+declare_lint! {
+    /// The `text_direction_codepoint_in_literal` lint detects Unicode codepoints that change the
+    /// visual representation of text on screen in a way that does not correspond to their on
+    /// memory representation.
+    ///
+    /// ### Explanation
+    ///
+    /// The unicode characters `\u{202A}`, `\u{202B}`, `\u{202D}`, `\u{202E}`, `\u{2066}`,
+    /// `\u{2067}`, `\u{2068}`, `\u{202C}` and `\u{2069}` make the flow of text on screen change
+    /// its direction on software that supports these codepoints. This makes the text "abc" display
+    /// as "cba" on screen. By leveraging software that supports these, people can write specially
+    /// crafted literals that make the surrounding code seem like it's performing one action, when
+    /// in reality it is performing another. Because of this, we proactively lint against their
+    /// presence to avoid surprises.
+    ///
+    /// ### Example
+    ///
+    /// ```rust,compile_fail
+    /// #![deny(text_direction_codepoint_in_literal)]
+    /// fn main() {
+    // ` - convince tidy that backticks match
+    #[doc = "    println!(\"{:?}\", '\u{202E}');"]
+    // `
+    /// }
+    /// ```
+    ///
+    /// {{produces}}
+    ///
+    pub TEXT_DIRECTION_CODEPOINT_IN_LITERAL,
+    Deny,
+    "detect special Unicode codepoints that affect the visual representation of text on screen, \
+     changing the direction in which text flows",
+    crate_level_only
 }
 
 declare_lint! {
@@ -4334,7 +4377,7 @@ declare_lint! {
     Warn,
     "detects certain glob imports that require reporting an ambiguity error",
     @future_incompatible = FutureIncompatibleInfo {
-        reason: FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps,
+        reason: FutureIncompatibilityReason::FutureReleaseError,
         reference: "issue #114095 <https://github.com/rust-lang/rust/issues/114095>",
     };
 }
@@ -4489,7 +4532,7 @@ declare_lint! {
     Deny,
     "elided lifetimes cannot be used in associated constants in impls",
     @future_incompatible = FutureIncompatibleInfo {
-        reason: FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps,
+        reason: FutureIncompatibilityReason::FutureReleaseError,
         reference: "issue #115010 <https://github.com/rust-lang/rust/issues/115010>",
     };
 }
@@ -4536,7 +4579,7 @@ declare_lint! {
     Warn,
     "detects certain macro bindings that should not be re-exported",
     @future_incompatible = FutureIncompatibleInfo {
-        reason: FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps,
+        reason: FutureIncompatibilityReason::FutureReleaseError,
         reference: "issue #120192 <https://github.com/rust-lang/rust/issues/120192>",
     };
 }
@@ -4601,7 +4644,7 @@ declare_lint! {
     Warn,
     "impl contains type parameters that are not covered",
     @future_incompatible = FutureIncompatibleInfo {
-        reason: FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps,
+        reason: FutureIncompatibilityReason::FutureReleaseError,
         reference: "issue #124559 <https://github.com/rust-lang/rust/issues/124559>",
     };
 }
@@ -4765,7 +4808,7 @@ declare_lint! {
     Warn,
     "detects out of scope calls to `macro_rules` in key-value attributes",
     @future_incompatible = FutureIncompatibleInfo {
-        reason: FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps,
+        reason: FutureIncompatibilityReason::FutureReleaseError,
         reference: "issue #124535 <https://github.com/rust-lang/rust/issues/124535>",
     };
 }
@@ -4852,64 +4895,6 @@ declare_lint! {
 }
 
 declare_lint! {
-    /// The `ptr_to_integer_transmute_in_consts` lint detects pointer to integer
-    /// transmute in const functions and associated constants.
-    ///
-    /// ### Example
-    ///
-    /// ```rust
-    /// const fn foo(ptr: *const u8) -> usize {
-    ///    unsafe {
-    ///        std::mem::transmute::<*const u8, usize>(ptr)
-    ///    }
-    /// }
-    /// ```
-    ///
-    /// {{produces}}
-    ///
-    /// ### Explanation
-    ///
-    /// Transmuting pointers to integers in a `const` context is undefined behavior.
-    /// Any attempt to use the resulting integer will abort const-evaluation.
-    ///
-    /// But sometimes the compiler might not emit an error for pointer to integer transmutes
-    /// inside const functions and associated consts because they are evaluated only when referenced.
-    /// Therefore, this lint serves as an extra layer of defense to prevent any undefined behavior
-    /// from compiling without any warnings or errors.
-    ///
-    /// See [std::mem::transmute] in the reference for more details.
-    ///
-    /// [std::mem::transmute]: https://doc.rust-lang.org/std/mem/fn.transmute.html
-    pub PTR_TO_INTEGER_TRANSMUTE_IN_CONSTS,
-    Warn,
-    "detects pointer to integer transmutes in const functions and associated constants",
-}
-
-declare_lint! {
-    /// The `unnecessary_transmutes` lint detects transmutations that have safer alternatives.
-    ///
-    /// ### Example
-    ///
-    /// ```rust
-    /// fn bytes_at_home(x: [u8; 4]) -> u32 {
-    ///   unsafe { std::mem::transmute(x) }
-    /// }
-    /// ```
-    ///
-    /// {{produces}}
-    ///
-    /// ### Explanation
-    ///
-    /// Using an explicit method is preferable over calls to
-    /// [`transmute`](https://doc.rust-lang.org/std/mem/fn.transmute.html) as
-    /// they more clearly communicate the intent, are easier to review, and
-    /// are less likely to accidentally result in unsoundness.
-    pub UNNECESSARY_TRANSMUTES,
-    Warn,
-    "detects transmutes that are shadowed by std methods"
-}
-
-declare_lint! {
     /// The `tail_expr_drop_order` lint looks for those values generated at the tail expression location,
     /// that runs a custom `Drop` destructor.
     /// Some of them may be dropped earlier in Edition 2024 that they used to in Edition 2021 and prior.
@@ -5064,8 +5049,9 @@ declare_lint! {
     Warn,
     "detects code relying on rustc's non-spec-compliant wasm C ABI",
     @future_incompatible = FutureIncompatibleInfo {
-        reason: FutureIncompatibilityReason::FutureReleaseErrorReportInDeps,
+        reason: FutureIncompatibilityReason::FutureReleaseError,
         reference: "issue #138762 <https://github.com/rust-lang/rust/issues/138762>",
+        report_in_deps: true,
     };
 }
 
@@ -5105,7 +5091,8 @@ declare_lint! {
     Warn,
     "detects code that could be affected by ABI issues on aarch64 softfloat targets",
     @future_incompatible = FutureIncompatibleInfo {
-        reason: FutureIncompatibilityReason::FutureReleaseErrorReportInDeps,
+        reason: FutureIncompatibilityReason::FutureReleaseError,
         reference: "issue #134375 <https://github.com/rust-lang/rust/issues/134375>",
+        report_in_deps: true,
     };
 }
diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs
index b4069b317bf..e19bf59e543 100644
--- a/compiler/rustc_lint_defs/src/lib.rs
+++ b/compiler/rustc_lint_defs/src/lib.rs
@@ -361,6 +361,18 @@ pub struct FutureIncompatibleInfo {
     /// Set to false for lints that already include a more detailed
     /// explanation.
     pub explain_reason: bool,
+    /// If set to `true`, this will make future incompatibility warnings show up in cargo's
+    /// reports.
+    ///
+    /// When a future incompatibility warning is first inroduced, set this to `false`
+    /// (or, rather, don't override the default). This allows crate developers an opportunity
+    /// to fix the warning before blasting all dependents with a warning they can't fix
+    /// (dependents have to wait for a new release of the affected crate to be published).
+    ///
+    /// After a lint has been in this state for a while, consider setting this to true, so it
+    /// warns for everyone. It is a good signal that it is ready if you can determine that all
+    /// or most affected crates on crates.io have been updated.
+    pub report_in_deps: bool,
 }
 
 /// The reason for future incompatibility
@@ -380,46 +392,24 @@ pub struct FutureIncompatibleInfo {
 pub enum FutureIncompatibilityReason {
     /// This will be an error in a future release for all editions
     ///
-    /// This will *not* show up in cargo's future breakage report.
-    /// The warning will hence only be seen in local crates, not in dependencies.
-    ///
     /// Choose this variant when you are first introducing a "future
     /// incompatible" warning that is intended to eventually be fixed in the
-    /// future. This allows crate developers an opportunity to fix the warning
-    /// before blasting all dependents with a warning they can't fix
-    /// (dependents have to wait for a new release of the affected crate to be
-    /// published).
-    ///
-    /// After a lint has been in this state for a while, consider graduating
-    /// it to [`FutureIncompatibilityReason::FutureReleaseErrorReportInDeps`].
-    FutureReleaseErrorDontReportInDeps,
-    /// This will be an error in a future release, and
-    /// Cargo should create a report even for dependencies
+    /// future.
     ///
-    /// This is the *only* reason that will make future incompatibility warnings show up in cargo's
-    /// reports. All other future incompatibility warnings are not visible when they occur in a
-    /// dependency.
-    ///
-    /// Choose this variant after the lint has been sitting in the
-    /// [`FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps`]
-    /// state for a while, and you feel like it is ready to graduate to
-    /// warning everyone. It is a good signal that it is ready if you can
-    /// determine that all or most affected crates on crates.io have been
-    /// updated.
+    /// After a lint has been in this state for a while and you feel like it is ready to graduate
+    /// to warning everyone, consider setting [`FutureIncompatibleInfo::report_in_deps`] to true.
+    /// (see it's documentation for more guidance)
     ///
     /// After some period of time, lints with this variant can be turned into
     /// hard errors (and the lint removed). Preferably when there is some
     /// confidence that the number of impacted projects is very small (few
     /// should have a broken dependency in their dependency tree).
-    ///
-    /// [`EditionAndFutureReleaseError`]: FutureIncompatibilityReason::EditionAndFutureReleaseError
-    FutureReleaseErrorReportInDeps,
+    FutureReleaseError,
     /// Code that changes meaning in some way in a
     /// future release.
     ///
     /// Choose this variant when the semantics of existing code is changing,
-    /// (as opposed to
-    /// [`FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps`],
+    /// (as opposed to [`FutureIncompatibilityReason::FutureReleaseError`],
     /// which is for when code is going to be rejected in the future).
     FutureReleaseSemanticsChange,
     /// Previously accepted code that will become an
@@ -454,13 +444,12 @@ pub enum FutureIncompatibilityReason {
     /// This will be an error in the provided edition *and* in a future
     /// release.
     ///
-    /// This variant a combination of [`FutureReleaseErrorDontReportInDeps`]
-    /// and [`EditionError`]. This is useful in rare cases when we
-    /// want to have "preview" of a breaking change in an edition, but do a
-    /// breaking change later on all editions anyway.
+    /// This variant a combination of [`FutureReleaseError`] and [`EditionError`].
+    /// This is useful in rare cases when we want to have "preview" of a breaking
+    /// change in an edition, but do a breaking change later on all editions anyway.
     ///
     /// [`EditionError`]: FutureIncompatibilityReason::EditionError
-    /// [`FutureReleaseErrorDontReportInDeps`]: FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps
+    /// [`FutureReleaseError`]: FutureIncompatibilityReason::FutureReleaseError
     EditionAndFutureReleaseError(Edition),
     /// This will change meaning in the provided edition *and* in a future
     /// release.
@@ -478,7 +467,7 @@ pub enum FutureIncompatibilityReason {
     /// Choose this variant if the built-in text of the diagnostic of the
     /// other variants doesn't match your situation. This is behaviorally
     /// equivalent to
-    /// [`FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps`].
+    /// [`FutureIncompatibilityReason::FutureReleaseError`].
     Custom(&'static str),
 }
 
@@ -490,34 +479,20 @@ impl FutureIncompatibilityReason {
             | Self::EditionAndFutureReleaseError(e)
             | Self::EditionAndFutureReleaseSemanticsChange(e) => Some(e),
 
-            FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps
-            | FutureIncompatibilityReason::FutureReleaseErrorReportInDeps
+            FutureIncompatibilityReason::FutureReleaseError
             | FutureIncompatibilityReason::FutureReleaseSemanticsChange
             | FutureIncompatibilityReason::Custom(_) => None,
         }
     }
-
-    pub fn has_future_breakage(self) -> bool {
-        match self {
-            FutureIncompatibilityReason::FutureReleaseErrorReportInDeps => true,
-
-            FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps
-            | FutureIncompatibilityReason::FutureReleaseSemanticsChange
-            | FutureIncompatibilityReason::EditionError(_)
-            | FutureIncompatibilityReason::EditionSemanticsChange(_)
-            | FutureIncompatibilityReason::EditionAndFutureReleaseError(_)
-            | FutureIncompatibilityReason::EditionAndFutureReleaseSemanticsChange(_)
-            | FutureIncompatibilityReason::Custom(_) => false,
-        }
-    }
 }
 
 impl FutureIncompatibleInfo {
     pub const fn default_fields_for_macro() -> Self {
         FutureIncompatibleInfo {
             reference: "",
-            reason: FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps,
+            reason: FutureIncompatibilityReason::FutureReleaseError,
             explain_reason: true,
+            report_in_deps: false,
         }
     }
 }
@@ -698,6 +673,14 @@ pub enum BuiltinLintDiag {
         is_string: bool,
         suggestion: Span,
     },
+    HiddenUnicodeCodepoints {
+        label: String,
+        count: usize,
+        span_label: Span,
+        labels: Option<Vec<(char, Span)>>,
+        escape: bool,
+        spans: Vec<(char, Span)>,
+    },
     TrailingMacro(bool, Ident),
     BreakWithLabelAndLoop(Span),
     UnicodeTextFlow(Span, String),
@@ -736,6 +719,7 @@ pub enum BuiltinLintDiag {
         ty: String,
     },
     UnusedExternCrate {
+        span: Span,
         removal_span: Span,
     },
     ExternCrateNotIdiomatic {
diff --git a/compiler/rustc_llvm/build.rs b/compiler/rustc_llvm/build.rs
index a662694ac38..9a6549379d3 100644
--- a/compiler/rustc_llvm/build.rs
+++ b/compiler/rustc_llvm/build.rs
@@ -228,10 +228,10 @@ fn main() {
     let mut cmd = Command::new(&llvm_config);
     cmd.arg(llvm_link_arg).arg("--libs");
 
-    // Don't link system libs if cross-compiling unless targeting Windows.
+    // Don't link system libs if cross-compiling unless targeting Windows from Windows host.
     // On Windows system DLLs aren't linked directly, instead import libraries are used.
     // These import libraries are independent of the host.
-    if !is_crossed || target.contains("windows") {
+    if !is_crossed || target.contains("windows") && host.contains("windows") {
         cmd.arg("--system-libs");
     }
 
diff --git a/compiler/rustc_metadata/Cargo.toml b/compiler/rustc_metadata/Cargo.toml
index cfe412e99d8..a163518fd19 100644
--- a/compiler/rustc_metadata/Cargo.toml
+++ b/compiler/rustc_metadata/Cargo.toml
@@ -23,6 +23,9 @@ rustc_hir_pretty = { path = "../rustc_hir_pretty" }
 rustc_index = { path = "../rustc_index" }
 rustc_macros = { path = "../rustc_macros" }
 rustc_middle = { path = "../rustc_middle" }
+# We must use the proc_macro version that we will compile proc-macros against,
+# not the one from our own sysroot.
+rustc_proc_macro = { path = "../rustc_proc_macro" }
 rustc_serialize = { path = "../rustc_serialize" }
 rustc_session = { path = "../rustc_session" }
 rustc_span = { path = "../rustc_span" }
diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs
index c7e9a2936f5..de19c10bc57 100644
--- a/compiler/rustc_metadata/src/creader.rs
+++ b/compiler/rustc_metadata/src/creader.rs
@@ -7,7 +7,6 @@ use std::str::FromStr;
 use std::time::Duration;
 use std::{cmp, env, iter};
 
-use proc_macro::bridge::client::ProcMacro;
 use rustc_ast::expand::allocator::{AllocatorKind, alloc_error_handler_name, global_fn_name};
 use rustc_ast::{self as ast, *};
 use rustc_data_structures::fx::FxHashSet;
@@ -22,7 +21,9 @@ use rustc_hir::def_id::{CrateNum, LOCAL_CRATE, LocalDefId, StableCrateId};
 use rustc_hir::definitions::Definitions;
 use rustc_index::IndexVec;
 use rustc_middle::bug;
+use rustc_middle::ty::data_structures::IndexSet;
 use rustc_middle::ty::{TyCtxt, TyCtxtFeed};
+use rustc_proc_macro::bridge::client::ProcMacro;
 use rustc_session::config::{
     self, CrateType, ExtendedTargetModifierInfo, ExternLocation, OptionsTargetModifiers,
     TargetModifier,
@@ -281,7 +282,7 @@ impl CStore {
             .filter_map(|(cnum, data)| data.as_deref_mut().map(|data| (cnum, data)))
     }
 
-    fn push_dependencies_in_postorder(&self, deps: &mut Vec<CrateNum>, cnum: CrateNum) {
+    fn push_dependencies_in_postorder(&self, deps: &mut IndexSet<CrateNum>, cnum: CrateNum) {
         if !deps.contains(&cnum) {
             let data = self.get_crate_data(cnum);
             for dep in data.dependencies() {
@@ -290,12 +291,12 @@ impl CStore {
                 }
             }
 
-            deps.push(cnum);
+            deps.insert(cnum);
         }
     }
 
-    pub(crate) fn crate_dependencies_in_postorder(&self, cnum: CrateNum) -> Vec<CrateNum> {
-        let mut deps = Vec::new();
+    pub(crate) fn crate_dependencies_in_postorder(&self, cnum: CrateNum) -> IndexSet<CrateNum> {
+        let mut deps = IndexSet::default();
         if cnum == LOCAL_CRATE {
             for (cnum, _) in self.iter_crate_data() {
                 self.push_dependencies_in_postorder(&mut deps, cnum);
@@ -306,10 +307,11 @@ impl CStore {
         deps
     }
 
-    fn crate_dependencies_in_reverse_postorder(&self, cnum: CrateNum) -> Vec<CrateNum> {
-        let mut deps = self.crate_dependencies_in_postorder(cnum);
-        deps.reverse();
-        deps
+    fn crate_dependencies_in_reverse_postorder(
+        &self,
+        cnum: CrateNum,
+    ) -> impl Iterator<Item = CrateNum> {
+        self.crate_dependencies_in_postorder(cnum).into_iter().rev()
     }
 
     pub(crate) fn injected_panic_runtime(&self) -> Option<CrateNum> {
diff --git a/compiler/rustc_metadata/src/lib.rs b/compiler/rustc_metadata/src/lib.rs
index 97b67140fa2..389a4ab7466 100644
--- a/compiler/rustc_metadata/src/lib.rs
+++ b/compiler/rustc_metadata/src/lib.rs
@@ -16,8 +16,6 @@
 #![feature(trusted_len)]
 // tidy-alphabetical-end
 
-extern crate proc_macro;
-
 pub use rmeta::provide;
 
 mod dependency_format;
diff --git a/compiler/rustc_metadata/src/locator.rs b/compiler/rustc_metadata/src/locator.rs
index 10123cb9a9d..79015aab5d3 100644
--- a/compiler/rustc_metadata/src/locator.rs
+++ b/compiler/rustc_metadata/src/locator.rs
@@ -435,7 +435,7 @@ impl<'a> CrateLocator<'a> {
                         info!("lib candidate: {}", spf.path.display());
 
                         let (rlibs, rmetas, dylibs, interfaces) =
-                            candidates.entry(hash.to_string()).or_default();
+                            candidates.entry(hash).or_default();
                         {
                             // As a perforamnce optimisation we canonicalize the path and skip
                             // ones we've already seeen. This allows us to ignore crates
diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs
index 2e4352ca532..1dae858b7ef 100644
--- a/compiler/rustc_metadata/src/rmeta/decoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/decoder.rs
@@ -6,7 +6,6 @@ use std::sync::{Arc, OnceLock};
 use std::{io, iter, mem};
 
 pub(super) use cstore_impl::provide;
-use proc_macro::bridge::client::ProcMacro;
 use rustc_ast as ast;
 use rustc_data_structures::fingerprint::Fingerprint;
 use rustc_data_structures::fx::FxIndexMap;
@@ -26,6 +25,7 @@ use rustc_middle::mir::interpret::{AllocDecodingSession, AllocDecodingState};
 use rustc_middle::ty::Visibility;
 use rustc_middle::ty::codec::TyDecoder;
 use rustc_middle::{bug, implement_ty_decoder};
+use rustc_proc_macro::bridge::client::ProcMacro;
 use rustc_serialize::opaque::MemDecoder;
 use rustc_serialize::{Decodable, Decoder};
 use rustc_session::Session;
diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
index f40a2374bea..375928c2245 100644
--- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
+++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
@@ -549,8 +549,9 @@ pub(in crate::rmeta) fn provide(providers: &mut Providers) {
         has_global_allocator: |tcx, LocalCrate| CStore::from_tcx(tcx).has_global_allocator(),
         has_alloc_error_handler: |tcx, LocalCrate| CStore::from_tcx(tcx).has_alloc_error_handler(),
         postorder_cnums: |tcx, ()| {
-            tcx.arena
-                .alloc_slice(&CStore::from_tcx(tcx).crate_dependencies_in_postorder(LOCAL_CRATE))
+            tcx.arena.alloc_from_iter(
+                CStore::from_tcx(tcx).crate_dependencies_in_postorder(LOCAL_CRATE).into_iter(),
+            )
         },
         crates: |tcx, ()| {
             // The list of loaded crates is now frozen in query cache,
diff --git a/compiler/rustc_middle/src/hir/map.rs b/compiler/rustc_middle/src/hir/map.rs
index fee707f7b4c..3de97c8c0d9 100644
--- a/compiler/rustc_middle/src/hir/map.rs
+++ b/compiler/rustc_middle/src/hir/map.rs
@@ -310,7 +310,7 @@ impl<'tcx> TyCtxt<'tcx> {
     /// This should only be used for determining the context of a body, a return
     /// value of `Some` does not always suggest that the owner of the body is `const`,
     /// just that it has to be checked as if it were.
-    pub fn hir_body_const_context(self, def_id: impl Into<DefId>) -> Option<ConstContext> {
+    pub fn hir_body_const_context(self, def_id: LocalDefId) -> Option<ConstContext> {
         let def_id = def_id.into();
         let ccx = match self.hir_body_owner_kind(def_id) {
             BodyOwnerKind::Const { inline } => ConstContext::Const { inline },
@@ -920,7 +920,7 @@ impl<'tcx> TyCtxt<'tcx> {
             }) => until_within(*outer_span, generics.where_clause_span),
             // Constants and Statics.
             Node::Item(Item {
-                kind: ItemKind::Const(_, ty, ..) | ItemKind::Static(_, ty, ..),
+                kind: ItemKind::Const(_, _, ty, _) | ItemKind::Static(_, _, ty, _),
                 span: outer_span,
                 ..
             })
diff --git a/compiler/rustc_middle/src/hir/place.rs b/compiler/rustc_middle/src/hir/place.rs
index c3d10615cf1..a34a3419d68 100644
--- a/compiler/rustc_middle/src/hir/place.rs
+++ b/compiler/rustc_middle/src/hir/place.rs
@@ -43,6 +43,9 @@ pub enum ProjectionKind {
     ///
     /// This is unused if `-Znext-solver` is enabled.
     OpaqueCast,
+
+    /// `unwrap_binder!(expr)`
+    UnwrapUnsafeBinder,
 }
 
 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable)]
diff --git a/compiler/rustc_middle/src/lint.rs b/compiler/rustc_middle/src/lint.rs
index d5a408fdfa6..341a735f88f 100644
--- a/compiler/rustc_middle/src/lint.rs
+++ b/compiler/rustc_middle/src/lint.rs
@@ -299,7 +299,7 @@ pub fn lint_level(
         let has_future_breakage = future_incompatible.map_or(
             // Default allow lints trigger too often for testing.
             sess.opts.unstable_opts.future_incompat_test && lint.default_level != Level::Allow,
-            |incompat| incompat.reason.has_future_breakage(),
+            |incompat| incompat.report_in_deps,
         );
 
         // Convert lint level to error level.
@@ -370,8 +370,7 @@ pub fn lint_level(
 
         if let Some(future_incompatible) = future_incompatible {
             let explanation = match future_incompatible.reason {
-                FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps
-                | FutureIncompatibilityReason::FutureReleaseErrorReportInDeps => {
+                FutureIncompatibilityReason::FutureReleaseError => {
                     "this was previously accepted by the compiler but is being phased out; \
                          it will become a hard error in a future release!"
                         .to_owned()
diff --git a/compiler/rustc_middle/src/mir/interpret/allocation.rs b/compiler/rustc_middle/src/mir/interpret/allocation.rs
index 57aafbb26bc..dd55d039794 100644
--- a/compiler/rustc_middle/src/mir/interpret/allocation.rs
+++ b/compiler/rustc_middle/src/mir/interpret/allocation.rs
@@ -27,12 +27,21 @@ use crate::ty;
 
 /// Functionality required for the bytes of an `Allocation`.
 pub trait AllocBytes: Clone + fmt::Debug + Deref<Target = [u8]> + DerefMut<Target = [u8]> {
+    /// The type of extra parameters passed in when creating an allocation.
+    /// Can be used by `interpret::Machine` instances to make runtime-configuration-dependent
+    /// decisions about the allocation strategy.
+    type AllocParams;
+
     /// Create an `AllocBytes` from a slice of `u8`.
-    fn from_bytes<'a>(slice: impl Into<Cow<'a, [u8]>>, _align: Align) -> Self;
+    fn from_bytes<'a>(
+        slice: impl Into<Cow<'a, [u8]>>,
+        _align: Align,
+        _params: Self::AllocParams,
+    ) -> Self;
 
     /// Create a zeroed `AllocBytes` of the specified size and alignment.
     /// Returns `None` if we ran out of memory on the host.
-    fn zeroed(size: Size, _align: Align) -> Option<Self>;
+    fn zeroed(size: Size, _align: Align, _params: Self::AllocParams) -> Option<Self>;
 
     /// Gives direct access to the raw underlying storage.
     ///
@@ -51,11 +60,13 @@ pub trait AllocBytes: Clone + fmt::Debug + Deref<Target = [u8]> + DerefMut<Targe
 
 /// Default `bytes` for `Allocation` is a `Box<u8>`.
 impl AllocBytes for Box<[u8]> {
-    fn from_bytes<'a>(slice: impl Into<Cow<'a, [u8]>>, _align: Align) -> Self {
+    type AllocParams = ();
+
+    fn from_bytes<'a>(slice: impl Into<Cow<'a, [u8]>>, _align: Align, _params: ()) -> Self {
         Box::<[u8]>::from(slice.into())
     }
 
-    fn zeroed(size: Size, _align: Align) -> Option<Self> {
+    fn zeroed(size: Size, _align: Align, _params: ()) -> Option<Self> {
         let bytes = Box::<[u8]>::try_new_zeroed_slice(size.bytes().try_into().ok()?).ok()?;
         // SAFETY: the box was zero-allocated, which is a valid initial value for Box<[u8]>
         let bytes = unsafe { bytes.assume_init() };
@@ -172,9 +183,8 @@ fn all_zero(buf: &[u8]) -> bool {
 }
 
 /// Custom encoder for [`Allocation`] to more efficiently represent the case where all bytes are 0.
-impl<Prov: Provenance, Extra, Bytes, E: Encoder> Encodable<E> for Allocation<Prov, Extra, Bytes>
+impl<Prov: Provenance, Extra, E: Encoder> Encodable<E> for Allocation<Prov, Extra, Box<[u8]>>
 where
-    Bytes: AllocBytes,
     ProvenanceMap<Prov>: Encodable<E>,
     Extra: Encodable<E>,
 {
@@ -192,9 +202,8 @@ where
     }
 }
 
-impl<Prov: Provenance, Extra, Bytes, D: Decoder> Decodable<D> for Allocation<Prov, Extra, Bytes>
+impl<Prov: Provenance, Extra, D: Decoder> Decodable<D> for Allocation<Prov, Extra, Box<[u8]>>
 where
-    Bytes: AllocBytes,
     ProvenanceMap<Prov>: Decodable<D>,
     Extra: Decodable<D>,
 {
@@ -203,7 +212,7 @@ where
 
         let len = decoder.read_usize();
         let bytes = if all_zero { vec![0u8; len] } else { decoder.read_raw_bytes(len).to_vec() };
-        let bytes = Bytes::from_bytes(bytes, align);
+        let bytes = <Box<[u8]> as AllocBytes>::from_bytes(bytes, align, ());
 
         let provenance = Decodable::decode(decoder);
         let init_mask = Decodable::decode(decoder);
@@ -395,8 +404,9 @@ impl<Prov: Provenance, Bytes: AllocBytes> Allocation<Prov, (), Bytes> {
         slice: impl Into<Cow<'a, [u8]>>,
         align: Align,
         mutability: Mutability,
+        params: <Bytes as AllocBytes>::AllocParams,
     ) -> Self {
-        let bytes = Bytes::from_bytes(slice, align);
+        let bytes = Bytes::from_bytes(slice, align, params);
         let size = Size::from_bytes(bytes.len());
         Self {
             bytes,
@@ -408,14 +418,18 @@ impl<Prov: Provenance, Bytes: AllocBytes> Allocation<Prov, (), Bytes> {
         }
     }
 
-    pub fn from_bytes_byte_aligned_immutable<'a>(slice: impl Into<Cow<'a, [u8]>>) -> Self {
-        Allocation::from_bytes(slice, Align::ONE, Mutability::Not)
+    pub fn from_bytes_byte_aligned_immutable<'a>(
+        slice: impl Into<Cow<'a, [u8]>>,
+        params: <Bytes as AllocBytes>::AllocParams,
+    ) -> Self {
+        Allocation::from_bytes(slice, Align::ONE, Mutability::Not, params)
     }
 
     fn new_inner<R>(
         size: Size,
         align: Align,
         init: AllocInit,
+        params: <Bytes as AllocBytes>::AllocParams,
         fail: impl FnOnce() -> R,
     ) -> Result<Self, R> {
         // We raise an error if we cannot create the allocation on the host.
@@ -424,7 +438,7 @@ impl<Prov: Provenance, Bytes: AllocBytes> Allocation<Prov, (), Bytes> {
         // deterministic. However, we can be non-deterministic here because all uses of const
         // evaluation (including ConstProp!) will make compilation fail (via hard error
         // or ICE) upon encountering a `MemoryExhausted` error.
-        let bytes = Bytes::zeroed(size, align).ok_or_else(fail)?;
+        let bytes = Bytes::zeroed(size, align, params).ok_or_else(fail)?;
 
         Ok(Allocation {
             bytes,
@@ -444,8 +458,13 @@ impl<Prov: Provenance, Bytes: AllocBytes> Allocation<Prov, (), Bytes> {
 
     /// Try to create an Allocation of `size` bytes, failing if there is not enough memory
     /// available to the compiler to do so.
-    pub fn try_new<'tcx>(size: Size, align: Align, init: AllocInit) -> InterpResult<'tcx, Self> {
-        Self::new_inner(size, align, init, || {
+    pub fn try_new<'tcx>(
+        size: Size,
+        align: Align,
+        init: AllocInit,
+        params: <Bytes as AllocBytes>::AllocParams,
+    ) -> InterpResult<'tcx, Self> {
+        Self::new_inner(size, align, init, params, || {
             ty::tls::with(|tcx| tcx.dcx().delayed_bug("exhausted memory during interpretation"));
             InterpErrorKind::ResourceExhaustion(ResourceExhaustionInfo::MemoryExhausted)
         })
@@ -457,8 +476,13 @@ impl<Prov: Provenance, Bytes: AllocBytes> Allocation<Prov, (), Bytes> {
     ///
     /// Example use case: To obtain an Allocation filled with specific data,
     /// first call this function and then call write_scalar to fill in the right data.
-    pub fn new(size: Size, align: Align, init: AllocInit) -> Self {
-        match Self::new_inner(size, align, init, || {
+    pub fn new(
+        size: Size,
+        align: Align,
+        init: AllocInit,
+        params: <Bytes as AllocBytes>::AllocParams,
+    ) -> Self {
+        match Self::new_inner(size, align, init, params, || {
             panic!(
                 "interpreter ran out of memory: cannot create allocation of {} bytes",
                 size.bytes()
@@ -488,7 +512,7 @@ impl Allocation {
     pub fn adjust_from_tcx<'tcx, Prov: Provenance, Bytes: AllocBytes>(
         &self,
         cx: &impl HasDataLayout,
-        mut alloc_bytes: impl FnMut(&[u8], Align) -> InterpResult<'tcx, Bytes>,
+        alloc_bytes: impl FnOnce(&[u8], Align) -> InterpResult<'tcx, Bytes>,
         mut adjust_ptr: impl FnMut(Pointer<CtfeProvenance>) -> InterpResult<'tcx, Pointer<Prov>>,
     ) -> InterpResult<'tcx, Allocation<Prov, (), Bytes>> {
         // Copy the data.
diff --git a/compiler/rustc_middle/src/mir/interpret/queries.rs b/compiler/rustc_middle/src/mir/interpret/queries.rs
index 4a5c42c721c..97db45a70d7 100644
--- a/compiler/rustc_middle/src/mir/interpret/queries.rs
+++ b/compiler/rustc_middle/src/mir/interpret/queries.rs
@@ -9,7 +9,6 @@ use super::{
     ReportedErrorInfo,
 };
 use crate::mir;
-use crate::query::TyCtxtEnsureOk;
 use crate::ty::{self, GenericArgs, TyCtxt, TypeVisitableExt};
 
 impl<'tcx> TyCtxt<'tcx> {
@@ -197,24 +196,3 @@ impl<'tcx> TyCtxt<'tcx> {
         }
     }
 }
-
-impl<'tcx> TyCtxtEnsureOk<'tcx> {
-    /// Evaluates a constant without providing any generic parameters. This is useful to evaluate consts
-    /// that can't take any generic arguments like const items or enum discriminants. If a
-    /// generic parameter is used within the constant `ErrorHandled::TooGeneric` will be returned.
-    #[instrument(skip(self), level = "debug")]
-    pub fn const_eval_poly(self, def_id: DefId) {
-        // In some situations def_id will have generic parameters within scope, but they aren't allowed
-        // to be used. So we can't use `Instance::mono`, instead we feed unresolved generic parameters
-        // into `const_eval` which will return `ErrorHandled::TooGeneric` if any of them are
-        // encountered.
-        let args = GenericArgs::identity_for_item(self.tcx, def_id);
-        let instance = ty::Instance::new_raw(def_id, self.tcx.erase_regions(args));
-        let cid = GlobalId { instance, promoted: None };
-        let typing_env = ty::TypingEnv::post_analysis(self.tcx, def_id);
-        // Const-eval shouldn't depend on lifetimes at all, so we can erase them, which should
-        // improve caching of queries.
-        let inputs = self.tcx.erase_regions(typing_env.as_query_input(cid));
-        self.eval_to_const_value_raw(inputs)
-    }
-}
diff --git a/compiler/rustc_middle/src/mir/interpret/value.rs b/compiler/rustc_middle/src/mir/interpret/value.rs
index 9d462093b9e..7ba0e5b5e07 100644
--- a/compiler/rustc_middle/src/mir/interpret/value.rs
+++ b/compiler/rustc_middle/src/mir/interpret/value.rs
@@ -180,27 +180,27 @@ impl<Prov> Scalar<Prov> {
 
     #[inline]
     pub fn from_i8(i: i8) -> Self {
-        Self::from_int(i, Size::from_bits(8))
+        Self::Int(i.into())
     }
 
     #[inline]
     pub fn from_i16(i: i16) -> Self {
-        Self::from_int(i, Size::from_bits(16))
+        Self::Int(i.into())
     }
 
     #[inline]
     pub fn from_i32(i: i32) -> Self {
-        Self::from_int(i, Size::from_bits(32))
+        Self::Int(i.into())
     }
 
     #[inline]
     pub fn from_i64(i: i64) -> Self {
-        Self::from_int(i, Size::from_bits(64))
+        Self::Int(i.into())
     }
 
     #[inline]
     pub fn from_i128(i: i128) -> Self {
-        Self::from_int(i, Size::from_bits(128))
+        Self::Int(i.into())
     }
 
     #[inline]
diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs
index 57ae7dc55c5..6b262a27500 100644
--- a/compiler/rustc_middle/src/mir/pretty.rs
+++ b/compiler/rustc_middle/src/mir/pretty.rs
@@ -1624,7 +1624,11 @@ pub fn write_allocations<'tcx>(
             Some(GlobalAlloc::Static(did)) if !tcx.is_foreign_item(did) => {
                 write!(w, " (static: {}", tcx.def_path_str(did))?;
                 if body.phase <= MirPhase::Runtime(RuntimePhase::PostCleanup)
-                    && tcx.hir_body_const_context(body.source.def_id()).is_some()
+                    && body
+                        .source
+                        .def_id()
+                        .as_local()
+                        .is_some_and(|def_id| tcx.hir_body_const_context(def_id).is_some())
                 {
                     // Statics may be cyclic and evaluating them too early
                     // in the MIR pipeline may cause cycle errors even though
diff --git a/compiler/rustc_middle/src/mir/statement.rs b/compiler/rustc_middle/src/mir/statement.rs
index d59b6df44ed..06e41e64fdc 100644
--- a/compiler/rustc_middle/src/mir/statement.rs
+++ b/compiler/rustc_middle/src/mir/statement.rs
@@ -88,26 +88,31 @@ impl<'tcx> PlaceTy<'tcx> {
     ///
     /// Note that the resulting type has not been normalized.
     #[instrument(level = "debug", skip(tcx), ret)]
-    pub fn field_ty(self, tcx: TyCtxt<'tcx>, f: FieldIdx) -> Ty<'tcx> {
-        if let Some(variant_index) = self.variant_index {
-            match *self.ty.kind() {
+    pub fn field_ty(
+        tcx: TyCtxt<'tcx>,
+        self_ty: Ty<'tcx>,
+        variant_idx: Option<VariantIdx>,
+        f: FieldIdx,
+    ) -> Ty<'tcx> {
+        if let Some(variant_index) = variant_idx {
+            match *self_ty.kind() {
                 ty::Adt(adt_def, args) if adt_def.is_enum() => {
                     adt_def.variant(variant_index).fields[f].ty(tcx, args)
                 }
                 ty::Coroutine(def_id, args) => {
                     let mut variants = args.as_coroutine().state_tys(def_id, tcx);
                     let Some(mut variant) = variants.nth(variant_index.into()) else {
-                        bug!("variant {variant_index:?} of coroutine out of range: {self:?}");
+                        bug!("variant {variant_index:?} of coroutine out of range: {self_ty:?}");
                     };
 
-                    variant
-                        .nth(f.index())
-                        .unwrap_or_else(|| bug!("field {f:?} out of range: {self:?}"))
+                    variant.nth(f.index()).unwrap_or_else(|| {
+                        bug!("field {f:?} out of range of variant: {self_ty:?} {variant_idx:?}")
+                    })
                 }
-                _ => bug!("can't downcast non-adt non-coroutine type: {self:?}"),
+                _ => bug!("can't downcast non-adt non-coroutine type: {self_ty:?}"),
             }
         } else {
-            match self.ty.kind() {
+            match self_ty.kind() {
                 ty::Adt(adt_def, args) if !adt_def.is_enum() => {
                     adt_def.non_enum_variant().fields[f].ty(tcx, args)
                 }
@@ -116,26 +121,25 @@ impl<'tcx> PlaceTy<'tcx> {
                     .upvar_tys()
                     .get(f.index())
                     .copied()
-                    .unwrap_or_else(|| bug!("field {f:?} out of range: {self:?}")),
+                    .unwrap_or_else(|| bug!("field {f:?} out of range: {self_ty:?}")),
                 ty::CoroutineClosure(_, args) => args
                     .as_coroutine_closure()
                     .upvar_tys()
                     .get(f.index())
                     .copied()
-                    .unwrap_or_else(|| bug!("field {f:?} out of range: {self:?}")),
+                    .unwrap_or_else(|| bug!("field {f:?} out of range: {self_ty:?}")),
                 // Only prefix fields (upvars and current state) are
                 // accessible without a variant index.
-                ty::Coroutine(_, args) => args
-                    .as_coroutine()
-                    .prefix_tys()
-                    .get(f.index())
-                    .copied()
-                    .unwrap_or_else(|| bug!("field {f:?} out of range: {self:?}")),
+                ty::Coroutine(_, args) => {
+                    args.as_coroutine().prefix_tys().get(f.index()).copied().unwrap_or_else(|| {
+                        bug!("field {f:?} out of range of prefixes for {self_ty}")
+                    })
+                }
                 ty::Tuple(tys) => tys
                     .get(f.index())
                     .copied()
-                    .unwrap_or_else(|| bug!("field {f:?} out of range: {self:?}")),
-                _ => bug!("can't project out of {self:?}"),
+                    .unwrap_or_else(|| bug!("field {f:?} out of range: {self_ty:?}")),
+                _ => bug!("can't project out of {self_ty:?}"),
             }
         }
     }
@@ -148,11 +152,11 @@ impl<'tcx> PlaceTy<'tcx> {
         elems.iter().fold(self, |place_ty, &elem| place_ty.projection_ty(tcx, elem))
     }
 
-    /// Convenience wrapper around `projection_ty_core` for
-    /// `PlaceElem`, where we can just use the `Ty` that is already
-    /// stored inline on field projection elems.
+    /// Convenience wrapper around `projection_ty_core` for `PlaceElem`,
+    /// where we can just use the `Ty` that is already stored inline on
+    /// field projection elems.
     pub fn projection_ty(self, tcx: TyCtxt<'tcx>, elem: PlaceElem<'tcx>) -> PlaceTy<'tcx> {
-        self.projection_ty_core(tcx, &elem, |_, _, ty| ty, |_, ty| ty)
+        self.projection_ty_core(tcx, &elem, |ty| ty, |_, _, _, ty| ty, |ty| ty)
     }
 
     /// `place_ty.projection_ty_core(tcx, elem, |...| { ... })`
@@ -164,8 +168,9 @@ impl<'tcx> PlaceTy<'tcx> {
         self,
         tcx: TyCtxt<'tcx>,
         elem: &ProjectionElem<V, T>,
-        mut handle_field: impl FnMut(&Self, FieldIdx, T) -> Ty<'tcx>,
-        mut handle_opaque_cast_and_subtype: impl FnMut(&Self, T) -> Ty<'tcx>,
+        mut structurally_normalize: impl FnMut(Ty<'tcx>) -> Ty<'tcx>,
+        mut handle_field: impl FnMut(Ty<'tcx>, Option<VariantIdx>, FieldIdx, T) -> Ty<'tcx>,
+        mut handle_opaque_cast_and_subtype: impl FnMut(T) -> Ty<'tcx>,
     ) -> PlaceTy<'tcx>
     where
         V: ::std::fmt::Debug,
@@ -176,16 +181,16 @@ impl<'tcx> PlaceTy<'tcx> {
         }
         let answer = match *elem {
             ProjectionElem::Deref => {
-                let ty = self.ty.builtin_deref(true).unwrap_or_else(|| {
+                let ty = structurally_normalize(self.ty).builtin_deref(true).unwrap_or_else(|| {
                     bug!("deref projection of non-dereferenceable ty {:?}", self)
                 });
                 PlaceTy::from_ty(ty)
             }
             ProjectionElem::Index(_) | ProjectionElem::ConstantIndex { .. } => {
-                PlaceTy::from_ty(self.ty.builtin_index().unwrap())
+                PlaceTy::from_ty(structurally_normalize(self.ty).builtin_index().unwrap())
             }
             ProjectionElem::Subslice { from, to, from_end } => {
-                PlaceTy::from_ty(match self.ty.kind() {
+                PlaceTy::from_ty(match structurally_normalize(self.ty).kind() {
                     ty::Slice(..) => self.ty,
                     ty::Array(inner, _) if !from_end => Ty::new_array(tcx, *inner, to - from),
                     ty::Array(inner, size) if from_end => {
@@ -201,17 +206,18 @@ impl<'tcx> PlaceTy<'tcx> {
             ProjectionElem::Downcast(_name, index) => {
                 PlaceTy { ty: self.ty, variant_index: Some(index) }
             }
-            ProjectionElem::Field(f, fty) => PlaceTy::from_ty(handle_field(&self, f, fty)),
-            ProjectionElem::OpaqueCast(ty) => {
-                PlaceTy::from_ty(handle_opaque_cast_and_subtype(&self, ty))
-            }
-            ProjectionElem::Subtype(ty) => {
-                PlaceTy::from_ty(handle_opaque_cast_and_subtype(&self, ty))
-            }
+            ProjectionElem::Field(f, fty) => PlaceTy::from_ty(handle_field(
+                structurally_normalize(self.ty),
+                self.variant_index,
+                f,
+                fty,
+            )),
+            ProjectionElem::OpaqueCast(ty) => PlaceTy::from_ty(handle_opaque_cast_and_subtype(ty)),
+            ProjectionElem::Subtype(ty) => PlaceTy::from_ty(handle_opaque_cast_and_subtype(ty)),
 
             // FIXME(unsafe_binders): Rename `handle_opaque_cast_and_subtype` to be more general.
             ProjectionElem::UnwrapUnsafeBinder(ty) => {
-                PlaceTy::from_ty(handle_opaque_cast_and_subtype(&self, ty))
+                PlaceTy::from_ty(handle_opaque_cast_and_subtype(ty))
             }
         };
         debug!("projection_ty self: {:?} elem: {:?} yields: {:?}", self, elem, answer);
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index 30245bc82d4..542653efd30 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -535,7 +535,8 @@ rustc_queries! {
         separate_provide_extern
     }
 
-    /// Fetch the THIR for a given body.
+    /// Fetch the THIR for a given body. The THIR body gets stolen by unsafety checking unless
+    /// `-Zno-steal-thir` is on.
     query thir_body(key: LocalDefId) -> Result<(&'tcx Steal<thir::Thir<'tcx>>, thir::ExprId), ErrorGuaranteed> {
         // Perf tests revealed that hashing THIR is inefficient (see #85729).
         no_hash
@@ -1137,7 +1138,7 @@ rustc_queries! {
     /// their respective impl (i.e., part of the derive macro)
     query live_symbols_and_ignored_derived_traits(_: ()) -> &'tcx (
         LocalDefIdSet,
-        LocalDefIdMap<Vec<(DefId, DefId)>>
+        LocalDefIdMap<FxIndexSet<(DefId, DefId)>>
     ) {
         arena_cache
         desc { "finding live symbols in crate" }
diff --git a/compiler/rustc_middle/src/thir/visit.rs b/compiler/rustc_middle/src/thir/visit.rs
index f3da2a5cc8e..4da4dc3c02e 100644
--- a/compiler/rustc_middle/src/thir/visit.rs
+++ b/compiler/rustc_middle/src/thir/visit.rs
@@ -41,7 +41,8 @@ pub fn walk_expr<'thir, 'tcx: 'thir, V: Visitor<'thir, 'tcx>>(
     expr: &'thir Expr<'tcx>,
 ) {
     use ExprKind::*;
-    match expr.kind {
+    let Expr { kind, ty: _, temp_lifetime: _, span: _ } = expr;
+    match *kind {
         Scope { value, region_scope: _, lint_level: _ } => {
             visitor.visit_expr(&visitor.thir()[value])
         }
@@ -191,7 +192,8 @@ pub fn walk_stmt<'thir, 'tcx: 'thir, V: Visitor<'thir, 'tcx>>(
     visitor: &mut V,
     stmt: &'thir Stmt<'tcx>,
 ) {
-    match &stmt.kind {
+    let Stmt { kind } = stmt;
+    match kind {
         StmtKind::Expr { expr, scope: _ } => visitor.visit_expr(&visitor.thir()[*expr]),
         StmtKind::Let {
             initializer,
@@ -217,11 +219,13 @@ pub fn walk_block<'thir, 'tcx: 'thir, V: Visitor<'thir, 'tcx>>(
     visitor: &mut V,
     block: &'thir Block,
 ) {
-    for &stmt in &*block.stmts {
+    let Block { stmts, expr, targeted_by_break: _, region_scope: _, span: _, safety_mode: _ } =
+        block;
+    for &stmt in &*stmts {
         visitor.visit_stmt(&visitor.thir()[stmt]);
     }
-    if let Some(expr) = block.expr {
-        visitor.visit_expr(&visitor.thir()[expr]);
+    if let Some(expr) = expr {
+        visitor.visit_expr(&visitor.thir()[*expr]);
     }
 }
 
@@ -229,11 +233,12 @@ pub fn walk_arm<'thir, 'tcx: 'thir, V: Visitor<'thir, 'tcx>>(
     visitor: &mut V,
     arm: &'thir Arm<'tcx>,
 ) {
-    if let Some(expr) = arm.guard {
-        visitor.visit_expr(&visitor.thir()[expr])
+    let Arm { guard, pattern, body, lint_level: _, span: _, scope: _ } = arm;
+    if let Some(expr) = guard {
+        visitor.visit_expr(&visitor.thir()[*expr])
     }
-    visitor.visit_pat(&arm.pattern);
-    visitor.visit_expr(&visitor.thir()[arm.body]);
+    visitor.visit_pat(pattern);
+    visitor.visit_expr(&visitor.thir()[*body]);
 }
 
 pub fn walk_pat<'thir, 'tcx: 'thir, V: Visitor<'thir, 'tcx>>(
@@ -249,7 +254,8 @@ pub(crate) fn for_each_immediate_subpat<'a, 'tcx>(
     pat: &'a Pat<'tcx>,
     mut callback: impl FnMut(&'a Pat<'tcx>),
 ) {
-    match &pat.kind {
+    let Pat { kind, ty: _, span: _ } = pat;
+    match kind {
         PatKind::Missing
         | PatKind::Wild
         | PatKind::Binding { subpattern: None, .. }
diff --git a/compiler/rustc_middle/src/ty/closure.rs b/compiler/rustc_middle/src/ty/closure.rs
index ff9096695d4..df67bb505a6 100644
--- a/compiler/rustc_middle/src/ty/closure.rs
+++ b/compiler/rustc_middle/src/ty/closure.rs
@@ -117,6 +117,10 @@ impl<'tcx> CapturedPlace<'tcx> {
                     }
                 },
 
+                HirProjectionKind::UnwrapUnsafeBinder => {
+                    write!(&mut symbol, "__unwrap").unwrap();
+                }
+
                 // Ignore derefs for now, as they are likely caused by
                 // autoderefs that don't appear in the original code.
                 HirProjectionKind::Deref => {}
diff --git a/compiler/rustc_middle/src/ty/consts/int.rs b/compiler/rustc_middle/src/ty/consts/int.rs
index 9f5e31d894c..b087ae25486 100644
--- a/compiler/rustc_middle/src/ty/consts/int.rs
+++ b/compiler/rustc_middle/src/ty/consts/int.rs
@@ -26,6 +26,19 @@ impl ConstInt {
     }
 }
 
+/// An enum to represent the compiler-side view of `intrinsics::AtomicOrdering`.
+/// This lives here because there's a method in this file that needs it and it is entirely unclear
+/// where else to put this...
+#[derive(Debug, Copy, Clone)]
+pub enum AtomicOrdering {
+    // These values must match `intrinsics::AtomicOrdering`!
+    Relaxed = 0,
+    Release = 1,
+    Acquire = 2,
+    AcqRel = 3,
+    SeqCst = 4,
+}
+
 impl std::fmt::Debug for ConstInt {
     fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         let Self { int, signed, is_ptr_sized_integral } = *self;
@@ -318,6 +331,25 @@ impl ScalarInt {
         self.to_uint(tcx.data_layout.pointer_size).try_into().unwrap()
     }
 
+    #[inline]
+    pub fn to_atomic_ordering(self) -> AtomicOrdering {
+        use AtomicOrdering::*;
+        let val = self.to_u32();
+        if val == Relaxed as u32 {
+            Relaxed
+        } else if val == Release as u32 {
+            Release
+        } else if val == Acquire as u32 {
+            Acquire
+        } else if val == AcqRel as u32 {
+            AcqRel
+        } else if val == SeqCst as u32 {
+            SeqCst
+        } else {
+            panic!("not a valid atomic ordering")
+        }
+    }
+
     /// Converts the `ScalarInt` to `bool`.
     /// Panics if the `size` of the `ScalarInt` is not equal to 1 byte.
     /// Errors if it is not a valid `bool`.
@@ -422,9 +454,9 @@ macro_rules! from_scalar_int_for_x {
             impl From<ScalarInt> for $ty {
                 #[inline]
                 fn from(int: ScalarInt) -> Self {
-                    // The `unwrap` cannot fail because to_bits (if it succeeds)
+                    // The `unwrap` cannot fail because to_uint (if it succeeds)
                     // is guaranteed to return a value that fits into the size.
-                    int.to_bits(Size::from_bytes(size_of::<$ty>()))
+                    int.to_uint(Size::from_bytes(size_of::<$ty>()))
                        .try_into().unwrap()
                 }
             }
@@ -450,6 +482,49 @@ impl From<char> for ScalarInt {
     }
 }
 
+macro_rules! from_x_for_scalar_int_signed {
+    ($($ty:ty),*) => {
+        $(
+            impl From<$ty> for ScalarInt {
+                #[inline]
+                fn from(u: $ty) -> Self {
+                    Self {
+                        data: u128::from(u.cast_unsigned()), // go via the unsigned type of the same size
+                        size: NonZero::new(size_of::<$ty>() as u8).unwrap(),
+                    }
+                }
+            }
+        )*
+    }
+}
+
+macro_rules! from_scalar_int_for_x_signed {
+    ($($ty:ty),*) => {
+        $(
+            impl From<ScalarInt> for $ty {
+                #[inline]
+                fn from(int: ScalarInt) -> Self {
+                    // The `unwrap` cannot fail because to_int (if it succeeds)
+                    // is guaranteed to return a value that fits into the size.
+                    int.to_int(Size::from_bytes(size_of::<$ty>()))
+                       .try_into().unwrap()
+                }
+            }
+        )*
+    }
+}
+
+from_x_for_scalar_int_signed!(i8, i16, i32, i64, i128);
+from_scalar_int_for_x_signed!(i8, i16, i32, i64, i128);
+
+impl From<std::cmp::Ordering> for ScalarInt {
+    #[inline]
+    fn from(c: std::cmp::Ordering) -> Self {
+        // Here we rely on `cmp::Ordering` having the same values in host and target!
+        ScalarInt::from(c as i8)
+    }
+}
+
 /// Error returned when a conversion from ScalarInt to char fails.
 #[derive(Debug)]
 pub struct CharTryFromScalarInt;
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index 8c915fea950..57b20a1bba6 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -1582,7 +1582,7 @@ impl<'tcx> TyCtxt<'tcx> {
     /// Returns the same `AllocId` if called again with the same bytes.
     pub fn allocate_bytes_dedup(self, bytes: &[u8], salt: usize) -> interpret::AllocId {
         // Create an allocation that just contains these bytes.
-        let alloc = interpret::Allocation::from_bytes_byte_aligned_immutable(bytes);
+        let alloc = interpret::Allocation::from_bytes_byte_aligned_immutable(bytes, ());
         let alloc = self.mk_const_alloc(alloc);
         self.reserve_and_set_memory_dedup(alloc, salt)
     }
@@ -2781,7 +2781,7 @@ impl<'tcx> TyCtxt<'tcx> {
                 return false;
             }
 
-            if !matches!(args[0].unpack(), ty::GenericArgKind::Type(_)) {
+            if !matches!(args[0].kind(), ty::GenericArgKind::Type(_)) {
                 return false;
             }
 
@@ -2803,7 +2803,7 @@ impl<'tcx> TyCtxt<'tcx> {
         };
 
         for (param, arg) in std::iter::zip(&generics.own_params, own_args) {
-            match (&param.kind, arg.unpack()) {
+            match (&param.kind, arg.kind()) {
                 (ty::GenericParamDefKind::Type { .. }, ty::GenericArgKind::Type(_))
                 | (ty::GenericParamDefKind::Lifetime, ty::GenericArgKind::Lifetime(_))
                 | (ty::GenericParamDefKind::Const { .. }, ty::GenericArgKind::Const(_)) => {}
diff --git a/compiler/rustc_middle/src/ty/erase_regions.rs b/compiler/rustc_middle/src/ty/erase_regions.rs
index 45a0b1288db..f4fead7e952 100644
--- a/compiler/rustc_middle/src/ty/erase_regions.rs
+++ b/compiler/rustc_middle/src/ty/erase_regions.rs
@@ -86,4 +86,12 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for RegionEraserVisitor<'tcx> {
             p
         }
     }
+
+    fn fold_clauses(&mut self, c: ty::Clauses<'tcx>) -> ty::Clauses<'tcx> {
+        if c.has_type_flags(TypeFlags::HAS_BINDER_VARS | TypeFlags::HAS_FREE_REGIONS) {
+            c.super_fold_with(self)
+        } else {
+            c
+        }
+    }
 }
diff --git a/compiler/rustc_middle/src/ty/fold.rs b/compiler/rustc_middle/src/ty/fold.rs
index 8d6871d2f1f..b2057fa36d7 100644
--- a/compiler/rustc_middle/src/ty/fold.rs
+++ b/compiler/rustc_middle/src/ty/fold.rs
@@ -177,6 +177,10 @@ where
     fn fold_predicate(&mut self, p: ty::Predicate<'tcx>) -> ty::Predicate<'tcx> {
         if p.has_vars_bound_at_or_above(self.current_index) { p.super_fold_with(self) } else { p }
     }
+
+    fn fold_clauses(&mut self, c: ty::Clauses<'tcx>) -> ty::Clauses<'tcx> {
+        if c.has_vars_bound_at_or_above(self.current_index) { c.super_fold_with(self) } else { c }
+    }
 }
 
 impl<'tcx> TyCtxt<'tcx> {
diff --git a/compiler/rustc_middle/src/ty/generic_args.rs b/compiler/rustc_middle/src/ty/generic_args.rs
index 542c0b3e6eb..5e038f91675 100644
--- a/compiler/rustc_middle/src/ty/generic_args.rs
+++ b/compiler/rustc_middle/src/ty/generic_args.rs
@@ -137,7 +137,7 @@ impl<'tcx> rustc_type_ir::inherent::IntoKind for GenericArg<'tcx> {
     type Kind = GenericArgKind<'tcx>;
 
     fn kind(self) -> Self::Kind {
-        self.unpack()
+        self.kind()
     }
 }
 
@@ -218,7 +218,7 @@ impl<'tcx> From<ty::Const<'tcx>> for GenericArg<'tcx> {
 
 impl<'tcx> From<ty::Term<'tcx>> for GenericArg<'tcx> {
     fn from(value: ty::Term<'tcx>) -> Self {
-        match value.unpack() {
+        match value.kind() {
             ty::TermKind::Ty(t) => t.into(),
             ty::TermKind::Const(c) => c.into(),
         }
@@ -227,7 +227,7 @@ impl<'tcx> From<ty::Term<'tcx>> for GenericArg<'tcx> {
 
 impl<'tcx> GenericArg<'tcx> {
     #[inline]
-    pub fn unpack(self) -> GenericArgKind<'tcx> {
+    pub fn kind(self) -> GenericArgKind<'tcx> {
         let ptr =
             unsafe { self.ptr.map_addr(|addr| NonZero::new_unchecked(addr.get() & !TAG_MASK)) };
         // SAFETY: use of `Interned::new_unchecked` here is ok because these
@@ -251,7 +251,7 @@ impl<'tcx> GenericArg<'tcx> {
 
     #[inline]
     pub fn as_region(self) -> Option<ty::Region<'tcx>> {
-        match self.unpack() {
+        match self.kind() {
             GenericArgKind::Lifetime(re) => Some(re),
             _ => None,
         }
@@ -259,7 +259,7 @@ impl<'tcx> GenericArg<'tcx> {
 
     #[inline]
     pub fn as_type(self) -> Option<Ty<'tcx>> {
-        match self.unpack() {
+        match self.kind() {
             GenericArgKind::Type(ty) => Some(ty),
             _ => None,
         }
@@ -267,7 +267,7 @@ impl<'tcx> GenericArg<'tcx> {
 
     #[inline]
     pub fn as_const(self) -> Option<ty::Const<'tcx>> {
-        match self.unpack() {
+        match self.kind() {
             GenericArgKind::Const(ct) => Some(ct),
             _ => None,
         }
@@ -275,7 +275,7 @@ impl<'tcx> GenericArg<'tcx> {
 
     #[inline]
     pub fn as_term(self) -> Option<ty::Term<'tcx>> {
-        match self.unpack() {
+        match self.kind() {
             GenericArgKind::Lifetime(_) => None,
             GenericArgKind::Type(ty) => Some(ty.into()),
             GenericArgKind::Const(ct) => Some(ct.into()),
@@ -300,7 +300,7 @@ impl<'tcx> GenericArg<'tcx> {
     }
 
     pub fn is_non_region_infer(self) -> bool {
-        match self.unpack() {
+        match self.kind() {
             GenericArgKind::Lifetime(_) => false,
             // FIXME: This shouldn't return numerical/float.
             GenericArgKind::Type(ty) => ty.is_ty_or_numeric_infer(),
@@ -327,7 +327,7 @@ impl<'a, 'tcx> Lift<TyCtxt<'tcx>> for GenericArg<'a> {
     type Lifted = GenericArg<'tcx>;
 
     fn lift_to_interner(self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
-        match self.unpack() {
+        match self.kind() {
             GenericArgKind::Lifetime(lt) => tcx.lift(lt).map(|lt| lt.into()),
             GenericArgKind::Type(ty) => tcx.lift(ty).map(|ty| ty.into()),
             GenericArgKind::Const(ct) => tcx.lift(ct).map(|ct| ct.into()),
@@ -340,7 +340,7 @@ impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for GenericArg<'tcx> {
         self,
         folder: &mut F,
     ) -> Result<Self, F::Error> {
-        match self.unpack() {
+        match self.kind() {
             GenericArgKind::Lifetime(lt) => lt.try_fold_with(folder).map(Into::into),
             GenericArgKind::Type(ty) => ty.try_fold_with(folder).map(Into::into),
             GenericArgKind::Const(ct) => ct.try_fold_with(folder).map(Into::into),
@@ -348,7 +348,7 @@ impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for GenericArg<'tcx> {
     }
 
     fn fold_with<F: TypeFolder<TyCtxt<'tcx>>>(self, folder: &mut F) -> Self {
-        match self.unpack() {
+        match self.kind() {
             GenericArgKind::Lifetime(lt) => lt.fold_with(folder).into(),
             GenericArgKind::Type(ty) => ty.fold_with(folder).into(),
             GenericArgKind::Const(ct) => ct.fold_with(folder).into(),
@@ -358,7 +358,7 @@ impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for GenericArg<'tcx> {
 
 impl<'tcx> TypeVisitable<TyCtxt<'tcx>> for GenericArg<'tcx> {
     fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> V::Result {
-        match self.unpack() {
+        match self.kind() {
             GenericArgKind::Lifetime(lt) => lt.visit_with(visitor),
             GenericArgKind::Type(ty) => ty.visit_with(visitor),
             GenericArgKind::Const(ct) => ct.visit_with(visitor),
@@ -368,7 +368,7 @@ impl<'tcx> TypeVisitable<TyCtxt<'tcx>> for GenericArg<'tcx> {
 
 impl<'tcx, E: TyEncoder<'tcx>> Encodable<E> for GenericArg<'tcx> {
     fn encode(&self, e: &mut E) {
-        self.unpack().encode(e)
+        self.kind().encode(e)
     }
 }
 
@@ -390,7 +390,7 @@ impl<'tcx> GenericArgs<'tcx> {
     ///
     /// If any of the generic arguments are not types.
     pub fn into_type_list(&self, tcx: TyCtxt<'tcx>) -> &'tcx List<Ty<'tcx>> {
-        tcx.mk_type_list_from_iter(self.iter().map(|arg| match arg.unpack() {
+        tcx.mk_type_list_from_iter(self.iter().map(|arg| match arg.kind() {
             GenericArgKind::Type(ty) => ty,
             _ => bug!("`into_type_list` called on generic arg with non-types"),
         }))
@@ -527,7 +527,7 @@ impl<'tcx> GenericArgs<'tcx> {
     /// Returns generic arguments that are not lifetimes.
     #[inline]
     pub fn non_erasable_generics(&self) -> impl DoubleEndedIterator<Item = GenericArgKind<'tcx>> {
-        self.iter().filter_map(|k| match k.unpack() {
+        self.iter().filter_map(|arg| match arg.kind() {
             ty::GenericArgKind::Lifetime(_) => None,
             generic => Some(generic),
         })
diff --git a/compiler/rustc_middle/src/ty/impls_ty.rs b/compiler/rustc_middle/src/ty/impls_ty.rs
index 5f6305bb48a..ac45ce887c9 100644
--- a/compiler/rustc_middle/src/ty/impls_ty.rs
+++ b/compiler/rustc_middle/src/ty/impls_ty.rs
@@ -60,7 +60,7 @@ where
 
 impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for ty::GenericArg<'tcx> {
     fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
-        self.unpack().hash_stable(hcx, hasher);
+        self.kind().hash_stable(hcx, hasher);
     }
 }
 
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index f57329608ef..af31f7ed33b 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -74,8 +74,8 @@ pub use self::closure::{
     place_to_string_for_capture,
 };
 pub use self::consts::{
-    AnonConstKind, Const, ConstInt, ConstKind, Expr, ExprKind, ScalarInt, UnevaluatedConst,
-    ValTree, ValTreeKind, Value,
+    AnonConstKind, AtomicOrdering, Const, ConstInt, ConstKind, Expr, ExprKind, ScalarInt,
+    UnevaluatedConst, ValTree, ValTreeKind, Value,
 };
 pub use self::context::{
     CtxtInterners, CurrentGcx, DeducedParamAttrs, Feed, FreeRegionInfo, GlobalCtxt, Lift, TyCtxt,
@@ -504,7 +504,7 @@ impl<'tcx> rustc_type_ir::inherent::IntoKind for Term<'tcx> {
     type Kind = TermKind<'tcx>;
 
     fn kind(self) -> Self::Kind {
-        self.unpack()
+        self.kind()
     }
 }
 
@@ -521,7 +521,7 @@ unsafe impl<'tcx> Sync for Term<'tcx> where &'tcx (Ty<'tcx>, Const<'tcx>): Sync
 
 impl Debug for Term<'_> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        match self.unpack() {
+        match self.kind() {
             TermKind::Ty(ty) => write!(f, "Term::Ty({ty:?})"),
             TermKind::Const(ct) => write!(f, "Term::Const({ct:?})"),
         }
@@ -542,7 +542,7 @@ impl<'tcx> From<Const<'tcx>> for Term<'tcx> {
 
 impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for Term<'tcx> {
     fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
-        self.unpack().hash_stable(hcx, hasher);
+        self.kind().hash_stable(hcx, hasher);
     }
 }
 
@@ -551,14 +551,14 @@ impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for Term<'tcx> {
         self,
         folder: &mut F,
     ) -> Result<Self, F::Error> {
-        match self.unpack() {
+        match self.kind() {
             ty::TermKind::Ty(ty) => ty.try_fold_with(folder).map(Into::into),
             ty::TermKind::Const(ct) => ct.try_fold_with(folder).map(Into::into),
         }
     }
 
     fn fold_with<F: TypeFolder<TyCtxt<'tcx>>>(self, folder: &mut F) -> Self {
-        match self.unpack() {
+        match self.kind() {
             ty::TermKind::Ty(ty) => ty.fold_with(folder).into(),
             ty::TermKind::Const(ct) => ct.fold_with(folder).into(),
         }
@@ -567,7 +567,7 @@ impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for Term<'tcx> {
 
 impl<'tcx> TypeVisitable<TyCtxt<'tcx>> for Term<'tcx> {
     fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> V::Result {
-        match self.unpack() {
+        match self.kind() {
             ty::TermKind::Ty(ty) => ty.visit_with(visitor),
             ty::TermKind::Const(ct) => ct.visit_with(visitor),
         }
@@ -576,7 +576,7 @@ impl<'tcx> TypeVisitable<TyCtxt<'tcx>> for Term<'tcx> {
 
 impl<'tcx, E: TyEncoder<'tcx>> Encodable<E> for Term<'tcx> {
     fn encode(&self, e: &mut E) {
-        self.unpack().encode(e)
+        self.kind().encode(e)
     }
 }
 
@@ -589,7 +589,7 @@ impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for Term<'tcx> {
 
 impl<'tcx> Term<'tcx> {
     #[inline]
-    pub fn unpack(self) -> TermKind<'tcx> {
+    pub fn kind(self) -> TermKind<'tcx> {
         let ptr =
             unsafe { self.ptr.map_addr(|addr| NonZero::new_unchecked(addr.get() & !TAG_MASK)) };
         // SAFETY: use of `Interned::new_unchecked` here is ok because these
@@ -609,7 +609,7 @@ impl<'tcx> Term<'tcx> {
     }
 
     pub fn as_type(&self) -> Option<Ty<'tcx>> {
-        if let TermKind::Ty(ty) = self.unpack() { Some(ty) } else { None }
+        if let TermKind::Ty(ty) = self.kind() { Some(ty) } else { None }
     }
 
     pub fn expect_type(&self) -> Ty<'tcx> {
@@ -617,7 +617,7 @@ impl<'tcx> Term<'tcx> {
     }
 
     pub fn as_const(&self) -> Option<Const<'tcx>> {
-        if let TermKind::Const(c) = self.unpack() { Some(c) } else { None }
+        if let TermKind::Const(c) = self.kind() { Some(c) } else { None }
     }
 
     pub fn expect_const(&self) -> Const<'tcx> {
@@ -625,14 +625,14 @@ impl<'tcx> Term<'tcx> {
     }
 
     pub fn into_arg(self) -> GenericArg<'tcx> {
-        match self.unpack() {
+        match self.kind() {
             TermKind::Ty(ty) => ty.into(),
             TermKind::Const(c) => c.into(),
         }
     }
 
     pub fn to_alias_term(self) -> Option<AliasTerm<'tcx>> {
-        match self.unpack() {
+        match self.kind() {
             TermKind::Ty(ty) => match *ty.kind() {
                 ty::Alias(_kind, alias_ty) => Some(alias_ty.into()),
                 _ => None,
@@ -645,7 +645,7 @@ impl<'tcx> Term<'tcx> {
     }
 
     pub fn is_infer(&self) -> bool {
-        match self.unpack() {
+        match self.kind() {
             TermKind::Ty(ty) => ty.is_ty_var(),
             TermKind::Const(ct) => ct.is_ct_infer(),
         }
diff --git a/compiler/rustc_middle/src/ty/opaque_types.rs b/compiler/rustc_middle/src/ty/opaque_types.rs
index 9445a18ad76..2b024b7b6cb 100644
--- a/compiler/rustc_middle/src/ty/opaque_types.rs
+++ b/compiler/rustc_middle/src/ty/opaque_types.rs
@@ -120,7 +120,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ReverseMapper<'tcx> {
             }
         }
 
-        match self.map.get(&r.into()).map(|k| k.unpack()) {
+        match self.map.get(&r.into()).map(|arg| arg.kind()) {
             Some(GenericArgKind::Lifetime(r1)) => r1,
             Some(u) => panic!("region mapped to unexpected kind: {u:?}"),
             None if self.do_not_error => self.tcx.lifetimes.re_static,
@@ -162,7 +162,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ReverseMapper<'tcx> {
 
             ty::Param(param) => {
                 // Look it up in the generic parameters list.
-                match self.map.get(&ty.into()).map(|k| k.unpack()) {
+                match self.map.get(&ty.into()).map(|arg| arg.kind()) {
                     // Found it in the generic parameters list; replace with the parameter from the
                     // opaque type.
                     Some(GenericArgKind::Type(t1)) => t1,
@@ -195,7 +195,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ReverseMapper<'tcx> {
         match ct.kind() {
             ty::ConstKind::Param(..) => {
                 // Look it up in the generic parameters list.
-                match self.map.get(&ct.into()).map(|k| k.unpack()) {
+                match self.map.get(&ct.into()).map(|arg| arg.kind()) {
                     // Found it in the generic parameters list, replace with the parameter from the
                     // opaque type.
                     Some(GenericArgKind::Const(c1)) => c1,
diff --git a/compiler/rustc_middle/src/ty/predicate.rs b/compiler/rustc_middle/src/ty/predicate.rs
index 551d816941b..bc2ac42b6b1 100644
--- a/compiler/rustc_middle/src/ty/predicate.rs
+++ b/compiler/rustc_middle/src/ty/predicate.rs
@@ -238,6 +238,8 @@ impl<'tcx> Clause<'tcx> {
     }
 }
 
+impl<'tcx> rustc_type_ir::inherent::Clauses<TyCtxt<'tcx>> for ty::Clauses<'tcx> {}
+
 #[extension(pub trait ExistentialPredicateStableCmpExt<'tcx>)]
 impl<'tcx> ExistentialPredicate<'tcx> {
     /// Compares via an ordering that will not change if modules are reordered or other changes are
diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs
index 6fd6aff0e2b..877bea095f9 100644
--- a/compiler/rustc_middle/src/ty/print/pretty.rs
+++ b/compiler/rustc_middle/src/ty/print/pretty.rs
@@ -1239,7 +1239,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
 
                         p!(write("{} = ", tcx.associated_item(assoc_item_def_id).name()));
 
-                        match term.unpack() {
+                        match term.kind() {
                             TermKind::Ty(ty) => p!(print(ty)),
                             TermKind::Const(c) => p!(print(c)),
                         };
@@ -3386,7 +3386,7 @@ define_print_and_forward_display! {
     }
 
     ty::Term<'tcx> {
-      match self.unpack() {
+      match self.kind() {
         ty::TermKind::Ty(ty) => p!(print(ty)),
         ty::TermKind::Const(c) => p!(print(c)),
       }
@@ -3401,7 +3401,7 @@ define_print_and_forward_display! {
     }
 
     GenericArg<'tcx> {
-        match self.unpack() {
+        match self.kind() {
             GenericArgKind::Lifetime(lt) => p!(print(lt)),
             GenericArgKind::Type(ty) => p!(print(ty)),
             GenericArgKind::Const(ct) => p!(print(ct)),
diff --git a/compiler/rustc_middle/src/ty/relate.rs b/compiler/rustc_middle/src/ty/relate.rs
index 6ad4e5276b2..dc1d60f3d43 100644
--- a/compiler/rustc_middle/src/ty/relate.rs
+++ b/compiler/rustc_middle/src/ty/relate.rs
@@ -169,7 +169,7 @@ impl<'tcx> Relate<TyCtxt<'tcx>> for ty::GenericArg<'tcx> {
         a: ty::GenericArg<'tcx>,
         b: ty::GenericArg<'tcx>,
     ) -> RelateResult<'tcx, ty::GenericArg<'tcx>> {
-        match (a.unpack(), b.unpack()) {
+        match (a.kind(), b.kind()) {
             (ty::GenericArgKind::Lifetime(a_lt), ty::GenericArgKind::Lifetime(b_lt)) => {
                 Ok(relation.relate(a_lt, b_lt)?.into())
             }
@@ -190,7 +190,7 @@ impl<'tcx> Relate<TyCtxt<'tcx>> for ty::Term<'tcx> {
         a: Self,
         b: Self,
     ) -> RelateResult<'tcx, Self> {
-        Ok(match (a.unpack(), b.unpack()) {
+        Ok(match (a.kind(), b.kind()) {
             (ty::TermKind::Ty(a), ty::TermKind::Ty(b)) => relation.relate(a, b)?.into(),
             (ty::TermKind::Const(a), ty::TermKind::Const(b)) => relation.relate(a, b)?.into(),
             _ => return Err(TypeError::Mismatch),
diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs
index 58f7bc75054..000ba7b6fa7 100644
--- a/compiler/rustc_middle/src/ty/structural_impls.rs
+++ b/compiler/rustc_middle/src/ty/structural_impls.rs
@@ -202,7 +202,7 @@ impl<T: fmt::Debug> fmt::Debug for ty::Placeholder<T> {
 
 impl<'tcx> fmt::Debug for GenericArg<'tcx> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        match self.unpack() {
+        match self.kind() {
             GenericArgKind::Lifetime(lt) => lt.fmt(f),
             GenericArgKind::Type(ty) => ty.fmt(f),
             GenericArgKind::Const(ct) => ct.fmt(f),
@@ -326,7 +326,7 @@ impl<'tcx, T: Lift<TyCtxt<'tcx>>> Lift<TyCtxt<'tcx>> for Option<T> {
 impl<'a, 'tcx> Lift<TyCtxt<'tcx>> for Term<'a> {
     type Lifted = ty::Term<'tcx>;
     fn lift_to_interner(self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
-        match self.unpack() {
+        match self.kind() {
             TermKind::Ty(ty) => tcx.lift(ty).map(Into::into),
             TermKind::Const(c) => tcx.lift(c).map(Into::into),
         }
@@ -570,6 +570,19 @@ impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for ty::Clause<'tcx> {
     }
 }
 
+impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for ty::Clauses<'tcx> {
+    fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
+        self,
+        folder: &mut F,
+    ) -> Result<Self, F::Error> {
+        folder.try_fold_clauses(self)
+    }
+
+    fn fold_with<F: TypeFolder<TyCtxt<'tcx>>>(self, folder: &mut F) -> Self {
+        folder.fold_clauses(self)
+    }
+}
+
 impl<'tcx> TypeVisitable<TyCtxt<'tcx>> for ty::Predicate<'tcx> {
     fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> V::Result {
         visitor.visit_predicate(*self)
@@ -615,6 +628,19 @@ impl<'tcx> TypeSuperVisitable<TyCtxt<'tcx>> for ty::Clauses<'tcx> {
     }
 }
 
+impl<'tcx> TypeSuperFoldable<TyCtxt<'tcx>> for ty::Clauses<'tcx> {
+    fn try_super_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
+        self,
+        folder: &mut F,
+    ) -> Result<Self, F::Error> {
+        ty::util::try_fold_list(self, folder, |tcx, v| tcx.mk_clauses(v))
+    }
+
+    fn super_fold_with<F: TypeFolder<TyCtxt<'tcx>>>(self, folder: &mut F) -> Self {
+        ty::util::fold_list(self, folder, |tcx, v| tcx.mk_clauses(v))
+    }
+}
+
 impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for ty::Const<'tcx> {
     fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
         self,
@@ -775,7 +801,6 @@ macro_rules! list_fold {
 }
 
 list_fold! {
-    ty::Clauses<'tcx> : mk_clauses,
     &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>> : mk_poly_existential_predicates,
     &'tcx ty::List<PlaceElem<'tcx>> : mk_place_elems,
     &'tcx ty::List<ty::Pattern<'tcx>> : mk_patterns,
diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs
index 77b9becba57..404674c359e 100644
--- a/compiler/rustc_middle/src/ty/sty.rs
+++ b/compiler/rustc_middle/src/ty/sty.rs
@@ -1882,10 +1882,8 @@ impl<'tcx> Ty<'tcx> {
             // Needs normalization or revealing to determine, so no is the safe answer.
             ty::Alias(..) => false,
 
-            ty::Param(..) | ty::Placeholder(..) | ty::Infer(..) | ty::Error(..) => false,
-
-            ty::Bound(..) => {
-                bug!("`is_trivially_pure_clone_copy` applied to unexpected type: {:?}", self);
+            ty::Param(..) | ty::Placeholder(..) | ty::Bound(..) | ty::Infer(..) | ty::Error(..) => {
+                false
             }
         }
     }
diff --git a/compiler/rustc_middle/src/ty/typeck_results.rs b/compiler/rustc_middle/src/ty/typeck_results.rs
index c6a45f84686..cc3887079d8 100644
--- a/compiler/rustc_middle/src/ty/typeck_results.rs
+++ b/compiler/rustc_middle/src/ty/typeck_results.rs
@@ -777,8 +777,8 @@ impl<'tcx> IsIdentity for CanonicalUserType<'tcx> {
                     return false;
                 }
 
-                iter::zip(user_args.args, BoundVar::ZERO..).all(|(kind, cvar)| {
-                    match kind.unpack() {
+                iter::zip(user_args.args, BoundVar::ZERO..).all(|(arg, cvar)| {
+                    match arg.kind() {
                         GenericArgKind::Type(ty) => match ty.kind() {
                             ty::Bound(debruijn, b) => {
                                 // We only allow a `ty::INNERMOST` index in generic parameters.
diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs
index ecf83926df7..461d92f8006 100644
--- a/compiler/rustc_middle/src/ty/util.rs
+++ b/compiler/rustc_middle/src/ty/util.rs
@@ -516,8 +516,8 @@ impl<'tcx> TyCtxt<'tcx> {
         let item_args = ty::GenericArgs::identity_for_item(self, def.did());
 
         let result = iter::zip(item_args, impl_args)
-            .filter(|&(_, k)| {
-                match k.unpack() {
+            .filter(|&(_, arg)| {
+                match arg.kind() {
                     GenericArgKind::Lifetime(region) => match region.kind() {
                         ty::ReEarlyParam(ebr) => {
                             !impl_generics.region_param(ebr, self).pure_wrt_drop
@@ -554,7 +554,7 @@ impl<'tcx> TyCtxt<'tcx> {
         let mut seen = GrowableBitSet::default();
         let mut seen_late = FxHashSet::default();
         for arg in args {
-            match arg.unpack() {
+            match arg.kind() {
                 GenericArgKind::Lifetime(lt) => match (ignore_regions, lt.kind()) {
                     (CheckRegions::FromFunction, ty::ReBound(di, reg)) => {
                         if !seen_late.insert((di, reg)) {
diff --git a/compiler/rustc_middle/src/ty/vtable.rs b/compiler/rustc_middle/src/ty/vtable.rs
index 6c9e0e7c0eb..74b6a840a2e 100644
--- a/compiler/rustc_middle/src/ty/vtable.rs
+++ b/compiler/rustc_middle/src/ty/vtable.rs
@@ -110,7 +110,7 @@ pub(super) fn vtable_allocation_provider<'tcx>(
     let ptr_align = tcx.data_layout.pointer_align.abi;
 
     let vtable_size = ptr_size * u64::try_from(vtable_entries.len()).unwrap();
-    let mut vtable = Allocation::new(vtable_size, ptr_align, AllocInit::Uninit);
+    let mut vtable = Allocation::new(vtable_size, ptr_align, AllocInit::Uninit, ());
 
     // No need to do any alignment checks on the memory accesses below, because we know the
     // allocation is correctly aligned as we created it above. Also we're only offsetting by
diff --git a/compiler/rustc_mir_build/src/builder/custom/parse/instruction.rs b/compiler/rustc_mir_build/src/builder/custom/parse/instruction.rs
index 494ee33fd8b..9825b947fe0 100644
--- a/compiler/rustc_mir_build/src/builder/custom/parse/instruction.rs
+++ b/compiler/rustc_mir_build/src/builder/custom/parse/instruction.rs
@@ -323,9 +323,9 @@ impl<'a, 'tcx> ParseCtxt<'a, 'tcx> {
     fn parse_place_inner(&self, expr_id: ExprId) -> PResult<(Place<'tcx>, PlaceTy<'tcx>)> {
         let (parent, proj) = parse_by_kind!(self, expr_id, expr, "place",
             @call(mir_field, args) => {
-                let (parent, ty) = self.parse_place_inner(args[0])?;
+                let (parent, place_ty) = self.parse_place_inner(args[0])?;
                 let field = FieldIdx::from_u32(self.parse_integer_literal(args[1])? as u32);
-                let field_ty = ty.field_ty(self.tcx, field);
+                let field_ty = PlaceTy::field_ty(self.tcx, place_ty.ty, place_ty.variant_index, field);
                 let proj = PlaceElem::Field(field, field_ty);
                 let place = parent.project_deeper(&[proj], self.tcx);
                 return Ok((place, PlaceTy::from_ty(field_ty)));
diff --git a/compiler/rustc_mir_build/src/builder/expr/as_constant.rs b/compiler/rustc_mir_build/src/builder/expr/as_constant.rs
index 64d092e0354..eb8e98ec364 100644
--- a/compiler/rustc_mir_build/src/builder/expr/as_constant.rs
+++ b/compiler/rustc_mir_build/src/builder/expr/as_constant.rs
@@ -121,14 +121,14 @@ fn lit_to_mir_constant<'tcx>(tcx: TyCtxt<'tcx>, lit_input: LitToConstInput<'tcx>
     let value = match (lit, lit_ty.kind()) {
         (ast::LitKind::Str(s, _), ty::Ref(_, inner_ty, _)) if inner_ty.is_str() => {
             let s = s.as_str();
-            let allocation = Allocation::from_bytes_byte_aligned_immutable(s.as_bytes());
+            let allocation = Allocation::from_bytes_byte_aligned_immutable(s.as_bytes(), ());
             let allocation = tcx.mk_const_alloc(allocation);
             ConstValue::Slice { data: allocation, meta: allocation.inner().size().bytes() }
         }
         (ast::LitKind::ByteStr(data, _), ty::Ref(_, inner_ty, _))
             if matches!(inner_ty.kind(), ty::Slice(_)) =>
         {
-            let allocation = Allocation::from_bytes_byte_aligned_immutable(data as &[u8]);
+            let allocation = Allocation::from_bytes_byte_aligned_immutable(data as &[u8], ());
             let allocation = tcx.mk_const_alloc(allocation);
             ConstValue::Slice { data: allocation, meta: allocation.inner().size().bytes() }
         }
@@ -138,7 +138,7 @@ fn lit_to_mir_constant<'tcx>(tcx: TyCtxt<'tcx>, lit_input: LitToConstInput<'tcx>
         }
         (ast::LitKind::CStr(data, _), ty::Ref(_, inner_ty, _)) if matches!(inner_ty.kind(), ty::Adt(def, _) if tcx.is_lang_item(def.did(), LangItem::CStr)) =>
         {
-            let allocation = Allocation::from_bytes_byte_aligned_immutable(data as &[u8]);
+            let allocation = Allocation::from_bytes_byte_aligned_immutable(data as &[u8], ());
             let allocation = tcx.mk_const_alloc(allocation);
             ConstValue::Slice { data: allocation, meta: allocation.inner().size().bytes() }
         }
diff --git a/compiler/rustc_mir_build/src/builder/expr/as_place.rs b/compiler/rustc_mir_build/src/builder/expr/as_place.rs
index fbe53081156..f8c64d7d13e 100644
--- a/compiler/rustc_mir_build/src/builder/expr/as_place.rs
+++ b/compiler/rustc_mir_build/src/builder/expr/as_place.rs
@@ -101,12 +101,12 @@ fn convert_to_hir_projections_and_truncate_for_capture(
                 variant = Some(*idx);
                 continue;
             }
+            ProjectionElem::UnwrapUnsafeBinder(_) => HirProjectionKind::UnwrapUnsafeBinder,
             // These do not affect anything, they just make sure we know the right type.
             ProjectionElem::OpaqueCast(_) | ProjectionElem::Subtype(..) => continue,
             ProjectionElem::Index(..)
             | ProjectionElem::ConstantIndex { .. }
-            | ProjectionElem::Subslice { .. }
-            | ProjectionElem::UnwrapUnsafeBinder(_) => {
+            | ProjectionElem::Subslice { .. } => {
                 // We don't capture array-access projections.
                 // We can stop here as arrays are captured completely.
                 break;
@@ -240,6 +240,9 @@ fn strip_prefix<'tcx>(
             HirProjectionKind::OpaqueCast => {
                 assert_matches!(iter.next(), Some(ProjectionElem::OpaqueCast(..)));
             }
+            HirProjectionKind::UnwrapUnsafeBinder => {
+                assert_matches!(iter.next(), Some(ProjectionElem::UnwrapUnsafeBinder(..)));
+            }
             HirProjectionKind::Index | HirProjectionKind::Subslice => {
                 bug!("unexpected projection kind: {:?}", projection);
             }
diff --git a/compiler/rustc_mir_build/src/builder/mod.rs b/compiler/rustc_mir_build/src/builder/mod.rs
index 127b191e335..3d5f6f4cf45 100644
--- a/compiler/rustc_mir_build/src/builder/mod.rs
+++ b/compiler/rustc_mir_build/src/builder/mod.rs
@@ -558,7 +558,7 @@ fn construct_const<'a, 'tcx>(
     // Figure out what primary body this item has.
     let (span, const_ty_span) = match tcx.hir_node(hir_id) {
         Node::Item(hir::Item {
-            kind: hir::ItemKind::Static(_, ty, _, _) | hir::ItemKind::Const(_, ty, _, _),
+            kind: hir::ItemKind::Static(_, _, ty, _) | hir::ItemKind::Const(_, _, ty, _),
             span,
             ..
         })
diff --git a/compiler/rustc_mir_build/src/builder/scope.rs b/compiler/rustc_mir_build/src/builder/scope.rs
index 2a30777e98c..67988f1fcbc 100644
--- a/compiler/rustc_mir_build/src/builder/scope.rs
+++ b/compiler/rustc_mir_build/src/builder/scope.rs
@@ -209,7 +209,7 @@ const ROOT_NODE: DropIdx = DropIdx::ZERO;
 #[derive(Debug)]
 struct DropTree {
     /// Nodes in the drop tree, containing drop data and a link to the next node.
-    drops: IndexVec<DropIdx, DropNode>,
+    drop_nodes: IndexVec<DropIdx, DropNode>,
     /// Map for finding the index of an existing node, given its contents.
     existing_drops_map: FxHashMap<DropNodeKey, DropIdx>,
     /// Edges into the `DropTree` that need to be added once it's lowered.
@@ -230,7 +230,6 @@ struct DropNode {
 struct DropNodeKey {
     next: DropIdx,
     local: Local,
-    kind: DropKind,
 }
 
 impl Scope {
@@ -278,8 +277,8 @@ impl DropTree {
         let fake_source_info = SourceInfo::outermost(DUMMY_SP);
         let fake_data =
             DropData { source_info: fake_source_info, local: Local::MAX, kind: DropKind::Storage };
-        let drops = IndexVec::from_raw(vec![DropNode { data: fake_data, next: DropIdx::MAX }]);
-        Self { drops, entry_points: Vec::new(), existing_drops_map: FxHashMap::default() }
+        let drop_nodes = IndexVec::from_raw(vec![DropNode { data: fake_data, next: DropIdx::MAX }]);
+        Self { drop_nodes, entry_points: Vec::new(), existing_drops_map: FxHashMap::default() }
     }
 
     /// Adds a node to the drop tree, consisting of drop data and the index of
@@ -288,12 +287,12 @@ impl DropTree {
     /// If there is already an equivalent node in the tree, nothing is added, and
     /// that node's index is returned. Otherwise, the new node's index is returned.
     fn add_drop(&mut self, data: DropData, next: DropIdx) -> DropIdx {
-        let drops = &mut self.drops;
+        let drop_nodes = &mut self.drop_nodes;
         *self
             .existing_drops_map
-            .entry(DropNodeKey { next, local: data.local, kind: data.kind })
+            .entry(DropNodeKey { next, local: data.local })
             // Create a new node, and also add its index to the map.
-            .or_insert_with(|| drops.push(DropNode { data, next }))
+            .or_insert_with(|| drop_nodes.push(DropNode { data, next }))
     }
 
     /// Registers `from` as an entry point to this drop tree, at `to`.
@@ -301,7 +300,7 @@ impl DropTree {
     /// During [`Self::build_mir`], `from` will be linked to the corresponding
     /// block within the drop tree.
     fn add_entry_point(&mut self, from: BasicBlock, to: DropIdx) {
-        debug_assert!(to < self.drops.next_index());
+        debug_assert!(to < self.drop_nodes.next_index());
         self.entry_points.push((to, from));
     }
 
@@ -341,10 +340,10 @@ impl DropTree {
             Own,
         }
 
-        let mut blocks = IndexVec::from_elem(None, &self.drops);
+        let mut blocks = IndexVec::from_elem(None, &self.drop_nodes);
         blocks[ROOT_NODE] = root_node;
 
-        let mut needs_block = IndexVec::from_elem(Block::None, &self.drops);
+        let mut needs_block = IndexVec::from_elem(Block::None, &self.drop_nodes);
         if root_node.is_some() {
             // In some cases (such as drops for `continue`) the root node
             // already has a block. In this case, make sure that we don't
@@ -356,7 +355,7 @@ impl DropTree {
         let entry_points = &mut self.entry_points;
         entry_points.sort();
 
-        for (drop_idx, drop_node) in self.drops.iter_enumerated().rev() {
+        for (drop_idx, drop_node) in self.drop_nodes.iter_enumerated().rev() {
             if entry_points.last().is_some_and(|entry_point| entry_point.0 == drop_idx) {
                 let block = *blocks[drop_idx].get_or_insert_with(|| T::make_block(cfg));
                 needs_block[drop_idx] = Block::Own;
@@ -396,7 +395,7 @@ impl DropTree {
         cfg: &mut CFG<'tcx>,
         blocks: &IndexSlice<DropIdx, Option<BasicBlock>>,
     ) {
-        for (drop_idx, drop_node) in self.drops.iter_enumerated().rev() {
+        for (drop_idx, drop_node) in self.drop_nodes.iter_enumerated().rev() {
             let Some(block) = blocks[drop_idx] else { continue };
             match drop_node.data.kind {
                 DropKind::Value => {
@@ -726,11 +725,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             drops
         };
 
-        let drop_idx = self.scopes.scopes[scope_index + 1..]
-            .iter()
-            .flat_map(|scope| &scope.drops)
-            .fold(ROOT_NODE, |drop_idx, &drop| drops.add_drop(drop, drop_idx));
-
+        let mut drop_idx = ROOT_NODE;
+        for scope in &self.scopes.scopes[scope_index + 1..] {
+            for drop in &scope.drops {
+                drop_idx = drops.add_drop(*drop, drop_idx);
+            }
+        }
         drops.add_entry_point(block, drop_idx);
 
         // `build_drop_trees` doesn't have access to our source_info, so we
@@ -829,9 +829,15 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                         // `unwind_to` should drop the value that we're about to
                         // schedule. If dropping this value panics, then we continue
                         // with the *next* value on the unwind path.
-                        debug_assert_eq!(unwind_drops.drops[unwind_to].data.local, drop_data.local);
-                        debug_assert_eq!(unwind_drops.drops[unwind_to].data.kind, drop_data.kind);
-                        unwind_to = unwind_drops.drops[unwind_to].next;
+                        debug_assert_eq!(
+                            unwind_drops.drop_nodes[unwind_to].data.local,
+                            drop_data.local
+                        );
+                        debug_assert_eq!(
+                            unwind_drops.drop_nodes[unwind_to].data.kind,
+                            drop_data.kind
+                        );
+                        unwind_to = unwind_drops.drop_nodes[unwind_to].next;
 
                         let mut unwind_entry_point = unwind_to;
 
@@ -1551,14 +1557,14 @@ where
                 //
                 // We adjust this BEFORE we create the drop (e.g., `drops[n]`)
                 // because `drops[n]` should unwind to `drops[n-1]`.
-                debug_assert_eq!(unwind_drops.drops[unwind_to].data.local, drop_data.local);
-                debug_assert_eq!(unwind_drops.drops[unwind_to].data.kind, drop_data.kind);
-                unwind_to = unwind_drops.drops[unwind_to].next;
+                debug_assert_eq!(unwind_drops.drop_nodes[unwind_to].data.local, drop_data.local);
+                debug_assert_eq!(unwind_drops.drop_nodes[unwind_to].data.kind, drop_data.kind);
+                unwind_to = unwind_drops.drop_nodes[unwind_to].next;
 
                 if let Some(idx) = dropline_to {
-                    debug_assert_eq!(coroutine_drops.drops[idx].data.local, drop_data.local);
-                    debug_assert_eq!(coroutine_drops.drops[idx].data.kind, drop_data.kind);
-                    dropline_to = Some(coroutine_drops.drops[idx].next);
+                    debug_assert_eq!(coroutine_drops.drop_nodes[idx].data.local, drop_data.local);
+                    debug_assert_eq!(coroutine_drops.drop_nodes[idx].data.kind, drop_data.kind);
+                    dropline_to = Some(coroutine_drops.drop_nodes[idx].next);
                 }
 
                 // If the operand has been moved, and we are not on an unwind
@@ -1598,9 +1604,12 @@ where
                 // cases we emit things ALSO on the unwind path, so we need to adjust
                 // `unwind_to` in that case.
                 if storage_dead_on_unwind {
-                    debug_assert_eq!(unwind_drops.drops[unwind_to].data.local, drop_data.local);
-                    debug_assert_eq!(unwind_drops.drops[unwind_to].data.kind, drop_data.kind);
-                    unwind_to = unwind_drops.drops[unwind_to].next;
+                    debug_assert_eq!(
+                        unwind_drops.drop_nodes[unwind_to].data.local,
+                        drop_data.local
+                    );
+                    debug_assert_eq!(unwind_drops.drop_nodes[unwind_to].data.kind, drop_data.kind);
+                    unwind_to = unwind_drops.drop_nodes[unwind_to].next;
                 }
 
                 // If the operand has been moved, and we are not on an unwind
@@ -1629,14 +1638,17 @@ where
                 // the storage-dead has completed, we need to adjust the `unwind_to` pointer
                 // so that any future drops we emit will not register storage-dead.
                 if storage_dead_on_unwind {
-                    debug_assert_eq!(unwind_drops.drops[unwind_to].data.local, drop_data.local);
-                    debug_assert_eq!(unwind_drops.drops[unwind_to].data.kind, drop_data.kind);
-                    unwind_to = unwind_drops.drops[unwind_to].next;
+                    debug_assert_eq!(
+                        unwind_drops.drop_nodes[unwind_to].data.local,
+                        drop_data.local
+                    );
+                    debug_assert_eq!(unwind_drops.drop_nodes[unwind_to].data.kind, drop_data.kind);
+                    unwind_to = unwind_drops.drop_nodes[unwind_to].next;
                 }
                 if let Some(idx) = dropline_to {
-                    debug_assert_eq!(coroutine_drops.drops[idx].data.local, drop_data.local);
-                    debug_assert_eq!(coroutine_drops.drops[idx].data.kind, drop_data.kind);
-                    dropline_to = Some(coroutine_drops.drops[idx].next);
+                    debug_assert_eq!(coroutine_drops.drop_nodes[idx].data.local, drop_data.local);
+                    debug_assert_eq!(coroutine_drops.drop_nodes[idx].data.kind, drop_data.kind);
+                    dropline_to = Some(coroutine_drops.drop_nodes[idx].next);
                 }
                 // Only temps and vars need their storage dead.
                 assert!(local.index() > arg_count);
@@ -1663,10 +1675,10 @@ impl<'a, 'tcx: 'a> Builder<'a, 'tcx> {
         let is_coroutine = self.coroutine.is_some();
 
         // Link the exit drop tree to unwind drop tree.
-        if drops.drops.iter().any(|drop_node| drop_node.data.kind == DropKind::Value) {
+        if drops.drop_nodes.iter().any(|drop_node| drop_node.data.kind == DropKind::Value) {
             let unwind_target = self.diverge_cleanup_target(else_scope, span);
             let mut unwind_indices = IndexVec::from_elem_n(unwind_target, 1);
-            for (drop_idx, drop_node) in drops.drops.iter_enumerated().skip(1) {
+            for (drop_idx, drop_node) in drops.drop_nodes.iter_enumerated().skip(1) {
                 match drop_node.data.kind {
                     DropKind::Storage | DropKind::ForLint => {
                         if is_coroutine {
@@ -1695,35 +1707,29 @@ impl<'a, 'tcx: 'a> Builder<'a, 'tcx> {
         }
         // Link the exit drop tree to dropline drop tree (coroutine drop path) for async drops
         if is_coroutine
-            && drops.drops.iter().any(|DropNode { data, next: _ }| {
+            && drops.drop_nodes.iter().any(|DropNode { data, next: _ }| {
                 data.kind == DropKind::Value && self.is_async_drop(data.local)
             })
         {
             let dropline_target = self.diverge_dropline_target(else_scope, span);
             let mut dropline_indices = IndexVec::from_elem_n(dropline_target, 1);
-            for (drop_idx, drop_data) in drops.drops.iter_enumerated().skip(1) {
+            for (drop_idx, drop_data) in drops.drop_nodes.iter_enumerated().skip(1) {
+                let coroutine_drop = self
+                    .scopes
+                    .coroutine_drops
+                    .add_drop(drop_data.data, dropline_indices[drop_data.next]);
                 match drop_data.data.kind {
-                    DropKind::Storage | DropKind::ForLint => {
-                        let coroutine_drop = self
-                            .scopes
-                            .coroutine_drops
-                            .add_drop(drop_data.data, dropline_indices[drop_data.next]);
-                        dropline_indices.push(coroutine_drop);
-                    }
+                    DropKind::Storage | DropKind::ForLint => {}
                     DropKind::Value => {
-                        let coroutine_drop = self
-                            .scopes
-                            .coroutine_drops
-                            .add_drop(drop_data.data, dropline_indices[drop_data.next]);
                         if self.is_async_drop(drop_data.data.local) {
                             self.scopes.coroutine_drops.add_entry_point(
                                 blocks[drop_idx].unwrap(),
                                 dropline_indices[drop_data.next],
                             );
                         }
-                        dropline_indices.push(coroutine_drop);
                     }
                 }
+                dropline_indices.push(coroutine_drop);
             }
         }
         blocks[ROOT_NODE].map(BasicBlock::unit)
@@ -1769,11 +1775,11 @@ impl<'a, 'tcx: 'a> Builder<'a, 'tcx> {
         // prevent drop elaboration from creating drop flags that would have
         // to be captured by the coroutine. I'm not sure how important this
         // optimization is, but it is here.
-        for (drop_idx, drop_node) in drops.drops.iter_enumerated() {
+        for (drop_idx, drop_node) in drops.drop_nodes.iter_enumerated() {
             if let DropKind::Value = drop_node.data.kind
                 && let Some(bb) = blocks[drop_idx]
             {
-                debug_assert!(drop_node.next < drops.drops.next_index());
+                debug_assert!(drop_node.next < drops.drop_nodes.next_index());
                 drops.entry_points.push((drop_node.next, bb));
             }
         }
diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs
index 9d0681b19b9..d5061b71699 100644
--- a/compiler/rustc_mir_build/src/check_unsafety.rs
+++ b/compiler/rustc_mir_build/src/check_unsafety.rs
@@ -201,9 +201,14 @@ impl<'tcx> UnsafetyVisitor<'_, 'tcx> {
     /// Handle closures/coroutines/inline-consts, which is unsafecked with their parent body.
     fn visit_inner_body(&mut self, def: LocalDefId) {
         if let Ok((inner_thir, expr)) = self.tcx.thir_body(def) {
-            // Runs all other queries that depend on THIR.
+            // Run all other queries that depend on THIR.
             self.tcx.ensure_done().mir_built(def);
-            let inner_thir = &inner_thir.steal();
+            let inner_thir = if self.tcx.sess.opts.unstable_opts.no_steal_thir {
+                &inner_thir.borrow()
+            } else {
+                // We don't have other use for the THIR. Steal it to reduce memory usage.
+                &inner_thir.steal()
+            };
             let hir_context = self.tcx.local_def_id_to_hir_id(def);
             let safety_context = mem::replace(&mut self.safety_context, SafetyContext::Safe);
             let mut inner_visitor = UnsafetyVisitor {
@@ -1157,7 +1162,12 @@ pub(crate) fn check_unsafety(tcx: TyCtxt<'_>, def: LocalDefId) {
     let Ok((thir, expr)) = tcx.thir_body(def) else { return };
     // Runs all other queries that depend on THIR.
     tcx.ensure_done().mir_built(def);
-    let thir = &thir.steal();
+    let thir = if tcx.sess.opts.unstable_opts.no_steal_thir {
+        &thir.borrow()
+    } else {
+        // We don't have other use for the THIR. Steal it to reduce memory usage.
+        &thir.steal()
+    };
 
     let hir_id = tcx.local_def_id_to_hir_id(def);
     let safety_context = tcx.hir_fn_sig_by_hir_id(hir_id).map_or(SafetyContext::Safe, |fn_sig| {
diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs
index fde23413972..226dc920a49 100644
--- a/compiler/rustc_mir_build/src/thir/cx/expr.rs
+++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs
@@ -1220,6 +1220,9 @@ impl<'tcx> ThirBuildCx<'tcx> {
                 HirProjectionKind::OpaqueCast => {
                     ExprKind::Use { source: self.thir.exprs.push(captured_place_expr) }
                 }
+                HirProjectionKind::UnwrapUnsafeBinder => ExprKind::PlaceUnwrapUnsafeBinder {
+                    source: self.thir.exprs.push(captured_place_expr),
+                },
                 HirProjectionKind::Index | HirProjectionKind::Subslice => {
                     // We don't capture these projections, so we can ignore them here
                     continue;
diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
index 78583a402fe..245bd866030 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
@@ -1047,26 +1047,21 @@ fn find_fallback_pattern_typo<'tcx>(
                 let hir::ItemKind::Use(path, _) = item.kind else {
                     continue;
                 };
-                for res in &path.res {
-                    if let Res::Def(DefKind::Const, id) = res
-                        && infcx.can_eq(param_env, ty, cx.tcx.type_of(id).instantiate_identity())
-                    {
-                        if cx.tcx.visibility(id).is_accessible_from(parent, cx.tcx) {
-                            // The original const is accessible, suggest using it directly.
-                            let item_name = cx.tcx.item_name(*id);
-                            accessible.push(item_name);
-                            accessible_path.push(with_no_trimmed_paths!(cx.tcx.def_path_str(id)));
-                        } else if cx
-                            .tcx
-                            .visibility(item.owner_id)
-                            .is_accessible_from(parent, cx.tcx)
-                        {
-                            // The const is accessible only through the re-export, point at
-                            // the `use`.
-                            let ident = item.kind.ident().unwrap();
-                            imported.push(ident.name);
-                            imported_spans.push(ident.span);
-                        }
+                if let Some(value_ns) = path.res.value_ns
+                    && let Res::Def(DefKind::Const, id) = value_ns
+                    && infcx.can_eq(param_env, ty, cx.tcx.type_of(id).instantiate_identity())
+                {
+                    if cx.tcx.visibility(id).is_accessible_from(parent, cx.tcx) {
+                        // The original const is accessible, suggest using it directly.
+                        let item_name = cx.tcx.item_name(id);
+                        accessible.push(item_name);
+                        accessible_path.push(with_no_trimmed_paths!(cx.tcx.def_path_str(id)));
+                    } else if cx.tcx.visibility(item.owner_id).is_accessible_from(parent, cx.tcx) {
+                        // The const is accessible only through the re-export, point at
+                        // the `use`.
+                        let ident = item.kind.ident().unwrap();
+                        imported.push(ident.name);
+                        imported_spans.push(ident.span);
                     }
                 }
             }
diff --git a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs
index e233358f386..84a0190a7fa 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs
@@ -131,7 +131,7 @@ impl<'tcx> ConstToPat<'tcx> {
                     .dcx()
                     .create_err(ConstPatternDependsOnGenericParameter { span: self.span });
                 for arg in uv.args {
-                    if let ty::GenericArgKind::Type(ty) = arg.unpack()
+                    if let ty::GenericArgKind::Type(ty) = arg.kind()
                         && let ty::Param(param_ty) = ty.kind()
                     {
                         let def_id = self.tcx.hir_enclosing_body_owner(self.id);
diff --git a/compiler/rustc_mir_transform/messages.ftl b/compiler/rustc_mir_transform/messages.ftl
index a1264471a2d..ae3062f07de 100644
--- a/compiler/rustc_mir_transform/messages.ftl
+++ b/compiler/rustc_mir_transform/messages.ftl
@@ -78,10 +78,4 @@ mir_transform_unconditional_recursion = function cannot return without recursing
 
 mir_transform_unconditional_recursion_call_site_label = recursive call site
 
-mir_transform_undefined_transmute = pointers cannot be transmuted to integers during const eval
-    .note = at compile-time, pointers do not have an integer value
-    .note2 = avoiding this restriction via `union` or raw pointers leads to compile-time undefined behavior
-    .help = for more information, see https://doc.rust-lang.org/std/mem/fn.transmute.html
-
 mir_transform_unknown_pass_name = MIR pass `{$name}` is unknown and will be ignored
-mir_transform_unnecessary_transmute = unnecessary transmute
diff --git a/compiler/rustc_mir_transform/src/check_undefined_transmutes.rs b/compiler/rustc_mir_transform/src/check_undefined_transmutes.rs
deleted file mode 100644
index daddb5dedbc..00000000000
--- a/compiler/rustc_mir_transform/src/check_undefined_transmutes.rs
+++ /dev/null
@@ -1,77 +0,0 @@
-use rustc_middle::mir::visit::Visitor;
-use rustc_middle::mir::{Body, Location, Operand, Terminator, TerminatorKind};
-use rustc_middle::ty::{AssocItem, AssocKind, TyCtxt};
-use rustc_session::lint::builtin::PTR_TO_INTEGER_TRANSMUTE_IN_CONSTS;
-use rustc_span::sym;
-
-use crate::errors;
-
-/// Check for transmutes that exhibit undefined behavior.
-/// For example, transmuting pointers to integers in a const context.
-pub(super) struct CheckUndefinedTransmutes;
-
-impl<'tcx> crate::MirLint<'tcx> for CheckUndefinedTransmutes {
-    fn run_lint(&self, tcx: TyCtxt<'tcx>, body: &Body<'tcx>) {
-        let mut checker = UndefinedTransmutesChecker { body, tcx };
-        checker.visit_body(body);
-    }
-}
-
-struct UndefinedTransmutesChecker<'a, 'tcx> {
-    body: &'a Body<'tcx>,
-    tcx: TyCtxt<'tcx>,
-}
-
-impl<'a, 'tcx> UndefinedTransmutesChecker<'a, 'tcx> {
-    // This functions checks two things:
-    // 1. `function` takes a raw pointer as input and returns an integer as output.
-    // 2. `function` is called from a const function or an associated constant.
-    //
-    // Why do we consider const functions and associated constants only?
-    //
-    // Generally, undefined behavior in const items are handled by the evaluator.
-    // But, const functions and associated constants are evaluated only when referenced.
-    // This can result in undefined behavior in a library going unnoticed until
-    // the function or constant is actually used.
-    //
-    // Therefore, we only consider const functions and associated constants here and leave
-    // other const items to be handled by the evaluator.
-    fn is_ptr_to_int_in_const(&self, function: &Operand<'tcx>) -> bool {
-        let def_id = self.body.source.def_id();
-
-        if self.tcx.is_const_fn(def_id)
-            || matches!(
-                self.tcx.opt_associated_item(def_id),
-                Some(AssocItem { kind: AssocKind::Const { .. }, .. })
-            )
-        {
-            let fn_sig = function.ty(self.body, self.tcx).fn_sig(self.tcx).skip_binder();
-            if let [input] = fn_sig.inputs() {
-                return input.is_raw_ptr() && fn_sig.output().is_integral();
-            }
-        }
-        false
-    }
-}
-
-impl<'tcx> Visitor<'tcx> for UndefinedTransmutesChecker<'_, 'tcx> {
-    // Check each block's terminator for calls to pointer to integer transmutes
-    // in const functions or associated constants and emit a lint.
-    fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location) {
-        if let TerminatorKind::Call { func, .. } = &terminator.kind
-            && let Some((func_def_id, _)) = func.const_fn_def()
-            && self.tcx.is_intrinsic(func_def_id, sym::transmute)
-            && self.is_ptr_to_int_in_const(func)
-            && let Some(call_id) = self.body.source.def_id().as_local()
-        {
-            let hir_id = self.tcx.local_def_id_to_hir_id(call_id);
-            let span = self.body.source_info(location).span;
-            self.tcx.emit_node_span_lint(
-                PTR_TO_INTEGER_TRANSMUTE_IN_CONSTS,
-                hir_id,
-                span,
-                errors::UndefinedTransmute,
-            );
-        }
-    }
-}
diff --git a/compiler/rustc_mir_transform/src/check_unnecessary_transmutes.rs b/compiler/rustc_mir_transform/src/check_unnecessary_transmutes.rs
deleted file mode 100644
index 1a3715465ad..00000000000
--- a/compiler/rustc_mir_transform/src/check_unnecessary_transmutes.rs
+++ /dev/null
@@ -1,136 +0,0 @@
-use rustc_middle::mir::visit::Visitor;
-use rustc_middle::mir::{Body, Location, Operand, Terminator, TerminatorKind};
-use rustc_middle::ty::*;
-use rustc_session::lint::builtin::UNNECESSARY_TRANSMUTES;
-use rustc_span::source_map::Spanned;
-use rustc_span::{Span, sym};
-
-use crate::errors::UnnecessaryTransmute as Error;
-
-/// Check for transmutes that overlap with stdlib methods.
-/// For example, transmuting `[u8; 4]` to `u32`.
-/// We chose not to lint u8 -> bool transmutes, see #140431
-pub(super) struct CheckUnnecessaryTransmutes;
-
-impl<'tcx> crate::MirLint<'tcx> for CheckUnnecessaryTransmutes {
-    fn run_lint(&self, tcx: TyCtxt<'tcx>, body: &Body<'tcx>) {
-        let mut checker = UnnecessaryTransmuteChecker { body, tcx };
-        checker.visit_body(body);
-    }
-}
-
-struct UnnecessaryTransmuteChecker<'a, 'tcx> {
-    body: &'a Body<'tcx>,
-    tcx: TyCtxt<'tcx>,
-}
-
-impl<'a, 'tcx> UnnecessaryTransmuteChecker<'a, 'tcx> {
-    fn is_unnecessary_transmute(
-        &self,
-        function: &Operand<'tcx>,
-        arg: String,
-        span: Span,
-        is_in_const: bool,
-    ) -> Option<Error> {
-        let fn_sig = function.ty(self.body, self.tcx).fn_sig(self.tcx).skip_binder();
-        let [input] = fn_sig.inputs() else { return None };
-
-        let err = |sugg| Error { span, sugg, help: None };
-
-        Some(match (input.kind(), fn_sig.output().kind()) {
-            // dont check the length; transmute does that for us.
-            // [u8; _] => primitive
-            (Array(t, _), Uint(_) | Float(_) | Int(_)) if *t.kind() == Uint(UintTy::U8) => Error {
-                sugg: format!("{}::from_ne_bytes({arg})", fn_sig.output()),
-                help: Some(
-                    "there's also `from_le_bytes` and `from_be_bytes` if you expect a particular byte order",
-                ),
-                span,
-            },
-            // primitive => [u8; _]
-            (Uint(_) | Float(_) | Int(_), Array(t, _)) if *t.kind() == Uint(UintTy::U8) => Error {
-                sugg: format!("{input}::to_ne_bytes({arg})"),
-                help: Some(
-                    "there's also `to_le_bytes` and `to_be_bytes` if you expect a particular byte order",
-                ),
-                span,
-            },
-            // char → u32
-            (Char, Uint(UintTy::U32)) => err(format!("u32::from({arg})")),
-            // char (→ u32) → i32
-            (Char, Int(IntTy::I32)) => err(format!("u32::from({arg}).cast_signed()")),
-            // u32 → char
-            (Uint(UintTy::U32), Char) => Error {
-                sugg: format!("char::from_u32_unchecked({arg})"),
-                help: Some("consider `char::from_u32(…).unwrap()`"),
-                span,
-            },
-            // i32 → char
-            (Int(IntTy::I32), Char) => Error {
-                sugg: format!("char::from_u32_unchecked(i32::cast_unsigned({arg}))"),
-                help: Some("consider `char::from_u32(i32::cast_unsigned(…)).unwrap()`"),
-                span,
-            },
-            // uNN → iNN
-            (Uint(ty), Int(_)) => err(format!("{}::cast_signed({arg})", ty.name_str())),
-            // iNN → uNN
-            (Int(ty), Uint(_)) => err(format!("{}::cast_unsigned({arg})", ty.name_str())),
-            // fNN → xsize
-            (Float(ty), Uint(UintTy::Usize)) => {
-                err(format!("{}::to_bits({arg}) as usize", ty.name_str()))
-            }
-            (Float(ty), Int(IntTy::Isize)) => {
-                err(format!("{}::to_bits({arg}) as isize", ty.name_str()))
-            }
-            // fNN (→ uNN) → iNN
-            (Float(ty), Int(..)) => err(format!("{}::to_bits({arg}).cast_signed()", ty.name_str())),
-            // fNN → uNN
-            (Float(ty), Uint(..)) => err(format!("{}::to_bits({arg})", ty.name_str())),
-            // xsize → fNN
-            (Uint(UintTy::Usize) | Int(IntTy::Isize), Float(ty)) => {
-                err(format!("{}::from_bits({arg} as _)", ty.name_str(),))
-            }
-            // iNN (→ uNN) → fNN
-            (Int(int_ty), Float(ty)) => err(format!(
-                "{}::from_bits({}::cast_unsigned({arg}))",
-                ty.name_str(),
-                int_ty.name_str()
-            )),
-            // uNN → fNN
-            (Uint(_), Float(ty)) => err(format!("{}::from_bits({arg})", ty.name_str())),
-            // bool → { x8 } in const context since `From::from` is not const yet
-            // FIXME: is it possible to know when the parentheses arent necessary?
-            // FIXME(const_traits): Remove this when From::from is constified?
-            (Bool, Int(..) | Uint(..)) if is_in_const => {
-                err(format!("({arg}) as {}", fn_sig.output()))
-            }
-            // " using `x8::from`
-            (Bool, Int(..) | Uint(..)) => err(format!("{}::from({arg})", fn_sig.output())),
-            _ => return None,
-        })
-    }
-}
-
-impl<'tcx> Visitor<'tcx> for UnnecessaryTransmuteChecker<'_, 'tcx> {
-    // Check each block's terminator for calls to pointer to integer transmutes
-    // in const functions or associated constants and emit a lint.
-    fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location) {
-        if let TerminatorKind::Call { func, args, .. } = &terminator.kind
-            && let [Spanned { span: arg, .. }] = **args
-            && let Some((func_def_id, _)) = func.const_fn_def()
-            && self.tcx.is_intrinsic(func_def_id, sym::transmute)
-            && let span = self.body.source_info(location).span
-            && let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(arg)
-            && let def_id = self.body.source.def_id()
-            && let Some(lint) = self.is_unnecessary_transmute(
-                func,
-                snippet,
-                span,
-                self.tcx.hir_body_const_context(def_id.expect_local()).is_some(),
-            )
-            && let Some(hir_id) = terminator.source_info.scope.lint_root(&self.body.source_scopes)
-        {
-            self.tcx.emit_node_span_lint(UNNECESSARY_TRANSMUTES, hir_id, span, lint);
-        }
-    }
-}
diff --git a/compiler/rustc_mir_transform/src/coverage/spans.rs b/compiler/rustc_mir_transform/src/coverage/spans.rs
index ddeae093df5..ec76076020e 100644
--- a/compiler/rustc_mir_transform/src/coverage/spans.rs
+++ b/compiler/rustc_mir_transform/src/coverage/spans.rs
@@ -1,8 +1,7 @@
 use rustc_data_structures::fx::FxHashSet;
 use rustc_middle::mir;
 use rustc_middle::ty::TyCtxt;
-use rustc_span::source_map::SourceMap;
-use rustc_span::{BytePos, DesugaringKind, ExpnKind, MacroKind, Span};
+use rustc_span::{DesugaringKind, ExpnKind, MacroKind, Span};
 use tracing::instrument;
 
 use crate::coverage::graph::{BasicCoverageBlock, CoverageGraph};
@@ -84,18 +83,8 @@ pub(super) fn extract_refined_covspans<'tcx>(
     // Discard any span that overlaps with a hole.
     discard_spans_overlapping_holes(&mut covspans, &holes);
 
-    // Discard spans that overlap in unwanted ways.
+    // Perform more refinement steps after holes have been dealt with.
     let mut covspans = remove_unwanted_overlapping_spans(covspans);
-
-    // For all empty spans, either enlarge them to be non-empty, or discard them.
-    let source_map = tcx.sess.source_map();
-    covspans.retain_mut(|covspan| {
-        let Some(span) = ensure_non_empty_span(source_map, covspan.span) else { return false };
-        covspan.span = span;
-        true
-    });
-
-    // Merge covspans that can be merged.
     covspans.dedup_by(|b, a| a.merge_if_eligible(b));
 
     code_mappings.extend(covspans.into_iter().map(|Covspan { span, bcb }| {
@@ -241,26 +230,3 @@ fn compare_spans(a: Span, b: Span) -> std::cmp::Ordering {
         // - Both have the same start and span A extends further right
         .then_with(|| Ord::cmp(&a.hi(), &b.hi()).reverse())
 }
-
-fn ensure_non_empty_span(source_map: &SourceMap, span: Span) -> Option<Span> {
-    if !span.is_empty() {
-        return Some(span);
-    }
-
-    // The span is empty, so try to enlarge it to cover an adjacent '{' or '}'.
-    source_map
-        .span_to_source(span, |src, start, end| try {
-            // Adjusting span endpoints by `BytePos(1)` is normally a bug,
-            // but in this case we have specifically checked that the character
-            // we're skipping over is one of two specific ASCII characters, so
-            // adjusting by exactly 1 byte is correct.
-            if src.as_bytes().get(end).copied() == Some(b'{') {
-                Some(span.with_hi(span.hi() + BytePos(1)))
-            } else if start > 0 && src.as_bytes()[start - 1] == b'}' {
-                Some(span.with_lo(span.lo() - BytePos(1)))
-            } else {
-                None
-            }
-        })
-        .ok()?
-}
diff --git a/compiler/rustc_mir_transform/src/elaborate_drop.rs b/compiler/rustc_mir_transform/src/elaborate_drop.rs
index 14f7c2a263b..c15d7d6f732 100644
--- a/compiler/rustc_mir_transform/src/elaborate_drop.rs
+++ b/compiler/rustc_mir_transform/src/elaborate_drop.rs
@@ -1,6 +1,7 @@
 use std::{fmt, iter, mem};
 
 use rustc_abi::{FIRST_VARIANT, FieldIdx, VariantIdx};
+use rustc_hir::def::DefKind;
 use rustc_hir::lang_items::LangItem;
 use rustc_index::Idx;
 use rustc_middle::mir::*;
@@ -254,8 +255,19 @@ where
             // impl_item_refs may be empty if drop fn is not implemented in 'impl AsyncDrop for ...'
             // (#140974).
             // Such code will report error, so just generate sync drop here and return
-            let Some(drop_fn_def_id) =
-                tcx.associated_item_def_ids(drop_trait).into_iter().nth(0).copied()
+            let Some(drop_fn_def_id) = tcx
+                .associated_item_def_ids(drop_trait)
+                .first()
+                .and_then(|def_id| {
+                    if tcx.def_kind(def_id) == DefKind::AssocFn
+                        && tcx.check_args_compatible(*def_id, trait_args)
+                    {
+                        Some(def_id)
+                    } else {
+                        None
+                    }
+                })
+                .copied()
             else {
                 tcx.dcx().span_delayed_bug(
                     self.elaborator.body().span,
@@ -1278,6 +1290,23 @@ where
             }
             ty::Slice(ety) => self.drop_loop_trio_for_slice(*ety),
 
+            ty::UnsafeBinder(_) => {
+                // Unsafe binders may elaborate drops if their inner type isn't copy.
+                // This is enforced in typeck, so this should never happen.
+                self.tcx().dcx().span_delayed_bug(
+                    self.source_info.span,
+                    "open drop for unsafe binder shouldn't be encountered",
+                );
+                self.elaborator.patch().new_block(BasicBlockData {
+                    statements: vec![],
+                    terminator: Some(Terminator {
+                        source_info: self.source_info,
+                        kind: TerminatorKind::Unreachable,
+                    }),
+                    is_cleanup: self.unwind.is_cleanup(),
+                })
+            }
+
             _ => span_bug!(self.source_info.span, "open drop from non-ADT `{:?}`", ty),
         }
     }
diff --git a/compiler/rustc_mir_transform/src/errors.rs b/compiler/rustc_mir_transform/src/errors.rs
index 5b03a4987ed..cffa0183fa7 100644
--- a/compiler/rustc_mir_transform/src/errors.rs
+++ b/compiler/rustc_mir_transform/src/errors.rs
@@ -158,33 +158,6 @@ pub(crate) struct MustNotSuspendReason {
     pub reason: String,
 }
 
-pub(crate) struct UnnecessaryTransmute {
-    pub span: Span,
-    pub sugg: String,
-    pub help: Option<&'static str>,
-}
-
-// Needed for def_path_str
-impl<'a> LintDiagnostic<'a, ()> for UnnecessaryTransmute {
-    fn decorate_lint<'b>(self, diag: &'b mut rustc_errors::Diag<'a, ()>) {
-        diag.primary_message(fluent::mir_transform_unnecessary_transmute);
-        diag.span_suggestion(
-            self.span,
-            "replace this with",
-            self.sugg,
-            lint::Applicability::MachineApplicable,
-        );
-        self.help.map(|help| diag.help(help));
-    }
-}
-
-#[derive(LintDiagnostic)]
-#[diag(mir_transform_undefined_transmute)]
-#[note]
-#[note(mir_transform_note2)]
-#[help]
-pub(crate) struct UndefinedTransmute;
-
 #[derive(Diagnostic)]
 #[diag(mir_transform_force_inline)]
 #[note]
diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs
index 209e818e9e3..a91d46ec406 100644
--- a/compiler/rustc_mir_transform/src/gvn.rs
+++ b/compiler/rustc_mir_transform/src/gvn.rs
@@ -638,6 +638,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
         place: PlaceRef<'tcx>,
         value: VnIndex,
         proj: PlaceElem<'tcx>,
+        from_non_ssa_index: &mut bool,
     ) -> Option<VnIndex> {
         let proj = match proj {
             ProjectionElem::Deref => {
@@ -682,6 +683,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
             }
             ProjectionElem::Index(idx) => {
                 if let Value::Repeat(inner, _) = self.get(value) {
+                    *from_non_ssa_index |= self.locals[idx].is_none();
                     return Some(*inner);
                 }
                 let idx = self.locals[idx]?;
@@ -774,6 +776,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
 
         // Invariant: `value` holds the value up-to the `index`th projection excluded.
         let mut value = self.locals[place.local]?;
+        let mut from_non_ssa_index = false;
         for (index, proj) in place.projection.iter().enumerate() {
             if let Value::Projection(pointer, ProjectionElem::Deref) = *self.get(value)
                 && let Value::Address { place: mut pointee, kind, .. } = *self.get(pointer)
@@ -791,7 +794,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
             }
 
             let base = PlaceRef { local: place.local, projection: &place.projection[..index] };
-            value = self.project(base, value, proj)?;
+            value = self.project(base, value, proj, &mut from_non_ssa_index)?;
         }
 
         if let Value::Projection(pointer, ProjectionElem::Deref) = *self.get(value)
@@ -804,6 +807,9 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
         }
         if let Some(new_local) = self.try_as_local(value, location) {
             place_ref = PlaceRef { local: new_local, projection: &[] };
+        } else if from_non_ssa_index {
+            // If access to non-SSA locals is unavoidable, bail out.
+            return None;
         }
 
         if place_ref.local != place.local || place_ref.projection.len() < place.projection.len() {
diff --git a/compiler/rustc_mir_transform/src/large_enums.rs b/compiler/rustc_mir_transform/src/large_enums.rs
index 47cb478fe33..1a91d6bd7da 100644
--- a/compiler/rustc_mir_transform/src/large_enums.rs
+++ b/compiler/rustc_mir_transform/src/large_enums.rs
@@ -241,6 +241,7 @@ impl EnumSizeOpt {
             data,
             tcx.data_layout.ptr_sized_integer().align(&tcx.data_layout).abi,
             Mutability::Not,
+            (),
         );
         let alloc = tcx.reserve_and_set_memory_alloc(tcx.mk_const_alloc(alloc));
         Some((*adt_def, num_discrs, *alloc_cache.entry(ty).or_insert(alloc)))
diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs
index 10dbb3437dc..d26e4468715 100644
--- a/compiler/rustc_mir_transform/src/lib.rs
+++ b/compiler/rustc_mir_transform/src/lib.rs
@@ -123,8 +123,6 @@ declare_passes! {
     mod check_const_item_mutation : CheckConstItemMutation;
     mod check_null : CheckNull;
     mod check_packed_ref : CheckPackedRef;
-    mod check_undefined_transmutes : CheckUndefinedTransmutes;
-    mod check_unnecessary_transmutes: CheckUnnecessaryTransmutes;
     // This pass is public to allow external drivers to perform MIR cleanup
     pub mod cleanup_post_borrowck : CleanupPostBorrowck;
 
@@ -390,8 +388,6 @@ fn mir_built(tcx: TyCtxt<'_>, def: LocalDefId) -> &Steal<Body<'_>> {
             &Lint(check_packed_ref::CheckPackedRef),
             &Lint(check_const_item_mutation::CheckConstItemMutation),
             &Lint(function_item_references::FunctionItemReferences),
-            &Lint(check_undefined_transmutes::CheckUndefinedTransmutes),
-            &Lint(check_unnecessary_transmutes::CheckUnnecessaryTransmutes),
             // What we need to do constant evaluation.
             &simplify::SimplifyCfg::Initial,
             &Lint(sanity_check::SanityCheck),
diff --git a/compiler/rustc_mir_transform/src/lower_intrinsics.rs b/compiler/rustc_mir_transform/src/lower_intrinsics.rs
index 9c21bcfc0d2..52f4c39c09b 100644
--- a/compiler/rustc_mir_transform/src/lower_intrinsics.rs
+++ b/compiler/rustc_mir_transform/src/lower_intrinsics.rs
@@ -262,6 +262,52 @@ impl<'tcx> crate::MirPass<'tcx> for LowerIntrinsics {
                         });
                         terminator.kind = TerminatorKind::Goto { target };
                     }
+                    sym::slice_get_unchecked => {
+                        let target = target.unwrap();
+                        let Ok([ptrish, index]) = take_array(args) else {
+                            span_bug!(
+                                terminator.source_info.span,
+                                "Wrong number of arguments for {intrinsic:?}",
+                            );
+                        };
+
+                        let place = ptrish.node.place().unwrap();
+                        assert!(!place.is_indirect());
+                        let updated_place = place.project_deeper(
+                            &[
+                                ProjectionElem::Deref,
+                                ProjectionElem::Index(
+                                    index.node.place().unwrap().as_local().unwrap(),
+                                ),
+                            ],
+                            tcx,
+                        );
+
+                        let ret_ty = generic_args.type_at(0);
+                        let rvalue = match *ret_ty.kind() {
+                            ty::RawPtr(_, Mutability::Not) => {
+                                Rvalue::RawPtr(RawPtrKind::Const, updated_place)
+                            }
+                            ty::RawPtr(_, Mutability::Mut) => {
+                                Rvalue::RawPtr(RawPtrKind::Mut, updated_place)
+                            }
+                            ty::Ref(region, _, Mutability::Not) => {
+                                Rvalue::Ref(region, BorrowKind::Shared, updated_place)
+                            }
+                            ty::Ref(region, _, Mutability::Mut) => Rvalue::Ref(
+                                region,
+                                BorrowKind::Mut { kind: MutBorrowKind::Default },
+                                updated_place,
+                            ),
+                            _ => bug!("Unknown return type {ret_ty:?}"),
+                        };
+
+                        block.statements.push(Statement {
+                            source_info: terminator.source_info,
+                            kind: StatementKind::Assign(Box::new((*destination, rvalue))),
+                        });
+                        terminator.kind = TerminatorKind::Goto { target };
+                    }
                     sym::transmute | sym::transmute_unchecked => {
                         let dst_ty = destination.ty(local_decls, tcx).ty;
                         let Ok([arg]) = take_array(args) else {
diff --git a/compiler/rustc_mir_transform/src/match_branches.rs b/compiler/rustc_mir_transform/src/match_branches.rs
index 8c0c3096899..5e511f1a418 100644
--- a/compiler/rustc_mir_transform/src/match_branches.rs
+++ b/compiler/rustc_mir_transform/src/match_branches.rs
@@ -284,12 +284,14 @@ fn can_cast(
     let v = match src_layout.ty.kind() {
         ty::Uint(_) => from_scalar.to_uint(src_layout.size),
         ty::Int(_) => from_scalar.to_int(src_layout.size) as u128,
-        _ => unreachable!("invalid int"),
+        // We can also transform the values of other integer representations (such as char),
+        // although this may not be practical in real-world scenarios.
+        _ => return false,
     };
     let size = match *cast_ty.kind() {
         ty::Int(t) => Integer::from_int_ty(&tcx, t).size(),
         ty::Uint(t) => Integer::from_uint_ty(&tcx, t).size(),
-        _ => unreachable!("invalid int"),
+        _ => return false,
     };
     let v = size.truncate(v);
     let cast_scalar = ScalarInt::try_from_uint(v, size).unwrap();
diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs
index b3d7eaf332b..1ee977a5457 100644
--- a/compiler/rustc_monomorphize/src/collector.rs
+++ b/compiler/rustc_monomorphize/src/collector.rs
@@ -1483,7 +1483,7 @@ impl<'v> RootCollector<'_, 'v> {
 
                 // But even just declaring them must collect the items they refer to
                 // unless their generics require monomorphization.
-                if !self.tcx.generics_of(id.owner_id).requires_monomorphization(self.tcx)
+                if !self.tcx.generics_of(id.owner_id).own_requires_monomorphization()
                     && let Ok(val) = self.tcx.const_eval_poly(id.owner_id.to_def_id())
                 {
                     collect_const_value(self.tcx, val, self.output);
diff --git a/compiler/rustc_next_trait_solver/src/canonicalizer.rs b/compiler/rustc_next_trait_solver/src/canonicalizer.rs
index 93b8940ee37..a87ae5284b1 100644
--- a/compiler/rustc_next_trait_solver/src/canonicalizer.rs
+++ b/compiler/rustc_next_trait_solver/src/canonicalizer.rs
@@ -4,12 +4,22 @@ use rustc_type_ir::data_structures::{HashMap, ensure_sufficient_stack};
 use rustc_type_ir::inherent::*;
 use rustc_type_ir::solve::{Goal, QueryInput};
 use rustc_type_ir::{
-    self as ty, Canonical, CanonicalTyVarKind, CanonicalVarKind, InferCtxtLike, Interner,
-    TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitableExt,
+    self as ty, Canonical, CanonicalTyVarKind, CanonicalVarKind, Flags, InferCtxtLike, Interner,
+    TypeFlags, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitableExt,
 };
 
 use crate::delegate::SolverDelegate;
 
+/// Does this have infer/placeholder/param, free regions or ReErased?
+const NEEDS_CANONICAL: TypeFlags = TypeFlags::from_bits(
+    TypeFlags::HAS_INFER.bits()
+        | TypeFlags::HAS_PLACEHOLDER.bits()
+        | TypeFlags::HAS_PARAM.bits()
+        | TypeFlags::HAS_FREE_REGIONS.bits()
+        | TypeFlags::HAS_RE_ERASED.bits(),
+)
+.unwrap();
+
 /// Whether we're canonicalizing a query input or the query response.
 ///
 /// When canonicalizing an input we're in the context of the caller
@@ -79,9 +89,13 @@ impl<'a, D: SolverDelegate<Interner = I>, I: Interner> Canonicalizer<'a, D, I> {
             cache: Default::default(),
         };
 
-        let value = value.fold_with(&mut canonicalizer);
-        assert!(!value.has_infer(), "unexpected infer in {value:?}");
-        assert!(!value.has_placeholders(), "unexpected placeholders in {value:?}");
+        let value = if value.has_type_flags(NEEDS_CANONICAL) {
+            value.fold_with(&mut canonicalizer)
+        } else {
+            value
+        };
+        debug_assert!(!value.has_infer(), "unexpected infer in {value:?}");
+        debug_assert!(!value.has_placeholders(), "unexpected placeholders in {value:?}");
         let (max_universe, variables) = canonicalizer.finalize();
         Canonical { max_universe, variables, value }
     }
@@ -111,7 +125,14 @@ impl<'a, D: SolverDelegate<Interner = I>, I: Interner> Canonicalizer<'a, D, I> {
 
             cache: Default::default(),
         };
-        let param_env = input.goal.param_env.fold_with(&mut env_canonicalizer);
+
+        let param_env = input.goal.param_env;
+        let param_env = if param_env.has_type_flags(NEEDS_CANONICAL) {
+            param_env.fold_with(&mut env_canonicalizer)
+        } else {
+            param_env
+        };
+
         debug_assert_eq!(env_canonicalizer.binder_index, ty::INNERMOST);
         // Then canonicalize the rest of the input without keeping `'static`
         // while *mostly* reusing the canonicalizer from above.
@@ -134,14 +155,26 @@ impl<'a, D: SolverDelegate<Interner = I>, I: Interner> Canonicalizer<'a, D, I> {
             cache: Default::default(),
         };
 
-        let predicate = input.goal.predicate.fold_with(&mut rest_canonicalizer);
+        let predicate = input.goal.predicate;
+        let predicate = if predicate.has_type_flags(NEEDS_CANONICAL) {
+            predicate.fold_with(&mut rest_canonicalizer)
+        } else {
+            predicate
+        };
         let goal = Goal { param_env, predicate };
+
+        let predefined_opaques_in_body = input.predefined_opaques_in_body;
         let predefined_opaques_in_body =
-            input.predefined_opaques_in_body.fold_with(&mut rest_canonicalizer);
+            if input.predefined_opaques_in_body.has_type_flags(NEEDS_CANONICAL) {
+                predefined_opaques_in_body.fold_with(&mut rest_canonicalizer)
+            } else {
+                predefined_opaques_in_body
+            };
+
         let value = QueryInput { goal, predefined_opaques_in_body };
 
-        assert!(!value.has_infer(), "unexpected infer in {value:?}");
-        assert!(!value.has_placeholders(), "unexpected placeholders in {value:?}");
+        debug_assert!(!value.has_infer(), "unexpected infer in {value:?}");
+        debug_assert!(!value.has_placeholders(), "unexpected placeholders in {value:?}");
         let (max_universe, variables) = rest_canonicalizer.finalize();
         Canonical { max_universe, variables, value }
     }
@@ -304,7 +337,7 @@ impl<'a, D: SolverDelegate<Interner = I>, I: Interner> Canonicalizer<'a, D, I> {
                     first_region = false;
                     curr_compressed_uv = curr_compressed_uv.next_universe();
                 }
-                assert!(var.is_existential());
+                debug_assert!(var.is_existential());
                 *var = var.with_updated_universe(curr_compressed_uv);
             }
         }
@@ -317,7 +350,7 @@ impl<'a, D: SolverDelegate<Interner = I>, I: Interner> Canonicalizer<'a, D, I> {
         let kind = match t.kind() {
             ty::Infer(i) => match i {
                 ty::TyVar(vid) => {
-                    assert_eq!(
+                    debug_assert_eq!(
                         self.delegate.opportunistic_resolve_ty_var(vid),
                         t,
                         "ty vid should have been resolved fully before canonicalization"
@@ -330,7 +363,7 @@ impl<'a, D: SolverDelegate<Interner = I>, I: Interner> Canonicalizer<'a, D, I> {
                     ))
                 }
                 ty::IntVar(vid) => {
-                    assert_eq!(
+                    debug_assert_eq!(
                         self.delegate.opportunistic_resolve_int_var(vid),
                         t,
                         "ty vid should have been resolved fully before canonicalization"
@@ -338,7 +371,7 @@ impl<'a, D: SolverDelegate<Interner = I>, I: Interner> Canonicalizer<'a, D, I> {
                     CanonicalVarKind::Ty(CanonicalTyVarKind::Int)
                 }
                 ty::FloatVar(vid) => {
-                    assert_eq!(
+                    debug_assert_eq!(
                         self.delegate.opportunistic_resolve_float_var(vid),
                         t,
                         "ty vid should have been resolved fully before canonicalization"
@@ -387,7 +420,11 @@ impl<'a, D: SolverDelegate<Interner = I>, I: Interner> Canonicalizer<'a, D, I> {
             | ty::Alias(_, _)
             | ty::Bound(_, _)
             | ty::Error(_) => {
-                return ensure_sufficient_stack(|| t.super_fold_with(self));
+                return if t.has_type_flags(NEEDS_CANONICAL) {
+                    ensure_sufficient_stack(|| t.super_fold_with(self))
+                } else {
+                    t
+                };
             }
         };
 
@@ -459,7 +496,7 @@ impl<D: SolverDelegate<Interner = I>, I: Interner> TypeFolder<I> for Canonicaliz
             },
 
             ty::ReVar(vid) => {
-                assert_eq!(
+                debug_assert_eq!(
                     self.delegate.opportunistic_resolve_lt_var(vid),
                     r,
                     "region vid should have been resolved fully before canonicalization"
@@ -485,7 +522,8 @@ impl<D: SolverDelegate<Interner = I>, I: Interner> TypeFolder<I> for Canonicaliz
             ty
         } else {
             let res = self.cached_fold_ty(t);
-            assert!(self.cache.insert((self.binder_index, t), res).is_none());
+            let old = self.cache.insert((self.binder_index, t), res);
+            assert_eq!(old, None);
             res
         }
     }
@@ -494,7 +532,7 @@ impl<D: SolverDelegate<Interner = I>, I: Interner> TypeFolder<I> for Canonicaliz
         let kind = match c.kind() {
             ty::ConstKind::Infer(i) => match i {
                 ty::InferConst::Var(vid) => {
-                    assert_eq!(
+                    debug_assert_eq!(
                         self.delegate.opportunistic_resolve_ct_var(vid),
                         c,
                         "const vid should have been resolved fully before canonicalization"
@@ -522,11 +560,28 @@ impl<D: SolverDelegate<Interner = I>, I: Interner> TypeFolder<I> for Canonicaliz
             | ty::ConstKind::Unevaluated(_)
             | ty::ConstKind::Value(_)
             | ty::ConstKind::Error(_)
-            | ty::ConstKind::Expr(_) => return c.super_fold_with(self),
+            | ty::ConstKind::Expr(_) => {
+                return if c.has_type_flags(NEEDS_CANONICAL) { c.super_fold_with(self) } else { c };
+            }
         };
 
         let var = self.get_or_insert_bound_var(c, kind);
 
         Const::new_anon_bound(self.cx(), self.binder_index, var)
     }
+
+    fn fold_predicate(&mut self, p: I::Predicate) -> I::Predicate {
+        if p.flags().intersects(NEEDS_CANONICAL) { p.super_fold_with(self) } else { p }
+    }
+
+    fn fold_clauses(&mut self, c: I::Clauses) -> I::Clauses {
+        match self.canonicalize_mode {
+            CanonicalizeMode::Input { keep_static: true }
+            | CanonicalizeMode::Response { max_input_universe: _ } => {}
+            CanonicalizeMode::Input { keep_static: false } => {
+                panic!("erasing 'static in env")
+            }
+        }
+        if c.flags().intersects(NEEDS_CANONICAL) { c.super_fold_with(self) } else { c }
+    }
 }
diff --git a/compiler/rustc_next_trait_solver/src/delegate.rs b/compiler/rustc_next_trait_solver/src/delegate.rs
index 32dc85b3e6a..7b932010d49 100644
--- a/compiler/rustc_next_trait_solver/src/delegate.rs
+++ b/compiler/rustc_next_trait_solver/src/delegate.rs
@@ -3,8 +3,6 @@ use std::ops::Deref;
 use rustc_type_ir::solve::{Certainty, Goal, NoSolution};
 use rustc_type_ir::{self as ty, InferCtxtLike, Interner, TypeFoldable};
 
-use crate::solve::HasChanged;
-
 pub trait SolverDelegate: Deref<Target = Self::Infcx> + Sized {
     type Infcx: InferCtxtLike<Interner = Self::Interner>;
     type Interner: Interner;
@@ -23,7 +21,7 @@ pub trait SolverDelegate: Deref<Target = Self::Infcx> + Sized {
         &self,
         goal: Goal<Self::Interner, <Self::Interner as Interner>::Predicate>,
         span: <Self::Interner as Interner>::Span,
-    ) -> Option<HasChanged>;
+    ) -> Option<Certainty>;
 
     fn fresh_var_for_kind_with_span(
         &self,
diff --git a/compiler/rustc_next_trait_solver/src/resolve.rs b/compiler/rustc_next_trait_solver/src/resolve.rs
index 992c5ddf504..c3c57eccd6e 100644
--- a/compiler/rustc_next_trait_solver/src/resolve.rs
+++ b/compiler/rustc_next_trait_solver/src/resolve.rs
@@ -11,7 +11,7 @@ use crate::delegate::SolverDelegate;
 // EAGER RESOLUTION
 
 /// Resolves ty, region, and const vars to their inferred values or their root vars.
-pub struct EagerResolver<'a, D, I = <D as SolverDelegate>::Interner>
+struct EagerResolver<'a, D, I = <D as SolverDelegate>::Interner>
 where
     D: SolverDelegate<Interner = I>,
     I: Interner,
@@ -22,8 +22,20 @@ where
     cache: DelayedMap<I::Ty, I::Ty>,
 }
 
+pub fn eager_resolve_vars<D: SolverDelegate, T: TypeFoldable<D::Interner>>(
+    delegate: &D,
+    value: T,
+) -> T {
+    if value.has_infer() {
+        let mut folder = EagerResolver::new(delegate);
+        value.fold_with(&mut folder)
+    } else {
+        value
+    }
+}
+
 impl<'a, D: SolverDelegate> EagerResolver<'a, D> {
-    pub fn new(delegate: &'a D) -> Self {
+    fn new(delegate: &'a D) -> Self {
         EagerResolver { delegate, cache: Default::default() }
     }
 }
@@ -86,4 +98,12 @@ impl<D: SolverDelegate<Interner = I>, I: Interner> TypeFolder<I> for EagerResolv
             }
         }
     }
+
+    fn fold_predicate(&mut self, p: I::Predicate) -> I::Predicate {
+        if p.has_infer() { p.super_fold_with(self) } else { p }
+    }
+
+    fn fold_clauses(&mut self, c: I::Clauses) -> I::Clauses {
+        if c.has_infer() { c.super_fold_with(self) } else { c }
+    }
 }
diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs
index 455a178595b..cb7c498b94e 100644
--- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs
@@ -22,7 +22,7 @@ use tracing::{debug, instrument, trace};
 
 use crate::canonicalizer::Canonicalizer;
 use crate::delegate::SolverDelegate;
-use crate::resolve::EagerResolver;
+use crate::resolve::eager_resolve_vars;
 use crate::solve::eval_ctxt::CurrentGoalKind;
 use crate::solve::{
     CanonicalInput, CanonicalResponse, Certainty, EvalCtxt, ExternalConstraintsData, Goal,
@@ -53,16 +53,15 @@ where
 {
     /// Canonicalizes the goal remembering the original values
     /// for each bound variable.
-    pub(super) fn canonicalize_goal<T: TypeFoldable<I>>(
+    pub(super) fn canonicalize_goal(
         &self,
-        goal: Goal<I, T>,
-    ) -> (Vec<I::GenericArg>, CanonicalInput<I, T>) {
+        goal: Goal<I, I::Predicate>,
+    ) -> (Vec<I::GenericArg>, CanonicalInput<I, I::Predicate>) {
         // We only care about one entry per `OpaqueTypeKey` here,
         // so we only canonicalize the lookup table and ignore
         // duplicate entries.
         let opaque_types = self.delegate.clone_opaque_types_lookup_table();
-        let (goal, opaque_types) =
-            (goal, opaque_types).fold_with(&mut EagerResolver::new(self.delegate));
+        let (goal, opaque_types) = eager_resolve_vars(self.delegate, (goal, opaque_types));
 
         let mut orig_values = Default::default();
         let canonical = Canonicalizer::canonicalize_input(
@@ -130,7 +129,12 @@ where
                     if goals.is_empty() {
                         assert!(matches!(goals_certainty, Certainty::Yes));
                     }
-                    (Certainty::Yes, NestedNormalizationGoals(goals))
+                    (
+                        Certainty::Yes,
+                        NestedNormalizationGoals(
+                            goals.into_iter().map(|(s, g, _)| (s, g)).collect(),
+                        ),
+                    )
                 }
                 _ => {
                     let certainty = shallow_certainty.and(goals_certainty);
@@ -157,8 +161,8 @@ where
 
         let external_constraints =
             self.compute_external_query_constraints(certainty, normalization_nested_goals);
-        let (var_values, mut external_constraints) = (self.var_values, external_constraints)
-            .fold_with(&mut EagerResolver::new(self.delegate));
+        let (var_values, mut external_constraints) =
+            eager_resolve_vars(self.delegate, (self.var_values, external_constraints));
 
         // Remove any trivial or duplicated region constraints once we've resolved regions
         let mut unique = HashSet::default();
@@ -272,7 +276,7 @@ where
     pub(super) fn instantiate_and_apply_query_response(
         &mut self,
         param_env: I::ParamEnv,
-        original_values: Vec<I::GenericArg>,
+        original_values: &[I::GenericArg],
         response: CanonicalResponse<I>,
     ) -> (NestedNormalizationGoals<I>, Certainty) {
         let instantiation = Self::compute_query_response_instantiation_values(
@@ -469,7 +473,7 @@ where
 {
     let var_values = CanonicalVarValues { var_values: delegate.cx().mk_args(var_values) };
     let state = inspect::State { var_values, data };
-    let state = state.fold_with(&mut EagerResolver::new(delegate));
+    let state = eager_resolve_vars(delegate, state);
     Canonicalizer::canonicalize_response(delegate, max_input_universe, &mut vec![], state)
 }
 
diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs
index dfabb94ebfc..38d7ff576a5 100644
--- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs
@@ -22,8 +22,9 @@ use crate::delegate::SolverDelegate;
 use crate::solve::inspect::{self, ProofTreeBuilder};
 use crate::solve::search_graph::SearchGraph;
 use crate::solve::{
-    CanonicalInput, Certainty, FIXPOINT_STEP_LIMIT, Goal, GoalEvaluationKind, GoalSource,
-    HasChanged, NestedNormalizationGoals, NoSolution, QueryInput, QueryResult,
+    CanonicalInput, Certainty, FIXPOINT_STEP_LIMIT, Goal, GoalEvaluation, GoalEvaluationKind,
+    GoalSource, GoalStalledOn, HasChanged, NestedNormalizationGoals, NoSolution, QueryInput,
+    QueryResult,
 };
 
 pub(super) mod canonical;
@@ -115,7 +116,7 @@ where
 
     pub(super) search_graph: &'a mut SearchGraph<D>,
 
-    nested_goals: Vec<(GoalSource, Goal<I, I::Predicate>)>,
+    nested_goals: Vec<(GoalSource, Goal<I, I::Predicate>, Option<GoalStalledOn<I>>)>,
 
     pub(super) origin_span: I::Span,
 
@@ -147,8 +148,9 @@ pub trait SolverDelegateEvalExt: SolverDelegate {
         goal: Goal<Self::Interner, <Self::Interner as Interner>::Predicate>,
         generate_proof_tree: GenerateProofTree,
         span: <Self::Interner as Interner>::Span,
+        stalled_on: Option<GoalStalledOn<Self::Interner>>,
     ) -> (
-        Result<(HasChanged, Certainty), NoSolution>,
+        Result<GoalEvaluation<Self::Interner>, NoSolution>,
         Option<inspect::GoalEvaluation<Self::Interner>>,
     );
 
@@ -171,8 +173,12 @@ pub trait SolverDelegateEvalExt: SolverDelegate {
         &self,
         goal: Goal<Self::Interner, <Self::Interner as Interner>::Predicate>,
         generate_proof_tree: GenerateProofTree,
+        stalled_on: Option<GoalStalledOn<Self::Interner>>,
     ) -> (
-        Result<(NestedNormalizationGoals<Self::Interner>, HasChanged, Certainty), NoSolution>,
+        Result<
+            (NestedNormalizationGoals<Self::Interner>, GoalEvaluation<Self::Interner>),
+            NoSolution,
+        >,
         Option<inspect::GoalEvaluation<Self::Interner>>,
     );
 }
@@ -188,9 +194,10 @@ where
         goal: Goal<I, I::Predicate>,
         generate_proof_tree: GenerateProofTree,
         span: I::Span,
-    ) -> (Result<(HasChanged, Certainty), NoSolution>, Option<inspect::GoalEvaluation<I>>) {
+        stalled_on: Option<GoalStalledOn<I>>,
+    ) -> (Result<GoalEvaluation<I>, NoSolution>, Option<inspect::GoalEvaluation<I>>) {
         EvalCtxt::enter_root(self, self.cx().recursion_limit(), generate_proof_tree, span, |ecx| {
-            ecx.evaluate_goal(GoalEvaluationKind::Root, GoalSource::Misc, goal)
+            ecx.evaluate_goal(GoalEvaluationKind::Root, GoalSource::Misc, goal, stalled_on)
         })
     }
 
@@ -201,7 +208,7 @@ where
     ) -> bool {
         self.probe(|| {
             EvalCtxt::enter_root(self, root_depth, GenerateProofTree::No, I::Span::dummy(), |ecx| {
-                ecx.evaluate_goal(GoalEvaluationKind::Root, GoalSource::Misc, goal)
+                ecx.evaluate_goal(GoalEvaluationKind::Root, GoalSource::Misc, goal, None)
             })
             .0
         })
@@ -213,8 +220,9 @@ where
         &self,
         goal: Goal<I, I::Predicate>,
         generate_proof_tree: GenerateProofTree,
+        stalled_on: Option<GoalStalledOn<I>>,
     ) -> (
-        Result<(NestedNormalizationGoals<I>, HasChanged, Certainty), NoSolution>,
+        Result<(NestedNormalizationGoals<I>, GoalEvaluation<I>), NoSolution>,
         Option<inspect::GoalEvaluation<I>>,
     ) {
         EvalCtxt::enter_root(
@@ -222,7 +230,9 @@ where
             self.cx().recursion_limit(),
             generate_proof_tree,
             I::Span::dummy(),
-            |ecx| ecx.evaluate_goal_raw(GoalEvaluationKind::Root, GoalSource::Misc, goal),
+            |ecx| {
+                ecx.evaluate_goal_raw(GoalEvaluationKind::Root, GoalSource::Misc, goal, stalled_on)
+            },
         )
     }
 }
@@ -447,11 +457,12 @@ where
         goal_evaluation_kind: GoalEvaluationKind,
         source: GoalSource,
         goal: Goal<I, I::Predicate>,
-    ) -> Result<(HasChanged, Certainty), NoSolution> {
-        let (normalization_nested_goals, has_changed, certainty) =
-            self.evaluate_goal_raw(goal_evaluation_kind, source, goal)?;
+        stalled_on: Option<GoalStalledOn<I>>,
+    ) -> Result<GoalEvaluation<I>, NoSolution> {
+        let (normalization_nested_goals, goal_evaluation) =
+            self.evaluate_goal_raw(goal_evaluation_kind, source, goal, stalled_on)?;
         assert!(normalization_nested_goals.is_empty());
-        Ok((has_changed, certainty))
+        Ok(goal_evaluation)
     }
 
     /// Recursively evaluates `goal`, returning the nested goals in case
@@ -466,7 +477,29 @@ where
         goal_evaluation_kind: GoalEvaluationKind,
         source: GoalSource,
         goal: Goal<I, I::Predicate>,
-    ) -> Result<(NestedNormalizationGoals<I>, HasChanged, Certainty), NoSolution> {
+        stalled_on: Option<GoalStalledOn<I>>,
+    ) -> Result<(NestedNormalizationGoals<I>, GoalEvaluation<I>), NoSolution> {
+        // If we have run this goal before, and it was stalled, check that any of the goal's
+        // args have changed. Otherwise, we don't need to re-run the goal because it'll remain
+        // stalled, since it'll canonicalize the same way and evaluation is pure.
+        if let Some(stalled_on) = stalled_on {
+            if !stalled_on.stalled_vars.iter().any(|value| self.delegate.is_changed_arg(*value))
+                && !self
+                    .delegate
+                    .opaque_types_storage_num_entries()
+                    .needs_reevaluation(stalled_on.num_opaques)
+            {
+                return Ok((
+                    NestedNormalizationGoals::empty(),
+                    GoalEvaluation {
+                        certainty: Certainty::Maybe(stalled_on.stalled_cause),
+                        has_changed: HasChanged::No,
+                        stalled_on: Some(stalled_on),
+                    },
+                ));
+            }
+        }
+
         let (orig_values, canonical_goal) = self.canonicalize_goal(goal);
         let mut goal_evaluation =
             self.inspect.new_goal_evaluation(goal, &orig_values, goal_evaluation_kind);
@@ -489,7 +522,7 @@ where
             if !has_only_region_constraints(response) { HasChanged::Yes } else { HasChanged::No };
 
         let (normalization_nested_goals, certainty) =
-            self.instantiate_and_apply_query_response(goal.param_env, orig_values, response);
+            self.instantiate_and_apply_query_response(goal.param_env, &orig_values, response);
         self.inspect.goal_evaluation(goal_evaluation);
 
         // FIXME: We previously had an assert here that checked that recomputing
@@ -502,7 +535,42 @@ where
         // Once we have decided on how to handle trait-system-refactor-initiative#75,
         // we should re-add an assert here.
 
-        Ok((normalization_nested_goals, has_changed, certainty))
+        let stalled_on = match certainty {
+            Certainty::Yes => None,
+            Certainty::Maybe(stalled_cause) => match has_changed {
+                // FIXME: We could recompute a *new* set of stalled variables by walking
+                // through the orig values, resolving, and computing the root vars of anything
+                // that is not resolved. Only when *these* have changed is it meaningful
+                // to recompute this goal.
+                HasChanged::Yes => None,
+                HasChanged::No => {
+                    // Remove the unconstrained RHS arg, which is expected to have changed.
+                    let mut stalled_vars = orig_values;
+                    if let Some(normalizes_to) = goal.predicate.as_normalizes_to() {
+                        let normalizes_to = normalizes_to.skip_binder();
+                        let rhs_arg: I::GenericArg = normalizes_to.term.into();
+                        let idx = stalled_vars
+                            .iter()
+                            .rposition(|arg| *arg == rhs_arg)
+                            .expect("expected unconstrained arg");
+                        stalled_vars.swap_remove(idx);
+                    }
+
+                    Some(GoalStalledOn {
+                        num_opaques: canonical_goal
+                            .canonical
+                            .value
+                            .predefined_opaques_in_body
+                            .opaque_types
+                            .len(),
+                        stalled_vars,
+                        stalled_cause,
+                    })
+                }
+            },
+        };
+
+        Ok((normalization_nested_goals, GoalEvaluation { certainty, has_changed, stalled_on }))
     }
 
     fn compute_goal(&mut self, goal: Goal<I, I::Predicate>) -> QueryResult<I> {
@@ -602,11 +670,14 @@ where
         let cx = self.cx();
         // If this loop did not result in any progress, what's our final certainty.
         let mut unchanged_certainty = Some(Certainty::Yes);
-        for (source, goal) in mem::take(&mut self.nested_goals) {
-            if let Some(has_changed) = self.delegate.compute_goal_fast_path(goal, self.origin_span)
-            {
-                if matches!(has_changed, HasChanged::Yes) {
-                    unchanged_certainty = None;
+        for (source, goal, stalled_on) in mem::take(&mut self.nested_goals) {
+            if let Some(certainty) = self.delegate.compute_goal_fast_path(goal, self.origin_span) {
+                match certainty {
+                    Certainty::Yes => {}
+                    Certainty::Maybe(_) => {
+                        self.nested_goals.push((source, goal, None));
+                        unchanged_certainty = unchanged_certainty.map(|c| c.and(certainty));
+                    }
                 }
                 continue;
             }
@@ -630,11 +701,18 @@ where
                 let unconstrained_goal =
                     goal.with(cx, ty::NormalizesTo { alias: pred.alias, term: unconstrained_rhs });
 
-                let (NestedNormalizationGoals(nested_goals), _, certainty) =
-                    self.evaluate_goal_raw(GoalEvaluationKind::Nested, source, unconstrained_goal)?;
+                let (
+                    NestedNormalizationGoals(nested_goals),
+                    GoalEvaluation { certainty, stalled_on, has_changed: _ },
+                ) = self.evaluate_goal_raw(
+                    GoalEvaluationKind::Nested,
+                    source,
+                    unconstrained_goal,
+                    stalled_on,
+                )?;
                 // Add the nested goals from normalization to our own nested goals.
                 trace!(?nested_goals);
-                self.nested_goals.extend(nested_goals);
+                self.nested_goals.extend(nested_goals.into_iter().map(|(s, g)| (s, g, None)));
 
                 // Finally, equate the goal's RHS with the unconstrained var.
                 //
@@ -660,6 +738,8 @@ where
                 // looking at the "has changed" return from evaluate_goal,
                 // because we expect the `unconstrained_rhs` part of the predicate
                 // to have changed -- that means we actually normalized successfully!
+                // FIXME: Do we need to eagerly resolve here? Or should we check
+                // if the cache key has any changed vars?
                 let with_resolved_vars = self.resolve_vars_if_possible(goal);
                 if pred.alias != goal.predicate.as_normalizes_to().unwrap().skip_binder().alias {
                     unchanged_certainty = None;
@@ -668,13 +748,13 @@ where
                 match certainty {
                     Certainty::Yes => {}
                     Certainty::Maybe(_) => {
-                        self.nested_goals.push((source, with_resolved_vars));
+                        self.nested_goals.push((source, with_resolved_vars, stalled_on));
                         unchanged_certainty = unchanged_certainty.map(|c| c.and(certainty));
                     }
                 }
             } else {
-                let (has_changed, certainty) =
-                    self.evaluate_goal(GoalEvaluationKind::Nested, source, goal)?;
+                let GoalEvaluation { certainty, has_changed, stalled_on } =
+                    self.evaluate_goal(GoalEvaluationKind::Nested, source, goal, stalled_on)?;
                 if has_changed == HasChanged::Yes {
                     unchanged_certainty = None;
                 }
@@ -682,7 +762,7 @@ where
                 match certainty {
                     Certainty::Yes => {}
                     Certainty::Maybe(_) => {
-                        self.nested_goals.push((source, goal));
+                        self.nested_goals.push((source, goal, stalled_on));
                         unchanged_certainty = unchanged_certainty.map(|c| c.and(certainty));
                     }
                 }
@@ -706,7 +786,7 @@ where
         goal.predicate =
             goal.predicate.fold_with(&mut ReplaceAliasWithInfer::new(self, source, goal.param_env));
         self.inspect.add_goal(self.delegate, self.max_input_universe, source, goal);
-        self.nested_goals.push((source, goal));
+        self.nested_goals.push((source, goal, None));
     }
 
     #[instrument(level = "trace", skip(self, goals))]
@@ -740,8 +820,8 @@ where
 
     /// Returns a ty infer or a const infer depending on whether `kind` is a `Ty` or `Const`.
     /// If `kind` is an integer inference variable this will still return a ty infer var.
-    pub(super) fn next_term_infer_of_kind(&mut self, kind: I::Term) -> I::Term {
-        match kind.kind() {
+    pub(super) fn next_term_infer_of_kind(&mut self, term: I::Term) -> I::Term {
+        match term.kind() {
             ty::TermKind::Ty(_) => self.next_ty_infer().into(),
             ty::TermKind::Const(_) => self.next_const_infer().into(),
         }
@@ -848,6 +928,22 @@ where
                     }
                 }
             }
+
+            fn visit_predicate(&mut self, p: I::Predicate) -> Self::Result {
+                if p.has_non_region_infer() || p.has_placeholders() {
+                    p.super_visit_with(self)
+                } else {
+                    ControlFlow::Continue(())
+                }
+            }
+
+            fn visit_clauses(&mut self, c: I::Clauses) -> Self::Result {
+                if c.has_non_region_infer() || c.has_placeholders() {
+                    c.super_visit_with(self)
+                } else {
+                    ControlFlow::Continue(())
+                }
+            }
         }
 
         let mut visitor = ContainsTermOrNotNameable {
@@ -1024,7 +1120,7 @@ where
     }
 
     pub(super) fn register_region_outlives(&self, a: I::Region, b: I::Region) {
-        // `b : a` ==> `a <= b`
+        // `'a: 'b` ==> `'b <= 'a`
         self.delegate.sub_regions(b, a, self.origin_span);
     }
 
diff --git a/compiler/rustc_next_trait_solver/src/solve/mod.rs b/compiler/rustc_next_trait_solver/src/solve/mod.rs
index 2a641807154..a7a984181d7 100644
--- a/compiler/rustc_next_trait_solver/src/solve/mod.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/mod.rs
@@ -21,6 +21,7 @@ mod project_goals;
 mod search_graph;
 mod trait_goals;
 
+use derive_where::derive_where;
 use rustc_type_ir::inherent::*;
 pub use rustc_type_ir::solve::*;
 use rustc_type_ir::{self as ty, Interner, TypingMode};
@@ -369,3 +370,21 @@ fn response_no_constraints_raw<I: Interner>(
         },
     }
 }
+
+/// The result of evaluating a goal.
+pub struct GoalEvaluation<I: Interner> {
+    pub certainty: Certainty,
+    pub has_changed: HasChanged,
+    /// If the [`Certainty`] was `Maybe`, then keep track of whether the goal has changed
+    /// before rerunning it.
+    pub stalled_on: Option<GoalStalledOn<I>>,
+}
+
+/// The conditions that must change for a goal to warrant
+#[derive_where(Clone, Debug; I: Interner)]
+pub struct GoalStalledOn<I: Interner> {
+    pub num_opaques: usize,
+    pub stalled_vars: Vec<I::GenericArg>,
+    /// The cause that will be returned on subsequent evaluations if this goal remains stalled.
+    pub stalled_cause: MaybeCause,
+}
diff --git a/compiler/rustc_parse/messages.ftl b/compiler/rustc_parse/messages.ftl
index a6919afef12..1f221b4bf78 100644
--- a/compiler/rustc_parse/messages.ftl
+++ b/compiler/rustc_parse/messages.ftl
@@ -8,6 +8,30 @@ parse_array_brackets_instead_of_braces = this is a block expression, not an arra
 
 parse_array_index_offset_of = array indexing not supported in offset_of
 
+parse_asm_expected_comma = expected token: `,`
+    .label = expected `,`
+
+parse_asm_expected_other = expected operand, {$is_inline_asm ->
+    [false] options
+    *[true] clobber_abi, options
+    }, or additional template string
+
+parse_asm_expected_register_class_or_explicit_register = expected register class or explicit register
+
+parse_asm_expected_string_literal = expected string literal
+    .label = not a string literal
+
+parse_asm_non_abi = at least one abi must be provided as an argument to `clobber_abi`
+
+parse_asm_requires_template = requires at least a template string argument
+
+parse_asm_sym_no_path = expected a path for argument to `sym`
+
+parse_asm_underscore_input = _ cannot be used for input operands
+
+parse_asm_unsupported_operand = the `{$symbol}` operand cannot be used with `{$macro_name}!`
+    .label = the `{$symbol}` operand is not meaningful for global-scoped inline assembly, remove it
+
 parse_assignment_else_not_allowed = <assignment> ... else {"{"} ... {"}"} is not allowed
 
 parse_associated_static_item_not_allowed = associated `static` items are not allowed
diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs
index 31a48b22cfe..2dba568a258 100644
--- a/compiler/rustc_parse/src/errors.rs
+++ b/compiler/rustc_parse/src/errors.rs
@@ -3525,3 +3525,73 @@ pub(crate) struct MoveSelfModifier {
     pub insertion_span: Span,
     pub modifier: String,
 }
+
+#[derive(Diagnostic)]
+#[diag(parse_asm_unsupported_operand)]
+pub(crate) struct AsmUnsupportedOperand<'a> {
+    #[primary_span]
+    #[label]
+    pub(crate) span: Span,
+    pub(crate) symbol: &'a str,
+    pub(crate) macro_name: &'static str,
+}
+
+#[derive(Diagnostic)]
+#[diag(parse_asm_underscore_input)]
+pub(crate) struct AsmUnderscoreInput {
+    #[primary_span]
+    pub(crate) span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(parse_asm_sym_no_path)]
+pub(crate) struct AsmSymNoPath {
+    #[primary_span]
+    pub(crate) span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(parse_asm_requires_template)]
+pub(crate) struct AsmRequiresTemplate {
+    #[primary_span]
+    pub(crate) span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(parse_asm_expected_comma)]
+pub(crate) struct AsmExpectedComma {
+    #[primary_span]
+    #[label]
+    pub(crate) span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(parse_asm_expected_other)]
+pub(crate) struct AsmExpectedOther {
+    #[primary_span]
+    #[label(parse_asm_expected_other)]
+    pub(crate) span: Span,
+    pub(crate) is_inline_asm: bool,
+}
+
+#[derive(Diagnostic)]
+#[diag(parse_asm_non_abi)]
+pub(crate) struct NonABI {
+    #[primary_span]
+    pub(crate) span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(parse_asm_expected_string_literal)]
+pub(crate) struct AsmExpectedStringLiteral {
+    #[primary_span]
+    #[label]
+    pub(crate) span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(parse_asm_expected_register_class_or_explicit_register)]
+pub(crate) struct ExpectedRegisterClassOrExplicitRegister {
+    #[primary_span]
+    pub(crate) span: Span,
+}
diff --git a/compiler/rustc_parse/src/lexer/mod.rs b/compiler/rustc_parse/src/lexer/mod.rs
index 78c5742414b..2845bbed1c0 100644
--- a/compiler/rustc_parse/src/lexer/mod.rs
+++ b/compiler/rustc_parse/src/lexer/mod.rs
@@ -4,7 +4,7 @@ use diagnostics::make_unclosed_delims_error;
 use rustc_ast::ast::{self, AttrStyle};
 use rustc_ast::token::{self, CommentKind, Delimiter, IdentIsRaw, Token, TokenKind};
 use rustc_ast::tokenstream::TokenStream;
-use rustc_ast::util::unicode::contains_text_flow_control_chars;
+use rustc_ast::util::unicode::{TEXT_FLOW_CONTROL_CHARS, contains_text_flow_control_chars};
 use rustc_errors::codes::*;
 use rustc_errors::{Applicability, Diag, DiagCtxtHandle, StashKey};
 use rustc_lexer::{
@@ -14,7 +14,7 @@ use rustc_literal_escaper::{EscapeError, Mode, unescape_mixed, unescape_unicode}
 use rustc_session::lint::BuiltinLintDiag;
 use rustc_session::lint::builtin::{
     RUST_2021_PREFIXES_INCOMPATIBLE_SYNTAX, RUST_2024_GUARDED_STRING_INCOMPATIBLE_SYNTAX,
-    TEXT_DIRECTION_CODEPOINT_IN_COMMENT,
+    TEXT_DIRECTION_CODEPOINT_IN_COMMENT, TEXT_DIRECTION_CODEPOINT_IN_LITERAL,
 };
 use rustc_session::parse::ParseSess;
 use rustc_span::{BytePos, Pos, Span, Symbol, sym};
@@ -174,6 +174,7 @@ impl<'psess, 'src> Lexer<'psess, 'src> {
                     // Opening delimiter of the length 3 is not included into the symbol.
                     let content_start = start + BytePos(3);
                     let content = self.str_from(content_start);
+                    self.lint_doc_comment_unicode_text_flow(start, content);
                     self.cook_doc_comment(content_start, content, CommentKind::Line, doc_style)
                 }
                 rustc_lexer::TokenKind::BlockComment { doc_style, terminated } => {
@@ -193,6 +194,7 @@ impl<'psess, 'src> Lexer<'psess, 'src> {
                     let content_start = start + BytePos(3);
                     let content_end = self.pos - BytePos(if terminated { 2 } else { 0 });
                     let content = self.str_from_to(content_start, content_end);
+                    self.lint_doc_comment_unicode_text_flow(start, content);
                     self.cook_doc_comment(content_start, content, CommentKind::Block, doc_style)
                 }
                 rustc_lexer::TokenKind::Frontmatter { has_invalid_preceding_whitespace, invalid_infostring } => {
@@ -287,6 +289,7 @@ impl<'psess, 'src> Lexer<'psess, 'src> {
                     } else {
                         None
                     };
+                    self.lint_literal_unicode_text_flow(symbol, kind, self.mk_sp(start, self.pos), "literal");
                     token::Literal(token::Lit { kind, symbol, suffix })
                 }
                 rustc_lexer::TokenKind::Lifetime { starts_with_number } => {
@@ -481,6 +484,88 @@ impl<'psess, 'src> Lexer<'psess, 'src> {
         }
     }
 
+    fn lint_doc_comment_unicode_text_flow(&mut self, start: BytePos, content: &str) {
+        if contains_text_flow_control_chars(content) {
+            self.report_text_direction_codepoint(
+                content,
+                self.mk_sp(start, self.pos),
+                0,
+                false,
+                "doc comment",
+            );
+        }
+    }
+
+    fn lint_literal_unicode_text_flow(
+        &mut self,
+        text: Symbol,
+        lit_kind: token::LitKind,
+        span: Span,
+        label: &'static str,
+    ) {
+        if !contains_text_flow_control_chars(text.as_str()) {
+            return;
+        }
+        let (padding, point_at_inner_spans) = match lit_kind {
+            // account for `"` or `'`
+            token::LitKind::Str | token::LitKind::Char => (1, true),
+            // account for `c"`
+            token::LitKind::CStr => (2, true),
+            // account for `r###"`
+            token::LitKind::StrRaw(n) => (n as u32 + 2, true),
+            // account for `cr###"`
+            token::LitKind::CStrRaw(n) => (n as u32 + 3, true),
+            // suppress bad literals.
+            token::LitKind::Err(_) => return,
+            // Be conservative just in case new literals do support these.
+            _ => (0, false),
+        };
+        self.report_text_direction_codepoint(
+            text.as_str(),
+            span,
+            padding,
+            point_at_inner_spans,
+            label,
+        );
+    }
+
+    fn report_text_direction_codepoint(
+        &self,
+        text: &str,
+        span: Span,
+        padding: u32,
+        point_at_inner_spans: bool,
+        label: &str,
+    ) {
+        // Obtain the `Span`s for each of the forbidden chars.
+        let spans: Vec<_> = text
+            .char_indices()
+            .filter_map(|(i, c)| {
+                TEXT_FLOW_CONTROL_CHARS.contains(&c).then(|| {
+                    let lo = span.lo() + BytePos(i as u32 + padding);
+                    (c, span.with_lo(lo).with_hi(lo + BytePos(c.len_utf8() as u32)))
+                })
+            })
+            .collect();
+
+        let count = spans.len();
+        let labels = point_at_inner_spans.then_some(spans.clone());
+
+        self.psess.buffer_lint(
+            TEXT_DIRECTION_CODEPOINT_IN_LITERAL,
+            span,
+            ast::CRATE_NODE_ID,
+            BuiltinLintDiag::HiddenUnicodeCodepoints {
+                label: label.to_string(),
+                count,
+                span_label: span,
+                labels,
+                escape: point_at_inner_spans && !spans.is_empty(),
+                spans,
+            },
+        );
+    }
+
     fn validate_frontmatter(
         &self,
         start: BytePos,
diff --git a/compiler/rustc_parse/src/parser/asm.rs b/compiler/rustc_parse/src/parser/asm.rs
new file mode 100644
index 00000000000..d4d0612a317
--- /dev/null
+++ b/compiler/rustc_parse/src/parser/asm.rs
@@ -0,0 +1,385 @@
+use rustc_ast::ptr::P;
+use rustc_ast::{self as ast, AsmMacro};
+use rustc_span::{Span, Symbol, kw};
+
+use super::{ExpKeywordPair, ForceCollect, IdentIsRaw, Trailing, UsePreAttrPos};
+use crate::{PResult, Parser, errors, exp, token};
+
+/// An argument to one of the `asm!` macros. The argument is syntactically valid, but is otherwise
+/// not validated at all.
+pub struct AsmArg {
+    pub kind: AsmArgKind,
+    pub attributes: AsmAttrVec,
+    pub span: Span,
+}
+
+pub enum AsmArgKind {
+    Template(P<ast::Expr>),
+    Operand(Option<Symbol>, ast::InlineAsmOperand),
+    Options(Vec<AsmOption>),
+    ClobberAbi(Vec<(Symbol, Span)>),
+}
+
+pub struct AsmOption {
+    pub symbol: Symbol,
+    pub span: Span,
+    // A bitset, with only the bit for this option's symbol set.
+    pub options: ast::InlineAsmOptions,
+    // Used when suggesting to remove an option.
+    pub span_with_comma: Span,
+}
+
+/// A parsed list of attributes that is not attached to any item.
+/// Used to check whether `asm!` arguments are configured out.
+pub struct AsmAttrVec(pub ast::AttrVec);
+
+impl AsmAttrVec {
+    fn parse<'a>(p: &mut Parser<'a>) -> PResult<'a, Self> {
+        let attrs = p.parse_outer_attributes()?;
+
+        p.collect_tokens(None, attrs, ForceCollect::No, |_, attrs| {
+            Ok((Self(attrs), Trailing::No, UsePreAttrPos::No))
+        })
+    }
+}
+impl ast::HasAttrs for AsmAttrVec {
+    // Follows `ast::Expr`.
+    const SUPPORTS_CUSTOM_INNER_ATTRS: bool = false;
+
+    fn attrs(&self) -> &[rustc_ast::Attribute] {
+        &self.0
+    }
+
+    fn visit_attrs(&mut self, f: impl FnOnce(&mut rustc_ast::AttrVec)) {
+        f(&mut self.0)
+    }
+}
+
+impl ast::HasTokens for AsmAttrVec {
+    fn tokens(&self) -> Option<&rustc_ast::tokenstream::LazyAttrTokenStream> {
+        None
+    }
+
+    fn tokens_mut(&mut self) -> Option<&mut Option<rustc_ast::tokenstream::LazyAttrTokenStream>> {
+        None
+    }
+}
+
+/// Used for better error messages when operand types are used that are not
+/// supported by the current macro (e.g. `in` or `out` for `global_asm!`)
+///
+/// returns
+///
+/// - `Ok(true)` if the current token matches the keyword, and was expected
+/// - `Ok(false)` if the current token does not match the keyword
+/// - `Err(_)` if the current token matches the keyword, but was not expected
+fn eat_operand_keyword<'a>(
+    p: &mut Parser<'a>,
+    exp: ExpKeywordPair,
+    asm_macro: AsmMacro,
+) -> PResult<'a, bool> {
+    if matches!(asm_macro, AsmMacro::Asm) {
+        Ok(p.eat_keyword(exp))
+    } else {
+        let span = p.token.span;
+        if p.eat_keyword_noexpect(exp.kw) {
+            // in gets printed as `r#in` otherwise
+            let symbol = if exp.kw == kw::In { "in" } else { exp.kw.as_str() };
+            Err(p.dcx().create_err(errors::AsmUnsupportedOperand {
+                span,
+                symbol,
+                macro_name: asm_macro.macro_name(),
+            }))
+        } else {
+            Ok(false)
+        }
+    }
+}
+
+fn parse_asm_operand<'a>(
+    p: &mut Parser<'a>,
+    asm_macro: AsmMacro,
+) -> PResult<'a, Option<ast::InlineAsmOperand>> {
+    let dcx = p.dcx();
+
+    Ok(Some(if eat_operand_keyword(p, exp!(In), asm_macro)? {
+        let reg = parse_reg(p)?;
+        if p.eat_keyword(exp!(Underscore)) {
+            let err = dcx.create_err(errors::AsmUnderscoreInput { span: p.token.span });
+            return Err(err);
+        }
+        let expr = p.parse_expr()?;
+        ast::InlineAsmOperand::In { reg, expr }
+    } else if eat_operand_keyword(p, exp!(Out), asm_macro)? {
+        let reg = parse_reg(p)?;
+        let expr = if p.eat_keyword(exp!(Underscore)) { None } else { Some(p.parse_expr()?) };
+        ast::InlineAsmOperand::Out { reg, expr, late: false }
+    } else if eat_operand_keyword(p, exp!(Lateout), asm_macro)? {
+        let reg = parse_reg(p)?;
+        let expr = if p.eat_keyword(exp!(Underscore)) { None } else { Some(p.parse_expr()?) };
+        ast::InlineAsmOperand::Out { reg, expr, late: true }
+    } else if eat_operand_keyword(p, exp!(Inout), asm_macro)? {
+        let reg = parse_reg(p)?;
+        if p.eat_keyword(exp!(Underscore)) {
+            let err = dcx.create_err(errors::AsmUnderscoreInput { span: p.token.span });
+            return Err(err);
+        }
+        let expr = p.parse_expr()?;
+        if p.eat(exp!(FatArrow)) {
+            let out_expr =
+                if p.eat_keyword(exp!(Underscore)) { None } else { Some(p.parse_expr()?) };
+            ast::InlineAsmOperand::SplitInOut { reg, in_expr: expr, out_expr, late: false }
+        } else {
+            ast::InlineAsmOperand::InOut { reg, expr, late: false }
+        }
+    } else if eat_operand_keyword(p, exp!(Inlateout), asm_macro)? {
+        let reg = parse_reg(p)?;
+        if p.eat_keyword(exp!(Underscore)) {
+            let err = dcx.create_err(errors::AsmUnderscoreInput { span: p.token.span });
+            return Err(err);
+        }
+        let expr = p.parse_expr()?;
+        if p.eat(exp!(FatArrow)) {
+            let out_expr =
+                if p.eat_keyword(exp!(Underscore)) { None } else { Some(p.parse_expr()?) };
+            ast::InlineAsmOperand::SplitInOut { reg, in_expr: expr, out_expr, late: true }
+        } else {
+            ast::InlineAsmOperand::InOut { reg, expr, late: true }
+        }
+    } else if eat_operand_keyword(p, exp!(Label), asm_macro)? {
+        let block = p.parse_block()?;
+        ast::InlineAsmOperand::Label { block }
+    } else if p.eat_keyword(exp!(Const)) {
+        let anon_const = p.parse_expr_anon_const()?;
+        ast::InlineAsmOperand::Const { anon_const }
+    } else if p.eat_keyword(exp!(Sym)) {
+        let expr = p.parse_expr()?;
+        let ast::ExprKind::Path(qself, path) = &expr.kind else {
+            let err = dcx.create_err(errors::AsmSymNoPath { span: expr.span });
+            return Err(err);
+        };
+        let sym =
+            ast::InlineAsmSym { id: ast::DUMMY_NODE_ID, qself: qself.clone(), path: path.clone() };
+        ast::InlineAsmOperand::Sym { sym }
+    } else {
+        return Ok(None);
+    }))
+}
+
+// Public for rustfmt.
+pub fn parse_asm_args<'a>(
+    p: &mut Parser<'a>,
+    sp: Span,
+    asm_macro: AsmMacro,
+) -> PResult<'a, Vec<AsmArg>> {
+    let dcx = p.dcx();
+
+    if p.token == token::Eof {
+        return Err(dcx.create_err(errors::AsmRequiresTemplate { span: sp }));
+    }
+
+    let mut args = Vec::new();
+
+    let attributes = AsmAttrVec::parse(p)?;
+    let first_template = p.parse_expr()?;
+    args.push(AsmArg {
+        span: first_template.span,
+        kind: AsmArgKind::Template(first_template),
+        attributes,
+    });
+
+    let mut allow_templates = true;
+
+    while p.token != token::Eof {
+        if !p.eat(exp!(Comma)) {
+            if allow_templates {
+                // After a template string, we always expect *only* a comma...
+                return Err(dcx.create_err(errors::AsmExpectedComma { span: p.token.span }));
+            } else {
+                // ...after that delegate to `expect` to also include the other expected tokens.
+                return Err(p.expect(exp!(Comma)).err().unwrap());
+            }
+        }
+
+        // Accept trailing commas.
+        if p.token == token::Eof {
+            break;
+        }
+
+        let attributes = AsmAttrVec::parse(p)?;
+        let span_start = p.token.span;
+
+        // Parse `clobber_abi`.
+        if p.eat_keyword(exp!(ClobberAbi)) {
+            allow_templates = false;
+
+            args.push(AsmArg {
+                kind: AsmArgKind::ClobberAbi(parse_clobber_abi(p)?),
+                span: span_start.to(p.prev_token.span),
+                attributes,
+            });
+
+            continue;
+        }
+
+        // Parse `options`.
+        if p.eat_keyword(exp!(Options)) {
+            allow_templates = false;
+
+            args.push(AsmArg {
+                kind: AsmArgKind::Options(parse_options(p, asm_macro)?),
+                span: span_start.to(p.prev_token.span),
+                attributes,
+            });
+
+            continue;
+        }
+
+        // Parse operand names.
+        let name = if p.token.is_ident() && p.look_ahead(1, |t| *t == token::Eq) {
+            let (ident, _) = p.token.ident().unwrap();
+            p.bump();
+            p.expect(exp!(Eq))?;
+            allow_templates = false;
+            Some(ident.name)
+        } else {
+            None
+        };
+
+        if let Some(op) = parse_asm_operand(p, asm_macro)? {
+            allow_templates = false;
+
+            args.push(AsmArg {
+                span: span_start.to(p.prev_token.span),
+                kind: AsmArgKind::Operand(name, op),
+                attributes,
+            });
+        } else if allow_templates {
+            let template = p.parse_expr()?;
+            // If it can't possibly expand to a string, provide diagnostics here to include other
+            // things it could have been.
+            match template.kind {
+                ast::ExprKind::Lit(token_lit)
+                    if matches!(
+                        token_lit.kind,
+                        token::LitKind::Str | token::LitKind::StrRaw(_)
+                    ) => {}
+                ast::ExprKind::MacCall(..) => {}
+                _ => {
+                    let err = dcx.create_err(errors::AsmExpectedOther {
+                        span: template.span,
+                        is_inline_asm: matches!(asm_macro, AsmMacro::Asm),
+                    });
+                    return Err(err);
+                }
+            }
+
+            args.push(AsmArg {
+                span: template.span,
+                kind: AsmArgKind::Template(template),
+                attributes,
+            });
+        } else {
+            p.unexpected_any()?
+        }
+    }
+
+    Ok(args)
+}
+
+fn parse_options<'a>(p: &mut Parser<'a>, asm_macro: AsmMacro) -> PResult<'a, Vec<AsmOption>> {
+    p.expect(exp!(OpenParen))?;
+
+    let mut asm_options = Vec::new();
+
+    while !p.eat(exp!(CloseParen)) {
+        const OPTIONS: [(ExpKeywordPair, ast::InlineAsmOptions); ast::InlineAsmOptions::COUNT] = [
+            (exp!(Pure), ast::InlineAsmOptions::PURE),
+            (exp!(Nomem), ast::InlineAsmOptions::NOMEM),
+            (exp!(Readonly), ast::InlineAsmOptions::READONLY),
+            (exp!(PreservesFlags), ast::InlineAsmOptions::PRESERVES_FLAGS),
+            (exp!(Noreturn), ast::InlineAsmOptions::NORETURN),
+            (exp!(Nostack), ast::InlineAsmOptions::NOSTACK),
+            (exp!(MayUnwind), ast::InlineAsmOptions::MAY_UNWIND),
+            (exp!(AttSyntax), ast::InlineAsmOptions::ATT_SYNTAX),
+            (exp!(Raw), ast::InlineAsmOptions::RAW),
+        ];
+
+        'blk: {
+            for (exp, options) in OPTIONS {
+                // Gives a more accurate list of expected next tokens.
+                let kw_matched = if asm_macro.is_supported_option(options) {
+                    p.eat_keyword(exp)
+                } else {
+                    p.eat_keyword_noexpect(exp.kw)
+                };
+
+                if kw_matched {
+                    let span = p.prev_token.span;
+                    let span_with_comma =
+                        if p.token == token::Comma { span.to(p.token.span) } else { span };
+
+                    asm_options.push(AsmOption { symbol: exp.kw, span, options, span_with_comma });
+                    break 'blk;
+                }
+            }
+
+            return p.unexpected_any();
+        }
+
+        // Allow trailing commas.
+        if p.eat(exp!(CloseParen)) {
+            break;
+        }
+        p.expect(exp!(Comma))?;
+    }
+
+    Ok(asm_options)
+}
+
+fn parse_clobber_abi<'a>(p: &mut Parser<'a>) -> PResult<'a, Vec<(Symbol, Span)>> {
+    p.expect(exp!(OpenParen))?;
+
+    if p.eat(exp!(CloseParen)) {
+        return Err(p.dcx().create_err(errors::NonABI { span: p.token.span }));
+    }
+
+    let mut new_abis = Vec::new();
+    while !p.eat(exp!(CloseParen)) {
+        match p.parse_str_lit() {
+            Ok(str_lit) => {
+                new_abis.push((str_lit.symbol_unescaped, str_lit.span));
+            }
+            Err(opt_lit) => {
+                let span = opt_lit.map_or(p.token.span, |lit| lit.span);
+                return Err(p.dcx().create_err(errors::AsmExpectedStringLiteral { span }));
+            }
+        };
+
+        // Allow trailing commas
+        if p.eat(exp!(CloseParen)) {
+            break;
+        }
+        p.expect(exp!(Comma))?;
+    }
+
+    Ok(new_abis)
+}
+
+fn parse_reg<'a>(p: &mut Parser<'a>) -> PResult<'a, ast::InlineAsmRegOrRegClass> {
+    p.expect(exp!(OpenParen))?;
+    let result = match p.token.uninterpolate().kind {
+        token::Ident(name, IdentIsRaw::No) => ast::InlineAsmRegOrRegClass::RegClass(name),
+        token::Literal(token::Lit { kind: token::LitKind::Str, symbol, suffix: _ }) => {
+            ast::InlineAsmRegOrRegClass::Reg(symbol)
+        }
+        _ => {
+            return Err(p.dcx().create_err(errors::ExpectedRegisterClassOrExplicitRegister {
+                span: p.token.span,
+            }));
+        }
+    };
+    p.bump();
+    p.expect(exp!(CloseParen))?;
+    Ok(result)
+}
diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs
index 2a7910a6af4..1a44f4af8a6 100644
--- a/compiler/rustc_parse/src/parser/expr.rs
+++ b/compiler/rustc_parse/src/parser/expr.rs
@@ -3311,26 +3311,44 @@ impl<'a> Parser<'a> {
                             let sm = this.psess.source_map();
                             if let Ok(expr_lines) = sm.span_to_lines(expr_span)
                                 && let Ok(arm_start_lines) = sm.span_to_lines(arm_start_span)
-                                && arm_start_lines.lines[0].end_col == expr_lines.lines[0].end_col
                                 && expr_lines.lines.len() == 2
                             {
-                                // We check whether there's any trailing code in the parse span,
-                                // if there isn't, we very likely have the following:
-                                //
-                                // X |     &Y => "y"
-                                //   |        --    - missing comma
-                                //   |        |
-                                //   |        arrow_span
-                                // X |     &X => "x"
-                                //   |      - ^^ self.token.span
-                                //   |      |
-                                //   |      parsed until here as `"y" & X`
-                                err.span_suggestion_short(
-                                    arm_start_span.shrink_to_hi(),
-                                    "missing a comma here to end this `match` arm",
-                                    ",",
-                                    Applicability::MachineApplicable,
-                                );
+                                if arm_start_lines.lines[0].end_col == expr_lines.lines[0].end_col {
+                                    // We check whether there's any trailing code in the parse span,
+                                    // if there isn't, we very likely have the following:
+                                    //
+                                    // X |     &Y => "y"
+                                    //   |        --    - missing comma
+                                    //   |        |
+                                    //   |        arrow_span
+                                    // X |     &X => "x"
+                                    //   |      - ^^ self.token.span
+                                    //   |      |
+                                    //   |      parsed until here as `"y" & X`
+                                    err.span_suggestion_short(
+                                        arm_start_span.shrink_to_hi(),
+                                        "missing a comma here to end this `match` arm",
+                                        ",",
+                                        Applicability::MachineApplicable,
+                                    );
+                                } else if arm_start_lines.lines[0].end_col + rustc_span::CharPos(1)
+                                    == expr_lines.lines[0].end_col
+                                {
+                                    // similar to the above, but we may typo a `.` or `/` at the end of the line
+                                    let comma_span = arm_start_span
+                                        .shrink_to_hi()
+                                        .with_hi(arm_start_span.hi() + rustc_span::BytePos(1));
+                                    if let Ok(res) = sm.span_to_snippet(comma_span)
+                                        && (res == "." || res == "/")
+                                    {
+                                        err.span_suggestion_short(
+                                            comma_span,
+                                            "you might have meant to write a `,` to end this `match` arm",
+                                            ",",
+                                            Applicability::MachineApplicable,
+                                        );
+                                    }
+                                }
                             }
                         } else {
                             err.span_label(
diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs
index babc55ccc0f..c7b0eb11e5a 100644
--- a/compiler/rustc_parse/src/parser/item.rs
+++ b/compiler/rustc_parse/src/parser/item.rs
@@ -1577,7 +1577,7 @@ impl<'a> Parser<'a> {
         };
 
         let enum_definition = EnumDef { variants: variants.into_iter().flatten().collect() };
-        Ok(ItemKind::Enum(ident, enum_definition, generics))
+        Ok(ItemKind::Enum(ident, generics, enum_definition))
     }
 
     fn parse_enum_variant(&mut self, span: Span) -> PResult<'a, Option<Variant>> {
@@ -1732,7 +1732,7 @@ impl<'a> Parser<'a> {
             return Err(self.dcx().create_err(err));
         };
 
-        Ok(ItemKind::Struct(ident, vdata, generics))
+        Ok(ItemKind::Struct(ident, generics, vdata))
     }
 
     /// Parses `union Foo { ... }`.
@@ -1764,7 +1764,7 @@ impl<'a> Parser<'a> {
             return Err(err);
         };
 
-        Ok(ItemKind::Union(ident, vdata, generics))
+        Ok(ItemKind::Union(ident, generics, vdata))
     }
 
     /// This function parses the fields of record structs:
diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs
index 968376678f3..b2e90251367 100644
--- a/compiler/rustc_parse/src/parser/mod.rs
+++ b/compiler/rustc_parse/src/parser/mod.rs
@@ -1,3 +1,4 @@
+pub mod asm;
 pub mod attr;
 mod attr_wrapper;
 mod diagnostics;
diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs
index 396ded96bde..c37cb0881c3 100644
--- a/compiler/rustc_parse/src/parser/stmt.rs
+++ b/compiler/rustc_parse/src/parser/stmt.rs
@@ -515,8 +515,8 @@ impl<'a> Parser<'a> {
     fn error_block_no_opening_brace_msg(&mut self, msg: Cow<'static, str>) -> Diag<'a> {
         let prev = self.prev_token.span;
         let sp = self.token.span;
-        let mut e = self.dcx().struct_span_err(sp, msg);
-        self.label_expected_raw_ref(&mut e);
+        let mut err = self.dcx().struct_span_err(sp, msg);
+        self.label_expected_raw_ref(&mut err);
 
         let do_not_suggest_help = self.token.is_keyword(kw::In)
             || self.token == token::Colon
@@ -558,20 +558,19 @@ impl<'a> Parser<'a> {
                     stmt.span
                 };
                 self.suggest_fixes_misparsed_for_loop_head(
-                    &mut e,
+                    &mut err,
                     prev.between(sp),
                     stmt_span,
                     &stmt.kind,
                 );
             }
             Err(e) => {
-                self.recover_stmt_(SemiColonMode::Break, BlockMode::Ignore);
-                e.cancel();
+                e.delay_as_bug();
             }
             _ => {}
         }
-        e.span_label(sp, "expected `{`");
-        e
+        err.span_label(sp, "expected `{`");
+        err
     }
 
     fn suggest_fixes_misparsed_for_loop_head(
@@ -714,7 +713,7 @@ impl<'a> Parser<'a> {
 
     /// Parses the rest of a block expression or function body.
     /// Precondition: already parsed the '{'.
-    pub(crate) fn parse_block_tail(
+    pub fn parse_block_tail(
         &mut self,
         lo: Span,
         s: BlockCheckMode,
diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs
index 1d024694049..5b7d45bb152 100644
--- a/compiler/rustc_passes/src/check_attr.rs
+++ b/compiler/rustc_passes/src/check_attr.rs
@@ -255,7 +255,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
                             self.check_generic_attr(hir_id, attr, target, Target::Fn);
                             self.check_proc_macro(hir_id, target, ProcMacroKind::Derive)
                         }
-                        [sym::autodiff, ..] => {
+                        [sym::autodiff_forward, ..] | [sym::autodiff_reverse, ..] => {
                             self.check_autodiff(hir_id, attr, span, target)
                         }
                         [sym::coroutine, ..] => {
@@ -802,7 +802,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
         match target {
             Target::Struct => {
                 if let Some(ItemLike::Item(hir::Item {
-                    kind: hir::ItemKind::Struct(_, hir::VariantData::Struct { fields, .. }, _),
+                    kind: hir::ItemKind::Struct(_, _, hir::VariantData::Struct { fields, .. }),
                     ..
                 })) = item
                     && !fields.is_empty()
@@ -1130,12 +1130,12 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
             return;
         };
         match item.kind {
-            ItemKind::Enum(_, _, generics) | ItemKind::Struct(_, _, generics)
+            ItemKind::Enum(_, generics, _) | ItemKind::Struct(_, generics, _)
                 if generics.params.len() != 0 => {}
             ItemKind::Trait(_, _, _, generics, _, items)
                 if generics.params.len() != 0
                     || items.iter().any(|item| matches!(item.kind, AssocItemKind::Type)) => {}
-            ItemKind::TyAlias(_, _, generics) if generics.params.len() != 0 => {}
+            ItemKind::TyAlias(_, generics, _) if generics.params.len() != 0 => {}
             _ => {
                 self.dcx().emit_err(errors::DocSearchUnboxInvalid { span: meta.span() });
             }
@@ -2312,7 +2312,9 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
     }
 
     fn check_macro_use(&self, hir_id: HirId, attr: &Attribute, target: Target) {
-        let name = attr.name().unwrap();
+        let Some(name) = attr.name() else {
+            return;
+        };
         match target {
             Target::ExternCrate | Target::Mod => {}
             _ => {
@@ -2792,7 +2794,7 @@ impl<'tcx> Visitor<'tcx> for CheckAttrVisitor<'tcx> {
 }
 
 fn is_c_like_enum(item: &Item<'_>) -> bool {
-    if let ItemKind::Enum(_, ref def, _) = item.kind {
+    if let ItemKind::Enum(_, _, ref def) = item.kind {
         for variant in def.variants {
             match variant.data {
                 hir::VariantData::Unit(..) => { /* continue */ }
diff --git a/compiler/rustc_passes/src/check_export.rs b/compiler/rustc_passes/src/check_export.rs
index 2bb698689be..b9a3849f32f 100644
--- a/compiler/rustc_passes/src/check_export.rs
+++ b/compiler/rustc_passes/src/check_export.rs
@@ -132,7 +132,7 @@ impl<'tcx> Visitor<'tcx> for ExportableItemCollector<'tcx> {
                 self.add_exportable(def_id);
             }
             hir::ItemKind::Use(path, _) => {
-                for res in &path.res {
+                for res in path.res.present_items() {
                     // Only local items are exportable.
                     if let Some(res_id) = res.opt_def_id()
                         && let Some(res_id) = res_id.as_local()
diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs
index 6e5357d8007..6b82252f32c 100644
--- a/compiler/rustc_passes/src/dead.rs
+++ b/compiler/rustc_passes/src/dead.rs
@@ -8,12 +8,13 @@ use std::mem;
 use hir::ItemKind;
 use hir::def_id::{LocalDefIdMap, LocalDefIdSet};
 use rustc_abi::FieldIdx;
+use rustc_data_structures::fx::FxIndexSet;
 use rustc_data_structures::unord::UnordSet;
 use rustc_errors::MultiSpan;
 use rustc_hir::def::{CtorOf, DefKind, Res};
 use rustc_hir::def_id::{DefId, LocalDefId, LocalModDefId};
 use rustc_hir::intravisit::{self, Visitor};
-use rustc_hir::{self as hir, Node, PatKind, TyKind};
+use rustc_hir::{self as hir, Node, PatKind, QPath, TyKind};
 use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
 use rustc_middle::middle::privacy::Level;
 use rustc_middle::query::Providers;
@@ -44,15 +45,20 @@ fn should_explore(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
     )
 }
 
-fn ty_ref_to_pub_struct(tcx: TyCtxt<'_>, ty: &hir::Ty<'_>) -> bool {
-    if let TyKind::Path(hir::QPath::Resolved(_, path)) = ty.kind
-        && let Res::Def(def_kind, def_id) = path.res
-        && def_id.is_local()
-        && matches!(def_kind, DefKind::Struct | DefKind::Enum | DefKind::Union)
-    {
-        tcx.visibility(def_id).is_public()
-    } else {
-        true
+/// Returns the local def id of the ADT if the given ty refers to a local one.
+fn local_adt_def_of_ty<'tcx>(ty: &hir::Ty<'tcx>) -> Option<LocalDefId> {
+    match ty.kind {
+        TyKind::Path(QPath::Resolved(_, path)) => {
+            if let Res::Def(def_kind, def_id) = path.res
+                && let Some(local_def_id) = def_id.as_local()
+                && matches!(def_kind, DefKind::Struct | DefKind::Enum | DefKind::Union)
+            {
+                Some(local_def_id)
+            } else {
+                None
+            }
+        }
+        _ => None,
     }
 }
 
@@ -78,7 +84,7 @@ struct MarkSymbolVisitor<'tcx> {
     // maps from ADTs to ignored derived traits (e.g. Debug and Clone)
     // and the span of their respective impl (i.e., part of the derive
     // macro)
-    ignored_derived_traits: LocalDefIdMap<Vec<(DefId, DefId)>>,
+    ignored_derived_traits: LocalDefIdMap<FxIndexSet<(DefId, DefId)>>,
 }
 
 impl<'tcx> MarkSymbolVisitor<'tcx> {
@@ -360,7 +366,7 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
                 && let Some(fn_sig) =
                     self.tcx.hir_fn_sig_by_hir_id(self.tcx.local_def_id_to_hir_id(local_def_id))
                 && matches!(fn_sig.decl.implicit_self, hir::ImplicitSelfKind::None)
-                && let TyKind::Path(hir::QPath::Resolved(_, path)) =
+                && let TyKind::Path(QPath::Resolved(_, path)) =
                     self.tcx.hir_expect_item(local_impl_of).expect_impl().self_ty.kind
                 && let Res::Def(def_kind, did) = path.res
             {
@@ -388,7 +394,7 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
                     self.ignored_derived_traits
                         .entry(adt_def_id)
                         .or_default()
-                        .push((trait_of, impl_of));
+                        .insert((trait_of, impl_of));
                 }
                 return true;
             }
@@ -420,51 +426,22 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
                     intravisit::walk_item(self, item)
                 }
                 hir::ItemKind::ForeignMod { .. } => {}
-                hir::ItemKind::Trait(..) => {
-                    for &impl_def_id in self.tcx.local_trait_impls(item.owner_id.def_id) {
-                        if let ItemKind::Impl(impl_ref) = self.tcx.hir_expect_item(impl_def_id).kind
-                        {
-                            // skip items
-                            // mark dependent traits live
-                            intravisit::walk_generics(self, impl_ref.generics);
-                            // mark dependent parameters live
-                            intravisit::walk_path(self, impl_ref.of_trait.unwrap().path);
+                hir::ItemKind::Trait(.., trait_item_refs) => {
+                    // mark assoc ty live if the trait is live
+                    for trait_item in trait_item_refs {
+                        if matches!(trait_item.kind, hir::AssocItemKind::Type) {
+                            self.check_def_id(trait_item.id.owner_id.to_def_id());
                         }
                     }
-
                     intravisit::walk_item(self, item)
                 }
                 _ => intravisit::walk_item(self, item),
             },
             Node::TraitItem(trait_item) => {
-                // mark corresponding ImplTerm live
+                // mark the trait live
                 let trait_item_id = trait_item.owner_id.to_def_id();
                 if let Some(trait_id) = self.tcx.trait_of_item(trait_item_id) {
-                    // mark the trait live
                     self.check_def_id(trait_id);
-
-                    for impl_id in self.tcx.all_impls(trait_id) {
-                        if let Some(local_impl_id) = impl_id.as_local()
-                            && let ItemKind::Impl(impl_ref) =
-                                self.tcx.hir_expect_item(local_impl_id).kind
-                        {
-                            if !matches!(trait_item.kind, hir::TraitItemKind::Type(..))
-                                && !ty_ref_to_pub_struct(self.tcx, impl_ref.self_ty)
-                            {
-                                // skip methods of private ty,
-                                // they would be solved in `solve_rest_impl_items`
-                                continue;
-                            }
-
-                            // mark self_ty live
-                            intravisit::walk_unambig_ty(self, impl_ref.self_ty);
-                            if let Some(&impl_item_id) =
-                                self.tcx.impl_item_implementor_ids(impl_id).get(&trait_item_id)
-                            {
-                                self.check_def_id(impl_item_id);
-                            }
-                        }
-                    }
                 }
                 intravisit::walk_trait_item(self, trait_item);
             }
@@ -508,48 +485,58 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
         }
     }
 
-    fn solve_rest_impl_items(&mut self, mut unsolved_impl_items: Vec<(hir::ItemId, LocalDefId)>) {
-        let mut ready;
-        (ready, unsolved_impl_items) =
-            unsolved_impl_items.into_iter().partition(|&(impl_id, impl_item_id)| {
-                self.impl_item_with_used_self(impl_id, impl_item_id)
-            });
-
-        while !ready.is_empty() {
-            self.worklist =
-                ready.into_iter().map(|(_, id)| (id, ComesFromAllowExpect::No)).collect();
-            self.mark_live_symbols();
-
-            (ready, unsolved_impl_items) =
-                unsolved_impl_items.into_iter().partition(|&(impl_id, impl_item_id)| {
-                    self.impl_item_with_used_self(impl_id, impl_item_id)
-                });
+    /// Returns whether `local_def_id` is potentially alive or not.
+    /// `local_def_id` points to an impl or an impl item,
+    /// both impl and impl item that may be passed to this function are of a trait,
+    /// and added into the unsolved_items during `create_and_seed_worklist`
+    fn check_impl_or_impl_item_live(
+        &mut self,
+        impl_id: hir::ItemId,
+        local_def_id: LocalDefId,
+    ) -> bool {
+        if self.should_ignore_item(local_def_id.to_def_id()) {
+            return false;
         }
-    }
 
-    fn impl_item_with_used_self(&mut self, impl_id: hir::ItemId, impl_item_id: LocalDefId) -> bool {
-        if let TyKind::Path(hir::QPath::Resolved(_, path)) =
-            self.tcx.hir_item(impl_id).expect_impl().self_ty.kind
-            && let Res::Def(def_kind, def_id) = path.res
-            && let Some(local_def_id) = def_id.as_local()
-            && matches!(def_kind, DefKind::Struct | DefKind::Enum | DefKind::Union)
-        {
-            if self.tcx.visibility(impl_item_id).is_public() {
-                // for the public method, we don't know the trait item is used or not,
-                // so we mark the method live if the self is used
-                return self.live_symbols.contains(&local_def_id);
+        let trait_def_id = match self.tcx.def_kind(local_def_id) {
+            // assoc impl items of traits are live if the corresponding trait items are live
+            DefKind::AssocFn => self.tcx.associated_item(local_def_id).trait_item_def_id,
+            // impl items are live if the corresponding traits are live
+            DefKind::Impl { of_trait: true } => self
+                .tcx
+                .impl_trait_ref(impl_id.owner_id.def_id)
+                .and_then(|trait_ref| Some(trait_ref.skip_binder().def_id)),
+            _ => None,
+        };
+
+        if let Some(trait_def_id) = trait_def_id {
+            if let Some(trait_def_id) = trait_def_id.as_local()
+                && !self.live_symbols.contains(&trait_def_id)
+            {
+                return false;
             }
 
-            if let Some(trait_item_id) = self.tcx.associated_item(impl_item_id).trait_item_def_id
-                && let Some(local_id) = trait_item_id.as_local()
+            // FIXME: legacy logic to check whether the function may construct `Self`,
+            // this can be removed after supporting marking ADTs appearing in patterns
+            // as live, then we can check private impls of public traits directly
+            if let Some(fn_sig) =
+                self.tcx.hir_fn_sig_by_hir_id(self.tcx.local_def_id_to_hir_id(local_def_id))
+                && matches!(fn_sig.decl.implicit_self, hir::ImplicitSelfKind::None)
+                && self.tcx.visibility(trait_def_id).is_public()
             {
-                // for the private method, we can know the trait item is used or not,
-                // so we mark the method live if the self is used and the trait item is used
-                return self.live_symbols.contains(&local_id)
-                    && self.live_symbols.contains(&local_def_id);
+                return true;
             }
         }
-        false
+
+        // The impl or impl item is used if the corresponding trait or trait item is used and the ty is used.
+        if let Some(local_def_id) =
+            local_adt_def_of_ty(self.tcx.hir_item(impl_id).expect_impl().self_ty)
+            && !self.live_symbols.contains(&local_def_id)
+        {
+            return false;
+        }
+
+        true
     }
 }
 
@@ -584,7 +571,7 @@ impl<'tcx> Visitor<'tcx> for MarkSymbolVisitor<'tcx> {
 
     fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) {
         match expr.kind {
-            hir::ExprKind::Path(ref qpath @ hir::QPath::TypeRelative(..)) => {
+            hir::ExprKind::Path(ref qpath @ QPath::TypeRelative(..)) => {
                 let res = self.typeck_results().qpath_res(qpath, expr.hir_id);
                 self.handle_res(res);
             }
@@ -738,7 +725,7 @@ fn check_item<'tcx>(
     tcx: TyCtxt<'tcx>,
     worklist: &mut Vec<(LocalDefId, ComesFromAllowExpect)>,
     struct_constructors: &mut LocalDefIdMap<LocalDefId>,
-    unsolved_impl_items: &mut Vec<(hir::ItemId, LocalDefId)>,
+    unsolved_items: &mut Vec<(hir::ItemId, LocalDefId)>,
     id: hir::ItemId,
 ) {
     let allow_dead_code = has_allow_dead_code_or_lang_attr(tcx, id.owner_id.def_id);
@@ -749,7 +736,7 @@ fn check_item<'tcx>(
     match tcx.def_kind(id.owner_id) {
         DefKind::Enum => {
             let item = tcx.hir_item(id);
-            if let hir::ItemKind::Enum(_, ref enum_def, _) = item.kind {
+            if let hir::ItemKind::Enum(_, _, ref enum_def) = item.kind {
                 if let Some(comes_from_allow) = allow_dead_code {
                     worklist.extend(
                         enum_def.variants.iter().map(|variant| (variant.def_id, comes_from_allow)),
@@ -764,47 +751,39 @@ fn check_item<'tcx>(
             }
         }
         DefKind::Impl { of_trait } => {
-            // get DefIds from another query
-            let local_def_ids = tcx
-                .associated_item_def_ids(id.owner_id)
-                .iter()
-                .filter_map(|def_id| def_id.as_local());
-
-            let ty_is_pub = ty_ref_to_pub_struct(tcx, tcx.hir_item(id).expect_impl().self_ty);
-
-            // And we access the Map here to get HirId from LocalDefId
-            for local_def_id in local_def_ids {
-                // check the function may construct Self
-                let mut may_construct_self = false;
-                if let Some(fn_sig) =
-                    tcx.hir_fn_sig_by_hir_id(tcx.local_def_id_to_hir_id(local_def_id))
-                {
-                    may_construct_self =
-                        matches!(fn_sig.decl.implicit_self, hir::ImplicitSelfKind::None);
-                }
+            if let Some(comes_from_allow) =
+                has_allow_dead_code_or_lang_attr(tcx, id.owner_id.def_id)
+            {
+                worklist.push((id.owner_id.def_id, comes_from_allow));
+            } else if of_trait {
+                unsolved_items.push((id, id.owner_id.def_id));
+            }
 
-                // for trait impl blocks,
-                // mark the method live if the self_ty is public,
-                // or the method is public and may construct self
-                if of_trait
-                    && (!matches!(tcx.def_kind(local_def_id), DefKind::AssocFn)
-                        || tcx.visibility(local_def_id).is_public()
-                            && (ty_is_pub || may_construct_self))
-                {
-                    worklist.push((local_def_id, ComesFromAllowExpect::No));
-                } else if let Some(comes_from_allow) =
-                    has_allow_dead_code_or_lang_attr(tcx, local_def_id)
+            for def_id in tcx.associated_item_def_ids(id.owner_id) {
+                let local_def_id = def_id.expect_local();
+
+                if let Some(comes_from_allow) = has_allow_dead_code_or_lang_attr(tcx, local_def_id)
                 {
                     worklist.push((local_def_id, comes_from_allow));
                 } else if of_trait {
-                    // private method || public method not constructs self
-                    unsolved_impl_items.push((id, local_def_id));
+                    // FIXME: This condition can be removed
+                    // if we support dead check for assoc consts and tys.
+                    if !matches!(tcx.def_kind(local_def_id), DefKind::AssocFn) {
+                        worklist.push((local_def_id, ComesFromAllowExpect::No));
+                    } else {
+                        // We only care about associated items of traits,
+                        // because they cannot be visited directly,
+                        // so we later mark them as live if their corresponding traits
+                        // or trait items and self types are both live,
+                        // but inherent associated items can be visited and marked directly.
+                        unsolved_items.push((id, local_def_id));
+                    }
                 }
             }
         }
         DefKind::Struct => {
             let item = tcx.hir_item(id);
-            if let hir::ItemKind::Struct(_, ref variant_data, _) = item.kind
+            if let hir::ItemKind::Struct(_, _, ref variant_data) = item.kind
                 && let Some(ctor_def_id) = variant_data.ctor_def_id()
             {
                 struct_constructors.insert(ctor_def_id, item.owner_id.def_id);
@@ -892,8 +871,8 @@ fn create_and_seed_worklist(
 fn live_symbols_and_ignored_derived_traits(
     tcx: TyCtxt<'_>,
     (): (),
-) -> (LocalDefIdSet, LocalDefIdMap<Vec<(DefId, DefId)>>) {
-    let (worklist, struct_constructors, unsolved_impl_items) = create_and_seed_worklist(tcx);
+) -> (LocalDefIdSet, LocalDefIdMap<FxIndexSet<(DefId, DefId)>>) {
+    let (worklist, struct_constructors, mut unsolved_items) = create_and_seed_worklist(tcx);
     let mut symbol_visitor = MarkSymbolVisitor {
         worklist,
         tcx,
@@ -907,7 +886,22 @@ fn live_symbols_and_ignored_derived_traits(
         ignored_derived_traits: Default::default(),
     };
     symbol_visitor.mark_live_symbols();
-    symbol_visitor.solve_rest_impl_items(unsolved_impl_items);
+    let mut items_to_check;
+    (items_to_check, unsolved_items) =
+        unsolved_items.into_iter().partition(|&(impl_id, local_def_id)| {
+            symbol_visitor.check_impl_or_impl_item_live(impl_id, local_def_id)
+        });
+
+    while !items_to_check.is_empty() {
+        symbol_visitor.worklist =
+            items_to_check.into_iter().map(|(_, id)| (id, ComesFromAllowExpect::No)).collect();
+        symbol_visitor.mark_live_symbols();
+
+        (items_to_check, unsolved_items) =
+            unsolved_items.into_iter().partition(|&(impl_id, local_def_id)| {
+                symbol_visitor.check_impl_or_impl_item_live(impl_id, local_def_id)
+            });
+    }
 
     (symbol_visitor.live_symbols, symbol_visitor.ignored_derived_traits)
 }
@@ -921,7 +915,7 @@ struct DeadItem {
 struct DeadVisitor<'tcx> {
     tcx: TyCtxt<'tcx>,
     live_symbols: &'tcx LocalDefIdSet,
-    ignored_derived_traits: &'tcx LocalDefIdMap<Vec<(DefId, DefId)>>,
+    ignored_derived_traits: &'tcx LocalDefIdMap<FxIndexSet<(DefId, DefId)>>,
 }
 
 enum ShouldWarnAboutField {
@@ -1061,7 +1055,7 @@ impl<'tcx> DeadVisitor<'tcx> {
                 let tuple_fields = if let Some(parent_id) = parent_item
                     && let node = tcx.hir_node_by_def_id(parent_id)
                     && let hir::Node::Item(hir::Item {
-                        kind: hir::ItemKind::Struct(_, hir::VariantData::Tuple(fields, _, _), _),
+                        kind: hir::ItemKind::Struct(_, _, hir::VariantData::Tuple(fields, _, _)),
                         ..
                     }) = node
                 {
@@ -1188,19 +1182,15 @@ fn check_mod_deathness(tcx: TyCtxt<'_>, module: LocalModDefId) {
         let def_kind = tcx.def_kind(item.owner_id);
 
         let mut dead_codes = Vec::new();
-        // if we have diagnosed the trait, do not diagnose unused methods
-        if matches!(def_kind, DefKind::Impl { .. })
+        // Only diagnose unused assoc items in inherient impl and used trait,
+        // for unused assoc items in impls of trait,
+        // we have diagnosed them in the trait if they are unused,
+        // for unused assoc items in unused trait,
+        // we have diagnosed the unused trait.
+        if matches!(def_kind, DefKind::Impl { of_trait: false })
             || (def_kind == DefKind::Trait && live_symbols.contains(&item.owner_id.def_id))
         {
             for &def_id in tcx.associated_item_def_ids(item.owner_id.def_id) {
-                // We have diagnosed unused methods in traits
-                if matches!(def_kind, DefKind::Impl { of_trait: true })
-                    && tcx.def_kind(def_id) == DefKind::AssocFn
-                    || def_kind == DefKind::Trait && tcx.def_kind(def_id) != DefKind::AssocFn
-                {
-                    continue;
-                }
-
                 if let Some(local_def_id) = def_id.as_local()
                     && !visitor.is_live_code(local_def_id)
                 {
diff --git a/compiler/rustc_passes/src/input_stats.rs b/compiler/rustc_passes/src/input_stats.rs
index 71815448172..6852153a2e7 100644
--- a/compiler/rustc_passes/src/input_stats.rs
+++ b/compiler/rustc_passes/src/input_stats.rs
@@ -426,10 +426,16 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> {
         hir_visit::walk_fn(self, fk, fd, b, id)
     }
 
-    fn visit_use(&mut self, p: &'v hir::UsePath<'v>, hir_id: HirId) {
+    fn visit_use(&mut self, p: &'v hir::UsePath<'v>, _hir_id: HirId) {
         // This is `visit_use`, but the type is `Path` so record it that way.
         self.record("Path", None, p);
-        hir_visit::walk_use(self, p, hir_id)
+        // Don't call `hir_visit::walk_use(self, p, hir_id)`: it calls
+        // `visit_path` up to three times, once for each namespace result in
+        // `p.res`, by building temporary `Path`s that are not part of the real
+        // HIR, which causes `p` to be double- or triple-counted. Instead just
+        // walk the path internals (i.e. the segments) directly.
+        let hir::Path { span: _, res: _, segments } = *p;
+        ast_visit::walk_list!(self, visit_path_segment, segments);
     }
 
     fn visit_trait_item(&mut self, ti: &'v hir::TraitItem<'v>) {
diff --git a/compiler/rustc_passes/src/stability.rs b/compiler/rustc_passes/src/stability.rs
index 9884386d68f..45e26c8999a 100644
--- a/compiler/rustc_passes/src/stability.rs
+++ b/compiler/rustc_passes/src/stability.rs
@@ -430,7 +430,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
                 kind = AnnotationKind::DeprecationProhibited;
                 const_stab_inherit = InheritConstStability::Yes;
             }
-            hir::ItemKind::Struct(_, ref sd, _) => {
+            hir::ItemKind::Struct(_, _, ref sd) => {
                 if let Some(ctor_def_id) = sd.ctor_def_id() {
                     self.annotate(
                         ctor_def_id,
diff --git a/compiler/rustc_pattern_analysis/src/rustc.rs b/compiler/rustc_pattern_analysis/src/rustc.rs
index d9f1888bfd9..46ced7500ea 100644
--- a/compiler/rustc_pattern_analysis/src/rustc.rs
+++ b/compiler/rustc_pattern_analysis/src/rustc.rs
@@ -249,12 +249,12 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> {
                 ty::Ref(_, rty, _) => reveal_and_alloc(cx, once(*rty)),
                 _ => bug!("Unexpected type for `Ref` constructor: {ty:?}"),
             },
-            Slice(slice) => match *ty.kind() {
-                ty::Slice(ty) | ty::Array(ty, _) => {
+            Slice(slice) => match ty.builtin_index() {
+                Some(ty) => {
                     let arity = slice.arity();
                     reveal_and_alloc(cx, (0..arity).map(|_| ty))
                 }
-                _ => bug!("bad slice pattern {:?} {:?}", ctor, ty),
+                None => bug!("bad slice pattern {:?} {:?}", ctor, ty),
             },
             DerefPattern(pointee_ty) => reveal_and_alloc(cx, once(pointee_ty.inner())),
             Bool(..) | IntRange(..) | F16Range(..) | F32Range(..) | F64Range(..)
diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs
index e2dfaec61b3..963f4c77d80 100644
--- a/compiler/rustc_privacy/src/lib.rs
+++ b/compiler/rustc_privacy/src/lib.rs
@@ -599,8 +599,8 @@ impl<'tcx> EmbargoVisitor<'tcx> {
             DefKind::Struct | DefKind::Union => {
                 // While structs and unions have type privacy, their fields do not.
                 let item = self.tcx.hir_expect_item(def_id);
-                if let hir::ItemKind::Struct(_, ref struct_def, _)
-                | hir::ItemKind::Union(_, ref struct_def, _) = item.kind
+                if let hir::ItemKind::Struct(_, _, ref struct_def)
+                | hir::ItemKind::Union(_, _, ref struct_def) = item.kind
                 {
                     for field in struct_def.fields() {
                         let field_vis = self.tcx.local_visibility(field.def_id);
@@ -725,7 +725,7 @@ impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> {
                     }
                 }
             }
-            hir::ItemKind::Enum(_, ref def, _) => {
+            hir::ItemKind::Enum(_, _, ref def) => {
                 if let Some(item_ev) = item_ev {
                     self.reach(item.owner_id.def_id, item_ev).generics().predicates();
                 }
@@ -763,8 +763,8 @@ impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> {
                     }
                 }
             }
-            hir::ItemKind::Struct(_, ref struct_def, _)
-            | hir::ItemKind::Union(_, ref struct_def, _) => {
+            hir::ItemKind::Struct(_, _, ref struct_def)
+            | hir::ItemKind::Union(_, _, ref struct_def) => {
                 if let Some(item_ev) = item_ev {
                     self.reach(item.owner_id.def_id, item_ev).generics().predicates();
                     for field in struct_def.fields() {
@@ -868,7 +868,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TestReachabilityVisitor<'a, 'tcx> {
         self.effective_visibility_diagnostic(item.owner_id.def_id);
 
         match item.kind {
-            hir::ItemKind::Enum(_, ref def, _) => {
+            hir::ItemKind::Enum(_, _, ref def) => {
                 for variant in def.variants.iter() {
                     self.effective_visibility_diagnostic(variant.def_id);
                     if let Some(ctor_def_id) = variant.data.ctor_def_id() {
@@ -879,7 +879,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TestReachabilityVisitor<'a, 'tcx> {
                     }
                 }
             }
-            hir::ItemKind::Struct(_, ref def, _) | hir::ItemKind::Union(_, ref def, _) => {
+            hir::ItemKind::Struct(_, _, ref def) | hir::ItemKind::Union(_, _, ref def) => {
                 if let Some(ctor_def_id) = def.ctor_def_id() {
                     self.effective_visibility_diagnostic(ctor_def_id);
                 }
@@ -1651,7 +1651,7 @@ impl<'tcx> PrivateItemsInPublicInterfacesChecker<'_, 'tcx> {
             }
             DefKind::Enum => {
                 let item = tcx.hir_item(id);
-                if let hir::ItemKind::Enum(_, ref def, _) = item.kind {
+                if let hir::ItemKind::Enum(_, _, ref def) = item.kind {
                     self.check_unnameable(item.owner_id.def_id, effective_vis);
 
                     self.check(item.owner_id.def_id, item_visibility, effective_vis)
@@ -1689,8 +1689,8 @@ impl<'tcx> PrivateItemsInPublicInterfacesChecker<'_, 'tcx> {
             // Subitems of structs and unions have their own publicity.
             DefKind::Struct | DefKind::Union => {
                 let item = tcx.hir_item(id);
-                if let hir::ItemKind::Struct(_, ref struct_def, _)
-                | hir::ItemKind::Union(_, ref struct_def, _) = item.kind
+                if let hir::ItemKind::Struct(_, _, ref struct_def)
+                | hir::ItemKind::Union(_, _, ref struct_def) = item.kind
                 {
                     self.check_unnameable(item.owner_id.def_id, effective_vis);
                     self.check(item.owner_id.def_id, item_visibility, effective_vis)
diff --git a/compiler/rustc_proc_macro/Cargo.toml b/compiler/rustc_proc_macro/Cargo.toml
new file mode 100644
index 00000000000..4a7c0d78ede
--- /dev/null
+++ b/compiler/rustc_proc_macro/Cargo.toml
@@ -0,0 +1,21 @@
+# We need to use a separate crate including library/proc_macro as opposed to a
+# direct path dependency on library/proc_macro because doing the latter will
+# cause two copies of libproc_macro.rlib to end up in the sysroot, breaking
+# proc-macro crates. In addition it confuses the workspace_members function of
+# bootstrap.
+
+[package]
+name = "rustc_proc_macro"
+version = "0.0.0"
+edition = "2024"
+
+[lib]
+path = "../../library/proc_macro/src/lib.rs"
+test = false
+doctest = false
+
+[dependencies]
+rustc-literal-escaper = "0.0.2"
+
+[features]
+rustc-dep-of-std = []
diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs
index 3460c53782f..c30ed781f35 100644
--- a/compiler/rustc_resolve/src/build_reduced_graph.rs
+++ b/compiler/rustc_resolve/src/build_reduced_graph.rs
@@ -823,7 +823,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
             }
 
             // These items live in both the type and value namespaces.
-            ItemKind::Struct(ident, ref vdata, _) => {
+            ItemKind::Struct(ident, _, ref vdata) => {
                 self.build_reduced_graph_for_struct_variant(
                     vdata.fields(),
                     ident,
@@ -874,7 +874,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
                 }
             }
 
-            ItemKind::Union(ident, ref vdata, _) => {
+            ItemKind::Union(ident, _, ref vdata) => {
                 self.build_reduced_graph_for_struct_variant(
                     vdata.fields(),
                     ident,
diff --git a/compiler/rustc_resolve/src/check_unused.rs b/compiler/rustc_resolve/src/check_unused.rs
index e97233e97ce..9b824572b66 100644
--- a/compiler/rustc_resolve/src/check_unused.rs
+++ b/compiler/rustc_resolve/src/check_unused.rs
@@ -118,9 +118,10 @@ impl<'a, 'ra, 'tcx> UnusedImportCheckVisitor<'a, 'ra, 'tcx> {
             ast::UseTreeKind::Simple(Some(ident)) => {
                 if ident.name == kw::Underscore
                     && !self.r.import_res_map.get(&id).is_some_and(|per_ns| {
-                        per_ns.iter().filter_map(|res| res.as_ref()).any(|res| {
-                            matches!(res, Res::Def(DefKind::Trait | DefKind::TraitAlias, _))
-                        })
+                        matches!(
+                            per_ns.type_ns,
+                            Some(Res::Def(DefKind::Trait | DefKind::TraitAlias, _))
+                        )
                     })
                 {
                     self.unused_import(self.base_id).add(id);
@@ -154,6 +155,7 @@ impl<'a, 'ra, 'tcx> UnusedImportCheckVisitor<'a, 'ra, 'tcx> {
                         extern_crate.id,
                         span,
                         BuiltinLintDiag::UnusedExternCrate {
+                            span: extern_crate.span,
                             removal_span: extern_crate.span_with_attributes,
                         },
                     );
@@ -192,6 +194,16 @@ impl<'a, 'ra, 'tcx> UnusedImportCheckVisitor<'a, 'ra, 'tcx> {
                 continue;
             }
 
+            let module = self
+                .r
+                .get_nearest_non_block_module(self.r.local_def_id(extern_crate.id).to_def_id());
+            if module.no_implicit_prelude {
+                // If the module has `no_implicit_prelude`, then we don't suggest
+                // replacing the extern crate with a use, as it would not be
+                // inserted into the prelude. User writes `extern` style deliberately.
+                continue;
+            }
+
             let vis_span = extern_crate
                 .vis_span
                 .find_ancestor_inside(extern_crate.span)
diff --git a/compiler/rustc_resolve/src/def_collector.rs b/compiler/rustc_resolve/src/def_collector.rs
index 13dfb59f27f..25485be5622 100644
--- a/compiler/rustc_resolve/src/def_collector.rs
+++ b/compiler/rustc_resolve/src/def_collector.rs
@@ -162,8 +162,8 @@ impl<'a, 'ra, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'ra, 'tcx> {
         self.with_parent(def_id, |this| {
             this.with_impl_trait(ImplTraitContext::Existential, |this| {
                 match i.kind {
-                    ItemKind::Struct(_, ref struct_def, _)
-                    | ItemKind::Union(_, ref struct_def, _) => {
+                    ItemKind::Struct(_, _, ref struct_def)
+                    | ItemKind::Union(_, _, ref struct_def) => {
                         // If this is a unit or tuple-like struct, register the constructor.
                         if let Some((ctor_kind, ctor_node_id)) = CtorKind::from_ast(struct_def) {
                             this.create_def(
diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs
index d09750fa281..201b1c0a493 100644
--- a/compiler/rustc_resolve/src/diagnostics.rs
+++ b/compiler/rustc_resolve/src/diagnostics.rs
@@ -6,7 +6,7 @@ use rustc_ast::{
 };
 use rustc_ast_pretty::pprust;
 use rustc_attr_data_structures::{self as attr, Stability};
-use rustc_data_structures::fx::FxHashSet;
+use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_data_structures::unord::UnordSet;
 use rustc_errors::codes::*;
 use rustc_errors::{
@@ -2623,7 +2623,53 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
         };
 
         for &StrippedCfgItem { parent_module, ident, ref cfg } in symbols {
-            if parent_module != module || ident.name != *segment {
+            if ident.name != *segment {
+                continue;
+            }
+
+            fn comes_from_same_module_for_glob(
+                r: &Resolver<'_, '_>,
+                parent_module: DefId,
+                module: DefId,
+                visited: &mut FxHashMap<DefId, bool>,
+            ) -> bool {
+                if let Some(&cached) = visited.get(&parent_module) {
+                    // this branch is prevent from being called recursively infinity,
+                    // because there has some cycles in globs imports,
+                    // see more spec case at `tests/ui/cfg/diagnostics-reexport-2.rs#reexport32`
+                    return cached;
+                }
+                visited.insert(parent_module, false);
+                let res = r.module_map.get(&parent_module).is_some_and(|m| {
+                    for importer in m.glob_importers.borrow().iter() {
+                        if let Some(next_parent_module) = importer.parent_scope.module.opt_def_id()
+                        {
+                            if next_parent_module == module
+                                || comes_from_same_module_for_glob(
+                                    r,
+                                    next_parent_module,
+                                    module,
+                                    visited,
+                                )
+                            {
+                                return true;
+                            }
+                        }
+                    }
+                    false
+                });
+                visited.insert(parent_module, res);
+                res
+            }
+
+            let comes_from_same_module = parent_module == module
+                || comes_from_same_module_for_glob(
+                    self,
+                    parent_module,
+                    module,
+                    &mut Default::default(),
+                );
+            if !comes_from_same_module {
                 continue;
             }
 
diff --git a/compiler/rustc_resolve/src/effective_visibilities.rs b/compiler/rustc_resolve/src/effective_visibilities.rs
index a5ca4565d7b..5de80de3f8d 100644
--- a/compiler/rustc_resolve/src/effective_visibilities.rs
+++ b/compiler/rustc_resolve/src/effective_visibilities.rs
@@ -252,7 +252,7 @@ impl<'a, 'ra, 'tcx> Visitor<'a> for EffectiveVisibilitiesVisitor<'a, 'ra, 'tcx>
                 self.current_private_vis = prev_private_vis;
             }
 
-            ast::ItemKind::Enum(_, EnumDef { ref variants }, _) => {
+            ast::ItemKind::Enum(_, _, EnumDef { ref variants }) => {
                 self.set_bindings_effective_visibilities(def_id);
                 for variant in variants {
                     let variant_def_id = self.r.local_def_id(variant.id);
@@ -262,7 +262,7 @@ impl<'a, 'ra, 'tcx> Visitor<'a> for EffectiveVisibilitiesVisitor<'a, 'ra, 'tcx>
                 }
             }
 
-            ast::ItemKind::Struct(_, ref def, _) | ast::ItemKind::Union(_, ref def, _) => {
+            ast::ItemKind::Struct(_, _, ref def) | ast::ItemKind::Union(_, _, ref def) => {
                 for field in def.fields() {
                     self.update_field(self.r.local_def_id(field.id), def_id);
                 }
diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs
index fd977a8eb6c..2a4be5fc3b1 100644
--- a/compiler/rustc_resolve/src/late.rs
+++ b/compiler/rustc_resolve/src/late.rs
@@ -415,7 +415,7 @@ pub(crate) enum AliasPossibility {
 }
 
 #[derive(Copy, Clone, Debug)]
-pub(crate) enum PathSource<'a> {
+pub(crate) enum PathSource<'a, 'c> {
     /// Type paths `Path`.
     Type,
     /// Trait paths in bounds or impls.
@@ -429,7 +429,10 @@ pub(crate) enum PathSource<'a> {
     /// Paths in tuple struct patterns `Path(..)`.
     TupleStruct(Span, &'a [Span]),
     /// `m::A::B` in `<T as m::A>::B::C`.
-    TraitItem(Namespace),
+    ///
+    /// Second field holds the "cause" of this one, i.e. the context within
+    /// which the trait item is resolved. Used for diagnostics.
+    TraitItem(Namespace, &'c PathSource<'a, 'c>),
     /// Paths in delegation item
     Delegation,
     /// An arg in a `use<'a, N>` precise-capturing bound.
@@ -440,7 +443,7 @@ pub(crate) enum PathSource<'a> {
     DefineOpaques,
 }
 
-impl<'a> PathSource<'a> {
+impl<'a> PathSource<'a, '_> {
     fn namespace(self) -> Namespace {
         match self {
             PathSource::Type
@@ -452,7 +455,7 @@ impl<'a> PathSource<'a> {
             | PathSource::TupleStruct(..)
             | PathSource::Delegation
             | PathSource::ReturnTypeNotation => ValueNS,
-            PathSource::TraitItem(ns) => ns,
+            PathSource::TraitItem(ns, _) => ns,
             PathSource::PreciseCapturingArg(ns) => ns,
         }
     }
@@ -480,8 +483,9 @@ impl<'a> PathSource<'a> {
             PathSource::Trait(_) => "trait",
             PathSource::Pat => "unit struct, unit variant or constant",
             PathSource::Struct => "struct, variant or union type",
-            PathSource::TupleStruct(..) => "tuple struct or tuple variant",
-            PathSource::TraitItem(ns) => match ns {
+            PathSource::TraitItem(ValueNS, PathSource::TupleStruct(..))
+            | PathSource::TupleStruct(..) => "tuple struct or tuple variant",
+            PathSource::TraitItem(ns, _) => match ns {
                 TypeNS => "associated type",
                 ValueNS => "method or associated constant",
                 MacroNS => bug!("associated macro"),
@@ -585,7 +589,7 @@ impl<'a> PathSource<'a> {
                 ) | Res::SelfTyParam { .. }
                     | Res::SelfTyAlias { .. }
             ),
-            PathSource::TraitItem(ns) => match res {
+            PathSource::TraitItem(ns, _) => match res {
                 Res::Def(DefKind::AssocConst | DefKind::AssocFn, _) if ns == ValueNS => true,
                 Res::Def(DefKind::AssocTy, _) if ns == TypeNS => true,
                 _ => false,
@@ -870,7 +874,7 @@ impl<'ra: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'_, 'ast, 'r
                             kind: LifetimeBinderKind::PolyTrait,
                             span,
                         },
-                        |this| this.visit_path(path, ty.id),
+                        |this| this.visit_path(path),
                     );
                 } else {
                     visit::walk_ty(self, ty)
@@ -934,8 +938,7 @@ impl<'ra: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'_, 'ast, 'r
                 )
             }
             TyKind::UnsafeBinder(unsafe_binder) => {
-                // FIXME(unsafe_binder): Better span
-                let span = ty.span;
+                let span = ty.span.shrink_to_lo().to(unsafe_binder.inner_ty.span.shrink_to_lo());
                 self.with_generic_param_rib(
                     &unsafe_binder.generic_params,
                     RibKind::Normal,
@@ -1262,7 +1265,7 @@ impl<'ra: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'_, 'ast, 'r
                             AnonConstKind::ConstArg(IsRepeatExpr::No),
                             |this| {
                                 this.smart_resolve_path(ty.id, &None, path, PathSource::Expr(None));
-                                this.visit_path(path, ty.id);
+                                this.visit_path(path);
                             },
                         );
 
@@ -2008,7 +2011,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
         &mut self,
         partial_res: PartialRes,
         path: &[Segment],
-        source: PathSource<'_>,
+        source: PathSource<'_, '_>,
         path_span: Span,
     ) {
         let proj_start = path.len() - partial_res.unresolved_segments();
@@ -2694,9 +2697,9 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
                 self.resolve_define_opaques(define_opaque);
             }
 
-            ItemKind::Enum(_, _, ref generics)
-            | ItemKind::Struct(_, _, ref generics)
-            | ItemKind::Union(_, _, ref generics) => {
+            ItemKind::Enum(_, ref generics, _)
+            | ItemKind::Struct(_, ref generics, _)
+            | ItemKind::Union(_, ref generics, _) => {
                 self.resolve_adt(item, generics);
             }
 
@@ -3637,7 +3640,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
         if let Some(qself) = &delegation.qself {
             self.visit_ty(&qself.ty);
         }
-        self.visit_path(&delegation.path, delegation.id);
+        self.visit_path(&delegation.path);
         let Some(body) = &delegation.body else { return };
         self.with_rib(ValueNS, RibKind::FnOrCoroutine, |this| {
             let span = delegation.path.segments.last().unwrap().ident.span;
@@ -4207,7 +4210,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
         id: NodeId,
         qself: &Option<P<QSelf>>,
         path: &Path,
-        source: PathSource<'ast>,
+        source: PathSource<'ast, '_>,
     ) {
         self.smart_resolve_path_fragment(
             qself,
@@ -4224,7 +4227,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
         &mut self,
         qself: &Option<P<QSelf>>,
         path: &[Segment],
-        source: PathSource<'ast>,
+        source: PathSource<'ast, '_>,
         finalize: Finalize,
         record_partial_res: RecordPartialRes,
         parent_qself: Option<&QSelf>,
@@ -4405,6 +4408,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
             path_span,
             source.defer_to_typeck(),
             finalize,
+            source,
         ) {
             Ok(Some(partial_res)) if let Some(res) = partial_res.full_res() => {
                 // if we also have an associated type that matches the ident, stash a suggestion
@@ -4527,12 +4531,13 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
         span: Span,
         defer_to_typeck: bool,
         finalize: Finalize,
+        source: PathSource<'ast, '_>,
     ) -> Result<Option<PartialRes>, Spanned<ResolutionError<'ra>>> {
         let mut fin_res = None;
 
         for (i, &ns) in [primary_ns, TypeNS, ValueNS].iter().enumerate() {
             if i == 0 || ns != primary_ns {
-                match self.resolve_qpath(qself, path, ns, finalize)? {
+                match self.resolve_qpath(qself, path, ns, finalize, source)? {
                     Some(partial_res)
                         if partial_res.unresolved_segments() == 0 || defer_to_typeck =>
                     {
@@ -4569,6 +4574,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
         path: &[Segment],
         ns: Namespace,
         finalize: Finalize,
+        source: PathSource<'ast, '_>,
     ) -> Result<Option<PartialRes>, Spanned<ResolutionError<'ra>>> {
         debug!(
             "resolve_qpath(qself={:?}, path={:?}, ns={:?}, finalize={:?})",
@@ -4616,7 +4622,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
             let partial_res = self.smart_resolve_path_fragment(
                 &None,
                 &path[..=qself.position],
-                PathSource::TraitItem(ns),
+                PathSource::TraitItem(ns, &source),
                 Finalize::with_root_span(finalize.node_id, finalize.path_span, qself.path_span),
                 RecordPartialRes::No,
                 Some(&qself),
@@ -4861,7 +4867,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
                 if let Some(qself) = &se.qself {
                     self.visit_ty(&qself.ty);
                 }
-                self.visit_path(&se.path, expr.id);
+                self.visit_path(&se.path);
                 walk_list!(self, resolve_expr_field, &se.fields, expr);
                 match &se.rest {
                     StructRest::Base(expr) => self.visit_expr(expr),
@@ -4892,11 +4898,28 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
                 self.resolve_expr(e, Some(expr));
             }
 
-            ExprKind::Let(ref pat, ref scrutinee, _, _) => {
+            ExprKind::Let(ref pat, ref scrutinee, _, Recovered::No) => {
                 self.visit_expr(scrutinee);
                 self.resolve_pattern_top(pat, PatternSource::Let);
             }
 
+            ExprKind::Let(ref pat, ref scrutinee, _, Recovered::Yes(_)) => {
+                self.visit_expr(scrutinee);
+                // This is basically a tweaked, inlined `resolve_pattern_top`.
+                let mut bindings = smallvec![(PatBoundCtx::Product, Default::default())];
+                self.resolve_pattern(pat, PatternSource::Let, &mut bindings);
+                // We still collect the bindings in this `let` expression which is in
+                // an invalid position (and therefore shouldn't declare variables into
+                // its parent scope). To avoid unnecessary errors though, we do just
+                // reassign the resolutions to `Res::Err`.
+                for (_, bindings) in &mut bindings {
+                    for (_, binding) in bindings {
+                        *binding = Res::Err;
+                    }
+                }
+                self.apply_pattern_bindings(bindings);
+            }
+
             ExprKind::If(ref cond, ref then, ref opt_else) => {
                 self.with_rib(ValueNS, RibKind::Normal, |this| {
                     let old = this.diag_metadata.in_if_condition.replace(cond);
@@ -5243,9 +5266,9 @@ impl<'ast> Visitor<'ast> for ItemInfoCollector<'_, '_, '_> {
             ItemKind::TyAlias(box TyAlias { generics, .. })
             | ItemKind::Const(box ConstItem { generics, .. })
             | ItemKind::Fn(box Fn { generics, .. })
-            | ItemKind::Enum(_, _, generics)
-            | ItemKind::Struct(_, _, generics)
-            | ItemKind::Union(_, _, generics)
+            | ItemKind::Enum(_, generics, _)
+            | ItemKind::Struct(_, generics, _)
+            | ItemKind::Union(_, generics, _)
             | ItemKind::Impl(box Impl { generics, .. })
             | ItemKind::Trait(box Trait { generics, .. })
             | ItemKind::TraitAlias(_, generics, _) => {
diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs
index ca25cdc9563..97a45fcf233 100644
--- a/compiler/rustc_resolve/src/late/diagnostics.rs
+++ b/compiler/rustc_resolve/src/late/diagnostics.rs
@@ -175,7 +175,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
         &mut self,
         path: &[Segment],
         span: Span,
-        source: PathSource<'_>,
+        source: PathSource<'_, '_>,
         res: Option<Res>,
     ) -> BaseError {
         // Make the base error.
@@ -421,7 +421,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
         path: &[Segment],
         following_seg: Option<&Segment>,
         span: Span,
-        source: PathSource<'_>,
+        source: PathSource<'_, '_>,
         res: Option<Res>,
         qself: Option<&QSelf>,
     ) -> (Diag<'tcx>, Vec<ImportSuggestion>) {
@@ -539,12 +539,12 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
         path: &[Segment],
         following_seg: Option<&Segment>,
         span: Span,
-        source: PathSource<'_>,
+        source: PathSource<'_, '_>,
         res: Option<Res>,
         qself: Option<&QSelf>,
     ) {
         if let Some(Res::Def(DefKind::AssocFn, _)) = res
-            && let PathSource::TraitItem(TypeNS) = source
+            && let PathSource::TraitItem(TypeNS, _) = source
             && let None = following_seg
             && let Some(qself) = qself
             && let TyKind::Path(None, ty_path) = &qself.ty.kind
@@ -650,7 +650,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
     fn try_lookup_name_relaxed(
         &mut self,
         err: &mut Diag<'_>,
-        source: PathSource<'_>,
+        source: PathSource<'_, '_>,
         path: &[Segment],
         following_seg: Option<&Segment>,
         span: Span,
@@ -940,7 +940,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
     fn suggest_trait_and_bounds(
         &mut self,
         err: &mut Diag<'_>,
-        source: PathSource<'_>,
+        source: PathSource<'_, '_>,
         res: Option<Res>,
         span: Span,
         base_error: &BaseError,
@@ -1017,7 +1017,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
     fn suggest_typo(
         &mut self,
         err: &mut Diag<'_>,
-        source: PathSource<'_>,
+        source: PathSource<'_, '_>,
         path: &[Segment],
         following_seg: Option<&Segment>,
         span: Span,
@@ -1063,7 +1063,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
     fn suggest_shadowed(
         &mut self,
         err: &mut Diag<'_>,
-        source: PathSource<'_>,
+        source: PathSource<'_, '_>,
         path: &[Segment],
         following_seg: Option<&Segment>,
         span: Span,
@@ -1096,7 +1096,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
     fn err_code_special_cases(
         &mut self,
         err: &mut Diag<'_>,
-        source: PathSource<'_>,
+        source: PathSource<'_, '_>,
         path: &[Segment],
         span: Span,
     ) {
@@ -1141,7 +1141,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
     fn suggest_self_ty(
         &mut self,
         err: &mut Diag<'_>,
-        source: PathSource<'_>,
+        source: PathSource<'_, '_>,
         path: &[Segment],
         span: Span,
     ) -> bool {
@@ -1164,7 +1164,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
     fn suggest_self_value(
         &mut self,
         err: &mut Diag<'_>,
-        source: PathSource<'_>,
+        source: PathSource<'_, '_>,
         path: &[Segment],
         span: Span,
     ) -> bool {
@@ -1332,7 +1332,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
     fn suggest_swapping_misplaced_self_ty_and_trait(
         &mut self,
         err: &mut Diag<'_>,
-        source: PathSource<'_>,
+        source: PathSource<'_, '_>,
         res: Option<Res>,
         span: Span,
     ) {
@@ -1361,7 +1361,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
         &mut self,
         err: &mut Diag<'_>,
         res: Option<Res>,
-        source: PathSource<'_>,
+        source: PathSource<'_, '_>,
     ) {
         let PathSource::TupleStruct(_, _) = source else { return };
         let Some(Res::Def(DefKind::Fn, _)) = res else { return };
@@ -1373,7 +1373,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
         &mut self,
         err: &mut Diag<'_>,
         res: Option<Res>,
-        source: PathSource<'_>,
+        source: PathSource<'_, '_>,
         span: Span,
     ) {
         let PathSource::Trait(_) = source else { return };
@@ -1422,7 +1422,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
     fn suggest_pattern_match_with_let(
         &mut self,
         err: &mut Diag<'_>,
-        source: PathSource<'_>,
+        source: PathSource<'_, '_>,
         span: Span,
     ) -> bool {
         if let PathSource::Expr(_) = source
@@ -1448,10 +1448,10 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
     fn get_single_associated_item(
         &mut self,
         path: &[Segment],
-        source: &PathSource<'_>,
+        source: &PathSource<'_, '_>,
         filter_fn: &impl Fn(Res) -> bool,
     ) -> Option<TypoSuggestion> {
-        if let crate::PathSource::TraitItem(_) = source {
+        if let crate::PathSource::TraitItem(_, _) = source {
             let mod_path = &path[..path.len() - 1];
             if let PathResult::Module(ModuleOrUniformRoot::Module(module)) =
                 self.resolve_path(mod_path, None, None)
@@ -1556,7 +1556,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
 
     /// Check if the source is call expression and the first argument is `self`. If true,
     /// return the span of whole call and the span for all arguments expect the first one (`self`).
-    fn call_has_self_arg(&self, source: PathSource<'_>) -> Option<(Span, Option<Span>)> {
+    fn call_has_self_arg(&self, source: PathSource<'_, '_>) -> Option<(Span, Option<Span>)> {
         let mut has_self_arg = None;
         if let PathSource::Expr(Some(parent)) = source
             && let ExprKind::Call(_, args) = &parent.kind
@@ -1614,7 +1614,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
         &mut self,
         err: &mut Diag<'_>,
         span: Span,
-        source: PathSource<'_>,
+        source: PathSource<'_, '_>,
         path: &[Segment],
         res: Res,
         path_str: &str,
@@ -1666,7 +1666,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
             }
         };
 
-        let find_span = |source: &PathSource<'_>, err: &mut Diag<'_>| {
+        let find_span = |source: &PathSource<'_, '_>, err: &mut Diag<'_>| {
             match source {
                 PathSource::Expr(Some(Expr { span, kind: ExprKind::Call(_, _), .. }))
                 | PathSource::TupleStruct(span, _) => {
@@ -2050,8 +2050,86 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
                 err.span_label(span, fallback_label.to_string());
                 err.note("can't use `Self` as a constructor, you must use the implemented struct");
             }
-            (Res::Def(DefKind::TyAlias | DefKind::AssocTy, _), _) if ns == ValueNS => {
+            (
+                Res::Def(DefKind::TyAlias | DefKind::AssocTy, _),
+                PathSource::TraitItem(ValueNS, PathSource::TupleStruct(whole, args)),
+            ) => {
+                err.note("can't use a type alias as tuple pattern");
+
+                let mut suggestion = Vec::new();
+
+                if let &&[first, ..] = args
+                    && let &&[.., last] = args
+                {
+                    suggestion.extend([
+                        // "0: " has to be included here so that the fix is machine applicable.
+                        //
+                        // If this would only add " { " and then the code below add "0: ",
+                        // rustfix would crash, because end of this suggestion is the same as start
+                        // of the suggestion below. Thus, we have to merge these...
+                        (span.between(first), " { 0: ".to_owned()),
+                        (last.between(whole.shrink_to_hi()), " }".to_owned()),
+                    ]);
+
+                    suggestion.extend(
+                        args.iter()
+                            .enumerate()
+                            .skip(1) // See above
+                            .map(|(index, &arg)| (arg.shrink_to_lo(), format!("{index}: "))),
+                    )
+                } else {
+                    suggestion.push((span.between(whole.shrink_to_hi()), " {}".to_owned()));
+                }
+
+                err.multipart_suggestion(
+                    "use struct pattern instead",
+                    suggestion,
+                    Applicability::MachineApplicable,
+                );
+            }
+            (
+                Res::Def(DefKind::TyAlias | DefKind::AssocTy, _),
+                PathSource::TraitItem(
+                    ValueNS,
+                    PathSource::Expr(Some(ast::Expr {
+                        span: whole,
+                        kind: ast::ExprKind::Call(_, args),
+                        ..
+                    })),
+                ),
+            ) => {
                 err.note("can't use a type alias as a constructor");
+
+                let mut suggestion = Vec::new();
+
+                if let [first, ..] = &**args
+                    && let [.., last] = &**args
+                {
+                    suggestion.extend([
+                        // "0: " has to be included here so that the fix is machine applicable.
+                        //
+                        // If this would only add " { " and then the code below add "0: ",
+                        // rustfix would crash, because end of this suggestion is the same as start
+                        // of the suggestion below. Thus, we have to merge these...
+                        (span.between(first.span), " { 0: ".to_owned()),
+                        (last.span.between(whole.shrink_to_hi()), " }".to_owned()),
+                    ]);
+
+                    suggestion.extend(
+                        args.iter()
+                            .enumerate()
+                            .skip(1) // See above
+                            .map(|(index, arg)| (arg.span.shrink_to_lo(), format!("{index}: "))),
+                    )
+                } else {
+                    suggestion.push((span.between(whole.shrink_to_hi()), " {}".to_owned()));
+                }
+
+                err.multipart_suggestion(
+                    "use struct expression instead",
+                    suggestion,
+                    Applicability::MachineApplicable,
+                );
             }
             _ => return false,
         }
@@ -2621,7 +2699,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
     fn suggest_using_enum_variant(
         &mut self,
         err: &mut Diag<'_>,
-        source: PathSource<'_>,
+        source: PathSource<'_, '_>,
         def_id: DefId,
         span: Span,
     ) {
@@ -2799,7 +2877,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
     pub(crate) fn suggest_adding_generic_parameter(
         &self,
         path: &[Segment],
-        source: PathSource<'_>,
+        source: PathSource<'_, '_>,
     ) -> Option<(Span, &'static str, String, Applicability)> {
         let (ident, span) = match path {
             [segment]
diff --git a/compiler/rustc_resolve/src/rustdoc.rs b/compiler/rustc_resolve/src/rustdoc.rs
index 01bb1324645..fa839d2748d 100644
--- a/compiler/rustc_resolve/src/rustdoc.rs
+++ b/compiler/rustc_resolve/src/rustdoc.rs
@@ -12,10 +12,14 @@ use rustc_data_structures::fx::FxIndexMap;
 use rustc_data_structures::unord::UnordSet;
 use rustc_middle::ty::TyCtxt;
 use rustc_span::def_id::DefId;
+use rustc_span::source_map::SourceMap;
 use rustc_span::{DUMMY_SP, InnerSpan, Span, Symbol, sym};
 use thin_vec::ThinVec;
 use tracing::{debug, trace};
 
+#[cfg(test)]
+mod tests;
+
 #[derive(Clone, Copy, PartialEq, Eq, Debug)]
 pub enum DocFragmentKind {
     /// A doc fragment created from a `///` or `//!` doc comment.
@@ -532,9 +536,19 @@ pub fn source_span_for_markdown_range(
     md_range: &Range<usize>,
     fragments: &[DocFragment],
 ) -> Option<Span> {
+    let map = tcx.sess.source_map();
+    source_span_for_markdown_range_inner(map, markdown, md_range, fragments)
+}
+
+// inner function used for unit testing
+pub fn source_span_for_markdown_range_inner(
+    map: &SourceMap,
+    markdown: &str,
+    md_range: &Range<usize>,
+    fragments: &[DocFragment],
+) -> Option<Span> {
     use rustc_span::BytePos;
 
-    let map = tcx.sess.source_map();
     if let &[fragment] = &fragments
         && fragment.kind == DocFragmentKind::RawDoc
         && let Ok(snippet) = map.span_to_snippet(fragment.span)
@@ -570,7 +584,13 @@ pub fn source_span_for_markdown_range(
             {
                 // If there is either a match in a previous fragment, or
                 // multiple matches in this fragment, there is ambiguity.
-                if match_data.is_none() && !snippet[match_start + 1..].contains(pat) {
+                // the snippet cannot be zero-sized, because it matches
+                // the pattern, which is checked to not be zero sized.
+                if match_data.is_none()
+                    && !snippet.as_bytes()[match_start + 1..]
+                        .windows(pat.len())
+                        .any(|s| s == pat.as_bytes())
+                {
                     match_data = Some((i, match_start));
                 } else {
                     // Heirustic produced ambiguity, return nothing.
diff --git a/compiler/rustc_resolve/src/rustdoc/tests.rs b/compiler/rustc_resolve/src/rustdoc/tests.rs
new file mode 100644
index 00000000000..221ac907e7c
--- /dev/null
+++ b/compiler/rustc_resolve/src/rustdoc/tests.rs
@@ -0,0 +1,50 @@
+use std::path::PathBuf;
+
+use rustc_span::source_map::{FilePathMapping, SourceMap};
+use rustc_span::symbol::sym;
+use rustc_span::{BytePos, Span};
+
+use super::{DocFragment, DocFragmentKind, source_span_for_markdown_range_inner};
+
+#[test]
+fn single_backtick() {
+    let sm = SourceMap::new(FilePathMapping::empty());
+    sm.new_source_file(PathBuf::from("foo.rs").into(), r#"#[doc = "`"] fn foo() {}"#.to_string());
+    let span = source_span_for_markdown_range_inner(
+        &sm,
+        "`",
+        &(0..1),
+        &[DocFragment {
+            span: Span::with_root_ctxt(BytePos(8), BytePos(11)),
+            item_id: None,
+            kind: DocFragmentKind::RawDoc,
+            doc: sym::empty, // unused placeholder
+            indent: 0,
+        }],
+    )
+    .unwrap();
+    assert_eq!(span.lo(), BytePos(9));
+    assert_eq!(span.hi(), BytePos(10));
+}
+
+#[test]
+fn utf8() {
+    // regression test for https://github.com/rust-lang/rust/issues/141665
+    let sm = SourceMap::new(FilePathMapping::empty());
+    sm.new_source_file(PathBuf::from("foo.rs").into(), r#"#[doc = "⚠"] fn foo() {}"#.to_string());
+    let span = source_span_for_markdown_range_inner(
+        &sm,
+        "⚠",
+        &(0..3),
+        &[DocFragment {
+            span: Span::with_root_ctxt(BytePos(8), BytePos(14)),
+            item_id: None,
+            kind: DocFragmentKind::RawDoc,
+            doc: sym::empty, // unused placeholder
+            indent: 0,
+        }],
+    )
+    .unwrap();
+    assert_eq!(span.lo(), BytePos(9));
+    assert_eq!(span.hi(), BytePos(12));
+}
diff --git a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs
index 47831f2f418..9d1d3412f8d 100644
--- a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs
+++ b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs
@@ -79,7 +79,7 @@ fn encode_args<'tcx>(
         s.push('I');
         let def_generics = tcx.generics_of(for_def);
         for (n, arg) in args.iter().enumerate() {
-            match arg.unpack() {
+            match arg.kind() {
                 GenericArgKind::Lifetime(region) => {
                     s.push_str(&encode_region(region, dict));
                 }
@@ -245,7 +245,7 @@ fn encode_predicate<'tcx>(
             let name = encode_ty_name(tcx, projection.def_id);
             let _ = write!(s, "u{}{}", name.len(), name);
             s.push_str(&encode_args(tcx, projection.args, projection.def_id, true, dict, options));
-            match projection.term.unpack() {
+            match projection.term.kind() {
                 TermKind::Ty(ty) => s.push_str(&encode_ty(tcx, ty, dict, options)),
                 TermKind::Const(c) => s.push_str(&encode_const(
                     tcx,
diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs
index 144aeb5c369..60e1b465ba9 100644
--- a/compiler/rustc_session/src/config.rs
+++ b/compiler/rustc_session/src/config.rs
@@ -195,11 +195,6 @@ pub struct CoverageOptions {
     /// regression tests for #133606, because we don't have an easy way to
     /// reproduce it from actual source code.
     pub discard_all_spans_in_codegen: bool,
-
-    /// `-Zcoverage-options=inject-unused-local-file`: During codegen, add an
-    /// extra dummy entry to each function's local file table, to exercise the
-    /// code that checks for local file IDs with no mapping regions.
-    pub inject_unused_local_file: bool,
 }
 
 /// Controls whether branch coverage or MC/DC coverage is enabled.
diff --git a/compiler/rustc_session/src/filesearch.rs b/compiler/rustc_session/src/filesearch.rs
index 92f1bd8ab73..0e711890e07 100644
--- a/compiler/rustc_session/src/filesearch.rs
+++ b/compiler/rustc_session/src/filesearch.rs
@@ -172,6 +172,11 @@ fn current_dll_path() -> Result<PathBuf, String> {
     Ok(OsString::from_wide(&filename).into())
 }
 
+#[cfg(target_os = "wasi")]
+fn current_dll_path() -> Result<PathBuf, String> {
+    Err("current_dll_path is not supported on WASI".to_string())
+}
+
 pub fn sysroot_candidates() -> SmallVec<[PathBuf; 2]> {
     let target = crate::config::host_tuple();
     let mut sysroot_candidates: SmallVec<[PathBuf; 2]> = smallvec![get_or_default_sysroot()];
diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs
index 3d9fdcbc7b1..12fa05118ca 100644
--- a/compiler/rustc_session/src/options.rs
+++ b/compiler/rustc_session/src/options.rs
@@ -1413,7 +1413,6 @@ pub mod parse {
                 "mcdc" => slot.level = CoverageLevel::Mcdc,
                 "no-mir-spans" => slot.no_mir_spans = true,
                 "discard-all-spans-in-codegen" => slot.discard_all_spans_in_codegen = true,
-                "inject-unused-local-file" => slot.inject_unused_local_file = true,
                 _ => return false,
             }
         }
@@ -2367,6 +2366,8 @@ options! {
         "run LLVM in non-parallel mode (while keeping codegen-units and ThinLTO)"),
     no_profiler_runtime: bool = (false, parse_no_value, [TRACKED],
         "prevent automatic injection of the profiler_builtins crate"),
+    no_steal_thir: bool = (false, parse_bool, [UNTRACKED],
+        "don't steal the THIR when we're done with it; useful for rustc drivers (default: no)"),
     no_trait_vptr: bool = (false, parse_no_value, [TRACKED],
         "disable generation of trait vptr in vtable for upcasting"),
     no_unique_section_names: bool = (false, parse_bool, [TRACKED],
diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs
index 34ac37d6378..010ae42c280 100644
--- a/compiler/rustc_session/src/session.rs
+++ b/compiler/rustc_session/src/session.rs
@@ -371,11 +371,6 @@ impl Session {
         self.opts.unstable_opts.coverage_options.discard_all_spans_in_codegen
     }
 
-    /// True if testing flag `-Zcoverage-options=inject-unused-local-file` was passed.
-    pub fn coverage_inject_unused_local_file(&self) -> bool {
-        self.opts.unstable_opts.coverage_options.inject_unused_local_file
-    }
-
     pub fn is_sanitizer_cfi_enabled(&self) -> bool {
         self.opts.unstable_opts.sanitizer.contains(SanitizerSet::CFI)
     }
diff --git a/compiler/rustc_smir/src/rustc_smir/alloc.rs b/compiler/rustc_smir/src/rustc_smir/alloc.rs
index 9cb89634c52..a6d31ac4e13 100644
--- a/compiler/rustc_smir/src/rustc_smir/alloc.rs
+++ b/compiler/rustc_smir/src/rustc_smir/alloc.rs
@@ -48,6 +48,7 @@ pub(crate) fn try_new_allocation<'tcx>(
                 size,
                 layout.align.abi,
                 AllocInit::Uninit,
+                (),
             );
             allocation
                 .write_scalar(&tables.tcx, alloc_range(Size::ZERO, size), scalar)
@@ -65,6 +66,7 @@ pub(crate) fn try_new_allocation<'tcx>(
                 layout.size,
                 layout.align.abi,
                 AllocInit::Uninit,
+                (),
             );
             allocation
                 .write_scalar(
diff --git a/compiler/rustc_smir/src/rustc_smir/convert/ty.rs b/compiler/rustc_smir/src/rustc_smir/convert/ty.rs
index 8bcac4c4678..b0c9dba78a6 100644
--- a/compiler/rustc_smir/src/rustc_smir/convert/ty.rs
+++ b/compiler/rustc_smir/src/rustc_smir/convert/ty.rs
@@ -100,7 +100,7 @@ impl<'tcx> Stable<'tcx> for ty::ExistentialProjection<'tcx> {
         stable_mir::ty::ExistentialProjection {
             def_id: tables.trait_def(*def_id),
             generic_args: args.stable(tables),
-            term: term.unpack().stable(tables),
+            term: term.kind().stable(tables),
         }
     }
 }
@@ -158,7 +158,7 @@ impl<'tcx> Stable<'tcx> for ty::FieldDef {
 impl<'tcx> Stable<'tcx> for ty::GenericArgs<'tcx> {
     type T = stable_mir::ty::GenericArgs;
     fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
-        GenericArgs(self.iter().map(|arg| arg.unpack().stable(tables)).collect())
+        GenericArgs(self.iter().map(|arg| arg.kind().stable(tables)).collect())
     }
 }
 
@@ -604,8 +604,8 @@ impl<'tcx> Stable<'tcx> for ty::PredicateKind<'tcx> {
             PredicateKind::NormalizesTo(_pred) => unimplemented!(),
             PredicateKind::AliasRelate(a, b, alias_relation_direction) => {
                 stable_mir::ty::PredicateKind::AliasRelate(
-                    a.unpack().stable(tables),
-                    b.unpack().stable(tables),
+                    a.kind().stable(tables),
+                    b.kind().stable(tables),
                     alias_relation_direction.stable(tables),
                 )
             }
@@ -640,7 +640,7 @@ impl<'tcx> Stable<'tcx> for ty::ClauseKind<'tcx> {
                 ty.stable(tables),
             ),
             ClauseKind::WellFormed(term) => {
-                stable_mir::ty::ClauseKind::WellFormed(term.unpack().stable(tables))
+                stable_mir::ty::ClauseKind::WellFormed(term.kind().stable(tables))
             }
             ClauseKind::ConstEvaluatable(const_) => {
                 stable_mir::ty::ClauseKind::ConstEvaluatable(const_.stable(tables))
@@ -726,7 +726,7 @@ impl<'tcx> Stable<'tcx> for ty::ProjectionPredicate<'tcx> {
         let ty::ProjectionPredicate { projection_term, term } = self;
         stable_mir::ty::ProjectionPredicate {
             projection_term: projection_term.stable(tables),
-            term: term.unpack().stable(tables),
+            term: term.kind().stable(tables),
         }
     }
 }
diff --git a/compiler/rustc_span/src/analyze_source_file.rs b/compiler/rustc_span/src/analyze_source_file.rs
index c32593a6d95..55d899c9ada 100644
--- a/compiler/rustc_span/src/analyze_source_file.rs
+++ b/compiler/rustc_span/src/analyze_source_file.rs
@@ -29,7 +29,18 @@ pub(crate) fn analyze_source_file(src: &str) -> (Vec<RelativeBytePos>, Vec<Multi
     (lines, multi_byte_chars)
 }
 
-cfg_select! {
+// cfg(bootstrap)
+macro_rules! cfg_select_dispatch {
+    ($($tokens:tt)*) => {
+        #[cfg(bootstrap)]
+        cfg_match! { $($tokens)* }
+
+        #[cfg(not(bootstrap))]
+        cfg_select! { $($tokens)* }
+    };
+}
+
+cfg_select_dispatch! {
     any(target_arch = "x86", target_arch = "x86_64") => {
         fn analyze_source_file_dispatch(
             src: &str,
diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs
index 906462a0d22..e950493f135 100644
--- a/compiler/rustc_span/src/lib.rs
+++ b/compiler/rustc_span/src/lib.rs
@@ -17,10 +17,11 @@
 
 // tidy-alphabetical-start
 #![allow(internal_features)]
+#![cfg_attr(bootstrap, feature(cfg_match))]
+#![cfg_attr(not(bootstrap), feature(cfg_select))]
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
 #![doc(rust_logo)]
 #![feature(array_windows)]
-#![feature(cfg_select)]
 #![feature(core_io_borrowed_buf)]
 #![feature(hash_set_entry)]
 #![feature(if_let_guard)]
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 6b10d2728b2..4e842a8f93a 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -244,6 +244,7 @@ symbols! {
         FnMut,
         FnOnce,
         Formatter,
+        Forward,
         From,
         FromIterator,
         FromResidual,
@@ -339,6 +340,7 @@ symbols! {
         Result,
         ResumeTy,
         Return,
+        Reverse,
         Right,
         Rust,
         RustaceansAreAwesome,
@@ -465,6 +467,7 @@ symbols! {
         as_ref,
         as_str,
         asm,
+        asm_cfg,
         asm_const,
         asm_experimental_arch,
         asm_experimental_reg,
@@ -512,6 +515,7 @@ symbols! {
         async_iterator_poll_next,
         async_trait_bounds,
         atomic,
+        atomic_load,
         atomic_mod,
         atomics,
         att_syntax,
@@ -521,7 +525,8 @@ symbols! {
         audit_that,
         augmented_assignments,
         auto_traits,
-        autodiff,
+        autodiff_forward,
+        autodiff_reverse,
         automatically_derived,
         avx,
         avx10_target_feature,
@@ -932,8 +937,10 @@ symbols! {
         external_doc,
         f,
         f128,
+        f128_epsilon,
         f128_nan,
         f16,
+        f16_epsilon,
         f16_nan,
         f16c_target_feature,
         f32,
@@ -1995,6 +2002,7 @@ symbols! {
         slice,
         slice_from_raw_parts,
         slice_from_raw_parts_mut,
+        slice_get_unchecked,
         slice_into_vec,
         slice_iter,
         slice_len_fn,
@@ -2070,6 +2078,9 @@ symbols! {
         sym,
         sync,
         synthetic,
+        sys_mutex_lock,
+        sys_mutex_try_lock,
+        sys_mutex_unlock,
         t32,
         target,
         target_abi,
diff --git a/compiler/rustc_symbol_mangling/src/export.rs b/compiler/rustc_symbol_mangling/src/export.rs
index 770401fc8cf..956c996326b 100644
--- a/compiler/rustc_symbol_mangling/src/export.rs
+++ b/compiler/rustc_symbol_mangling/src/export.rs
@@ -147,7 +147,7 @@ impl<'tcx> AbiHashStable<'tcx> for ty::FnSig<'tcx> {
 
 impl<'tcx> AbiHashStable<'tcx> for ty::GenericArg<'tcx> {
     fn abi_hash(&self, tcx: TyCtxt<'tcx>, hasher: &mut StableHasher) {
-        self.unpack().abi_hash(tcx, hasher);
+        self.kind().abi_hash(tcx, hasher);
     }
 }
 
diff --git a/compiler/rustc_symbol_mangling/src/legacy.rs b/compiler/rustc_symbol_mangling/src/legacy.rs
index db102abda7f..12d1de46313 100644
--- a/compiler/rustc_symbol_mangling/src/legacy.rs
+++ b/compiler/rustc_symbol_mangling/src/legacy.rs
@@ -386,7 +386,7 @@ impl<'tcx> Printer<'tcx> for SymbolPrinter<'tcx> {
         print_prefix(self)?;
 
         let args =
-            args.iter().cloned().filter(|arg| !matches!(arg.unpack(), GenericArgKind::Lifetime(_)));
+            args.iter().cloned().filter(|arg| !matches!(arg.kind(), GenericArgKind::Lifetime(_)));
 
         if args.clone().next().is_some() {
             self.generic_delimiters(|cx| cx.comma_sep(args))
diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs
index 644031af859..49a5e20d7cf 100644
--- a/compiler/rustc_symbol_mangling/src/v0.rs
+++ b/compiler/rustc_symbol_mangling/src/v0.rs
@@ -646,7 +646,7 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> {
                         let name = cx.tcx.associated_item(projection.def_id).name();
                         cx.push("p");
                         cx.push_ident(name.as_str());
-                        match projection.term.unpack() {
+                        match projection.term.kind() {
                             ty::TermKind::Ty(ty) => ty.print(cx),
                             ty::TermKind::Const(c) => c.print(cx),
                         }?;
@@ -912,11 +912,11 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> {
         args: &[GenericArg<'tcx>],
     ) -> Result<(), PrintError> {
         // Don't print any regions if they're all erased.
-        let print_regions = args.iter().any(|arg| match arg.unpack() {
+        let print_regions = args.iter().any(|arg| match arg.kind() {
             GenericArgKind::Lifetime(r) => !r.is_erased(),
             _ => false,
         });
-        let args = args.iter().cloned().filter(|arg| match arg.unpack() {
+        let args = args.iter().cloned().filter(|arg| match arg.kind() {
             GenericArgKind::Lifetime(_) => print_regions,
             _ => true,
         });
@@ -928,7 +928,7 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> {
         self.push("I");
         print_prefix(self)?;
         for arg in args {
-            match arg.unpack() {
+            match arg.kind() {
                 GenericArgKind::Lifetime(lt) => {
                     lt.print(self)?;
                 }
diff --git a/compiler/rustc_target/src/spec/base/cygwin.rs b/compiler/rustc_target/src/spec/base/cygwin.rs
index 819d1d68a71..d6ae0a905bf 100644
--- a/compiler/rustc_target/src/spec/base/cygwin.rs
+++ b/compiler/rustc_target/src/spec/base/cygwin.rs
@@ -1,7 +1,8 @@
 use std::borrow::Cow;
 
 use crate::spec::{
-    BinaryFormat, Cc, DebuginfoKind, LinkerFlavor, Lld, SplitDebuginfo, TargetOptions, cvs,
+    BinaryFormat, Cc, DebuginfoKind, LinkerFlavor, Lld, SplitDebuginfo, TargetOptions, TlsModel,
+    cvs,
 };
 
 pub(crate) fn opts() -> TargetOptions {
@@ -44,6 +45,8 @@ pub(crate) fn opts() -> TargetOptions {
         eh_frame_header: false,
         debuginfo_kind: DebuginfoKind::Dwarf,
         supported_split_debuginfo: Cow::Borrowed(&[SplitDebuginfo::Off]),
+        tls_model: TlsModel::Emulated,
+        has_thread_local: true,
         ..Default::default()
     }
 }
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_darwin.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_darwin.rs
index d3e0a32c8b8..6587abb2ba7 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_apple_darwin.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_darwin.rs
@@ -22,6 +22,7 @@ pub(crate) fn target() -> Target {
             max_atomic_width: Some(128),
             // FIXME: The leak sanitizer currently fails the tests, see #88132.
             supported_sanitizers: SanitizerSet::ADDRESS | SanitizerSet::CFI | SanitizerSet::THREAD,
+            supports_xray: true,
             ..opts
         },
     }
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_pc_windows_gnullvm.rs b/compiler/rustc_target/src/spec/targets/aarch64_pc_windows_gnullvm.rs
index a8b133d19bb..eee668cc67e 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_pc_windows_gnullvm.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_pc_windows_gnullvm.rs
@@ -1,4 +1,4 @@
-use crate::spec::{Target, TargetMetadata, base};
+use crate::spec::{FramePointer, Target, TargetMetadata, base};
 
 pub(crate) fn target() -> Target {
     let mut base = base::windows_gnullvm::opts();
@@ -6,6 +6,12 @@ pub(crate) fn target() -> Target {
     base.features = "+v8a,+neon,+fp-armv8".into();
     base.linker = Some("aarch64-w64-mingw32-clang".into());
 
+    // Microsoft recommends enabling frame pointers on Arm64 Windows.
+    // From https://learn.microsoft.com/en-us/cpp/build/arm64-windows-abi-conventions?view=msvc-170#integer-registers
+    // "The frame pointer (x29) is required for compatibility with fast stack walking used by ETW
+    // and other services. It must point to the previous {x29, x30} pair on the stack."
+    base.frame_pointer = FramePointer::NonLeaf;
+
     Target {
         llvm_target: "aarch64-pc-windows-gnu".into(),
         metadata: TargetMetadata {
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_apple_darwin.rs b/compiler/rustc_target/src/spec/targets/x86_64_apple_darwin.rs
index 2f868e38f1a..64c17054780 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_apple_darwin.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_apple_darwin.rs
@@ -23,6 +23,7 @@ pub(crate) fn target() -> Target {
                 | SanitizerSet::CFI
                 | SanitizerSet::LEAK
                 | SanitizerSet::THREAD,
+            supports_xray: true,
             ..opts
         },
     }
diff --git a/compiler/rustc_trait_selection/messages.ftl b/compiler/rustc_trait_selection/messages.ftl
index 9b949a0a795..8232da4df43 100644
--- a/compiler/rustc_trait_selection/messages.ftl
+++ b/compiler/rustc_trait_selection/messages.ftl
@@ -72,8 +72,6 @@ trait_selection_adjust_signature_remove_borrow = consider adjusting the signatur
 
 trait_selection_ascribe_user_type_prove_predicate = ...so that the where clause holds
 
-trait_selection_async_closure_not_fn = async closure does not implement `{$kind}` because it captures state from its environment
-
 trait_selection_await_both_futures = consider `await`ing on both `Future`s
 trait_selection_await_future = consider `await`ing on the `Future`
 trait_selection_await_note = calling an async function returns a future
@@ -123,6 +121,8 @@ trait_selection_closure_kind_requirement = the requirement to implement `{$trait
 
 trait_selection_compare_impl_item_obligation = ...so that the definition in impl matches the definition from the trait
 trait_selection_consider_specifying_length = consider specifying the actual array length
+trait_selection_coro_closure_not_fn = {$coro_kind}closure does not implement `{$kind}` because it captures state from its environment
+
 trait_selection_data_flows = ...but data{$label_var1_exists ->
     [true] {" "}from `{$label_var1}`
     *[false] {""}
diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs
index fdd547448f0..8e2137da655 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs
@@ -738,7 +738,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                 value.push_normal(", ");
             }
 
-            match arg.unpack() {
+            match arg.kind() {
                 ty::GenericArgKind::Lifetime(lt) => {
                     let s = lt.to_string();
                     value.push_normal(if s.is_empty() { "'_" } else { &s });
@@ -1166,7 +1166,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
 
                     for (i, (arg1, arg2)) in sub1.iter().zip(sub2).enumerate().take(len) {
                         self.push_comma(&mut values.0, &mut values.1, i);
-                        match arg1.unpack() {
+                        match arg1.kind() {
                             // At one point we'd like to elide all lifetimes here, they are
                             // irrelevant for all diagnostics that use this output.
                             //
@@ -1509,7 +1509,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                 }
                 let (is_simple_error, exp_found) = match values {
                     ValuePairs::Terms(ExpectedFound { expected, found }) => {
-                        match (expected.unpack(), found.unpack()) {
+                        match (expected.kind(), found.kind()) {
                             (ty::TermKind::Ty(expected), ty::TermKind::Ty(found)) => {
                                 let is_simple_err =
                                     expected.is_simple_text() && found.is_simple_text();
@@ -2026,7 +2026,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                 }
                 LetVisitor { span }.visit_body(body).break_value()
             }
-            hir::Node::Item(hir::Item { kind: hir::ItemKind::Const(_, ty, _, _), .. }) => {
+            hir::Node::Item(hir::Item { kind: hir::ItemKind::Const(_, _, ty, _), .. }) => {
                 Some(&ty.peel_refs().kind)
             }
             _ => None,
@@ -2156,7 +2156,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
             return None;
         }
 
-        Some(match (exp_found.expected.unpack(), exp_found.found.unpack()) {
+        Some(match (exp_found.expected.kind(), exp_found.found.kind()) {
             (ty::TermKind::Ty(expected), ty::TermKind::Ty(found)) => {
                 let (mut exp, mut fnd) = self.cmp(expected, found);
                 // Use the terminal width as the basis to determine when to compress the printed
diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs
index cb1c9c75369..bfef3340b32 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs
@@ -215,7 +215,7 @@ impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for ClosureEraser<'a, 'tcx> {
                                 // `_` because then we'd end up with `Vec<_, _>`, instead of
                                 // `Vec<_>`.
                                 arg
-                            } else if let GenericArgKind::Type(_) = arg.unpack() {
+                            } else if let GenericArgKind::Type(_) = arg.kind() {
                                 // We don't replace lifetime or const params, only type params.
                                 self.new_infer().into()
                             } else {
@@ -347,7 +347,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
         highlight: ty::print::RegionHighlightMode<'tcx>,
     ) -> InferenceDiagnosticsData {
         let tcx = self.tcx;
-        match term.unpack() {
+        match term.kind() {
             TermKind::Ty(ty) => {
                 if let ty::Infer(ty::TyVar(ty_vid)) = *ty.kind() {
                     let var_origin = self.infcx.type_var_origin(ty_vid);
@@ -568,7 +568,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                                 return arg;
                             }
 
-                            match arg.unpack() {
+                            match arg.kind() {
                                 GenericArgKind::Lifetime(_) => bug!("unexpected lifetime"),
                                 GenericArgKind::Type(_) => self.next_ty_var(DUMMY_SP).into(),
                                 GenericArgKind::Const(_) => self.next_const_var(DUMMY_SP).into(),
@@ -803,7 +803,7 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> {
         }
         impl<'tcx> CostCtxt<'tcx> {
             fn arg_cost(self, arg: GenericArg<'tcx>) -> usize {
-                match arg.unpack() {
+                match arg.kind() {
                     GenericArgKind::Lifetime(_) => 0, // erased
                     GenericArgKind::Type(ty) => self.ty_cost(ty),
                     GenericArgKind::Const(_) => 3, // some non-zero value
@@ -898,7 +898,7 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> {
             return true;
         }
 
-        match (arg.unpack(), self.target.unpack()) {
+        match (arg.kind(), self.target.kind()) {
             (GenericArgKind::Type(inner_ty), TermKind::Ty(target_ty)) => {
                 use ty::{Infer, TyVar};
                 match (inner_ty.kind(), target_ty.kind()) {
@@ -929,7 +929,7 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> {
             if self.generic_arg_is_target(inner) {
                 return true;
             }
-            match inner.unpack() {
+            match inner.kind() {
                 GenericArgKind::Lifetime(_) => {}
                 GenericArgKind::Type(ty) => {
                     if matches!(
diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/suggest.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/suggest.rs
index cdbb92f4c7b..3804c13acce 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/infer/suggest.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/infer/suggest.rs
@@ -664,8 +664,8 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
         let Some(found) = exp_found.found.args.get(1) else {
             return;
         };
-        let expected = expected.unpack();
-        let found = found.unpack();
+        let expected = expected.kind();
+        let found = found.kind();
         // 3. Extract the tuple type from Fn trait and suggest the change.
         if let GenericArgKind::Type(expected) = expected
             && let GenericArgKind::Type(found) = found
diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs
index b88040a0f98..fc5be111144 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs
@@ -42,9 +42,7 @@ use super::{
 use crate::error_reporting::TypeErrCtxt;
 use crate::error_reporting::infer::TyCategory;
 use crate::error_reporting::traits::report_dyn_incompatibility;
-use crate::errors::{
-    AsyncClosureNotFn, ClosureFnMutLabel, ClosureFnOnceLabel, ClosureKindMismatch,
-};
+use crate::errors::{ClosureFnMutLabel, ClosureFnOnceLabel, ClosureKindMismatch, CoroClosureNotFn};
 use crate::infer::{self, InferCtxt, InferCtxtExt as _};
 use crate::traits::query::evaluate_obligation::InferCtxtExt as _;
 use crate::traits::{
@@ -886,9 +884,18 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
         // is unimplemented is because async closures don't implement `Fn`/`FnMut`
         // if they have captures.
         if has_self_borrows && expected_kind != ty::ClosureKind::FnOnce {
-            let mut err = self.dcx().create_err(AsyncClosureNotFn {
+            let coro_kind = match self
+                .tcx
+                .coroutine_kind(self.tcx.coroutine_for_closure(closure_def_id))
+                .unwrap()
+            {
+                rustc_hir::CoroutineKind::Desugared(desugaring, _) => desugaring.to_string(),
+                coro => coro.to_string(),
+            };
+            let mut err = self.dcx().create_err(CoroClosureNotFn {
                 span: self.tcx.def_span(closure_def_id),
                 kind: expected_kind.as_str(),
+                coro_kind,
             });
             self.note_obligation_cause(&mut err, &obligation);
             return Some(err.emit());
@@ -2446,7 +2453,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
             }
             if let ty::Adt(def, args) = self_ty.kind()
                 && let [arg] = &args[..]
-                && let ty::GenericArgKind::Type(ty) = arg.unpack()
+                && let ty::GenericArgKind::Type(ty) = arg.kind()
                 && let ty::Adt(inner_def, _) = ty.kind()
                 && inner_def == def
             {
diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs
index 6863857f9ec..c4f1f7d712a 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs
@@ -351,14 +351,14 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
 
                 hir::Node::Item(hir::Item {
                     kind:
-                        hir::ItemKind::Struct(_, _, generics)
-                        | hir::ItemKind::Enum(_, _, generics)
-                        | hir::ItemKind::Union(_, _, generics)
+                        hir::ItemKind::Struct(_, generics, _)
+                        | hir::ItemKind::Enum(_, generics, _)
+                        | hir::ItemKind::Union(_, generics, _)
                         | hir::ItemKind::Trait(_, _, _, generics, ..)
                         | hir::ItemKind::Impl(hir::Impl { generics, .. })
                         | hir::ItemKind::Fn { generics, .. }
-                        | hir::ItemKind::TyAlias(_, _, generics)
-                        | hir::ItemKind::Const(_, _, generics, _)
+                        | hir::ItemKind::TyAlias(_, generics, _)
+                        | hir::ItemKind::Const(_, generics, _, _)
                         | hir::ItemKind::TraitAlias(_, generics, _),
                     ..
                 })
@@ -411,14 +411,14 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
 
                 hir::Node::Item(hir::Item {
                     kind:
-                        hir::ItemKind::Struct(_, _, generics)
-                        | hir::ItemKind::Enum(_, _, generics)
-                        | hir::ItemKind::Union(_, _, generics)
+                        hir::ItemKind::Struct(_, generics, _)
+                        | hir::ItemKind::Enum(_, generics, _)
+                        | hir::ItemKind::Union(_, generics, _)
                         | hir::ItemKind::Trait(_, _, _, generics, ..)
                         | hir::ItemKind::Impl(hir::Impl { generics, .. })
                         | hir::ItemKind::Fn { generics, .. }
-                        | hir::ItemKind::TyAlias(_, _, generics)
-                        | hir::ItemKind::Const(_, _, generics, _)
+                        | hir::ItemKind::TyAlias(_, generics, _)
+                        | hir::ItemKind::Const(_, generics, _, _)
                         | hir::ItemKind::TraitAlias(_, generics, _),
                     ..
                 }) if !param_ty => {
diff --git a/compiler/rustc_trait_selection/src/errors.rs b/compiler/rustc_trait_selection/src/errors.rs
index 779c861637a..0bea308ed5c 100644
--- a/compiler/rustc_trait_selection/src/errors.rs
+++ b/compiler/rustc_trait_selection/src/errors.rs
@@ -201,11 +201,12 @@ pub struct ClosureFnMutLabel {
 }
 
 #[derive(Diagnostic)]
-#[diag(trait_selection_async_closure_not_fn)]
-pub(crate) struct AsyncClosureNotFn {
+#[diag(trait_selection_coro_closure_not_fn)]
+pub(crate) struct CoroClosureNotFn {
     #[primary_span]
     pub span: Span,
     pub kind: &'static str,
+    pub coro_kind: String,
 }
 
 #[derive(Diagnostic)]
diff --git a/compiler/rustc_trait_selection/src/opaque_types.rs b/compiler/rustc_trait_selection/src/opaque_types.rs
index 332204a0c5f..d5bde9192d5 100644
--- a/compiler/rustc_trait_selection/src/opaque_types.rs
+++ b/compiler/rustc_trait_selection/src/opaque_types.rs
@@ -81,7 +81,7 @@ pub fn check_opaque_type_parameter_valid<'tcx>(
     }
 
     for (i, arg) in opaque_type_key.iter_captured_args(tcx) {
-        let arg_is_param = match arg.unpack() {
+        let arg_is_param = match arg.kind() {
             GenericArgKind::Lifetime(lt) => match defining_scope_kind {
                 DefiningScopeKind::HirTypeck => continue,
                 DefiningScopeKind::MirBorrowck => {
diff --git a/compiler/rustc_trait_selection/src/solve/delegate.rs b/compiler/rustc_trait_selection/src/solve/delegate.rs
index b68a7845366..e92e37b8738 100644
--- a/compiler/rustc_trait_selection/src/solve/delegate.rs
+++ b/compiler/rustc_trait_selection/src/solve/delegate.rs
@@ -11,8 +11,9 @@ use rustc_infer::infer::{InferCtxt, RegionVariableOrigin, SubregionOrigin, TyCtx
 use rustc_infer::traits::solve::Goal;
 use rustc_middle::traits::query::NoSolution;
 use rustc_middle::traits::solve::Certainty;
-use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable, TypeVisitableExt as _, TypingMode};
-use rustc_next_trait_solver::solve::HasChanged;
+use rustc_middle::ty::{
+    self, Ty, TyCtxt, TypeFlags, TypeFoldable, TypeVisitableExt as _, TypingMode,
+};
 use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span};
 
 use crate::traits::{EvaluateConstErr, ObligationCause, specialization_graph};
@@ -61,11 +62,41 @@ impl<'tcx> rustc_next_trait_solver::delegate::SolverDelegate for SolverDelegate<
         &self,
         goal: Goal<'tcx, ty::Predicate<'tcx>>,
         span: Span,
-    ) -> Option<HasChanged> {
+    ) -> Option<Certainty> {
+        if let Some(trait_pred) = goal.predicate.as_trait_clause() {
+            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())
+                            .is_trivially_sized(self.0.tcx) =>
+                    {
+                        return Some(Certainty::Yes);
+                    }
+                    Some(LangItem::Copy | LangItem::Clone) => {
+                        let self_ty =
+                            self.resolve_vars_if_possible(trait_pred.self_ty().skip_binder());
+                        // Unlike `Sized` traits, which always prefer the built-in impl,
+                        // `Copy`/`Clone` may be shadowed by a param-env candidate which
+                        // could force a lifetime error or guide inference. While that's
+                        // not generally desirable, it is observable, so for now let's
+                        // ignore this fast path for types that have regions or infer.
+                        if !self_ty
+                            .has_type_flags(TypeFlags::HAS_FREE_REGIONS | TypeFlags::HAS_INFER)
+                            && self_ty.is_trivially_pure_clone_copy()
+                        {
+                            return Some(Certainty::Yes);
+                        }
+                    }
+                    _ => {}
+                }
+            }
+        }
+
         let pred = goal.predicate.kind();
         match pred.no_bound_vars()? {
             ty::PredicateKind::DynCompatible(def_id) if self.0.tcx.is_dyn_compatible(def_id) => {
-                Some(HasChanged::No)
+                Some(Certainty::Yes)
             }
             ty::PredicateKind::Clause(ty::ClauseKind::RegionOutlives(outlives)) => {
                 self.0.sub_regions(
@@ -73,31 +104,16 @@ impl<'tcx> rustc_next_trait_solver::delegate::SolverDelegate for SolverDelegate<
                     outlives.1,
                     outlives.0,
                 );
-                Some(HasChanged::No)
+                Some(Certainty::Yes)
             }
             ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(outlives)) => {
-                self.0.register_region_obligation_with_cause(
+                self.0.register_type_outlives_constraint(
                     outlives.0,
                     outlives.1,
                     &ObligationCause::dummy_with_span(span),
                 );
 
-                Some(HasChanged::No)
-            }
-            ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_pred)) => {
-                match self.0.tcx.as_lang_item(trait_pred.def_id()) {
-                    Some(LangItem::Sized)
-                        if trait_pred.self_ty().is_trivially_sized(self.0.tcx) =>
-                    {
-                        Some(HasChanged::No)
-                    }
-                    Some(LangItem::Copy | LangItem::Clone)
-                        if trait_pred.self_ty().is_trivially_pure_clone_copy() =>
-                    {
-                        Some(HasChanged::No)
-                    }
-                    _ => None,
-                }
+                Some(Certainty::Yes)
             }
             _ => None,
         }
@@ -108,7 +124,7 @@ impl<'tcx> rustc_next_trait_solver::delegate::SolverDelegate for SolverDelegate<
         arg: ty::GenericArg<'tcx>,
         span: Span,
     ) -> ty::GenericArg<'tcx> {
-        match arg.unpack() {
+        match arg.kind() {
             ty::GenericArgKind::Lifetime(_) => {
                 self.next_region_var(RegionVariableOrigin::MiscVariable(span)).into()
             }
diff --git a/compiler/rustc_trait_selection/src/solve/fulfill.rs b/compiler/rustc_trait_selection/src/solve/fulfill.rs
index aa3be43fcd1..ed99c678a4d 100644
--- a/compiler/rustc_trait_selection/src/solve/fulfill.rs
+++ b/compiler/rustc_trait_selection/src/solve/fulfill.rs
@@ -13,8 +13,11 @@ use rustc_middle::ty::{
     self, DelayedSet, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor, TypingMode,
 };
 use rustc_next_trait_solver::delegate::SolverDelegate as _;
-use rustc_next_trait_solver::solve::{GenerateProofTree, HasChanged, SolverDelegateEvalExt as _};
+use rustc_next_trait_solver::solve::{
+    GenerateProofTree, GoalEvaluation, GoalStalledOn, HasChanged, SolverDelegateEvalExt as _,
+};
 use rustc_span::Span;
+use thin_vec::ThinVec;
 use tracing::instrument;
 
 use self::derive_errors::*;
@@ -25,6 +28,10 @@ use crate::traits::{FulfillmentError, ScrubbedTraitError};
 
 mod derive_errors;
 
+// FIXME: Do we need to use a `ThinVec` here?
+type PendingObligations<'tcx> =
+    ThinVec<(PredicateObligation<'tcx>, Option<GoalStalledOn<TyCtxt<'tcx>>>)>;
+
 /// A trait engine using the new trait solver.
 ///
 /// This is mostly identical to how `evaluate_all` works inside of the
@@ -54,13 +61,17 @@ struct ObligationStorage<'tcx> {
     /// We cannot eagerly return these as error so we instead store them here
     /// to avoid recomputing them each time `select_where_possible` is called.
     /// This also allows us to return the correct `FulfillmentError` for them.
-    overflowed: PredicateObligations<'tcx>,
-    pending: PredicateObligations<'tcx>,
+    overflowed: Vec<PredicateObligation<'tcx>>,
+    pending: PendingObligations<'tcx>,
 }
 
 impl<'tcx> ObligationStorage<'tcx> {
-    fn register(&mut self, obligation: PredicateObligation<'tcx>) {
-        self.pending.push(obligation);
+    fn register(
+        &mut self,
+        obligation: PredicateObligation<'tcx>,
+        stalled_on: Option<GoalStalledOn<TyCtxt<'tcx>>>,
+    ) {
+        self.pending.push((obligation, stalled_on));
     }
 
     fn has_pending_obligations(&self) -> bool {
@@ -68,7 +79,8 @@ impl<'tcx> ObligationStorage<'tcx> {
     }
 
     fn clone_pending(&self) -> PredicateObligations<'tcx> {
-        let mut obligations = self.pending.clone();
+        let mut obligations: PredicateObligations<'tcx> =
+            self.pending.iter().map(|(o, _)| o.clone()).collect();
         obligations.extend(self.overflowed.iter().cloned());
         obligations
     }
@@ -76,8 +88,9 @@ impl<'tcx> ObligationStorage<'tcx> {
     fn drain_pending(
         &mut self,
         cond: impl Fn(&PredicateObligation<'tcx>) -> bool,
-    ) -> PredicateObligations<'tcx> {
-        let (unstalled, pending) = mem::take(&mut self.pending).into_iter().partition(cond);
+    ) -> PendingObligations<'tcx> {
+        let (unstalled, pending) =
+            mem::take(&mut self.pending).into_iter().partition(|(o, _)| cond(o));
         self.pending = pending;
         unstalled
     }
@@ -90,13 +103,21 @@ impl<'tcx> ObligationStorage<'tcx> {
             // we were to do another step of `select_where_possible`, which goals would
             // change.
             // FIXME: <https://github.com/Gankra/thin-vec/pull/66> is merged, this can be removed.
-            self.overflowed.extend(ExtractIf::new(&mut self.pending, |o| {
-                let goal = o.as_goal();
-                let result = <&SolverDelegate<'tcx>>::from(infcx)
-                    .evaluate_root_goal(goal, GenerateProofTree::No, o.cause.span)
-                    .0;
-                matches!(result, Ok((HasChanged::Yes, _)))
-            }));
+            self.overflowed.extend(
+                ExtractIf::new(&mut self.pending, |(o, stalled_on)| {
+                    let goal = o.as_goal();
+                    let result = <&SolverDelegate<'tcx>>::from(infcx)
+                        .evaluate_root_goal(
+                            goal,
+                            GenerateProofTree::No,
+                            o.cause.span,
+                            stalled_on.take(),
+                        )
+                        .0;
+                    matches!(result, Ok(GoalEvaluation { has_changed: HasChanged::Yes, .. }))
+                })
+                .map(|(o, _)| o),
+            );
         })
     }
 }
@@ -119,11 +140,11 @@ impl<'tcx, E: 'tcx> FulfillmentCtxt<'tcx, E> {
         &self,
         infcx: &InferCtxt<'tcx>,
         obligation: &PredicateObligation<'tcx>,
-        result: &Result<(HasChanged, Certainty), NoSolution>,
+        result: &Result<GoalEvaluation<TyCtxt<'tcx>>, NoSolution>,
     ) {
         if let Some(inspector) = infcx.obligation_inspector.get() {
             let result = match result {
-                Ok((_, c)) => Ok(*c),
+                Ok(GoalEvaluation { certainty, .. }) => Ok(*certainty),
                 Err(NoSolution) => Err(NoSolution),
             };
             (inspector)(infcx, &obligation, result);
@@ -142,14 +163,14 @@ where
         obligation: PredicateObligation<'tcx>,
     ) {
         assert_eq!(self.usable_in_snapshot, infcx.num_open_snapshots());
-        self.obligations.register(obligation);
+        self.obligations.register(obligation, None);
     }
 
     fn collect_remaining_errors(&mut self, infcx: &InferCtxt<'tcx>) -> Vec<E> {
         self.obligations
             .pending
             .drain(..)
-            .map(|obligation| NextSolverError::Ambiguity(obligation))
+            .map(|(obligation, _)| NextSolverError::Ambiguity(obligation))
             .chain(
                 self.obligations
                     .overflowed
@@ -164,8 +185,8 @@ where
         assert_eq!(self.usable_in_snapshot, infcx.num_open_snapshots());
         let mut errors = Vec::new();
         loop {
-            let mut has_changed = false;
-            for mut obligation in self.obligations.drain_pending(|_| true) {
+            let mut any_changed = false;
+            for (mut obligation, stalled_on) in self.obligations.drain_pending(|_| true) {
                 if !infcx.tcx.recursion_limit().value_within_limit(obligation.recursion_depth) {
                     self.obligations.on_fulfillment_overflow(infcx);
                     // Only return true errors that we have accumulated while processing.
@@ -174,18 +195,28 @@ where
 
                 let goal = obligation.as_goal();
                 let delegate = <&SolverDelegate<'tcx>>::from(infcx);
-                if let Some(fast_path_has_changed) =
+                if let Some(certainty) =
                     delegate.compute_goal_fast_path(goal, obligation.cause.span)
                 {
-                    has_changed |= matches!(fast_path_has_changed, HasChanged::Yes);
+                    match certainty {
+                        Certainty::Yes => {}
+                        Certainty::Maybe(_) => {
+                            self.obligations.register(obligation, None);
+                        }
+                    }
                     continue;
                 }
 
                 let result = delegate
-                    .evaluate_root_goal(goal, GenerateProofTree::No, obligation.cause.span)
+                    .evaluate_root_goal(
+                        goal,
+                        GenerateProofTree::No,
+                        obligation.cause.span,
+                        stalled_on,
+                    )
                     .0;
                 self.inspect_evaluated_obligation(infcx, &obligation, &result);
-                let (changed, certainty) = match result {
+                let GoalEvaluation { certainty, has_changed, stalled_on } = match result {
                     Ok(result) => result,
                     Err(NoSolution) => {
                         errors.push(E::from_solver_error(
@@ -196,7 +227,7 @@ where
                     }
                 };
 
-                if changed == HasChanged::Yes {
+                if has_changed == HasChanged::Yes {
                     // We increment the recursion depth here to track the number of times
                     // this goal has resulted in inference progress. This doesn't precisely
                     // model the way that we track recursion depth in the old solver due
@@ -204,16 +235,16 @@ where
                     // approximation and should only result in fulfillment overflow in
                     // pathological cases.
                     obligation.recursion_depth += 1;
-                    has_changed = true;
+                    any_changed = true;
                 }
 
                 match certainty {
                     Certainty::Yes => {}
-                    Certainty::Maybe(_) => self.obligations.register(obligation),
+                    Certainty::Maybe(_) => self.obligations.register(obligation, stalled_on),
                 }
             }
 
-            if !has_changed {
+            if !any_changed {
                 break;
             }
         }
@@ -247,20 +278,24 @@ where
             return Default::default();
         }
 
-        self.obligations.drain_pending(|obl| {
-            infcx.probe(|_| {
-                infcx
-                    .visit_proof_tree(
-                        obl.as_goal(),
-                        &mut StalledOnCoroutines {
-                            stalled_generators,
-                            span: obl.cause.span,
-                            cache: Default::default(),
-                        },
-                    )
-                    .is_break()
+        self.obligations
+            .drain_pending(|obl| {
+                infcx.probe(|_| {
+                    infcx
+                        .visit_proof_tree(
+                            obl.as_goal(),
+                            &mut StalledOnCoroutines {
+                                stalled_generators,
+                                span: obl.cause.span,
+                                cache: Default::default(),
+                            },
+                        )
+                        .is_break()
+                })
             })
-        })
+            .into_iter()
+            .map(|(o, _)| o)
+            .collect()
     }
 }
 
diff --git a/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs b/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs
index f64cd5ffebe..1c9d69da322 100644
--- a/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs
+++ b/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs
@@ -11,7 +11,9 @@ use rustc_middle::traits::query::NoSolution;
 use rustc_middle::ty::error::{ExpectedFound, TypeError};
 use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_middle::{bug, span_bug};
-use rustc_next_trait_solver::solve::{GenerateProofTree, SolverDelegateEvalExt as _};
+use rustc_next_trait_solver::solve::{
+    GenerateProofTree, GoalEvaluation, SolverDelegateEvalExt as _,
+};
 use tracing::{instrument, trace};
 
 use crate::solve::delegate::SolverDelegate;
@@ -93,19 +95,21 @@ pub(super) fn fulfillment_error_for_stalled<'tcx>(
                 root_obligation.as_goal(),
                 GenerateProofTree::No,
                 root_obligation.cause.span,
+                None,
             )
             .0
         {
-            Ok((_, Certainty::Maybe(MaybeCause::Ambiguity))) => {
+            Ok(GoalEvaluation { certainty: Certainty::Maybe(MaybeCause::Ambiguity), .. }) => {
                 (FulfillmentErrorCode::Ambiguity { overflow: None }, true)
             }
-            Ok((
-                _,
-                Certainty::Maybe(MaybeCause::Overflow {
-                    suggest_increasing_limit,
-                    keep_constraints: _,
-                }),
-            )) => (
+            Ok(GoalEvaluation {
+                certainty:
+                    Certainty::Maybe(MaybeCause::Overflow {
+                        suggest_increasing_limit,
+                        keep_constraints: _,
+                    }),
+                ..
+            }) => (
                 FulfillmentErrorCode::Ambiguity { overflow: Some(suggest_increasing_limit) },
                 // Don't look into overflows because we treat overflows weirdly anyways.
                 // We discard the inference constraints from overflowing goals, so
@@ -115,7 +119,7 @@ pub(super) fn fulfillment_error_for_stalled<'tcx>(
                 // FIXME: We should probably just look into overflows here.
                 false,
             ),
-            Ok((_, Certainty::Yes)) => {
+            Ok(GoalEvaluation { certainty: Certainty::Yes, .. }) => {
                 bug!(
                     "did not expect successful goal when collecting ambiguity errors for `{:?}`",
                     infcx.resolve_vars_if_possible(root_obligation.predicate),
diff --git a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs
index 9795655e842..1193a9059ca 100644
--- a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs
+++ b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs
@@ -15,9 +15,9 @@ use rustc_infer::infer::{DefineOpaqueTypes, InferCtxt, InferOk};
 use rustc_macros::extension;
 use rustc_middle::traits::ObligationCause;
 use rustc_middle::traits::solve::{Certainty, Goal, GoalSource, NoSolution, QueryResult};
-use rustc_middle::ty::{TyCtxt, TypeFoldable, VisitorResult, try_visit};
+use rustc_middle::ty::{TyCtxt, VisitorResult, try_visit};
 use rustc_middle::{bug, ty};
-use rustc_next_trait_solver::resolve::EagerResolver;
+use rustc_next_trait_solver::resolve::eager_resolve_vars;
 use rustc_next_trait_solver::solve::inspect::{self, instantiate_canonical_state};
 use rustc_next_trait_solver::solve::{GenerateProofTree, MaybeCause, SolverDelegateEvalExt as _};
 use rustc_span::{DUMMY_SP, Span};
@@ -187,8 +187,7 @@ impl<'a, 'tcx> InspectCandidate<'a, 'tcx> {
             let _ = term_hack.constrain(infcx, span, param_env);
         }
 
-        let opt_impl_args =
-            opt_impl_args.map(|impl_args| impl_args.fold_with(&mut EagerResolver::new(infcx)));
+        let opt_impl_args = opt_impl_args.map(|impl_args| eager_resolve_vars(infcx, impl_args));
 
         let goals = instantiated_goals
             .into_iter()
@@ -207,7 +206,7 @@ impl<'a, 'tcx> InspectCandidate<'a, 'tcx> {
         let infcx = self.goal.infcx;
         match goal.predicate.kind().no_bound_vars() {
             Some(ty::PredicateKind::NormalizesTo(ty::NormalizesTo { alias, term })) => {
-                let unconstrained_term = match term.unpack() {
+                let unconstrained_term = match term.kind() {
                     ty::TermKind::Ty(_) => infcx.next_ty_var(span).into(),
                     ty::TermKind::Const(_) => infcx.next_const_var(span).into(),
                 };
@@ -219,8 +218,8 @@ impl<'a, 'tcx> InspectCandidate<'a, 'tcx> {
                 // building their proof tree, the expected term was unconstrained, but when
                 // instantiating the candidate it is already constrained to the result of another
                 // candidate.
-                let proof_tree =
-                    infcx.probe(|_| infcx.evaluate_root_goal_raw(goal, GenerateProofTree::Yes).1);
+                let proof_tree = infcx
+                    .probe(|_| infcx.evaluate_root_goal_raw(goal, GenerateProofTree::Yes, None).1);
                 InspectGoal::new(
                     infcx,
                     self.goal.depth + 1,
@@ -236,7 +235,7 @@ impl<'a, 'tcx> InspectCandidate<'a, 'tcx> {
                 // constraints, we get an ICE if we already applied the constraints
                 // from the chosen candidate.
                 let proof_tree = infcx
-                    .probe(|_| infcx.evaluate_root_goal(goal, GenerateProofTree::Yes, span).1)
+                    .probe(|_| infcx.evaluate_root_goal(goal, GenerateProofTree::Yes, span, None).1)
                     .unwrap();
                 InspectGoal::new(infcx, self.goal.depth + 1, proof_tree, None, source)
             }
@@ -392,7 +391,7 @@ impl<'a, 'tcx> InspectGoal<'a, 'tcx> {
             infcx,
             depth,
             orig_values,
-            goal: uncanonicalized_goal.fold_with(&mut EagerResolver::new(infcx)),
+            goal: eager_resolve_vars(infcx, uncanonicalized_goal),
             result,
             evaluation_kind: evaluation.kind,
             normalizes_to_term_hack,
@@ -442,6 +441,7 @@ impl<'tcx> InferCtxt<'tcx> {
             goal,
             GenerateProofTree::Yes,
             visitor.span(),
+            None,
         );
         let proof_tree = proof_tree.unwrap();
         visitor.visit_goal(&InspectGoal::new(self, depth, proof_tree, None, GoalSource::Misc))
diff --git a/compiler/rustc_trait_selection/src/traits/auto_trait.rs b/compiler/rustc_trait_selection/src/traits/auto_trait.rs
index 02521c9453d..3ae908ec16b 100644
--- a/compiler/rustc_trait_selection/src/traits/auto_trait.rs
+++ b/compiler/rustc_trait_selection/src/traits/auto_trait.rs
@@ -726,7 +726,9 @@ impl<'tcx> AutoTraitFinder<'tcx> {
                 }
                 ty::PredicateKind::Clause(ty::ClauseKind::RegionOutlives(binder)) => {
                     let binder = bound_predicate.rebind(binder);
-                    selcx.infcx.region_outlives_predicate(&dummy_cause, binder)
+                    selcx.infcx.enter_forall(binder, |pred| {
+                        selcx.infcx.register_region_outlives_constraint(pred, &dummy_cause);
+                    });
                 }
                 ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(binder)) => {
                     let binder = bound_predicate.rebind(binder);
@@ -735,14 +737,14 @@ impl<'tcx> AutoTraitFinder<'tcx> {
                         binder.map_bound_ref(|pred| pred.0).no_bound_vars(),
                     ) {
                         (None, Some(t_a)) => {
-                            selcx.infcx.register_region_obligation_with_cause(
+                            selcx.infcx.register_type_outlives_constraint(
                                 t_a,
                                 selcx.infcx.tcx.lifetimes.re_static,
                                 &dummy_cause,
                             );
                         }
                         (Some(ty::OutlivesPredicate(t_a, r_b)), _) => {
-                            selcx.infcx.register_region_obligation_with_cause(
+                            selcx.infcx.register_type_outlives_constraint(
                                 t_a,
                                 r_b,
                                 &dummy_cause,
diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs
index 34c3c905bd9..951dfb879ae 100644
--- a/compiler/rustc_trait_selection/src/traits/fulfill.rs
+++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs
@@ -428,7 +428,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
 
                 ty::PredicateKind::Clause(ty::ClauseKind::RegionOutlives(data)) => {
                     if infcx.considering_regions {
-                        infcx.region_outlives_predicate(&obligation.cause, Binder::dummy(data));
+                        infcx.register_region_outlives_constraint(data, &obligation.cause);
                     }
 
                     ProcessResult::Changed(Default::default())
@@ -439,7 +439,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
                     r_b,
                 ))) => {
                     if infcx.considering_regions {
-                        infcx.register_region_obligation_with_cause(t_a, r_b, &obligation.cause);
+                        infcx.register_type_outlives_constraint(t_a, r_b, &obligation.cause);
                     }
                     ProcessResult::Changed(Default::default())
                 }
diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs
index a9bdb909bdc..999ef97683c 100644
--- a/compiler/rustc_trait_selection/src/traits/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/mod.rs
@@ -221,7 +221,7 @@ fn pred_known_to_hold_modulo_regions<'tcx>(
 
     if result.must_apply_modulo_regions() {
         true
-    } else if result.may_apply() {
+    } else if result.may_apply() && !infcx.next_trait_solver() {
         // Sometimes obligations are ambiguous because the recursive evaluator
         // is not smart enough, so we fall back to fulfillment when we're not certain
         // that an obligation holds or not. Even still, we must make sure that
diff --git a/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs b/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs
index 68983ef80fa..59d3ac21387 100644
--- a/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs
+++ b/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs
@@ -9,7 +9,7 @@ use rustc_span::def_id::LocalDefId;
 use tracing::instrument;
 
 use crate::infer::InferCtxt;
-use crate::traits::{ObligationCause, ObligationCtxt};
+use crate::traits::ObligationCause;
 
 /// Implied bounds are region relationships that we deduce
 /// automatically. The idea is that (e.g.) a caller must check that a
@@ -79,24 +79,9 @@ fn implied_outlives_bounds<'a, 'tcx>(
 
     if !constraints.is_empty() {
         let QueryRegionConstraints { outlives } = constraints;
-        // Instantiation may have produced new inference variables and constraints on those
-        // variables. Process these constraints.
-        let ocx = ObligationCtxt::new(infcx);
         let cause = ObligationCause::misc(span, body_id);
-        for &constraint in &outlives {
-            ocx.register_obligation(infcx.query_outlives_constraint_to_obligation(
-                constraint,
-                cause.clone(),
-                param_env,
-            ));
-        }
-
-        let errors = ocx.select_all_or_error();
-        if !errors.is_empty() {
-            infcx.dcx().span_bug(
-                span,
-                "implied_outlives_bounds failed to solve obligations from instantiation",
-            );
+        for &(predicate, _) in &outlives {
+            infcx.register_outlives_constraint(predicate, &cause);
         }
     };
 
diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs
index d9b57f0c67d..e294f7839aa 100644
--- a/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs
@@ -1,6 +1,6 @@
 use std::ops::ControlFlow;
 
-use rustc_infer::infer::RegionObligation;
+use rustc_infer::infer::TypeOutlivesConstraint;
 use rustc_infer::infer::canonical::CanonicalQueryInput;
 use rustc_infer::traits::query::OutlivesBound;
 use rustc_infer::traits::query::type_op::ImpliedOutlivesBounds;
@@ -141,7 +141,7 @@ pub fn compute_implied_outlives_bounds_inner<'tcx>(
         && !ocx.infcx.tcx.sess.opts.unstable_opts.no_implied_bounds_compat
         && ty.visit_with(&mut ContainsBevyParamSet { tcx: ocx.infcx.tcx }).is_break()
     {
-        for RegionObligation { sup_type, sub_region, .. } in
+        for TypeOutlivesConstraint { sup_type, sub_region, .. } in
             ocx.infcx.take_registered_region_obligations()
         {
             let mut components = smallvec![];
diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
index 7d869b27445..97ecf9702e6 100644
--- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
@@ -11,7 +11,7 @@ use std::ops::ControlFlow;
 use hir::LangItem;
 use hir::def_id::DefId;
 use rustc_data_structures::fx::{FxHashSet, FxIndexSet};
-use rustc_hir as hir;
+use rustc_hir::{self as hir, CoroutineDesugaring, CoroutineKind};
 use rustc_infer::traits::{Obligation, PolyTraitObligation, SelectionError};
 use rustc_middle::ty::fast_reject::DeepRejectCtxt;
 use rustc_middle::ty::{self, Ty, TypeVisitableExt, TypingMode, elaborate};
@@ -438,6 +438,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         }
     }
 
+    #[instrument(level = "debug", skip(self, candidates))]
     fn assemble_async_closure_candidates(
         &mut self,
         obligation: &PolyTraitObligation<'tcx>,
@@ -446,15 +447,30 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         let goal_kind =
             self.tcx().async_fn_trait_kind_from_def_id(obligation.predicate.def_id()).unwrap();
 
+        debug!("self_ty = {:?}", obligation.self_ty().skip_binder().kind());
         match *obligation.self_ty().skip_binder().kind() {
-            ty::CoroutineClosure(_, args) => {
+            ty::CoroutineClosure(def_id, args) => {
                 if let Some(closure_kind) =
                     args.as_coroutine_closure().kind_ty().to_opt_closure_kind()
                     && !closure_kind.extends(goal_kind)
                 {
                     return;
                 }
-                candidates.vec.push(AsyncClosureCandidate);
+
+                // Make sure this is actually an async closure.
+                let Some(coroutine_kind) =
+                    self.tcx().coroutine_kind(self.tcx().coroutine_for_closure(def_id))
+                else {
+                    bug!("coroutine with no kind");
+                };
+
+                debug!(?coroutine_kind);
+                match coroutine_kind {
+                    CoroutineKind::Desugared(CoroutineDesugaring::Async, _) => {
+                        candidates.vec.push(AsyncClosureCandidate);
+                    }
+                    _ => (),
+                }
             }
             // Closures and fn pointers implement `AsyncFn*` if their return types
             // implement `Future`, which is checked later.
diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs
index 2be799735a8..3a2f9e8ca17 100644
--- a/compiler/rustc_trait_selection/src/traits/select/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs
@@ -1784,7 +1784,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             if !generics.is_own_empty()
                 && obligation.predicate.args[generics.parent_count..].iter().any(|&p| {
                     p.has_non_region_infer()
-                        && match p.unpack() {
+                        && match p.kind() {
                             ty::GenericArgKind::Const(ct) => {
                                 self.infcx.shallow_resolve_const(ct) != ct
                             }
diff --git a/compiler/rustc_trait_selection/src/traits/structural_normalize.rs b/compiler/rustc_trait_selection/src/traits/structural_normalize.rs
index e6d5d336b8d..3f741345404 100644
--- a/compiler/rustc_trait_selection/src/traits/structural_normalize.rs
+++ b/compiler/rustc_trait_selection/src/traits/structural_normalize.rs
@@ -39,7 +39,7 @@ impl<'tcx> At<'_, 'tcx> {
                 return Ok(term);
             }
 
-            let new_infer = match term.unpack() {
+            let new_infer = match term.kind() {
                 ty::TermKind::Ty(_) => self.infcx.next_ty_var(self.cause.span).into(),
                 ty::TermKind::Const(_) => self.infcx.next_const_var(self.cause.span).into(),
             };
diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs
index 08d3b92e9b5..3018dad8e09 100644
--- a/compiler/rustc_trait_selection/src/traits/wf.rs
+++ b/compiler/rustc_trait_selection/src/traits/wf.rs
@@ -37,7 +37,7 @@ pub fn obligations<'tcx>(
     span: Span,
 ) -> Option<PredicateObligations<'tcx>> {
     // Handle the "cycle" case (see comment above) by bailing out if necessary.
-    let term = match term.unpack() {
+    let term = match term.kind() {
         TermKind::Ty(ty) => {
             match ty.kind() {
                 ty::Infer(ty::TyVar(_)) => {
diff --git a/compiler/rustc_ty_utils/src/opaque_types.rs b/compiler/rustc_ty_utils/src/opaque_types.rs
index 841f602d985..3b4482146d4 100644
--- a/compiler/rustc_ty_utils/src/opaque_types.rs
+++ b/compiler/rustc_ty_utils/src/opaque_types.rs
@@ -321,7 +321,10 @@ fn opaque_types_defined_by<'tcx>(
             collector.collect_taits_declared_in_body();
         }
         // Closures and coroutines are type checked with their parent
-        DefKind::Closure | DefKind::InlineConst => {
+        // Note that we also support `SyntheticCoroutineBody` since we create
+        // a MIR body for the def kind, and some MIR passes (like promotion)
+        // may require doing analysis using its typing env.
+        DefKind::Closure | DefKind::InlineConst | DefKind::SyntheticCoroutineBody => {
             collector.opaques.extend(tcx.opaque_types_defined_by(tcx.local_parent(item)));
         }
         DefKind::AssocTy | DefKind::TyAlias | DefKind::GlobalAsm => {}
@@ -343,8 +346,7 @@ fn opaque_types_defined_by<'tcx>(
         | DefKind::ForeignMod
         | DefKind::Field
         | DefKind::LifetimeParam
-        | DefKind::Impl { .. }
-        | DefKind::SyntheticCoroutineBody => {
+        | DefKind::Impl { .. } => {
             span_bug!(
                 tcx.def_span(item),
                 "`opaque_types_defined_by` not defined for {} `{item:?}`",
diff --git a/compiler/rustc_ty_utils/src/representability.rs b/compiler/rustc_ty_utils/src/representability.rs
index 98b1550e1a3..33d334092ba 100644
--- a/compiler/rustc_ty_utils/src/representability.rs
+++ b/compiler/rustc_ty_utils/src/representability.rs
@@ -74,7 +74,7 @@ fn representability_adt_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Representab
     // but the type parameters may cause a cycle with an upstream type
     let params_in_repr = tcx.params_in_repr(adt.did());
     for (i, arg) in args.iter().enumerate() {
-        if let ty::GenericArgKind::Type(ty) = arg.unpack() {
+        if let ty::GenericArgKind::Type(ty) = arg.kind() {
             if params_in_repr.contains(i as u32) {
                 rtry!(representability_ty(tcx, ty));
             }
@@ -104,7 +104,7 @@ fn params_in_repr_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, params_in_repr: &mut
         ty::Adt(adt, args) => {
             let inner_params_in_repr = tcx.params_in_repr(adt.did());
             for (i, arg) in args.iter().enumerate() {
-                if let ty::GenericArgKind::Type(ty) = arg.unpack() {
+                if let ty::GenericArgKind::Type(ty) = arg.kind() {
                     if inner_params_in_repr.contains(i as u32) {
                         params_in_repr_ty(tcx, ty, params_in_repr);
                     }
diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs
index 0c49ddff39b..330aaa25d13 100644
--- a/compiler/rustc_ty_utils/src/ty.rs
+++ b/compiler/rustc_ty_utils/src/ty.rs
@@ -274,7 +274,7 @@ fn unsizing_params_for_adt<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> DenseBitSe
     let def = tcx.adt_def(def_id);
     let num_params = tcx.generics_of(def_id).count();
 
-    let maybe_unsizing_param_idx = |arg: ty::GenericArg<'tcx>| match arg.unpack() {
+    let maybe_unsizing_param_idx = |arg: ty::GenericArg<'tcx>| match arg.kind() {
         ty::GenericArgKind::Type(ty) => match ty.kind() {
             ty::Param(p) => Some(p.index),
             _ => None,
diff --git a/compiler/rustc_type_ir/src/binder.rs b/compiler/rustc_type_ir/src/binder.rs
index 000cf1e1fd8..55c0a3bba9f 100644
--- a/compiler/rustc_type_ir/src/binder.rs
+++ b/compiler/rustc_type_ir/src/binder.rs
@@ -676,7 +676,7 @@ impl<'a, I: Interner> TypeFolder<I> for ArgFolder<'a, I> {
         // the specialized routine `ty::replace_late_regions()`.
         match r.kind() {
             ty::ReEarlyParam(data) => {
-                let rk = self.args.get(data.index() as usize).map(|k| k.kind());
+                let rk = self.args.get(data.index() as usize).map(|arg| arg.kind());
                 match rk {
                     Some(ty::GenericArgKind::Lifetime(lt)) => self.shift_region_through_binders(lt),
                     Some(other) => self.region_param_expected(data, r, other),
@@ -711,12 +711,20 @@ impl<'a, I: Interner> TypeFolder<I> for ArgFolder<'a, I> {
             c.super_fold_with(self)
         }
     }
+
+    fn fold_predicate(&mut self, p: I::Predicate) -> I::Predicate {
+        if p.has_param() { p.super_fold_with(self) } else { p }
+    }
+
+    fn fold_clauses(&mut self, c: I::Clauses) -> I::Clauses {
+        if c.has_param() { c.super_fold_with(self) } else { c }
+    }
 }
 
 impl<'a, I: Interner> ArgFolder<'a, I> {
     fn ty_for_param(&self, p: I::ParamTy, source_ty: I::Ty) -> I::Ty {
         // Look up the type in the args. It really should be in there.
-        let opt_ty = self.args.get(p.index() as usize).map(|k| k.kind());
+        let opt_ty = self.args.get(p.index() as usize).map(|arg| arg.kind());
         let ty = match opt_ty {
             Some(ty::GenericArgKind::Type(ty)) => ty,
             Some(kind) => self.type_param_expected(p, source_ty, kind),
@@ -753,7 +761,7 @@ impl<'a, I: Interner> ArgFolder<'a, I> {
 
     fn const_for_param(&self, p: I::ParamConst, source_ct: I::Const) -> I::Const {
         // Look up the const in the args. It really should be in there.
-        let opt_ct = self.args.get(p.index() as usize).map(|k| k.kind());
+        let opt_ct = self.args.get(p.index() as usize).map(|arg| arg.kind());
         let ct = match opt_ct {
             Some(ty::GenericArgKind::Const(ct)) => ct,
             Some(kind) => self.const_param_expected(p, source_ct, kind),
diff --git a/compiler/rustc_type_ir/src/flags.rs b/compiler/rustc_type_ir/src/flags.rs
index 7ed0f92b639..37cc2baa402 100644
--- a/compiler/rustc_type_ir/src/flags.rs
+++ b/compiler/rustc_type_ir/src/flags.rs
@@ -479,8 +479,8 @@ impl<I: Interner> FlagComputation<I> {
     }
 
     fn add_args(&mut self, args: &[I::GenericArg]) {
-        for kind in args {
-            match kind.kind() {
+        for arg in args {
+            match arg.kind() {
                 ty::GenericArgKind::Type(ty) => self.add_ty(ty),
                 ty::GenericArgKind::Lifetime(lt) => self.add_region(lt),
                 ty::GenericArgKind::Const(ct) => self.add_const(ct),
diff --git a/compiler/rustc_type_ir/src/fold.rs b/compiler/rustc_type_ir/src/fold.rs
index ce1188070ca..a5eb8699e5f 100644
--- a/compiler/rustc_type_ir/src/fold.rs
+++ b/compiler/rustc_type_ir/src/fold.rs
@@ -152,6 +152,10 @@ pub trait TypeFolder<I: Interner>: Sized {
     fn fold_predicate(&mut self, p: I::Predicate) -> I::Predicate {
         p.super_fold_with(self)
     }
+
+    fn fold_clauses(&mut self, c: I::Clauses) -> I::Clauses {
+        c.super_fold_with(self)
+    }
 }
 
 /// This trait is implemented for every folding traversal. There is a fold
@@ -190,6 +194,10 @@ pub trait FallibleTypeFolder<I: Interner>: Sized {
     fn try_fold_predicate(&mut self, p: I::Predicate) -> Result<I::Predicate, Self::Error> {
         p.try_super_fold_with(self)
     }
+
+    fn try_fold_clauses(&mut self, c: I::Clauses) -> Result<I::Clauses, Self::Error> {
+        c.try_super_fold_with(self)
+    }
 }
 
 ///////////////////////////////////////////////////////////////////////////
diff --git a/compiler/rustc_type_ir/src/infer_ctxt.rs b/compiler/rustc_type_ir/src/infer_ctxt.rs
index c1490762117..2bc12d0a23b 100644
--- a/compiler/rustc_type_ir/src/infer_ctxt.rs
+++ b/compiler/rustc_type_ir/src/infer_ctxt.rs
@@ -1,11 +1,10 @@
-use std::fmt::Debug;
-
 use derive_where::derive_where;
 #[cfg(feature = "nightly")]
 use rustc_macros::{Decodable_NoContext, Encodable_NoContext, HashStable_NoContext};
 use rustc_type_ir_macros::{TypeFoldable_Generic, TypeVisitable_Generic};
 
 use crate::fold::TypeFoldable;
+use crate::inherent::*;
 use crate::relate::RelateResult;
 use crate::relate::combine::PredicateEmittingRelation;
 use crate::{self as ty, Interner};
@@ -168,6 +167,8 @@ pub trait InferCtxtLike: Sized {
         vid: ty::RegionVid,
     ) -> <Self::Interner as Interner>::Region;
 
+    fn is_changed_arg(&self, arg: <Self::Interner as Interner>::GenericArg) -> bool;
+
     fn next_region_infer(&self) -> <Self::Interner as Interner>::Region;
     fn next_ty_infer(&self) -> <Self::Interner as Interner>::Ty;
     fn next_const_infer(&self) -> <Self::Interner as Interner>::Const;
@@ -248,7 +249,7 @@ pub trait InferCtxtLike: Sized {
         span: <Self::Interner as Interner>::Span,
     );
 
-    type OpaqueTypeStorageEntries: Debug + Copy + Default;
+    type OpaqueTypeStorageEntries: OpaqueTypeStorageEntries;
     fn opaque_types_storage_num_entries(&self) -> Self::OpaqueTypeStorageEntries;
     fn clone_opaque_types_lookup_table(
         &self,
diff --git a/compiler/rustc_type_ir/src/inherent.rs b/compiler/rustc_type_ir/src/inherent.rs
index ee4a8096462..fa88bcb891a 100644
--- a/compiler/rustc_type_ir/src/inherent.rs
+++ b/compiler/rustc_type_ir/src/inherent.rs
@@ -297,6 +297,7 @@ pub trait GenericArg<I: Interner<GenericArg = Self>>:
     + From<I::Ty>
     + From<I::Region>
     + From<I::Const>
+    + From<I::Term>
 {
     fn as_term(&self) -> Option<I::Term> {
         match self.kind() {
@@ -510,6 +511,18 @@ pub trait Clause<I: Interner<Clause = Self>>:
     fn instantiate_supertrait(self, cx: I, trait_ref: ty::Binder<I, ty::TraitRef<I>>) -> Self;
 }
 
+pub trait Clauses<I: Interner<Clauses = Self>>:
+    Copy
+    + Debug
+    + Hash
+    + Eq
+    + TypeSuperVisitable<I>
+    + TypeSuperFoldable<I>
+    + Flags
+    + SliceLike<Item = I::Clause>
+{
+}
+
 /// Common capabilities of placeholder kinds
 pub trait PlaceholderLike: Copy + Debug + Hash + Eq {
     fn universe(self) -> ty::UniverseIndex;
@@ -596,6 +609,13 @@ pub trait Span<I: Interner>: Copy + Debug + Hash + Eq + TypeFoldable<I> {
     fn dummy() -> Self;
 }
 
+pub trait OpaqueTypeStorageEntries: Debug + Copy + Default {
+    /// Whether the number of opaques has changed in a way that necessitates
+    /// reevaluating a goal. For now, this is only when the number of non-duplicated
+    /// entries changed.
+    fn needs_reevaluation(self, canonicalized: usize) -> bool;
+}
+
 pub trait SliceLike: Sized + Copy {
     type Item: Copy;
     type IntoIter: Iterator<Item = Self::Item> + DoubleEndedIterator;
diff --git a/compiler/rustc_type_ir/src/interner.rs b/compiler/rustc_type_ir/src/interner.rs
index 7e88114df46..a9917192144 100644
--- a/compiler/rustc_type_ir/src/interner.rs
+++ b/compiler/rustc_type_ir/src/interner.rs
@@ -12,7 +12,7 @@ use crate::ir_print::IrPrint;
 use crate::lang_items::TraitSolverLangItem;
 use crate::relate::Relate;
 use crate::solve::{CanonicalInput, ExternalConstraintsData, PredefinedOpaquesData, QueryResult};
-use crate::visit::{Flags, TypeSuperVisitable, TypeVisitable};
+use crate::visit::{Flags, TypeVisitable};
 use crate::{self as ty, search_graph};
 
 #[cfg_attr(feature = "nightly", rustc_diagnostic_item = "type_ir_interner")]
@@ -146,7 +146,7 @@ pub trait Interner:
     type ParamEnv: ParamEnv<Self>;
     type Predicate: Predicate<Self>;
     type Clause: Clause<Self>;
-    type Clauses: Copy + Debug + Hash + Eq + TypeSuperVisitable<Self> + Flags;
+    type Clauses: Clauses<Self>;
 
     fn with_global_cache<R>(self, f: impl FnOnce(&mut search_graph::GlobalCache<Self>) -> R) -> R;
 
diff --git a/compiler/rustc_type_ir/src/visit.rs b/compiler/rustc_type_ir/src/visit.rs
index ccb84e25911..fc3864dd5ae 100644
--- a/compiler/rustc_type_ir/src/visit.rs
+++ b/compiler/rustc_type_ir/src/visit.rs
@@ -120,8 +120,8 @@ pub trait TypeVisitor<I: Interner>: Sized {
         p.super_visit_with(self)
     }
 
-    fn visit_clauses(&mut self, p: I::Clauses) -> Self::Result {
-        p.super_visit_with(self)
+    fn visit_clauses(&mut self, c: I::Clauses) -> Self::Result {
+        c.super_visit_with(self)
     }
 
     fn visit_error(&mut self, _guar: I::ErrorGuaranteed) -> Self::Result {
diff --git a/library/Cargo.lock b/library/Cargo.lock
index 02018057ed5..0c75977ee79 100644
--- a/library/Cargo.lock
+++ b/library/Cargo.lock
@@ -61,9 +61,9 @@ dependencies = [
 
 [[package]]
 name = "compiler_builtins"
-version = "0.1.159"
+version = "0.1.160"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "448068da8f2326b2a0472353cb401dd8795a89c007ef30fff90f50706e862e72"
+checksum = "6376049cfa92c0aa8b9ac95fae22184b981c658208d4ed8a1dc553cd83612895"
 dependencies = [
  "cc",
  "rustc-std-workspace-core",
diff --git a/library/alloc/Cargo.toml b/library/alloc/Cargo.toml
index 9d0d957226d..365c9dc00df 100644
--- a/library/alloc/Cargo.toml
+++ b/library/alloc/Cargo.toml
@@ -16,7 +16,7 @@ bench = false
 
 [dependencies]
 core = { path = "../core", public = true }
-compiler_builtins = { version = "=0.1.159", features = ['rustc-dep-of-std'] }
+compiler_builtins = { version = "=0.1.160", features = ['rustc-dep-of-std'] }
 
 [features]
 compiler-builtins-mem = ['compiler_builtins/mem']
diff --git a/library/alloc/src/collections/btree/map.rs b/library/alloc/src/collections/btree/map.rs
index ea81645aa64..52b98291ff9 100644
--- a/library/alloc/src/collections/btree/map.rs
+++ b/library/alloc/src/collections/btree/map.rs
@@ -1151,7 +1151,7 @@ impl<K, V, A: Allocator + Clone> BTreeMap<K, V, A> {
         K: Ord,
         F: FnMut(&K, &mut V) -> bool,
     {
-        self.extract_if(|k, v| !f(k, v)).for_each(drop);
+        self.extract_if(.., |k, v| !f(k, v)).for_each(drop);
     }
 
     /// Moves all elements from `other` into `self`, leaving `other` empty.
@@ -1397,7 +1397,7 @@ impl<K, V, A: Allocator + Clone> BTreeMap<K, V, A> {
         }
     }
 
-    /// Creates an iterator that visits all elements (key-value pairs) in
+    /// Creates an iterator that visits elements (key-value pairs) in the specified range in
     /// ascending key order and uses a closure to determine if an element
     /// should be removed.
     ///
@@ -1423,33 +1423,42 @@ impl<K, V, A: Allocator + Clone> BTreeMap<K, V, A> {
     /// use std::collections::BTreeMap;
     ///
     /// let mut map: BTreeMap<i32, i32> = (0..8).map(|x| (x, x)).collect();
-    /// let evens: BTreeMap<_, _> = map.extract_if(|k, _v| k % 2 == 0).collect();
+    /// let evens: BTreeMap<_, _> = map.extract_if(.., |k, _v| k % 2 == 0).collect();
     /// let odds = map;
     /// assert_eq!(evens.keys().copied().collect::<Vec<_>>(), [0, 2, 4, 6]);
     /// assert_eq!(odds.keys().copied().collect::<Vec<_>>(), [1, 3, 5, 7]);
+    ///
+    /// let mut map: BTreeMap<i32, i32> = (0..8).map(|x| (x, x)).collect();
+    /// let low: BTreeMap<_, _> = map.extract_if(0..4, |_k, _v| true).collect();
+    /// let high = map;
+    /// assert_eq!(low.keys().copied().collect::<Vec<_>>(), [0, 1, 2, 3]);
+    /// assert_eq!(high.keys().copied().collect::<Vec<_>>(), [4, 5, 6, 7]);
     /// ```
     #[unstable(feature = "btree_extract_if", issue = "70530")]
-    pub fn extract_if<F>(&mut self, pred: F) -> ExtractIf<'_, K, V, F, A>
+    pub fn extract_if<F, R>(&mut self, range: R, pred: F) -> ExtractIf<'_, K, V, R, F, A>
     where
         K: Ord,
+        R: RangeBounds<K>,
         F: FnMut(&K, &mut V) -> bool,
     {
-        let (inner, alloc) = self.extract_if_inner();
+        let (inner, alloc) = self.extract_if_inner(range);
         ExtractIf { pred, inner, alloc }
     }
 
-    pub(super) fn extract_if_inner(&mut self) -> (ExtractIfInner<'_, K, V>, A)
+    pub(super) fn extract_if_inner<R>(&mut self, range: R) -> (ExtractIfInner<'_, K, V, R>, A)
     where
         K: Ord,
+        R: RangeBounds<K>,
     {
         if let Some(root) = self.root.as_mut() {
             let (root, dormant_root) = DormantMutRef::new(root);
-            let front = root.borrow_mut().first_leaf_edge();
+            let first = root.borrow_mut().lower_bound(SearchBound::from_range(range.start_bound()));
             (
                 ExtractIfInner {
                     length: &mut self.length,
                     dormant_root: Some(dormant_root),
-                    cur_leaf_edge: Some(front),
+                    cur_leaf_edge: Some(first),
+                    range,
                 },
                 (*self.alloc).clone(),
             )
@@ -1459,6 +1468,7 @@ impl<K, V, A: Allocator + Clone> BTreeMap<K, V, A> {
                     length: &mut self.length,
                     dormant_root: None,
                     cur_leaf_edge: None,
+                    range,
                 },
                 (*self.alloc).clone(),
             )
@@ -1917,18 +1927,19 @@ pub struct ExtractIf<
     'a,
     K,
     V,
+    R,
     F,
     #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator + Clone = Global,
 > {
     pred: F,
-    inner: ExtractIfInner<'a, K, V>,
+    inner: ExtractIfInner<'a, K, V, R>,
     /// The BTreeMap will outlive this IntoIter so we don't care about drop order for `alloc`.
     alloc: A,
 }
 
 /// Most of the implementation of ExtractIf are generic over the type
 /// of the predicate, thus also serving for BTreeSet::ExtractIf.
-pub(super) struct ExtractIfInner<'a, K, V> {
+pub(super) struct ExtractIfInner<'a, K, V, R> {
     /// Reference to the length field in the borrowed map, updated live.
     length: &'a mut usize,
     /// Buried reference to the root field in the borrowed map.
@@ -1938,10 +1949,13 @@ pub(super) struct ExtractIfInner<'a, K, V> {
     /// Empty if the map has no root, if iteration went beyond the last leaf edge,
     /// or if a panic occurred in the predicate.
     cur_leaf_edge: Option<Handle<NodeRef<marker::Mut<'a>, K, V, marker::Leaf>, marker::Edge>>,
+    /// Range over which iteration was requested.  We don't need the left side, but we
+    /// can't extract the right side without requiring K: Clone.
+    range: R,
 }
 
 #[unstable(feature = "btree_extract_if", issue = "70530")]
-impl<K, V, F, A> fmt::Debug for ExtractIf<'_, K, V, F, A>
+impl<K, V, R, F, A> fmt::Debug for ExtractIf<'_, K, V, R, F, A>
 where
     K: fmt::Debug,
     V: fmt::Debug,
@@ -1953,8 +1967,10 @@ where
 }
 
 #[unstable(feature = "btree_extract_if", issue = "70530")]
-impl<K, V, F, A: Allocator + Clone> Iterator for ExtractIf<'_, K, V, F, A>
+impl<K, V, R, F, A: Allocator + Clone> Iterator for ExtractIf<'_, K, V, R, F, A>
 where
+    K: PartialOrd,
+    R: RangeBounds<K>,
     F: FnMut(&K, &mut V) -> bool,
 {
     type Item = (K, V);
@@ -1968,7 +1984,7 @@ where
     }
 }
 
-impl<'a, K, V> ExtractIfInner<'a, K, V> {
+impl<'a, K, V, R> ExtractIfInner<'a, K, V, R> {
     /// Allow Debug implementations to predict the next element.
     pub(super) fn peek(&self) -> Option<(&K, &V)> {
         let edge = self.cur_leaf_edge.as_ref()?;
@@ -1978,10 +1994,22 @@ impl<'a, K, V> ExtractIfInner<'a, K, V> {
     /// Implementation of a typical `ExtractIf::next` method, given the predicate.
     pub(super) fn next<F, A: Allocator + Clone>(&mut self, pred: &mut F, alloc: A) -> Option<(K, V)>
     where
+        K: PartialOrd,
+        R: RangeBounds<K>,
         F: FnMut(&K, &mut V) -> bool,
     {
         while let Ok(mut kv) = self.cur_leaf_edge.take()?.next_kv() {
             let (k, v) = kv.kv_mut();
+
+            // On creation, we navigated directly to the left bound, so we need only check the
+            // right bound here to decide whether to stop.
+            match self.range.end_bound() {
+                Bound::Included(ref end) if (*k).le(end) => (),
+                Bound::Excluded(ref end) if (*k).lt(end) => (),
+                Bound::Unbounded => (),
+                _ => return None,
+            }
+
             if pred(k, v) {
                 *self.length -= 1;
                 let (kv, pos) = kv.remove_kv_tracking(
@@ -2013,7 +2041,13 @@ impl<'a, K, V> ExtractIfInner<'a, K, V> {
 }
 
 #[unstable(feature = "btree_extract_if", issue = "70530")]
-impl<K, V, F> FusedIterator for ExtractIf<'_, K, V, F> where F: FnMut(&K, &mut V) -> bool {}
+impl<K, V, R, F> FusedIterator for ExtractIf<'_, K, V, R, F>
+where
+    K: PartialOrd,
+    R: RangeBounds<K>,
+    F: FnMut(&K, &mut V) -> bool,
+{
+}
 
 #[stable(feature = "btree_range", since = "1.17.0")]
 impl<'a, K, V> Iterator for Range<'a, K, V> {
diff --git a/library/alloc/src/collections/btree/map/tests.rs b/library/alloc/src/collections/btree/map/tests.rs
index 5975134382e..79879d31d3d 100644
--- a/library/alloc/src/collections/btree/map/tests.rs
+++ b/library/alloc/src/collections/btree/map/tests.rs
@@ -944,7 +944,7 @@ mod test_extract_if {
     #[test]
     fn empty() {
         let mut map: BTreeMap<i32, i32> = BTreeMap::new();
-        map.extract_if(|_, _| unreachable!("there's nothing to decide on")).for_each(drop);
+        map.extract_if(.., |_, _| unreachable!("there's nothing to decide on")).for_each(drop);
         assert_eq!(map.height(), None);
         map.check();
     }
@@ -954,7 +954,7 @@ mod test_extract_if {
     fn consumed_keeping_all() {
         let pairs = (0..3).map(|i| (i, i));
         let mut map = BTreeMap::from_iter(pairs);
-        assert!(map.extract_if(|_, _| false).eq(iter::empty()));
+        assert!(map.extract_if(.., |_, _| false).eq(iter::empty()));
         map.check();
     }
 
@@ -963,18 +963,42 @@ mod test_extract_if {
     fn consumed_removing_all() {
         let pairs = (0..3).map(|i| (i, i));
         let mut map = BTreeMap::from_iter(pairs.clone());
-        assert!(map.extract_if(|_, _| true).eq(pairs));
+        assert!(map.extract_if(.., |_, _| true).eq(pairs));
         assert!(map.is_empty());
         map.check();
     }
 
+    #[test]
+    fn consumed_removing_some() {
+        let pairs = (0..3).map(|i| (i, i));
+        let map = BTreeMap::from_iter(pairs);
+        for x in 0..3 {
+            for y in 0..3 {
+                let mut map = map.clone();
+                assert!(map.extract_if(x..y, |_, _| true).eq((x..y).map(|i| (i, i))));
+                for i in 0..3 {
+                    assert_ne!(map.contains_key(&i), (x..y).contains(&i));
+                }
+            }
+        }
+        for x in 0..3 {
+            for y in 0..2 {
+                let mut map = map.clone();
+                assert!(map.extract_if(x..=y, |_, _| true).eq((x..=y).map(|i| (i, i))));
+                for i in 0..3 {
+                    assert_ne!(map.contains_key(&i), (x..=y).contains(&i));
+                }
+            }
+        }
+    }
+
     // Explicitly consumes the iterator and modifies values through it.
     #[test]
     fn mutating_and_keeping() {
         let pairs = (0..3).map(|i| (i, i));
         let mut map = BTreeMap::from_iter(pairs);
         assert!(
-            map.extract_if(|_, v| {
+            map.extract_if(.., |_, v| {
                 *v += 6;
                 false
             })
@@ -991,7 +1015,7 @@ mod test_extract_if {
         let pairs = (0..3).map(|i| (i, i));
         let mut map = BTreeMap::from_iter(pairs);
         assert!(
-            map.extract_if(|_, v| {
+            map.extract_if(.., |_, v| {
                 *v += 6;
                 true
             })
@@ -1005,7 +1029,7 @@ mod test_extract_if {
     fn underfull_keeping_all() {
         let pairs = (0..3).map(|i| (i, i));
         let mut map = BTreeMap::from_iter(pairs);
-        map.extract_if(|_, _| false).for_each(drop);
+        map.extract_if(.., |_, _| false).for_each(drop);
         assert!(map.keys().copied().eq(0..3));
         map.check();
     }
@@ -1015,7 +1039,7 @@ mod test_extract_if {
         let pairs = (0..3).map(|i| (i, i));
         for doomed in 0..3 {
             let mut map = BTreeMap::from_iter(pairs.clone());
-            map.extract_if(|i, _| *i == doomed).for_each(drop);
+            map.extract_if(.., |i, _| *i == doomed).for_each(drop);
             assert_eq!(map.len(), 2);
             map.check();
         }
@@ -1026,7 +1050,7 @@ mod test_extract_if {
         let pairs = (0..3).map(|i| (i, i));
         for sacred in 0..3 {
             let mut map = BTreeMap::from_iter(pairs.clone());
-            map.extract_if(|i, _| *i != sacred).for_each(drop);
+            map.extract_if(.., |i, _| *i != sacred).for_each(drop);
             assert!(map.keys().copied().eq(sacred..=sacred));
             map.check();
         }
@@ -1036,7 +1060,7 @@ mod test_extract_if {
     fn underfull_removing_all() {
         let pairs = (0..3).map(|i| (i, i));
         let mut map = BTreeMap::from_iter(pairs);
-        map.extract_if(|_, _| true).for_each(drop);
+        map.extract_if(.., |_, _| true).for_each(drop);
         assert!(map.is_empty());
         map.check();
     }
@@ -1045,7 +1069,7 @@ mod test_extract_if {
     fn height_0_keeping_all() {
         let pairs = (0..node::CAPACITY).map(|i| (i, i));
         let mut map = BTreeMap::from_iter(pairs);
-        map.extract_if(|_, _| false).for_each(drop);
+        map.extract_if(.., |_, _| false).for_each(drop);
         assert!(map.keys().copied().eq(0..node::CAPACITY));
         map.check();
     }
@@ -1055,7 +1079,7 @@ mod test_extract_if {
         let pairs = (0..node::CAPACITY).map(|i| (i, i));
         for doomed in 0..node::CAPACITY {
             let mut map = BTreeMap::from_iter(pairs.clone());
-            map.extract_if(|i, _| *i == doomed).for_each(drop);
+            map.extract_if(.., |i, _| *i == doomed).for_each(drop);
             assert_eq!(map.len(), node::CAPACITY - 1);
             map.check();
         }
@@ -1066,7 +1090,7 @@ mod test_extract_if {
         let pairs = (0..node::CAPACITY).map(|i| (i, i));
         for sacred in 0..node::CAPACITY {
             let mut map = BTreeMap::from_iter(pairs.clone());
-            map.extract_if(|i, _| *i != sacred).for_each(drop);
+            map.extract_if(.., |i, _| *i != sacred).for_each(drop);
             assert!(map.keys().copied().eq(sacred..=sacred));
             map.check();
         }
@@ -1076,7 +1100,7 @@ mod test_extract_if {
     fn height_0_removing_all() {
         let pairs = (0..node::CAPACITY).map(|i| (i, i));
         let mut map = BTreeMap::from_iter(pairs);
-        map.extract_if(|_, _| true).for_each(drop);
+        map.extract_if(.., |_, _| true).for_each(drop);
         assert!(map.is_empty());
         map.check();
     }
@@ -1084,7 +1108,7 @@ mod test_extract_if {
     #[test]
     fn height_0_keeping_half() {
         let mut map = BTreeMap::from_iter((0..16).map(|i| (i, i)));
-        assert_eq!(map.extract_if(|i, _| *i % 2 == 0).count(), 8);
+        assert_eq!(map.extract_if(.., |i, _| *i % 2 == 0).count(), 8);
         assert_eq!(map.len(), 8);
         map.check();
     }
@@ -1093,7 +1117,7 @@ mod test_extract_if {
     fn height_1_removing_all() {
         let pairs = (0..MIN_INSERTS_HEIGHT_1).map(|i| (i, i));
         let mut map = BTreeMap::from_iter(pairs);
-        map.extract_if(|_, _| true).for_each(drop);
+        map.extract_if(.., |_, _| true).for_each(drop);
         assert!(map.is_empty());
         map.check();
     }
@@ -1103,7 +1127,7 @@ mod test_extract_if {
         let pairs = (0..MIN_INSERTS_HEIGHT_1).map(|i| (i, i));
         for doomed in 0..MIN_INSERTS_HEIGHT_1 {
             let mut map = BTreeMap::from_iter(pairs.clone());
-            map.extract_if(|i, _| *i == doomed).for_each(drop);
+            map.extract_if(.., |i, _| *i == doomed).for_each(drop);
             assert_eq!(map.len(), MIN_INSERTS_HEIGHT_1 - 1);
             map.check();
         }
@@ -1114,7 +1138,7 @@ mod test_extract_if {
         let pairs = (0..MIN_INSERTS_HEIGHT_1).map(|i| (i, i));
         for sacred in 0..MIN_INSERTS_HEIGHT_1 {
             let mut map = BTreeMap::from_iter(pairs.clone());
-            map.extract_if(|i, _| *i != sacred).for_each(drop);
+            map.extract_if(.., |i, _| *i != sacred).for_each(drop);
             assert!(map.keys().copied().eq(sacred..=sacred));
             map.check();
         }
@@ -1125,7 +1149,7 @@ mod test_extract_if {
         let pairs = (0..MIN_INSERTS_HEIGHT_2).map(|i| (i, i));
         for doomed in (0..MIN_INSERTS_HEIGHT_2).step_by(12) {
             let mut map = BTreeMap::from_iter(pairs.clone());
-            map.extract_if(|i, _| *i == doomed).for_each(drop);
+            map.extract_if(.., |i, _| *i == doomed).for_each(drop);
             assert_eq!(map.len(), MIN_INSERTS_HEIGHT_2 - 1);
             map.check();
         }
@@ -1136,7 +1160,7 @@ mod test_extract_if {
         let pairs = (0..MIN_INSERTS_HEIGHT_2).map(|i| (i, i));
         for sacred in (0..MIN_INSERTS_HEIGHT_2).step_by(12) {
             let mut map = BTreeMap::from_iter(pairs.clone());
-            map.extract_if(|i, _| *i != sacred).for_each(drop);
+            map.extract_if(.., |i, _| *i != sacred).for_each(drop);
             assert!(map.keys().copied().eq(sacred..=sacred));
             map.check();
         }
@@ -1146,7 +1170,7 @@ mod test_extract_if {
     fn height_2_removing_all() {
         let pairs = (0..MIN_INSERTS_HEIGHT_2).map(|i| (i, i));
         let mut map = BTreeMap::from_iter(pairs);
-        map.extract_if(|_, _| true).for_each(drop);
+        map.extract_if(.., |_, _| true).for_each(drop);
         assert!(map.is_empty());
         map.check();
     }
@@ -1162,7 +1186,7 @@ mod test_extract_if {
         map.insert(b.spawn(Panic::InDrop), ());
         map.insert(c.spawn(Panic::Never), ());
 
-        catch_unwind(move || map.extract_if(|dummy, _| dummy.query(true)).for_each(drop))
+        catch_unwind(move || map.extract_if(.., |dummy, _| dummy.query(true)).for_each(drop))
             .unwrap_err();
 
         assert_eq!(a.queried(), 1);
@@ -1185,7 +1209,7 @@ mod test_extract_if {
         map.insert(c.spawn(Panic::InQuery), ());
 
         catch_unwind(AssertUnwindSafe(|| {
-            map.extract_if(|dummy, _| dummy.query(true)).for_each(drop)
+            map.extract_if(.., |dummy, _| dummy.query(true)).for_each(drop)
         }))
         .unwrap_err();
 
@@ -1214,7 +1238,7 @@ mod test_extract_if {
         map.insert(c.spawn(Panic::InQuery), ());
 
         {
-            let mut it = map.extract_if(|dummy, _| dummy.query(true));
+            let mut it = map.extract_if(.., |dummy, _| dummy.query(true));
             catch_unwind(AssertUnwindSafe(|| while it.next().is_some() {})).unwrap_err();
             // Iterator behavior after a panic is explicitly unspecified,
             // so this is just the current implementation:
@@ -1658,7 +1682,7 @@ fn assert_sync() {
     }
 
     fn extract_if<T: Sync + Ord>(v: &mut BTreeMap<T, T>) -> impl Sync + '_ {
-        v.extract_if(|_, _| false)
+        v.extract_if(.., |_, _| false)
     }
 
     fn iter<T: Sync>(v: &BTreeMap<T, T>) -> impl Sync + '_ {
@@ -1727,7 +1751,7 @@ fn assert_send() {
     }
 
     fn extract_if<T: Send + Ord>(v: &mut BTreeMap<T, T>) -> impl Send + '_ {
-        v.extract_if(|_, _| false)
+        v.extract_if(.., |_, _| false)
     }
 
     fn iter<T: Send + Sync>(v: &BTreeMap<T, T>) -> impl Send + '_ {
diff --git a/library/alloc/src/collections/btree/set.rs b/library/alloc/src/collections/btree/set.rs
index 343934680b8..780bd8b0dd1 100644
--- a/library/alloc/src/collections/btree/set.rs
+++ b/library/alloc/src/collections/btree/set.rs
@@ -1109,7 +1109,7 @@ impl<T, A: Allocator + Clone> BTreeSet<T, A> {
         T: Ord,
         F: FnMut(&T) -> bool,
     {
-        self.extract_if(|v| !f(v)).for_each(drop);
+        self.extract_if(.., |v| !f(v)).for_each(drop);
     }
 
     /// Moves all elements from `other` into `self`, leaving `other` empty.
@@ -1187,7 +1187,7 @@ impl<T, A: Allocator + Clone> BTreeSet<T, A> {
         BTreeSet { map: self.map.split_off(value) }
     }
 
-    /// Creates an iterator that visits all elements in ascending order and
+    /// Creates an iterator that visits elements in the specified range in ascending order and
     /// uses a closure to determine if an element should be removed.
     ///
     /// If the closure returns `true`, the element is removed from the set and
@@ -1208,18 +1208,25 @@ impl<T, A: Allocator + Clone> BTreeSet<T, A> {
     /// use std::collections::BTreeSet;
     ///
     /// let mut set: BTreeSet<i32> = (0..8).collect();
-    /// let evens: BTreeSet<_> = set.extract_if(|v| v % 2 == 0).collect();
+    /// let evens: BTreeSet<_> = set.extract_if(.., |v| v % 2 == 0).collect();
     /// let odds = set;
     /// assert_eq!(evens.into_iter().collect::<Vec<_>>(), vec![0, 2, 4, 6]);
     /// assert_eq!(odds.into_iter().collect::<Vec<_>>(), vec![1, 3, 5, 7]);
+    ///
+    /// let mut map: BTreeSet<i32> = (0..8).collect();
+    /// let low: BTreeSet<_> = map.extract_if(0..4, |_v| true).collect();
+    /// let high = map;
+    /// assert_eq!(low.into_iter().collect::<Vec<_>>(), [0, 1, 2, 3]);
+    /// assert_eq!(high.into_iter().collect::<Vec<_>>(), [4, 5, 6, 7]);
     /// ```
     #[unstable(feature = "btree_extract_if", issue = "70530")]
-    pub fn extract_if<'a, F>(&'a mut self, pred: F) -> ExtractIf<'a, T, F, A>
+    pub fn extract_if<'a, F, R>(&'a mut self, range: R, pred: F) -> ExtractIf<'a, T, R, F, A>
     where
         T: Ord,
+        R: RangeBounds<T>,
         F: 'a + FnMut(&T) -> bool,
     {
-        let (inner, alloc) = self.map.extract_if_inner();
+        let (inner, alloc) = self.map.extract_if_inner(range);
         ExtractIf { pred, inner, alloc }
     }
 
@@ -1554,17 +1561,18 @@ impl<'a, T, A: Allocator + Clone> IntoIterator for &'a BTreeSet<T, A> {
 pub struct ExtractIf<
     'a,
     T,
+    R,
     F,
     #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator + Clone = Global,
 > {
     pred: F,
-    inner: super::map::ExtractIfInner<'a, T, SetValZST>,
+    inner: super::map::ExtractIfInner<'a, T, SetValZST, R>,
     /// The BTreeMap will outlive this IntoIter so we don't care about drop order for `alloc`.
     alloc: A,
 }
 
 #[unstable(feature = "btree_extract_if", issue = "70530")]
-impl<T, F, A> fmt::Debug for ExtractIf<'_, T, F, A>
+impl<T, R, F, A> fmt::Debug for ExtractIf<'_, T, R, F, A>
 where
     T: fmt::Debug,
     A: Allocator + Clone,
@@ -1577,8 +1585,10 @@ where
 }
 
 #[unstable(feature = "btree_extract_if", issue = "70530")]
-impl<'a, T, F, A: Allocator + Clone> Iterator for ExtractIf<'_, T, F, A>
+impl<'a, T, R, F, A: Allocator + Clone> Iterator for ExtractIf<'_, T, R, F, A>
 where
+    T: PartialOrd,
+    R: RangeBounds<T>,
     F: 'a + FnMut(&T) -> bool,
 {
     type Item = T;
@@ -1595,7 +1605,13 @@ where
 }
 
 #[unstable(feature = "btree_extract_if", issue = "70530")]
-impl<T, F, A: Allocator + Clone> FusedIterator for ExtractIf<'_, T, F, A> where F: FnMut(&T) -> bool {}
+impl<T, R, F, A: Allocator + Clone> FusedIterator for ExtractIf<'_, T, R, F, A>
+where
+    T: PartialOrd,
+    R: RangeBounds<T>,
+    F: FnMut(&T) -> bool,
+{
+}
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T: Ord, A: Allocator + Clone> Extend<T> for BTreeSet<T, A> {
diff --git a/library/alloc/src/collections/btree/set/tests.rs b/library/alloc/src/collections/btree/set/tests.rs
index d538ef707eb..85c9a98c461 100644
--- a/library/alloc/src/collections/btree/set/tests.rs
+++ b/library/alloc/src/collections/btree/set/tests.rs
@@ -368,8 +368,8 @@ fn test_extract_if() {
     let mut x = BTreeSet::from([1]);
     let mut y = BTreeSet::from([1]);
 
-    x.extract_if(|_| true).for_each(drop);
-    y.extract_if(|_| false).for_each(drop);
+    x.extract_if(.., |_| true).for_each(drop);
+    y.extract_if(.., |_| false).for_each(drop);
     assert_eq!(x.len(), 0);
     assert_eq!(y.len(), 1);
 }
@@ -385,7 +385,7 @@ fn test_extract_if_drop_panic_leak() {
     set.insert(b.spawn(Panic::InDrop));
     set.insert(c.spawn(Panic::Never));
 
-    catch_unwind(move || set.extract_if(|dummy| dummy.query(true)).for_each(drop)).ok();
+    catch_unwind(move || set.extract_if(.., |dummy| dummy.query(true)).for_each(drop)).ok();
 
     assert_eq!(a.queried(), 1);
     assert_eq!(b.queried(), 1);
@@ -406,7 +406,7 @@ fn test_extract_if_pred_panic_leak() {
     set.insert(b.spawn(Panic::InQuery));
     set.insert(c.spawn(Panic::InQuery));
 
-    catch_unwind(AssertUnwindSafe(|| set.extract_if(|dummy| dummy.query(true)).for_each(drop)))
+    catch_unwind(AssertUnwindSafe(|| set.extract_if(.., |dummy| dummy.query(true)).for_each(drop)))
         .ok();
 
     assert_eq!(a.queried(), 1);
@@ -605,7 +605,7 @@ fn assert_sync() {
     }
 
     fn extract_if<T: Sync + Ord>(v: &mut BTreeSet<T>) -> impl Sync + '_ {
-        v.extract_if(|_| false)
+        v.extract_if(.., |_| false)
     }
 
     fn difference<T: Sync + Ord>(v: &BTreeSet<T>) -> impl Sync + '_ {
@@ -644,7 +644,7 @@ fn assert_send() {
     }
 
     fn extract_if<T: Send + Ord>(v: &mut BTreeSet<T>) -> impl Send + '_ {
-        v.extract_if(|_| false)
+        v.extract_if(.., |_| false)
     }
 
     fn difference<T: Send + Sync + Ord>(v: &BTreeSet<T>) -> impl Send + '_ {
diff --git a/library/alloctests/benches/btree/map.rs b/library/alloctests/benches/btree/map.rs
index 20f02dc3a96..778065fd965 100644
--- a/library/alloctests/benches/btree/map.rs
+++ b/library/alloctests/benches/btree/map.rs
@@ -386,7 +386,7 @@ pub fn clone_slim_100_and_clear(b: &mut Bencher) {
 #[bench]
 pub fn clone_slim_100_and_drain_all(b: &mut Bencher) {
     let src = slim_map(100);
-    b.iter(|| src.clone().extract_if(|_, _| true).count())
+    b.iter(|| src.clone().extract_if(.., |_, _| true).count())
 }
 
 #[bench]
@@ -394,7 +394,7 @@ pub fn clone_slim_100_and_drain_half(b: &mut Bencher) {
     let src = slim_map(100);
     b.iter(|| {
         let mut map = src.clone();
-        assert_eq!(map.extract_if(|i, _| i % 2 == 0).count(), 100 / 2);
+        assert_eq!(map.extract_if(.., |i, _| i % 2 == 0).count(), 100 / 2);
         assert_eq!(map.len(), 100 / 2);
     })
 }
@@ -457,7 +457,7 @@ pub fn clone_slim_10k_and_clear(b: &mut Bencher) {
 #[bench]
 pub fn clone_slim_10k_and_drain_all(b: &mut Bencher) {
     let src = slim_map(10_000);
-    b.iter(|| src.clone().extract_if(|_, _| true).count())
+    b.iter(|| src.clone().extract_if(.., |_, _| true).count())
 }
 
 #[bench]
@@ -465,7 +465,7 @@ pub fn clone_slim_10k_and_drain_half(b: &mut Bencher) {
     let src = slim_map(10_000);
     b.iter(|| {
         let mut map = src.clone();
-        assert_eq!(map.extract_if(|i, _| i % 2 == 0).count(), 10_000 / 2);
+        assert_eq!(map.extract_if(.., |i, _| i % 2 == 0).count(), 10_000 / 2);
         assert_eq!(map.len(), 10_000 / 2);
     })
 }
@@ -528,7 +528,7 @@ pub fn clone_fat_val_100_and_clear(b: &mut Bencher) {
 #[bench]
 pub fn clone_fat_val_100_and_drain_all(b: &mut Bencher) {
     let src = fat_val_map(100);
-    b.iter(|| src.clone().extract_if(|_, _| true).count())
+    b.iter(|| src.clone().extract_if(.., |_, _| true).count())
 }
 
 #[bench]
@@ -536,7 +536,7 @@ pub fn clone_fat_val_100_and_drain_half(b: &mut Bencher) {
     let src = fat_val_map(100);
     b.iter(|| {
         let mut map = src.clone();
-        assert_eq!(map.extract_if(|i, _| i % 2 == 0).count(), 100 / 2);
+        assert_eq!(map.extract_if(.., |i, _| i % 2 == 0).count(), 100 / 2);
         assert_eq!(map.len(), 100 / 2);
     })
 }
diff --git a/library/alloctests/benches/btree/set.rs b/library/alloctests/benches/btree/set.rs
index 5aa395b4d52..027c86a89a5 100644
--- a/library/alloctests/benches/btree/set.rs
+++ b/library/alloctests/benches/btree/set.rs
@@ -69,7 +69,7 @@ pub fn clone_100_and_clear(b: &mut Bencher) {
 #[bench]
 pub fn clone_100_and_drain_all(b: &mut Bencher) {
     let src = slim_set(100);
-    b.iter(|| src.clone().extract_if(|_| true).count())
+    b.iter(|| src.clone().extract_if(.., |_| true).count())
 }
 
 #[bench]
@@ -77,7 +77,7 @@ pub fn clone_100_and_drain_half(b: &mut Bencher) {
     let src = slim_set(100);
     b.iter(|| {
         let mut set = src.clone();
-        assert_eq!(set.extract_if(|i| i % 2 == 0).count(), 100 / 2);
+        assert_eq!(set.extract_if(.., |i| i % 2 == 0).count(), 100 / 2);
         assert_eq!(set.len(), 100 / 2);
     })
 }
@@ -140,7 +140,7 @@ pub fn clone_10k_and_clear(b: &mut Bencher) {
 #[bench]
 pub fn clone_10k_and_drain_all(b: &mut Bencher) {
     let src = slim_set(10_000);
-    b.iter(|| src.clone().extract_if(|_| true).count())
+    b.iter(|| src.clone().extract_if(.., |_| true).count())
 }
 
 #[bench]
@@ -148,7 +148,7 @@ pub fn clone_10k_and_drain_half(b: &mut Bencher) {
     let src = slim_set(10_000);
     b.iter(|| {
         let mut set = src.clone();
-        assert_eq!(set.extract_if(|i| i % 2 == 0).count(), 10_000 / 2);
+        assert_eq!(set.extract_if(.., |i| i % 2 == 0).count(), 10_000 / 2);
         assert_eq!(set.len(), 10_000 / 2);
     })
 }
diff --git a/library/alloctests/tests/autotraits.rs b/library/alloctests/tests/autotraits.rs
index 6b82deeac8a..ad0a1038596 100644
--- a/library/alloctests/tests/autotraits.rs
+++ b/library/alloctests/tests/autotraits.rs
@@ -1,3 +1,5 @@
+use std::ops::Range;
+
 fn require_sync<T: Sync>(_: T) {}
 fn require_send_sync<T: Send + Sync>(_: T) {}
 
@@ -55,7 +57,13 @@ fn test_btree_map() {
 
     require_send_sync(async {
         let _v = None::<
-            alloc::collections::btree_map::ExtractIf<'_, &u32, &u32, fn(&&u32, &mut &u32) -> bool>,
+            alloc::collections::btree_map::ExtractIf<
+                '_,
+                &u32,
+                &u32,
+                Range<u32>,
+                fn(&&u32, &mut &u32) -> bool,
+            >,
         >;
         async {}.await;
     });
@@ -144,7 +152,9 @@ fn test_btree_set() {
     });
 
     require_send_sync(async {
-        let _v = None::<alloc::collections::btree_set::ExtractIf<'_, &u32, fn(&&u32) -> bool>>;
+        let _v = None::<
+            alloc::collections::btree_set::ExtractIf<'_, &u32, Range<u32>, fn(&&u32) -> bool>,
+        >;
         async {}.await;
     });
 
diff --git a/library/core/src/alloc/layout.rs b/library/core/src/alloc/layout.rs
index e8a03aadc33..380f67f91f9 100644
--- a/library/core/src/alloc/layout.rs
+++ b/library/core/src/alloc/layout.rs
@@ -126,6 +126,7 @@ impl Layout {
     #[rustc_const_stable(feature = "const_alloc_layout_unchecked", since = "1.36.0")]
     #[must_use]
     #[inline]
+    #[track_caller]
     pub const unsafe fn from_size_align_unchecked(size: usize, align: usize) -> Self {
         assert_unsafe_precondition!(
             check_library_ub,
diff --git a/library/core/src/ascii/ascii_char.rs b/library/core/src/ascii/ascii_char.rs
index 48de4f17b1b..0b72b4780f1 100644
--- a/library/core/src/ascii/ascii_char.rs
+++ b/library/core/src/ascii/ascii_char.rs
@@ -503,6 +503,7 @@ impl AsciiChar {
     /// something useful. It might be tightened before stabilization.)
     #[unstable(feature = "ascii_char", issue = "110998")]
     #[inline]
+    #[track_caller]
     pub const unsafe fn digit_unchecked(d: u8) -> Self {
         assert_unsafe_precondition!(
             check_language_ub,
diff --git a/library/core/src/char/convert.rs b/library/core/src/char/convert.rs
index fd17f92f7be..78cd89fefae 100644
--- a/library/core/src/char/convert.rs
+++ b/library/core/src/char/convert.rs
@@ -22,6 +22,7 @@ pub(super) const fn from_u32(i: u32) -> Option<char> {
 #[inline]
 #[must_use]
 #[allow(unnecessary_transmutes)]
+#[track_caller]
 pub(super) const unsafe fn from_u32_unchecked(i: u32) -> char {
     // SAFETY: the caller must guarantee that `i` is a valid char value.
     unsafe {
diff --git a/library/core/src/clone.rs b/library/core/src/clone.rs
index c237ac84cf4..2c0662c9629 100644
--- a/library/core/src/clone.rs
+++ b/library/core/src/clone.rs
@@ -38,7 +38,16 @@
 
 mod uninit;
 
-/// A common trait for the ability to explicitly duplicate an object.
+/// A common trait that allows explicit creation of a duplicate value.
+///
+/// Calling [`clone`] always produces a new value.
+/// However, for types that are references to other data (such as smart pointers or references),
+/// the new value may still point to the same underlying data, rather than duplicating it.
+/// See [`Clone::clone`] for more details.
+///
+/// This distinction is especially important when using `#[derive(Clone)]` on structs containing
+/// smart pointers like `Arc<Mutex<T>>` - the cloned struct will share mutable state with the
+/// original.
 ///
 /// Differs from [`Copy`] in that [`Copy`] is implicit and an inexpensive bit-wise copy, while
 /// `Clone` is always explicit and may or may not be expensive. In order to enforce
@@ -147,7 +156,16 @@ mod uninit;
 #[rustc_diagnostic_item = "Clone"]
 #[rustc_trivial_field_reads]
 pub trait Clone: Sized {
-    /// Returns a copy of the value.
+    /// Returns a duplicate of the value.
+    ///
+    /// Note that what "duplicate" means varies by type:
+    /// - For most types, this creates a deep, independent copy
+    /// - For reference types like `&T`, this creates another reference to the same value
+    /// - For smart pointers like [`Arc`] or [`Rc`], this increments the reference count
+    ///   but still points to the same underlying data
+    ///
+    /// [`Arc`]: ../../std/sync/struct.Arc.html
+    /// [`Rc`]: ../../std/rc/struct.Rc.html
     ///
     /// # Examples
     ///
@@ -157,6 +175,23 @@ pub trait Clone: Sized {
     ///
     /// assert_eq!("Hello", hello.clone());
     /// ```
+    ///
+    /// Example with a reference-counted type:
+    ///
+    /// ```
+    /// use std::sync::{Arc, Mutex};
+    ///
+    /// let data = Arc::new(Mutex::new(vec![1, 2, 3]));
+    /// let data_clone = data.clone(); // Creates another Arc pointing to the same Mutex
+    ///
+    /// {
+    ///     let mut lock = data.lock().unwrap();
+    ///     lock.push(4);
+    /// }
+    ///
+    /// // Changes are visible through the clone because they share the same underlying data
+    /// assert_eq!(*data_clone.lock().unwrap(), vec![1, 2, 3, 4]);
+    /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[must_use = "cloning is often expensive and is not expected to have side effects"]
     // Clone::clone is special because the compiler generates MIR to implement it for some types.
diff --git a/library/core/src/ffi/c_str.rs b/library/core/src/ffi/c_str.rs
index 825402116e5..595cc1fe025 100644
--- a/library/core/src/ffi/c_str.rs
+++ b/library/core/src/ffi/c_str.rs
@@ -207,7 +207,7 @@ impl CStr {
     /// * `ptr` must be [valid] for reads of bytes up to and including the nul terminator.
     ///   This means in particular:
     ///
-    ///     * The entire memory range of this `CStr` must be contained within a single allocated object!
+    ///     * The entire memory range of this `CStr` must be contained within a single allocation!
     ///     * `ptr` must be non-null even for a zero-length cstr.
     ///
     /// * The memory referenced by the returned `CStr` must not be mutated for
@@ -632,6 +632,30 @@ impl CStr {
         // instead of doing it afterwards.
         str::from_utf8(self.to_bytes())
     }
+
+    /// Returns an object that implements [`Display`] for safely printing a [`CStr`] that may
+    /// contain non-Unicode data.
+    ///
+    /// Behaves as if `self` were first lossily converted to a `str`, with invalid UTF-8 presented
+    /// as the Unicode replacement character: �.
+    ///
+    /// [`Display`]: fmt::Display
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(cstr_display)]
+    ///
+    /// let cstr = c"Hello, world!";
+    /// println!("{}", cstr.display());
+    /// ```
+    #[unstable(feature = "cstr_display", issue = "139984")]
+    #[must_use = "this does not display the `CStr`; \
+                  it returns an object that can be displayed"]
+    #[inline]
+    pub fn display(&self) -> impl fmt::Display {
+        crate::bstr::ByteStr::from_bytes(self.to_bytes())
+    }
 }
 
 // `.to_bytes()` representations are compared instead of the inner `[c_char]`s,
diff --git a/library/core/src/hint.rs b/library/core/src/hint.rs
index 8ea9de7e9e5..696d323c66d 100644
--- a/library/core/src/hint.rs
+++ b/library/core/src/hint.rs
@@ -98,7 +98,7 @@ use crate::{intrinsics, ub_checks};
 #[inline]
 #[stable(feature = "unreachable", since = "1.27.0")]
 #[rustc_const_stable(feature = "const_unreachable_unchecked", since = "1.57.0")]
-#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
+#[track_caller]
 pub const unsafe fn unreachable_unchecked() -> ! {
     ub_checks::assert_unsafe_precondition!(
         check_language_ub,
diff --git a/library/core/src/intrinsics/bounds.rs b/library/core/src/intrinsics/bounds.rs
new file mode 100644
index 00000000000..046e191212c
--- /dev/null
+++ b/library/core/src/intrinsics/bounds.rs
@@ -0,0 +1,39 @@
+//! Various traits used to restrict intrinsics to not-completely-wrong types.
+
+/// Types with a built-in dereference operator in runtime MIR,
+/// aka references and raw pointers.
+///
+/// # Safety
+/// Must actually *be* such a type.
+pub unsafe trait BuiltinDeref: Sized {
+    type Pointee: ?Sized;
+}
+
+unsafe impl<T: ?Sized> BuiltinDeref for &mut T {
+    type Pointee = T;
+}
+unsafe impl<T: ?Sized> BuiltinDeref for &T {
+    type Pointee = T;
+}
+unsafe impl<T: ?Sized> BuiltinDeref for *mut T {
+    type Pointee = T;
+}
+unsafe impl<T: ?Sized> BuiltinDeref for *const T {
+    type Pointee = T;
+}
+
+pub trait ChangePointee<U: ?Sized>: BuiltinDeref {
+    type Output;
+}
+impl<'a, T: ?Sized + 'a, U: ?Sized + 'a> ChangePointee<U> for &'a mut T {
+    type Output = &'a mut U;
+}
+impl<'a, T: ?Sized + 'a, U: ?Sized + 'a> ChangePointee<U> for &'a T {
+    type Output = &'a U;
+}
+impl<T: ?Sized, U: ?Sized> ChangePointee<U> for *mut T {
+    type Output = *mut U;
+}
+impl<T: ?Sized, U: ?Sized> ChangePointee<U> for *const T {
+    type Output = *const U;
+}
diff --git a/library/core/src/intrinsics/mod.rs b/library/core/src/intrinsics/mod.rs
index 23bafa778bc..d147cf889cc 100644
--- a/library/core/src/intrinsics/mod.rs
+++ b/library/core/src/intrinsics/mod.rs
@@ -1,7 +1,10 @@
 //! Compiler intrinsics.
 //!
-//! The corresponding definitions are in <https://github.com/rust-lang/rust/blob/master/compiler/rustc_codegen_llvm/src/intrinsic.rs>.
-//! The corresponding const implementations are in <https://github.com/rust-lang/rust/blob/master/compiler/rustc_const_eval/src/interpret/intrinsics.rs>.
+//! These are the imports making intrinsics available to Rust code. The actual implementations live in the compiler.
+//! Some of these intrinsics are lowered to MIR in <https://github.com/rust-lang/rust/blob/master/compiler/rustc_mir_transform/src/lower_intrinsics.rs>.
+//! The remaining intrinsics are implemented for the LLVM backend in <https://github.com/rust-lang/rust/blob/master/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs>
+//! and <https://github.com/rust-lang/rust/blob/master/compiler/rustc_codegen_llvm/src/intrinsic.rs>,
+//! and for const evaluation in <https://github.com/rust-lang/rust/blob/master/compiler/rustc_const_eval/src/interpret/intrinsics.rs>.
 //!
 //! # Const intrinsics
 //!
@@ -20,28 +23,14 @@
 //!
 //! The volatile intrinsics provide operations intended to act on I/O
 //! memory, which are guaranteed to not be reordered by the compiler
-//! across other volatile intrinsics. See the LLVM documentation on
-//! [[volatile]].
-//!
-//! [volatile]: https://llvm.org/docs/LangRef.html#volatile-memory-accesses
+//! across other volatile intrinsics. See [`read_volatile`][ptr::read_volatile]
+//! and [`write_volatile`][ptr::write_volatile].
 //!
 //! # Atomics
 //!
 //! The atomic intrinsics provide common atomic operations on machine
-//! words, with multiple possible memory orderings. They obey the same
-//! semantics as C++11. See the LLVM documentation on [[atomics]].
-//!
-//! [atomics]: https://llvm.org/docs/Atomics.html
-//!
-//! A quick refresher on memory ordering:
-//!
-//! * Acquire - a barrier for acquiring a lock. Subsequent reads and writes
-//!   take place after the barrier.
-//! * Release - a barrier for releasing a lock. Preceding reads and writes
-//!   take place before the barrier.
-//! * Sequentially consistent - sequentially consistent operations are
-//!   guaranteed to happen in order. This is the standard mode for working
-//!   with atomic types and is equivalent to Java's `volatile`.
+//! words, with multiple possible memory orderings. See the
+//! [atomic types][atomic] docs for details.
 //!
 //! # Unwinding
 //!
@@ -61,9 +50,10 @@
 )]
 #![allow(missing_docs)]
 
-use crate::marker::{DiscriminantKind, Tuple};
+use crate::marker::{ConstParamTy, DiscriminantKind, Tuple};
 use crate::ptr;
 
+mod bounds;
 pub mod fallback;
 pub mod mir;
 pub mod simd;
@@ -73,6 +63,20 @@ pub mod simd;
 #[cfg(all(target_has_atomic = "8", target_has_atomic = "32", target_has_atomic = "ptr"))]
 use crate::sync::atomic::{self, AtomicBool, AtomicI32, AtomicIsize, AtomicU32, Ordering};
 
+/// A type for atomic ordering parameters for intrinsics. This is a separate type from
+/// `atomic::Ordering` so that we can make it `ConstParamTy` and fix the values used here without a
+/// risk of leaking that to stable code.
+#[derive(Debug, ConstParamTy, PartialEq, Eq)]
+pub enum AtomicOrdering {
+    // These values must match the compiler's `AtomicOrdering` defined in
+    // `rustc_middle/src/ty/consts/int.rs`!
+    Relaxed = 0,
+    Release = 1,
+    Acquire = 2,
+    AcqRel = 3,
+    SeqCst = 4,
+}
+
 // N.B., these intrinsics take raw pointers because they mutate aliased
 // memory, which is not valid for either `&` or `&mut`.
 
@@ -406,10 +410,20 @@ pub unsafe fn atomic_cxchgweak_seqcst_seqcst<T: Copy>(dst: *mut T, old: T, src:
 /// `T` must be an integer or pointer type.
 ///
 /// The stabilized version of this intrinsic is available on the
+/// [`atomic`] types via the `load` method. For example, [`AtomicBool::load`].
+#[rustc_intrinsic]
+#[rustc_nounwind]
+#[cfg(not(bootstrap))]
+pub unsafe fn atomic_load<T: Copy, const ORD: AtomicOrdering>(src: *const T) -> T;
+/// Loads the current value of the pointer.
+/// `T` must be an integer or pointer type.
+///
+/// The stabilized version of this intrinsic is available on the
 /// [`atomic`] types via the `load` method by passing
 /// [`Ordering::SeqCst`] as the `order`. For example, [`AtomicBool::load`].
 #[rustc_intrinsic]
 #[rustc_nounwind]
+#[cfg(bootstrap)]
 pub unsafe fn atomic_load_seqcst<T: Copy>(src: *const T) -> T;
 /// Loads the current value of the pointer.
 /// `T` must be an integer or pointer type.
@@ -419,6 +433,7 @@ pub unsafe fn atomic_load_seqcst<T: Copy>(src: *const T) -> T;
 /// [`Ordering::Acquire`] as the `order`. For example, [`AtomicBool::load`].
 #[rustc_intrinsic]
 #[rustc_nounwind]
+#[cfg(bootstrap)]
 pub unsafe fn atomic_load_acquire<T: Copy>(src: *const T) -> T;
 /// Loads the current value of the pointer.
 /// `T` must be an integer or pointer type.
@@ -428,6 +443,7 @@ pub unsafe fn atomic_load_acquire<T: Copy>(src: *const T) -> T;
 /// [`Ordering::Relaxed`] as the `order`. For example, [`AtomicBool::load`].
 #[rustc_intrinsic]
 #[rustc_nounwind]
+#[cfg(bootstrap)]
 pub unsafe fn atomic_load_relaxed<T: Copy>(src: *const T) -> T;
 
 /// Stores the value at the specified memory location.
@@ -1707,7 +1723,7 @@ pub const fn needs_drop<T: ?Sized>() -> bool;
 /// # Safety
 ///
 /// If the computed offset is non-zero, then both the starting and resulting pointer must be
-/// either in bounds or at the end of an allocated object. If either pointer is out
+/// either in bounds or at the end of an allocation. If either pointer is out
 /// of bounds or arithmetic overflow occurs then this operation is undefined behavior.
 ///
 /// The stabilized version of this intrinsic is [`pointer::offset`].
@@ -1715,7 +1731,7 @@ pub const fn needs_drop<T: ?Sized>() -> bool;
 #[rustc_intrinsic_const_stable_indirect]
 #[rustc_nounwind]
 #[rustc_intrinsic]
-pub const unsafe fn offset<Ptr, Delta>(dst: Ptr, offset: Delta) -> Ptr;
+pub const unsafe fn offset<Ptr: bounds::BuiltinDeref, Delta>(dst: Ptr, offset: Delta) -> Ptr;
 
 /// Calculates the offset from a pointer, potentially wrapping.
 ///
@@ -1736,6 +1752,33 @@ pub const unsafe fn offset<Ptr, Delta>(dst: Ptr, offset: Delta) -> Ptr;
 #[rustc_intrinsic]
 pub const unsafe fn arith_offset<T>(dst: *const T, offset: isize) -> *const T;
 
+/// Projects to the `index`-th element of `slice_ptr`, as the same kind of pointer
+/// as the slice was provided -- so `&mut [T] → &mut T`, `&[T] → &T`,
+/// `*mut [T] → *mut T`, or `*const [T] → *const T` -- without a bounds check.
+///
+/// This is exposed via `<usize as SliceIndex>::get(_unchecked)(_mut)`,
+/// and isn't intended to be used elsewhere.
+///
+/// Expands in MIR to `{&, &mut, &raw const, &raw mut} (*slice_ptr)[index]`,
+/// depending on the types involved, so no backend support is needed.
+///
+/// # Safety
+///
+/// - `index < PtrMetadata(slice_ptr)`, so the indexing is in-bounds for the slice
+/// - the resulting offsetting is in-bounds of the allocated object, which is
+///   always the case for references, but needs to be upheld manually for pointers
+#[cfg(not(bootstrap))]
+#[rustc_nounwind]
+#[rustc_intrinsic]
+pub const unsafe fn slice_get_unchecked<
+    ItemPtr: bounds::ChangePointee<[T], Pointee = T, Output = SlicePtr>,
+    SlicePtr,
+    T,
+>(
+    slice_ptr: SlicePtr,
+    index: usize,
+) -> ItemPtr;
+
 /// Masks out bits of the pointer according to a mask.
 ///
 /// Note that, unlike most intrinsics, this is safe to call;
@@ -2197,28 +2240,28 @@ pub unsafe fn fmuladdf128(a: f128, b: f128, c: f128) -> f128;
 /// [`f16::floor`](../../std/primitive.f16.html#method.floor)
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn floorf16(x: f16) -> f16;
+pub const unsafe fn floorf16(x: f16) -> f16;
 /// Returns the largest integer less than or equal to an `f32`.
 ///
 /// The stabilized version of this intrinsic is
 /// [`f32::floor`](../../std/primitive.f32.html#method.floor)
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn floorf32(x: f32) -> f32;
+pub const unsafe fn floorf32(x: f32) -> f32;
 /// Returns the largest integer less than or equal to an `f64`.
 ///
 /// The stabilized version of this intrinsic is
 /// [`f64::floor`](../../std/primitive.f64.html#method.floor)
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn floorf64(x: f64) -> f64;
+pub const unsafe fn floorf64(x: f64) -> f64;
 /// Returns the largest integer less than or equal to an `f128`.
 ///
 /// The stabilized version of this intrinsic is
 /// [`f128::floor`](../../std/primitive.f128.html#method.floor)
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn floorf128(x: f128) -> f128;
+pub const unsafe fn floorf128(x: f128) -> f128;
 
 /// Returns the smallest integer greater than or equal to an `f16`.
 ///
@@ -2226,28 +2269,28 @@ pub unsafe fn floorf128(x: f128) -> f128;
 /// [`f16::ceil`](../../std/primitive.f16.html#method.ceil)
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn ceilf16(x: f16) -> f16;
+pub const unsafe fn ceilf16(x: f16) -> f16;
 /// Returns the smallest integer greater than or equal to an `f32`.
 ///
 /// The stabilized version of this intrinsic is
 /// [`f32::ceil`](../../std/primitive.f32.html#method.ceil)
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn ceilf32(x: f32) -> f32;
+pub const unsafe fn ceilf32(x: f32) -> f32;
 /// Returns the smallest integer greater than or equal to an `f64`.
 ///
 /// The stabilized version of this intrinsic is
 /// [`f64::ceil`](../../std/primitive.f64.html#method.ceil)
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn ceilf64(x: f64) -> f64;
+pub const unsafe fn ceilf64(x: f64) -> f64;
 /// Returns the smallest integer greater than or equal to an `f128`.
 ///
 /// The stabilized version of this intrinsic is
 /// [`f128::ceil`](../../std/primitive.f128.html#method.ceil)
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn ceilf128(x: f128) -> f128;
+pub const unsafe fn ceilf128(x: f128) -> f128;
 
 /// Returns the integer part of an `f16`.
 ///
@@ -2255,28 +2298,28 @@ pub unsafe fn ceilf128(x: f128) -> f128;
 /// [`f16::trunc`](../../std/primitive.f16.html#method.trunc)
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn truncf16(x: f16) -> f16;
+pub const unsafe fn truncf16(x: f16) -> f16;
 /// Returns the integer part of an `f32`.
 ///
 /// The stabilized version of this intrinsic is
 /// [`f32::trunc`](../../std/primitive.f32.html#method.trunc)
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn truncf32(x: f32) -> f32;
+pub const unsafe fn truncf32(x: f32) -> f32;
 /// Returns the integer part of an `f64`.
 ///
 /// The stabilized version of this intrinsic is
 /// [`f64::trunc`](../../std/primitive.f64.html#method.trunc)
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn truncf64(x: f64) -> f64;
+pub const unsafe fn truncf64(x: f64) -> f64;
 /// Returns the integer part of an `f128`.
 ///
 /// The stabilized version of this intrinsic is
 /// [`f128::trunc`](../../std/primitive.f128.html#method.trunc)
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn truncf128(x: f128) -> f128;
+pub const unsafe fn truncf128(x: f128) -> f128;
 
 /// Returns the nearest integer to an `f16`. Rounds half-way cases to the number with an even
 /// least significant digit.
@@ -2285,7 +2328,7 @@ pub unsafe fn truncf128(x: f128) -> f128;
 /// [`f16::round_ties_even`](../../std/primitive.f16.html#method.round_ties_even)
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub fn round_ties_even_f16(x: f16) -> f16;
+pub const fn round_ties_even_f16(x: f16) -> f16;
 
 /// Returns the nearest integer to an `f32`. Rounds half-way cases to the number with an even
 /// least significant digit.
@@ -2294,13 +2337,7 @@ pub fn round_ties_even_f16(x: f16) -> f16;
 /// [`f32::round_ties_even`](../../std/primitive.f32.html#method.round_ties_even)
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub fn round_ties_even_f32(x: f32) -> f32;
-
-/// Provided for compatibility with stdarch. DO NOT USE.
-#[inline(always)]
-pub unsafe fn rintf32(x: f32) -> f32 {
-    round_ties_even_f32(x)
-}
+pub const fn round_ties_even_f32(x: f32) -> f32;
 
 /// Returns the nearest integer to an `f64`. Rounds half-way cases to the number with an even
 /// least significant digit.
@@ -2309,13 +2346,7 @@ pub unsafe fn rintf32(x: f32) -> f32 {
 /// [`f64::round_ties_even`](../../std/primitive.f64.html#method.round_ties_even)
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub fn round_ties_even_f64(x: f64) -> f64;
-
-/// Provided for compatibility with stdarch. DO NOT USE.
-#[inline(always)]
-pub unsafe fn rintf64(x: f64) -> f64 {
-    round_ties_even_f64(x)
-}
+pub const fn round_ties_even_f64(x: f64) -> f64;
 
 /// Returns the nearest integer to an `f128`. Rounds half-way cases to the number with an even
 /// least significant digit.
@@ -2324,7 +2355,7 @@ pub unsafe fn rintf64(x: f64) -> f64 {
 /// [`f128::round_ties_even`](../../std/primitive.f128.html#method.round_ties_even)
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub fn round_ties_even_f128(x: f128) -> f128;
+pub const fn round_ties_even_f128(x: f128) -> f128;
 
 /// Returns the nearest integer to an `f16`. Rounds half-way cases away from zero.
 ///
@@ -2332,28 +2363,28 @@ pub fn round_ties_even_f128(x: f128) -> f128;
 /// [`f16::round`](../../std/primitive.f16.html#method.round)
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn roundf16(x: f16) -> f16;
+pub const unsafe fn roundf16(x: f16) -> f16;
 /// Returns the nearest integer to an `f32`. Rounds half-way cases away from zero.
 ///
 /// The stabilized version of this intrinsic is
 /// [`f32::round`](../../std/primitive.f32.html#method.round)
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn roundf32(x: f32) -> f32;
+pub const unsafe fn roundf32(x: f32) -> f32;
 /// Returns the nearest integer to an `f64`. Rounds half-way cases away from zero.
 ///
 /// The stabilized version of this intrinsic is
 /// [`f64::round`](../../std/primitive.f64.html#method.round)
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn roundf64(x: f64) -> f64;
+pub const unsafe fn roundf64(x: f64) -> f64;
 /// Returns the nearest integer to an `f128`. Rounds half-way cases away from zero.
 ///
 /// The stabilized version of this intrinsic is
 /// [`f128::round`](../../std/primitive.f128.html#method.round)
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn roundf128(x: f128) -> f128;
+pub const unsafe fn roundf128(x: f128) -> f128;
 
 /// Float addition that allows optimizations based on algebraic rules.
 /// May assume inputs are finite.
@@ -2634,7 +2665,7 @@ pub const fn three_way_compare<T: Copy>(lhs: T, rhss: T) -> crate::cmp::Ordering
 #[rustc_const_unstable(feature = "disjoint_bitor", issue = "135758")]
 #[rustc_nounwind]
 #[rustc_intrinsic]
-#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
+#[track_caller]
 #[miri::intrinsic_fallback_is_spec] // the fallbacks all `assume` to tell Miri
 pub const unsafe fn disjoint_bitor<T: ~const fallback::DisjointBitOr>(a: T, b: T) -> T {
     // SAFETY: same preconditions as this function.
@@ -3572,18 +3603,9 @@ pub const fn type_id<T: ?Sized + 'static>() -> u128;
 #[unstable(feature = "core_intrinsics", issue = "none")]
 #[rustc_intrinsic_const_stable_indirect]
 #[rustc_intrinsic]
-pub const fn aggregate_raw_ptr<P: AggregateRawPtr<D, Metadata = M>, D, M>(data: D, meta: M) -> P;
-
-#[unstable(feature = "core_intrinsics", issue = "none")]
-pub trait AggregateRawPtr<D> {
-    type Metadata: Copy;
-}
-impl<P: ?Sized, T: ptr::Thin> AggregateRawPtr<*const T> for *const P {
-    type Metadata = <P as ptr::Pointee>::Metadata;
-}
-impl<P: ?Sized, T: ptr::Thin> AggregateRawPtr<*mut T> for *mut P {
-    type Metadata = <P as ptr::Pointee>::Metadata;
-}
+pub const fn aggregate_raw_ptr<P: bounds::BuiltinDeref, D, M>(data: D, meta: M) -> P
+where
+    <P as bounds::BuiltinDeref>::Pointee: ptr::Pointee<Metadata = M>;
 
 /// Lowers in MIR to `Rvalue::UnaryOp` with `UnOp::PtrMetadata`.
 ///
diff --git a/library/core/src/iter/mod.rs b/library/core/src/iter/mod.rs
index d62a445d704..b85841295da 100644
--- a/library/core/src/iter/mod.rs
+++ b/library/core/src/iter/mod.rs
@@ -420,6 +420,8 @@ pub use self::adapters::{Intersperse, IntersperseWith};
     issue = "42168"
 )]
 pub use self::range::Step;
+#[unstable(feature = "iter_macro", issue = "none", reason = "generators are unstable")]
+pub use self::sources::iter;
 #[stable(feature = "iter_empty", since = "1.2.0")]
 pub use self::sources::{Empty, empty};
 #[unstable(
diff --git a/library/core/src/iter/sources.rs b/library/core/src/iter/sources.rs
index 1eb4367b183..fd9330201ff 100644
--- a/library/core/src/iter/sources.rs
+++ b/library/core/src/iter/sources.rs
@@ -1,6 +1,7 @@
 mod empty;
 mod from_coroutine;
 mod from_fn;
+mod generator;
 mod once;
 mod once_with;
 mod repeat;
@@ -18,6 +19,8 @@ pub use self::empty::{Empty, empty};
 pub use self::from_coroutine::{FromCoroutine, from_coroutine};
 #[stable(feature = "iter_from_fn", since = "1.34.0")]
 pub use self::from_fn::{FromFn, from_fn};
+#[unstable(feature = "iter_macro", issue = "none", reason = "generators are unstable")]
+pub use self::generator::iter;
 #[stable(feature = "iter_once", since = "1.2.0")]
 pub use self::once::{Once, once};
 #[stable(feature = "iter_once_with", since = "1.43.0")]
diff --git a/library/core/src/iter/sources/generator.rs b/library/core/src/iter/sources/generator.rs
new file mode 100644
index 00000000000..c94232e09eb
--- /dev/null
+++ b/library/core/src/iter/sources/generator.rs
@@ -0,0 +1,29 @@
+/// Creates a new closure that returns an iterator where each iteration steps the given
+/// generator to the next `yield` statement.
+///
+/// Similar to [`iter::from_fn`], but allows arbitrary control flow.
+///
+/// [`iter::from_fn`]: crate::iter::from_fn
+///
+/// # Examples
+///
+/// ```
+/// #![feature(iter_macro, coroutines)]
+/// # #[cfg(not(bootstrap))]
+/// # {
+///
+/// let it = std::iter::iter!{|| {
+///     yield 1;
+///     yield 2;
+///     yield 3;
+/// } }();
+/// let v: Vec<_> = it.collect();
+/// assert_eq!(v, [1, 2, 3]);
+/// # }
+/// ```
+#[unstable(feature = "iter_macro", issue = "none", reason = "generators are unstable")]
+#[allow_internal_unstable(coroutines, iter_from_coroutine)]
+#[cfg_attr(not(bootstrap), rustc_builtin_macro)]
+pub macro iter($($t:tt)*) {
+    /* compiler-builtin */
+}
diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs
index c49513f7a6d..989ab80b77d 100644
--- a/library/core/src/lib.rs
+++ b/library/core/src/lib.rs
@@ -225,10 +225,11 @@ pub mod assert_matches {
 
 // We don't export this through #[macro_export] for now, to avoid breakage.
 #[unstable(feature = "autodiff", issue = "124509")]
+#[cfg(not(bootstrap))]
 /// Unstable module containing the unstable `autodiff` macro.
 pub mod autodiff {
     #[unstable(feature = "autodiff", issue = "124509")]
-    pub use crate::macros::builtin::autodiff;
+    pub use crate::macros::builtin::{autodiff_forward, autodiff_reverse};
 }
 
 #[unstable(feature = "contracts", issue = "128044")]
diff --git a/library/core/src/macros/mod.rs b/library/core/src/macros/mod.rs
index 4742add0957..e70a1dab6e9 100644
--- a/library/core/src/macros/mod.rs
+++ b/library/core/src/macros/mod.rs
@@ -1519,20 +1519,41 @@ pub(crate) mod builtin {
         ($file:expr $(,)?) => {{ /* compiler built-in */ }};
     }
 
-    /// Automatic Differentiation macro which allows generating a new function to compute
-    /// the derivative of a given function. It may only be applied to a function.
-    /// The expected usage syntax is
-    /// `#[autodiff(NAME, MODE, INPUT_ACTIVITIES, OUTPUT_ACTIVITY)]`
-    /// where:
-    /// NAME is a string that represents a valid function name.
-    /// MODE is any of Forward, Reverse, ForwardFirst, ReverseFirst.
-    /// INPUT_ACTIVITIES consists of one valid activity for each input parameter.
-    /// OUTPUT_ACTIVITY must not be set if we implicitly return nothing (or explicitly return
-    /// `-> ()`). Otherwise it must be set to one of the allowed activities.
+    /// This macro uses forward-mode automatic differentiation to generate a new function.
+    /// It may only be applied to a function. The new function will compute the derivative
+    /// of the function to which the macro was applied.
+    ///
+    /// The expected usage syntax is:
+    /// `#[autodiff_forward(NAME, INPUT_ACTIVITIES, OUTPUT_ACTIVITY)]`
+    ///
+    /// - `NAME`: A string that represents a valid function name.
+    /// - `INPUT_ACTIVITIES`: Specifies one valid activity for each input parameter.
+    /// - `OUTPUT_ACTIVITY`: Must not be set if the function implicitly returns nothing
+    ///   (or explicitly returns `-> ()`). Otherwise, it must be set to one of the allowed activities.
+    #[unstable(feature = "autodiff", issue = "124509")]
+    #[allow_internal_unstable(rustc_attrs)]
+    #[rustc_builtin_macro]
+    #[cfg(not(bootstrap))]
+    pub macro autodiff_forward($item:item) {
+        /* compiler built-in */
+    }
+
+    /// This macro uses reverse-mode automatic differentiation to generate a new function.
+    /// It may only be applied to a function. The new function will compute the derivative
+    /// of the function to which the macro was applied.
+    ///
+    /// The expected usage syntax is:
+    /// `#[autodiff_reverse(NAME, INPUT_ACTIVITIES, OUTPUT_ACTIVITY)]`
+    ///
+    /// - `NAME`: A string that represents a valid function name.
+    /// - `INPUT_ACTIVITIES`: Specifies one valid activity for each input parameter.
+    /// - `OUTPUT_ACTIVITY`: Must not be set if the function implicitly returns nothing
+    ///   (or explicitly returns `-> ()`). Otherwise, it must be set to one of the allowed activities.
     #[unstable(feature = "autodiff", issue = "124509")]
     #[allow_internal_unstable(rustc_attrs)]
     #[rustc_builtin_macro]
-    pub macro autodiff($item:item) {
+    #[cfg(not(bootstrap))]
+    pub macro autodiff_reverse($item:item) {
         /* compiler built-in */
     }
 
diff --git a/library/core/src/marker.rs b/library/core/src/marker.rs
index 700fb0f386e..9991b76cd0a 100644
--- a/library/core/src/marker.rs
+++ b/library/core/src/marker.rs
@@ -200,7 +200,7 @@ pub trait Unsize<T: ?Sized> {
 ///
 /// Constants are only allowed as patterns if (a) their type implements
 /// `PartialEq`, and (b) interpreting the value of the constant as a pattern
-/// is equialent to calling `PartialEq`. This ensures that constants used as
+/// is equivalent to calling `PartialEq`. This ensures that constants used as
 /// patterns cannot expose implementation details in an unexpected way or
 /// cause semver hazards.
 ///
diff --git a/library/core/src/marker/variance.rs b/library/core/src/marker/variance.rs
index 235f8a3bb79..f9638fea225 100644
--- a/library/core/src/marker/variance.rs
+++ b/library/core/src/marker/variance.rs
@@ -131,6 +131,8 @@ phantom_lifetime! {
     ///
     /// [1]: https://doc.rust-lang.org/stable/reference/subtyping.html#variance
     ///
+    /// Note: If `'a` is otherwise contravariant or invariant, the resulting type is invariant.
+    ///
     /// ## Layout
     ///
     /// For all `'a`, the following are guaranteed:
@@ -146,6 +148,8 @@ phantom_lifetime! {
     ///
     /// [1]: https://doc.rust-lang.org/stable/reference/subtyping.html#variance
     ///
+    /// Note: If `'a` is otherwise covariant or invariant, the resulting type is invariant.
+    ///
     /// ## Layout
     ///
     /// For all `'a`, the following are guaranteed:
@@ -180,6 +184,8 @@ phantom_type! {
     ///
     /// [1]: https://doc.rust-lang.org/stable/reference/subtyping.html#variance
     ///
+    /// Note: If `T` is otherwise contravariant or invariant, the resulting type is invariant.
+    ///
     /// ## Layout
     ///
     /// For all `T`, the following are guaranteed:
@@ -196,6 +202,8 @@ phantom_type! {
     ///
     /// [1]: https://doc.rust-lang.org/stable/reference/subtyping.html#variance
     ///
+    /// Note: If `T` is otherwise covariant or invariant, the resulting type is invariant.
+    ///
     /// ## Layout
     ///
     /// For all `T`, the following are guaranteed:
diff --git a/library/core/src/mem/manually_drop.rs b/library/core/src/mem/manually_drop.rs
index 7d519384e37..02bb8179293 100644
--- a/library/core/src/mem/manually_drop.rs
+++ b/library/core/src/mem/manually_drop.rs
@@ -84,7 +84,7 @@ use crate::ptr;
 /// use std::mem::ManuallyDrop;
 ///
 /// pub struct BadOption<T> {
-///     // Invariant: Has been dropped iff `is_some` is false.
+///     // Invariant: Has been dropped if `is_some` is false.
 ///     value: ManuallyDrop<T>,
 ///     is_some: bool,
 /// }
diff --git a/library/core/src/num/dec2flt/mod.rs b/library/core/src/num/dec2flt/mod.rs
index abad7acb104..1844cd98082 100644
--- a/library/core/src/num/dec2flt/mod.rs
+++ b/library/core/src/num/dec2flt/mod.rs
@@ -58,7 +58,7 @@
 //!
 //! There are unit tests but they are woefully inadequate at ensuring correctness, they only cover
 //! a small percentage of possible errors. Far more extensive tests are located in the directory
-//! `src/etc/test-float-parse` as a Rust program.
+//! `src/tools/test-float-parse` as a Rust program.
 //!
 //! A note on integer overflow: Many parts of this file perform arithmetic with the decimal
 //! exponent `e`. Primarily, we shift the decimal point around: Before the first decimal digit,
diff --git a/library/core/src/num/f128.rs b/library/core/src/num/f128.rs
index 0c2c4155d66..58de62a8be8 100644
--- a/library/core/src/num/f128.rs
+++ b/library/core/src/num/f128.rs
@@ -171,6 +171,7 @@ impl f128 {
     /// [Machine epsilon]: https://en.wikipedia.org/wiki/Machine_epsilon
     /// [`MANTISSA_DIGITS`]: f128::MANTISSA_DIGITS
     #[unstable(feature = "f128", issue = "116909")]
+    #[rustc_diagnostic_item = "f128_epsilon"]
     pub const EPSILON: f128 = 1.92592994438723585305597794258492732e-34_f128;
 
     /// Smallest finite `f128` value.
@@ -1447,8 +1448,10 @@ impl f128 {
     #[inline]
     #[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 fn floor(self) -> f128 {
+    pub const fn floor(self) -> f128 {
         // SAFETY: intrinsic with no preconditions
         unsafe { intrinsics::floorf128(self) }
     }
@@ -1477,8 +1480,10 @@ impl f128 {
     #[doc(alias = "ceiling")]
     #[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 fn ceil(self) -> f128 {
+    pub const fn ceil(self) -> f128 {
         // SAFETY: intrinsic with no preconditions
         unsafe { intrinsics::ceilf128(self) }
     }
@@ -1513,8 +1518,10 @@ impl f128 {
     #[inline]
     #[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 fn round(self) -> f128 {
+    pub const fn round(self) -> f128 {
         // SAFETY: intrinsic with no preconditions
         unsafe { intrinsics::roundf128(self) }
     }
@@ -1547,8 +1554,10 @@ impl f128 {
     #[inline]
     #[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 fn round_ties_even(self) -> f128 {
+    pub const fn round_ties_even(self) -> f128 {
         intrinsics::round_ties_even_f128(self)
     }
 
@@ -1579,8 +1588,10 @@ impl f128 {
     #[doc(alias = "truncate")]
     #[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 fn trunc(self) -> f128 {
+    pub const fn trunc(self) -> f128 {
         // SAFETY: intrinsic with no preconditions
         unsafe { intrinsics::truncf128(self) }
     }
@@ -1610,8 +1621,10 @@ impl f128 {
     #[inline]
     #[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 fn fract(self) -> f128 {
+    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 1a859f2277f..45f402d4967 100644
--- a/library/core/src/num/f16.rs
+++ b/library/core/src/num/f16.rs
@@ -168,6 +168,7 @@ impl f16 {
     /// [Machine epsilon]: https://en.wikipedia.org/wiki/Machine_epsilon
     /// [`MANTISSA_DIGITS`]: f16::MANTISSA_DIGITS
     #[unstable(feature = "f16", issue = "116909")]
+    #[rustc_diagnostic_item = "f16_epsilon"]
     pub const EPSILON: f16 = 9.7656e-4_f16;
 
     /// Smallest finite `f16` value.
@@ -1423,8 +1424,10 @@ impl f16 {
     #[inline]
     #[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 fn floor(self) -> f16 {
+    pub const fn floor(self) -> f16 {
         // SAFETY: intrinsic with no preconditions
         unsafe { intrinsics::floorf16(self) }
     }
@@ -1453,8 +1456,10 @@ impl f16 {
     #[doc(alias = "ceiling")]
     #[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 fn ceil(self) -> f16 {
+    pub const fn ceil(self) -> f16 {
         // SAFETY: intrinsic with no preconditions
         unsafe { intrinsics::ceilf16(self) }
     }
@@ -1489,8 +1494,10 @@ impl f16 {
     #[inline]
     #[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 fn round(self) -> f16 {
+    pub const fn round(self) -> f16 {
         // SAFETY: intrinsic with no preconditions
         unsafe { intrinsics::roundf16(self) }
     }
@@ -1523,8 +1530,10 @@ impl f16 {
     #[inline]
     #[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 fn round_ties_even(self) -> f16 {
+    pub const fn round_ties_even(self) -> f16 {
         intrinsics::round_ties_even_f16(self)
     }
 
@@ -1555,8 +1564,10 @@ impl f16 {
     #[doc(alias = "truncate")]
     #[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 fn trunc(self) -> f16 {
+    pub const fn trunc(self) -> f16 {
         // SAFETY: intrinsic with no preconditions
         unsafe { intrinsics::truncf16(self) }
     }
@@ -1586,8 +1597,10 @@ impl f16 {
     #[inline]
     #[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 fn fract(self) -> f16 {
+    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 bf67b6ed05a..bf923d4070a 100644
--- a/library/core/src/num/f32.rs
+++ b/library/core/src/num/f32.rs
@@ -999,6 +999,7 @@ impl f32 {
                 target_arch = "x86_64",
                 target_arch = "aarch64",
                 all(any(target_arch = "riscv32", target_arch = "riscv64"), target_feature = "d"),
+                all(target_arch = "loongarch64", target_feature = "d"),
                 all(target_arch = "arm", target_feature = "vfp2"),
                 target_arch = "wasm32",
                 target_arch = "wasm64",
@@ -1590,8 +1591,9 @@ 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 fn floor(x: f32) -> f32 {
+    pub const fn floor(x: f32) -> f32 {
         // SAFETY: intrinsic with no preconditions
         unsafe { intrinsics::floorf32(x) }
     }
@@ -1620,7 +1622,8 @@ 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")]
-    pub fn ceil(x: f32) -> f32 {
+    #[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) }
     }
@@ -1654,7 +1657,8 @@ 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"]
-    pub fn round(x: f32) -> f32 {
+    #[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) }
     }
@@ -1687,7 +1691,8 @@ 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"]
-    pub fn round_ties_even(x: f32) -> f32 {
+    #[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)
     }
 
@@ -1717,7 +1722,8 @@ 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")]
-    pub fn trunc(x: f32) -> f32 {
+    #[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) }
     }
@@ -1746,8 +1752,9 @@ 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 fn fract(x: f32) -> f32 {
+    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 8fbf2cffbaf..be933cfa41a 100644
--- a/library/core/src/num/f64.rs
+++ b/library/core/src/num/f64.rs
@@ -943,7 +943,7 @@ impl f64 {
     /// This returns NaN when *either* argument is NaN, as opposed to
     /// [`f64::max`] which only returns NaN when *both* arguments are NaN.
     ///
-    /// ```
+    /// ```ignore-arm-unknown-linux-gnueabihf (see https://github.com/rust-lang/rust/issues/141087)
     /// #![feature(float_minimum_maximum)]
     /// let x = 1.0_f64;
     /// let y = 2.0_f64;
@@ -970,7 +970,7 @@ impl f64 {
     /// This returns NaN when *either* argument is NaN, as opposed to
     /// [`f64::min`] which only returns NaN when *both* arguments are NaN.
     ///
-    /// ```
+    /// ```ignore-arm-unknown-linux-gnueabihf (see https://github.com/rust-lang/rust/issues/141087)
     /// #![feature(float_minimum_maximum)]
     /// let x = 1.0_f64;
     /// let y = 2.0_f64;
@@ -1589,8 +1589,9 @@ 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 fn floor(x: f64) -> f64 {
+    pub const fn floor(x: f64) -> f64 {
         // SAFETY: intrinsic with no preconditions
         unsafe { intrinsics::floorf64(x) }
     }
@@ -1618,8 +1619,9 @@ 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 fn ceil(x: f64) -> f64 {
+    pub const fn ceil(x: f64) -> f64 {
         // SAFETY: intrinsic with no preconditions
         unsafe { intrinsics::ceilf64(x) }
     }
@@ -1652,8 +1654,9 @@ 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 fn round(x: f64) -> f64 {
+    pub const fn round(x: f64) -> f64 {
         // SAFETY: intrinsic with no preconditions
         unsafe { intrinsics::roundf64(x) }
     }
@@ -1685,8 +1688,9 @@ 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 fn round_ties_even(x: f64) -> f64 {
+    pub const fn round_ties_even(x: f64) -> f64 {
         intrinsics::round_ties_even_f64(x)
     }
 
@@ -1715,8 +1719,9 @@ 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 fn trunc(x: f64) -> f64 {
+    pub const fn trunc(x: f64) -> f64 {
         // SAFETY: intrinsic with no preconditions
         unsafe { intrinsics::truncf64(x) }
     }
@@ -1745,8 +1750,9 @@ 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 fn fract(x: f64) -> f64 {
+    pub const fn fract(x: f64) -> f64 {
         x - trunc(x)
     }
 
diff --git a/library/core/src/num/int_macros.rs b/library/core/src/num/int_macros.rs
index 84e1482ed31..65560f63c18 100644
--- a/library/core/src/num/int_macros.rs
+++ b/library/core/src/num/int_macros.rs
@@ -4,7 +4,7 @@ macro_rules! int_impl {
         ActualT = $ActualT:ident,
         UnsignedT = $UnsignedT:ty,
 
-        // There are all for use *only* in doc comments.
+        // These are all for use *only* in doc comments.
         // As such, they're all passed as literals -- passing them as a string
         // literal is fine if they need to be multiple code tokens.
         // In non-comments, use the associated constants rather than these.
@@ -555,7 +555,7 @@ macro_rules! int_impl {
         #[must_use = "this returns the result of the operation, \
                       without modifying the original"]
         #[inline(always)]
-        #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
+        #[track_caller]
         pub const unsafe fn unchecked_add(self, rhs: Self) -> Self {
             assert_unsafe_precondition!(
                 check_language_ub,
@@ -705,7 +705,7 @@ macro_rules! int_impl {
         #[must_use = "this returns the result of the operation, \
                       without modifying the original"]
         #[inline(always)]
-        #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
+        #[track_caller]
         pub const unsafe fn unchecked_sub(self, rhs: Self) -> Self {
             assert_unsafe_precondition!(
                 check_language_ub,
@@ -855,7 +855,7 @@ macro_rules! int_impl {
         #[must_use = "this returns the result of the operation, \
                       without modifying the original"]
         #[inline(always)]
-        #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
+        #[track_caller]
         pub const unsafe fn unchecked_mul(self, rhs: Self) -> Self {
             assert_unsafe_precondition!(
                 check_language_ub,
@@ -1018,6 +1018,110 @@ macro_rules! int_impl {
             if b { overflow_panic::div() } else { a }
         }
 
+        /// Checked integer division without remainder. Computes `self / rhs`,
+        /// returning `None` if `rhs == 0`, the division results in overflow,
+        /// or `self % rhs != 0`.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        /// #![feature(exact_div)]
+        #[doc = concat!("assert_eq!((", stringify!($SelfT), "::MIN + 1).checked_exact_div(-1), Some(", stringify!($Max), "));")]
+        #[doc = concat!("assert_eq!((-5", stringify!($SelfT), ").checked_exact_div(2), None);")]
+        #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MIN.checked_exact_div(-1), None);")]
+        #[doc = concat!("assert_eq!((1", stringify!($SelfT), ").checked_exact_div(0), None);")]
+        /// ```
+        #[unstable(
+            feature = "exact_div",
+            issue = "139911",
+        )]
+        #[must_use = "this returns the result of the operation, \
+                      without modifying the original"]
+        #[inline]
+        pub const fn checked_exact_div(self, rhs: Self) -> Option<Self> {
+            if intrinsics::unlikely(rhs == 0 || ((self == Self::MIN) && (rhs == -1))) {
+                None
+            } else {
+                // SAFETY: division by zero and overflow are checked above
+                unsafe {
+                    if intrinsics::unlikely(intrinsics::unchecked_rem(self, rhs) != 0) {
+                        None
+                    } else {
+                        Some(intrinsics::exact_div(self, rhs))
+                    }
+                }
+            }
+        }
+
+        /// Checked integer division without remainder. Computes `self / rhs`.
+        ///
+        /// # Panics
+        ///
+        /// This function will panic  if `rhs == 0`, the division results in overflow,
+        /// or `self % rhs != 0`.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        /// #![feature(exact_div)]
+        #[doc = concat!("assert_eq!(64", stringify!($SelfT), ".exact_div(2), 32);")]
+        #[doc = concat!("assert_eq!(64", stringify!($SelfT), ".exact_div(32), 2);")]
+        #[doc = concat!("assert_eq!((", stringify!($SelfT), "::MIN + 1).exact_div(-1), ", stringify!($Max), ");")]
+        /// ```
+        ///
+        /// ```should_panic
+        /// #![feature(exact_div)]
+        #[doc = concat!("let _ = 65", stringify!($SelfT), ".exact_div(2);")]
+        /// ```
+        /// ```should_panic
+        /// #![feature(exact_div)]
+        #[doc = concat!("let _ = ", stringify!($SelfT), "::MIN.exact_div(-1);")]
+        /// ```
+        #[unstable(
+            feature = "exact_div",
+            issue = "139911",
+        )]
+        #[must_use = "this returns the result of the operation, \
+                      without modifying the original"]
+        #[inline]
+        pub const fn exact_div(self, rhs: Self) -> Self {
+            match self.checked_exact_div(rhs) {
+                Some(x) => x,
+                None => panic!("Failed to divide without remainder"),
+            }
+        }
+
+        /// Unchecked integer division without remainder. Computes `self / rhs`.
+        ///
+        /// # Safety
+        ///
+        /// This results in undefined behavior when `rhs == 0`, `self % rhs != 0`, or
+        #[doc = concat!("`self == ", stringify!($SelfT), "::MIN && rhs == -1`,")]
+        /// i.e. when [`checked_exact_div`](Self::checked_exact_div) would return `None`.
+        #[unstable(
+            feature = "exact_div",
+            issue = "139911",
+        )]
+        #[must_use = "this returns the result of the operation, \
+                      without modifying the original"]
+        #[inline]
+        pub const unsafe fn unchecked_exact_div(self, rhs: Self) -> Self {
+            assert_unsafe_precondition!(
+                check_language_ub,
+                concat!(stringify!($SelfT), "::unchecked_exact_div cannot overflow, divide by zero, or leave a remainder"),
+                (
+                    lhs: $SelfT = self,
+                    rhs: $SelfT = rhs,
+                ) => rhs > 0 && lhs % rhs == 0 && (lhs != <$SelfT>::MIN || rhs != -1),
+            );
+            // SAFETY: Same precondition
+            unsafe { intrinsics::exact_div(self, rhs) }
+        }
+
         /// Checked integer remainder. Computes `self % rhs`, returning `None` if
         /// `rhs == 0` or the division results in overflow.
         ///
@@ -1199,7 +1303,7 @@ macro_rules! int_impl {
         #[must_use = "this returns the result of the operation, \
                       without modifying the original"]
         #[inline(always)]
-        #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
+        #[track_caller]
         pub const unsafe fn unchecked_neg(self) -> Self {
             assert_unsafe_precondition!(
                 check_language_ub,
@@ -1327,7 +1431,7 @@ macro_rules! int_impl {
         #[must_use = "this returns the result of the operation, \
                       without modifying the original"]
         #[inline(always)]
-        #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
+        #[track_caller]
         pub const unsafe fn unchecked_shl(self, rhs: u32) -> Self {
             assert_unsafe_precondition!(
                 check_language_ub,
@@ -1448,7 +1552,7 @@ macro_rules! int_impl {
         #[must_use = "this returns the result of the operation, \
                       without modifying the original"]
         #[inline(always)]
-        #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
+        #[track_caller]
         pub const unsafe fn unchecked_shr(self, rhs: u32) -> Self {
             assert_unsafe_precondition!(
                 check_language_ub,
diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs
index 8a8b2733d5e..a279f002772 100644
--- a/library/core/src/num/nonzero.rs
+++ b/library/core/src/num/nonzero.rs
@@ -388,6 +388,7 @@ where
     #[rustc_const_stable(feature = "nonzero", since = "1.28.0")]
     #[must_use]
     #[inline]
+    #[track_caller]
     pub const unsafe fn new_unchecked(n: T) -> Self {
         match Self::new(n) {
             Some(n) => n,
@@ -428,6 +429,7 @@ where
     #[unstable(feature = "nonzero_from_mut", issue = "106290")]
     #[must_use]
     #[inline]
+    #[track_caller]
     pub unsafe fn from_mut_unchecked(n: &mut T) -> &mut Self {
         match Self::from_mut(n) {
             Some(n) => n,
diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs
index f38d809c154..5f82e6af86b 100644
--- a/library/core/src/num/uint_macros.rs
+++ b/library/core/src/num/uint_macros.rs
@@ -601,7 +601,7 @@ macro_rules! uint_impl {
         #[must_use = "this returns the result of the operation, \
                       without modifying the original"]
         #[inline(always)]
-        #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
+        #[track_caller]
         pub const unsafe fn unchecked_add(self, rhs: Self) -> Self {
             assert_unsafe_precondition!(
                 check_language_ub,
@@ -791,7 +791,7 @@ macro_rules! uint_impl {
         #[must_use = "this returns the result of the operation, \
                       without modifying the original"]
         #[inline(always)]
-        #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
+        #[track_caller]
         pub const unsafe fn unchecked_sub(self, rhs: Self) -> Self {
             assert_unsafe_precondition!(
                 check_language_ub,
@@ -974,7 +974,7 @@ macro_rules! uint_impl {
         #[must_use = "this returns the result of the operation, \
                       without modifying the original"]
         #[inline(always)]
-        #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
+        #[track_caller]
         pub const unsafe fn unchecked_mul(self, rhs: Self) -> Self {
             assert_unsafe_precondition!(
                 check_language_ub,
@@ -1110,6 +1110,108 @@ macro_rules! uint_impl {
             self / rhs
         }
 
+        /// Checked integer division without remainder. Computes `self / rhs`.
+        ///
+        /// # Panics
+        ///
+        /// This function will panic  if `rhs == 0` or `self % rhs != 0`.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        /// #![feature(exact_div)]
+        #[doc = concat!("assert_eq!(64", stringify!($SelfT), ".exact_div(2), 32);")]
+        #[doc = concat!("assert_eq!(64", stringify!($SelfT), ".exact_div(32), 2);")]
+        /// ```
+        ///
+        /// ```should_panic
+        /// #![feature(exact_div)]
+        #[doc = concat!("let _ = 65", stringify!($SelfT), ".exact_div(2);")]
+        /// ```
+        #[unstable(
+            feature = "exact_div",
+            issue = "139911",
+        )]
+        #[must_use = "this returns the result of the operation, \
+                      without modifying the original"]
+        #[inline]
+        pub const fn checked_exact_div(self, rhs: Self) -> Option<Self> {
+            if intrinsics::unlikely(rhs == 0) {
+                None
+            } else {
+                // SAFETY: division by zero is checked above
+                unsafe {
+                    if intrinsics::unlikely(intrinsics::unchecked_rem(self, rhs) != 0) {
+                        None
+                    } else {
+                        Some(intrinsics::exact_div(self, rhs))
+                    }
+                }
+            }
+        }
+
+        /// Checked integer division without remainder. Computes `self / rhs`.
+        ///
+        /// # Panics
+        ///
+        /// This function will panic  if `rhs == 0` or `self % rhs != 0`.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        /// #![feature(exact_div)]
+        #[doc = concat!("assert_eq!(64", stringify!($SelfT), ".exact_div(2), 32);")]
+        #[doc = concat!("assert_eq!(64", stringify!($SelfT), ".exact_div(32), 2);")]
+        /// ```
+        ///
+        /// ```should_panic
+        /// #![feature(exact_div)]
+        #[doc = concat!("let _ = 65", stringify!($SelfT), ".exact_div(2);")]
+        /// ```
+        #[unstable(
+            feature = "exact_div",
+            issue = "139911",
+        )]
+        #[must_use = "this returns the result of the operation, \
+                      without modifying the original"]
+        #[inline]
+        pub const fn exact_div(self, rhs: Self) -> Self {
+            match self.checked_exact_div(rhs) {
+                Some(x) => x,
+                None => panic!("Failed to divide without remainder"),
+            }
+        }
+
+        /// Unchecked integer division without remainder. Computes `self / rhs`.
+        ///
+        /// # Safety
+        ///
+        /// This results in undefined behavior when `rhs == 0` or `self % rhs != 0`,
+        /// i.e. when [`checked_exact_div`](Self::checked_exact_div) would return `None`.
+        #[unstable(
+            feature = "exact_div",
+            issue = "139911",
+        )]
+        #[must_use = "this returns the result of the operation, \
+                      without modifying the original"]
+        #[inline]
+        pub const unsafe fn unchecked_exact_div(self, rhs: Self) -> Self {
+            assert_unsafe_precondition!(
+                check_language_ub,
+                concat!(stringify!($SelfT), "::unchecked_exact_div divide by zero or leave a remainder"),
+                (
+                    lhs: $SelfT = self,
+                    rhs: $SelfT = rhs,
+                ) => rhs > 0 && lhs % rhs == 0,
+            );
+            // SAFETY: Same precondition
+            unsafe { intrinsics::exact_div(self, rhs) }
+        }
+
         /// Checked integer remainder. Computes `self % rhs`, returning `None`
         /// if `rhs == 0`.
         ///
@@ -1588,7 +1690,7 @@ macro_rules! uint_impl {
         #[must_use = "this returns the result of the operation, \
                       without modifying the original"]
         #[inline(always)]
-        #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
+        #[track_caller]
         pub const unsafe fn unchecked_shl(self, rhs: u32) -> Self {
             assert_unsafe_precondition!(
                 check_language_ub,
@@ -1709,7 +1811,7 @@ macro_rules! uint_impl {
         #[must_use = "this returns the result of the operation, \
                       without modifying the original"]
         #[inline(always)]
-        #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
+        #[track_caller]
         pub const unsafe fn unchecked_shr(self, rhs: u32) -> Self {
             assert_unsafe_precondition!(
                 check_language_ub,
diff --git a/library/core/src/ops/index_range.rs b/library/core/src/ops/index_range.rs
index c645c996eb7..507fa9460be 100644
--- a/library/core/src/ops/index_range.rs
+++ b/library/core/src/ops/index_range.rs
@@ -19,6 +19,7 @@ impl IndexRange {
     /// # Safety
     /// - `start <= end`
     #[inline]
+    #[track_caller]
     pub(crate) const unsafe fn new_unchecked(start: usize, end: usize) -> Self {
         ub_checks::assert_unsafe_precondition!(
             check_library_ub,
diff --git a/library/core/src/option.rs b/library/core/src/option.rs
index 1d264b26076..675556b07a8 100644
--- a/library/core/src/option.rs
+++ b/library/core/src/option.rs
@@ -1253,6 +1253,36 @@ impl<T> Option<T> {
         }
     }
 
+    /// Maps an `Option<T>` to a `U` by applying function `f` to the contained
+    /// value if the option is [`Some`], otherwise if [`None`], returns the
+    /// [default value] for the type `U`.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(result_option_map_or_default)]
+    ///
+    /// let x: Option<&str> = Some("hi");
+    /// let y: Option<&str> = None;
+    ///
+    /// assert_eq!(x.map_or_default(|x| x.len()), 2);
+    /// assert_eq!(y.map_or_default(|y| y.len()), 0);
+    /// ```
+    ///
+    /// [default value]: Default::default
+    #[inline]
+    #[unstable(feature = "result_option_map_or_default", issue = "138099")]
+    pub fn map_or_default<U, F>(self, f: F) -> U
+    where
+        U: Default,
+        F: FnOnce(T) -> U,
+    {
+        match self {
+            Some(t) => f(t),
+            None => U::default(),
+        }
+    }
+
     /// Transforms the `Option<T>` into a [`Result<T, E>`], mapping [`Some(v)`] to
     /// [`Ok(v)`] and [`None`] to [`Err(err)`].
     ///
diff --git a/library/core/src/primitive_docs.rs b/library/core/src/primitive_docs.rs
index 17c4b488361..10b11613f90 100644
--- a/library/core/src/primitive_docs.rs
+++ b/library/core/src/primitive_docs.rs
@@ -1623,7 +1623,7 @@ mod prim_usize {}
 /// * if `size_of_val(t) > 0`, then `t` is dereferenceable for `size_of_val(t)` many bytes
 ///
 /// If `t` points at address `a`, being "dereferenceable" for N bytes means that the memory range
-/// `[a, a + N)` is all contained within a single [allocated object].
+/// `[a, a + N)` is all contained within a single [allocation].
 ///
 /// For instance, this means that unsafe code in a safe function may assume these invariants are
 /// ensured of arguments passed by the caller, and it may assume that these invariants are ensured
@@ -1639,7 +1639,7 @@ mod prim_usize {}
 /// may be unsound or become unsound in future versions of Rust depending on how this question is
 /// decided.
 ///
-/// [allocated object]: ptr#allocated-object
+/// [allocation]: ptr#allocation
 #[stable(feature = "rust1", since = "1.0.0")]
 mod prim_ref {}
 
diff --git a/library/core/src/ptr/alignment.rs b/library/core/src/ptr/alignment.rs
index 19311e39b45..3e66e271f03 100644
--- a/library/core/src/ptr/alignment.rs
+++ b/library/core/src/ptr/alignment.rs
@@ -73,6 +73,7 @@ impl Alignment {
     /// It must *not* be zero.
     #[unstable(feature = "ptr_alignment_type", issue = "102070")]
     #[inline]
+    #[track_caller]
     pub const unsafe fn new_unchecked(align: usize) -> Self {
         assert_unsafe_precondition!(
             check_language_ub,
diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs
index 19ed7599a51..a1dab23ea7b 100644
--- a/library/core/src/ptr/const_ptr.rs
+++ b/library/core/src/ptr/const_ptr.rs
@@ -397,35 +397,7 @@ impl<T: ?Sized> *const T {
         if self.is_null() { None } else { Some(unsafe { &*(self as *const MaybeUninit<T>) }) }
     }
 
-    /// Adds a signed offset to a pointer.
-    ///
-    /// `count` is in units of T; e.g., a `count` of 3 represents a pointer
-    /// offset of `3 * size_of::<T>()` bytes.
-    ///
-    /// # Safety
-    ///
-    /// If any of the following conditions are violated, the result is Undefined Behavior:
-    ///
-    /// * The offset in bytes, `count * size_of::<T>()`, computed on mathematical integers (without
-    ///   "wrapping around"), must fit in an `isize`.
-    ///
-    /// * If the computed offset is non-zero, then `self` must be [derived from][crate::ptr#provenance] a pointer to some
-    ///   [allocated object], and the entire memory range between `self` and the result must be in
-    ///   bounds of that allocated object. In particular, this range must not "wrap around" the edge
-    ///   of the address space. Note that "range" here refers to a half-open range as usual in Rust,
-    ///   i.e., `self..result` for non-negative offsets and `result..self` for negative offsets.
-    ///
-    /// Allocated objects can never be larger than `isize::MAX` bytes, so if the computed offset
-    /// stays in bounds of the allocated object, it is guaranteed to satisfy the first requirement.
-    /// This implies, for instance, that `vec.as_ptr().add(vec.len())` (for `vec: Vec<T>`) is always
-    /// safe.
-    ///
-    /// Consider using [`wrapping_offset`] instead if these constraints are
-    /// difficult to satisfy. The only advantage of this method is that it
-    /// enables more aggressive compiler optimizations.
-    ///
-    /// [`wrapping_offset`]: #method.wrapping_offset
-    /// [allocated object]: crate::ptr#allocated-object
+    #[doc = include_str!("./docs/offset.md")]
     ///
     /// # Examples
     ///
@@ -442,7 +414,7 @@ impl<T: ?Sized> *const T {
     #[must_use = "returns a new pointer rather than modifying its argument"]
     #[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")]
     #[inline(always)]
-    #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
+    #[track_caller]
     pub const unsafe fn offset(self, count: isize) -> *const T
     where
         T: Sized,
@@ -495,7 +467,7 @@ impl<T: ?Sized> *const T {
     #[inline(always)]
     #[stable(feature = "pointer_byte_offsets", since = "1.75.0")]
     #[rustc_const_stable(feature = "const_pointer_byte_offsets", since = "1.75.0")]
-    #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
+    #[track_caller]
     pub const unsafe fn byte_offset(self, count: isize) -> Self {
         // SAFETY: the caller must uphold the safety contract for `offset`.
         unsafe { self.cast::<u8>().offset(count).with_metadata_of(self) }
@@ -510,17 +482,17 @@ impl<T: ?Sized> *const T {
     ///
     /// This operation itself is always safe, but using the resulting pointer is not.
     ///
-    /// The resulting pointer "remembers" the [allocated object] that `self` points to
+    /// The resulting pointer "remembers" the [allocation] that `self` points to
     /// (this is called "[Provenance](ptr/index.html#provenance)").
-    /// The pointer must not be used to read or write other allocated objects.
+    /// The pointer must not be used to read or write other allocations.
     ///
     /// In other words, `let z = x.wrapping_offset((y as isize) - (x as isize))` does *not* make `z`
     /// the same as `y` even if we assume `T` has size `1` and there is no overflow: `z` is still
     /// attached to the object `x` is attached to, and dereferencing it is Undefined Behavior unless
-    /// `x` and `y` point into the same allocated object.
+    /// `x` and `y` point into the same allocation.
     ///
     /// Compared to [`offset`], this method basically delays the requirement of staying within the
-    /// same allocated object: [`offset`] is immediate Undefined Behavior when crossing object
+    /// same allocation: [`offset`] is immediate Undefined Behavior when crossing object
     /// boundaries; `wrapping_offset` produces a pointer but still leads to Undefined Behavior if a
     /// pointer is dereferenced when it is out-of-bounds of the object it is attached to. [`offset`]
     /// can be optimized better and is thus preferable in performance-sensitive code.
@@ -528,10 +500,10 @@ impl<T: ?Sized> *const T {
     /// The delayed check only considers the value of the pointer that was dereferenced, not the
     /// intermediate values used during the computation of the final result. For example,
     /// `x.wrapping_offset(o).wrapping_offset(o.wrapping_neg())` is always the same as `x`. In other
-    /// words, leaving the allocated object and then re-entering it later is permitted.
+    /// words, leaving the allocation and then re-entering it later is permitted.
     ///
     /// [`offset`]: #method.offset
-    /// [allocated object]: crate::ptr#allocated-object
+    /// [allocation]: crate::ptr#allocation
     ///
     /// # Examples
     ///
@@ -644,7 +616,7 @@ impl<T: ?Sized> *const T {
     /// * `self` and `origin` must either
     ///
     ///   * point to the same address, or
-    ///   * both be [derived from][crate::ptr#provenance] a pointer to the same [allocated object], and the memory range between
+    ///   * both be [derived from][crate::ptr#provenance] a pointer to the same [allocation], and the memory range between
     ///     the two pointers must be in bounds of that object. (See below for an example.)
     ///
     /// * The distance between the pointers, in bytes, must be an exact multiple
@@ -652,10 +624,10 @@ impl<T: ?Sized> *const T {
     ///
     /// As a consequence, the absolute distance between the pointers, in bytes, computed on
     /// mathematical integers (without "wrapping around"), cannot overflow an `isize`. This is
-    /// implied by the in-bounds requirement, and the fact that no allocated object can be larger
+    /// implied by the in-bounds requirement, and the fact that no allocation can be larger
     /// than `isize::MAX` bytes.
     ///
-    /// The requirement for pointers to be derived from the same allocated object is primarily
+    /// The requirement for pointers to be derived from the same allocation is primarily
     /// needed for `const`-compatibility: the distance between pointers into *different* allocated
     /// objects is not known at compile-time. However, the requirement also exists at
     /// runtime and may be exploited by optimizations. If you wish to compute the difference between
@@ -664,7 +636,7 @@ impl<T: ?Sized> *const T {
     // FIXME: recommend `addr()` instead of `as usize` once that is stable.
     ///
     /// [`add`]: #method.add
-    /// [allocated object]: crate::ptr#allocated-object
+    /// [allocation]: crate::ptr#allocation
     ///
     /// # Panics
     ///
@@ -794,7 +766,7 @@ impl<T: ?Sized> *const T {
     #[stable(feature = "ptr_sub_ptr", since = "1.87.0")]
     #[rustc_const_stable(feature = "const_ptr_sub_ptr", since = "1.87.0")]
     #[inline]
-    #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
+    #[track_caller]
     pub const unsafe fn offset_from_unsigned(self, origin: *const T) -> usize
     where
         T: Sized,
@@ -839,7 +811,7 @@ impl<T: ?Sized> *const T {
     #[stable(feature = "ptr_sub_ptr", since = "1.87.0")]
     #[rustc_const_stable(feature = "const_ptr_sub_ptr", since = "1.87.0")]
     #[inline]
-    #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
+    #[track_caller]
     pub const unsafe fn byte_offset_from_unsigned<U: ?Sized>(self, origin: *const U) -> usize {
         // SAFETY: the caller must uphold the safety contract for `offset_from_unsigned`.
         unsafe { self.cast::<u8>().offset_from_unsigned(origin.cast::<u8>()) }
@@ -905,38 +877,7 @@ impl<T: ?Sized> *const T {
         }
     }
 
-    /// Adds an unsigned offset to a pointer.
-    ///
-    /// This can only move the pointer forward (or not move it). If you need to move forward or
-    /// backward depending on the value, then you might want [`offset`](#method.offset) instead
-    /// which takes a signed offset.
-    ///
-    /// `count` is in units of T; e.g., a `count` of 3 represents a pointer
-    /// offset of `3 * size_of::<T>()` bytes.
-    ///
-    /// # Safety
-    ///
-    /// If any of the following conditions are violated, the result is Undefined Behavior:
-    ///
-    /// * The offset in bytes, `count * size_of::<T>()`, computed on mathematical integers (without
-    ///   "wrapping around"), must fit in an `isize`.
-    ///
-    /// * If the computed offset is non-zero, then `self` must be [derived from][crate::ptr#provenance] a pointer to some
-    ///   [allocated object], and the entire memory range between `self` and the result must be in
-    ///   bounds of that allocated object. In particular, this range must not "wrap around" the edge
-    ///   of the address space.
-    ///
-    /// Allocated objects can never be larger than `isize::MAX` bytes, so if the computed offset
-    /// stays in bounds of the allocated object, it is guaranteed to satisfy the first requirement.
-    /// This implies, for instance, that `vec.as_ptr().add(vec.len())` (for `vec: Vec<T>`) is always
-    /// safe.
-    ///
-    /// Consider using [`wrapping_add`] instead if these constraints are
-    /// difficult to satisfy. The only advantage of this method is that it
-    /// enables more aggressive compiler optimizations.
-    ///
-    /// [`wrapping_add`]: #method.wrapping_add
-    /// [allocated object]: crate::ptr#allocated-object
+    #[doc = include_str!("./docs/add.md")]
     ///
     /// # Examples
     ///
@@ -953,7 +894,7 @@ impl<T: ?Sized> *const T {
     #[must_use = "returns a new pointer rather than modifying its argument"]
     #[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")]
     #[inline(always)]
-    #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
+    #[track_caller]
     pub const unsafe fn add(self, count: usize) -> Self
     where
         T: Sized,
@@ -1005,7 +946,7 @@ impl<T: ?Sized> *const T {
     #[inline(always)]
     #[stable(feature = "pointer_byte_offsets", since = "1.75.0")]
     #[rustc_const_stable(feature = "const_pointer_byte_offsets", since = "1.75.0")]
-    #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
+    #[track_caller]
     pub const unsafe fn byte_add(self, count: usize) -> Self {
         // SAFETY: the caller must uphold the safety contract for `add`.
         unsafe { self.cast::<u8>().add(count).with_metadata_of(self) }
@@ -1028,12 +969,12 @@ impl<T: ?Sized> *const T {
     ///   "wrapping around"), must fit in an `isize`.
     ///
     /// * If the computed offset is non-zero, then `self` must be [derived from][crate::ptr#provenance] a pointer to some
-    ///   [allocated object], and the entire memory range between `self` and the result must be in
-    ///   bounds of that allocated object. In particular, this range must not "wrap around" the edge
+    ///   [allocation], and the entire memory range between `self` and the result must be in
+    ///   bounds of that allocation. In particular, this range must not "wrap around" the edge
     ///   of the address space.
     ///
-    /// Allocated objects can never be larger than `isize::MAX` bytes, so if the computed offset
-    /// stays in bounds of the allocated object, it is guaranteed to satisfy the first requirement.
+    /// Allocations can never be larger than `isize::MAX` bytes, so if the computed offset
+    /// stays in bounds of the allocation, it is guaranteed to satisfy the first requirement.
     /// This implies, for instance, that `vec.as_ptr().add(vec.len())` (for `vec: Vec<T>`) is always
     /// safe.
     ///
@@ -1042,7 +983,7 @@ impl<T: ?Sized> *const T {
     /// enables more aggressive compiler optimizations.
     ///
     /// [`wrapping_sub`]: #method.wrapping_sub
-    /// [allocated object]: crate::ptr#allocated-object
+    /// [allocation]: crate::ptr#allocation
     ///
     /// # Examples
     ///
@@ -1059,7 +1000,7 @@ impl<T: ?Sized> *const T {
     #[must_use = "returns a new pointer rather than modifying its argument"]
     #[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")]
     #[inline(always)]
-    #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
+    #[track_caller]
     pub const unsafe fn sub(self, count: usize) -> Self
     where
         T: Sized,
@@ -1117,7 +1058,7 @@ impl<T: ?Sized> *const T {
     #[inline(always)]
     #[stable(feature = "pointer_byte_offsets", since = "1.75.0")]
     #[rustc_const_stable(feature = "const_pointer_byte_offsets", since = "1.75.0")]
-    #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
+    #[track_caller]
     pub const unsafe fn byte_sub(self, count: usize) -> Self {
         // SAFETY: the caller must uphold the safety contract for `sub`.
         unsafe { self.cast::<u8>().sub(count).with_metadata_of(self) }
@@ -1132,16 +1073,16 @@ impl<T: ?Sized> *const T {
     ///
     /// This operation itself is always safe, but using the resulting pointer is not.
     ///
-    /// The resulting pointer "remembers" the [allocated object] that `self` points to; it must not
-    /// be used to read or write other allocated objects.
+    /// The resulting pointer "remembers" the [allocation] that `self` points to; it must not
+    /// be used to read or write other allocations.
     ///
     /// In other words, `let z = x.wrapping_add((y as usize) - (x as usize))` does *not* make `z`
     /// the same as `y` even if we assume `T` has size `1` and there is no overflow: `z` is still
     /// attached to the object `x` is attached to, and dereferencing it is Undefined Behavior unless
-    /// `x` and `y` point into the same allocated object.
+    /// `x` and `y` point into the same allocation.
     ///
     /// Compared to [`add`], this method basically delays the requirement of staying within the
-    /// same allocated object: [`add`] is immediate Undefined Behavior when crossing object
+    /// same allocation: [`add`] is immediate Undefined Behavior when crossing object
     /// boundaries; `wrapping_add` produces a pointer but still leads to Undefined Behavior if a
     /// pointer is dereferenced when it is out-of-bounds of the object it is attached to. [`add`]
     /// can be optimized better and is thus preferable in performance-sensitive code.
@@ -1149,10 +1090,10 @@ impl<T: ?Sized> *const T {
     /// The delayed check only considers the value of the pointer that was dereferenced, not the
     /// intermediate values used during the computation of the final result. For example,
     /// `x.wrapping_add(o).wrapping_sub(o)` is always the same as `x`. In other words, leaving the
-    /// allocated object and then re-entering it later is permitted.
+    /// allocation and then re-entering it later is permitted.
     ///
     /// [`add`]: #method.add
-    /// [allocated object]: crate::ptr#allocated-object
+    /// [allocation]: crate::ptr#allocation
     ///
     /// # Examples
     ///
@@ -1211,16 +1152,16 @@ impl<T: ?Sized> *const T {
     ///
     /// This operation itself is always safe, but using the resulting pointer is not.
     ///
-    /// The resulting pointer "remembers" the [allocated object] that `self` points to; it must not
-    /// be used to read or write other allocated objects.
+    /// The resulting pointer "remembers" the [allocation] that `self` points to; it must not
+    /// be used to read or write other allocations.
     ///
     /// In other words, `let z = x.wrapping_sub((x as usize) - (y as usize))` does *not* make `z`
     /// the same as `y` even if we assume `T` has size `1` and there is no overflow: `z` is still
     /// attached to the object `x` is attached to, and dereferencing it is Undefined Behavior unless
-    /// `x` and `y` point into the same allocated object.
+    /// `x` and `y` point into the same allocation.
     ///
     /// Compared to [`sub`], this method basically delays the requirement of staying within the
-    /// same allocated object: [`sub`] is immediate Undefined Behavior when crossing object
+    /// same allocation: [`sub`] is immediate Undefined Behavior when crossing object
     /// boundaries; `wrapping_sub` produces a pointer but still leads to Undefined Behavior if a
     /// pointer is dereferenced when it is out-of-bounds of the object it is attached to. [`sub`]
     /// can be optimized better and is thus preferable in performance-sensitive code.
@@ -1228,10 +1169,10 @@ impl<T: ?Sized> *const T {
     /// The delayed check only considers the value of the pointer that was dereferenced, not the
     /// intermediate values used during the computation of the final result. For example,
     /// `x.wrapping_add(o).wrapping_sub(o)` is always the same as `x`. In other words, leaving the
-    /// allocated object and then re-entering it later is permitted.
+    /// allocation and then re-entering it later is permitted.
     ///
     /// [`sub`]: #method.sub
-    /// [allocated object]: crate::ptr#allocated-object
+    /// [allocation]: crate::ptr#allocation
     ///
     /// # Examples
     ///
@@ -1290,7 +1231,7 @@ impl<T: ?Sized> *const T {
     #[stable(feature = "pointer_methods", since = "1.26.0")]
     #[rustc_const_stable(feature = "const_ptr_read", since = "1.71.0")]
     #[inline]
-    #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
+    #[track_caller]
     pub const unsafe fn read(self) -> T
     where
         T: Sized,
@@ -1311,7 +1252,7 @@ impl<T: ?Sized> *const T {
     /// [`ptr::read_volatile`]: crate::ptr::read_volatile()
     #[stable(feature = "pointer_methods", since = "1.26.0")]
     #[inline]
-    #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
+    #[track_caller]
     pub unsafe fn read_volatile(self) -> T
     where
         T: Sized,
@@ -1331,7 +1272,7 @@ impl<T: ?Sized> *const T {
     #[stable(feature = "pointer_methods", since = "1.26.0")]
     #[rustc_const_stable(feature = "const_ptr_read", since = "1.71.0")]
     #[inline]
-    #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
+    #[track_caller]
     pub const unsafe fn read_unaligned(self) -> T
     where
         T: Sized,
@@ -1351,7 +1292,7 @@ impl<T: ?Sized> *const T {
     #[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.83.0")]
     #[stable(feature = "pointer_methods", since = "1.26.0")]
     #[inline]
-    #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
+    #[track_caller]
     pub const unsafe fn copy_to(self, dest: *mut T, count: usize)
     where
         T: Sized,
@@ -1371,7 +1312,7 @@ impl<T: ?Sized> *const T {
     #[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.83.0")]
     #[stable(feature = "pointer_methods", since = "1.26.0")]
     #[inline]
-    #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
+    #[track_caller]
     pub const unsafe fn copy_to_nonoverlapping(self, dest: *mut T, count: usize)
     where
         T: Sized,
@@ -1623,8 +1564,8 @@ impl<T> *const [T] {
     /// * 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:
     ///
-    ///     * The entire memory range of this slice must be contained within a single [allocated object]!
-    ///       Slices can never span across multiple allocated objects.
+    ///     * The entire memory range of this slice must be contained within a single [allocation]!
+    ///       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
@@ -1645,7 +1586,7 @@ impl<T> *const [T] {
     /// See also [`slice::from_raw_parts`][].
     ///
     /// [valid]: crate::ptr#safety
-    /// [allocated object]: crate::ptr#allocated-object
+    /// [allocation]: crate::ptr#allocation
     ///
     /// # Panics during const evaluation
     ///
diff --git a/library/core/src/ptr/docs/add.md b/library/core/src/ptr/docs/add.md
new file mode 100644
index 00000000000..ae7c7785684
--- /dev/null
+++ b/library/core/src/ptr/docs/add.md
@@ -0,0 +1,32 @@
+Adds an unsigned offset to a pointer.
+
+This can only move the pointer forward (or not move it). If you need to move forward or
+backward depending on the value, then you might want [`offset`](#method.offset) instead
+which takes a signed offset.
+
+`count` is in units of T; e.g., a `count` of 3 represents a pointer
+offset of `3 * size_of::<T>()` bytes.
+
+# Safety
+
+If any of the following conditions are violated, the result is Undefined Behavior:
+
+* The offset in bytes, `count * size_of::<T>()`, computed on mathematical integers (without
+"wrapping around"), must fit in an `isize`.
+
+* If the computed offset is non-zero, then `self` must be [derived from][crate::ptr#provenance] a pointer to some
+[allocation], and the entire memory range between `self` and the result must be in
+bounds of that allocation. In particular, this range must not "wrap around" the edge
+of the address space.
+
+Allocated objects can never be larger than `isize::MAX` bytes, so if the computed offset
+stays in bounds of the allocation, it is guaranteed to satisfy the first requirement.
+This implies, for instance, that `vec.as_ptr().add(vec.len())` (for `vec: Vec<T>`) is always
+safe.
+
+Consider using [`wrapping_add`] instead if these constraints are
+difficult to satisfy. The only advantage of this method is that it
+enables more aggressive compiler optimizations.
+
+[`wrapping_add`]: #method.wrapping_add
+[allocation]: crate::ptr#allocation
diff --git a/library/core/src/ptr/docs/offset.md b/library/core/src/ptr/docs/offset.md
new file mode 100644
index 00000000000..f2e335a79a5
--- /dev/null
+++ b/library/core/src/ptr/docs/offset.md
@@ -0,0 +1,29 @@
+Adds a signed offset to a pointer.
+
+`count` is in units of T; e.g., a `count` of 3 represents a pointer
+offset of `3 * size_of::<T>()` bytes.
+
+# Safety
+
+If any of the following conditions are violated, the result is Undefined Behavior:
+
+* The offset in bytes, `count * size_of::<T>()`, computed on mathematical integers (without
+"wrapping around"), must fit in an `isize`.
+
+* If the computed offset is non-zero, then `self` must be [derived from][crate::ptr#provenance] a pointer to some
+[allocation], and the entire memory range between `self` and the result must be in
+bounds of that allocation. In particular, this range must not "wrap around" the edge
+of the address space. Note that "range" here refers to a half-open range as usual in Rust,
+i.e., `self..result` for non-negative offsets and `result..self` for negative offsets.
+
+Allocated objects can never be larger than `isize::MAX` bytes, so if the computed offset
+stays in bounds of the allocation, it is guaranteed to satisfy the first requirement.
+This implies, for instance, that `vec.as_ptr().add(vec.len())` (for `vec: Vec<T>`) is always
+safe.
+
+Consider using [`wrapping_offset`] instead if these constraints are
+difficult to satisfy. The only advantage of this method is that it
+enables more aggressive compiler optimizations.
+
+[`wrapping_offset`]: #method.wrapping_offset
+[allocation]: crate::ptr#allocation
diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs
index 35a909f6904..81bf6778b05 100644
--- a/library/core/src/ptr/mod.rs
+++ b/library/core/src/ptr/mod.rs
@@ -19,10 +19,10 @@
 //!   pointer. The following points are only concerned with non-zero-sized accesses.
 //! * A [null] pointer is *never* valid.
 //! * For a pointer to be valid, it is necessary, but not always sufficient, that the pointer be
-//!   *dereferenceable*. The [provenance] of the pointer is used to determine which [allocated
-//!   object] it is derived from; a pointer is dereferenceable if the memory range of the given size
-//!   starting at the pointer is entirely contained within the bounds of that allocated object. Note
-//!   that in Rust, every (stack-allocated) variable is considered a separate allocated object.
+//!   *dereferenceable*. The [provenance] of the pointer is used to determine which [allocation]
+//!   it is derived from; a pointer is dereferenceable if the memory range of the given size
+//!   starting at the pointer is entirely contained within the bounds of that allocation. Note
+//!   that in Rust, every (stack-allocated) variable is considered a separate allocation.
 //! * All accesses performed by functions in this module are *non-atomic* in the sense
 //!   of [atomic operations] used to synchronize between threads. This means it is
 //!   undefined behavior to perform two concurrent accesses to the same location from different
@@ -30,7 +30,7 @@
 //!   includes [`read_volatile`] and [`write_volatile`]: Volatile accesses cannot
 //!   be used for inter-thread synchronization.
 //! * The result of casting a reference to a pointer is valid for as long as the
-//!   underlying object is live and no reference (just raw pointers) is used to
+//!   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
 //!   interleaved.
 //!
@@ -95,24 +95,26 @@
 //!
 //! [valid value]: ../../reference/behavior-considered-undefined.html#invalid-values
 //!
-//! ## Allocated object
+//! ## Allocation
 //!
-//! An *allocated object* is a subset of program memory which is addressable
+//! <a id="allocated-object"></a> <!-- keep old URLs working -->
+//!
+//! An *allocation* is a subset of program memory which is addressable
 //! from Rust, and within which pointer arithmetic is possible. Examples of
-//! allocated objects include heap allocations, stack-allocated variables,
+//! allocations include heap allocations, stack-allocated variables,
 //! statics, and consts. The safety preconditions of some Rust operations -
 //! such as `offset` and field projections (`expr.field`) - are defined in
-//! terms of the allocated objects on which they operate.
+//! terms of the allocations on which they operate.
 //!
-//! An allocated object has a base address, a size, and a set of memory
-//! addresses. It is possible for an allocated object to have zero size, but
-//! such an allocated object will still have a base address. The base address
-//! of an allocated object is not necessarily unique. While it is currently the
-//! case that an allocated object always has a set of memory addresses which is
+//! An allocation has a base address, a size, and a set of memory
+//! addresses. It is possible for an allocation to have zero size, but
+//! such an allocation will still have a base address. The base address
+//! of an allocation is not necessarily unique. While it is currently the
+//! case that an allocation always has a set of memory addresses which is
 //! fully contiguous (i.e., has no "holes"), there is no guarantee that this
 //! will not change in the future.
 //!
-//! For any allocated object with `base` address, `size`, and a set of
+//! 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 +
 //!   size)` (note that this requires `a < base + size`, not `a <= base + size`)
@@ -122,11 +124,11 @@
 //! - `size <= isize::MAX`
 //!
 //! As a consequence of these guarantees, given any address `a` within the set
-//! of addresses of an allocated object:
+//! of addresses of an allocation:
 //! - It is guaranteed that `a - base` does not overflow `isize`
 //! - It is guaranteed that `a - base` is non-negative
 //! - It is guaranteed that, given `o = a - base` (i.e., the offset of `a` within
-//!   the allocated object), `base + o` will not wrap around the address space (in
+//!   the allocation), `base + o` will not wrap around the address space (in
 //!   other words, will not overflow `usize`)
 //!
 //! [`null()`]: null
@@ -138,8 +140,8 @@
 //! and the freed memory gets reallocated before your read/write (in fact this is the
 //! worst-case scenario, UAFs would be much less concerning if this didn't happen!).
 //! As another example, consider that [`wrapping_offset`] is documented to "remember"
-//! the allocated object that the original pointer points to, even if it is offset far
-//! outside the memory range occupied by that allocated object.
+//! the allocation that the original pointer points to, even if it is offset far
+//! outside the memory range occupied by that allocation.
 //! To rationalize claims like this, pointers need to somehow be *more* than just their addresses:
 //! they must have **provenance**.
 //!
@@ -159,12 +161,12 @@
 //!   writes. Note that this can interact with the other components, e.g. a pointer might permit
 //!   mutation only for a subset of addresses, or only for a subset of its maximal timespan.
 //!
-//! When an [allocated object] is created, it has a unique Original Pointer. For alloc
+//! When an [allocation] is created, it has a unique Original Pointer. For alloc
 //! APIs this is literally the pointer the call returns, and for local variables and statics,
 //! this is the name of the variable/static. (This is mildly overloading the term "pointer"
 //! for the sake of brevity/exposition.)
 //!
-//! The Original Pointer for an allocated object has provenance that constrains the *spatial*
+//! The Original Pointer for an allocation has provenance that constrains the *spatial*
 //! permissions of this pointer to the memory range of the allocation, and the *temporal*
 //! permissions to the lifetime of the allocation. Provenance is implicitly inherited by all
 //! pointers transitively derived from the Original Pointer through operations like [`offset`],
@@ -192,10 +194,10 @@
 //!   provenance since they access an empty range of memory.
 //!
 //! * It is undefined behavior to [`offset`] a pointer across a memory range that is not contained
-//!   in the allocated object it is derived from, or to [`offset_from`] two pointers not derived
-//!   from the same allocated object. Provenance is used to say what exactly "derived from" even
+//!   in the allocation it is derived from, or to [`offset_from`] two pointers not derived
+//!   from the same allocation. Provenance is used to say what exactly "derived from" even
 //!   means: the lineage of a pointer is traced back to the Original Pointer it descends from, and
-//!   that identifies the relevant allocated object. In particular, it's always UB to offset a
+//!   that identifies the relevant allocation. In particular, it's always UB to offset a
 //!   pointer derived from something that is now deallocated, except if the offset is 0.
 //!
 //! But it *is* still sound to:
@@ -216,7 +218,7 @@
 //! * Compare arbitrary pointers by address. Pointer comparison ignores provenance and addresses
 //!   *are* just integers, so there is always a coherent answer, even if the pointers are dangling
 //!   or from different provenances. Note that if you get "lucky" and notice that a pointer at the
-//!   end of one allocated object is the "same" address as the start of another allocated object,
+//!   end of one allocation is the "same" address as the start of another allocation,
 //!   anything you do with that fact is *probably* going to be gibberish. The scope of that
 //!   gibberish is kept under control by the fact that the two pointers *still* aren't allowed to
 //!   access the other's allocation (bytes), because they still have different provenance.
@@ -369,7 +371,7 @@
 //! integer-to-pointer casts.
 //!
 //! [aliasing]: ../../nomicon/aliasing.html
-//! [allocated object]: #allocated-object
+//! [allocation]: #allocation
 //! [provenance]: #provenance
 //! [book]: ../../book/ch19-01-unsafe-rust.html#dereferencing-a-raw-pointer
 //! [ub]: ../../reference/behavior-considered-undefined.html
@@ -1289,7 +1291,7 @@ pub const unsafe fn swap<T>(x: *mut T, y: *mut T) {
     // SAFETY: the caller must guarantee that `x` and `y` are
     // valid for writes and properly aligned. `tmp` cannot be
     // overlapping either `x` or `y` because `tmp` was just allocated
-    // on the stack as a separate allocated object.
+    // on the stack as a separate allocation.
     unsafe {
         copy_nonoverlapping(x, tmp.as_mut_ptr(), 1);
         copy(y, x, 1); // `x` and `y` may overlap
@@ -1377,6 +1379,7 @@ pub const unsafe fn swap<T>(x: *mut T, y: *mut T) {
 #[rustc_const_stable(feature = "const_swap_nonoverlapping", since = "1.88.0")]
 #[rustc_diagnostic_item = "ptr_swap_nonoverlapping"]
 #[rustc_allow_const_fn_unstable(const_eval_select)] // both implementations behave the same
+#[track_caller]
 pub const unsafe fn swap_nonoverlapping<T>(x: *mut T, y: *mut T, count: usize) {
     ub_checks::assert_unsafe_precondition!(
         check_library_ub,
@@ -1408,7 +1411,7 @@ pub const unsafe fn swap_nonoverlapping<T>(x: *mut T, y: *mut T, count: usize) {
             // Going though a slice here helps codegen know the size fits in `isize`
             let slice = slice_from_raw_parts_mut(x, count);
             // SAFETY: This is all readable from the pointer, meaning it's one
-            // allocated object, and thus cannot be more than isize::MAX bytes.
+            // allocation, and thus cannot be more than isize::MAX bytes.
             let bytes = unsafe { mem::size_of_val_raw::<[T]>(slice) };
             if let Some(bytes) = NonZero::new(bytes) {
                 // SAFETY: These are the same ranges, just expressed in a different
@@ -1557,11 +1560,12 @@ unsafe fn swap_nonoverlapping_bytes(x: *mut u8, y: *mut u8, bytes: NonZero<usize
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_const_stable(feature = "const_replace", since = "1.83.0")]
 #[rustc_diagnostic_item = "ptr_replace"]
+#[track_caller]
 pub const unsafe fn replace<T>(dst: *mut T, src: T) -> T {
     // SAFETY: the caller must guarantee that `dst` is valid to be
     // cast to a mutable reference (valid for writes, aligned, initialized),
     // and cannot overlap `src` since `dst` must point to a distinct
-    // allocated object.
+    // allocation.
     unsafe {
         ub_checks::assert_unsafe_precondition!(
             check_language_ub,
@@ -1684,7 +1688,7 @@ pub const unsafe fn replace<T>(dst: *mut T, src: T) -> T {
 #[inline]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_const_stable(feature = "const_ptr_read", since = "1.71.0")]
-#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
+#[track_caller]
 #[rustc_diagnostic_item = "ptr_read"]
 pub const unsafe fn read<T>(src: *const T) -> T {
     // It would be semantically correct to implement this via `copy_nonoverlapping`
@@ -1802,13 +1806,13 @@ pub const unsafe fn read<T>(src: *const T) -> T {
 #[inline]
 #[stable(feature = "ptr_unaligned", since = "1.17.0")]
 #[rustc_const_stable(feature = "const_ptr_read", since = "1.71.0")]
-#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
+#[track_caller]
 #[rustc_diagnostic_item = "ptr_read_unaligned"]
 pub const unsafe fn read_unaligned<T>(src: *const T) -> T {
     let mut tmp = MaybeUninit::<T>::uninit();
     // SAFETY: the caller must guarantee that `src` is valid for reads.
     // `src` cannot overlap `tmp` because `tmp` was just allocated on
-    // the stack as a separate allocated object.
+    // the stack as a separate allocation.
     //
     // Also, since we just wrote a valid value into `tmp`, it is guaranteed
     // to be properly initialized.
@@ -1901,7 +1905,7 @@ pub const unsafe fn read_unaligned<T>(src: *const T) -> T {
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_const_stable(feature = "const_ptr_write", since = "1.83.0")]
 #[rustc_diagnostic_item = "ptr_write"]
-#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
+#[track_caller]
 pub const unsafe fn write<T>(dst: *mut T, src: T) {
     // Semantically, it would be fine for this to be implemented as a
     // `copy_nonoverlapping` and appropriate drop suppression of `src`.
@@ -2005,7 +2009,7 @@ pub const unsafe fn write<T>(dst: *mut T, src: T) {
 #[stable(feature = "ptr_unaligned", since = "1.17.0")]
 #[rustc_const_stable(feature = "const_ptr_write", since = "1.83.0")]
 #[rustc_diagnostic_item = "ptr_write_unaligned"]
-#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
+#[track_caller]
 pub const unsafe fn write_unaligned<T>(dst: *mut T, src: T) {
     // SAFETY: the caller must guarantee that `dst` is valid for writes.
     // `dst` cannot overlap `src` because the caller has mutable access
@@ -2079,7 +2083,7 @@ pub const unsafe fn write_unaligned<T>(dst: *mut T, src: T) {
 /// ```
 #[inline]
 #[stable(feature = "volatile", since = "1.9.0")]
-#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
+#[track_caller]
 #[rustc_diagnostic_item = "ptr_read_volatile"]
 pub unsafe fn read_volatile<T>(src: *const T) -> T {
     // SAFETY: the caller must uphold the safety contract for `volatile_load`.
@@ -2160,7 +2164,7 @@ pub unsafe fn read_volatile<T>(src: *const T) -> T {
 #[inline]
 #[stable(feature = "volatile", since = "1.9.0")]
 #[rustc_diagnostic_item = "ptr_write_volatile"]
-#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
+#[track_caller]
 pub unsafe fn write_volatile<T>(dst: *mut T, src: T) {
     // SAFETY: the caller must uphold the safety contract for `volatile_store`.
     unsafe {
diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs
index 53aa3ab4938..968f033bf59 100644
--- a/library/core/src/ptr/mut_ptr.rs
+++ b/library/core/src/ptr/mut_ptr.rs
@@ -394,34 +394,7 @@ impl<T: ?Sized> *mut T {
         if self.is_null() { None } else { Some(unsafe { &*(self as *const MaybeUninit<T>) }) }
     }
 
-    /// Adds a signed offset to a pointer.
-    ///
-    /// `count` is in units of T; e.g., a `count` of 3 represents a pointer
-    /// offset of `3 * size_of::<T>()` bytes.
-    ///
-    /// # Safety
-    ///
-    /// If any of the following conditions are violated, the result is Undefined Behavior:
-    ///
-    /// * The offset in bytes, `count * size_of::<T>()`, computed on mathematical integers (without
-    ///   "wrapping around"), must fit in an `isize`.
-    ///
-    /// * If the computed offset is non-zero, then `self` must be [derived from][crate::ptr#provenance] a pointer to some
-    ///   [allocated object], and the entire memory range between `self` and the result must be in
-    ///   bounds of that allocated object. In particular, this range must not "wrap around" the edge
-    ///   of the address space.
-    ///
-    /// Allocated objects can never be larger than `isize::MAX` bytes, so if the computed offset
-    /// stays in bounds of the allocated object, it is guaranteed to satisfy the first requirement.
-    /// This implies, for instance, that `vec.as_ptr().add(vec.len())` (for `vec: Vec<T>`) is always
-    /// safe.
-    ///
-    /// Consider using [`wrapping_offset`] instead if these constraints are
-    /// difficult to satisfy. The only advantage of this method is that it
-    /// enables more aggressive compiler optimizations.
-    ///
-    /// [`wrapping_offset`]: #method.wrapping_offset
-    /// [allocated object]: crate::ptr#allocated-object
+    #[doc = include_str!("./docs/offset.md")]
     ///
     /// # Examples
     ///
@@ -438,7 +411,7 @@ impl<T: ?Sized> *mut T {
     #[must_use = "returns a new pointer rather than modifying its argument"]
     #[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")]
     #[inline(always)]
-    #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
+    #[track_caller]
     pub const unsafe fn offset(self, count: isize) -> *mut T
     where
         T: Sized,
@@ -475,7 +448,7 @@ impl<T: ?Sized> *mut T {
 
         // SAFETY: the caller must uphold the safety contract for `offset`.
         // The obtained pointer is valid for writes since the caller must
-        // guarantee that it points to the same allocated object as `self`.
+        // guarantee that it points to the same allocation as `self`.
         unsafe { intrinsics::offset(self, count) }
     }
 
@@ -493,7 +466,7 @@ impl<T: ?Sized> *mut T {
     #[inline(always)]
     #[stable(feature = "pointer_byte_offsets", since = "1.75.0")]
     #[rustc_const_stable(feature = "const_pointer_byte_offsets", since = "1.75.0")]
-    #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
+    #[track_caller]
     pub const unsafe fn byte_offset(self, count: isize) -> Self {
         // SAFETY: the caller must uphold the safety contract for `offset`.
         unsafe { self.cast::<u8>().offset(count).with_metadata_of(self) }
@@ -508,17 +481,17 @@ impl<T: ?Sized> *mut T {
     ///
     /// This operation itself is always safe, but using the resulting pointer is not.
     ///
-    /// The resulting pointer "remembers" the [allocated object] that `self` points to
+    /// The resulting pointer "remembers" the [allocation] that `self` points to
     /// (this is called "[Provenance](ptr/index.html#provenance)").
-    /// The pointer must not be used to read or write other allocated objects.
+    /// The pointer must not be used to read or write other allocations.
     ///
     /// In other words, `let z = x.wrapping_offset((y as isize) - (x as isize))` does *not* make `z`
     /// the same as `y` even if we assume `T` has size `1` and there is no overflow: `z` is still
     /// attached to the object `x` is attached to, and dereferencing it is Undefined Behavior unless
-    /// `x` and `y` point into the same allocated object.
+    /// `x` and `y` point into the same allocation.
     ///
     /// Compared to [`offset`], this method basically delays the requirement of staying within the
-    /// same allocated object: [`offset`] is immediate Undefined Behavior when crossing object
+    /// same allocation: [`offset`] is immediate Undefined Behavior when crossing object
     /// boundaries; `wrapping_offset` produces a pointer but still leads to Undefined Behavior if a
     /// pointer is dereferenced when it is out-of-bounds of the object it is attached to. [`offset`]
     /// can be optimized better and is thus preferable in performance-sensitive code.
@@ -526,10 +499,10 @@ impl<T: ?Sized> *mut T {
     /// The delayed check only considers the value of the pointer that was dereferenced, not the
     /// intermediate values used during the computation of the final result. For example,
     /// `x.wrapping_offset(o).wrapping_offset(o.wrapping_neg())` is always the same as `x`. In other
-    /// words, leaving the allocated object and then re-entering it later is permitted.
+    /// words, leaving the allocation and then re-entering it later is permitted.
     ///
     /// [`offset`]: #method.offset
-    /// [allocated object]: crate::ptr#allocated-object
+    /// [allocation]: crate::ptr#allocation
     ///
     /// # Examples
     ///
@@ -818,7 +791,7 @@ impl<T: ?Sized> *mut T {
     /// * `self` and `origin` must either
     ///
     ///   * point to the same address, or
-    ///   * both be [derived from][crate::ptr#provenance] a pointer to the same [allocated object], and the memory range between
+    ///   * both be [derived from][crate::ptr#provenance] a pointer to the same [allocation], and the memory range between
     ///     the two pointers must be in bounds of that object. (See below for an example.)
     ///
     /// * The distance between the pointers, in bytes, must be an exact multiple
@@ -826,10 +799,10 @@ impl<T: ?Sized> *mut T {
     ///
     /// As a consequence, the absolute distance between the pointers, in bytes, computed on
     /// mathematical integers (without "wrapping around"), cannot overflow an `isize`. This is
-    /// implied by the in-bounds requirement, and the fact that no allocated object can be larger
+    /// implied by the in-bounds requirement, and the fact that no allocation can be larger
     /// than `isize::MAX` bytes.
     ///
-    /// The requirement for pointers to be derived from the same allocated object is primarily
+    /// The requirement for pointers to be derived from the same allocation is primarily
     /// needed for `const`-compatibility: the distance between pointers into *different* allocated
     /// objects is not known at compile-time. However, the requirement also exists at
     /// runtime and may be exploited by optimizations. If you wish to compute the difference between
@@ -838,7 +811,7 @@ impl<T: ?Sized> *mut T {
     // FIXME: recommend `addr()` instead of `as usize` once that is stable.
     ///
     /// [`add`]: #method.add
-    /// [allocated object]: crate::ptr#allocated-object
+    /// [allocation]: crate::ptr#allocation
     ///
     /// # Panics
     ///
@@ -968,7 +941,7 @@ impl<T: ?Sized> *mut T {
     #[stable(feature = "ptr_sub_ptr", since = "1.87.0")]
     #[rustc_const_stable(feature = "const_ptr_sub_ptr", since = "1.87.0")]
     #[inline]
-    #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
+    #[track_caller]
     pub const unsafe fn offset_from_unsigned(self, origin: *const T) -> usize
     where
         T: Sized,
@@ -990,50 +963,19 @@ impl<T: ?Sized> *mut T {
     #[stable(feature = "ptr_sub_ptr", since = "1.87.0")]
     #[rustc_const_stable(feature = "const_ptr_sub_ptr", since = "1.87.0")]
     #[inline]
-    #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
+    #[track_caller]
     pub const unsafe fn byte_offset_from_unsigned<U: ?Sized>(self, origin: *mut U) -> usize {
         // SAFETY: the caller must uphold the safety contract for `byte_offset_from_unsigned`.
         unsafe { (self as *const T).byte_offset_from_unsigned(origin) }
     }
 
-    /// Adds an unsigned offset to a pointer.
-    ///
-    /// This can only move the pointer forward (or not move it). If you need to move forward or
-    /// backward depending on the value, then you might want [`offset`](#method.offset) instead
-    /// which takes a signed offset.
-    ///
-    /// `count` is in units of T; e.g., a `count` of 3 represents a pointer
-    /// offset of `3 * size_of::<T>()` bytes.
-    ///
-    /// # Safety
-    ///
-    /// If any of the following conditions are violated, the result is Undefined Behavior:
-    ///
-    /// * The offset in bytes, `count * size_of::<T>()`, computed on mathematical integers (without
-    ///   "wrapping around"), must fit in an `isize`.
-    ///
-    /// * If the computed offset is non-zero, then `self` must be [derived from][crate::ptr#provenance] a pointer to some
-    ///   [allocated object], and the entire memory range between `self` and the result must be in
-    ///   bounds of that allocated object. In particular, this range must not "wrap around" the edge
-    ///   of the address space.
-    ///
-    /// Allocated objects can never be larger than `isize::MAX` bytes, so if the computed offset
-    /// stays in bounds of the allocated object, it is guaranteed to satisfy the first requirement.
-    /// This implies, for instance, that `vec.as_ptr().add(vec.len())` (for `vec: Vec<T>`) is always
-    /// safe.
-    ///
-    /// Consider using [`wrapping_add`] instead if these constraints are
-    /// difficult to satisfy. The only advantage of this method is that it
-    /// enables more aggressive compiler optimizations.
-    ///
-    /// [`wrapping_add`]: #method.wrapping_add
-    /// [allocated object]: crate::ptr#allocated-object
+    #[doc = include_str!("./docs/add.md")]
     ///
     /// # Examples
     ///
     /// ```
-    /// let s: &str = "123";
-    /// let ptr: *const u8 = s.as_ptr();
+    /// let mut s: String = "123".to_string();
+    /// let ptr: *mut u8 = s.as_mut_ptr();
     ///
     /// unsafe {
     ///     assert_eq!('2', *ptr.add(1) as char);
@@ -1044,7 +986,7 @@ impl<T: ?Sized> *mut T {
     #[must_use = "returns a new pointer rather than modifying its argument"]
     #[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")]
     #[inline(always)]
-    #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
+    #[track_caller]
     pub const unsafe fn add(self, count: usize) -> Self
     where
         T: Sized,
@@ -1096,7 +1038,7 @@ impl<T: ?Sized> *mut T {
     #[inline(always)]
     #[stable(feature = "pointer_byte_offsets", since = "1.75.0")]
     #[rustc_const_stable(feature = "const_pointer_byte_offsets", since = "1.75.0")]
-    #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
+    #[track_caller]
     pub const unsafe fn byte_add(self, count: usize) -> Self {
         // SAFETY: the caller must uphold the safety contract for `add`.
         unsafe { self.cast::<u8>().add(count).with_metadata_of(self) }
@@ -1119,12 +1061,12 @@ impl<T: ?Sized> *mut T {
     ///   "wrapping around"), must fit in an `isize`.
     ///
     /// * If the computed offset is non-zero, then `self` must be [derived from][crate::ptr#provenance] a pointer to some
-    ///   [allocated object], and the entire memory range between `self` and the result must be in
-    ///   bounds of that allocated object. In particular, this range must not "wrap around" the edge
+    ///   [allocation], and the entire memory range between `self` and the result must be in
+    ///   bounds of that allocation. In particular, this range must not "wrap around" the edge
     ///   of the address space.
     ///
-    /// Allocated objects can never be larger than `isize::MAX` bytes, so if the computed offset
-    /// stays in bounds of the allocated object, it is guaranteed to satisfy the first requirement.
+    /// Allocations can never be larger than `isize::MAX` bytes, so if the computed offset
+    /// stays in bounds of the allocation, it is guaranteed to satisfy the first requirement.
     /// This implies, for instance, that `vec.as_ptr().add(vec.len())` (for `vec: Vec<T>`) is always
     /// safe.
     ///
@@ -1133,7 +1075,7 @@ impl<T: ?Sized> *mut T {
     /// enables more aggressive compiler optimizations.
     ///
     /// [`wrapping_sub`]: #method.wrapping_sub
-    /// [allocated object]: crate::ptr#allocated-object
+    /// [allocation]: crate::ptr#allocation
     ///
     /// # Examples
     ///
@@ -1150,7 +1092,7 @@ impl<T: ?Sized> *mut T {
     #[must_use = "returns a new pointer rather than modifying its argument"]
     #[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")]
     #[inline(always)]
-    #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
+    #[track_caller]
     pub const unsafe fn sub(self, count: usize) -> Self
     where
         T: Sized,
@@ -1208,7 +1150,7 @@ impl<T: ?Sized> *mut T {
     #[inline(always)]
     #[stable(feature = "pointer_byte_offsets", since = "1.75.0")]
     #[rustc_const_stable(feature = "const_pointer_byte_offsets", since = "1.75.0")]
-    #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
+    #[track_caller]
     pub const unsafe fn byte_sub(self, count: usize) -> Self {
         // SAFETY: the caller must uphold the safety contract for `sub`.
         unsafe { self.cast::<u8>().sub(count).with_metadata_of(self) }
@@ -1223,16 +1165,16 @@ impl<T: ?Sized> *mut T {
     ///
     /// This operation itself is always safe, but using the resulting pointer is not.
     ///
-    /// The resulting pointer "remembers" the [allocated object] that `self` points to; it must not
-    /// be used to read or write other allocated objects.
+    /// The resulting pointer "remembers" the [allocation] that `self` points to; it must not
+    /// be used to read or write other allocations.
     ///
     /// In other words, `let z = x.wrapping_add((y as usize) - (x as usize))` does *not* make `z`
     /// the same as `y` even if we assume `T` has size `1` and there is no overflow: `z` is still
     /// attached to the object `x` is attached to, and dereferencing it is Undefined Behavior unless
-    /// `x` and `y` point into the same allocated object.
+    /// `x` and `y` point into the same allocation.
     ///
     /// Compared to [`add`], this method basically delays the requirement of staying within the
-    /// same allocated object: [`add`] is immediate Undefined Behavior when crossing object
+    /// same allocation: [`add`] is immediate Undefined Behavior when crossing object
     /// boundaries; `wrapping_add` produces a pointer but still leads to Undefined Behavior if a
     /// pointer is dereferenced when it is out-of-bounds of the object it is attached to. [`add`]
     /// can be optimized better and is thus preferable in performance-sensitive code.
@@ -1240,10 +1182,10 @@ impl<T: ?Sized> *mut T {
     /// The delayed check only considers the value of the pointer that was dereferenced, not the
     /// intermediate values used during the computation of the final result. For example,
     /// `x.wrapping_add(o).wrapping_sub(o)` is always the same as `x`. In other words, leaving the
-    /// allocated object and then re-entering it later is permitted.
+    /// allocation and then re-entering it later is permitted.
     ///
     /// [`add`]: #method.add
-    /// [allocated object]: crate::ptr#allocated-object
+    /// [allocation]: crate::ptr#allocation
     ///
     /// # Examples
     ///
@@ -1299,16 +1241,16 @@ impl<T: ?Sized> *mut T {
     ///
     /// This operation itself is always safe, but using the resulting pointer is not.
     ///
-    /// The resulting pointer "remembers" the [allocated object] that `self` points to; it must not
-    /// be used to read or write other allocated objects.
+    /// The resulting pointer "remembers" the [allocation] that `self` points to; it must not
+    /// be used to read or write other allocations.
     ///
     /// In other words, `let z = x.wrapping_sub((x as usize) - (y as usize))` does *not* make `z`
     /// the same as `y` even if we assume `T` has size `1` and there is no overflow: `z` is still
     /// attached to the object `x` is attached to, and dereferencing it is Undefined Behavior unless
-    /// `x` and `y` point into the same allocated object.
+    /// `x` and `y` point into the same allocation.
     ///
     /// Compared to [`sub`], this method basically delays the requirement of staying within the
-    /// same allocated object: [`sub`] is immediate Undefined Behavior when crossing object
+    /// same allocation: [`sub`] is immediate Undefined Behavior when crossing object
     /// boundaries; `wrapping_sub` produces a pointer but still leads to Undefined Behavior if a
     /// pointer is dereferenced when it is out-of-bounds of the object it is attached to. [`sub`]
     /// can be optimized better and is thus preferable in performance-sensitive code.
@@ -1316,10 +1258,10 @@ impl<T: ?Sized> *mut T {
     /// The delayed check only considers the value of the pointer that was dereferenced, not the
     /// intermediate values used during the computation of the final result. For example,
     /// `x.wrapping_add(o).wrapping_sub(o)` is always the same as `x`. In other words, leaving the
-    /// allocated object and then re-entering it later is permitted.
+    /// allocation and then re-entering it later is permitted.
     ///
     /// [`sub`]: #method.sub
-    /// [allocated object]: crate::ptr#allocated-object
+    /// [allocation]: crate::ptr#allocation
     ///
     /// # Examples
     ///
@@ -1375,7 +1317,7 @@ impl<T: ?Sized> *mut T {
     #[stable(feature = "pointer_methods", since = "1.26.0")]
     #[rustc_const_stable(feature = "const_ptr_read", since = "1.71.0")]
     #[inline(always)]
-    #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
+    #[track_caller]
     pub const unsafe fn read(self) -> T
     where
         T: Sized,
@@ -1396,7 +1338,7 @@ impl<T: ?Sized> *mut T {
     /// [`ptr::read_volatile`]: crate::ptr::read_volatile()
     #[stable(feature = "pointer_methods", since = "1.26.0")]
     #[inline(always)]
-    #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
+    #[track_caller]
     pub unsafe fn read_volatile(self) -> T
     where
         T: Sized,
@@ -1416,7 +1358,7 @@ impl<T: ?Sized> *mut T {
     #[stable(feature = "pointer_methods", since = "1.26.0")]
     #[rustc_const_stable(feature = "const_ptr_read", since = "1.71.0")]
     #[inline(always)]
-    #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
+    #[track_caller]
     pub const unsafe fn read_unaligned(self) -> T
     where
         T: Sized,
@@ -1436,7 +1378,7 @@ impl<T: ?Sized> *mut T {
     #[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.83.0")]
     #[stable(feature = "pointer_methods", since = "1.26.0")]
     #[inline(always)]
-    #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
+    #[track_caller]
     pub const unsafe fn copy_to(self, dest: *mut T, count: usize)
     where
         T: Sized,
@@ -1456,7 +1398,7 @@ impl<T: ?Sized> *mut T {
     #[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.83.0")]
     #[stable(feature = "pointer_methods", since = "1.26.0")]
     #[inline(always)]
-    #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
+    #[track_caller]
     pub const unsafe fn copy_to_nonoverlapping(self, dest: *mut T, count: usize)
     where
         T: Sized,
@@ -1476,7 +1418,7 @@ impl<T: ?Sized> *mut T {
     #[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.83.0")]
     #[stable(feature = "pointer_methods", since = "1.26.0")]
     #[inline(always)]
-    #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
+    #[track_caller]
     pub const unsafe fn copy_from(self, src: *const T, count: usize)
     where
         T: Sized,
@@ -1496,7 +1438,7 @@ impl<T: ?Sized> *mut T {
     #[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.83.0")]
     #[stable(feature = "pointer_methods", since = "1.26.0")]
     #[inline(always)]
-    #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
+    #[track_caller]
     pub const unsafe fn copy_from_nonoverlapping(self, src: *const T, count: usize)
     where
         T: Sized,
@@ -1526,7 +1468,7 @@ impl<T: ?Sized> *mut T {
     #[stable(feature = "pointer_methods", since = "1.26.0")]
     #[rustc_const_stable(feature = "const_ptr_write", since = "1.83.0")]
     #[inline(always)]
-    #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
+    #[track_caller]
     pub const unsafe fn write(self, val: T)
     where
         T: Sized,
@@ -1545,7 +1487,7 @@ impl<T: ?Sized> *mut T {
     #[stable(feature = "pointer_methods", since = "1.26.0")]
     #[rustc_const_stable(feature = "const_ptr_write", since = "1.83.0")]
     #[inline(always)]
-    #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
+    #[track_caller]
     pub const unsafe fn write_bytes(self, val: u8, count: usize)
     where
         T: Sized,
@@ -1566,7 +1508,7 @@ impl<T: ?Sized> *mut T {
     /// [`ptr::write_volatile`]: crate::ptr::write_volatile()
     #[stable(feature = "pointer_methods", since = "1.26.0")]
     #[inline(always)]
-    #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
+    #[track_caller]
     pub unsafe fn write_volatile(self, val: T)
     where
         T: Sized,
@@ -1586,7 +1528,7 @@ impl<T: ?Sized> *mut T {
     #[stable(feature = "pointer_methods", since = "1.26.0")]
     #[rustc_const_stable(feature = "const_ptr_write", since = "1.83.0")]
     #[inline(always)]
-    #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
+    #[track_caller]
     pub const unsafe fn write_unaligned(self, val: T)
     where
         T: Sized,
@@ -1828,7 +1770,7 @@ impl<T> *mut [T] {
     ///
     /// # Safety
     ///
-    /// `mid` must be [in-bounds] of the underlying [allocated object].
+    /// `mid` must be [in-bounds] of the underlying [allocation].
     /// Which means `self` must be dereferenceable and span a single allocation
     /// that is at least `mid * size_of::<T>()` bytes long. Not upholding these
     /// requirements is *[undefined behavior]* even if the resulting pointers are not used.
@@ -1839,7 +1781,7 @@ impl<T> *mut [T] {
     ///
     /// [`split_at_mut_unchecked`]: #method.split_at_mut_unchecked
     /// [in-bounds]: #method.add
-    /// [allocated object]: crate::ptr#allocated-object
+    /// [allocation]: crate::ptr#allocation
     /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
     ///
     /// # Examples
@@ -1874,13 +1816,14 @@ impl<T> *mut [T] {
     ///
     /// # Safety
     ///
-    /// `mid` must be [in-bounds] of the underlying [allocated object].
+    /// `mid` must be [in-bounds] of the underlying [allocation].
     /// Which means `self` must be dereferenceable and span a single allocation
     /// that is at least `mid * size_of::<T>()` bytes long. Not upholding these
     /// requirements is *[undefined behavior]* even if the resulting pointers are not used.
     ///
     /// [in-bounds]: #method.add
     /// [out-of-bounds index]: #method.add
+    /// [allocation]: crate::ptr#allocation
     /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
     ///
     /// # Examples
@@ -1980,8 +1923,8 @@ impl<T> *mut [T] {
     /// * 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:
     ///
-    ///     * The entire memory range of this slice must be contained within a single [allocated object]!
-    ///       Slices can never span across multiple allocated objects.
+    ///     * The entire memory range of this slice must be contained within a single [allocation]!
+    ///       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
@@ -2002,7 +1945,7 @@ impl<T> *mut [T] {
     /// See also [`slice::from_raw_parts`][].
     ///
     /// [valid]: crate::ptr#safety
-    /// [allocated object]: crate::ptr#allocated-object
+    /// [allocation]: crate::ptr#allocation
     ///
     /// # Panics during const evaluation
     ///
@@ -2038,8 +1981,8 @@ impl<T> *mut [T] {
     /// * The pointer must be [valid] for reads and writes for `ptr.len() * size_of::<T>()`
     ///   many bytes, and it must be properly aligned. This means in particular:
     ///
-    ///     * The entire memory range of this slice must be contained within a single [allocated object]!
-    ///       Slices can never span across multiple allocated objects.
+    ///     * The entire memory range of this slice must be contained within a single [allocation]!
+    ///       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
@@ -2060,7 +2003,7 @@ impl<T> *mut [T] {
     /// See also [`slice::from_raw_parts_mut`][].
     ///
     /// [valid]: crate::ptr#safety
-    /// [allocated object]: crate::ptr#allocated-object
+    /// [allocation]: crate::ptr#allocation
     ///
     /// # Panics during const evaluation
     ///
diff --git a/library/core/src/ptr/non_null.rs b/library/core/src/ptr/non_null.rs
index 7c9b898f8e9..91b8d1bf9a7 100644
--- a/library/core/src/ptr/non_null.rs
+++ b/library/core/src/ptr/non_null.rs
@@ -216,6 +216,7 @@ impl<T: ?Sized> NonNull<T> {
     #[stable(feature = "nonnull", since = "1.25.0")]
     #[rustc_const_stable(feature = "const_nonnull_new_unchecked", since = "1.25.0")]
     #[inline]
+    #[track_caller]
     pub const unsafe fn new_unchecked(ptr: *mut T) -> Self {
         // SAFETY: the caller must guarantee that `ptr` is non-null.
         unsafe {
@@ -529,16 +530,16 @@ impl<T: ?Sized> NonNull<T> {
     /// * The computed offset, `count * size_of::<T>()` bytes, must not overflow `isize`.
     ///
     /// * If the computed offset is non-zero, then `self` must be derived from a pointer to some
-    ///   [allocated object], and the entire memory range between `self` and the result must be in
-    ///   bounds of that allocated object. In particular, this range must not "wrap around" the edge
+    ///   [allocation], and the entire memory range between `self` and the result must be in
+    ///   bounds of that allocation. In particular, this range must not "wrap around" the edge
     ///   of the address space.
     ///
-    /// Allocated objects can never be larger than `isize::MAX` bytes, so if the computed offset
-    /// stays in bounds of the allocated object, it is guaranteed to satisfy the first requirement.
+    /// Allocations can never be larger than `isize::MAX` bytes, so if the computed offset
+    /// stays in bounds of the allocation, it is guaranteed to satisfy the first requirement.
     /// This implies, for instance, that `vec.as_ptr().add(vec.len())` (for `vec: Vec<T>`) is always
     /// safe.
     ///
-    /// [allocated object]: crate::ptr#allocated-object
+    /// [allocation]: crate::ptr#allocation
     ///
     /// # Examples
     ///
@@ -605,16 +606,16 @@ impl<T: ?Sized> NonNull<T> {
     /// * The computed offset, `count * size_of::<T>()` bytes, must not overflow `isize`.
     ///
     /// * If the computed offset is non-zero, then `self` must be derived from a pointer to some
-    ///   [allocated object], and the entire memory range between `self` and the result must be in
-    ///   bounds of that allocated object. In particular, this range must not "wrap around" the edge
+    ///   [allocation], and the entire memory range between `self` and the result must be in
+    ///   bounds of that allocation. In particular, this range must not "wrap around" the edge
     ///   of the address space.
     ///
-    /// Allocated objects can never be larger than `isize::MAX` bytes, so if the computed offset
-    /// stays in bounds of the allocated object, it is guaranteed to satisfy the first requirement.
+    /// Allocations can never be larger than `isize::MAX` bytes, so if the computed offset
+    /// stays in bounds of the allocation, it is guaranteed to satisfy the first requirement.
     /// This implies, for instance, that `vec.as_ptr().add(vec.len())` (for `vec: Vec<T>`) is always
     /// safe.
     ///
-    /// [allocated object]: crate::ptr#allocated-object
+    /// [allocation]: crate::ptr#allocation
     ///
     /// # Examples
     ///
@@ -682,16 +683,16 @@ impl<T: ?Sized> NonNull<T> {
     /// * The computed offset, `count * size_of::<T>()` bytes, must not overflow `isize`.
     ///
     /// * If the computed offset is non-zero, then `self` must be derived from a pointer to some
-    ///   [allocated object], and the entire memory range between `self` and the result must be in
-    ///   bounds of that allocated object. In particular, this range must not "wrap around" the edge
+    ///   [allocation], and the entire memory range between `self` and the result must be in
+    ///   bounds of that allocation. In particular, this range must not "wrap around" the edge
     ///   of the address space.
     ///
-    /// Allocated objects can never be larger than `isize::MAX` bytes, so if the computed offset
-    /// stays in bounds of the allocated object, it is guaranteed to satisfy the first requirement.
+    /// Allocations can never be larger than `isize::MAX` bytes, so if the computed offset
+    /// stays in bounds of the allocation, it is guaranteed to satisfy the first requirement.
     /// This implies, for instance, that `vec.as_ptr().add(vec.len())` (for `vec: Vec<T>`) is always
     /// safe.
     ///
-    /// [allocated object]: crate::ptr#allocated-object
+    /// [allocation]: crate::ptr#allocation
     ///
     /// # Examples
     ///
@@ -774,7 +775,7 @@ impl<T: ?Sized> NonNull<T> {
     /// * `self` and `origin` must either
     ///
     ///   * point to the same address, or
-    ///   * both be *derived from* a pointer to the same [allocated object], and the memory range between
+    ///   * both be *derived from* a pointer to the same [allocation], and the memory range between
     ///     the two pointers must be in bounds of that object. (See below for an example.)
     ///
     /// * The distance between the pointers, in bytes, must be an exact multiple
@@ -782,10 +783,10 @@ impl<T: ?Sized> NonNull<T> {
     ///
     /// As a consequence, the absolute distance between the pointers, in bytes, computed on
     /// mathematical integers (without "wrapping around"), cannot overflow an `isize`. This is
-    /// implied by the in-bounds requirement, and the fact that no allocated object can be larger
+    /// implied by the in-bounds requirement, and the fact that no allocation can be larger
     /// than `isize::MAX` bytes.
     ///
-    /// The requirement for pointers to be derived from the same allocated object is primarily
+    /// The requirement for pointers to be derived from the same allocation is primarily
     /// needed for `const`-compatibility: the distance between pointers into *different* allocated
     /// objects is not known at compile-time. However, the requirement also exists at
     /// runtime and may be exploited by optimizations. If you wish to compute the difference between
@@ -794,7 +795,7 @@ impl<T: ?Sized> NonNull<T> {
     // FIXME: recommend `addr()` instead of `as usize` once that is stable.
     ///
     /// [`add`]: #method.add
-    /// [allocated object]: crate::ptr#allocated-object
+    /// [allocation]: crate::ptr#allocation
     ///
     /// # Panics
     ///
@@ -1474,8 +1475,8 @@ impl<T> NonNull<[T]> {
     /// * 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:
     ///
-    ///     * The entire memory range of this slice must be contained within a single allocated object!
-    ///       Slices can never span across multiple allocated objects.
+    ///     * The entire memory range of this slice must be contained within a single allocation!
+    ///       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
@@ -1519,8 +1520,8 @@ impl<T> NonNull<[T]> {
     /// * The pointer must be [valid] for reads and writes for `ptr.len() * size_of::<T>()`
     ///   many bytes, and it must be properly aligned. This means in particular:
     ///
-    ///     * The entire memory range of this slice must be contained within a single allocated object!
-    ///       Slices can never span across multiple allocated objects.
+    ///     * The entire memory range of this slice must be contained within a single allocation!
+    ///       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
diff --git a/library/core/src/result.rs b/library/core/src/result.rs
index 736ffb7d0ca..23e32c2e0f0 100644
--- a/library/core/src/result.rs
+++ b/library/core/src/result.rs
@@ -858,6 +858,36 @@ impl<T, E> Result<T, E> {
         }
     }
 
+    /// Maps a `Result<T, E>` to a `U` by applying function `f` to the contained
+    /// value if the result is [`Ok`], otherwise if [`Err`], returns the
+    /// [default value] for the type `U`.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(result_option_map_or_default)]
+    ///
+    /// let x: Result<_, &str> = Ok("foo");
+    /// let y: Result<&str, _> = Err("bar");
+    ///
+    /// assert_eq!(x.map_or_default(|x| x.len()), 3);
+    /// assert_eq!(y.map_or_default(|y| y.len()), 0);
+    /// ```
+    ///
+    /// [default value]: Default::default
+    #[inline]
+    #[unstable(feature = "result_option_map_or_default", issue = "138099")]
+    pub fn map_or_default<U, F>(self, f: F) -> U
+    where
+        U: Default,
+        F: FnOnce(T) -> U,
+    {
+        match self {
+            Ok(t) => f(t),
+            Err(_) => U::default(),
+        }
+    }
+
     /// Maps a `Result<T, E>` to `Result<T, F>` by applying a function to a
     /// contained [`Err`] value, leaving an [`Ok`] value untouched.
     ///
@@ -1692,7 +1722,6 @@ impl<T, E> Result<Result<T, E>, E> {
     /// # Examples
     ///
     /// ```
-    /// #![feature(result_flattening)]
     /// let x: Result<Result<&'static str, u32>, u32> = Ok(Ok("hello"));
     /// assert_eq!(Ok("hello"), x.flatten());
     ///
@@ -1706,14 +1735,14 @@ impl<T, E> Result<Result<T, E>, E> {
     /// Flattening only removes one level of nesting at a time:
     ///
     /// ```
-    /// #![feature(result_flattening)]
     /// let x: Result<Result<Result<&'static str, u32>, u32>, u32> = Ok(Ok(Ok("hello")));
     /// assert_eq!(Ok(Ok("hello")), x.flatten());
     /// assert_eq!(Ok("hello"), x.flatten().flatten());
     /// ```
     #[inline]
-    #[unstable(feature = "result_flattening", issue = "70142")]
-    #[rustc_const_unstable(feature = "result_flattening", issue = "70142")]
+    #[stable(feature = "result_flattening", since = "CURRENT_RUSTC_VERSION")]
+    #[rustc_allow_const_fn_unstable(const_precise_live_drops)]
+    #[rustc_const_stable(feature = "result_flattening", since = "CURRENT_RUSTC_VERSION")]
     pub const fn flatten(self) -> Result<T, E> {
         // FIXME(const-hack): could be written with `and_then`
         match self {
diff --git a/library/core/src/slice/index.rs b/library/core/src/slice/index.rs
index 409bad9f061..69160a911b2 100644
--- a/library/core/src/slice/index.rs
+++ b/library/core/src/slice/index.rs
@@ -1,5 +1,7 @@
 //! Indexing implementations for `[T]`.
 
+#[cfg(not(bootstrap))]
+use crate::intrinsics::slice_get_unchecked;
 use crate::panic::const_panic;
 use crate::ub_checks::assert_unsafe_precondition;
 use crate::{ops, range};
@@ -83,6 +85,7 @@ const fn slice_end_index_overflow_fail() -> ! {
 // Both the safe and unsafe public methods share these helpers,
 // which use intrinsics directly to get *no* extra checks.
 
+#[cfg(bootstrap)]
 #[inline(always)]
 const unsafe fn get_noubcheck<T>(ptr: *const [T], index: usize) -> *const T {
     let ptr = ptr as *const T;
@@ -90,6 +93,7 @@ const unsafe fn get_noubcheck<T>(ptr: *const [T], index: usize) -> *const T {
     unsafe { crate::intrinsics::offset(ptr, index) }
 }
 
+#[cfg(bootstrap)]
 #[inline(always)]
 const unsafe fn get_mut_noubcheck<T>(ptr: *mut [T], index: usize) -> *mut T {
     let ptr = ptr as *mut T;
@@ -103,8 +107,9 @@ const unsafe fn get_offset_len_noubcheck<T>(
     offset: usize,
     len: usize,
 ) -> *const [T] {
+    let ptr = ptr as *const T;
     // SAFETY: The caller already checked these preconditions
-    let ptr = unsafe { get_noubcheck(ptr, offset) };
+    let ptr = unsafe { crate::intrinsics::offset(ptr, offset) };
     crate::intrinsics::aggregate_raw_ptr(ptr, len)
 }
 
@@ -114,8 +119,9 @@ const unsafe fn get_offset_len_mut_noubcheck<T>(
     offset: usize,
     len: usize,
 ) -> *mut [T] {
+    let ptr = ptr as *mut T;
     // SAFETY: The caller already checked these preconditions
-    let ptr = unsafe { get_mut_noubcheck(ptr, offset) };
+    let ptr = unsafe { crate::intrinsics::offset(ptr, offset) };
     crate::intrinsics::aggregate_raw_ptr(ptr, len)
 }
 
@@ -224,21 +230,42 @@ unsafe impl<T> SliceIndex<[T]> for usize {
 
     #[inline]
     fn get(self, slice: &[T]) -> Option<&T> {
-        // SAFETY: `self` is checked to be in bounds.
-        if self < slice.len() { unsafe { Some(&*get_noubcheck(slice, self)) } } else { None }
+        if self < slice.len() {
+            #[cfg(bootstrap)]
+            // SAFETY: `self` is checked to be in bounds.
+            unsafe {
+                Some(&*get_noubcheck(slice, self))
+            }
+            #[cfg(not(bootstrap))]
+            // SAFETY: `self` is checked to be in bounds.
+            unsafe {
+                Some(slice_get_unchecked(slice, self))
+            }
+        } else {
+            None
+        }
     }
 
     #[inline]
     fn get_mut(self, slice: &mut [T]) -> Option<&mut T> {
         if self < slice.len() {
+            #[cfg(bootstrap)]
+            // SAFETY: `self` is checked to be in bounds.
+            unsafe {
+                Some(&mut *get_mut_noubcheck(slice, self))
+            }
+            #[cfg(not(bootstrap))]
             // SAFETY: `self` is checked to be in bounds.
-            unsafe { Some(&mut *get_mut_noubcheck(slice, self)) }
+            unsafe {
+                Some(slice_get_unchecked(slice, self))
+            }
         } else {
             None
         }
     }
 
     #[inline]
+    #[track_caller]
     unsafe fn get_unchecked(self, slice: *const [T]) -> *const T {
         assert_unsafe_precondition!(
             check_language_ub,
@@ -253,11 +280,19 @@ unsafe impl<T> SliceIndex<[T]> for usize {
             // Use intrinsics::assume instead of hint::assert_unchecked so that we don't check the
             // precondition of this function twice.
             crate::intrinsics::assume(self < slice.len());
-            get_noubcheck(slice, self)
+            #[cfg(bootstrap)]
+            {
+                get_noubcheck(slice, self)
+            }
+            #[cfg(not(bootstrap))]
+            {
+                slice_get_unchecked(slice, self)
+            }
         }
     }
 
     #[inline]
+    #[track_caller]
     unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut T {
         assert_unsafe_precondition!(
             check_library_ub,
@@ -265,7 +300,16 @@ unsafe impl<T> SliceIndex<[T]> for usize {
             (this: usize = self, len: usize = slice.len()) => this < len
         );
         // SAFETY: see comments for `get_unchecked` above.
-        unsafe { get_mut_noubcheck(slice, self) }
+        unsafe {
+            #[cfg(bootstrap)]
+            {
+                get_mut_noubcheck(slice, self)
+            }
+            #[cfg(not(bootstrap))]
+            {
+                slice_get_unchecked(slice, self)
+            }
+        }
     }
 
     #[inline]
@@ -307,6 +351,7 @@ unsafe impl<T> SliceIndex<[T]> for ops::IndexRange {
     }
 
     #[inline]
+    #[track_caller]
     unsafe fn get_unchecked(self, slice: *const [T]) -> *const [T] {
         assert_unsafe_precondition!(
             check_library_ub,
@@ -321,6 +366,7 @@ unsafe impl<T> SliceIndex<[T]> for ops::IndexRange {
     }
 
     #[inline]
+    #[track_caller]
     unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut [T] {
         assert_unsafe_precondition!(
             check_library_ub,
@@ -386,6 +432,7 @@ unsafe impl<T> SliceIndex<[T]> for ops::Range<usize> {
     }
 
     #[inline]
+    #[track_caller]
     unsafe fn get_unchecked(self, slice: *const [T]) -> *const [T] {
         assert_unsafe_precondition!(
             check_library_ub,
@@ -410,6 +457,7 @@ unsafe impl<T> SliceIndex<[T]> for ops::Range<usize> {
     }
 
     #[inline]
+    #[track_caller]
     unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut [T] {
         assert_unsafe_precondition!(
             check_library_ub,
diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs
index 26520123a8d..4f7e1440880 100644
--- a/library/core/src/slice/mod.rs
+++ b/library/core/src/slice/mod.rs
@@ -631,6 +631,7 @@ impl<T> [T] {
     #[rustc_no_implicit_autorefs]
     #[inline]
     #[must_use]
+    #[track_caller]
     pub unsafe fn get_unchecked<I>(&self, index: I) -> &I::Output
     where
         I: SliceIndex<Self>,
@@ -674,6 +675,7 @@ impl<T> [T] {
     #[rustc_no_implicit_autorefs]
     #[inline]
     #[must_use]
+    #[track_caller]
     pub unsafe fn get_unchecked_mut<I>(&mut self, index: I) -> &mut I::Output
     where
         I: SliceIndex<Self>,
@@ -935,6 +937,7 @@ impl<T> [T] {
     /// [`swap`]: slice::swap
     /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
     #[unstable(feature = "slice_swap_unchecked", issue = "88539")]
+    #[track_caller]
     pub const unsafe fn swap_unchecked(&mut self, a: usize, b: usize) {
         assert_unsafe_precondition!(
             check_library_ub,
@@ -1307,6 +1310,7 @@ impl<T> [T] {
     #[rustc_const_stable(feature = "slice_as_chunks", since = "1.88.0")]
     #[inline]
     #[must_use]
+    #[track_caller]
     pub const unsafe fn as_chunks_unchecked<const N: usize>(&self) -> &[[T; N]] {
         assert_unsafe_precondition!(
             check_language_ub,
@@ -1502,6 +1506,7 @@ impl<T> [T] {
     #[rustc_const_stable(feature = "slice_as_chunks", since = "1.88.0")]
     #[inline]
     #[must_use]
+    #[track_caller]
     pub const unsafe fn as_chunks_unchecked_mut<const N: usize>(&mut self) -> &mut [[T; N]] {
         assert_unsafe_precondition!(
             check_language_ub,
@@ -2061,6 +2066,7 @@ impl<T> [T] {
     #[rustc_const_stable(feature = "const_slice_split_at_unchecked", since = "1.77.0")]
     #[inline]
     #[must_use]
+    #[track_caller]
     pub const unsafe fn split_at_unchecked(&self, mid: usize) -> (&[T], &[T]) {
         // FIXME(const-hack): the const function `from_raw_parts` is used to make this
         // function const; previously the implementation used
@@ -2114,6 +2120,7 @@ impl<T> [T] {
     #[rustc_const_stable(feature = "const_slice_split_at_mut", since = "1.83.0")]
     #[inline]
     #[must_use]
+    #[track_caller]
     pub const unsafe fn split_at_mut_unchecked(&mut self, mid: usize) -> (&mut [T], &mut [T]) {
         let len = self.len();
         let ptr = self.as_mut_ptr();
@@ -4642,6 +4649,7 @@ impl<T> [T] {
     /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
     #[stable(feature = "get_many_mut", since = "1.86.0")]
     #[inline]
+    #[track_caller]
     pub unsafe fn get_disjoint_unchecked_mut<I, const N: usize>(
         &mut self,
         indices: [I; N],
diff --git a/library/core/src/slice/raw.rs b/library/core/src/slice/raw.rs
index 3582c7e8b3f..eba2f89a169 100644
--- a/library/core/src/slice/raw.rs
+++ b/library/core/src/slice/raw.rs
@@ -14,8 +14,8 @@ use crate::{array, ptr, ub_checks};
 /// * `data` must be non-null, [valid] for reads for `len * size_of::<T>()` many bytes,
 ///   and it must be properly aligned. This means in particular:
 ///
-///     * The entire memory range of this slice must be contained within a single allocated object!
-///       Slices can never span across multiple allocated objects. See [below](#incorrect-usage)
+///     * The entire memory range of this slice must be contained within a single allocation!
+///       Slices can never span across multiple allocations. See [below](#incorrect-usage)
 ///       for an example incorrectly not taking this into account.
 ///     * `data` must be non-null and aligned even for zero-length slices or slices of ZSTs. One
 ///       reason for this is that enum layout optimizations may rely on references
@@ -65,14 +65,14 @@ use crate::{array, ptr, ub_checks};
 ///     assert_eq!(fst_end, snd_start, "Slices must be contiguous!");
 ///     unsafe {
 ///         // The assertion above ensures `fst` and `snd` are contiguous, but they might
-///         // still be contained within _different allocated objects_, in which case
+///         // still be contained within _different allocations_, in which case
 ///         // creating this slice is undefined behavior.
 ///         slice::from_raw_parts(fst.as_ptr(), fst.len() + snd.len())
 ///     }
 /// }
 ///
 /// fn main() {
-///     // `a` and `b` are different allocated objects...
+///     // `a` and `b` are different allocations...
 ///     let a = 42;
 ///     let b = 27;
 ///     // ... which may nevertheless be laid out contiguously in memory: | a | b |
@@ -120,6 +120,7 @@ use crate::{array, ptr, ub_checks};
 #[rustc_const_stable(feature = "const_slice_from_raw_parts", since = "1.64.0")]
 #[must_use]
 #[rustc_diagnostic_item = "slice_from_raw_parts"]
+#[track_caller]
 pub const unsafe fn from_raw_parts<'a, T>(data: *const T, len: usize) -> &'a [T] {
     // SAFETY: the caller must uphold the safety contract for `from_raw_parts`.
     unsafe {
@@ -149,8 +150,8 @@ pub const unsafe fn from_raw_parts<'a, T>(data: *const T, len: usize) -> &'a [T]
 /// * `data` must be non-null, [valid] for both reads and writes for `len * size_of::<T>()` many bytes,
 ///   and it must be properly aligned. This means in particular:
 ///
-///     * The entire memory range of this slice must be contained within a single allocated object!
-///       Slices can never span across multiple allocated objects.
+///     * The entire memory range of this slice must be contained within a single allocation!
+///       Slices can never span across multiple allocations.
 ///     * `data` must be non-null and aligned even for zero-length slices or slices of ZSTs. 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
@@ -174,6 +175,7 @@ pub const unsafe fn from_raw_parts<'a, T>(data: *const T, len: usize) -> &'a [T]
 #[rustc_const_stable(feature = "const_slice_from_raw_parts_mut", since = "1.83.0")]
 #[must_use]
 #[rustc_diagnostic_item = "slice_from_raw_parts_mut"]
+#[track_caller]
 pub const unsafe fn from_raw_parts_mut<'a, T>(data: *mut T, len: usize) -> &'a mut [T] {
     // SAFETY: the caller must uphold the safety contract for `from_raw_parts_mut`.
     unsafe {
@@ -226,8 +228,8 @@ pub const fn from_mut<T>(s: &mut T) -> &mut [T] {
 ///   the last element, such that the offset from the end to the start pointer is
 ///   the length of the slice.
 ///
-/// * The entire memory range of this slice must be contained within a single allocated object!
-///   Slices can never span across multiple allocated objects.
+/// * The entire memory range of this slice must be contained within a single allocation!
+///   Slices can never span across multiple allocations.
 ///
 /// * The range must contain `N` consecutive properly initialized values of type `T`.
 ///
@@ -270,6 +272,7 @@ pub const fn from_mut<T>(s: &mut T) -> &mut [T] {
 /// [valid]: ptr#safety
 #[unstable(feature = "slice_from_ptr_range", issue = "89792")]
 #[rustc_const_unstable(feature = "const_slice_from_ptr_range", issue = "89792")]
+#[track_caller]
 pub const unsafe fn from_ptr_range<'a, T>(range: Range<*const T>) -> &'a [T] {
     // SAFETY: the caller must uphold the safety contract for `from_ptr_range`.
     unsafe { from_raw_parts(range.start, range.end.offset_from_unsigned(range.start)) }
@@ -295,8 +298,8 @@ pub const unsafe fn from_ptr_range<'a, T>(range: Range<*const T>) -> &'a [T] {
 ///   the last element, such that the offset from the end to the start pointer is
 ///   the length of the slice.
 ///
-/// * The entire memory range of this slice must be contained within a single allocated object!
-///   Slices can never span across multiple allocated objects.
+/// * The entire memory range of this slice must be contained within a single allocation!
+///   Slices can never span across multiple allocations.
 ///
 /// * The range must contain `N` consecutive properly initialized values of type `T`.
 ///
diff --git a/library/core/src/str/converts.rs b/library/core/src/str/converts.rs
index 058628797ea..6da9dce2d87 100644
--- a/library/core/src/str/converts.rs
+++ b/library/core/src/str/converts.rs
@@ -6,6 +6,8 @@ use crate::{mem, ptr};
 
 /// Converts a slice of bytes to a string slice.
 ///
+/// This is an alias to [`str::from_utf8`].
+///
 /// A string slice ([`&str`]) is made of bytes ([`u8`]), and a byte slice
 /// ([`&[u8]`][byteslice]) is made of bytes, so this function converts between
 /// the two. Not all byte slices are valid string slices, however: [`&str`] requires
@@ -97,6 +99,8 @@ pub const fn from_utf8(v: &[u8]) -> Result<&str, Utf8Error> {
 
 /// Converts a mutable slice of bytes to a mutable string slice.
 ///
+/// This is an alias to [`str::from_utf8_mut`].
+///
 /// # Examples
 ///
 /// Basic usage:
@@ -142,6 +146,8 @@ pub const fn from_utf8_mut(v: &mut [u8]) -> Result<&mut str, Utf8Error> {
 /// Converts a slice of bytes to a string slice without checking
 /// that the string contains valid UTF-8.
 ///
+/// This is an alias to [`str::from_utf8_unchecked`].
+///
 /// See the safe version, [`from_utf8`], for more information.
 ///
 /// # Safety
@@ -178,6 +184,8 @@ pub const unsafe fn from_utf8_unchecked(v: &[u8]) -> &str {
 /// Converts a slice of bytes to a string slice without checking
 /// that the string contains valid UTF-8; mutable version.
 ///
+/// This is an alias to [`str::from_utf8_unchecked_mut`].
+///
 /// See the immutable version, [`from_utf8_unchecked()`] for documentation and safety requirements.
 ///
 /// # Examples
diff --git a/library/core/src/str/mod.rs b/library/core/src/str/mod.rs
index e505e228095..06161cb6c7c 100644
--- a/library/core/src/str/mod.rs
+++ b/library/core/src/str/mod.rs
@@ -1173,6 +1173,7 @@ impl str {
     /// The iterator returned will return string slices that are sub-slices of
     /// the original string slice, separated by any amount of ASCII whitespace.
     ///
+    /// This uses the same definition as [`char::is_ascii_whitespace`].
     /// To split by Unicode `Whitespace` instead, use [`split_whitespace`].
     ///
     /// [`split_whitespace`]: str::split_whitespace
@@ -1191,7 +1192,8 @@ impl str {
     /// assert_eq!(None, iter.next());
     /// ```
     ///
-    /// All kinds of ASCII whitespace are considered:
+    /// Various kinds of ASCII whitespace are considered
+    /// (see [`char::is_ascii_whitespace`]):
     ///
     /// ```
     /// let mut iter = " Mary   had\ta little  \n\t lamb".split_ascii_whitespace();
diff --git a/library/core/src/str/traits.rs b/library/core/src/str/traits.rs
index 77c70b978fd..4baf9aacad7 100644
--- a/library/core/src/str/traits.rs
+++ b/library/core/src/str/traits.rs
@@ -186,6 +186,7 @@ unsafe impl SliceIndex<str> for ops::Range<usize> {
         }
     }
     #[inline]
+    #[track_caller]
     unsafe fn get_unchecked(self, slice: *const str) -> *const Self::Output {
         let slice = slice as *const [u8];
 
@@ -213,6 +214,7 @@ unsafe impl SliceIndex<str> for ops::Range<usize> {
         }
     }
     #[inline]
+    #[track_caller]
     unsafe fn get_unchecked_mut(self, slice: *mut str) -> *mut Self::Output {
         let slice = slice as *mut [u8];
 
@@ -288,6 +290,7 @@ unsafe impl SliceIndex<str> for range::Range<usize> {
         }
     }
     #[inline]
+    #[track_caller]
     unsafe fn get_unchecked(self, slice: *const str) -> *const Self::Output {
         let slice = slice as *const [u8];
 
@@ -315,6 +318,7 @@ unsafe impl SliceIndex<str> for range::Range<usize> {
         }
     }
     #[inline]
+    #[track_caller]
     unsafe fn get_unchecked_mut(self, slice: *mut str) -> *mut Self::Output {
         let slice = slice as *mut [u8];
 
diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs
index bd5a58d74ba..b43f3bad6e2 100644
--- a/library/core/src/sync/atomic.rs
+++ b/library/core/src/sync/atomic.rs
@@ -3822,6 +3822,7 @@ unsafe fn atomic_store<T: Copy>(dst: *mut T, val: T, order: Ordering) {
 
 #[inline]
 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
+#[cfg(bootstrap)]
 unsafe fn atomic_load<T: Copy>(dst: *const T, order: Ordering) -> T {
     // SAFETY: the caller must uphold the safety contract for `atomic_load`.
     unsafe {
@@ -3836,6 +3837,23 @@ unsafe fn atomic_load<T: Copy>(dst: *const T, order: Ordering) -> T {
 }
 
 #[inline]
+#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
+#[cfg(not(bootstrap))]
+unsafe fn atomic_load<T: Copy>(dst: *const T, order: Ordering) -> T {
+    use intrinsics::AtomicOrdering;
+    // SAFETY: the caller must uphold the safety contract for `atomic_load`.
+    unsafe {
+        match order {
+            Relaxed => intrinsics::atomic_load::<T, { AtomicOrdering::Relaxed }>(dst),
+            Acquire => intrinsics::atomic_load::<T, { AtomicOrdering::Acquire }>(dst),
+            SeqCst => intrinsics::atomic_load::<T, { AtomicOrdering::SeqCst }>(dst),
+            Release => panic!("there is no such thing as a release load"),
+            AcqRel => panic!("there is no such thing as an acquire-release load"),
+        }
+    }
+}
+
+#[inline]
 #[cfg(target_has_atomic)]
 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
 unsafe fn atomic_swap<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T {
@@ -3885,10 +3903,13 @@ unsafe fn atomic_sub<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T {
     }
 }
 
+/// Publicly exposed for stdarch; nobody else should use this.
 #[inline]
 #[cfg(target_has_atomic)]
 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
-unsafe fn atomic_compare_exchange<T: Copy>(
+#[unstable(feature = "core_intrinsics", issue = "none")]
+#[doc(hidden)]
+pub unsafe fn atomic_compare_exchange<T: Copy>(
     dst: *mut T,
     old: T,
     new: T,
diff --git a/library/core/src/ub_checks.rs b/library/core/src/ub_checks.rs
index 9eb71922218..a7caaeb95cd 100644
--- a/library/core/src/ub_checks.rs
+++ b/library/core/src/ub_checks.rs
@@ -63,11 +63,13 @@ macro_rules! assert_unsafe_precondition {
             #[rustc_no_mir_inline]
             #[inline]
             #[rustc_nounwind]
+            #[track_caller]
             const fn precondition_check($($name:$ty),*) {
                 if !$e {
-                    ::core::panicking::panic_nounwind(concat!("unsafe precondition(s) violated: ", $message,
+                    let msg = concat!("unsafe precondition(s) violated: ", $message,
                         "\n\nThis indicates a bug in the program. \
-                        This Undefined Behavior check is optional, and cannot be relied on for safety."));
+                        This Undefined Behavior check is optional, and cannot be relied on for safety.");
+                    ::core::panicking::panic_nounwind_fmt(::core::fmt::Arguments::new_const(&[msg]), false);
                 }
             }
 
diff --git a/library/coretests/tests/ffi/cstr.rs b/library/coretests/tests/ffi/cstr.rs
index 0d85b22c585..dc34240cd99 100644
--- a/library/coretests/tests/ffi/cstr.rs
+++ b/library/coretests/tests/ffi/cstr.rs
@@ -19,3 +19,9 @@ fn debug() {
     let s = c"abc\x01\x02\n\xE2\x80\xA6\xFF";
     assert_eq!(format!("{s:?}"), r#""abc\x01\x02\n\xe2\x80\xa6\xff""#);
 }
+
+#[test]
+fn display() {
+    let s = c"\xf0\x28\x8c\xbc";
+    assert_eq!(format!("{}", s.display()), "�(��");
+}
diff --git a/library/coretests/tests/floats/f128.rs b/library/coretests/tests/floats/f128.rs
index 12cf651f03f..01770f119df 100644
--- a/library/coretests/tests/floats/f128.rs
+++ b/library/coretests/tests/floats/f128.rs
@@ -1,12 +1,9 @@
 // FIXME(f16_f128): only tested on platforms that have symbols and aren't buggy
 #![cfg(target_has_reliable_f128)]
 
+use core::ops::{Add, Div, Mul, Sub};
 use std::f128::consts;
 use std::num::FpCategory as Fp;
-#[cfg(not(miri))]
-#[cfg(target_has_reliable_f128_math)]
-use std::ops::Rem;
-use std::ops::{Add, Div, Mul, Sub};
 
 // Note these tolerances make sense around zero, but not for more extreme exponents.
 
@@ -39,68 +36,46 @@ const NAN_MASK1: u128 = 0x0000aaaaaaaaaaaaaaaaaaaaaaaaaaaa;
 /// Second pattern over the mantissa
 const NAN_MASK2: u128 = 0x00005555555555555555555555555555;
 
-/// Compare by representation
-#[allow(unused_macros)]
-macro_rules! assert_f128_biteq {
-    ($a:expr, $b:expr) => {
-        let (l, r): (&f128, &f128) = (&$a, &$b);
-        let lb = l.to_bits();
-        let rb = r.to_bits();
-        assert_eq!(lb, rb, "float {l:?} is not bitequal to {r:?}.\na: {lb:#034x}\nb: {rb:#034x}");
-    };
-}
-
 #[test]
 fn test_num_f128() {
     // FIXME(f16_f128): replace with a `test_num` call once the required `fmodl`/`fmodf128`
     // function is available on all platforms.
     let ten = 10f128;
     let two = 2f128;
-    assert_eq!(ten.add(two), ten + two);
-    assert_eq!(ten.sub(two), ten - two);
-    assert_eq!(ten.mul(two), ten * two);
-    assert_eq!(ten.div(two), ten / two);
+    assert_biteq!(ten.add(two), ten + two);
+    assert_biteq!(ten.sub(two), ten - two);
+    assert_biteq!(ten.mul(two), ten * two);
+    assert_biteq!(ten.div(two), ten / two);
+    #[cfg(any(miri, target_has_reliable_f128_math))]
+    assert_biteq!(core::ops::Rem::rem(ten, two), ten % two);
 }
 
 // FIXME(f16_f128,miri): many of these have to be disabled since miri does not yet support
 // the intrinsics.
 
 #[test]
-#[cfg(not(miri))]
-#[cfg(target_has_reliable_f128_math)]
-fn test_num_f128_rem() {
-    let ten = 10f128;
-    let two = 2f128;
-    assert_eq!(ten.rem(two), ten % two);
-}
-
-#[test]
-#[cfg(not(miri))]
-#[cfg(target_has_reliable_f128_math)]
+#[cfg(any(miri, target_has_reliable_f128_math))]
 fn test_min_nan() {
-    assert_eq!(f128::NAN.min(2.0), 2.0);
-    assert_eq!(2.0f128.min(f128::NAN), 2.0);
+    assert_biteq!(f128::NAN.min(2.0), 2.0);
+    assert_biteq!(2.0f128.min(f128::NAN), 2.0);
 }
 
 #[test]
-#[cfg(not(miri))]
-#[cfg(target_has_reliable_f128_math)]
+#[cfg(any(miri, target_has_reliable_f128_math))]
 fn test_max_nan() {
-    assert_eq!(f128::NAN.max(2.0), 2.0);
-    assert_eq!(2.0f128.max(f128::NAN), 2.0);
+    assert_biteq!(f128::NAN.max(2.0), 2.0);
+    assert_biteq!(2.0f128.max(f128::NAN), 2.0);
 }
 
 #[test]
-#[cfg(not(miri))]
-#[cfg(target_has_reliable_f128_math)]
+#[cfg(any(miri, target_has_reliable_f128_math))]
 fn test_minimum() {
     assert!(f128::NAN.minimum(2.0).is_nan());
     assert!(2.0f128.minimum(f128::NAN).is_nan());
 }
 
 #[test]
-#[cfg(not(miri))]
-#[cfg(target_has_reliable_f128_math)]
+#[cfg(any(miri, target_has_reliable_f128_math))]
 fn test_maximum() {
     assert!(f128::NAN.maximum(2.0).is_nan());
     assert!(2.0f128.maximum(f128::NAN).is_nan());
@@ -147,7 +122,7 @@ fn test_neg_infinity() {
 #[test]
 fn test_zero() {
     let zero: f128 = 0.0f128;
-    assert_eq!(0.0, zero);
+    assert_biteq!(0.0, zero);
     assert!(!zero.is_infinite());
     assert!(zero.is_finite());
     assert!(zero.is_sign_positive());
@@ -161,6 +136,7 @@ fn test_zero() {
 fn test_neg_zero() {
     let neg_zero: f128 = -0.0;
     assert_eq!(0.0, neg_zero);
+    assert_biteq!(-0.0, neg_zero);
     assert!(!neg_zero.is_infinite());
     assert!(neg_zero.is_finite());
     assert!(!neg_zero.is_sign_positive());
@@ -173,7 +149,7 @@ fn test_neg_zero() {
 #[test]
 fn test_one() {
     let one: f128 = 1.0f128;
-    assert_eq!(1.0, one);
+    assert_biteq!(1.0, one);
     assert!(!one.is_infinite());
     assert!(one.is_finite());
     assert!(one.is_sign_positive());
@@ -257,114 +233,107 @@ fn test_classify() {
 }
 
 #[test]
-#[cfg(not(miri))]
 #[cfg(target_has_reliable_f128_math)]
 fn test_floor() {
-    assert_approx_eq!(1.0f128.floor(), 1.0f128, TOL_PRECISE);
-    assert_approx_eq!(1.3f128.floor(), 1.0f128, TOL_PRECISE);
-    assert_approx_eq!(1.5f128.floor(), 1.0f128, TOL_PRECISE);
-    assert_approx_eq!(1.7f128.floor(), 1.0f128, TOL_PRECISE);
-    assert_approx_eq!(0.0f128.floor(), 0.0f128, TOL_PRECISE);
-    assert_approx_eq!((-0.0f128).floor(), -0.0f128, TOL_PRECISE);
-    assert_approx_eq!((-1.0f128).floor(), -1.0f128, TOL_PRECISE);
-    assert_approx_eq!((-1.3f128).floor(), -2.0f128, TOL_PRECISE);
-    assert_approx_eq!((-1.5f128).floor(), -2.0f128, TOL_PRECISE);
-    assert_approx_eq!((-1.7f128).floor(), -2.0f128, TOL_PRECISE);
+    assert_biteq!(1.0f128.floor(), 1.0f128);
+    assert_biteq!(1.3f128.floor(), 1.0f128);
+    assert_biteq!(1.5f128.floor(), 1.0f128);
+    assert_biteq!(1.7f128.floor(), 1.0f128);
+    assert_biteq!(0.0f128.floor(), 0.0f128);
+    assert_biteq!((-0.0f128).floor(), -0.0f128);
+    assert_biteq!((-1.0f128).floor(), -1.0f128);
+    assert_biteq!((-1.3f128).floor(), -2.0f128);
+    assert_biteq!((-1.5f128).floor(), -2.0f128);
+    assert_biteq!((-1.7f128).floor(), -2.0f128);
 }
 
 #[test]
-#[cfg(not(miri))]
-#[cfg(target_has_reliable_f128_math)]
+#[cfg(any(miri, target_has_reliable_f128_math))]
 fn test_ceil() {
-    assert_approx_eq!(1.0f128.ceil(), 1.0f128, TOL_PRECISE);
-    assert_approx_eq!(1.3f128.ceil(), 2.0f128, TOL_PRECISE);
-    assert_approx_eq!(1.5f128.ceil(), 2.0f128, TOL_PRECISE);
-    assert_approx_eq!(1.7f128.ceil(), 2.0f128, TOL_PRECISE);
-    assert_approx_eq!(0.0f128.ceil(), 0.0f128, TOL_PRECISE);
-    assert_approx_eq!((-0.0f128).ceil(), -0.0f128, TOL_PRECISE);
-    assert_approx_eq!((-1.0f128).ceil(), -1.0f128, TOL_PRECISE);
-    assert_approx_eq!((-1.3f128).ceil(), -1.0f128, TOL_PRECISE);
-    assert_approx_eq!((-1.5f128).ceil(), -1.0f128, TOL_PRECISE);
-    assert_approx_eq!((-1.7f128).ceil(), -1.0f128, TOL_PRECISE);
+    assert_biteq!(1.0f128.ceil(), 1.0f128);
+    assert_biteq!(1.3f128.ceil(), 2.0f128);
+    assert_biteq!(1.5f128.ceil(), 2.0f128);
+    assert_biteq!(1.7f128.ceil(), 2.0f128);
+    assert_biteq!(0.0f128.ceil(), 0.0f128);
+    assert_biteq!((-0.0f128).ceil(), -0.0f128);
+    assert_biteq!((-1.0f128).ceil(), -1.0f128);
+    assert_biteq!((-1.3f128).ceil(), -1.0f128);
+    assert_biteq!((-1.5f128).ceil(), -1.0f128);
+    assert_biteq!((-1.7f128).ceil(), -1.0f128);
 }
 
 #[test]
-#[cfg(not(miri))]
-#[cfg(target_has_reliable_f128_math)]
+#[cfg(any(miri, target_has_reliable_f128_math))]
 fn test_round() {
-    assert_approx_eq!(2.5f128.round(), 3.0f128, TOL_PRECISE);
-    assert_approx_eq!(1.0f128.round(), 1.0f128, TOL_PRECISE);
-    assert_approx_eq!(1.3f128.round(), 1.0f128, TOL_PRECISE);
-    assert_approx_eq!(1.5f128.round(), 2.0f128, TOL_PRECISE);
-    assert_approx_eq!(1.7f128.round(), 2.0f128, TOL_PRECISE);
-    assert_approx_eq!(0.0f128.round(), 0.0f128, TOL_PRECISE);
-    assert_approx_eq!((-0.0f128).round(), -0.0f128, TOL_PRECISE);
-    assert_approx_eq!((-1.0f128).round(), -1.0f128, TOL_PRECISE);
-    assert_approx_eq!((-1.3f128).round(), -1.0f128, TOL_PRECISE);
-    assert_approx_eq!((-1.5f128).round(), -2.0f128, TOL_PRECISE);
-    assert_approx_eq!((-1.7f128).round(), -2.0f128, TOL_PRECISE);
+    assert_biteq!(2.5f128.round(), 3.0f128);
+    assert_biteq!(1.0f128.round(), 1.0f128);
+    assert_biteq!(1.3f128.round(), 1.0f128);
+    assert_biteq!(1.5f128.round(), 2.0f128);
+    assert_biteq!(1.7f128.round(), 2.0f128);
+    assert_biteq!(0.0f128.round(), 0.0f128);
+    assert_biteq!((-0.0f128).round(), -0.0f128);
+    assert_biteq!((-1.0f128).round(), -1.0f128);
+    assert_biteq!((-1.3f128).round(), -1.0f128);
+    assert_biteq!((-1.5f128).round(), -2.0f128);
+    assert_biteq!((-1.7f128).round(), -2.0f128);
 }
 
 #[test]
-#[cfg(not(miri))]
-#[cfg(target_has_reliable_f128_math)]
+#[cfg(any(miri, target_has_reliable_f128_math))]
 fn test_round_ties_even() {
-    assert_approx_eq!(2.5f128.round_ties_even(), 2.0f128, TOL_PRECISE);
-    assert_approx_eq!(1.0f128.round_ties_even(), 1.0f128, TOL_PRECISE);
-    assert_approx_eq!(1.3f128.round_ties_even(), 1.0f128, TOL_PRECISE);
-    assert_approx_eq!(1.5f128.round_ties_even(), 2.0f128, TOL_PRECISE);
-    assert_approx_eq!(1.7f128.round_ties_even(), 2.0f128, TOL_PRECISE);
-    assert_approx_eq!(0.0f128.round_ties_even(), 0.0f128, TOL_PRECISE);
-    assert_approx_eq!((-0.0f128).round_ties_even(), -0.0f128, TOL_PRECISE);
-    assert_approx_eq!((-1.0f128).round_ties_even(), -1.0f128, TOL_PRECISE);
-    assert_approx_eq!((-1.3f128).round_ties_even(), -1.0f128, TOL_PRECISE);
-    assert_approx_eq!((-1.5f128).round_ties_even(), -2.0f128, TOL_PRECISE);
-    assert_approx_eq!((-1.7f128).round_ties_even(), -2.0f128, TOL_PRECISE);
+    assert_biteq!(2.5f128.round_ties_even(), 2.0f128);
+    assert_biteq!(1.0f128.round_ties_even(), 1.0f128);
+    assert_biteq!(1.3f128.round_ties_even(), 1.0f128);
+    assert_biteq!(1.5f128.round_ties_even(), 2.0f128);
+    assert_biteq!(1.7f128.round_ties_even(), 2.0f128);
+    assert_biteq!(0.0f128.round_ties_even(), 0.0f128);
+    assert_biteq!((-0.0f128).round_ties_even(), -0.0f128);
+    assert_biteq!((-1.0f128).round_ties_even(), -1.0f128);
+    assert_biteq!((-1.3f128).round_ties_even(), -1.0f128);
+    assert_biteq!((-1.5f128).round_ties_even(), -2.0f128);
+    assert_biteq!((-1.7f128).round_ties_even(), -2.0f128);
 }
 
 #[test]
-#[cfg(not(miri))]
-#[cfg(target_has_reliable_f128_math)]
+#[cfg(any(miri, target_has_reliable_f128_math))]
 fn test_trunc() {
-    assert_approx_eq!(1.0f128.trunc(), 1.0f128, TOL_PRECISE);
-    assert_approx_eq!(1.3f128.trunc(), 1.0f128, TOL_PRECISE);
-    assert_approx_eq!(1.5f128.trunc(), 1.0f128, TOL_PRECISE);
-    assert_approx_eq!(1.7f128.trunc(), 1.0f128, TOL_PRECISE);
-    assert_approx_eq!(0.0f128.trunc(), 0.0f128, TOL_PRECISE);
-    assert_approx_eq!((-0.0f128).trunc(), -0.0f128, TOL_PRECISE);
-    assert_approx_eq!((-1.0f128).trunc(), -1.0f128, TOL_PRECISE);
-    assert_approx_eq!((-1.3f128).trunc(), -1.0f128, TOL_PRECISE);
-    assert_approx_eq!((-1.5f128).trunc(), -1.0f128, TOL_PRECISE);
-    assert_approx_eq!((-1.7f128).trunc(), -1.0f128, TOL_PRECISE);
+    assert_biteq!(1.0f128.trunc(), 1.0f128);
+    assert_biteq!(1.3f128.trunc(), 1.0f128);
+    assert_biteq!(1.5f128.trunc(), 1.0f128);
+    assert_biteq!(1.7f128.trunc(), 1.0f128);
+    assert_biteq!(0.0f128.trunc(), 0.0f128);
+    assert_biteq!((-0.0f128).trunc(), -0.0f128);
+    assert_biteq!((-1.0f128).trunc(), -1.0f128);
+    assert_biteq!((-1.3f128).trunc(), -1.0f128);
+    assert_biteq!((-1.5f128).trunc(), -1.0f128);
+    assert_biteq!((-1.7f128).trunc(), -1.0f128);
 }
 
 #[test]
-#[cfg(not(miri))]
-#[cfg(target_has_reliable_f128_math)]
+#[cfg(any(miri, target_has_reliable_f128_math))]
 fn test_fract() {
-    assert_approx_eq!(1.0f128.fract(), 0.0f128, TOL_PRECISE);
-    assert_approx_eq!(1.3f128.fract(), 0.3f128, TOL_PRECISE);
-    assert_approx_eq!(1.5f128.fract(), 0.5f128, TOL_PRECISE);
-    assert_approx_eq!(1.7f128.fract(), 0.7f128, TOL_PRECISE);
-    assert_approx_eq!(0.0f128.fract(), 0.0f128, TOL_PRECISE);
-    assert_approx_eq!((-0.0f128).fract(), -0.0f128, TOL_PRECISE);
-    assert_approx_eq!((-1.0f128).fract(), -0.0f128, TOL_PRECISE);
-    assert_approx_eq!((-1.3f128).fract(), -0.3f128, TOL_PRECISE);
-    assert_approx_eq!((-1.5f128).fract(), -0.5f128, TOL_PRECISE);
-    assert_approx_eq!((-1.7f128).fract(), -0.7f128, TOL_PRECISE);
+    assert_biteq!(1.0f128.fract(), 0.0f128);
+    assert_biteq!(1.3f128.fract(), 0.300000000000000000000000000000000039f128);
+    assert_biteq!(1.5f128.fract(), 0.5f128);
+    assert_biteq!(1.7f128.fract(), 0.7f128);
+    assert_biteq!(0.0f128.fract(), 0.0f128);
+    assert_biteq!((-0.0f128).fract(), 0.0f128);
+    assert_biteq!((-1.0f128).fract(), 0.0f128);
+    assert_biteq!((-1.3f128).fract(), -0.300000000000000000000000000000000039f128);
+    assert_biteq!((-1.5f128).fract(), -0.5f128);
+    assert_biteq!((-1.7f128).fract(), -0.699999999999999999999999999999999961f128);
 }
 
 #[test]
-#[cfg(not(miri))]
-#[cfg(target_has_reliable_f128_math)]
+#[cfg(any(miri, target_has_reliable_f128_math))]
 fn test_abs() {
-    assert_eq!(f128::INFINITY.abs(), f128::INFINITY);
-    assert_eq!(1f128.abs(), 1f128);
-    assert_eq!(0f128.abs(), 0f128);
-    assert_eq!((-0f128).abs(), 0f128);
-    assert_eq!((-1f128).abs(), 1f128);
-    assert_eq!(f128::NEG_INFINITY.abs(), f128::INFINITY);
-    assert_eq!((1f128 / f128::NEG_INFINITY).abs(), 0f128);
+    assert_biteq!(f128::INFINITY.abs(), f128::INFINITY);
+    assert_biteq!(1f128.abs(), 1f128);
+    assert_biteq!(0f128.abs(), 0f128);
+    assert_biteq!((-0f128).abs(), 0f128);
+    assert_biteq!((-1f128).abs(), 1f128);
+    assert_biteq!(f128::NEG_INFINITY.abs(), f128::INFINITY);
+    assert_biteq!((1f128 / f128::NEG_INFINITY).abs(), 0f128);
     assert!(f128::NAN.abs().is_nan());
 }
 
@@ -401,27 +370,27 @@ fn test_next_up() {
     let max_down = f128::from_bits(MAX_DOWN_BITS);
     let largest_subnormal = f128::from_bits(LARGEST_SUBNORMAL_BITS);
     let smallest_normal = f128::from_bits(SMALLEST_NORMAL_BITS);
-    assert_f128_biteq!(f128::NEG_INFINITY.next_up(), f128::MIN);
-    assert_f128_biteq!(f128::MIN.next_up(), -max_down);
-    assert_f128_biteq!((-1.0 - f128::EPSILON).next_up(), -1.0);
-    assert_f128_biteq!((-smallest_normal).next_up(), -largest_subnormal);
-    assert_f128_biteq!((-tiny_up).next_up(), -tiny);
-    assert_f128_biteq!((-tiny).next_up(), -0.0f128);
-    assert_f128_biteq!((-0.0f128).next_up(), tiny);
-    assert_f128_biteq!(0.0f128.next_up(), tiny);
-    assert_f128_biteq!(tiny.next_up(), tiny_up);
-    assert_f128_biteq!(largest_subnormal.next_up(), smallest_normal);
-    assert_f128_biteq!(1.0f128.next_up(), 1.0 + f128::EPSILON);
-    assert_f128_biteq!(f128::MAX.next_up(), f128::INFINITY);
-    assert_f128_biteq!(f128::INFINITY.next_up(), f128::INFINITY);
+    assert_biteq!(f128::NEG_INFINITY.next_up(), f128::MIN);
+    assert_biteq!(f128::MIN.next_up(), -max_down);
+    assert_biteq!((-1.0 - f128::EPSILON).next_up(), -1.0f128);
+    assert_biteq!((-smallest_normal).next_up(), -largest_subnormal);
+    assert_biteq!((-tiny_up).next_up(), -tiny);
+    assert_biteq!((-tiny).next_up(), -0.0f128);
+    assert_biteq!((-0.0f128).next_up(), tiny);
+    assert_biteq!(0.0f128.next_up(), tiny);
+    assert_biteq!(tiny.next_up(), tiny_up);
+    assert_biteq!(largest_subnormal.next_up(), smallest_normal);
+    assert_biteq!(1.0f128.next_up(), 1.0 + f128::EPSILON);
+    assert_biteq!(f128::MAX.next_up(), f128::INFINITY);
+    assert_biteq!(f128::INFINITY.next_up(), f128::INFINITY);
 
     // Check that NaNs roundtrip.
     let nan0 = f128::NAN;
     let nan1 = f128::from_bits(f128::NAN.to_bits() ^ 0x002a_aaaa);
     let nan2 = f128::from_bits(f128::NAN.to_bits() ^ 0x0055_5555);
-    assert_f128_biteq!(nan0.next_up(), nan0);
-    assert_f128_biteq!(nan1.next_up(), nan1);
-    assert_f128_biteq!(nan2.next_up(), nan2);
+    assert_biteq!(nan0.next_up(), nan0);
+    assert_biteq!(nan1.next_up(), nan1);
+    assert_biteq!(nan2.next_up(), nan2);
 }
 
 #[test]
@@ -431,28 +400,28 @@ fn test_next_down() {
     let max_down = f128::from_bits(MAX_DOWN_BITS);
     let largest_subnormal = f128::from_bits(LARGEST_SUBNORMAL_BITS);
     let smallest_normal = f128::from_bits(SMALLEST_NORMAL_BITS);
-    assert_f128_biteq!(f128::NEG_INFINITY.next_down(), f128::NEG_INFINITY);
-    assert_f128_biteq!(f128::MIN.next_down(), f128::NEG_INFINITY);
-    assert_f128_biteq!((-max_down).next_down(), f128::MIN);
-    assert_f128_biteq!((-1.0f128).next_down(), -1.0 - f128::EPSILON);
-    assert_f128_biteq!((-largest_subnormal).next_down(), -smallest_normal);
-    assert_f128_biteq!((-tiny).next_down(), -tiny_up);
-    assert_f128_biteq!((-0.0f128).next_down(), -tiny);
-    assert_f128_biteq!((0.0f128).next_down(), -tiny);
-    assert_f128_biteq!(tiny.next_down(), 0.0f128);
-    assert_f128_biteq!(tiny_up.next_down(), tiny);
-    assert_f128_biteq!(smallest_normal.next_down(), largest_subnormal);
-    assert_f128_biteq!((1.0 + f128::EPSILON).next_down(), 1.0f128);
-    assert_f128_biteq!(f128::MAX.next_down(), max_down);
-    assert_f128_biteq!(f128::INFINITY.next_down(), f128::MAX);
+    assert_biteq!(f128::NEG_INFINITY.next_down(), f128::NEG_INFINITY);
+    assert_biteq!(f128::MIN.next_down(), f128::NEG_INFINITY);
+    assert_biteq!((-max_down).next_down(), f128::MIN);
+    assert_biteq!((-1.0f128).next_down(), -1.0 - f128::EPSILON);
+    assert_biteq!((-largest_subnormal).next_down(), -smallest_normal);
+    assert_biteq!((-tiny).next_down(), -tiny_up);
+    assert_biteq!((-0.0f128).next_down(), -tiny);
+    assert_biteq!((0.0f128).next_down(), -tiny);
+    assert_biteq!(tiny.next_down(), 0.0f128);
+    assert_biteq!(tiny_up.next_down(), tiny);
+    assert_biteq!(smallest_normal.next_down(), largest_subnormal);
+    assert_biteq!((1.0 + f128::EPSILON).next_down(), 1.0f128);
+    assert_biteq!(f128::MAX.next_down(), max_down);
+    assert_biteq!(f128::INFINITY.next_down(), f128::MAX);
 
     // Check that NaNs roundtrip.
     let nan0 = f128::NAN;
     let nan1 = f128::from_bits(f128::NAN.to_bits() ^ 0x002a_aaaa);
     let nan2 = f128::from_bits(f128::NAN.to_bits() ^ 0x0055_5555);
-    assert_f128_biteq!(nan0.next_down(), nan0);
-    assert_f128_biteq!(nan1.next_down(), nan1);
-    assert_f128_biteq!(nan2.next_down(), nan2);
+    assert_biteq!(nan0.next_down(), nan0);
+    assert_biteq!(nan1.next_down(), nan1);
+    assert_biteq!(nan2.next_down(), nan2);
 }
 
 #[test]
@@ -462,36 +431,35 @@ fn test_mul_add() {
     let nan: f128 = f128::NAN;
     let inf: f128 = f128::INFINITY;
     let neg_inf: f128 = f128::NEG_INFINITY;
-    assert_approx_eq!(12.3f128.mul_add(4.5, 6.7), 62.05, TOL_PRECISE);
-    assert_approx_eq!((-12.3f128).mul_add(-4.5, -6.7), 48.65, TOL_PRECISE);
-    assert_approx_eq!(0.0f128.mul_add(8.9, 1.2), 1.2, TOL_PRECISE);
-    assert_approx_eq!(3.4f128.mul_add(-0.0, 5.6), 5.6, TOL_PRECISE);
+    assert_biteq!(12.3f128.mul_add(4.5, 6.7), 62.0500000000000000000000000000000037);
+    assert_biteq!((-12.3f128).mul_add(-4.5, -6.7), 48.6500000000000000000000000000000049);
+    assert_biteq!(0.0f128.mul_add(8.9, 1.2), 1.2);
+    assert_biteq!(3.4f128.mul_add(-0.0, 5.6), 5.6);
     assert!(nan.mul_add(7.8, 9.0).is_nan());
-    assert_eq!(inf.mul_add(7.8, 9.0), inf);
-    assert_eq!(neg_inf.mul_add(7.8, 9.0), neg_inf);
-    assert_eq!(8.9f128.mul_add(inf, 3.2), inf);
-    assert_eq!((-3.2f128).mul_add(2.4, neg_inf), neg_inf);
+    assert_biteq!(inf.mul_add(7.8, 9.0), inf);
+    assert_biteq!(neg_inf.mul_add(7.8, 9.0), neg_inf);
+    assert_biteq!(8.9f128.mul_add(inf, 3.2), inf);
+    assert_biteq!((-3.2f128).mul_add(2.4, neg_inf), neg_inf);
 }
 
 #[test]
-#[cfg(not(miri))]
-#[cfg(target_has_reliable_f128_math)]
+#[cfg(any(miri, target_has_reliable_f128_math))]
 fn test_recip() {
     let nan: f128 = f128::NAN;
     let inf: f128 = f128::INFINITY;
     let neg_inf: f128 = f128::NEG_INFINITY;
-    assert_eq!(1.0f128.recip(), 1.0);
-    assert_eq!(2.0f128.recip(), 0.5);
-    assert_eq!((-0.4f128).recip(), -2.5);
-    assert_eq!(0.0f128.recip(), inf);
+    assert_biteq!(1.0f128.recip(), 1.0);
+    assert_biteq!(2.0f128.recip(), 0.5);
+    assert_biteq!((-0.4f128).recip(), -2.5);
+    assert_biteq!(0.0f128.recip(), inf);
     assert_approx_eq!(
         f128::MAX.recip(),
         8.40525785778023376565669454330438228902076605e-4933,
         1e-4900
     );
     assert!(nan.recip().is_nan());
-    assert_eq!(inf.recip(), 0.0);
-    assert_eq!(neg_inf.recip(), 0.0);
+    assert_biteq!(inf.recip(), 0.0);
+    assert_biteq!(neg_inf.recip(), -0.0);
 }
 
 #[test]
@@ -501,13 +469,13 @@ fn test_powi() {
     let nan: f128 = f128::NAN;
     let inf: f128 = f128::INFINITY;
     let neg_inf: f128 = f128::NEG_INFINITY;
-    assert_eq!(1.0f128.powi(1), 1.0);
+    assert_biteq!(1.0f128.powi(1), 1.0);
     assert_approx_eq!((-3.1f128).powi(2), 9.6100000000000005506706202140776519387, TOL);
     assert_approx_eq!(5.9f128.powi(-2), 0.028727377190462507313100483690639638451, TOL);
-    assert_eq!(8.3f128.powi(0), 1.0);
+    assert_biteq!(8.3f128.powi(0), 1.0);
     assert!(nan.powi(2).is_nan());
-    assert_eq!(inf.powi(3), inf);
-    assert_eq!(neg_inf.powi(2), inf);
+    assert_biteq!(inf.powi(3), inf);
+    assert_biteq!(neg_inf.powi(2), inf);
 }
 
 #[test]
@@ -517,10 +485,10 @@ fn test_sqrt_domain() {
     assert!(f128::NAN.sqrt().is_nan());
     assert!(f128::NEG_INFINITY.sqrt().is_nan());
     assert!((-1.0f128).sqrt().is_nan());
-    assert_eq!((-0.0f128).sqrt(), -0.0);
-    assert_eq!(0.0f128.sqrt(), 0.0);
-    assert_eq!(1.0f128.sqrt(), 1.0);
-    assert_eq!(f128::INFINITY.sqrt(), f128::INFINITY);
+    assert_biteq!((-0.0f128).sqrt(), -0.0);
+    assert_biteq!(0.0f128.sqrt(), 0.0);
+    assert_biteq!(1.0f128.sqrt(), 1.0);
+    assert_biteq!(f128::INFINITY.sqrt(), f128::INFINITY);
 }
 
 #[test]
@@ -529,13 +497,13 @@ fn test_to_degrees() {
     let nan: f128 = f128::NAN;
     let inf: f128 = f128::INFINITY;
     let neg_inf: f128 = f128::NEG_INFINITY;
-    assert_eq!(0.0f128.to_degrees(), 0.0);
+    assert_biteq!(0.0f128.to_degrees(), 0.0);
     assert_approx_eq!((-5.8f128).to_degrees(), -332.31552117587745090765431723855668471, TOL);
     assert_approx_eq!(pi.to_degrees(), 180.0, TOL);
     assert!(nan.to_degrees().is_nan());
-    assert_eq!(inf.to_degrees(), inf);
-    assert_eq!(neg_inf.to_degrees(), neg_inf);
-    assert_eq!(1_f128.to_degrees(), 57.2957795130823208767981548141051703);
+    assert_biteq!(inf.to_degrees(), inf);
+    assert_biteq!(neg_inf.to_degrees(), neg_inf);
+    assert_biteq!(1_f128.to_degrees(), 57.2957795130823208767981548141051703);
 }
 
 #[test]
@@ -544,15 +512,15 @@ fn test_to_radians() {
     let nan: f128 = f128::NAN;
     let inf: f128 = f128::INFINITY;
     let neg_inf: f128 = f128::NEG_INFINITY;
-    assert_eq!(0.0f128.to_radians(), 0.0);
+    assert_biteq!(0.0f128.to_radians(), 0.0);
     assert_approx_eq!(154.6f128.to_radians(), 2.6982790235832334267135442069489767804, TOL);
     assert_approx_eq!((-332.31f128).to_radians(), -5.7999036373023566567593094812182763013, TOL);
     // check approx rather than exact because round trip for pi doesn't fall on an exactly
     // representable value (unlike `f32` and `f64`).
     assert_approx_eq!(180.0f128.to_radians(), pi, TOL_PRECISE);
     assert!(nan.to_radians().is_nan());
-    assert_eq!(inf.to_radians(), inf);
-    assert_eq!(neg_inf.to_radians(), neg_inf);
+    assert_biteq!(inf.to_radians(), inf);
+    assert_biteq!(neg_inf.to_radians(), neg_inf);
 }
 
 #[test]
@@ -561,10 +529,10 @@ fn test_float_bits_conv() {
     assert_eq!((12.5f128).to_bits(), 0x40029000000000000000000000000000);
     assert_eq!((1337f128).to_bits(), 0x40094e40000000000000000000000000);
     assert_eq!((-14.25f128).to_bits(), 0xc002c800000000000000000000000000);
-    assert_approx_eq!(f128::from_bits(0x3fff0000000000000000000000000000), 1.0, TOL_PRECISE);
-    assert_approx_eq!(f128::from_bits(0x40029000000000000000000000000000), 12.5, TOL_PRECISE);
-    assert_approx_eq!(f128::from_bits(0x40094e40000000000000000000000000), 1337.0, TOL_PRECISE);
-    assert_approx_eq!(f128::from_bits(0xc002c800000000000000000000000000), -14.25, TOL_PRECISE);
+    assert_biteq!(f128::from_bits(0x3fff0000000000000000000000000000), 1.0);
+    assert_biteq!(f128::from_bits(0x40029000000000000000000000000000), 12.5);
+    assert_biteq!(f128::from_bits(0x40094e40000000000000000000000000), 1337.0);
+    assert_biteq!(f128::from_bits(0xc002c800000000000000000000000000), -14.25);
 
     // Check that NaNs roundtrip their bits regardless of signaling-ness
     // 0xA is 0b1010; 0x5 is 0b0101 -- so these two together clobbers all the mantissa bits
@@ -760,26 +728,26 @@ fn test_algebraic() {
 
 #[test]
 fn test_from() {
-    assert_eq!(f128::from(false), 0.0);
-    assert_eq!(f128::from(true), 1.0);
-    assert_eq!(f128::from(u8::MIN), 0.0);
-    assert_eq!(f128::from(42_u8), 42.0);
-    assert_eq!(f128::from(u8::MAX), 255.0);
-    assert_eq!(f128::from(i8::MIN), -128.0);
-    assert_eq!(f128::from(42_i8), 42.0);
-    assert_eq!(f128::from(i8::MAX), 127.0);
-    assert_eq!(f128::from(u16::MIN), 0.0);
-    assert_eq!(f128::from(42_u16), 42.0);
-    assert_eq!(f128::from(u16::MAX), 65535.0);
-    assert_eq!(f128::from(i16::MIN), -32768.0);
-    assert_eq!(f128::from(42_i16), 42.0);
-    assert_eq!(f128::from(i16::MAX), 32767.0);
-    assert_eq!(f128::from(u32::MIN), 0.0);
-    assert_eq!(f128::from(42_u32), 42.0);
-    assert_eq!(f128::from(u32::MAX), 4294967295.0);
-    assert_eq!(f128::from(i32::MIN), -2147483648.0);
-    assert_eq!(f128::from(42_i32), 42.0);
-    assert_eq!(f128::from(i32::MAX), 2147483647.0);
+    assert_biteq!(f128::from(false), 0.0);
+    assert_biteq!(f128::from(true), 1.0);
+    assert_biteq!(f128::from(u8::MIN), 0.0);
+    assert_biteq!(f128::from(42_u8), 42.0);
+    assert_biteq!(f128::from(u8::MAX), 255.0);
+    assert_biteq!(f128::from(i8::MIN), -128.0);
+    assert_biteq!(f128::from(42_i8), 42.0);
+    assert_biteq!(f128::from(i8::MAX), 127.0);
+    assert_biteq!(f128::from(u16::MIN), 0.0);
+    assert_biteq!(f128::from(42_u16), 42.0);
+    assert_biteq!(f128::from(u16::MAX), 65535.0);
+    assert_biteq!(f128::from(i16::MIN), -32768.0);
+    assert_biteq!(f128::from(42_i16), 42.0);
+    assert_biteq!(f128::from(i16::MAX), 32767.0);
+    assert_biteq!(f128::from(u32::MIN), 0.0);
+    assert_biteq!(f128::from(42_u32), 42.0);
+    assert_biteq!(f128::from(u32::MAX), 4294967295.0);
+    assert_biteq!(f128::from(i32::MIN), -2147483648.0);
+    assert_biteq!(f128::from(42_i32), 42.0);
+    assert_biteq!(f128::from(i32::MAX), 2147483647.0);
     // FIXME(f16_f128): Uncomment these tests once the From<{u64,i64}> impls are added.
     // assert_eq!(f128::from(u64::MIN), 0.0);
     // assert_eq!(f128::from(42_u64), 42.0);
diff --git a/library/coretests/tests/floats/f16.rs b/library/coretests/tests/floats/f16.rs
index db98181226c..4797573f7d0 100644
--- a/library/coretests/tests/floats/f16.rs
+++ b/library/coretests/tests/floats/f16.rs
@@ -41,17 +41,6 @@ const NAN_MASK1: u16 = 0x02aa;
 /// Second pattern over the mantissa
 const NAN_MASK2: u16 = 0x0155;
 
-/// Compare by representation
-#[allow(unused_macros)]
-macro_rules! assert_f16_biteq {
-    ($a:expr, $b:expr) => {
-        let (l, r): (&f16, &f16) = (&$a, &$b);
-        let lb = l.to_bits();
-        let rb = r.to_bits();
-        assert_eq!(lb, rb, "float {l:?} ({lb:#04x}) is not bitequal to {r:?} ({rb:#04x})");
-    };
-}
-
 #[test]
 fn test_num_f16() {
     super::test_num(10f16, 2f16);
@@ -61,32 +50,28 @@ fn test_num_f16() {
 // the intrinsics.
 
 #[test]
-#[cfg(not(miri))]
-#[cfg(target_has_reliable_f16_math)]
+#[cfg(any(miri, target_has_reliable_f16_math))]
 fn test_min_nan() {
-    assert_eq!(f16::NAN.min(2.0), 2.0);
-    assert_eq!(2.0f16.min(f16::NAN), 2.0);
+    assert_biteq!(f16::NAN.min(2.0), 2.0);
+    assert_biteq!(2.0f16.min(f16::NAN), 2.0);
 }
 
 #[test]
-#[cfg(not(miri))]
-#[cfg(target_has_reliable_f16_math)]
+#[cfg(any(miri, target_has_reliable_f16_math))]
 fn test_max_nan() {
-    assert_eq!(f16::NAN.max(2.0), 2.0);
-    assert_eq!(2.0f16.max(f16::NAN), 2.0);
+    assert_biteq!(f16::NAN.max(2.0), 2.0);
+    assert_biteq!(2.0f16.max(f16::NAN), 2.0);
 }
 
 #[test]
-#[cfg(not(miri))]
-#[cfg(target_has_reliable_f16_math)]
+#[cfg(any(miri, target_has_reliable_f16_math))]
 fn test_minimum() {
     assert!(f16::NAN.minimum(2.0).is_nan());
     assert!(2.0f16.minimum(f16::NAN).is_nan());
 }
 
 #[test]
-#[cfg(not(miri))]
-#[cfg(target_has_reliable_f16_math)]
+#[cfg(any(miri, target_has_reliable_f16_math))]
 fn test_maximum() {
     assert!(f16::NAN.maximum(2.0).is_nan());
     assert!(2.0f16.maximum(f16::NAN).is_nan());
@@ -133,7 +118,7 @@ fn test_neg_infinity() {
 #[test]
 fn test_zero() {
     let zero: f16 = 0.0f16;
-    assert_eq!(0.0, zero);
+    assert_biteq!(0.0, zero);
     assert!(!zero.is_infinite());
     assert!(zero.is_finite());
     assert!(zero.is_sign_positive());
@@ -147,6 +132,7 @@ fn test_zero() {
 fn test_neg_zero() {
     let neg_zero: f16 = -0.0;
     assert_eq!(0.0, neg_zero);
+    assert_biteq!(-0.0, neg_zero);
     assert!(!neg_zero.is_infinite());
     assert!(neg_zero.is_finite());
     assert!(!neg_zero.is_sign_positive());
@@ -159,7 +145,7 @@ fn test_neg_zero() {
 #[test]
 fn test_one() {
     let one: f16 = 1.0f16;
-    assert_eq!(1.0, one);
+    assert_biteq!(1.0, one);
     assert!(!one.is_infinite());
     assert!(one.is_finite());
     assert!(one.is_sign_positive());
@@ -243,114 +229,107 @@ fn test_classify() {
 }
 
 #[test]
-#[cfg(not(miri))]
-#[cfg(target_has_reliable_f16_math)]
+#[cfg(any(miri, target_has_reliable_f16_math))]
 fn test_floor() {
-    assert_approx_eq!(1.0f16.floor(), 1.0f16, TOL_0);
-    assert_approx_eq!(1.3f16.floor(), 1.0f16, TOL_0);
-    assert_approx_eq!(1.5f16.floor(), 1.0f16, TOL_0);
-    assert_approx_eq!(1.7f16.floor(), 1.0f16, TOL_0);
-    assert_approx_eq!(0.0f16.floor(), 0.0f16, TOL_0);
-    assert_approx_eq!((-0.0f16).floor(), -0.0f16, TOL_0);
-    assert_approx_eq!((-1.0f16).floor(), -1.0f16, TOL_0);
-    assert_approx_eq!((-1.3f16).floor(), -2.0f16, TOL_0);
-    assert_approx_eq!((-1.5f16).floor(), -2.0f16, TOL_0);
-    assert_approx_eq!((-1.7f16).floor(), -2.0f16, TOL_0);
+    assert_biteq!(1.0f16.floor(), 1.0f16);
+    assert_biteq!(1.3f16.floor(), 1.0f16);
+    assert_biteq!(1.5f16.floor(), 1.0f16);
+    assert_biteq!(1.7f16.floor(), 1.0f16);
+    assert_biteq!(0.0f16.floor(), 0.0f16);
+    assert_biteq!((-0.0f16).floor(), -0.0f16);
+    assert_biteq!((-1.0f16).floor(), -1.0f16);
+    assert_biteq!((-1.3f16).floor(), -2.0f16);
+    assert_biteq!((-1.5f16).floor(), -2.0f16);
+    assert_biteq!((-1.7f16).floor(), -2.0f16);
 }
 
 #[test]
-#[cfg(not(miri))]
-#[cfg(target_has_reliable_f16_math)]
+#[cfg(any(miri, target_has_reliable_f16_math))]
 fn test_ceil() {
-    assert_approx_eq!(1.0f16.ceil(), 1.0f16, TOL_0);
-    assert_approx_eq!(1.3f16.ceil(), 2.0f16, TOL_0);
-    assert_approx_eq!(1.5f16.ceil(), 2.0f16, TOL_0);
-    assert_approx_eq!(1.7f16.ceil(), 2.0f16, TOL_0);
-    assert_approx_eq!(0.0f16.ceil(), 0.0f16, TOL_0);
-    assert_approx_eq!((-0.0f16).ceil(), -0.0f16, TOL_0);
-    assert_approx_eq!((-1.0f16).ceil(), -1.0f16, TOL_0);
-    assert_approx_eq!((-1.3f16).ceil(), -1.0f16, TOL_0);
-    assert_approx_eq!((-1.5f16).ceil(), -1.0f16, TOL_0);
-    assert_approx_eq!((-1.7f16).ceil(), -1.0f16, TOL_0);
+    assert_biteq!(1.0f16.ceil(), 1.0f16);
+    assert_biteq!(1.3f16.ceil(), 2.0f16);
+    assert_biteq!(1.5f16.ceil(), 2.0f16);
+    assert_biteq!(1.7f16.ceil(), 2.0f16);
+    assert_biteq!(0.0f16.ceil(), 0.0f16);
+    assert_biteq!((-0.0f16).ceil(), -0.0f16);
+    assert_biteq!((-1.0f16).ceil(), -1.0f16);
+    assert_biteq!((-1.3f16).ceil(), -1.0f16);
+    assert_biteq!((-1.5f16).ceil(), -1.0f16);
+    assert_biteq!((-1.7f16).ceil(), -1.0f16);
 }
 
 #[test]
-#[cfg(not(miri))]
-#[cfg(target_has_reliable_f16_math)]
+#[cfg(any(miri, target_has_reliable_f16_math))]
 fn test_round() {
-    assert_approx_eq!(2.5f16.round(), 3.0f16, TOL_0);
-    assert_approx_eq!(1.0f16.round(), 1.0f16, TOL_0);
-    assert_approx_eq!(1.3f16.round(), 1.0f16, TOL_0);
-    assert_approx_eq!(1.5f16.round(), 2.0f16, TOL_0);
-    assert_approx_eq!(1.7f16.round(), 2.0f16, TOL_0);
-    assert_approx_eq!(0.0f16.round(), 0.0f16, TOL_0);
-    assert_approx_eq!((-0.0f16).round(), -0.0f16, TOL_0);
-    assert_approx_eq!((-1.0f16).round(), -1.0f16, TOL_0);
-    assert_approx_eq!((-1.3f16).round(), -1.0f16, TOL_0);
-    assert_approx_eq!((-1.5f16).round(), -2.0f16, TOL_0);
-    assert_approx_eq!((-1.7f16).round(), -2.0f16, TOL_0);
+    assert_biteq!(2.5f16.round(), 3.0f16);
+    assert_biteq!(1.0f16.round(), 1.0f16);
+    assert_biteq!(1.3f16.round(), 1.0f16);
+    assert_biteq!(1.5f16.round(), 2.0f16);
+    assert_biteq!(1.7f16.round(), 2.0f16);
+    assert_biteq!(0.0f16.round(), 0.0f16);
+    assert_biteq!((-0.0f16).round(), -0.0f16);
+    assert_biteq!((-1.0f16).round(), -1.0f16);
+    assert_biteq!((-1.3f16).round(), -1.0f16);
+    assert_biteq!((-1.5f16).round(), -2.0f16);
+    assert_biteq!((-1.7f16).round(), -2.0f16);
 }
 
 #[test]
-#[cfg(not(miri))]
-#[cfg(target_has_reliable_f16_math)]
+#[cfg(any(miri, target_has_reliable_f16_math))]
 fn test_round_ties_even() {
-    assert_approx_eq!(2.5f16.round_ties_even(), 2.0f16, TOL_0);
-    assert_approx_eq!(1.0f16.round_ties_even(), 1.0f16, TOL_0);
-    assert_approx_eq!(1.3f16.round_ties_even(), 1.0f16, TOL_0);
-    assert_approx_eq!(1.5f16.round_ties_even(), 2.0f16, TOL_0);
-    assert_approx_eq!(1.7f16.round_ties_even(), 2.0f16, TOL_0);
-    assert_approx_eq!(0.0f16.round_ties_even(), 0.0f16, TOL_0);
-    assert_approx_eq!((-0.0f16).round_ties_even(), -0.0f16, TOL_0);
-    assert_approx_eq!((-1.0f16).round_ties_even(), -1.0f16, TOL_0);
-    assert_approx_eq!((-1.3f16).round_ties_even(), -1.0f16, TOL_0);
-    assert_approx_eq!((-1.5f16).round_ties_even(), -2.0f16, TOL_0);
-    assert_approx_eq!((-1.7f16).round_ties_even(), -2.0f16, TOL_0);
+    assert_biteq!(2.5f16.round_ties_even(), 2.0f16);
+    assert_biteq!(1.0f16.round_ties_even(), 1.0f16);
+    assert_biteq!(1.3f16.round_ties_even(), 1.0f16);
+    assert_biteq!(1.5f16.round_ties_even(), 2.0f16);
+    assert_biteq!(1.7f16.round_ties_even(), 2.0f16);
+    assert_biteq!(0.0f16.round_ties_even(), 0.0f16);
+    assert_biteq!((-0.0f16).round_ties_even(), -0.0f16);
+    assert_biteq!((-1.0f16).round_ties_even(), -1.0f16);
+    assert_biteq!((-1.3f16).round_ties_even(), -1.0f16);
+    assert_biteq!((-1.5f16).round_ties_even(), -2.0f16);
+    assert_biteq!((-1.7f16).round_ties_even(), -2.0f16);
 }
 
 #[test]
-#[cfg(not(miri))]
-#[cfg(target_has_reliable_f16_math)]
+#[cfg(any(miri, target_has_reliable_f16_math))]
 fn test_trunc() {
-    assert_approx_eq!(1.0f16.trunc(), 1.0f16, TOL_0);
-    assert_approx_eq!(1.3f16.trunc(), 1.0f16, TOL_0);
-    assert_approx_eq!(1.5f16.trunc(), 1.0f16, TOL_0);
-    assert_approx_eq!(1.7f16.trunc(), 1.0f16, TOL_0);
-    assert_approx_eq!(0.0f16.trunc(), 0.0f16, TOL_0);
-    assert_approx_eq!((-0.0f16).trunc(), -0.0f16, TOL_0);
-    assert_approx_eq!((-1.0f16).trunc(), -1.0f16, TOL_0);
-    assert_approx_eq!((-1.3f16).trunc(), -1.0f16, TOL_0);
-    assert_approx_eq!((-1.5f16).trunc(), -1.0f16, TOL_0);
-    assert_approx_eq!((-1.7f16).trunc(), -1.0f16, TOL_0);
+    assert_biteq!(1.0f16.trunc(), 1.0f16);
+    assert_biteq!(1.3f16.trunc(), 1.0f16);
+    assert_biteq!(1.5f16.trunc(), 1.0f16);
+    assert_biteq!(1.7f16.trunc(), 1.0f16);
+    assert_biteq!(0.0f16.trunc(), 0.0f16);
+    assert_biteq!((-0.0f16).trunc(), -0.0f16);
+    assert_biteq!((-1.0f16).trunc(), -1.0f16);
+    assert_biteq!((-1.3f16).trunc(), -1.0f16);
+    assert_biteq!((-1.5f16).trunc(), -1.0f16);
+    assert_biteq!((-1.7f16).trunc(), -1.0f16);
 }
 
 #[test]
-#[cfg(not(miri))]
-#[cfg(target_has_reliable_f16_math)]
+#[cfg(any(miri, target_has_reliable_f16_math))]
 fn test_fract() {
-    assert_approx_eq!(1.0f16.fract(), 0.0f16, TOL_0);
-    assert_approx_eq!(1.3f16.fract(), 0.3f16, TOL_0);
-    assert_approx_eq!(1.5f16.fract(), 0.5f16, TOL_0);
-    assert_approx_eq!(1.7f16.fract(), 0.7f16, TOL_0);
-    assert_approx_eq!(0.0f16.fract(), 0.0f16, TOL_0);
-    assert_approx_eq!((-0.0f16).fract(), -0.0f16, TOL_0);
-    assert_approx_eq!((-1.0f16).fract(), -0.0f16, TOL_0);
-    assert_approx_eq!((-1.3f16).fract(), -0.3f16, TOL_0);
-    assert_approx_eq!((-1.5f16).fract(), -0.5f16, TOL_0);
-    assert_approx_eq!((-1.7f16).fract(), -0.7f16, TOL_0);
+    assert_biteq!(1.0f16.fract(), 0.0f16);
+    assert_biteq!(1.3f16.fract(), 0.2998f16);
+    assert_biteq!(1.5f16.fract(), 0.5f16);
+    assert_biteq!(1.7f16.fract(), 0.7f16);
+    assert_biteq!(0.0f16.fract(), 0.0f16);
+    assert_biteq!((-0.0f16).fract(), 0.0f16);
+    assert_biteq!((-1.0f16).fract(), 0.0f16);
+    assert_biteq!((-1.3f16).fract(), -0.2998f16);
+    assert_biteq!((-1.5f16).fract(), -0.5f16);
+    assert_biteq!((-1.7f16).fract(), -0.7f16);
 }
 
 #[test]
-#[cfg(not(miri))]
-#[cfg(target_has_reliable_f16_math)]
+#[cfg(any(miri, target_has_reliable_f16_math))]
 fn test_abs() {
-    assert_eq!(f16::INFINITY.abs(), f16::INFINITY);
-    assert_eq!(1f16.abs(), 1f16);
-    assert_eq!(0f16.abs(), 0f16);
-    assert_eq!((-0f16).abs(), 0f16);
-    assert_eq!((-1f16).abs(), 1f16);
-    assert_eq!(f16::NEG_INFINITY.abs(), f16::INFINITY);
-    assert_eq!((1f16 / f16::NEG_INFINITY).abs(), 0f16);
+    assert_biteq!(f16::INFINITY.abs(), f16::INFINITY);
+    assert_biteq!(1f16.abs(), 1f16);
+    assert_biteq!(0f16.abs(), 0f16);
+    assert_biteq!((-0f16).abs(), 0f16);
+    assert_biteq!((-1f16).abs(), 1f16);
+    assert_biteq!(f16::NEG_INFINITY.abs(), f16::INFINITY);
+    assert_biteq!((1f16 / f16::NEG_INFINITY).abs(), 0f16);
     assert!(f16::NAN.abs().is_nan());
 }
 
@@ -387,27 +366,27 @@ fn test_next_up() {
     let max_down = f16::from_bits(MAX_DOWN_BITS);
     let largest_subnormal = f16::from_bits(LARGEST_SUBNORMAL_BITS);
     let smallest_normal = f16::from_bits(SMALLEST_NORMAL_BITS);
-    assert_f16_biteq!(f16::NEG_INFINITY.next_up(), f16::MIN);
-    assert_f16_biteq!(f16::MIN.next_up(), -max_down);
-    assert_f16_biteq!((-1.0 - f16::EPSILON).next_up(), -1.0);
-    assert_f16_biteq!((-smallest_normal).next_up(), -largest_subnormal);
-    assert_f16_biteq!((-tiny_up).next_up(), -tiny);
-    assert_f16_biteq!((-tiny).next_up(), -0.0f16);
-    assert_f16_biteq!((-0.0f16).next_up(), tiny);
-    assert_f16_biteq!(0.0f16.next_up(), tiny);
-    assert_f16_biteq!(tiny.next_up(), tiny_up);
-    assert_f16_biteq!(largest_subnormal.next_up(), smallest_normal);
-    assert_f16_biteq!(1.0f16.next_up(), 1.0 + f16::EPSILON);
-    assert_f16_biteq!(f16::MAX.next_up(), f16::INFINITY);
-    assert_f16_biteq!(f16::INFINITY.next_up(), f16::INFINITY);
+    assert_biteq!(f16::NEG_INFINITY.next_up(), f16::MIN);
+    assert_biteq!(f16::MIN.next_up(), -max_down);
+    assert_biteq!((-1.0 - f16::EPSILON).next_up(), -1.0f16);
+    assert_biteq!((-smallest_normal).next_up(), -largest_subnormal);
+    assert_biteq!((-tiny_up).next_up(), -tiny);
+    assert_biteq!((-tiny).next_up(), -0.0f16);
+    assert_biteq!((-0.0f16).next_up(), tiny);
+    assert_biteq!(0.0f16.next_up(), tiny);
+    assert_biteq!(tiny.next_up(), tiny_up);
+    assert_biteq!(largest_subnormal.next_up(), smallest_normal);
+    assert_biteq!(1.0f16.next_up(), 1.0 + f16::EPSILON);
+    assert_biteq!(f16::MAX.next_up(), f16::INFINITY);
+    assert_biteq!(f16::INFINITY.next_up(), f16::INFINITY);
 
     // Check that NaNs roundtrip.
     let nan0 = f16::NAN;
     let nan1 = f16::from_bits(f16::NAN.to_bits() ^ NAN_MASK1);
     let nan2 = f16::from_bits(f16::NAN.to_bits() ^ NAN_MASK2);
-    assert_f16_biteq!(nan0.next_up(), nan0);
-    assert_f16_biteq!(nan1.next_up(), nan1);
-    assert_f16_biteq!(nan2.next_up(), nan2);
+    assert_biteq!(nan0.next_up(), nan0);
+    assert_biteq!(nan1.next_up(), nan1);
+    assert_biteq!(nan2.next_up(), nan2);
 }
 
 #[test]
@@ -417,28 +396,28 @@ fn test_next_down() {
     let max_down = f16::from_bits(MAX_DOWN_BITS);
     let largest_subnormal = f16::from_bits(LARGEST_SUBNORMAL_BITS);
     let smallest_normal = f16::from_bits(SMALLEST_NORMAL_BITS);
-    assert_f16_biteq!(f16::NEG_INFINITY.next_down(), f16::NEG_INFINITY);
-    assert_f16_biteq!(f16::MIN.next_down(), f16::NEG_INFINITY);
-    assert_f16_biteq!((-max_down).next_down(), f16::MIN);
-    assert_f16_biteq!((-1.0f16).next_down(), -1.0 - f16::EPSILON);
-    assert_f16_biteq!((-largest_subnormal).next_down(), -smallest_normal);
-    assert_f16_biteq!((-tiny).next_down(), -tiny_up);
-    assert_f16_biteq!((-0.0f16).next_down(), -tiny);
-    assert_f16_biteq!((0.0f16).next_down(), -tiny);
-    assert_f16_biteq!(tiny.next_down(), 0.0f16);
-    assert_f16_biteq!(tiny_up.next_down(), tiny);
-    assert_f16_biteq!(smallest_normal.next_down(), largest_subnormal);
-    assert_f16_biteq!((1.0 + f16::EPSILON).next_down(), 1.0f16);
-    assert_f16_biteq!(f16::MAX.next_down(), max_down);
-    assert_f16_biteq!(f16::INFINITY.next_down(), f16::MAX);
+    assert_biteq!(f16::NEG_INFINITY.next_down(), f16::NEG_INFINITY);
+    assert_biteq!(f16::MIN.next_down(), f16::NEG_INFINITY);
+    assert_biteq!((-max_down).next_down(), f16::MIN);
+    assert_biteq!((-1.0f16).next_down(), -1.0 - f16::EPSILON);
+    assert_biteq!((-largest_subnormal).next_down(), -smallest_normal);
+    assert_biteq!((-tiny).next_down(), -tiny_up);
+    assert_biteq!((-0.0f16).next_down(), -tiny);
+    assert_biteq!((0.0f16).next_down(), -tiny);
+    assert_biteq!(tiny.next_down(), 0.0f16);
+    assert_biteq!(tiny_up.next_down(), tiny);
+    assert_biteq!(smallest_normal.next_down(), largest_subnormal);
+    assert_biteq!((1.0 + f16::EPSILON).next_down(), 1.0f16);
+    assert_biteq!(f16::MAX.next_down(), max_down);
+    assert_biteq!(f16::INFINITY.next_down(), f16::MAX);
 
     // Check that NaNs roundtrip.
     let nan0 = f16::NAN;
     let nan1 = f16::from_bits(f16::NAN.to_bits() ^ NAN_MASK1);
     let nan2 = f16::from_bits(f16::NAN.to_bits() ^ NAN_MASK2);
-    assert_f16_biteq!(nan0.next_down(), nan0);
-    assert_f16_biteq!(nan1.next_down(), nan1);
-    assert_f16_biteq!(nan2.next_down(), nan2);
+    assert_biteq!(nan0.next_down(), nan0);
+    assert_biteq!(nan1.next_down(), nan1);
+    assert_biteq!(nan2.next_down(), nan2);
 }
 
 #[test]
@@ -448,32 +427,31 @@ fn test_mul_add() {
     let nan: f16 = f16::NAN;
     let inf: f16 = f16::INFINITY;
     let neg_inf: f16 = f16::NEG_INFINITY;
-    assert_approx_eq!(12.3f16.mul_add(4.5, 6.7), 62.05, TOL_P2);
-    assert_approx_eq!((-12.3f16).mul_add(-4.5, -6.7), 48.65, TOL_P2);
-    assert_approx_eq!(0.0f16.mul_add(8.9, 1.2), 1.2, TOL_0);
-    assert_approx_eq!(3.4f16.mul_add(-0.0, 5.6), 5.6, TOL_0);
+    assert_biteq!(12.3f16.mul_add(4.5, 6.7), 62.031);
+    assert_biteq!((-12.3f16).mul_add(-4.5, -6.7), 48.625);
+    assert_biteq!(0.0f16.mul_add(8.9, 1.2), 1.2);
+    assert_biteq!(3.4f16.mul_add(-0.0, 5.6), 5.6);
     assert!(nan.mul_add(7.8, 9.0).is_nan());
-    assert_eq!(inf.mul_add(7.8, 9.0), inf);
-    assert_eq!(neg_inf.mul_add(7.8, 9.0), neg_inf);
-    assert_eq!(8.9f16.mul_add(inf, 3.2), inf);
-    assert_eq!((-3.2f16).mul_add(2.4, neg_inf), neg_inf);
+    assert_biteq!(inf.mul_add(7.8, 9.0), inf);
+    assert_biteq!(neg_inf.mul_add(7.8, 9.0), neg_inf);
+    assert_biteq!(8.9f16.mul_add(inf, 3.2), inf);
+    assert_biteq!((-3.2f16).mul_add(2.4, neg_inf), neg_inf);
 }
 
 #[test]
-#[cfg(not(miri))]
-#[cfg(target_has_reliable_f16_math)]
+#[cfg(any(miri, target_has_reliable_f16_math))]
 fn test_recip() {
     let nan: f16 = f16::NAN;
     let inf: f16 = f16::INFINITY;
     let neg_inf: f16 = f16::NEG_INFINITY;
-    assert_eq!(1.0f16.recip(), 1.0);
-    assert_eq!(2.0f16.recip(), 0.5);
-    assert_eq!((-0.4f16).recip(), -2.5);
-    assert_eq!(0.0f16.recip(), inf);
+    assert_biteq!(1.0f16.recip(), 1.0);
+    assert_biteq!(2.0f16.recip(), 0.5);
+    assert_biteq!((-0.4f16).recip(), -2.5);
+    assert_biteq!(0.0f16.recip(), inf);
     assert_approx_eq!(f16::MAX.recip(), 1.526624e-5f16, 1e-4);
     assert!(nan.recip().is_nan());
-    assert_eq!(inf.recip(), 0.0);
-    assert_eq!(neg_inf.recip(), 0.0);
+    assert_biteq!(inf.recip(), 0.0);
+    assert_biteq!(neg_inf.recip(), -0.0);
 }
 
 #[test]
@@ -483,13 +461,13 @@ fn test_powi() {
     let nan: f16 = f16::NAN;
     let inf: f16 = f16::INFINITY;
     let neg_inf: f16 = f16::NEG_INFINITY;
-    assert_eq!(1.0f16.powi(1), 1.0);
+    assert_biteq!(1.0f16.powi(1), 1.0);
     assert_approx_eq!((-3.1f16).powi(2), 9.61, TOL_0);
     assert_approx_eq!(5.9f16.powi(-2), 0.028727, TOL_N2);
-    assert_eq!(8.3f16.powi(0), 1.0);
+    assert_biteq!(8.3f16.powi(0), 1.0);
     assert!(nan.powi(2).is_nan());
-    assert_eq!(inf.powi(3), inf);
-    assert_eq!(neg_inf.powi(2), inf);
+    assert_biteq!(inf.powi(3), inf);
+    assert_biteq!(neg_inf.powi(2), inf);
 }
 
 #[test]
@@ -499,10 +477,10 @@ fn test_sqrt_domain() {
     assert!(f16::NAN.sqrt().is_nan());
     assert!(f16::NEG_INFINITY.sqrt().is_nan());
     assert!((-1.0f16).sqrt().is_nan());
-    assert_eq!((-0.0f16).sqrt(), -0.0);
-    assert_eq!(0.0f16.sqrt(), 0.0);
-    assert_eq!(1.0f16.sqrt(), 1.0);
-    assert_eq!(f16::INFINITY.sqrt(), f16::INFINITY);
+    assert_biteq!((-0.0f16).sqrt(), -0.0);
+    assert_biteq!(0.0f16.sqrt(), 0.0);
+    assert_biteq!(1.0f16.sqrt(), 1.0);
+    assert_biteq!(f16::INFINITY.sqrt(), f16::INFINITY);
 }
 
 #[test]
@@ -511,13 +489,13 @@ fn test_to_degrees() {
     let nan: f16 = f16::NAN;
     let inf: f16 = f16::INFINITY;
     let neg_inf: f16 = f16::NEG_INFINITY;
-    assert_eq!(0.0f16.to_degrees(), 0.0);
+    assert_biteq!(0.0f16.to_degrees(), 0.0);
     assert_approx_eq!((-5.8f16).to_degrees(), -332.315521, TOL_P2);
     assert_approx_eq!(pi.to_degrees(), 180.0, TOL_P2);
     assert!(nan.to_degrees().is_nan());
-    assert_eq!(inf.to_degrees(), inf);
-    assert_eq!(neg_inf.to_degrees(), neg_inf);
-    assert_eq!(1_f16.to_degrees(), 57.2957795130823208767981548141051703);
+    assert_biteq!(inf.to_degrees(), inf);
+    assert_biteq!(neg_inf.to_degrees(), neg_inf);
+    assert_biteq!(1_f16.to_degrees(), 57.2957795130823208767981548141051703);
 }
 
 #[test]
@@ -526,13 +504,13 @@ fn test_to_radians() {
     let nan: f16 = f16::NAN;
     let inf: f16 = f16::INFINITY;
     let neg_inf: f16 = f16::NEG_INFINITY;
-    assert_eq!(0.0f16.to_radians(), 0.0);
+    assert_biteq!(0.0f16.to_radians(), 0.0);
     assert_approx_eq!(154.6f16.to_radians(), 2.698279, TOL_0);
     assert_approx_eq!((-332.31f16).to_radians(), -5.799903, TOL_0);
     assert_approx_eq!(180.0f16.to_radians(), pi, TOL_0);
     assert!(nan.to_radians().is_nan());
-    assert_eq!(inf.to_radians(), inf);
-    assert_eq!(neg_inf.to_radians(), neg_inf);
+    assert_biteq!(inf.to_radians(), inf);
+    assert_biteq!(neg_inf.to_radians(), neg_inf);
 }
 
 #[test]
@@ -541,10 +519,10 @@ fn test_float_bits_conv() {
     assert_eq!((12.5f16).to_bits(), 0x4a40);
     assert_eq!((1337f16).to_bits(), 0x6539);
     assert_eq!((-14.25f16).to_bits(), 0xcb20);
-    assert_approx_eq!(f16::from_bits(0x3c00), 1.0, TOL_0);
-    assert_approx_eq!(f16::from_bits(0x4a40), 12.5, TOL_0);
-    assert_approx_eq!(f16::from_bits(0x6539), 1337.0, TOL_P4);
-    assert_approx_eq!(f16::from_bits(0xcb20), -14.25, TOL_0);
+    assert_biteq!(f16::from_bits(0x3c00), 1.0);
+    assert_biteq!(f16::from_bits(0x4a40), 12.5);
+    assert_biteq!(f16::from_bits(0x6539), 1337.0);
+    assert_biteq!(f16::from_bits(0xcb20), -14.25);
 
     // Check that NaNs roundtrip their bits regardless of signaling-ness
     let masked_nan1 = f16::NAN.to_bits() ^ NAN_MASK1;
@@ -596,12 +574,15 @@ fn test_total_cmp() {
         f16::from_bits(f16::NAN.to_bits() | quiet_bit_mask())
     }
 
-    fn s_nan() -> f16 {
-        f16::from_bits((f16::NAN.to_bits() & !quiet_bit_mask()) + 42)
-    }
+    // FIXME(f16_f128): Tests involving sNaN are disabled because without optimizations,
+    // `total_cmp` is getting incorrectly lowered to code that includes a `extend`/`trunc` round
+    // trip, which quiets sNaNs. See: https://github.com/llvm/llvm-project/issues/104915
+    // fn s_nan() -> f16 {
+    //     f16::from_bits((f16::NAN.to_bits() & !quiet_bit_mask()) + 42)
+    // }
 
     assert_eq!(Ordering::Equal, (-q_nan()).total_cmp(&-q_nan()));
-    assert_eq!(Ordering::Equal, (-s_nan()).total_cmp(&-s_nan()));
+    // assert_eq!(Ordering::Equal, (-s_nan()).total_cmp(&-s_nan()));
     assert_eq!(Ordering::Equal, (-f16::INFINITY).total_cmp(&-f16::INFINITY));
     assert_eq!(Ordering::Equal, (-f16::MAX).total_cmp(&-f16::MAX));
     assert_eq!(Ordering::Equal, (-2.5_f16).total_cmp(&-2.5));
@@ -622,11 +603,11 @@ fn test_total_cmp() {
     assert_eq!(Ordering::Equal, 2.5_f16.total_cmp(&2.5));
     assert_eq!(Ordering::Equal, f16::MAX.total_cmp(&f16::MAX));
     assert_eq!(Ordering::Equal, f16::INFINITY.total_cmp(&f16::INFINITY));
-    assert_eq!(Ordering::Equal, s_nan().total_cmp(&s_nan()));
+    // assert_eq!(Ordering::Equal, s_nan().total_cmp(&s_nan()));
     assert_eq!(Ordering::Equal, q_nan().total_cmp(&q_nan()));
 
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-s_nan()));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-f16::INFINITY));
+    // assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-s_nan()));
+    // assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-f16::INFINITY));
     assert_eq!(Ordering::Less, (-f16::INFINITY).total_cmp(&-f16::MAX));
     assert_eq!(Ordering::Less, (-f16::MAX).total_cmp(&-2.5));
     assert_eq!(Ordering::Less, (-2.5_f16).total_cmp(&-1.5));
@@ -646,11 +627,11 @@ fn test_total_cmp() {
     assert_eq!(Ordering::Less, 1.5_f16.total_cmp(&2.5));
     assert_eq!(Ordering::Less, 2.5_f16.total_cmp(&f16::MAX));
     assert_eq!(Ordering::Less, f16::MAX.total_cmp(&f16::INFINITY));
-    assert_eq!(Ordering::Less, f16::INFINITY.total_cmp(&s_nan()));
-    assert_eq!(Ordering::Less, s_nan().total_cmp(&q_nan()));
+    // assert_eq!(Ordering::Less, f16::INFINITY.total_cmp(&s_nan()));
+    // assert_eq!(Ordering::Less, s_nan().total_cmp(&q_nan()));
 
-    assert_eq!(Ordering::Greater, (-s_nan()).total_cmp(&-q_nan()));
-    assert_eq!(Ordering::Greater, (-f16::INFINITY).total_cmp(&-s_nan()));
+    // assert_eq!(Ordering::Greater, (-s_nan()).total_cmp(&-q_nan()));
+    // assert_eq!(Ordering::Greater, (-f16::INFINITY).total_cmp(&-s_nan()));
     assert_eq!(Ordering::Greater, (-f16::MAX).total_cmp(&-f16::INFINITY));
     assert_eq!(Ordering::Greater, (-2.5_f16).total_cmp(&-f16::MAX));
     assert_eq!(Ordering::Greater, (-1.5_f16).total_cmp(&-2.5));
@@ -670,10 +651,10 @@ fn test_total_cmp() {
     assert_eq!(Ordering::Greater, 2.5_f16.total_cmp(&1.5));
     assert_eq!(Ordering::Greater, f16::MAX.total_cmp(&2.5));
     assert_eq!(Ordering::Greater, f16::INFINITY.total_cmp(&f16::MAX));
-    assert_eq!(Ordering::Greater, s_nan().total_cmp(&f16::INFINITY));
-    assert_eq!(Ordering::Greater, q_nan().total_cmp(&s_nan()));
+    // assert_eq!(Ordering::Greater, s_nan().total_cmp(&f16::INFINITY));
+    // assert_eq!(Ordering::Greater, q_nan().total_cmp(&s_nan()));
 
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-s_nan()));
+    // assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-s_nan()));
     assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-f16::INFINITY));
     assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-f16::MAX));
     assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-2.5));
@@ -694,29 +675,29 @@ fn test_total_cmp() {
     assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&2.5));
     assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&f16::MAX));
     assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&f16::INFINITY));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&s_nan()));
-
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-f16::INFINITY));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-f16::MAX));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-2.5));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-1.5));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-1.0));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-0.5));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-f16::MIN_POSITIVE));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-max_subnorm()));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-min_subnorm()));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-0.0));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&0.0));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&min_subnorm()));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&max_subnorm()));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&f16::MIN_POSITIVE));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&0.5));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&1.0));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&1.5));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&2.5));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&f16::MAX));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&f16::INFINITY));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&s_nan()));
+    // assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&s_nan()));
+
+    // assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-f16::INFINITY));
+    // assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-f16::MAX));
+    // assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-2.5));
+    // assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-1.5));
+    // assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-1.0));
+    // assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-0.5));
+    // assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-f16::MIN_POSITIVE));
+    // assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-max_subnorm()));
+    // assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-min_subnorm()));
+    // assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-0.0));
+    // assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&0.0));
+    // assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&min_subnorm()));
+    // assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&max_subnorm()));
+    // assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&f16::MIN_POSITIVE));
+    // assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&0.5));
+    // assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&1.0));
+    // assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&1.5));
+    // assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&2.5));
+    // assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&f16::MAX));
+    // assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&f16::INFINITY));
+    // assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&s_nan()));
 }
 
 #[test]
@@ -742,12 +723,12 @@ fn test_algebraic() {
 
 #[test]
 fn test_from() {
-    assert_eq!(f16::from(false), 0.0);
-    assert_eq!(f16::from(true), 1.0);
-    assert_eq!(f16::from(u8::MIN), 0.0);
-    assert_eq!(f16::from(42_u8), 42.0);
-    assert_eq!(f16::from(u8::MAX), 255.0);
-    assert_eq!(f16::from(i8::MIN), -128.0);
-    assert_eq!(f16::from(42_i8), 42.0);
-    assert_eq!(f16::from(i8::MAX), 127.0);
+    assert_biteq!(f16::from(false), 0.0);
+    assert_biteq!(f16::from(true), 1.0);
+    assert_biteq!(f16::from(u8::MIN), 0.0);
+    assert_biteq!(f16::from(42_u8), 42.0);
+    assert_biteq!(f16::from(u8::MAX), 255.0);
+    assert_biteq!(f16::from(i8::MIN), -128.0);
+    assert_biteq!(f16::from(42_i8), 42.0);
+    assert_biteq!(f16::from(i8::MAX), 127.0);
 }
diff --git a/library/coretests/tests/floats/f32.rs b/library/coretests/tests/floats/f32.rs
index 36f1937bedf..4e6509ead2b 100644
--- a/library/coretests/tests/floats/f32.rs
+++ b/library/coretests/tests/floats/f32.rs
@@ -23,17 +23,6 @@ const NAN_MASK1: u32 = 0x002a_aaaa;
 /// Second pattern over the mantissa
 const NAN_MASK2: u32 = 0x0055_5555;
 
-#[allow(unused_macros)]
-macro_rules! assert_f32_biteq {
-    ($left : expr, $right : expr) => {
-        let l: &f32 = &$left;
-        let r: &f32 = &$right;
-        let lb = l.to_bits();
-        let rb = r.to_bits();
-        assert_eq!(lb, rb, "float {l} ({lb:#010x}) is not bitequal to {r} ({rb:#010x})");
-    };
-}
-
 #[test]
 fn test_num_f32() {
     super::test_num(10f32, 2f32);
@@ -41,14 +30,14 @@ fn test_num_f32() {
 
 #[test]
 fn test_min_nan() {
-    assert_eq!(f32::NAN.min(2.0), 2.0);
-    assert_eq!(2.0f32.min(f32::NAN), 2.0);
+    assert_biteq!(f32::NAN.min(2.0), 2.0);
+    assert_biteq!(2.0f32.min(f32::NAN), 2.0);
 }
 
 #[test]
 fn test_max_nan() {
-    assert_eq!(f32::NAN.max(2.0), 2.0);
-    assert_eq!(2.0f32.max(f32::NAN), 2.0);
+    assert_biteq!(f32::NAN.max(2.0), 2.0);
+    assert_biteq!(2.0f32.max(f32::NAN), 2.0);
 }
 
 #[test]
@@ -104,7 +93,7 @@ fn test_neg_infinity() {
 #[test]
 fn test_zero() {
     let zero: f32 = 0.0f32;
-    assert_eq!(0.0, zero);
+    assert_biteq!(0.0, zero);
     assert!(!zero.is_infinite());
     assert!(zero.is_finite());
     assert!(zero.is_sign_positive());
@@ -118,6 +107,7 @@ fn test_zero() {
 fn test_neg_zero() {
     let neg_zero: f32 = -0.0;
     assert_eq!(0.0, neg_zero);
+    assert_biteq!(-0.0, neg_zero);
     assert!(!neg_zero.is_infinite());
     assert!(neg_zero.is_finite());
     assert!(!neg_zero.is_sign_positive());
@@ -130,7 +120,7 @@ fn test_neg_zero() {
 #[test]
 fn test_one() {
     let one: f32 = 1.0f32;
-    assert_eq!(1.0, one);
+    assert_biteq!(1.0, one);
     assert!(!one.is_infinite());
     assert!(one.is_finite());
     assert!(one.is_sign_positive());
@@ -215,111 +205,111 @@ fn test_classify() {
 
 #[test]
 fn test_floor() {
-    assert_approx_eq!(f32::math::floor(1.0f32), 1.0f32);
-    assert_approx_eq!(f32::math::floor(1.3f32), 1.0f32);
-    assert_approx_eq!(f32::math::floor(1.5f32), 1.0f32);
-    assert_approx_eq!(f32::math::floor(1.7f32), 1.0f32);
-    assert_approx_eq!(f32::math::floor(0.0f32), 0.0f32);
-    assert_approx_eq!(f32::math::floor(-0.0f32), -0.0f32);
-    assert_approx_eq!(f32::math::floor(-1.0f32), -1.0f32);
-    assert_approx_eq!(f32::math::floor(-1.3f32), -2.0f32);
-    assert_approx_eq!(f32::math::floor(-1.5f32), -2.0f32);
-    assert_approx_eq!(f32::math::floor(-1.7f32), -2.0f32);
+    assert_biteq!(f32::math::floor(1.0f32), 1.0f32);
+    assert_biteq!(f32::math::floor(1.3f32), 1.0f32);
+    assert_biteq!(f32::math::floor(1.5f32), 1.0f32);
+    assert_biteq!(f32::math::floor(1.7f32), 1.0f32);
+    assert_biteq!(f32::math::floor(0.0f32), 0.0f32);
+    assert_biteq!(f32::math::floor(-0.0f32), -0.0f32);
+    assert_biteq!(f32::math::floor(-1.0f32), -1.0f32);
+    assert_biteq!(f32::math::floor(-1.3f32), -2.0f32);
+    assert_biteq!(f32::math::floor(-1.5f32), -2.0f32);
+    assert_biteq!(f32::math::floor(-1.7f32), -2.0f32);
 }
 
 #[test]
 fn test_ceil() {
-    assert_approx_eq!(f32::math::ceil(1.0f32), 1.0f32);
-    assert_approx_eq!(f32::math::ceil(1.3f32), 2.0f32);
-    assert_approx_eq!(f32::math::ceil(1.5f32), 2.0f32);
-    assert_approx_eq!(f32::math::ceil(1.7f32), 2.0f32);
-    assert_approx_eq!(f32::math::ceil(0.0f32), 0.0f32);
-    assert_approx_eq!(f32::math::ceil(-0.0f32), -0.0f32);
-    assert_approx_eq!(f32::math::ceil(-1.0f32), -1.0f32);
-    assert_approx_eq!(f32::math::ceil(-1.3f32), -1.0f32);
-    assert_approx_eq!(f32::math::ceil(-1.5f32), -1.0f32);
-    assert_approx_eq!(f32::math::ceil(-1.7f32), -1.0f32);
+    assert_biteq!(f32::math::ceil(1.0f32), 1.0f32);
+    assert_biteq!(f32::math::ceil(1.3f32), 2.0f32);
+    assert_biteq!(f32::math::ceil(1.5f32), 2.0f32);
+    assert_biteq!(f32::math::ceil(1.7f32), 2.0f32);
+    assert_biteq!(f32::math::ceil(0.0f32), 0.0f32);
+    assert_biteq!(f32::math::ceil(-0.0f32), -0.0f32);
+    assert_biteq!(f32::math::ceil(-1.0f32), -1.0f32);
+    assert_biteq!(f32::math::ceil(-1.3f32), -1.0f32);
+    assert_biteq!(f32::math::ceil(-1.5f32), -1.0f32);
+    assert_biteq!(f32::math::ceil(-1.7f32), -1.0f32);
 }
 
 #[test]
 fn test_round() {
-    assert_approx_eq!(f32::math::round(2.5f32), 3.0f32);
-    assert_approx_eq!(f32::math::round(1.0f32), 1.0f32);
-    assert_approx_eq!(f32::math::round(1.3f32), 1.0f32);
-    assert_approx_eq!(f32::math::round(1.5f32), 2.0f32);
-    assert_approx_eq!(f32::math::round(1.7f32), 2.0f32);
-    assert_approx_eq!(f32::math::round(0.0f32), 0.0f32);
-    assert_approx_eq!(f32::math::round(-0.0f32), -0.0f32);
-    assert_approx_eq!(f32::math::round(-1.0f32), -1.0f32);
-    assert_approx_eq!(f32::math::round(-1.3f32), -1.0f32);
-    assert_approx_eq!(f32::math::round(-1.5f32), -2.0f32);
-    assert_approx_eq!(f32::math::round(-1.7f32), -2.0f32);
+    assert_biteq!(f32::math::round(2.5f32), 3.0f32);
+    assert_biteq!(f32::math::round(1.0f32), 1.0f32);
+    assert_biteq!(f32::math::round(1.3f32), 1.0f32);
+    assert_biteq!(f32::math::round(1.5f32), 2.0f32);
+    assert_biteq!(f32::math::round(1.7f32), 2.0f32);
+    assert_biteq!(f32::math::round(0.0f32), 0.0f32);
+    assert_biteq!(f32::math::round(-0.0f32), -0.0f32);
+    assert_biteq!(f32::math::round(-1.0f32), -1.0f32);
+    assert_biteq!(f32::math::round(-1.3f32), -1.0f32);
+    assert_biteq!(f32::math::round(-1.5f32), -2.0f32);
+    assert_biteq!(f32::math::round(-1.7f32), -2.0f32);
 }
 
 #[test]
 fn test_round_ties_even() {
-    assert_approx_eq!(f32::math::round_ties_even(2.5f32), 2.0f32);
-    assert_approx_eq!(f32::math::round_ties_even(1.0f32), 1.0f32);
-    assert_approx_eq!(f32::math::round_ties_even(1.3f32), 1.0f32);
-    assert_approx_eq!(f32::math::round_ties_even(1.5f32), 2.0f32);
-    assert_approx_eq!(f32::math::round_ties_even(1.7f32), 2.0f32);
-    assert_approx_eq!(f32::math::round_ties_even(0.0f32), 0.0f32);
-    assert_approx_eq!(f32::math::round_ties_even(-0.0f32), -0.0f32);
-    assert_approx_eq!(f32::math::round_ties_even(-1.0f32), -1.0f32);
-    assert_approx_eq!(f32::math::round_ties_even(-1.3f32), -1.0f32);
-    assert_approx_eq!(f32::math::round_ties_even(-1.5f32), -2.0f32);
-    assert_approx_eq!(f32::math::round_ties_even(-1.7f32), -2.0f32);
+    assert_biteq!(f32::math::round_ties_even(2.5f32), 2.0f32);
+    assert_biteq!(f32::math::round_ties_even(1.0f32), 1.0f32);
+    assert_biteq!(f32::math::round_ties_even(1.3f32), 1.0f32);
+    assert_biteq!(f32::math::round_ties_even(1.5f32), 2.0f32);
+    assert_biteq!(f32::math::round_ties_even(1.7f32), 2.0f32);
+    assert_biteq!(f32::math::round_ties_even(0.0f32), 0.0f32);
+    assert_biteq!(f32::math::round_ties_even(-0.0f32), -0.0f32);
+    assert_biteq!(f32::math::round_ties_even(-1.0f32), -1.0f32);
+    assert_biteq!(f32::math::round_ties_even(-1.3f32), -1.0f32);
+    assert_biteq!(f32::math::round_ties_even(-1.5f32), -2.0f32);
+    assert_biteq!(f32::math::round_ties_even(-1.7f32), -2.0f32);
 }
 
 #[test]
 fn test_trunc() {
-    assert_approx_eq!(f32::math::trunc(1.0f32), 1.0f32);
-    assert_approx_eq!(f32::math::trunc(1.3f32), 1.0f32);
-    assert_approx_eq!(f32::math::trunc(1.5f32), 1.0f32);
-    assert_approx_eq!(f32::math::trunc(1.7f32), 1.0f32);
-    assert_approx_eq!(f32::math::trunc(0.0f32), 0.0f32);
-    assert_approx_eq!(f32::math::trunc(-0.0f32), -0.0f32);
-    assert_approx_eq!(f32::math::trunc(-1.0f32), -1.0f32);
-    assert_approx_eq!(f32::math::trunc(-1.3f32), -1.0f32);
-    assert_approx_eq!(f32::math::trunc(-1.5f32), -1.0f32);
-    assert_approx_eq!(f32::math::trunc(-1.7f32), -1.0f32);
+    assert_biteq!(f32::math::trunc(1.0f32), 1.0f32);
+    assert_biteq!(f32::math::trunc(1.3f32), 1.0f32);
+    assert_biteq!(f32::math::trunc(1.5f32), 1.0f32);
+    assert_biteq!(f32::math::trunc(1.7f32), 1.0f32);
+    assert_biteq!(f32::math::trunc(0.0f32), 0.0f32);
+    assert_biteq!(f32::math::trunc(-0.0f32), -0.0f32);
+    assert_biteq!(f32::math::trunc(-1.0f32), -1.0f32);
+    assert_biteq!(f32::math::trunc(-1.3f32), -1.0f32);
+    assert_biteq!(f32::math::trunc(-1.5f32), -1.0f32);
+    assert_biteq!(f32::math::trunc(-1.7f32), -1.0f32);
 }
 
 #[test]
 fn test_fract() {
-    assert_approx_eq!(f32::math::fract(1.0f32), 0.0f32);
-    assert_approx_eq!(f32::math::fract(1.3f32), 0.3f32);
-    assert_approx_eq!(f32::math::fract(1.5f32), 0.5f32);
-    assert_approx_eq!(f32::math::fract(1.7f32), 0.7f32);
-    assert_approx_eq!(f32::math::fract(0.0f32), 0.0f32);
-    assert_approx_eq!(f32::math::fract(-0.0f32), -0.0f32);
-    assert_approx_eq!(f32::math::fract(-1.0f32), -0.0f32);
-    assert_approx_eq!(f32::math::fract(-1.3f32), -0.3f32);
-    assert_approx_eq!(f32::math::fract(-1.5f32), -0.5f32);
-    assert_approx_eq!(f32::math::fract(-1.7f32), -0.7f32);
+    assert_biteq!(f32::math::fract(1.0f32), 0.0f32);
+    assert_biteq!(f32::math::fract(1.3f32), 0.29999995f32);
+    assert_biteq!(f32::math::fract(1.5f32), 0.5f32);
+    assert_biteq!(f32::math::fract(1.7f32), 0.70000005f32);
+    assert_biteq!(f32::math::fract(0.0f32), 0.0f32);
+    assert_biteq!(f32::math::fract(-0.0f32), 0.0f32);
+    assert_biteq!(f32::math::fract(-1.0f32), 0.0f32);
+    assert_biteq!(f32::math::fract(-1.3f32), -0.29999995f32);
+    assert_biteq!(f32::math::fract(-1.5f32), -0.5f32);
+    assert_biteq!(f32::math::fract(-1.7f32), -0.70000005f32);
 }
 
 #[test]
 fn test_abs() {
-    assert_eq!(f32::INFINITY.abs(), f32::INFINITY);
-    assert_eq!(1f32.abs(), 1f32);
-    assert_eq!(0f32.abs(), 0f32);
-    assert_eq!((-0f32).abs(), 0f32);
-    assert_eq!((-1f32).abs(), 1f32);
-    assert_eq!(f32::NEG_INFINITY.abs(), f32::INFINITY);
-    assert_eq!((1f32 / f32::NEG_INFINITY).abs(), 0f32);
+    assert_biteq!(f32::INFINITY.abs(), f32::INFINITY);
+    assert_biteq!(1f32.abs(), 1f32);
+    assert_biteq!(0f32.abs(), 0f32);
+    assert_biteq!((-0f32).abs(), 0f32);
+    assert_biteq!((-1f32).abs(), 1f32);
+    assert_biteq!(f32::NEG_INFINITY.abs(), f32::INFINITY);
+    assert_biteq!((1f32 / f32::NEG_INFINITY).abs(), 0f32);
     assert!(f32::NAN.abs().is_nan());
 }
 
 #[test]
 fn test_signum() {
-    assert_eq!(f32::INFINITY.signum(), 1f32);
-    assert_eq!(1f32.signum(), 1f32);
-    assert_eq!(0f32.signum(), 1f32);
-    assert_eq!((-0f32).signum(), -1f32);
-    assert_eq!((-1f32).signum(), -1f32);
-    assert_eq!(f32::NEG_INFINITY.signum(), -1f32);
-    assert_eq!((1f32 / f32::NEG_INFINITY).signum(), -1f32);
+    assert_biteq!(f32::INFINITY.signum(), 1f32);
+    assert_biteq!(1f32.signum(), 1f32);
+    assert_biteq!(0f32.signum(), 1f32);
+    assert_biteq!((-0f32).signum(), -1f32);
+    assert_biteq!((-1f32).signum(), -1f32);
+    assert_biteq!(f32::NEG_INFINITY.signum(), -1f32);
+    assert_biteq!((1f32 / f32::NEG_INFINITY).signum(), -1f32);
     assert!(f32::NAN.signum().is_nan());
 }
 
@@ -356,27 +346,27 @@ fn test_next_up() {
     let max_down = f32::from_bits(MAX_DOWN_BITS);
     let largest_subnormal = f32::from_bits(LARGEST_SUBNORMAL_BITS);
     let smallest_normal = f32::from_bits(SMALLEST_NORMAL_BITS);
-    assert_f32_biteq!(f32::NEG_INFINITY.next_up(), f32::MIN);
-    assert_f32_biteq!(f32::MIN.next_up(), -max_down);
-    assert_f32_biteq!((-1.0 - f32::EPSILON).next_up(), -1.0);
-    assert_f32_biteq!((-smallest_normal).next_up(), -largest_subnormal);
-    assert_f32_biteq!((-tiny_up).next_up(), -tiny);
-    assert_f32_biteq!((-tiny).next_up(), -0.0f32);
-    assert_f32_biteq!((-0.0f32).next_up(), tiny);
-    assert_f32_biteq!(0.0f32.next_up(), tiny);
-    assert_f32_biteq!(tiny.next_up(), tiny_up);
-    assert_f32_biteq!(largest_subnormal.next_up(), smallest_normal);
-    assert_f32_biteq!(1.0f32.next_up(), 1.0 + f32::EPSILON);
-    assert_f32_biteq!(f32::MAX.next_up(), f32::INFINITY);
-    assert_f32_biteq!(f32::INFINITY.next_up(), f32::INFINITY);
+    assert_biteq!(f32::NEG_INFINITY.next_up(), f32::MIN);
+    assert_biteq!(f32::MIN.next_up(), -max_down);
+    assert_biteq!((-1.0f32 - f32::EPSILON).next_up(), -1.0f32);
+    assert_biteq!((-smallest_normal).next_up(), -largest_subnormal);
+    assert_biteq!((-tiny_up).next_up(), -tiny);
+    assert_biteq!((-tiny).next_up(), -0.0f32);
+    assert_biteq!((-0.0f32).next_up(), tiny);
+    assert_biteq!(0.0f32.next_up(), tiny);
+    assert_biteq!(tiny.next_up(), tiny_up);
+    assert_biteq!(largest_subnormal.next_up(), smallest_normal);
+    assert_biteq!(1.0f32.next_up(), 1.0 + f32::EPSILON);
+    assert_biteq!(f32::MAX.next_up(), f32::INFINITY);
+    assert_biteq!(f32::INFINITY.next_up(), f32::INFINITY);
 
     // Check that NaNs roundtrip.
     let nan0 = f32::NAN;
     let nan1 = f32::from_bits(f32::NAN.to_bits() ^ NAN_MASK1);
     let nan2 = f32::from_bits(f32::NAN.to_bits() ^ NAN_MASK2);
-    assert_f32_biteq!(nan0.next_up(), nan0);
-    assert_f32_biteq!(nan1.next_up(), nan1);
-    assert_f32_biteq!(nan2.next_up(), nan2);
+    assert_biteq!(nan0.next_up(), nan0);
+    assert_biteq!(nan1.next_up(), nan1);
+    assert_biteq!(nan2.next_up(), nan2);
 }
 
 #[test]
@@ -386,28 +376,28 @@ fn test_next_down() {
     let max_down = f32::from_bits(MAX_DOWN_BITS);
     let largest_subnormal = f32::from_bits(LARGEST_SUBNORMAL_BITS);
     let smallest_normal = f32::from_bits(SMALLEST_NORMAL_BITS);
-    assert_f32_biteq!(f32::NEG_INFINITY.next_down(), f32::NEG_INFINITY);
-    assert_f32_biteq!(f32::MIN.next_down(), f32::NEG_INFINITY);
-    assert_f32_biteq!((-max_down).next_down(), f32::MIN);
-    assert_f32_biteq!((-1.0f32).next_down(), -1.0 - f32::EPSILON);
-    assert_f32_biteq!((-largest_subnormal).next_down(), -smallest_normal);
-    assert_f32_biteq!((-tiny).next_down(), -tiny_up);
-    assert_f32_biteq!((-0.0f32).next_down(), -tiny);
-    assert_f32_biteq!((0.0f32).next_down(), -tiny);
-    assert_f32_biteq!(tiny.next_down(), 0.0f32);
-    assert_f32_biteq!(tiny_up.next_down(), tiny);
-    assert_f32_biteq!(smallest_normal.next_down(), largest_subnormal);
-    assert_f32_biteq!((1.0 + f32::EPSILON).next_down(), 1.0f32);
-    assert_f32_biteq!(f32::MAX.next_down(), max_down);
-    assert_f32_biteq!(f32::INFINITY.next_down(), f32::MAX);
+    assert_biteq!(f32::NEG_INFINITY.next_down(), f32::NEG_INFINITY);
+    assert_biteq!(f32::MIN.next_down(), f32::NEG_INFINITY);
+    assert_biteq!((-max_down).next_down(), f32::MIN);
+    assert_biteq!((-1.0f32).next_down(), -1.0 - f32::EPSILON);
+    assert_biteq!((-largest_subnormal).next_down(), -smallest_normal);
+    assert_biteq!((-tiny).next_down(), -tiny_up);
+    assert_biteq!((-0.0f32).next_down(), -tiny);
+    assert_biteq!((0.0f32).next_down(), -tiny);
+    assert_biteq!(tiny.next_down(), 0.0f32);
+    assert_biteq!(tiny_up.next_down(), tiny);
+    assert_biteq!(smallest_normal.next_down(), largest_subnormal);
+    assert_biteq!((1.0 + f32::EPSILON).next_down(), 1.0f32);
+    assert_biteq!(f32::MAX.next_down(), max_down);
+    assert_biteq!(f32::INFINITY.next_down(), f32::MAX);
 
     // Check that NaNs roundtrip.
     let nan0 = f32::NAN;
     let nan1 = f32::from_bits(f32::NAN.to_bits() ^ NAN_MASK1);
     let nan2 = f32::from_bits(f32::NAN.to_bits() ^ NAN_MASK2);
-    assert_f32_biteq!(nan0.next_down(), nan0);
-    assert_f32_biteq!(nan1.next_down(), nan1);
-    assert_f32_biteq!(nan2.next_down(), nan2);
+    assert_biteq!(nan0.next_down(), nan0);
+    assert_biteq!(nan1.next_down(), nan1);
+    assert_biteq!(nan2.next_down(), nan2);
 }
 
 // FIXME(#140515): mingw has an incorrect fma https://sourceforge.net/p/mingw-w64/bugs/848/
@@ -417,15 +407,15 @@ fn test_mul_add() {
     let nan: f32 = f32::NAN;
     let inf: f32 = f32::INFINITY;
     let neg_inf: f32 = f32::NEG_INFINITY;
-    assert_approx_eq!(f32::math::mul_add(12.3f32, 4.5, 6.7), 62.05);
-    assert_approx_eq!(f32::math::mul_add(-12.3f32, -4.5, -6.7), 48.65);
-    assert_approx_eq!(f32::math::mul_add(0.0f32, 8.9, 1.2), 1.2);
-    assert_approx_eq!(f32::math::mul_add(3.4f32, -0.0, 5.6), 5.6);
+    assert_biteq!(f32::math::mul_add(12.3f32, 4.5, 6.7), 62.05);
+    assert_biteq!(f32::math::mul_add(-12.3f32, -4.5, -6.7), 48.65);
+    assert_biteq!(f32::math::mul_add(0.0f32, 8.9, 1.2), 1.2);
+    assert_biteq!(f32::math::mul_add(3.4f32, -0.0, 5.6), 5.6);
     assert!(f32::math::mul_add(nan, 7.8, 9.0).is_nan());
-    assert_eq!(f32::math::mul_add(inf, 7.8, 9.0), inf);
-    assert_eq!(f32::math::mul_add(neg_inf, 7.8, 9.0), neg_inf);
-    assert_eq!(f32::math::mul_add(8.9f32, inf, 3.2), inf);
-    assert_eq!(f32::math::mul_add(-3.2f32, 2.4, neg_inf), neg_inf);
+    assert_biteq!(f32::math::mul_add(inf, 7.8, 9.0), inf);
+    assert_biteq!(f32::math::mul_add(neg_inf, 7.8, 9.0), neg_inf);
+    assert_biteq!(f32::math::mul_add(8.9f32, inf, 3.2), inf);
+    assert_biteq!(f32::math::mul_add(-3.2f32, 2.4, neg_inf), neg_inf);
 }
 
 #[test]
@@ -433,13 +423,13 @@ fn test_recip() {
     let nan: f32 = f32::NAN;
     let inf: f32 = f32::INFINITY;
     let neg_inf: f32 = f32::NEG_INFINITY;
-    assert_eq!(1.0f32.recip(), 1.0);
-    assert_eq!(2.0f32.recip(), 0.5);
-    assert_eq!((-0.4f32).recip(), -2.5);
-    assert_eq!(0.0f32.recip(), inf);
+    assert_biteq!(1.0f32.recip(), 1.0);
+    assert_biteq!(2.0f32.recip(), 0.5);
+    assert_biteq!((-0.4f32).recip(), -2.5);
+    assert_biteq!(0.0f32.recip(), inf);
     assert!(nan.recip().is_nan());
-    assert_eq!(inf.recip(), 0.0);
-    assert_eq!(neg_inf.recip(), 0.0);
+    assert_biteq!(inf.recip(), 0.0);
+    assert_biteq!(neg_inf.recip(), -0.0);
 }
 
 #[test]
@@ -447,13 +437,13 @@ fn test_powi() {
     let nan: f32 = f32::NAN;
     let inf: f32 = f32::INFINITY;
     let neg_inf: f32 = f32::NEG_INFINITY;
-    assert_eq!(1.0f32.powi(1), 1.0);
+    assert_biteq!(1.0f32.powi(1), 1.0);
     assert_approx_eq!((-3.1f32).powi(2), 9.61);
     assert_approx_eq!(5.9f32.powi(-2), 0.028727);
-    assert_eq!(8.3f32.powi(0), 1.0);
+    assert_biteq!(8.3f32.powi(0), 1.0);
     assert!(nan.powi(2).is_nan());
-    assert_eq!(inf.powi(3), inf);
-    assert_eq!(neg_inf.powi(2), inf);
+    assert_biteq!(inf.powi(3), inf);
+    assert_biteq!(neg_inf.powi(2), inf);
 }
 
 #[test]
@@ -461,10 +451,10 @@ fn test_sqrt_domain() {
     assert!(f32::NAN.sqrt().is_nan());
     assert!(f32::NEG_INFINITY.sqrt().is_nan());
     assert!((-1.0f32).sqrt().is_nan());
-    assert_eq!((-0.0f32).sqrt(), -0.0);
-    assert_eq!(0.0f32.sqrt(), 0.0);
-    assert_eq!(1.0f32.sqrt(), 1.0);
-    assert_eq!(f32::INFINITY.sqrt(), f32::INFINITY);
+    assert_biteq!((-0.0f32).sqrt(), -0.0);
+    assert_biteq!(0.0f32.sqrt(), 0.0);
+    assert_biteq!(1.0f32.sqrt(), 1.0);
+    assert_biteq!(f32::INFINITY.sqrt(), f32::INFINITY);
 }
 
 #[test]
@@ -473,13 +463,13 @@ fn test_to_degrees() {
     let nan: f32 = f32::NAN;
     let inf: f32 = f32::INFINITY;
     let neg_inf: f32 = f32::NEG_INFINITY;
-    assert_eq!(0.0f32.to_degrees(), 0.0);
+    assert_biteq!(0.0f32.to_degrees(), 0.0);
     assert_approx_eq!((-5.8f32).to_degrees(), -332.315521);
-    assert_eq!(pi.to_degrees(), 180.0);
+    assert_biteq!(pi.to_degrees(), 180.0);
     assert!(nan.to_degrees().is_nan());
-    assert_eq!(inf.to_degrees(), inf);
-    assert_eq!(neg_inf.to_degrees(), neg_inf);
-    assert_eq!(1_f32.to_degrees(), 57.2957795130823208767981548141051703);
+    assert_biteq!(inf.to_degrees(), inf);
+    assert_biteq!(neg_inf.to_degrees(), neg_inf);
+    assert_biteq!(1_f32.to_degrees(), 57.2957795130823208767981548141051703);
 }
 
 #[test]
@@ -488,13 +478,13 @@ fn test_to_radians() {
     let nan: f32 = f32::NAN;
     let inf: f32 = f32::INFINITY;
     let neg_inf: f32 = f32::NEG_INFINITY;
-    assert_eq!(0.0f32.to_radians(), 0.0);
+    assert_biteq!(0.0f32.to_radians(), 0.0);
     assert_approx_eq!(154.6f32.to_radians(), 2.698279);
     assert_approx_eq!((-332.31f32).to_radians(), -5.799903);
-    assert_eq!(180.0f32.to_radians(), pi);
+    assert_biteq!(180.0f32.to_radians(), pi);
     assert!(nan.to_radians().is_nan());
-    assert_eq!(inf.to_radians(), inf);
-    assert_eq!(neg_inf.to_radians(), neg_inf);
+    assert_biteq!(inf.to_radians(), inf);
+    assert_biteq!(neg_inf.to_radians(), neg_inf);
 }
 
 #[test]
@@ -503,10 +493,10 @@ fn test_float_bits_conv() {
     assert_eq!((12.5f32).to_bits(), 0x41480000);
     assert_eq!((1337f32).to_bits(), 0x44a72000);
     assert_eq!((-14.25f32).to_bits(), 0xc1640000);
-    assert_approx_eq!(f32::from_bits(0x3f800000), 1.0);
-    assert_approx_eq!(f32::from_bits(0x41480000), 12.5);
-    assert_approx_eq!(f32::from_bits(0x44a72000), 1337.0);
-    assert_approx_eq!(f32::from_bits(0xc1640000), -14.25);
+    assert_biteq!(f32::from_bits(0x3f800000), 1.0);
+    assert_biteq!(f32::from_bits(0x41480000), 12.5);
+    assert_biteq!(f32::from_bits(0x44a72000), 1337.0);
+    assert_biteq!(f32::from_bits(0xc1640000), -14.25);
 
     // Check that NaNs roundtrip their bits regardless of signaling-ness
     // 0xA is 0b1010; 0x5 is 0b0101 -- so these two together clobbers all the mantissa bits
diff --git a/library/coretests/tests/floats/f64.rs b/library/coretests/tests/floats/f64.rs
index 97051998353..74202a37409 100644
--- a/library/coretests/tests/floats/f64.rs
+++ b/library/coretests/tests/floats/f64.rs
@@ -23,17 +23,6 @@ const NAN_MASK1: u64 = 0x000a_aaaa_aaaa_aaaa;
 /// Second pattern over the mantissa
 const NAN_MASK2: u64 = 0x0005_5555_5555_5555;
 
-#[allow(unused_macros)]
-macro_rules! assert_f64_biteq {
-    ($left : expr, $right : expr) => {
-        let l: &f64 = &$left;
-        let r: &f64 = &$right;
-        let lb = l.to_bits();
-        let rb = r.to_bits();
-        assert_eq!(lb, rb, "float {l} ({lb:#018x}) is not bitequal to {r} ({rb:#018x})");
-    };
-}
-
 #[test]
 fn test_num_f64() {
     super::test_num(10f64, 2f64);
@@ -41,14 +30,14 @@ fn test_num_f64() {
 
 #[test]
 fn test_min_nan() {
-    assert_eq!(f64::NAN.min(2.0), 2.0);
-    assert_eq!(2.0f64.min(f64::NAN), 2.0);
+    assert_biteq!(f64::NAN.min(2.0), 2.0);
+    assert_biteq!(2.0f64.min(f64::NAN), 2.0);
 }
 
 #[test]
 fn test_max_nan() {
-    assert_eq!(f64::NAN.max(2.0), 2.0);
-    assert_eq!(2.0f64.max(f64::NAN), 2.0);
+    assert_biteq!(f64::NAN.max(2.0), 2.0);
+    assert_biteq!(2.0f64.max(f64::NAN), 2.0);
 }
 
 #[test]
@@ -92,7 +81,7 @@ fn test_neg_infinity() {
 #[test]
 fn test_zero() {
     let zero: f64 = 0.0f64;
-    assert_eq!(0.0, zero);
+    assert_biteq!(0.0, zero);
     assert!(!zero.is_infinite());
     assert!(zero.is_finite());
     assert!(zero.is_sign_positive());
@@ -106,6 +95,7 @@ fn test_zero() {
 fn test_neg_zero() {
     let neg_zero: f64 = -0.0;
     assert_eq!(0.0, neg_zero);
+    assert_biteq!(-0.0, neg_zero);
     assert!(!neg_zero.is_infinite());
     assert!(neg_zero.is_finite());
     assert!(!neg_zero.is_sign_positive());
@@ -118,7 +108,7 @@ fn test_neg_zero() {
 #[test]
 fn test_one() {
     let one: f64 = 1.0f64;
-    assert_eq!(1.0, one);
+    assert_biteq!(1.0, one);
     assert!(!one.is_infinite());
     assert!(one.is_finite());
     assert!(one.is_sign_positive());
@@ -202,111 +192,111 @@ fn test_classify() {
 
 #[test]
 fn test_floor() {
-    assert_approx_eq!(f64::math::floor(1.0f64), 1.0f64);
-    assert_approx_eq!(f64::math::floor(1.3f64), 1.0f64);
-    assert_approx_eq!(f64::math::floor(1.5f64), 1.0f64);
-    assert_approx_eq!(f64::math::floor(1.7f64), 1.0f64);
-    assert_approx_eq!(f64::math::floor(0.0f64), 0.0f64);
-    assert_approx_eq!(f64::math::floor(-0.0f64), -0.0f64);
-    assert_approx_eq!(f64::math::floor(-1.0f64), -1.0f64);
-    assert_approx_eq!(f64::math::floor(-1.3f64), -2.0f64);
-    assert_approx_eq!(f64::math::floor(-1.5f64), -2.0f64);
-    assert_approx_eq!(f64::math::floor(-1.7f64), -2.0f64);
+    assert_biteq!(f64::math::floor(1.0f64), 1.0f64);
+    assert_biteq!(f64::math::floor(1.3f64), 1.0f64);
+    assert_biteq!(f64::math::floor(1.5f64), 1.0f64);
+    assert_biteq!(f64::math::floor(1.7f64), 1.0f64);
+    assert_biteq!(f64::math::floor(0.0f64), 0.0f64);
+    assert_biteq!(f64::math::floor(-0.0f64), -0.0f64);
+    assert_biteq!(f64::math::floor(-1.0f64), -1.0f64);
+    assert_biteq!(f64::math::floor(-1.3f64), -2.0f64);
+    assert_biteq!(f64::math::floor(-1.5f64), -2.0f64);
+    assert_biteq!(f64::math::floor(-1.7f64), -2.0f64);
 }
 
 #[test]
 fn test_ceil() {
-    assert_approx_eq!(f64::math::ceil(1.0f64), 1.0f64);
-    assert_approx_eq!(f64::math::ceil(1.3f64), 2.0f64);
-    assert_approx_eq!(f64::math::ceil(1.5f64), 2.0f64);
-    assert_approx_eq!(f64::math::ceil(1.7f64), 2.0f64);
-    assert_approx_eq!(f64::math::ceil(0.0f64), 0.0f64);
-    assert_approx_eq!(f64::math::ceil(-0.0f64), -0.0f64);
-    assert_approx_eq!(f64::math::ceil(-1.0f64), -1.0f64);
-    assert_approx_eq!(f64::math::ceil(-1.3f64), -1.0f64);
-    assert_approx_eq!(f64::math::ceil(-1.5f64), -1.0f64);
-    assert_approx_eq!(f64::math::ceil(-1.7f64), -1.0f64);
+    assert_biteq!(f64::math::ceil(1.0f64), 1.0f64);
+    assert_biteq!(f64::math::ceil(1.3f64), 2.0f64);
+    assert_biteq!(f64::math::ceil(1.5f64), 2.0f64);
+    assert_biteq!(f64::math::ceil(1.7f64), 2.0f64);
+    assert_biteq!(f64::math::ceil(0.0f64), 0.0f64);
+    assert_biteq!(f64::math::ceil(-0.0f64), -0.0f64);
+    assert_biteq!(f64::math::ceil(-1.0f64), -1.0f64);
+    assert_biteq!(f64::math::ceil(-1.3f64), -1.0f64);
+    assert_biteq!(f64::math::ceil(-1.5f64), -1.0f64);
+    assert_biteq!(f64::math::ceil(-1.7f64), -1.0f64);
 }
 
 #[test]
 fn test_round() {
-    assert_approx_eq!(f64::math::round(2.5f64), 3.0f64);
-    assert_approx_eq!(f64::math::round(1.0f64), 1.0f64);
-    assert_approx_eq!(f64::math::round(1.3f64), 1.0f64);
-    assert_approx_eq!(f64::math::round(1.5f64), 2.0f64);
-    assert_approx_eq!(f64::math::round(1.7f64), 2.0f64);
-    assert_approx_eq!(f64::math::round(0.0f64), 0.0f64);
-    assert_approx_eq!(f64::math::round(-0.0f64), -0.0f64);
-    assert_approx_eq!(f64::math::round(-1.0f64), -1.0f64);
-    assert_approx_eq!(f64::math::round(-1.3f64), -1.0f64);
-    assert_approx_eq!(f64::math::round(-1.5f64), -2.0f64);
-    assert_approx_eq!(f64::math::round(-1.7f64), -2.0f64);
+    assert_biteq!(f64::math::round(2.5f64), 3.0f64);
+    assert_biteq!(f64::math::round(1.0f64), 1.0f64);
+    assert_biteq!(f64::math::round(1.3f64), 1.0f64);
+    assert_biteq!(f64::math::round(1.5f64), 2.0f64);
+    assert_biteq!(f64::math::round(1.7f64), 2.0f64);
+    assert_biteq!(f64::math::round(0.0f64), 0.0f64);
+    assert_biteq!(f64::math::round(-0.0f64), -0.0f64);
+    assert_biteq!(f64::math::round(-1.0f64), -1.0f64);
+    assert_biteq!(f64::math::round(-1.3f64), -1.0f64);
+    assert_biteq!(f64::math::round(-1.5f64), -2.0f64);
+    assert_biteq!(f64::math::round(-1.7f64), -2.0f64);
 }
 
 #[test]
 fn test_round_ties_even() {
-    assert_approx_eq!(f64::math::round_ties_even(2.5f64), 2.0f64);
-    assert_approx_eq!(f64::math::round_ties_even(1.0f64), 1.0f64);
-    assert_approx_eq!(f64::math::round_ties_even(1.3f64), 1.0f64);
-    assert_approx_eq!(f64::math::round_ties_even(1.5f64), 2.0f64);
-    assert_approx_eq!(f64::math::round_ties_even(1.7f64), 2.0f64);
-    assert_approx_eq!(f64::math::round_ties_even(0.0f64), 0.0f64);
-    assert_approx_eq!(f64::math::round_ties_even(-0.0f64), -0.0f64);
-    assert_approx_eq!(f64::math::round_ties_even(-1.0f64), -1.0f64);
-    assert_approx_eq!(f64::math::round_ties_even(-1.3f64), -1.0f64);
-    assert_approx_eq!(f64::math::round_ties_even(-1.5f64), -2.0f64);
-    assert_approx_eq!(f64::math::round_ties_even(-1.7f64), -2.0f64);
+    assert_biteq!(f64::math::round_ties_even(2.5f64), 2.0f64);
+    assert_biteq!(f64::math::round_ties_even(1.0f64), 1.0f64);
+    assert_biteq!(f64::math::round_ties_even(1.3f64), 1.0f64);
+    assert_biteq!(f64::math::round_ties_even(1.5f64), 2.0f64);
+    assert_biteq!(f64::math::round_ties_even(1.7f64), 2.0f64);
+    assert_biteq!(f64::math::round_ties_even(0.0f64), 0.0f64);
+    assert_biteq!(f64::math::round_ties_even(-0.0f64), -0.0f64);
+    assert_biteq!(f64::math::round_ties_even(-1.0f64), -1.0f64);
+    assert_biteq!(f64::math::round_ties_even(-1.3f64), -1.0f64);
+    assert_biteq!(f64::math::round_ties_even(-1.5f64), -2.0f64);
+    assert_biteq!(f64::math::round_ties_even(-1.7f64), -2.0f64);
 }
 
 #[test]
 fn test_trunc() {
-    assert_approx_eq!(f64::math::trunc(1.0f64), 1.0f64);
-    assert_approx_eq!(f64::math::trunc(1.3f64), 1.0f64);
-    assert_approx_eq!(f64::math::trunc(1.5f64), 1.0f64);
-    assert_approx_eq!(f64::math::trunc(1.7f64), 1.0f64);
-    assert_approx_eq!(f64::math::trunc(0.0f64), 0.0f64);
-    assert_approx_eq!(f64::math::trunc(-0.0f64), -0.0f64);
-    assert_approx_eq!(f64::math::trunc(-1.0f64), -1.0f64);
-    assert_approx_eq!(f64::math::trunc(-1.3f64), -1.0f64);
-    assert_approx_eq!(f64::math::trunc(-1.5f64), -1.0f64);
-    assert_approx_eq!(f64::math::trunc(-1.7f64), -1.0f64);
+    assert_biteq!(f64::math::trunc(1.0f64), 1.0f64);
+    assert_biteq!(f64::math::trunc(1.3f64), 1.0f64);
+    assert_biteq!(f64::math::trunc(1.5f64), 1.0f64);
+    assert_biteq!(f64::math::trunc(1.7f64), 1.0f64);
+    assert_biteq!(f64::math::trunc(0.0f64), 0.0f64);
+    assert_biteq!(f64::math::trunc(-0.0f64), -0.0f64);
+    assert_biteq!(f64::math::trunc(-1.0f64), -1.0f64);
+    assert_biteq!(f64::math::trunc(-1.3f64), -1.0f64);
+    assert_biteq!(f64::math::trunc(-1.5f64), -1.0f64);
+    assert_biteq!(f64::math::trunc(-1.7f64), -1.0f64);
 }
 
 #[test]
 fn test_fract() {
-    assert_approx_eq!(f64::math::fract(1.0f64), 0.0f64);
-    assert_approx_eq!(f64::math::fract(1.3f64), 0.3f64);
-    assert_approx_eq!(f64::math::fract(1.5f64), 0.5f64);
-    assert_approx_eq!(f64::math::fract(1.7f64), 0.7f64);
-    assert_approx_eq!(f64::math::fract(0.0f64), 0.0f64);
-    assert_approx_eq!(f64::math::fract(-0.0f64), -0.0f64);
-    assert_approx_eq!(f64::math::fract(-1.0f64), -0.0f64);
-    assert_approx_eq!(f64::math::fract(-1.3f64), -0.3f64);
-    assert_approx_eq!(f64::math::fract(-1.5f64), -0.5f64);
-    assert_approx_eq!(f64::math::fract(-1.7f64), -0.7f64);
+    assert_biteq!(f64::math::fract(1.0f64), 0.0f64);
+    assert_biteq!(f64::math::fract(1.3f64), 0.30000000000000004f64);
+    assert_biteq!(f64::math::fract(1.5f64), 0.5f64);
+    assert_biteq!(f64::math::fract(1.7f64), 0.7f64);
+    assert_biteq!(f64::math::fract(0.0f64), 0.0f64);
+    assert_biteq!(f64::math::fract(-0.0f64), 0.0f64);
+    assert_biteq!(f64::math::fract(-1.0f64), 0.0f64);
+    assert_biteq!(f64::math::fract(-1.3f64), -0.30000000000000004f64);
+    assert_biteq!(f64::math::fract(-1.5f64), -0.5f64);
+    assert_biteq!(f64::math::fract(-1.7f64), -0.69999999999999996f64);
 }
 
 #[test]
 fn test_abs() {
-    assert_eq!(f64::INFINITY.abs(), f64::INFINITY);
-    assert_eq!(1f64.abs(), 1f64);
-    assert_eq!(0f64.abs(), 0f64);
-    assert_eq!((-0f64).abs(), 0f64);
-    assert_eq!((-1f64).abs(), 1f64);
-    assert_eq!(f64::NEG_INFINITY.abs(), f64::INFINITY);
-    assert_eq!((1f64 / f64::NEG_INFINITY).abs(), 0f64);
+    assert_biteq!(f64::INFINITY.abs(), f64::INFINITY);
+    assert_biteq!(1f64.abs(), 1f64);
+    assert_biteq!(0f64.abs(), 0f64);
+    assert_biteq!((-0f64).abs(), 0f64);
+    assert_biteq!((-1f64).abs(), 1f64);
+    assert_biteq!(f64::NEG_INFINITY.abs(), f64::INFINITY);
+    assert_biteq!((1f64 / f64::NEG_INFINITY).abs(), 0f64);
     assert!(f64::NAN.abs().is_nan());
 }
 
 #[test]
 fn test_signum() {
-    assert_eq!(f64::INFINITY.signum(), 1f64);
-    assert_eq!(1f64.signum(), 1f64);
-    assert_eq!(0f64.signum(), 1f64);
-    assert_eq!((-0f64).signum(), -1f64);
-    assert_eq!((-1f64).signum(), -1f64);
-    assert_eq!(f64::NEG_INFINITY.signum(), -1f64);
-    assert_eq!((1f64 / f64::NEG_INFINITY).signum(), -1f64);
+    assert_biteq!(f64::INFINITY.signum(), 1f64);
+    assert_biteq!(1f64.signum(), 1f64);
+    assert_biteq!(0f64.signum(), 1f64);
+    assert_biteq!((-0f64).signum(), -1f64);
+    assert_biteq!((-1f64).signum(), -1f64);
+    assert_biteq!(f64::NEG_INFINITY.signum(), -1f64);
+    assert_biteq!((1f64 / f64::NEG_INFINITY).signum(), -1f64);
     assert!(f64::NAN.signum().is_nan());
 }
 
@@ -343,26 +333,26 @@ fn test_next_up() {
     let max_down = f64::from_bits(MAX_DOWN_BITS);
     let largest_subnormal = f64::from_bits(LARGEST_SUBNORMAL_BITS);
     let smallest_normal = f64::from_bits(SMALLEST_NORMAL_BITS);
-    assert_f64_biteq!(f64::NEG_INFINITY.next_up(), f64::MIN);
-    assert_f64_biteq!(f64::MIN.next_up(), -max_down);
-    assert_f64_biteq!((-1.0 - f64::EPSILON).next_up(), -1.0);
-    assert_f64_biteq!((-smallest_normal).next_up(), -largest_subnormal);
-    assert_f64_biteq!((-tiny_up).next_up(), -tiny);
-    assert_f64_biteq!((-tiny).next_up(), -0.0f64);
-    assert_f64_biteq!((-0.0f64).next_up(), tiny);
-    assert_f64_biteq!(0.0f64.next_up(), tiny);
-    assert_f64_biteq!(tiny.next_up(), tiny_up);
-    assert_f64_biteq!(largest_subnormal.next_up(), smallest_normal);
-    assert_f64_biteq!(1.0f64.next_up(), 1.0 + f64::EPSILON);
-    assert_f64_biteq!(f64::MAX.next_up(), f64::INFINITY);
-    assert_f64_biteq!(f64::INFINITY.next_up(), f64::INFINITY);
+    assert_biteq!(f64::NEG_INFINITY.next_up(), f64::MIN);
+    assert_biteq!(f64::MIN.next_up(), -max_down);
+    assert_biteq!((-1.0 - f64::EPSILON).next_up(), -1.0f64);
+    assert_biteq!((-smallest_normal).next_up(), -largest_subnormal);
+    assert_biteq!((-tiny_up).next_up(), -tiny);
+    assert_biteq!((-tiny).next_up(), -0.0f64);
+    assert_biteq!((-0.0f64).next_up(), tiny);
+    assert_biteq!(0.0f64.next_up(), tiny);
+    assert_biteq!(tiny.next_up(), tiny_up);
+    assert_biteq!(largest_subnormal.next_up(), smallest_normal);
+    assert_biteq!(1.0f64.next_up(), 1.0 + f64::EPSILON);
+    assert_biteq!(f64::MAX.next_up(), f64::INFINITY);
+    assert_biteq!(f64::INFINITY.next_up(), f64::INFINITY);
 
     let nan0 = f64::NAN;
     let nan1 = f64::from_bits(f64::NAN.to_bits() ^ NAN_MASK1);
     let nan2 = f64::from_bits(f64::NAN.to_bits() ^ NAN_MASK2);
-    assert_f64_biteq!(nan0.next_up(), nan0);
-    assert_f64_biteq!(nan1.next_up(), nan1);
-    assert_f64_biteq!(nan2.next_up(), nan2);
+    assert_biteq!(nan0.next_up(), nan0);
+    assert_biteq!(nan1.next_up(), nan1);
+    assert_biteq!(nan2.next_up(), nan2);
 }
 
 #[test]
@@ -372,27 +362,27 @@ fn test_next_down() {
     let max_down = f64::from_bits(MAX_DOWN_BITS);
     let largest_subnormal = f64::from_bits(LARGEST_SUBNORMAL_BITS);
     let smallest_normal = f64::from_bits(SMALLEST_NORMAL_BITS);
-    assert_f64_biteq!(f64::NEG_INFINITY.next_down(), f64::NEG_INFINITY);
-    assert_f64_biteq!(f64::MIN.next_down(), f64::NEG_INFINITY);
-    assert_f64_biteq!((-max_down).next_down(), f64::MIN);
-    assert_f64_biteq!((-1.0f64).next_down(), -1.0 - f64::EPSILON);
-    assert_f64_biteq!((-largest_subnormal).next_down(), -smallest_normal);
-    assert_f64_biteq!((-tiny).next_down(), -tiny_up);
-    assert_f64_biteq!((-0.0f64).next_down(), -tiny);
-    assert_f64_biteq!((0.0f64).next_down(), -tiny);
-    assert_f64_biteq!(tiny.next_down(), 0.0f64);
-    assert_f64_biteq!(tiny_up.next_down(), tiny);
-    assert_f64_biteq!(smallest_normal.next_down(), largest_subnormal);
-    assert_f64_biteq!((1.0 + f64::EPSILON).next_down(), 1.0f64);
-    assert_f64_biteq!(f64::MAX.next_down(), max_down);
-    assert_f64_biteq!(f64::INFINITY.next_down(), f64::MAX);
+    assert_biteq!(f64::NEG_INFINITY.next_down(), f64::NEG_INFINITY);
+    assert_biteq!(f64::MIN.next_down(), f64::NEG_INFINITY);
+    assert_biteq!((-max_down).next_down(), f64::MIN);
+    assert_biteq!((-1.0f64).next_down(), -1.0 - f64::EPSILON);
+    assert_biteq!((-largest_subnormal).next_down(), -smallest_normal);
+    assert_biteq!((-tiny).next_down(), -tiny_up);
+    assert_biteq!((-0.0f64).next_down(), -tiny);
+    assert_biteq!((0.0f64).next_down(), -tiny);
+    assert_biteq!(tiny.next_down(), 0.0f64);
+    assert_biteq!(tiny_up.next_down(), tiny);
+    assert_biteq!(smallest_normal.next_down(), largest_subnormal);
+    assert_biteq!((1.0 + f64::EPSILON).next_down(), 1.0f64);
+    assert_biteq!(f64::MAX.next_down(), max_down);
+    assert_biteq!(f64::INFINITY.next_down(), f64::MAX);
 
     let nan0 = f64::NAN;
     let nan1 = f64::from_bits(f64::NAN.to_bits() ^ NAN_MASK1);
     let nan2 = f64::from_bits(f64::NAN.to_bits() ^ NAN_MASK2);
-    assert_f64_biteq!(nan0.next_down(), nan0);
-    assert_f64_biteq!(nan1.next_down(), nan1);
-    assert_f64_biteq!(nan2.next_down(), nan2);
+    assert_biteq!(nan0.next_down(), nan0);
+    assert_biteq!(nan1.next_down(), nan1);
+    assert_biteq!(nan2.next_down(), nan2);
 }
 
 // FIXME(#140515): mingw has an incorrect fma https://sourceforge.net/p/mingw-w64/bugs/848/
@@ -402,15 +392,15 @@ fn test_mul_add() {
     let nan: f64 = f64::NAN;
     let inf: f64 = f64::INFINITY;
     let neg_inf: f64 = f64::NEG_INFINITY;
-    assert_approx_eq!(12.3f64.mul_add(4.5, 6.7), 62.05);
-    assert_approx_eq!((-12.3f64).mul_add(-4.5, -6.7), 48.65);
-    assert_approx_eq!(0.0f64.mul_add(8.9, 1.2), 1.2);
-    assert_approx_eq!(3.4f64.mul_add(-0.0, 5.6), 5.6);
+    assert_biteq!(12.3f64.mul_add(4.5, 6.7), 62.050000000000004);
+    assert_biteq!((-12.3f64).mul_add(-4.5, -6.7), 48.650000000000006);
+    assert_biteq!(0.0f64.mul_add(8.9, 1.2), 1.2);
+    assert_biteq!(3.4f64.mul_add(-0.0, 5.6), 5.6);
     assert!(nan.mul_add(7.8, 9.0).is_nan());
-    assert_eq!(inf.mul_add(7.8, 9.0), inf);
-    assert_eq!(neg_inf.mul_add(7.8, 9.0), neg_inf);
-    assert_eq!(8.9f64.mul_add(inf, 3.2), inf);
-    assert_eq!((-3.2f64).mul_add(2.4, neg_inf), neg_inf);
+    assert_biteq!(inf.mul_add(7.8, 9.0), inf);
+    assert_biteq!(neg_inf.mul_add(7.8, 9.0), neg_inf);
+    assert_biteq!(8.9f64.mul_add(inf, 3.2), inf);
+    assert_biteq!((-3.2f64).mul_add(2.4, neg_inf), neg_inf);
 }
 
 #[test]
@@ -418,13 +408,13 @@ fn test_recip() {
     let nan: f64 = f64::NAN;
     let inf: f64 = f64::INFINITY;
     let neg_inf: f64 = f64::NEG_INFINITY;
-    assert_eq!(1.0f64.recip(), 1.0);
-    assert_eq!(2.0f64.recip(), 0.5);
-    assert_eq!((-0.4f64).recip(), -2.5);
-    assert_eq!(0.0f64.recip(), inf);
+    assert_biteq!(1.0f64.recip(), 1.0);
+    assert_biteq!(2.0f64.recip(), 0.5);
+    assert_biteq!((-0.4f64).recip(), -2.5);
+    assert_biteq!(0.0f64.recip(), inf);
     assert!(nan.recip().is_nan());
-    assert_eq!(inf.recip(), 0.0);
-    assert_eq!(neg_inf.recip(), 0.0);
+    assert_biteq!(inf.recip(), 0.0);
+    assert_biteq!(neg_inf.recip(), -0.0);
 }
 
 #[test]
@@ -432,13 +422,13 @@ fn test_powi() {
     let nan: f64 = f64::NAN;
     let inf: f64 = f64::INFINITY;
     let neg_inf: f64 = f64::NEG_INFINITY;
-    assert_eq!(1.0f64.powi(1), 1.0);
+    assert_biteq!(1.0f64.powi(1), 1.0);
     assert_approx_eq!((-3.1f64).powi(2), 9.61);
     assert_approx_eq!(5.9f64.powi(-2), 0.028727);
-    assert_eq!(8.3f64.powi(0), 1.0);
+    assert_biteq!(8.3f64.powi(0), 1.0);
     assert!(nan.powi(2).is_nan());
-    assert_eq!(inf.powi(3), inf);
-    assert_eq!(neg_inf.powi(2), inf);
+    assert_biteq!(inf.powi(3), inf);
+    assert_biteq!(neg_inf.powi(2), inf);
 }
 
 #[test]
@@ -446,10 +436,10 @@ fn test_sqrt_domain() {
     assert!(f64::NAN.sqrt().is_nan());
     assert!(f64::NEG_INFINITY.sqrt().is_nan());
     assert!((-1.0f64).sqrt().is_nan());
-    assert_eq!((-0.0f64).sqrt(), -0.0);
-    assert_eq!(0.0f64.sqrt(), 0.0);
-    assert_eq!(1.0f64.sqrt(), 1.0);
-    assert_eq!(f64::INFINITY.sqrt(), f64::INFINITY);
+    assert_biteq!((-0.0f64).sqrt(), -0.0);
+    assert_biteq!(0.0f64.sqrt(), 0.0);
+    assert_biteq!(1.0f64.sqrt(), 1.0);
+    assert_biteq!(f64::INFINITY.sqrt(), f64::INFINITY);
 }
 
 #[test]
@@ -458,12 +448,12 @@ fn test_to_degrees() {
     let nan: f64 = f64::NAN;
     let inf: f64 = f64::INFINITY;
     let neg_inf: f64 = f64::NEG_INFINITY;
-    assert_eq!(0.0f64.to_degrees(), 0.0);
+    assert_biteq!(0.0f64.to_degrees(), 0.0);
     assert_approx_eq!((-5.8f64).to_degrees(), -332.315521);
-    assert_eq!(pi.to_degrees(), 180.0);
+    assert_biteq!(pi.to_degrees(), 180.0);
     assert!(nan.to_degrees().is_nan());
-    assert_eq!(inf.to_degrees(), inf);
-    assert_eq!(neg_inf.to_degrees(), neg_inf);
+    assert_biteq!(inf.to_degrees(), inf);
+    assert_biteq!(neg_inf.to_degrees(), neg_inf);
 }
 
 #[test]
@@ -472,13 +462,13 @@ fn test_to_radians() {
     let nan: f64 = f64::NAN;
     let inf: f64 = f64::INFINITY;
     let neg_inf: f64 = f64::NEG_INFINITY;
-    assert_eq!(0.0f64.to_radians(), 0.0);
+    assert_biteq!(0.0f64.to_radians(), 0.0);
     assert_approx_eq!(154.6f64.to_radians(), 2.698279);
     assert_approx_eq!((-332.31f64).to_radians(), -5.799903);
-    assert_eq!(180.0f64.to_radians(), pi);
+    assert_biteq!(180.0f64.to_radians(), pi);
     assert!(nan.to_radians().is_nan());
-    assert_eq!(inf.to_radians(), inf);
-    assert_eq!(neg_inf.to_radians(), neg_inf);
+    assert_biteq!(inf.to_radians(), inf);
+    assert_biteq!(neg_inf.to_radians(), neg_inf);
 }
 
 #[test]
@@ -487,10 +477,10 @@ fn test_float_bits_conv() {
     assert_eq!((12.5f64).to_bits(), 0x4029000000000000);
     assert_eq!((1337f64).to_bits(), 0x4094e40000000000);
     assert_eq!((-14.25f64).to_bits(), 0xc02c800000000000);
-    assert_approx_eq!(f64::from_bits(0x3ff0000000000000), 1.0);
-    assert_approx_eq!(f64::from_bits(0x4029000000000000), 12.5);
-    assert_approx_eq!(f64::from_bits(0x4094e40000000000), 1337.0);
-    assert_approx_eq!(f64::from_bits(0xc02c800000000000), -14.25);
+    assert_biteq!(f64::from_bits(0x3ff0000000000000), 1.0);
+    assert_biteq!(f64::from_bits(0x4029000000000000), 12.5);
+    assert_biteq!(f64::from_bits(0x4094e40000000000), 1337.0);
+    assert_biteq!(f64::from_bits(0xc02c800000000000), -14.25);
 
     // Check that NaNs roundtrip their bits regardless of signaling-ness
     let masked_nan1 = f64::NAN.to_bits() ^ NAN_MASK1;
diff --git a/library/coretests/tests/floats/mod.rs b/library/coretests/tests/floats/mod.rs
index 7de34271ad0..7e27028a2a2 100644
--- a/library/coretests/tests/floats/mod.rs
+++ b/library/coretests/tests/floats/mod.rs
@@ -15,6 +15,43 @@ macro_rules! assert_approx_eq {
     }};
 }
 
+/// Verify that floats have the same bitwise representation. Used to avoid the default `0.0 == -0.0`
+/// behavior, as well as to ensure exact NaN bitpatterns.
+macro_rules! assert_biteq {
+    (@inner $left:expr, $right:expr, $msg_sep:literal, $($tt:tt)*) => {{
+        let l = $left;
+        let r = $right;
+
+        // Hack to coerce left and right to the same type
+        let mut _eq_ty = l;
+        _eq_ty = r;
+
+        // Hack to get the width from a value
+        let bits = (l.to_bits() - l.to_bits()).leading_zeros();
+        assert!(
+            l.to_bits() == r.to_bits(),
+            "{msg}{nl}l: {l:?} ({lb:#0width$x})\nr: {r:?} ({rb:#0width$x})",
+            msg = format_args!($($tt)*),
+            nl = $msg_sep,
+            lb = l.to_bits(),
+            rb = r.to_bits(),
+            width = ((bits / 4) + 2) as usize,
+        );
+
+        if !l.is_nan() && !r.is_nan() {
+            // Also check that standard equality holds, since most tests use `assert_biteq` rather
+            // than `assert_eq`.
+            assert_eq!(l, r)
+        }
+    }};
+    ($left:expr, $right:expr , $($tt:tt)*) => {
+        assert_biteq!(@inner $left, $right, "\n", $($tt)*)
+    };
+    ($left:expr, $right:expr $(,)?) => {
+        assert_biteq!(@inner $left, $right, "", "")
+    };
+}
+
 /// Helper function for testing numeric operations
 pub fn test_num<T>(ten: T, two: T)
 where
diff --git a/library/coretests/tests/lib.rs b/library/coretests/tests/lib.rs
index b1301200981..dd7cdd79c0d 100644
--- a/library/coretests/tests/lib.rs
+++ b/library/coretests/tests/lib.rs
@@ -16,6 +16,7 @@
 #![feature(char_max_len)]
 #![feature(clone_to_uninit)]
 #![feature(const_eval_select)]
+#![feature(const_float_round_methods)]
 #![feature(const_trait_impl)]
 #![feature(core_float_math)]
 #![feature(core_intrinsics)]
@@ -23,6 +24,7 @@
 #![feature(core_io_borrowed_buf)]
 #![feature(core_private_bignum)]
 #![feature(core_private_diy_float)]
+#![feature(cstr_display)]
 #![feature(dec2flt)]
 #![feature(duration_constants)]
 #![feature(duration_constructors)]
diff --git a/library/coretests/tests/num/mod.rs b/library/coretests/tests/num/mod.rs
index a6b75f70266..fa05bbdd9b7 100644
--- a/library/coretests/tests/num/mod.rs
+++ b/library/coretests/tests/num/mod.rs
@@ -731,8 +731,11 @@ assume_usize_width! {
     }
 }
 
+// FIXME(141726): there is a lot of duplication between the following tests and
+// the tests in `coretests/tests/floats/f*.rs`
+// See issue https://github.com/rust-lang/rust/issues/141726 for more details.
 macro_rules! test_float {
-    ($modname: ident, $fassert: ident, $fty: ty, $inf: expr, $neginf: expr, $nan: expr, $min: expr, $max: expr, $min_pos: expr, $max_exp:expr) => {
+    ($modname: ident, $fassert: ident, $fty: ty) => {
         mod $modname {
             #[test]
             fn min() {
@@ -747,19 +750,19 @@ macro_rules! test_float {
                 $fassert!((-0.0 as $fty).min(9.0), -0.0);
                 $fassert!((-0.0 as $fty).min(9.0).is_sign_negative());
                 $fassert!((-0.0 as $fty).min(-9.0), -9.0);
-                $fassert!(($inf as $fty).min(9.0), 9.0);
-                $fassert!((9.0 as $fty).min($inf), 9.0);
-                $fassert!(($inf as $fty).min(-9.0), -9.0);
-                $fassert!((-9.0 as $fty).min($inf), -9.0);
-                $fassert!(($neginf as $fty).min(9.0), $neginf);
-                $fassert!((9.0 as $fty).min($neginf), $neginf);
-                $fassert!(($neginf as $fty).min(-9.0), $neginf);
-                $fassert!((-9.0 as $fty).min($neginf), $neginf);
-                $fassert!(($nan as $fty).min(9.0), 9.0);
-                $fassert!(($nan as $fty).min(-9.0), -9.0);
-                $fassert!((9.0 as $fty).min($nan), 9.0);
-                $fassert!((-9.0 as $fty).min($nan), -9.0);
-                $fassert!(($nan as $fty).min($nan).is_nan());
+                $fassert!(<$fty>::INFINITY.min(9.0), 9.0);
+                $fassert!((9.0 as $fty).min(<$fty>::INFINITY), 9.0);
+                $fassert!(<$fty>::INFINITY.min(-9.0), -9.0);
+                $fassert!((-9.0 as $fty).min(<$fty>::INFINITY), -9.0);
+                $fassert!(<$fty>::NEG_INFINITY.min(9.0), <$fty>::NEG_INFINITY);
+                $fassert!((9.0 as $fty).min(<$fty>::NEG_INFINITY), <$fty>::NEG_INFINITY);
+                $fassert!(<$fty>::NEG_INFINITY.min(-9.0), <$fty>::NEG_INFINITY);
+                $fassert!((-9.0 as $fty).min(<$fty>::NEG_INFINITY), <$fty>::NEG_INFINITY);
+                $fassert!(<$fty>::NAN.min(9.0), 9.0);
+                $fassert!(<$fty>::NAN.min(-9.0), -9.0);
+                $fassert!((9.0 as $fty).min(<$fty>::NAN), 9.0);
+                $fassert!((-9.0 as $fty).min(<$fty>::NAN), -9.0);
+                $fassert!(<$fty>::NAN.min(<$fty>::NAN).is_nan());
             }
             #[test]
             fn max() {
@@ -777,19 +780,19 @@ macro_rules! test_float {
                 $fassert!((0.0 as $fty).max(-9.0).is_sign_positive());
                 $fassert!((-0.0 as $fty).max(-9.0), -0.0);
                 $fassert!((-0.0 as $fty).max(-9.0).is_sign_negative());
-                $fassert!(($inf as $fty).max(9.0), $inf);
-                $fassert!((9.0 as $fty).max($inf), $inf);
-                $fassert!(($inf as $fty).max(-9.0), $inf);
-                $fassert!((-9.0 as $fty).max($inf), $inf);
-                $fassert!(($neginf as $fty).max(9.0), 9.0);
-                $fassert!((9.0 as $fty).max($neginf), 9.0);
-                $fassert!(($neginf as $fty).max(-9.0), -9.0);
-                $fassert!((-9.0 as $fty).max($neginf), -9.0);
-                $fassert!(($nan as $fty).max(9.0), 9.0);
-                $fassert!(($nan as $fty).max(-9.0), -9.0);
-                $fassert!((9.0 as $fty).max($nan), 9.0);
-                $fassert!((-9.0 as $fty).max($nan), -9.0);
-                $fassert!(($nan as $fty).max($nan).is_nan());
+                $fassert!(<$fty>::INFINITY.max(9.0), <$fty>::INFINITY);
+                $fassert!((9.0 as $fty).max(<$fty>::INFINITY), <$fty>::INFINITY);
+                $fassert!(<$fty>::INFINITY.max(-9.0), <$fty>::INFINITY);
+                $fassert!((-9.0 as $fty).max(<$fty>::INFINITY), <$fty>::INFINITY);
+                $fassert!(<$fty>::NEG_INFINITY.max(9.0), 9.0);
+                $fassert!((9.0 as $fty).max(<$fty>::NEG_INFINITY), 9.0);
+                $fassert!(<$fty>::NEG_INFINITY.max(-9.0), -9.0);
+                $fassert!((-9.0 as $fty).max(<$fty>::NEG_INFINITY), -9.0);
+                $fassert!(<$fty>::NAN.max(9.0), 9.0);
+                $fassert!(<$fty>::NAN.max(-9.0), -9.0);
+                $fassert!((9.0 as $fty).max(<$fty>::NAN), 9.0);
+                $fassert!((-9.0 as $fty).max(<$fty>::NAN), -9.0);
+                $fassert!(<$fty>::NAN.max(<$fty>::NAN).is_nan());
             }
             #[test]
             fn minimum() {
@@ -806,19 +809,19 @@ macro_rules! test_float {
                 $fassert!((-0.0 as $fty).minimum(9.0), -0.0);
                 $fassert!((-0.0 as $fty).minimum(9.0).is_sign_negative());
                 $fassert!((-0.0 as $fty).minimum(-9.0), -9.0);
-                $fassert!(($inf as $fty).minimum(9.0), 9.0);
-                $fassert!((9.0 as $fty).minimum($inf), 9.0);
-                $fassert!(($inf as $fty).minimum(-9.0), -9.0);
-                $fassert!((-9.0 as $fty).minimum($inf), -9.0);
-                $fassert!(($neginf as $fty).minimum(9.0), $neginf);
-                $fassert!((9.0 as $fty).minimum($neginf), $neginf);
-                $fassert!(($neginf as $fty).minimum(-9.0), $neginf);
-                $fassert!((-9.0 as $fty).minimum($neginf), $neginf);
-                $fassert!(($nan as $fty).minimum(9.0).is_nan());
-                $fassert!(($nan as $fty).minimum(-9.0).is_nan());
-                $fassert!((9.0 as $fty).minimum($nan).is_nan());
-                $fassert!((-9.0 as $fty).minimum($nan).is_nan());
-                $fassert!(($nan as $fty).minimum($nan).is_nan());
+                $fassert!(<$fty>::INFINITY.minimum(9.0), 9.0);
+                $fassert!((9.0 as $fty).minimum(<$fty>::INFINITY), 9.0);
+                $fassert!(<$fty>::INFINITY.minimum(-9.0), -9.0);
+                $fassert!((-9.0 as $fty).minimum(<$fty>::INFINITY), -9.0);
+                $fassert!(<$fty>::NEG_INFINITY.minimum(9.0), <$fty>::NEG_INFINITY);
+                $fassert!((9.0 as $fty).minimum(<$fty>::NEG_INFINITY), <$fty>::NEG_INFINITY);
+                $fassert!(<$fty>::NEG_INFINITY.minimum(-9.0), <$fty>::NEG_INFINITY);
+                $fassert!((-9.0 as $fty).minimum(<$fty>::NEG_INFINITY), <$fty>::NEG_INFINITY);
+                $fassert!(<$fty>::NAN.minimum(9.0).is_nan());
+                $fassert!(<$fty>::NAN.minimum(-9.0).is_nan());
+                $fassert!((9.0 as $fty).minimum(<$fty>::NAN).is_nan());
+                $fassert!((-9.0 as $fty).minimum(<$fty>::NAN).is_nan());
+                $fassert!(<$fty>::NAN.minimum(<$fty>::NAN).is_nan());
             }
             #[test]
             fn maximum() {
@@ -838,19 +841,19 @@ macro_rules! test_float {
                 $fassert!((0.0 as $fty).maximum(-9.0).is_sign_positive());
                 $fassert!((-0.0 as $fty).maximum(-9.0), -0.0);
                 $fassert!((-0.0 as $fty).maximum(-9.0).is_sign_negative());
-                $fassert!(($inf as $fty).maximum(9.0), $inf);
-                $fassert!((9.0 as $fty).maximum($inf), $inf);
-                $fassert!(($inf as $fty).maximum(-9.0), $inf);
-                $fassert!((-9.0 as $fty).maximum($inf), $inf);
-                $fassert!(($neginf as $fty).maximum(9.0), 9.0);
-                $fassert!((9.0 as $fty).maximum($neginf), 9.0);
-                $fassert!(($neginf as $fty).maximum(-9.0), -9.0);
-                $fassert!((-9.0 as $fty).maximum($neginf), -9.0);
-                $fassert!(($nan as $fty).maximum(9.0).is_nan());
-                $fassert!(($nan as $fty).maximum(-9.0).is_nan());
-                $fassert!((9.0 as $fty).maximum($nan).is_nan());
-                $fassert!((-9.0 as $fty).maximum($nan).is_nan());
-                $fassert!(($nan as $fty).maximum($nan).is_nan());
+                $fassert!(<$fty>::INFINITY.maximum(9.0), <$fty>::INFINITY);
+                $fassert!((9.0 as $fty).maximum(<$fty>::INFINITY), <$fty>::INFINITY);
+                $fassert!(<$fty>::INFINITY.maximum(-9.0), <$fty>::INFINITY);
+                $fassert!((-9.0 as $fty).maximum(<$fty>::INFINITY), <$fty>::INFINITY);
+                $fassert!(<$fty>::NEG_INFINITY.maximum(9.0), 9.0);
+                $fassert!((9.0 as $fty).maximum(<$fty>::NEG_INFINITY), 9.0);
+                $fassert!(<$fty>::NEG_INFINITY.maximum(-9.0), -9.0);
+                $fassert!((-9.0 as $fty).maximum(<$fty>::NEG_INFINITY), -9.0);
+                $fassert!(<$fty>::NAN.maximum(9.0).is_nan());
+                $fassert!(<$fty>::NAN.maximum(-9.0).is_nan());
+                $fassert!((9.0 as $fty).maximum(<$fty>::NAN).is_nan());
+                $fassert!((-9.0 as $fty).maximum(<$fty>::NAN).is_nan());
+                $fassert!(<$fty>::NAN.maximum(<$fty>::NAN).is_nan());
             }
             #[test]
             fn midpoint() {
@@ -863,38 +866,47 @@ macro_rules! test_float {
                 $fassert!((0.0 as $fty).midpoint(0.0), 0.0);
                 $fassert!((-0.0 as $fty).midpoint(-0.0), -0.0);
                 $fassert!((-5.0 as $fty).midpoint(5.0), 0.0);
-                $fassert!(($max as $fty).midpoint($min), 0.0);
-                $fassert!(($min as $fty).midpoint($max), -0.0);
-                $fassert!(($max as $fty).midpoint($min_pos), $max / 2.);
-                $fassert!((-$max as $fty).midpoint($min_pos), -$max / 2.);
-                $fassert!(($max as $fty).midpoint(-$min_pos), $max / 2.);
-                $fassert!((-$max as $fty).midpoint(-$min_pos), -$max / 2.);
-                $fassert!(($min_pos as $fty).midpoint($max), $max / 2.);
-                $fassert!(($min_pos as $fty).midpoint(-$max), -$max / 2.);
-                $fassert!((-$min_pos as $fty).midpoint($max), $max / 2.);
-                $fassert!((-$min_pos as $fty).midpoint(-$max), -$max / 2.);
-                $fassert!(($max as $fty).midpoint($max), $max);
-                $fassert!(($min_pos as $fty).midpoint($min_pos), $min_pos);
-                $fassert!((-$min_pos as $fty).midpoint(-$min_pos), -$min_pos);
-                $fassert!(($max as $fty).midpoint(5.0), $max / 2.0 + 2.5);
-                $fassert!(($max as $fty).midpoint(-5.0), $max / 2.0 - 2.5);
-                $fassert!(($inf as $fty).midpoint($inf), $inf);
-                $fassert!(($neginf as $fty).midpoint($neginf), $neginf);
-                $fassert!(($nan as $fty).midpoint(1.0).is_nan());
-                $fassert!((1.0 as $fty).midpoint($nan).is_nan());
-                $fassert!(($nan as $fty).midpoint($nan).is_nan());
+                $fassert!(<$fty>::MAX.midpoint(<$fty>::MIN), 0.0);
+                $fassert!(<$fty>::MIN.midpoint(<$fty>::MAX), -0.0);
+                $fassert!(<$fty>::MAX.midpoint(<$fty>::MIN_POSITIVE), <$fty>::MAX / 2.);
+                $fassert!((-<$fty>::MAX).midpoint(<$fty>::MIN_POSITIVE), -<$fty>::MAX / 2.);
+                $fassert!(<$fty>::MAX.midpoint(-<$fty>::MIN_POSITIVE), <$fty>::MAX / 2.);
+                $fassert!((-<$fty>::MAX).midpoint(-<$fty>::MIN_POSITIVE), -<$fty>::MAX / 2.);
+                $fassert!((<$fty>::MIN_POSITIVE).midpoint(<$fty>::MAX), <$fty>::MAX / 2.);
+                $fassert!((<$fty>::MIN_POSITIVE).midpoint(-<$fty>::MAX), -<$fty>::MAX / 2.);
+                $fassert!((-<$fty>::MIN_POSITIVE).midpoint(<$fty>::MAX), <$fty>::MAX / 2.);
+                $fassert!((-<$fty>::MIN_POSITIVE).midpoint(-<$fty>::MAX), -<$fty>::MAX / 2.);
+                $fassert!(<$fty>::MAX.midpoint(<$fty>::MAX), <$fty>::MAX);
+                $fassert!(
+                    (<$fty>::MIN_POSITIVE).midpoint(<$fty>::MIN_POSITIVE),
+                    <$fty>::MIN_POSITIVE
+                );
+                $fassert!(
+                    (-<$fty>::MIN_POSITIVE).midpoint(-<$fty>::MIN_POSITIVE),
+                    -<$fty>::MIN_POSITIVE
+                );
+                $fassert!(<$fty>::MAX.midpoint(5.0), <$fty>::MAX / 2.0 + 2.5);
+                $fassert!(<$fty>::MAX.midpoint(-5.0), <$fty>::MAX / 2.0 - 2.5);
+                $fassert!(<$fty>::INFINITY.midpoint(<$fty>::INFINITY), <$fty>::INFINITY);
+                $fassert!(
+                    <$fty>::NEG_INFINITY.midpoint(<$fty>::NEG_INFINITY),
+                    <$fty>::NEG_INFINITY
+                );
+                $fassert!(<$fty>::NAN.midpoint(1.0).is_nan());
+                $fassert!((1.0 as $fty).midpoint(<$fty>::NAN).is_nan());
+                $fassert!(<$fty>::NAN.midpoint(<$fty>::NAN).is_nan());
 
                 // test if large differences in magnitude are still correctly computed.
                 // NOTE: that because of how small x and y are, x + y can never overflow
                 // so (x + y) / 2.0 is always correct
                 // in particular, `2.pow(i)` will  never be at the max exponent, so it could
                 // be safely doubled, while j is significantly smaller.
-                for i in $max_exp.saturating_sub(64)..$max_exp {
+                for i in <$fty>::MAX_EXP.saturating_sub(64)..<$fty>::MAX_EXP {
                     for j in 0..64u8 {
-                        let large = <$fty>::from(2.0f32).powi(i);
+                        let large = (2.0 as $fty).powi(i);
                         // a much smaller number, such that there is no chance of overflow to test
                         // potential double rounding in midpoint's implementation.
-                        let small = <$fty>::from(2.0f32).powi($max_exp - 1)
+                        let small = (2.0 as $fty).powi(<$fty>::MAX_EXP - 1)
                             * <$fty>::EPSILON
                             * <$fty>::from(j);
 
@@ -906,23 +918,148 @@ macro_rules! test_float {
                 }
             }
             #[test]
+            fn abs() {
+                $fassert!((-1.0 as $fty).abs(), 1.0);
+                $fassert!((1.0 as $fty).abs(), 1.0);
+                $fassert!(<$fty>::NEG_INFINITY.abs(), <$fty>::INFINITY);
+                $fassert!(<$fty>::INFINITY.abs(), <$fty>::INFINITY);
+            }
+            #[test]
+            fn copysign() {
+                $fassert!((1.0 as $fty).copysign(-2.0), -1.0);
+                $fassert!((-1.0 as $fty).copysign(2.0), 1.0);
+                $fassert!(<$fty>::INFINITY.copysign(-0.0), <$fty>::NEG_INFINITY);
+                $fassert!(<$fty>::NEG_INFINITY.copysign(0.0), <$fty>::INFINITY);
+            }
+            #[test]
             fn rem_euclid() {
                 // FIXME: Use $fassert when rem_euclid becomes const
-                assert!($inf.rem_euclid((42.0 as $fty)).is_nan());
-                assert_eq!((42.0 as $fty).rem_euclid($inf), (42.0 as $fty));
-                assert!((42.0 as $fty).rem_euclid($nan).is_nan());
-                assert!($inf.rem_euclid($inf).is_nan());
-                assert!($inf.rem_euclid($nan).is_nan());
-                assert!($nan.rem_euclid($inf).is_nan());
+                assert!(<$fty>::INFINITY.rem_euclid((42.0 as $fty)).is_nan());
+                assert_eq!((42.0 as $fty).rem_euclid(<$fty>::INFINITY), (42.0 as $fty));
+                assert!((42.0 as $fty).rem_euclid(<$fty>::NAN).is_nan());
+                assert!(<$fty>::INFINITY.rem_euclid(<$fty>::INFINITY).is_nan());
+                assert!(<$fty>::INFINITY.rem_euclid(<$fty>::NAN).is_nan());
+                assert!(<$fty>::NAN.rem_euclid(<$fty>::INFINITY).is_nan());
             }
             #[test]
             fn div_euclid() {
                 // FIXME: Use $fassert when div_euclid becomes const
-                assert_eq!((42.0 as $fty).div_euclid($inf), 0.0);
-                assert!((42.0 as $fty).div_euclid($nan).is_nan());
-                assert!($inf.div_euclid($inf).is_nan());
-                assert!($inf.div_euclid($nan).is_nan());
-                assert!($nan.div_euclid($inf).is_nan());
+                assert_eq!((42.0 as $fty).div_euclid(<$fty>::INFINITY), 0.0);
+                assert!((42.0 as $fty).div_euclid(<$fty>::NAN).is_nan());
+                assert!(<$fty>::INFINITY.div_euclid(<$fty>::INFINITY).is_nan());
+                assert!(<$fty>::INFINITY.div_euclid(<$fty>::NAN).is_nan());
+                assert!(<$fty>::NAN.div_euclid(<$fty>::INFINITY).is_nan());
+            }
+            #[test]
+            #[cfg(not(bootstrap))]
+            fn floor() {
+                $fassert!((0.0 as $fty).floor(), 0.0);
+                $fassert!((0.0 as $fty).floor().is_sign_positive());
+                $fassert!((-0.0 as $fty).floor(), -0.0);
+                $fassert!((-0.0 as $fty).floor().is_sign_negative());
+                $fassert!((0.5 as $fty).floor(), 0.0);
+                $fassert!((-0.5 as $fty).floor(), -1.0);
+                $fassert!((1.5 as $fty).floor(), 1.0);
+                $fassert!(<$fty>::MAX.floor(), <$fty>::MAX);
+                $fassert!(<$fty>::MIN.floor(), <$fty>::MIN);
+                $fassert!(<$fty>::MIN_POSITIVE.floor(), 0.0);
+                $fassert!((-<$fty>::MIN_POSITIVE).floor(), -1.0);
+                $fassert!(<$fty>::NAN.floor().is_nan());
+                $fassert!(<$fty>::INFINITY.floor(), <$fty>::INFINITY);
+                $fassert!(<$fty>::NEG_INFINITY.floor(), <$fty>::NEG_INFINITY);
+            }
+            #[test]
+            #[cfg(not(bootstrap))]
+            fn ceil() {
+                $fassert!((0.0 as $fty).ceil(), 0.0);
+                $fassert!((0.0 as $fty).ceil().is_sign_positive());
+                $fassert!((-0.0 as $fty).ceil(), 0.0);
+                $fassert!((-0.0 as $fty).ceil().is_sign_negative());
+                $fassert!((0.5 as $fty).ceil(), 1.0);
+                $fassert!((-0.5 as $fty).ceil(), 0.0);
+                $fassert!(<$fty>::MAX.ceil(), <$fty>::MAX);
+                $fassert!(<$fty>::MIN.ceil(), <$fty>::MIN);
+                $fassert!(<$fty>::MIN_POSITIVE.ceil(), 1.0);
+                $fassert!((-<$fty>::MIN_POSITIVE).ceil(), 0.0);
+                $fassert!(<$fty>::NAN.ceil().is_nan());
+                $fassert!(<$fty>::INFINITY.ceil(), <$fty>::INFINITY);
+                $fassert!(<$fty>::NEG_INFINITY.ceil(), <$fty>::NEG_INFINITY);
+            }
+            #[test]
+            #[cfg(not(bootstrap))]
+            fn round() {
+                $fassert!((0.0 as $fty).round(), 0.0);
+                $fassert!((0.0 as $fty).round().is_sign_positive());
+                $fassert!((-0.0 as $fty).round(), -0.0);
+                $fassert!((-0.0 as $fty).round().is_sign_negative());
+                $fassert!((0.5 as $fty).round(), 1.0);
+                $fassert!((-0.5 as $fty).round(), -1.0);
+                $fassert!(<$fty>::MAX.round(), <$fty>::MAX);
+                $fassert!(<$fty>::MIN.round(), <$fty>::MIN);
+                $fassert!(<$fty>::MIN_POSITIVE.round(), 0.0);
+                $fassert!((-<$fty>::MIN_POSITIVE).round(), 0.0);
+                $fassert!(<$fty>::NAN.round().is_nan());
+                $fassert!(<$fty>::INFINITY.round(), <$fty>::INFINITY);
+                $fassert!(<$fty>::NEG_INFINITY.round(), <$fty>::NEG_INFINITY);
+            }
+            #[test]
+            #[cfg(not(bootstrap))]
+            fn round_ties_even() {
+                $fassert!((0.0 as $fty).round_ties_even(), 0.0);
+                $fassert!((0.0 as $fty).round_ties_even().is_sign_positive());
+                $fassert!((-0.0 as $fty).round_ties_even(), -0.0);
+                $fassert!((-0.0 as $fty).round_ties_even().is_sign_negative());
+                $fassert!((0.5 as $fty).round_ties_even(), 0.0);
+                $fassert!((0.5 as $fty).round_ties_even().is_sign_positive());
+                $fassert!((-0.5 as $fty).round_ties_even(), -0.0);
+                $fassert!((-0.5 as $fty).round_ties_even().is_sign_negative());
+                $fassert!(<$fty>::MAX.round_ties_even(), <$fty>::MAX);
+                $fassert!(<$fty>::MIN.round_ties_even(), <$fty>::MIN);
+                $fassert!(<$fty>::MIN_POSITIVE.round_ties_even(), 0.0);
+                $fassert!((-<$fty>::MIN_POSITIVE).round_ties_even(), 0.0);
+                $fassert!(<$fty>::NAN.round_ties_even().is_nan());
+                $fassert!(<$fty>::INFINITY.round_ties_even(), <$fty>::INFINITY);
+                $fassert!(<$fty>::NEG_INFINITY.round_ties_even(), <$fty>::NEG_INFINITY);
+            }
+            #[test]
+            #[cfg(not(bootstrap))]
+            fn trunc() {
+                $fassert!((0.0 as $fty).trunc(), 0.0);
+                $fassert!((0.0 as $fty).trunc().is_sign_positive());
+                $fassert!((-0.0 as $fty).trunc(), -0.0);
+                $fassert!((-0.0 as $fty).trunc().is_sign_negative());
+                $fassert!((0.5 as $fty).trunc(), 0.0);
+                $fassert!((0.5 as $fty).trunc().is_sign_positive());
+                $fassert!((-0.5 as $fty).trunc(), -0.0);
+                $fassert!((-0.5 as $fty).trunc().is_sign_negative());
+                $fassert!(<$fty>::MAX.trunc(), <$fty>::MAX);
+                $fassert!(<$fty>::MIN.trunc(), <$fty>::MIN);
+                $fassert!(<$fty>::MIN_POSITIVE.trunc(), 0.0);
+                $fassert!((-<$fty>::MIN_POSITIVE).trunc(), 0.0);
+                $fassert!(<$fty>::NAN.trunc().is_nan());
+                $fassert!(<$fty>::INFINITY.trunc(), <$fty>::INFINITY);
+                $fassert!(<$fty>::NEG_INFINITY.trunc(), <$fty>::NEG_INFINITY);
+            }
+            #[test]
+            #[cfg(not(bootstrap))]
+            fn fract() {
+                $fassert!((0.0 as $fty).fract(), 0.0);
+                $fassert!((0.0 as $fty).fract().is_sign_positive());
+                $fassert!((-0.0 as $fty).fract(), 0.0);
+                $fassert!((-0.0 as $fty).fract().is_sign_positive());
+                $fassert!((0.5 as $fty).fract(), 0.5);
+                $fassert!((0.5 as $fty).fract().is_sign_positive());
+                $fassert!((-0.5 as $fty).fract(), -0.5);
+                $fassert!((-0.5 as $fty).fract().is_sign_negative());
+                $fassert!(<$fty>::MAX.fract(), 0.0);
+                $fassert!(<$fty>::MIN.fract(), 0.0);
+                $fassert!(<$fty>::MIN_POSITIVE.fract(), <$fty>::MIN_POSITIVE);
+                $fassert!(<$fty>::MIN_POSITIVE.fract().is_sign_positive());
+                $fassert!((-<$fty>::MIN_POSITIVE).fract(), -<$fty>::MIN_POSITIVE);
+                $fassert!((-<$fty>::MIN_POSITIVE).fract().is_sign_negative());
+                $fassert!(<$fty>::NAN.fract().is_nan());
+                $fassert!(<$fty>::INFINITY.fract().is_nan());
+                $fassert!(<$fty>::NEG_INFINITY.fract().is_nan());
             }
         }
     };
@@ -948,51 +1085,7 @@ macro_rules! float_const_assert {
     };
 }
 
-test_float!(
-    f32,
-    float_assert,
-    f32,
-    f32::INFINITY,
-    f32::NEG_INFINITY,
-    f32::NAN,
-    f32::MIN,
-    f32::MAX,
-    f32::MIN_POSITIVE,
-    f32::MAX_EXP
-);
-test_float!(
-    f32_const,
-    float_const_assert,
-    f32,
-    f32::INFINITY,
-    f32::NEG_INFINITY,
-    f32::NAN,
-    f32::MIN,
-    f32::MAX,
-    f32::MIN_POSITIVE,
-    f32::MAX_EXP
-);
-test_float!(
-    f64,
-    float_assert,
-    f64,
-    f64::INFINITY,
-    f64::NEG_INFINITY,
-    f64::NAN,
-    f64::MIN,
-    f64::MAX,
-    f64::MIN_POSITIVE,
-    f64::MAX_EXP
-);
-test_float!(
-    f64_const,
-    float_const_assert,
-    f64,
-    f64::INFINITY,
-    f64::NEG_INFINITY,
-    f64::NAN,
-    f64::MIN,
-    f64::MAX,
-    f64::MIN_POSITIVE,
-    f64::MAX_EXP
-);
+test_float!(f32, float_assert, f32);
+test_float!(f32_const, float_const_assert, f32);
+test_float!(f64, float_assert, f64);
+test_float!(f64_const, float_const_assert, f64);
diff --git a/library/proc_macro/Cargo.toml b/library/proc_macro/Cargo.toml
index b8bc2a3af4c..1d79246356a 100644
--- a/library/proc_macro/Cargo.toml
+++ b/library/proc_macro/Cargo.toml
@@ -10,3 +10,7 @@ std = { path = "../std" }
 # loaded from sysroot causing duplicate lang items and other similar errors.
 core = { path = "../core" }
 rustc-literal-escaper = { version = "0.0.2", features = ["rustc-dep-of-std"] }
+
+[features]
+default = ["rustc-dep-of-std"]
+rustc-dep-of-std = []
diff --git a/library/proc_macro/src/lib.rs b/library/proc_macro/src/lib.rs
index b4fd20c0c17..32c306be94e 100644
--- a/library/proc_macro/src/lib.rs
+++ b/library/proc_macro/src/lib.rs
@@ -32,6 +32,7 @@
 #![recursion_limit = "256"]
 #![allow(internal_features)]
 #![deny(ffi_unwind_calls)]
+#![allow(rustc::internal)] // Can't use FxHashMap when compiled as part of the standard library
 #![warn(rustdoc::unescaped_backticks)]
 #![warn(unreachable_pub)]
 #![deny(unsafe_op_in_unsafe_fn)]
@@ -95,7 +96,7 @@ pub fn is_available() -> bool {
 ///
 /// This is both the input and output of `#[proc_macro]`, `#[proc_macro_attribute]`
 /// and `#[proc_macro_derive]` definitions.
-#[rustc_diagnostic_item = "TokenStream"]
+#[cfg_attr(feature = "rustc-dep-of-std", rustc_diagnostic_item = "TokenStream")]
 #[stable(feature = "proc_macro_lib", since = "1.15.0")]
 #[derive(Clone)]
 pub struct TokenStream(Option<bridge::client::TokenStream>);
diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml
index 4ff4895ecde..31371f06b38 100644
--- a/library/std/Cargo.toml
+++ b/library/std/Cargo.toml
@@ -18,7 +18,7 @@ cfg-if = { version = "1.0", features = ['rustc-dep-of-std'] }
 panic_unwind = { path = "../panic_unwind", optional = true }
 panic_abort = { path = "../panic_abort" }
 core = { path = "../core", public = true }
-compiler_builtins = { version = "=0.1.159" }
+compiler_builtins = { version = "=0.1.160" }
 unwind = { path = "../unwind" }
 hashbrown = { version = "0.15", default-features = false, features = [
     'rustc-dep-of-std',
diff --git a/library/std/src/ffi/os_str.rs b/library/std/src/ffi/os_str.rs
index ead48775127..b0580b467be 100644
--- a/library/std/src/ffi/os_str.rs
+++ b/library/std/src/ffi/os_str.rs
@@ -594,9 +594,9 @@ impl OsString {
     /// The slice must be valid for the platform encoding (as described in
     /// [`OsStr::from_encoded_bytes_unchecked`]).
     ///
-    /// This bypasses the encoding-dependent surrogate joining, so `self` must
-    /// not end with a leading surrogate half and `other` must not start with
-    /// with a trailing surrogate half.
+    /// This bypasses the encoding-dependent surrogate joining, so either
+    /// `self` must not end with a leading surrogate half, or `other` must not
+    /// start with a trailing surrogate half.
     #[inline]
     pub(crate) unsafe fn extend_from_slice_unchecked(&mut self, other: &[u8]) {
         // SAFETY: Guaranteed by caller.
diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs
index 509e673bdb8..711efc7d011 100644
--- a/library/std/src/fs.rs
+++ b/library/std/src/fs.rs
@@ -391,6 +391,16 @@ impl fmt::Display for TryLockError {
     }
 }
 
+#[unstable(feature = "file_lock", issue = "130994")]
+impl From<TryLockError> for io::Error {
+    fn from(err: TryLockError) -> io::Error {
+        match err {
+            TryLockError::Error(err) => err,
+            TryLockError::WouldBlock => io::ErrorKind::WouldBlock.into(),
+        }
+    }
+}
+
 impl File {
     /// Attempts to open a file in read-only mode.
     ///
@@ -820,11 +830,14 @@ impl File {
     ///
     /// fn main() -> std::io::Result<()> {
     ///     let f = File::create("foo.txt")?;
+    ///     // Explicit handling of the WouldBlock error
     ///     match f.try_lock() {
     ///         Ok(_) => (),
     ///         Err(TryLockError::WouldBlock) => (), // Lock not acquired
     ///         Err(TryLockError::Error(err)) => return Err(err),
     ///     }
+    ///     // Alternately, propagate the error as an io::Error
+    ///     f.try_lock()?;
     ///     Ok(())
     /// }
     /// ```
@@ -881,11 +894,14 @@ impl File {
     ///
     /// fn main() -> std::io::Result<()> {
     ///     let f = File::open("foo.txt")?;
+    ///     // Explicit handling of the WouldBlock error
     ///     match f.try_lock_shared() {
     ///         Ok(_) => (),
     ///         Err(TryLockError::WouldBlock) => (), // Lock not acquired
     ///         Err(TryLockError::Error(err)) => return Err(err),
     ///     }
+    ///     // Alternately, propagate the error as an io::Error
+    ///     f.try_lock_shared()?;
     ///
     ///     Ok(())
     /// }
@@ -2803,8 +2819,8 @@ pub fn create_dir<P: AsRef<Path>>(path: P) -> io::Result<()> {
 /// Recursively create a directory and all of its parent components if they
 /// are missing.
 ///
-/// If this function returns an error, some of the parent components might have
-/// been created already.
+/// This function is not atomic. If it returns an error, any parent components it was able to create
+/// will remain.
 ///
 /// If the empty path is passed to this function, it always succeeds without
 /// creating any directories.
@@ -2899,17 +2915,28 @@ pub fn remove_dir<P: AsRef<Path>>(path: P) -> io::Result<()> {
 ///
 /// # Platform-specific behavior
 ///
-/// This function currently corresponds to `openat`, `fdopendir`, `unlinkat` and `lstat` functions
-/// on Unix (except for REDOX) and the `CreateFileW`, `GetFileInformationByHandleEx`,
-/// `SetFileInformationByHandle`, and `NtCreateFile` functions on Windows. Note that, this
-/// [may change in the future][changes].
+/// These implementation details [may change in the future][changes].
+///
+/// - "Unix-like": By default, this function currently corresponds to
+/// `openat`, `fdopendir`, `unlinkat` and `lstat`
+/// on Unix-family platforms, except where noted otherwise.
+/// - "Windows": This function currently corresponds to `CreateFileW`,
+/// `GetFileInformationByHandleEx`, `SetFileInformationByHandle`, and `NtCreateFile`.
+///
+/// ## Time-of-check to time-of-use (TOCTOU) race conditions
+/// On a few platforms there is no way to remove a directory's contents without following symlinks
+/// unless you perform a check and then operate on paths based on that directory.
+/// This allows concurrently-running code to replace the directory with a symlink after the check,
+/// causing a removal to instead operate on a path based on the symlink. This is a TOCTOU race.
+/// By default, `fs::remove_dir_all` protects against a symlink TOCTOU race on all platforms
+/// except the following. It should not be used in security-sensitive contexts on these platforms:
+/// - Miri: Even when emulating targets where the underlying implementation will protect against
+/// TOCTOU races, Miri will not do so.
+/// - Redox OS: This function does not protect against TOCTOU races, as Redox does not implement
+/// the required platform support to do so.
 ///
 /// [changes]: io#platform-specific-behavior
 ///
-/// On REDOX, as well as when running in Miri for any target, this function is not protected against
-/// time-of-check to time-of-use (TOCTOU) race conditions, and should not be used in
-/// security-sensitive code on those platforms. All other platforms are protected.
-///
 /// # Errors
 ///
 /// See [`fs::remove_file`] and [`fs::remove_dir`].
diff --git a/library/std/src/fs/tests.rs b/library/std/src/fs/tests.rs
index c81a5ff4d96..c81e3af2f0d 100644
--- a/library/std/src/fs/tests.rs
+++ b/library/std/src/fs/tests.rs
@@ -367,6 +367,28 @@ fn file_lock_blocking_async() {
 }
 
 #[test]
+#[cfg(windows)]
+fn file_try_lock_async() {
+    const FILE_FLAG_OVERLAPPED: u32 = 0x40000000;
+
+    let tmpdir = tmpdir();
+    let filename = &tmpdir.join("file_try_lock_async.txt");
+    let f1 = check!(File::create(filename));
+    let f2 =
+        check!(OpenOptions::new().custom_flags(FILE_FLAG_OVERLAPPED).write(true).open(filename));
+
+    // Check that shared locks block exclusive locks
+    check!(f1.lock_shared());
+    assert_matches!(f2.try_lock(), Err(TryLockError::WouldBlock));
+    check!(f1.unlock());
+
+    // Check that exclusive locks block all locks
+    check!(f1.lock());
+    assert_matches!(f2.try_lock(), Err(TryLockError::WouldBlock));
+    assert_matches!(f2.try_lock_shared(), Err(TryLockError::WouldBlock));
+}
+
+#[test]
 fn file_test_io_seek_shakedown() {
     //                   01234567890123
     let initial_msg = "qwer-asdf-zxcv";
@@ -1760,8 +1782,30 @@ fn test_eq_windows_file_type() {
     // Change the readonly attribute of one file.
     let mut perms = file1.metadata().unwrap().permissions();
     perms.set_readonly(true);
-    file1.set_permissions(perms).unwrap();
+    file1.set_permissions(perms.clone()).unwrap();
+    #[cfg(target_vendor = "win7")]
+    let _g = ReadonlyGuard { file: &file1, perms };
     assert_eq!(file1.metadata().unwrap().file_type(), file2.metadata().unwrap().file_type());
+
+    // Reset the attribute before the `TmpDir`'s drop that removes the
+    // associated directory, which fails with a `PermissionDenied` error when
+    // running under Windows 7.
+    #[cfg(target_vendor = "win7")]
+    struct ReadonlyGuard<'f> {
+        file: &'f File,
+        perms: fs::Permissions,
+    }
+    #[cfg(target_vendor = "win7")]
+    impl<'f> Drop for ReadonlyGuard<'f> {
+        fn drop(&mut self) {
+            self.perms.set_readonly(false);
+            let res = self.file.set_permissions(self.perms.clone());
+
+            if !thread::panicking() {
+                res.unwrap();
+            }
+        }
+    }
 }
 
 /// Regression test for https://github.com/rust-lang/rust/issues/50619.
diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs
index 4d984617739..74a34339860 100644
--- a/library/std/src/lib.rs
+++ b/library/std/src/lib.rs
@@ -276,12 +276,12 @@
 // tidy-alphabetical-start
 
 // stabilization was reverted after it hit beta
+#![cfg_attr(not(bootstrap), feature(autodiff))]
 #![feature(alloc_error_handler)]
 #![feature(allocator_internals)]
 #![feature(allow_internal_unsafe)]
 #![feature(allow_internal_unstable)]
 #![feature(asm_experimental_arch)]
-#![feature(autodiff)]
 #![feature(cfg_sanitizer_cfi)]
 #![feature(cfg_target_thread_local)]
 #![feature(cfi_encoding)]
@@ -335,6 +335,7 @@
 #![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)]
@@ -585,11 +586,13 @@ pub use alloc_crate::string;
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use alloc_crate::vec;
 
-#[unstable(feature = "f128", issue = "116909")]
+#[path = "num/f128.rs"]
 pub mod f128;
-#[unstable(feature = "f16", issue = "116909")]
+#[path = "num/f16.rs"]
 pub mod f16;
+#[path = "num/f32.rs"]
 pub mod f32;
+#[path = "num/f64.rs"]
 pub mod f64;
 
 #[macro_use]
@@ -636,12 +639,15 @@ pub mod simd {
     #[doc(inline)]
     pub use crate::std_float::StdFloat;
 }
+
 #[unstable(feature = "autodiff", issue = "124509")]
+#[cfg(not(bootstrap))]
 /// This module provides support for automatic differentiation.
 pub mod autodiff {
     /// This macro handles automatic differentiation.
-    pub use core::autodiff::autodiff;
+    pub use core::autodiff::{autodiff_forward, autodiff_reverse};
 }
+
 #[stable(feature = "futures_api", since = "1.36.0")]
 pub mod task {
     //! Types and Traits for working with asynchronous tasks.
diff --git a/library/std/src/f128.rs b/library/std/src/num/f128.rs
index bb4acde4822..c0190de089f 100644
--- a/library/std/src/f128.rs
+++ b/library/std/src/num/f128.rs
@@ -4,6 +4,8 @@
 //!
 //! Mathematically significant numbers are provided in the `consts` sub-module.
 
+#![unstable(feature = "f128", issue = "116909")]
+
 #[unstable(feature = "f128", issue = "116909")]
 pub use core::f128::consts;
 
diff --git a/library/std/src/f16.rs b/library/std/src/num/f16.rs
index 4792eac1f9e..4a4a8fd839a 100644
--- a/library/std/src/f16.rs
+++ b/library/std/src/num/f16.rs
@@ -4,6 +4,8 @@
 //!
 //! Mathematically significant numbers are provided in the `consts` sub-module.
 
+#![unstable(feature = "f16", issue = "116909")]
+
 #[unstable(feature = "f16", issue = "116909")]
 pub use core::f16::consts;
 
diff --git a/library/std/src/f32.rs b/library/std/src/num/f32.rs
index 5210e75ec45..b7f6529ac40 100644
--- a/library/std/src/f32.rs
+++ b/library/std/src/num/f32.rs
@@ -44,8 +44,9 @@ 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")]
     #[inline]
-    pub fn floor(self) -> f32 {
+    pub const fn floor(self) -> f32 {
         core::f32::math::floor(self)
     }
 
@@ -66,8 +67,9 @@ 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")]
     #[inline]
-    pub fn ceil(self) -> f32 {
+    pub const fn ceil(self) -> f32 {
         core::f32::math::ceil(self)
     }
 
@@ -94,8 +96,9 @@ 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")]
     #[inline]
-    pub fn round(self) -> f32 {
+    pub const fn round(self) -> f32 {
         core::f32::math::round(self)
     }
 
@@ -120,8 +123,9 @@ 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")]
     #[inline]
-    pub fn round_ties_even(self) -> f32 {
+    pub const fn round_ties_even(self) -> f32 {
         core::f32::math::round_ties_even(self)
     }
 
@@ -145,8 +149,9 @@ 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")]
     #[inline]
-    pub fn trunc(self) -> f32 {
+    pub const fn trunc(self) -> f32 {
         core::f32::math::trunc(self)
     }
 
@@ -168,8 +173,9 @@ 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")]
     #[inline]
-    pub fn fract(self) -> f32 {
+    pub const fn fract(self) -> f32 {
         core::f32::math::fract(self)
     }
 
diff --git a/library/std/src/f64.rs b/library/std/src/num/f64.rs
index f837800d663..75e35a8db33 100644
--- a/library/std/src/f64.rs
+++ b/library/std/src/num/f64.rs
@@ -44,8 +44,9 @@ 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")]
     #[inline]
-    pub fn floor(self) -> f64 {
+    pub const fn floor(self) -> f64 {
         core::f64::math::floor(self)
     }
 
@@ -66,8 +67,9 @@ 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")]
     #[inline]
-    pub fn ceil(self) -> f64 {
+    pub const fn ceil(self) -> f64 {
         core::f64::math::ceil(self)
     }
 
@@ -94,8 +96,9 @@ 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")]
     #[inline]
-    pub fn round(self) -> f64 {
+    pub const fn round(self) -> f64 {
         core::f64::math::round(self)
     }
 
@@ -120,8 +123,9 @@ 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")]
     #[inline]
-    pub fn round_ties_even(self) -> f64 {
+    pub const fn round_ties_even(self) -> f64 {
         core::f64::math::round_ties_even(self)
     }
 
@@ -145,8 +149,9 @@ 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")]
     #[inline]
-    pub fn trunc(self) -> f64 {
+    pub const fn trunc(self) -> f64 {
         core::f64::math::trunc(self)
     }
 
@@ -168,8 +173,9 @@ 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")]
     #[inline]
-    pub fn fract(self) -> f64 {
+    pub const fn fract(self) -> f64 {
         core::f64::math::fract(self)
     }
 
diff --git a/library/std/src/num.rs b/library/std/src/num/mod.rs
index ffb8789c906..ffb8789c906 100644
--- a/library/std/src/num.rs
+++ b/library/std/src/num/mod.rs
diff --git a/library/std/src/path.rs b/library/std/src/path.rs
index 7959c633858..050c617f564 100644
--- a/library/std/src/path.rs
+++ b/library/std/src/path.rs
@@ -2154,6 +2154,13 @@ pub struct Path {
 #[stable(since = "1.7.0", feature = "strip_prefix")]
 pub struct StripPrefixError(());
 
+/// An error returned from [`Path::normalize_lexically`] if a `..` parent reference
+/// would escape the path.
+#[unstable(feature = "normalize_lexically", issue = "134694")]
+#[derive(Debug, PartialEq)]
+#[non_exhaustive]
+pub struct NormalizeError;
+
 impl Path {
     // The following (private!) function allows construction of a path from a u8
     // slice, which is only safe when it is known to follow the OsStr encoding.
@@ -2739,15 +2746,30 @@ impl Path {
     /// # Examples
     ///
     /// ```
-    /// use std::path::{Path, PathBuf};
+    /// use std::path::Path;
     ///
     /// let path = Path::new("foo.rs");
-    /// assert_eq!(path.with_extension("txt"), PathBuf::from("foo.txt"));
+    /// assert_eq!(path.with_extension("txt"), Path::new("foo.txt"));
+    /// assert_eq!(path.with_extension(""), Path::new("foo"));
+    /// ```
+    ///
+    /// Handling multiple extensions:
+    ///
+    /// ```
+    /// use std::path::Path;
     ///
     /// let path = Path::new("foo.tar.gz");
-    /// assert_eq!(path.with_extension(""), PathBuf::from("foo.tar"));
-    /// assert_eq!(path.with_extension("xz"), PathBuf::from("foo.tar.xz"));
-    /// assert_eq!(path.with_extension("").with_extension("txt"), PathBuf::from("foo.txt"));
+    /// assert_eq!(path.with_extension("xz"), Path::new("foo.tar.xz"));
+    /// assert_eq!(path.with_extension("").with_extension("txt"), Path::new("foo.txt"));
+    /// ```
+    ///
+    /// Adding an extension where one did not exist:
+    ///
+    /// ```
+    /// use std::path::Path;
+    ///
+    /// let path = Path::new("foo");
+    /// assert_eq!(path.with_extension("rs"), Path::new("foo.rs"));
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn with_extension<S: AsRef<OsStr>>(&self, extension: S) -> PathBuf {
@@ -2961,6 +2983,67 @@ impl Path {
         fs::canonicalize(self)
     }
 
+    /// Normalize a path, including `..` without traversing the filesystem.
+    ///
+    /// Returns an error if normalization would leave leading `..` components.
+    ///
+    /// <div class="warning">
+    ///
+    /// This function always resolves `..` to the "lexical" parent.
+    /// That is "a/b/../c" will always resolve to `a/c` which can change the meaning of the path.
+    /// In particular, `a/c` and `a/b/../c` are distinct on many systems because `b` may be a symbolic link, so its parent isn’t `a`.
+    ///
+    /// </div>
+    ///
+    /// [`path::absolute`](absolute) is an alternative that preserves `..`.
+    /// Or [`Path::canonicalize`] can be used to resolve any `..` by querying the filesystem.
+    #[unstable(feature = "normalize_lexically", issue = "134694")]
+    pub fn normalize_lexically(&self) -> Result<PathBuf, NormalizeError> {
+        let mut lexical = PathBuf::new();
+        let mut iter = self.components().peekable();
+
+        // Find the root, if any, and add it to the lexical path.
+        // Here we treat the Windows path "C:\" as a single "root" even though
+        // `components` splits it into two: (Prefix, RootDir).
+        let root = match iter.peek() {
+            Some(Component::ParentDir) => return Err(NormalizeError),
+            Some(p @ Component::RootDir) | Some(p @ Component::CurDir) => {
+                lexical.push(p);
+                iter.next();
+                lexical.as_os_str().len()
+            }
+            Some(Component::Prefix(prefix)) => {
+                lexical.push(prefix.as_os_str());
+                iter.next();
+                if let Some(p @ Component::RootDir) = iter.peek() {
+                    lexical.push(p);
+                    iter.next();
+                }
+                lexical.as_os_str().len()
+            }
+            None => return Ok(PathBuf::new()),
+            Some(Component::Normal(_)) => 0,
+        };
+
+        for component in iter {
+            match component {
+                Component::RootDir => unreachable!(),
+                Component::Prefix(_) => return Err(NormalizeError),
+                Component::CurDir => continue,
+                Component::ParentDir => {
+                    // It's an error if ParentDir causes us to go above the "root".
+                    if lexical.as_os_str().len() == root {
+                        return Err(NormalizeError);
+                    } else {
+                        lexical.pop();
+                    }
+                }
+                Component::Normal(path) => lexical.push(path),
+            }
+        }
+        Ok(lexical)
+    }
+
     /// Reads a symbolic link, returning the file that the link points to.
     ///
     /// This is an alias to [`fs::read_link`].
@@ -3502,6 +3585,15 @@ impl Error for StripPrefixError {
     }
 }
 
+#[unstable(feature = "normalize_lexically", issue = "134694")]
+impl fmt::Display for NormalizeError {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        f.write_str("parent reference `..` points outside of base directory")
+    }
+}
+#[unstable(feature = "normalize_lexically", issue = "134694")]
+impl Error for NormalizeError {}
+
 /// Makes the path absolute without accessing the filesystem.
 ///
 /// If the path is relative, the current directory is used as the base directory.
diff --git a/library/std/src/sync/once_lock.rs b/library/std/src/sync/once_lock.rs
index 324b5451873..a5c3a6c46a4 100644
--- a/library/std/src/sync/once_lock.rs
+++ b/library/std/src/sync/once_lock.rs
@@ -159,8 +159,11 @@ impl<T> OnceLock<T> {
 
     /// Gets the mutable reference to the underlying value.
     ///
-    /// Returns `None` if the cell is uninitialized, or being initialized.
-    /// This method never blocks.
+    /// Returns `None` if the cell is uninitialized.
+    ///
+    /// This method never blocks. Since it borrows the `OnceLock` mutably,
+    /// it is statically guaranteed that no active borrows to the `OnceLock`
+    /// exist, including from other threads.
     #[inline]
     #[stable(feature = "once_cell", since = "1.70.0")]
     pub fn get_mut(&mut self) -> Option<&mut T> {
@@ -315,7 +318,9 @@ impl<T> OnceLock<T> {
     /// Gets the mutable reference of the contents of the cell, initializing
     /// it to `f()` if the cell was uninitialized.
     ///
-    /// This method never blocks.
+    /// This method never blocks. Since it borrows the `OnceLock` mutably,
+    /// it is statically guaranteed that no active borrows to the `OnceLock`
+    /// exist, including from other threads.
     ///
     /// # Panics
     ///
@@ -405,7 +410,9 @@ impl<T> OnceLock<T> {
     /// it to `f()` if the cell was uninitialized. If the cell was uninitialized
     /// and `f()` failed, an error is returned.
     ///
-    /// This method never blocks.
+    /// This method never blocks. Since it borrows the `OnceLock` mutably,
+    /// it is statically guaranteed that no active borrows to the `OnceLock`
+    /// exist, including from other threads.
     ///
     /// # Panics
     ///
@@ -469,7 +476,8 @@ impl<T> OnceLock<T> {
     ///
     /// Has no effect and returns `None` if the `OnceLock` was uninitialized.
     ///
-    /// Safety is guaranteed by requiring a mutable reference.
+    /// Since this method borrows the `OnceLock` mutably, it is statically guaranteed that
+    /// no active borrows to the `OnceLock` exist, including from other threads.
     ///
     /// # Examples
     ///
diff --git a/library/std/src/sync/poison/mutex.rs b/library/std/src/sync/poison/mutex.rs
index 1c29c619edc..30325be685c 100644
--- a/library/std/src/sync/poison/mutex.rs
+++ b/library/std/src/sync/poison/mutex.rs
@@ -608,6 +608,17 @@ impl<T: ?Sized> Mutex<T> {
         let data = self.data.get_mut();
         poison::map_result(self.poison.borrow(), |()| data)
     }
+
+    /// Returns a raw pointer to the underlying data.
+    ///
+    /// The returned pointer is always non-null and properly aligned, but it is
+    /// the user's responsibility to ensure that any reads and writes through it
+    /// are properly synchronized to avoid data races, and that it is not read
+    /// or written through after the mutex is dropped.
+    #[unstable(feature = "mutex_data_ptr", issue = "140368")]
+    pub fn data_ptr(&self) -> *mut T {
+        self.data.get()
+    }
 }
 
 #[stable(feature = "mutex_from", since = "1.24.0")]
diff --git a/library/std/src/sync/poison/rwlock.rs b/library/std/src/sync/poison/rwlock.rs
index 6976c0a64e2..a060e2ea57a 100644
--- a/library/std/src/sync/poison/rwlock.rs
+++ b/library/std/src/sync/poison/rwlock.rs
@@ -634,6 +634,17 @@ impl<T: ?Sized> RwLock<T> {
         let data = self.data.get_mut();
         poison::map_result(self.poison.borrow(), |()| data)
     }
+
+    /// Returns a raw pointer to the underlying data.
+    ///
+    /// The returned pointer is always non-null and properly aligned, but it is
+    /// the user's responsibility to ensure that any reads and writes through it
+    /// are properly synchronized to avoid data races, and that it is not read
+    /// or written through after the lock is dropped.
+    #[unstable(feature = "rwlock_data_ptr", issue = "140368")]
+    pub fn data_ptr(&self) -> *mut T {
+        self.data.get()
+    }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
diff --git a/library/std/src/sync/reentrant_lock.rs b/library/std/src/sync/reentrant_lock.rs
index 96a4cf12659..727252f03a2 100644
--- a/library/std/src/sync/reentrant_lock.rs
+++ b/library/std/src/sync/reentrant_lock.rs
@@ -349,6 +349,17 @@ impl<T: ?Sized> ReentrantLock<T> {
         }
     }
 
+    /// Returns a raw pointer to the underlying data.
+    ///
+    /// The returned pointer is always non-null and properly aligned, but it is
+    /// the user's responsibility to ensure that any reads through it are
+    /// properly synchronized to avoid data races, and that it is not read
+    /// through after the lock is dropped.
+    #[unstable(feature = "reentrant_lock_data_ptr", issue = "140368")]
+    pub fn data_ptr(&self) -> *const T {
+        &raw const self.data
+    }
+
     unsafe fn increment_lock_count(&self) -> Option<()> {
         unsafe {
             *self.lock_count.get() = (*self.lock_count.get()).checked_add(1)?;
diff --git a/library/std/src/sys/fs/windows.rs b/library/std/src/sys/fs/windows.rs
index 9039fd00f5d..d01a572ac73 100644
--- a/library/std/src/sys/fs/windows.rs
+++ b/library/std/src/sys/fs/windows.rs
@@ -415,10 +415,7 @@ impl File {
 
         match result {
             Ok(_) => Ok(()),
-            Err(err)
-                if err.raw_os_error() == Some(c::ERROR_IO_PENDING as i32)
-                    || err.raw_os_error() == Some(c::ERROR_LOCK_VIOLATION as i32) =>
-            {
+            Err(err) if err.raw_os_error() == Some(c::ERROR_LOCK_VIOLATION as i32) => {
                 Err(TryLockError::WouldBlock)
             }
             Err(err) => Err(TryLockError::Error(err)),
@@ -440,10 +437,7 @@ impl File {
 
         match result {
             Ok(_) => Ok(()),
-            Err(err)
-                if err.raw_os_error() == Some(c::ERROR_IO_PENDING as i32)
-                    || err.raw_os_error() == Some(c::ERROR_LOCK_VIOLATION as i32) =>
-            {
+            Err(err) if err.raw_os_error() == Some(c::ERROR_LOCK_VIOLATION as i32) => {
                 Err(TryLockError::WouldBlock)
             }
             Err(err) => Err(TryLockError::Error(err)),
diff --git a/library/std/src/sys/os_str/wtf8.rs b/library/std/src/sys/os_str/wtf8.rs
index 5174ea65d0c..892bd2e3de6 100644
--- a/library/std/src/sys/os_str/wtf8.rs
+++ b/library/std/src/sys/os_str/wtf8.rs
@@ -215,9 +215,9 @@ impl Buf {
     /// The slice must be valid for the platform encoding (as described in
     /// [`Slice::from_encoded_bytes_unchecked`]).
     ///
-    /// This bypasses the WTF-8 surrogate joining, so `self` must not end with a
-    /// leading surrogate half and `other` must not start with with a trailing
-    /// surrogate half.
+    /// This bypasses the WTF-8 surrogate joining, so either `self` must not
+    /// end with a leading surrogate half, or `other` must not start with a
+    /// trailing surrogate half.
     #[inline]
     pub unsafe fn extend_from_slice_unchecked(&mut self, other: &[u8]) {
         self.inner.extend_from_slice(other);
diff --git a/library/std/src/sys/sync/mutex/futex.rs b/library/std/src/sys/sync/mutex/futex.rs
index ce9b2daa5f8..70e2ea9f605 100644
--- a/library/std/src/sys/sync/mutex/futex.rs
+++ b/library/std/src/sys/sync/mutex/futex.rs
@@ -19,11 +19,15 @@ impl Mutex {
     }
 
     #[inline]
+    // Make this a diagnostic item for Miri's concurrency model checker.
+    #[cfg_attr(not(test), rustc_diagnostic_item = "sys_mutex_try_lock")]
     pub fn try_lock(&self) -> bool {
         self.futex.compare_exchange(UNLOCKED, LOCKED, Acquire, Relaxed).is_ok()
     }
 
     #[inline]
+    // Make this a diagnostic item for Miri's concurrency model checker.
+    #[cfg_attr(not(test), rustc_diagnostic_item = "sys_mutex_lock")]
     pub fn lock(&self) {
         if self.futex.compare_exchange(UNLOCKED, LOCKED, Acquire, Relaxed).is_err() {
             self.lock_contended();
@@ -80,6 +84,8 @@ impl Mutex {
     }
 
     #[inline]
+    // Make this a diagnostic item for Miri's concurrency model checker.
+    #[cfg_attr(not(test), rustc_diagnostic_item = "sys_mutex_unlock")]
     pub unsafe fn unlock(&self) {
         if self.futex.swap(UNLOCKED, Release) == CONTENDED {
             // We only wake up one thread. When that thread locks the mutex, it
diff --git a/library/std/src/sys/sync/mutex/pthread.rs b/library/std/src/sys/sync/mutex/pthread.rs
index 75b4b9c6dad..a7a3b47d0ec 100644
--- a/library/std/src/sys/sync/mutex/pthread.rs
+++ b/library/std/src/sys/sync/mutex/pthread.rs
@@ -6,7 +6,7 @@ use crate::sys::pal::sync as pal;
 use crate::sys::sync::OnceBox;
 
 pub struct Mutex {
-    pub pal: OnceBox<pal::Mutex>,
+    pub(in crate::sys::sync) pal: OnceBox<pal::Mutex>,
 }
 
 impl Mutex {
@@ -28,6 +28,8 @@ impl Mutex {
     }
 
     #[inline]
+    // Make this a diagnostic item for Miri's concurrency model checker.
+    #[cfg_attr(not(test), rustc_diagnostic_item = "sys_mutex_lock")]
     pub fn lock(&self) {
         // SAFETY: we call `init` above, therefore reentrant locking is safe.
         // In `drop` we ensure that the mutex is not destroyed while locked.
@@ -35,6 +37,8 @@ impl Mutex {
     }
 
     #[inline]
+    // Make this a diagnostic item for Miri's concurrency model checker.
+    #[cfg_attr(not(test), rustc_diagnostic_item = "sys_mutex_unlock")]
     pub unsafe fn unlock(&self) {
         // SAFETY: the mutex can only be locked if it is already initialized
         // and we observed this initialization since we observed the locking.
@@ -42,6 +46,8 @@ impl Mutex {
     }
 
     #[inline]
+    // Make this a diagnostic item for Miri's concurrency model checker.
+    #[cfg_attr(not(test), rustc_diagnostic_item = "sys_mutex_try_lock")]
     pub fn try_lock(&self) -> bool {
         // SAFETY: we call `init` above, therefore reentrant locking is safe.
         // In `drop` we ensure that the mutex is not destroyed while locked.
diff --git a/library/std/src/sys/thread_local/key/unix.rs b/library/std/src/sys/thread_local/key/unix.rs
index 93bd0d1f668..8fa24265e43 100644
--- a/library/std/src/sys/thread_local/key/unix.rs
+++ b/library/std/src/sys/thread_local/key/unix.rs
@@ -25,7 +25,9 @@ pub type Key = libc::pthread_key_t;
 #[inline]
 pub fn create(dtor: Option<unsafe extern "C" fn(*mut u8)>) -> Key {
     let mut key = 0;
-    assert_eq!(unsafe { libc::pthread_key_create(&mut key, mem::transmute(dtor)) }, 0);
+    if unsafe { libc::pthread_key_create(&mut key, mem::transmute(dtor)) } != 0 {
+        rtabort!("out of TLS keys");
+    }
     key
 }
 
diff --git a/library/std/src/sys/thread_local/key/windows.rs b/library/std/src/sys/thread_local/key/windows.rs
index c34c7bc204f..2ff0fd1196e 100644
--- a/library/std/src/sys/thread_local/key/windows.rs
+++ b/library/std/src/sys/thread_local/key/windows.rs
@@ -81,15 +81,10 @@ impl LazyKey {
             } else {
                 let key = unsafe { c::TlsAlloc() };
                 if key == c::TLS_OUT_OF_INDEXES {
-                    // Wakeup the waiting threads before panicking to avoid deadlock.
-                    unsafe {
-                        c::InitOnceComplete(
-                            self.once.get(),
-                            c::INIT_ONCE_INIT_FAILED,
-                            ptr::null_mut(),
-                        );
-                    }
-                    panic!("out of TLS indexes");
+                    // Since we abort the process, there is no need to wake up
+                    // the waiting threads. If this were a panic, the wakeup
+                    // would need to occur first in order to avoid deadlock.
+                    rtabort!("out of TLS indexes");
                 }
 
                 unsafe {
@@ -112,7 +107,9 @@ impl LazyKey {
             // If there is no destructor to clean up, we can use racy initialization.
 
             let key = unsafe { c::TlsAlloc() };
-            assert_ne!(key, c::TLS_OUT_OF_INDEXES, "out of TLS indexes");
+            if key == c::TLS_OUT_OF_INDEXES {
+                rtabort!("out of TLS indexes");
+            }
 
             match self.key.compare_exchange(0, key + 1, AcqRel, Acquire) {
                 Ok(_) => key,
diff --git a/library/std/src/sys/thread_local/native/lazy.rs b/library/std/src/sys/thread_local/native/lazy.rs
index 51294285ba0..b556dd9aa25 100644
--- a/library/std/src/sys/thread_local/native/lazy.rs
+++ b/library/std/src/sys/thread_local/native/lazy.rs
@@ -1,9 +1,9 @@
-use crate::cell::UnsafeCell;
-use crate::hint::unreachable_unchecked;
+use crate::cell::{Cell, UnsafeCell};
+use crate::mem::MaybeUninit;
 use crate::ptr;
 use crate::sys::thread_local::{abort_on_dtor_unwind, destructors};
 
-pub unsafe trait DestroyedState: Sized {
+pub unsafe trait DestroyedState: Sized + Copy {
     fn register_dtor<T>(s: &Storage<T, Self>);
 }
 
@@ -19,15 +19,17 @@ unsafe impl DestroyedState for () {
     }
 }
 
-enum State<T, D> {
-    Initial,
-    Alive(T),
+#[derive(Copy, Clone)]
+enum State<D> {
+    Uninitialized,
+    Alive,
     Destroyed(D),
 }
 
 #[allow(missing_debug_implementations)]
 pub struct Storage<T, D> {
-    state: UnsafeCell<State<T, D>>,
+    state: Cell<State<D>>,
+    value: UnsafeCell<MaybeUninit<T>>,
 }
 
 impl<T, D> Storage<T, D>
@@ -35,7 +37,10 @@ where
     D: DestroyedState,
 {
     pub const fn new() -> Storage<T, D> {
-        Storage { state: UnsafeCell::new(State::Initial) }
+        Storage {
+            state: Cell::new(State::Uninitialized),
+            value: UnsafeCell::new(MaybeUninit::uninit()),
+        }
     }
 
     /// Gets a pointer to the TLS value, potentially initializing it with the
@@ -49,35 +54,49 @@ where
     /// The `self` reference must remain valid until the TLS destructor is run.
     #[inline]
     pub unsafe fn get_or_init(&self, i: Option<&mut Option<T>>, f: impl FnOnce() -> T) -> *const T {
-        let state = unsafe { &*self.state.get() };
-        match state {
-            State::Alive(v) => v,
-            State::Destroyed(_) => ptr::null(),
-            State::Initial => unsafe { self.initialize(i, f) },
+        if let State::Alive = self.state.get() {
+            self.value.get().cast()
+        } else {
+            unsafe { self.get_or_init_slow(i, f) }
         }
     }
 
+    /// # Safety
+    /// The `self` reference must remain valid until the TLS destructor is run.
     #[cold]
-    unsafe fn initialize(&self, i: Option<&mut Option<T>>, f: impl FnOnce() -> T) -> *const T {
-        // Perform initialization
+    unsafe fn get_or_init_slow(
+        &self,
+        i: Option<&mut Option<T>>,
+        f: impl FnOnce() -> T,
+    ) -> *const T {
+        match self.state.get() {
+            State::Uninitialized => {}
+            State::Alive => return self.value.get().cast(),
+            State::Destroyed(_) => return ptr::null(),
+        }
 
         let v = i.and_then(Option::take).unwrap_or_else(f);
 
-        let old = unsafe { self.state.get().replace(State::Alive(v)) };
-        match old {
+        // SAFETY: we cannot be inside a `LocalKey::with` scope, as the initializer
+        // has already returned and the next scope only starts after we return
+        // the pointer. Therefore, there can be no references to the old value,
+        // even if it was initialized. Thus because we are !Sync we have exclusive
+        // access to self.value and may replace it.
+        let mut old_value = unsafe { self.value.get().replace(MaybeUninit::new(v)) };
+        match self.state.replace(State::Alive) {
             // If the variable is not being recursively initialized, register
             // the destructor. This might be a noop if the value does not need
             // destruction.
-            State::Initial => D::register_dtor(self),
-            // Else, drop the old value. This might be changed to a panic.
-            val => drop(val),
-        }
+            State::Uninitialized => D::register_dtor(self),
 
-        // SAFETY: the state was just set to `Alive`
-        unsafe {
-            let State::Alive(v) = &*self.state.get() else { unreachable_unchecked() };
-            v
+            // Recursive initialization, we only need to drop the old value
+            // as we've already registered the destructor.
+            State::Alive => unsafe { old_value.assume_init_drop() },
+
+            State::Destroyed(_) => unreachable!(),
         }
+
+        self.value.get().cast()
     }
 }
 
@@ -92,9 +111,12 @@ unsafe extern "C" fn destroy<T>(ptr: *mut u8) {
     // Print a nice abort message if a panic occurs.
     abort_on_dtor_unwind(|| {
         let storage = unsafe { &*(ptr as *const Storage<T, ()>) };
-        // Update the state before running the destructor as it may attempt to
-        // access the variable.
-        let val = unsafe { storage.state.get().replace(State::Destroyed(())) };
-        drop(val);
+        if let State::Alive = storage.state.replace(State::Destroyed(())) {
+            // SAFETY: we ensured the state was Alive so the value was initialized.
+            // We also updated the state to Destroyed to prevent the destructor
+            // from accessing the thread-local variable, as this would violate
+            // the exclusive access provided by &mut T in Drop::drop.
+            unsafe { (*storage.value.get()).assume_init_drop() }
+        }
     })
 }
diff --git a/library/std/tests/path.rs b/library/std/tests/path.rs
index 87e0d226cbd..781855a2d14 100644
--- a/library/std/tests/path.rs
+++ b/library/std/tests/path.rs
@@ -3,7 +3,8 @@
     path_add_extension,
     path_file_prefix,
     maybe_uninit_slice,
-    os_string_pathbuf_leak
+    os_string_pathbuf_leak,
+    normalize_lexically
 )]
 
 use std::clone::CloneToUninit;
@@ -2007,3 +2008,56 @@ fn test_embedded_newline() {
     assert_eq!(path.file_name(), Some(OsStr::new("foo\nbar")));
     assert_eq!(path.to_str(), Some("foo\nbar"));
 }
+
+#[test]
+fn normalize_lexically() {
+    #[track_caller]
+    fn check_ok(a: &str, b: &str) {
+        assert_eq!(Path::new(a).normalize_lexically().unwrap(), PathBuf::from(b));
+    }
+
+    #[track_caller]
+    fn check_err(a: &str) {
+        assert!(Path::new(a).normalize_lexically().is_err());
+    }
+
+    // Relative paths
+    check_ok("a", "a");
+    check_ok("./a", "./a");
+    check_ok("a/b/c", "a/b/c");
+    check_ok("a/././b/./c/.", "a/b/c");
+    check_ok("a/../c", "c");
+    check_ok("./a/b", "./a/b");
+    check_ok("a/../b/c/..", "b");
+
+    check_err("..");
+    check_err("../..");
+    check_err("a/../..");
+    check_err("a/../../b");
+    check_err("a/../../b/c");
+    check_err("a/../b/../..");
+
+    // Check we don't escape the root or prefix
+    #[cfg(unix)]
+    {
+        check_err("/..");
+        check_err("/a/../..");
+    }
+    #[cfg(windows)]
+    {
+        check_err(r"C:\..");
+        check_err(r"C:\a\..\..");
+
+        check_err(r"C:..");
+        check_err(r"C:a\..\..");
+
+        check_err(r"\\server\share\..");
+        check_err(r"\\server\share\a\..\..");
+
+        check_err(r"\..");
+        check_err(r"\a\..\..");
+
+        check_err(r"\\?\UNC\server\share\..");
+        check_err(r"\\?\UNC\server\share\a\..\..");
+    }
+}
diff --git a/rust-bors.toml b/rust-bors.toml
index f27eb239367..fbfaa980f05 100644
--- a/rust-bors.toml
+++ b/rust-bors.toml
@@ -1 +1,2 @@
-timeout = 14400
+# 6 hours timeout for CI builds
+timeout = 21600
diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py
index 42ad14a81d0..c60c6b8db64 100644
--- a/src/bootstrap/bootstrap.py
+++ b/src/bootstrap/bootstrap.py
@@ -1118,7 +1118,6 @@ class RustBuild(object):
         if "RUSTFLAGS_BOOTSTRAP" in env:
             env["RUSTFLAGS"] += " " + env["RUSTFLAGS_BOOTSTRAP"]
 
-        env["PATH"] = os.path.join(self.bin_root(), "bin") + os.pathsep + env["PATH"]
         if not os.path.isfile(self.cargo()):
             raise Exception("no cargo executable found at `{}`".format(self.cargo()))
         args = [
diff --git a/src/bootstrap/defaults/bootstrap.library.toml b/src/bootstrap/defaults/bootstrap.library.toml
index b43796d6f20..895e50b9a20 100644
--- a/src/bootstrap/defaults/bootstrap.library.toml
+++ b/src/bootstrap/defaults/bootstrap.library.toml
@@ -1,17 +1,19 @@
 # These defaults are meant for contributors to the standard library and documentation.
 [build]
-# When building the standard library, you almost never want to build the compiler itself.
-build-stage = 0
-test-stage = 0
-bench-stage = 0
+bench-stage = 1
+build-stage = 1
+check-stage = 1
+test-stage = 1
 
 [rust]
 # This greatly increases the speed of rebuilds, especially when there are only minor changes. However, it makes the initial build slightly slower.
 incremental = true
 # Make the compiler and standard library faster to build, at the expense of a ~20% runtime slowdown.
 lto = "off"
-# Download rustc by default for library profile if compiler-affecting
-# directories are not modified. For CI this is disabled.
+# When building the standard library, you almost never want to build the compiler itself.
+#
+# If compiler-affecting directories are not modified, use precompiled rustc to speed up
+# library development by skipping compiler builds.
 download-rustc = "if-unchanged"
 
 [llvm]
diff --git a/src/bootstrap/mk/Makefile.in b/src/bootstrap/mk/Makefile.in
index 08a288170fa..82c05092dfa 100644
--- a/src/bootstrap/mk/Makefile.in
+++ b/src/bootstrap/mk/Makefile.in
@@ -51,16 +51,18 @@ check-aux:
 	$(Q)$(BOOTSTRAP) test --stage 2 \
 		src/tools/cargo \
 		src/tools/cargotest \
-		src/etc/test-float-parse \
+		src/tools/test-float-parse \
 		$(BOOTSTRAP_ARGS)
 	# Run standard library tests in Miri.
-	$(Q)$(BOOTSTRAP) miri --stage 2 \
+	$(Q)MIRIFLAGS="-Zmiri-strict-provenance" \
+		$(BOOTSTRAP) miri --stage 2 \
 		library/coretests \
 		library/alloctests \
 		library/alloc \
 		$(BOOTSTRAP_ARGS) \
 		--no-doc
-	# Some doctests use file system operations to demonstrate dealing with `Result`.
+	# Some doctests use file system operations to demonstrate dealing with `Result`,
+	# so we have to run them with isolation disabled.
 	$(Q)MIRIFLAGS="-Zmiri-disable-isolation" \
 		$(BOOTSTRAP) miri --stage 2 \
 		library/coretests \
@@ -70,22 +72,19 @@ check-aux:
 		--doc
 	# In `std` we cannot test everything, so we skip some modules.
 	$(Q)MIRIFLAGS="-Zmiri-disable-isolation" \
-		$(BOOTSTRAP) miri --stage 2 library/std \
-		$(BOOTSTRAP_ARGS) \
-		--no-doc -- \
-		--skip fs:: --skip net:: --skip process:: --skip sys::fd:: --skip sys::pal::
-	$(Q)MIRIFLAGS="-Zmiri-disable-isolation" \
-		$(BOOTSTRAP) miri --stage 2 library/std \
+		$(BOOTSTRAP) miri --stage 2 \
+		library/std \
 		$(BOOTSTRAP_ARGS) \
-		--doc -- \
+		-- \
 		--skip fs:: --skip net:: --skip process:: --skip sys::fd:: --skip sys::pal::
 	# Also test some very target-specific modules on other targets
 	# (making sure to cover an i686 target as well).
 	$(Q)MIRIFLAGS="-Zmiri-disable-isolation" BOOTSTRAP_SKIP_TARGET_SANITY=1 \
-		$(BOOTSTRAP) miri --stage 2 library/std \
-		$(BOOTSTRAP_ARGS) \
+		$(BOOTSTRAP) miri --stage 2 \
+		library/std \
 		--target aarch64-apple-darwin,i686-pc-windows-msvc \
-		--no-doc -- \
+		$(BOOTSTRAP_ARGS) \
+		-- \
 		time:: sync:: thread:: env::
 dist:
 	$(Q)$(BOOTSTRAP) dist $(BOOTSTRAP_ARGS)
diff --git a/src/bootstrap/src/bin/rustc.rs b/src/bootstrap/src/bin/rustc.rs
index 374884d8a9a..0671a8467e8 100644
--- a/src/bootstrap/src/bin/rustc.rs
+++ b/src/bootstrap/src/bin/rustc.rs
@@ -120,14 +120,12 @@ fn main() {
     };
     cmd.args(&args).env(dylib_path_var(), env::join_paths(&dylib_path).unwrap());
 
-    if let Some(crate_name) = crate_name {
-        if let Some(target) = env::var_os("RUSTC_TIME") {
-            if target == "all"
-                || target.into_string().unwrap().split(',').any(|c| c.trim() == crate_name)
-            {
-                cmd.arg("-Ztime-passes");
-            }
-        }
+    if let Some(crate_name) = crate_name
+        && let Some(target) = env::var_os("RUSTC_TIME")
+        && (target == "all"
+            || target.into_string().unwrap().split(',').any(|c| c.trim() == crate_name))
+    {
+        cmd.arg("-Ztime-passes");
     }
 
     // Print backtrace in case of ICE
@@ -242,10 +240,10 @@ fn main() {
         }
     }
 
-    if env::var_os("RUSTC_BOLT_LINK_FLAGS").is_some() {
-        if let Some("rustc_driver") = crate_name {
-            cmd.arg("-Clink-args=-Wl,-q");
-        }
+    if env::var_os("RUSTC_BOLT_LINK_FLAGS").is_some()
+        && let Some("rustc_driver") = crate_name
+    {
+        cmd.arg("-Clink-args=-Wl,-q");
     }
 
     let is_test = args.iter().any(|a| a == "--test");
@@ -282,25 +280,24 @@ fn main() {
         (child, status)
     };
 
-    if env::var_os("RUSTC_PRINT_STEP_TIMINGS").is_some()
-        || env::var_os("RUSTC_PRINT_STEP_RUSAGE").is_some()
+    if (env::var_os("RUSTC_PRINT_STEP_TIMINGS").is_some()
+        || env::var_os("RUSTC_PRINT_STEP_RUSAGE").is_some())
+        && let Some(crate_name) = crate_name
     {
-        if let Some(crate_name) = crate_name {
-            let dur = start.elapsed();
-            // If the user requested resource usage data, then
-            // include that in addition to the timing output.
-            let rusage_data =
-                env::var_os("RUSTC_PRINT_STEP_RUSAGE").and_then(|_| format_rusage_data(child));
-            eprintln!(
-                "[RUSTC-TIMING] {} test:{} {}.{:03}{}{}",
-                crate_name,
-                is_test,
-                dur.as_secs(),
-                dur.subsec_millis(),
-                if rusage_data.is_some() { " " } else { "" },
-                rusage_data.unwrap_or_default(),
-            );
-        }
+        let dur = start.elapsed();
+        // If the user requested resource usage data, then
+        // include that in addition to the timing output.
+        let rusage_data =
+            env::var_os("RUSTC_PRINT_STEP_RUSAGE").and_then(|_| format_rusage_data(child));
+        eprintln!(
+            "[RUSTC-TIMING] {} test:{} {}.{:03}{}{}",
+            crate_name,
+            is_test,
+            dur.as_secs(),
+            dur.subsec_millis(),
+            if rusage_data.is_some() { " " } else { "" },
+            rusage_data.unwrap_or_default(),
+        );
     }
 
     if status.success() {
diff --git a/src/bootstrap/src/core/build_steps/check.rs b/src/bootstrap/src/core/build_steps/check.rs
index fa848c492b4..833cbedd5cf 100644
--- a/src/bootstrap/src/core/build_steps/check.rs
+++ b/src/bootstrap/src/core/build_steps/check.rs
@@ -1,5 +1,6 @@
 //! Implementation of compiling the compiler and standard library, in "check"-based modes.
 
+use crate::core::build_steps::compile;
 use crate::core::build_steps::compile::{
     add_to_sysroot, run_cargo, rustc_cargo, rustc_cargo_env, std_cargo, std_crates_for_run_make,
 };
@@ -30,6 +31,8 @@ pub struct Std {
 }
 
 impl Std {
+    const CRATE_OR_DEPS: &[&str] = &["sysroot", "coretests", "alloctests"];
+
     pub fn new(target: TargetSelection) -> Self {
         Self { target, crates: vec![], override_build_kind: None }
     }
@@ -45,10 +48,19 @@ impl Step for Std {
     const DEFAULT: bool = true;
 
     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
-        run.crate_or_deps("sysroot")
-            .crate_or_deps("coretests")
-            .crate_or_deps("alloctests")
-            .path("library")
+        let builder = run.builder;
+        let stage = if builder.config.is_explicit_stage() || builder.top_stage >= 1 {
+            builder.top_stage
+        } else {
+            1
+        };
+
+        let mut run = run;
+        for c in Std::CRATE_OR_DEPS {
+            run = run.crate_or_deps(c);
+        }
+
+        run.path("library").default_condition(stage != 0)
     }
 
     fn make_run(run: RunConfig<'_>) {
@@ -59,8 +71,33 @@ impl Step for Std {
     fn run(self, builder: &Builder<'_>) {
         builder.require_submodule("library/stdarch", None);
 
+        let stage = if builder.config.is_explicit_stage() || builder.top_stage >= 1 {
+            builder.top_stage
+        } else {
+            1
+        };
+
         let target = self.target;
-        let compiler = builder.compiler(builder.top_stage, builder.config.build);
+        let compiler = builder.compiler(stage, builder.config.build);
+
+        if stage == 0 {
+            let mut is_explicitly_called =
+                builder.paths.iter().any(|p| p.starts_with("library") || p.starts_with("std"));
+
+            if !is_explicitly_called {
+                for c in Std::CRATE_OR_DEPS {
+                    is_explicitly_called = builder.paths.iter().any(|p| p.starts_with(c));
+                }
+            }
+
+            if is_explicitly_called {
+                eprintln!("WARNING: stage 0 std is precompiled and does nothing during `x check`.");
+            }
+
+            // Reuse the stage0 libstd
+            builder.ensure(compile::Std::new(compiler, target));
+            return;
+        }
 
         let mut cargo = builder::Cargo::new(
             builder,
@@ -84,6 +121,7 @@ impl Step for Std {
         let _guard = builder.msg_check(
             format_args!("library artifacts{}", crate_description(&self.crates)),
             target,
+            Some(stage),
         );
 
         let stamp = build_stamp::libstd_stamp(builder, compiler, target).with_prefix("check");
@@ -136,7 +174,7 @@ impl Step for Std {
         }
 
         let stamp = build_stamp::libstd_stamp(builder, compiler, target).with_prefix("check-test");
-        let _guard = builder.msg_check("library test/bench/example targets", target);
+        let _guard = builder.msg_check("library test/bench/example targets", target, Some(stage));
         run_cargo(builder, cargo, builder.config.free_args.clone(), &stamp, vec![], true, false);
     }
 }
@@ -237,6 +275,7 @@ impl Step for Rustc {
         let _guard = builder.msg_check(
             format_args!("compiler artifacts{}", crate_description(&self.crates)),
             target,
+            None,
         );
 
         let stamp = build_stamp::librustc_stamp(builder, compiler, target).with_prefix("check");
@@ -297,7 +336,7 @@ impl Step for CodegenBackend {
             .arg(builder.src.join(format!("compiler/rustc_codegen_{backend}/Cargo.toml")));
         rustc_cargo_env(builder, &mut cargo, target, compiler.stage);
 
-        let _guard = builder.msg_check(backend, target);
+        let _guard = builder.msg_check(backend, target, None);
 
         let stamp = build_stamp::codegen_backend_stamp(builder, compiler, target, backend)
             .with_prefix("check");
@@ -364,7 +403,7 @@ impl Step for RustAnalyzer {
         let stamp = BuildStamp::new(&builder.cargo_out(compiler, Mode::ToolRustc, target))
             .with_prefix("rust-analyzer-check");
 
-        let _guard = builder.msg_check("rust-analyzer artifacts", target);
+        let _guard = builder.msg_check("rust-analyzer artifacts", target, None);
         run_cargo(builder, cargo, builder.config.free_args.clone(), &stamp, vec![], true, false);
     }
 }
@@ -427,7 +466,7 @@ impl Step for Compiletest {
         let stamp = BuildStamp::new(&builder.cargo_out(compiler, mode, self.target))
             .with_prefix("compiletest-check");
 
-        let _guard = builder.msg_check("compiletest artifacts", self.target);
+        let _guard = builder.msg_check("compiletest artifacts", self.target, None);
         run_cargo(builder, cargo, builder.config.free_args.clone(), &stamp, vec![], true, false);
     }
 }
@@ -505,7 +544,7 @@ fn run_tool_check_step(
     let stamp = BuildStamp::new(&builder.cargo_out(compiler, Mode::ToolRustc, target))
         .with_prefix(&format!("{}-check", step_type_name.to_lowercase()));
 
-    let _guard = builder.msg_check(format!("{display_name} artifacts"), target);
+    let _guard = builder.msg_check(format!("{display_name} artifacts"), target, None);
     run_cargo(builder, cargo, builder.config.free_args.clone(), &stamp, vec![], true, false);
 }
 
@@ -519,7 +558,7 @@ tool_check_step!(Miri { path: "src/tools/miri" });
 tool_check_step!(CargoMiri { path: "src/tools/miri/cargo-miri" });
 tool_check_step!(Rustfmt { path: "src/tools/rustfmt" });
 tool_check_step!(MiroptTestTools { path: "src/tools/miropt-test-tools" });
-tool_check_step!(TestFloatParse { path: "src/etc/test-float-parse" });
+tool_check_step!(TestFloatParse { path: "src/tools/test-float-parse" });
 tool_check_step!(FeaturesStatusDump { path: "src/tools/features-status-dump" });
 
 tool_check_step!(Bootstrap { path: "src/bootstrap", default: false });
diff --git a/src/bootstrap/src/core/build_steps/clippy.rs b/src/bootstrap/src/core/build_steps/clippy.rs
index 07fd51919d4..0652c08ff49 100644
--- a/src/bootstrap/src/core/build_steps/clippy.rs
+++ b/src/bootstrap/src/core/build_steps/clippy.rs
@@ -207,16 +207,18 @@ impl Step for Rustc {
         let compiler = builder.compiler(builder.top_stage, builder.config.build);
         let target = self.target;
 
-        if compiler.stage != 0 {
-            // If we're not in stage 0, then we won't have a std from the beta
-            // compiler around. That means we need to make sure there's one in
-            // the sysroot for the compiler to find. Otherwise, we're going to
-            // fail when building crates that need to generate code (e.g., build
-            // scripts and their dependencies).
-            builder.ensure(compile::Std::new(compiler, compiler.host));
-            builder.ensure(compile::Std::new(compiler, target));
-        } else {
-            builder.ensure(check::Std::new(target).build_kind(Some(Kind::Check)));
+        if !builder.download_rustc() {
+            if compiler.stage != 0 {
+                // If we're not in stage 0, then we won't have a std from the beta
+                // compiler around. That means we need to make sure there's one in
+                // the sysroot for the compiler to find. Otherwise, we're going to
+                // fail when building crates that need to generate code (e.g., build
+                // scripts and their dependencies).
+                builder.ensure(compile::Std::new(compiler, compiler.host));
+                builder.ensure(compile::Std::new(compiler, target));
+            } else {
+                builder.ensure(check::Std::new(target).build_kind(Some(Kind::Check)));
+            }
         }
 
         let mut cargo = builder::Cargo::new(
@@ -286,7 +288,9 @@ macro_rules! lint_any {
                 let compiler = builder.compiler(builder.top_stage, builder.config.build);
                 let target = self.target;
 
-                builder.ensure(check::Rustc::new(target, builder).build_kind(Some(Kind::Check)));
+                if !builder.download_rustc() {
+                    builder.ensure(check::Rustc::new(target, builder).build_kind(Some(Kind::Check)));
+                };
 
                 let cargo = prepare_tool_cargo(
                     builder,
@@ -351,7 +355,7 @@ lint_any!(
     Rustfmt, "src/tools/rustfmt", "rustfmt";
     RustInstaller, "src/tools/rust-installer", "rust-installer";
     Tidy, "src/tools/tidy", "tidy";
-    TestFloatParse, "src/etc/test-float-parse", "test-float-parse";
+    TestFloatParse, "src/tools/test-float-parse", "test-float-parse";
 );
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs
index d5ea96b43f5..37d53ce476a 100644
--- a/src/bootstrap/src/core/build_steps/compile.rs
+++ b/src/bootstrap/src/core/build_steps/compile.rs
@@ -147,14 +147,27 @@ impl Step for Std {
     )]
     fn run(self, builder: &Builder<'_>) {
         let target = self.target;
-        let compiler = self.compiler;
+
+        // We already have std ready to be used for stage 0.
+        if self.compiler.stage == 0 {
+            let compiler = self.compiler;
+            builder.ensure(StdLink::from_std(self, compiler));
+
+            return;
+        }
+
+        let compiler = if builder.download_rustc() && self.force_recompile {
+            // When there are changes in the library tree with CI-rustc, we want to build
+            // the stageN library and that requires using stageN-1 compiler.
+            builder.compiler(self.compiler.stage.saturating_sub(1), builder.config.build)
+        } else {
+            self.compiler
+        };
 
         // When using `download-rustc`, we already have artifacts for the host available. Don't
         // recompile them.
-        if builder.download_rustc() && builder.config.is_host_target(target)
-            // NOTE: the beta compiler may generate different artifacts than the downloaded compiler, so
-            // its artifacts can't be reused.
-            && compiler.stage != 0
+        if builder.download_rustc()
+            && builder.config.is_host_target(target)
             && !self.force_recompile
         {
             let sysroot = builder.ensure(Sysroot { compiler, force_recompile: false });
@@ -189,7 +202,13 @@ impl Step for Std {
         let compiler_to_use = builder.compiler_for(compiler.stage, compiler.host, target);
         trace!(?compiler_to_use);
 
-        if compiler_to_use != compiler {
+        if compiler_to_use != compiler
+            // Never uplift std unless we have compiled stage 1; if stage 1 is compiled,
+            // uplift it from there.
+            //
+            // FIXME: improve `fn compiler_for` to avoid adding stage condition here.
+            && compiler.stage > 1
+        {
             trace!(?compiler_to_use, ?compiler, "compiler != compiler_to_use, uplifting library");
 
             builder.ensure(Std::new(compiler_to_use, target));
@@ -222,27 +241,6 @@ impl Step for Std {
 
         target_deps.extend(self.copy_extra_objects(builder, &compiler, target));
 
-        // The LLD wrappers and `rust-lld` are self-contained linking components that can be
-        // necessary to link the stdlib on some targets. We'll also need to copy these binaries to
-        // the `stage0-sysroot` to ensure the linker is found when bootstrapping on such a target.
-        if compiler.stage == 0 && builder.config.is_host_target(compiler.host) {
-            trace!(
-                "(build == host) copying linking components to `stage0-sysroot` for bootstrapping"
-            );
-            // We want to copy the host `bin` folder within the `rustlib` folder in the sysroot.
-            let src_sysroot_bin = builder
-                .rustc_snapshot_sysroot()
-                .join("lib")
-                .join("rustlib")
-                .join(compiler.host)
-                .join("bin");
-            if src_sysroot_bin.exists() {
-                let target_sysroot_bin = builder.sysroot_target_bindir(compiler, target);
-                t!(fs::create_dir_all(&target_sysroot_bin));
-                builder.cp_link_r(&src_sysroot_bin, &target_sysroot_bin);
-            }
-        }
-
         // We build a sysroot for mir-opt tests using the same trick that Miri does: A check build
         // with -Zalways-encode-mir. This frees us from the need to have a target linker, and the
         // fact that this is a check build integrates nicely with run_cargo.
@@ -628,18 +626,18 @@ pub fn std_cargo(builder: &Builder<'_>, target: TargetSelection, stage: u32, car
 
         // Help the libc crate compile by assisting it in finding various
         // sysroot native libraries.
-        if target.contains("musl") {
-            if let Some(p) = builder.musl_libdir(target) {
-                let root = format!("native={}", p.to_str().unwrap());
-                cargo.rustflag("-L").rustflag(&root);
-            }
+        if target.contains("musl")
+            && let Some(p) = builder.musl_libdir(target)
+        {
+            let root = format!("native={}", p.to_str().unwrap());
+            cargo.rustflag("-L").rustflag(&root);
         }
 
-        if target.contains("-wasi") {
-            if let Some(dir) = builder.wasi_libdir(target) {
-                let root = format!("native={}", dir.to_str().unwrap());
-                cargo.rustflag("-L").rustflag(&root);
-            }
+        if target.contains("-wasi")
+            && let Some(dir) = builder.wasi_libdir(target)
+        {
+            let root = format!("native={}", dir.to_str().unwrap());
+            cargo.rustflag("-L").rustflag(&root);
         }
     }
 
@@ -737,7 +735,7 @@ impl Step for StdLink {
         let target = self.target;
 
         // NOTE: intentionally does *not* check `target == builder.build` to avoid having to add the same check in `test::Crate`.
-        let (libdir, hostdir) = if self.force_recompile && builder.download_rustc() {
+        let (libdir, hostdir) = if !self.force_recompile && builder.download_rustc() {
             // NOTE: copies part of `sysroot_libdir` to avoid having to add a new `force_recompile` argument there too
             let lib = builder.sysroot_libdir_relative(self.compiler);
             let sysroot = builder.ensure(crate::core::build_steps::compile::Sysroot {
@@ -753,23 +751,16 @@ impl Step for StdLink {
             (libdir, hostdir)
         };
 
-        add_to_sysroot(
-            builder,
-            &libdir,
-            &hostdir,
-            &build_stamp::libstd_stamp(builder, compiler, target),
-        );
+        let is_downloaded_beta_stage0 = builder
+            .build
+            .config
+            .initial_rustc
+            .starts_with(builder.out.join(compiler.host).join("stage0/bin"));
 
         // Special case for stage0, to make `rustup toolchain link` and `x dist --stage 0`
         // work for stage0-sysroot. We only do this if the stage0 compiler comes from beta,
         // and is not set to a custom path.
-        if compiler.stage == 0
-            && builder
-                .build
-                .config
-                .initial_rustc
-                .starts_with(builder.out.join(compiler.host).join("stage0/bin"))
-        {
+        if compiler.stage == 0 && is_downloaded_beta_stage0 {
             // Copy bin files from stage0/bin to stage0-sysroot/bin
             let sysroot = builder.out.join(compiler.host).join("stage0-sysroot");
 
@@ -779,21 +770,9 @@ impl Step for StdLink {
             t!(fs::create_dir_all(&sysroot_bin_dir));
             builder.cp_link_r(&stage0_bin_dir, &sysroot_bin_dir);
 
-            // Copy all files from stage0/lib to stage0-sysroot/lib
             let stage0_lib_dir = builder.out.join(host).join("stage0/lib");
-            if let Ok(files) = fs::read_dir(stage0_lib_dir) {
-                for file in files {
-                    let file = t!(file);
-                    let path = file.path();
-                    if path.is_file() {
-                        builder.copy_link(
-                            &path,
-                            &sysroot.join("lib").join(path.file_name().unwrap()),
-                            FileType::Regular,
-                        );
-                    }
-                }
-            }
+            t!(fs::create_dir_all(sysroot.join("lib")));
+            builder.cp_link_r(&stage0_lib_dir, &sysroot.join("lib"));
 
             // Copy codegen-backends from stage0
             let sysroot_codegen_backends = builder.sysroot_codegen_backends(compiler);
@@ -807,6 +786,30 @@ impl Step for StdLink {
             if stage0_codegen_backends.exists() {
                 builder.cp_link_r(&stage0_codegen_backends, &sysroot_codegen_backends);
             }
+        } else if compiler.stage == 0 {
+            let sysroot = builder.out.join(compiler.host.triple).join("stage0-sysroot");
+
+            if builder.local_rebuild {
+                // On local rebuilds this path might be a symlink to the project root,
+                // which can be read-only (e.g., on CI). So remove it before copying
+                // the stage0 lib.
+                let _ = fs::remove_dir_all(sysroot.join("lib/rustlib/src/rust"));
+            }
+
+            builder.cp_link_r(&builder.initial_sysroot.join("lib"), &sysroot.join("lib"));
+        } else {
+            if builder.download_rustc() {
+                // Ensure there are no CI-rustc std artifacts.
+                let _ = fs::remove_dir_all(&libdir);
+                let _ = fs::remove_dir_all(&hostdir);
+            }
+
+            add_to_sysroot(
+                builder,
+                &libdir,
+                &hostdir,
+                &build_stamp::libstd_stamp(builder, compiler, target),
+            );
         }
     }
 }
@@ -1029,7 +1032,7 @@ impl Step for Rustc {
         let compiler = self.compiler;
         let target = self.target;
 
-        // NOTE: the ABI of the beta compiler is different from the ABI of the downloaded compiler,
+        // NOTE: the ABI of the stage0 compiler is different from the ABI of the downloaded compiler,
         // so its artifacts can't be reused.
         if builder.download_rustc() && compiler.stage != 0 {
             trace!(stage = compiler.stage, "`download_rustc` requested");
@@ -1275,6 +1278,17 @@ pub fn rustc_cargo(
         ));
     }
 
+    // The stage0 compiler changes infrequently and does not directly depend on code
+    // in the current working directory. Therefore, caching it with sccache should be
+    // useful.
+    // This is only performed for non-incremental builds, as ccache cannot deal with these.
+    if let Some(ref ccache) = builder.config.ccache
+        && compiler.stage == 0
+        && !builder.config.incremental
+    {
+        cargo.env("RUSTC_WRAPPER", ccache);
+    }
+
     rustc_cargo_env(builder, cargo, target, compiler.stage);
 }
 
@@ -1388,12 +1402,13 @@ fn rustc_llvm_env(builder: &Builder<'_>, cargo: &mut Cargo, target: TargetSelect
     // found. This is to avoid the linker errors about undefined references to
     // `__llvm_profile_instrument_memop` when linking `rustc_driver`.
     let mut llvm_linker_flags = String::new();
-    if builder.config.llvm_profile_generate && target.is_msvc() {
-        if let Some(ref clang_cl_path) = builder.config.llvm_clang_cl {
-            // Add clang's runtime library directory to the search path
-            let clang_rt_dir = get_clang_cl_resource_dir(builder, clang_cl_path);
-            llvm_linker_flags.push_str(&format!("-L{}", clang_rt_dir.display()));
-        }
+    if builder.config.llvm_profile_generate
+        && target.is_msvc()
+        && let Some(ref clang_cl_path) = builder.config.llvm_clang_cl
+    {
+        // Add clang's runtime library directory to the search path
+        let clang_rt_dir = get_clang_cl_resource_dir(builder, clang_cl_path);
+        llvm_linker_flags.push_str(&format!("-L{}", clang_rt_dir.display()));
     }
 
     // The config can also specify its own llvm linker flags.
@@ -1409,7 +1424,7 @@ fn rustc_llvm_env(builder: &Builder<'_>, cargo: &mut Cargo, target: TargetSelect
         cargo.env("LLVM_LINKER_FLAGS", llvm_linker_flags);
     }
 
-    // Building with a static libstdc++ is only supported on linux right now,
+    // Building with a static libstdc++ is only supported on Linux and windows-gnu* right now,
     // not for MSVC or macOS
     if builder.config.llvm_static_stdcpp
         && !target.contains("freebsd")
@@ -1417,12 +1432,14 @@ fn rustc_llvm_env(builder: &Builder<'_>, cargo: &mut Cargo, target: TargetSelect
         && !target.contains("apple")
         && !target.contains("solaris")
     {
+        let libstdcxx_name =
+            if target.contains("windows-gnullvm") { "libc++.a" } else { "libstdc++.a" };
         let file = compiler_file(
             builder,
             &builder.cxx(target).unwrap(),
             target,
             CLang::Cxx,
-            "libstdc++.a",
+            libstdcxx_name,
         );
         cargo.env("LLVM_STATIC_STDCPP", file);
     }
@@ -1783,9 +1800,9 @@ impl Step for Sysroot {
         t!(fs::create_dir_all(&sysroot));
 
         // In some cases(see https://github.com/rust-lang/rust/issues/109314), when the stage0
-        // compiler relies on more recent version of LLVM than the beta compiler, it may not
+        // compiler relies on more recent version of LLVM than the stage0 compiler, it may not
         // be able to locate the correct LLVM in the sysroot. This situation typically occurs
-        // when we upgrade LLVM version while the beta compiler continues to use an older version.
+        // when we upgrade LLVM version while the stage0 compiler continues to use an older version.
         //
         // Make sure to add the correct version of LLVM into the stage0 sysroot.
         if compiler.stage == 0 {
diff --git a/src/bootstrap/src/core/build_steps/dist.rs b/src/bootstrap/src/core/build_steps/dist.rs
index 253fa224152..587fca80374 100644
--- a/src/bootstrap/src/core/build_steps/dist.rs
+++ b/src/bootstrap/src/core/build_steps/dist.rs
@@ -776,7 +776,8 @@ impl Step for RustcDev {
         copy_src_dirs(
             builder,
             &builder.src,
-            &["compiler"],
+            // The compiler has a path dependency on proc_macro, so make sure to include it.
+            &["compiler", "library/proc_macro"],
             &[],
             &tarball.image_dir().join("lib/rustlib/rustc-src/rust"),
         );
@@ -2275,11 +2276,16 @@ impl Step for LlvmTools {
         let target = self.target;
 
         // Run only if a custom llvm-config is not used
-        if let Some(config) = builder.config.target_config.get(&target) {
-            if !builder.config.llvm_from_ci && config.llvm_config.is_some() {
-                builder.info(&format!("Skipping LlvmTools ({target}): external LLVM"));
-                return None;
-            }
+        if let Some(config) = builder.config.target_config.get(&target)
+            && !builder.config.llvm_from_ci
+            && config.llvm_config.is_some()
+        {
+            builder.info(&format!("Skipping LlvmTools ({target}): external LLVM"));
+            return None;
+        }
+
+        if !builder.config.dry_run() {
+            builder.require_submodule("src/llvm-project", None);
         }
 
         builder.ensure(crate::core::build_steps::llvm::Llvm { target });
@@ -2393,11 +2399,15 @@ impl Step for RustDev {
         let target = self.target;
 
         /* run only if llvm-config isn't used */
-        if let Some(config) = builder.config.target_config.get(&target) {
-            if let Some(ref _s) = config.llvm_config {
-                builder.info(&format!("Skipping RustDev ({target}): external LLVM"));
-                return None;
-            }
+        if let Some(config) = builder.config.target_config.get(&target)
+            && let Some(ref _s) = config.llvm_config
+        {
+            builder.info(&format!("Skipping RustDev ({target}): external LLVM"));
+            return None;
+        }
+
+        if !builder.config.dry_run() {
+            builder.require_submodule("src/llvm-project", None);
         }
 
         let mut tarball = Tarball::new(builder, "rust-dev", &target.triple);
diff --git a/src/bootstrap/src/core/build_steps/format.rs b/src/bootstrap/src/core/build_steps/format.rs
index 1c317ce4b86..61268df7336 100644
--- a/src/bootstrap/src/core/build_steps/format.rs
+++ b/src/bootstrap/src/core/build_steps/format.rs
@@ -318,10 +318,10 @@ pub fn format(build: &Builder<'_>, check: bool, all: bool, paths: &[PathBuf]) {
                     // `into_path` produces an absolute path. Try to strip `cwd` to get a shorter
                     // relative path.
                     let mut path = entry.clone().into_path();
-                    if let Ok(cwd) = cwd {
-                        if let Ok(path2) = path.strip_prefix(cwd) {
-                            path = path2.to_path_buf();
-                        }
+                    if let Ok(cwd) = cwd
+                        && let Ok(path2) = path.strip_prefix(cwd)
+                    {
+                        path = path2.to_path_buf();
                     }
                     path.display().to_string()
                 });
diff --git a/src/bootstrap/src/core/build_steps/install.rs b/src/bootstrap/src/core/build_steps/install.rs
index 585adf9be16..5419540aa2e 100644
--- a/src/bootstrap/src/core/build_steps/install.rs
+++ b/src/bootstrap/src/core/build_steps/install.rs
@@ -38,7 +38,9 @@ fn sanitize_sh(path: &Path, is_cygwin: bool) -> String {
         if ch.next() != Some('/') {
             return None;
         }
-        Some(format!("/{}/{}", drive, &s[drive.len_utf8() + 2..]))
+        // The prefix for Windows drives in Cygwin/MSYS2 is configurable, but
+        // /proc/cygdrive is available regardless of configuration since 1.7.33
+        Some(format!("/proc/cygdrive/{}/{}", drive, &s[drive.len_utf8() + 2..]))
     }
 }
 
diff --git a/src/bootstrap/src/core/build_steps/llvm.rs b/src/bootstrap/src/core/build_steps/llvm.rs
index a3788197471..20a4d1a1515 100644
--- a/src/bootstrap/src/core/build_steps/llvm.rs
+++ b/src/bootstrap/src/core/build_steps/llvm.rs
@@ -107,18 +107,18 @@ pub fn prebuilt_llvm_config(
 
     // If we're using a custom LLVM bail out here, but we can only use a
     // custom LLVM for the build triple.
-    if let Some(config) = builder.config.target_config.get(&target) {
-        if let Some(ref s) = config.llvm_config {
-            check_llvm_version(builder, s);
-            let llvm_config = s.to_path_buf();
-            let mut llvm_cmake_dir = llvm_config.clone();
-            llvm_cmake_dir.pop();
-            llvm_cmake_dir.pop();
-            llvm_cmake_dir.push("lib");
-            llvm_cmake_dir.push("cmake");
-            llvm_cmake_dir.push("llvm");
-            return LlvmBuildStatus::AlreadyBuilt(LlvmResult { llvm_config, llvm_cmake_dir });
-        }
+    if let Some(config) = builder.config.target_config.get(&target)
+        && let Some(ref s) = config.llvm_config
+    {
+        check_llvm_version(builder, s);
+        let llvm_config = s.to_path_buf();
+        let mut llvm_cmake_dir = llvm_config.clone();
+        llvm_cmake_dir.pop();
+        llvm_cmake_dir.pop();
+        llvm_cmake_dir.push("lib");
+        llvm_cmake_dir.push("cmake");
+        llvm_cmake_dir.push("llvm");
+        return LlvmBuildStatus::AlreadyBuilt(LlvmResult { llvm_config, llvm_cmake_dir });
     }
 
     if handle_submodule_when_needed {
@@ -285,7 +285,8 @@ impl Step for Llvm {
             LlvmBuildStatus::ShouldBuild(m) => m,
         };
 
-        if builder.llvm_link_shared() && target.is_windows() {
+        if builder.llvm_link_shared() && target.is_windows() && !target.ends_with("windows-gnullvm")
+        {
             panic!("shared linking to LLVM is not currently supported on {}", target.triple);
         }
 
@@ -467,10 +468,10 @@ impl Step for Llvm {
             cfg.define("LLVM_ENABLE_RUNTIMES", enabled_llvm_runtimes.join(";"));
         }
 
-        if let Some(num_linkers) = builder.config.llvm_link_jobs {
-            if num_linkers > 0 {
-                cfg.define("LLVM_PARALLEL_LINK_JOBS", num_linkers.to_string());
-            }
+        if let Some(num_linkers) = builder.config.llvm_link_jobs
+            && num_linkers > 0
+        {
+            cfg.define("LLVM_PARALLEL_LINK_JOBS", num_linkers.to_string());
         }
 
         // https://llvm.org/docs/HowToCrossCompileLLVM.html
@@ -596,10 +597,10 @@ fn check_llvm_version(builder: &Builder<'_>, llvm_config: &Path) {
 
     let version = get_llvm_version(builder, llvm_config);
     let mut parts = version.split('.').take(2).filter_map(|s| s.parse::<u32>().ok());
-    if let (Some(major), Some(_minor)) = (parts.next(), parts.next()) {
-        if major >= 19 {
-            return;
-        }
+    if let (Some(major), Some(_minor)) = (parts.next(), parts.next())
+        && major >= 19
+    {
+        return;
     }
     panic!("\n\nbad LLVM version: {version}, need >=19\n\n")
 }
@@ -729,11 +730,9 @@ fn configure_cmake(
 
     // If ccache is configured we inform the build a little differently how
     // to invoke ccache while also invoking our compilers.
-    if use_compiler_launcher {
-        if let Some(ref ccache) = builder.config.ccache {
-            cfg.define("CMAKE_C_COMPILER_LAUNCHER", ccache)
-                .define("CMAKE_CXX_COMPILER_LAUNCHER", ccache);
-        }
+    if use_compiler_launcher && let Some(ref ccache) = builder.config.ccache {
+        cfg.define("CMAKE_C_COMPILER_LAUNCHER", ccache)
+            .define("CMAKE_CXX_COMPILER_LAUNCHER", ccache);
     }
     cfg.define("CMAKE_C_COMPILER", sanitize_cc(&cc))
         .define("CMAKE_CXX_COMPILER", sanitize_cc(&cxx))
@@ -791,20 +790,20 @@ fn configure_cmake(
         cxxflags.push(format!(" --target={target}"));
     }
     cfg.define("CMAKE_CXX_FLAGS", cxxflags);
-    if let Some(ar) = builder.ar(target) {
-        if ar.is_absolute() {
-            // LLVM build breaks if `CMAKE_AR` is a relative path, for some reason it
-            // tries to resolve this path in the LLVM build directory.
-            cfg.define("CMAKE_AR", sanitize_cc(&ar));
-        }
+    if let Some(ar) = builder.ar(target)
+        && ar.is_absolute()
+    {
+        // LLVM build breaks if `CMAKE_AR` is a relative path, for some reason it
+        // tries to resolve this path in the LLVM build directory.
+        cfg.define("CMAKE_AR", sanitize_cc(&ar));
     }
 
-    if let Some(ranlib) = builder.ranlib(target) {
-        if ranlib.is_absolute() {
-            // LLVM build breaks if `CMAKE_RANLIB` is a relative path, for some reason it
-            // tries to resolve this path in the LLVM build directory.
-            cfg.define("CMAKE_RANLIB", sanitize_cc(&ranlib));
-        }
+    if let Some(ranlib) = builder.ranlib(target)
+        && ranlib.is_absolute()
+    {
+        // LLVM build breaks if `CMAKE_RANLIB` is a relative path, for some reason it
+        // tries to resolve this path in the LLVM build directory.
+        cfg.define("CMAKE_RANLIB", sanitize_cc(&ranlib));
     }
 
     if let Some(ref flags) = builder.config.llvm_ldflags {
@@ -1037,13 +1036,14 @@ impl Step for Lld {
         // when doing PGO on CI, cmake or clang-cl don't automatically link clang's
         // profiler runtime in. In that case, we need to manually ask cmake to do it, to avoid
         // linking errors, much like LLVM's cmake setup does in that situation.
-        if builder.config.llvm_profile_generate && target.is_msvc() {
-            if let Some(clang_cl_path) = builder.config.llvm_clang_cl.as_ref() {
-                // Find clang's runtime library directory and push that as a search path to the
-                // cmake linker flags.
-                let clang_rt_dir = get_clang_cl_resource_dir(builder, clang_cl_path);
-                ldflags.push_all(format!("/libpath:{}", clang_rt_dir.display()));
-            }
+        if builder.config.llvm_profile_generate
+            && target.is_msvc()
+            && let Some(clang_cl_path) = builder.config.llvm_clang_cl.as_ref()
+        {
+            // Find clang's runtime library directory and push that as a search path to the
+            // cmake linker flags.
+            let clang_rt_dir = get_clang_cl_resource_dir(builder, clang_cl_path);
+            ldflags.push_all(format!("/libpath:{}", clang_rt_dir.display()));
         }
 
         // LLD is built as an LLVM tool, but is distributed outside of the `llvm-tools` component,
@@ -1430,6 +1430,7 @@ impl Step for Libunwind {
             cfg.flag("-funwind-tables");
             cfg.flag("-fvisibility=hidden");
             cfg.define("_LIBUNWIND_DISABLE_VISIBILITY_ANNOTATIONS", None);
+            cfg.define("_LIBUNWIND_IS_NATIVE_ONLY", "1");
             cfg.include(root.join("include"));
             cfg.cargo_metadata(false);
             cfg.out_dir(&out_dir);
@@ -1447,12 +1448,10 @@ impl Step for Libunwind {
                 cfg.define("__NO_STRING_INLINES", None);
                 cfg.define("__NO_MATH_INLINES", None);
                 cfg.define("_LIBUNWIND_IS_BAREMETAL", None);
-                cfg.define("__LIBUNWIND_IS_NATIVE_ONLY", None);
                 cfg.define("NDEBUG", None);
             }
             if self.target.is_windows() {
                 cfg.define("_LIBUNWIND_HIDE_SYMBOLS", "1");
-                cfg.define("_LIBUNWIND_IS_NATIVE_ONLY", "1");
             }
         }
 
diff --git a/src/bootstrap/src/core/build_steps/perf.rs b/src/bootstrap/src/core/build_steps/perf.rs
index 71cdb665ed4..14c7b7cf5e9 100644
--- a/src/bootstrap/src/core/build_steps/perf.rs
+++ b/src/bootstrap/src/core/build_steps/perf.rs
@@ -154,10 +154,10 @@ Consider setting `rust.debuginfo-level = 1` in `bootstrap.toml`."#);
     let compiler = builder.compiler(builder.top_stage, builder.config.build);
     builder.ensure(Std::new(compiler, builder.config.build));
 
-    if let Some(opts) = args.cmd.shared_opts() {
-        if opts.profiles.contains(&Profile::Doc) {
-            builder.ensure(Rustdoc { compiler });
-        }
+    if let Some(opts) = args.cmd.shared_opts()
+        && opts.profiles.contains(&Profile::Doc)
+    {
+        builder.ensure(Rustdoc { compiler });
     }
 
     let sysroot = builder.ensure(Sysroot::new(compiler));
diff --git a/src/bootstrap/src/core/build_steps/run.rs b/src/bootstrap/src/core/build_steps/run.rs
index 0bba441c3fa..6ef1b13abcd 100644
--- a/src/bootstrap/src/core/build_steps/run.rs
+++ b/src/bootstrap/src/core/build_steps/run.rs
@@ -5,7 +5,6 @@
 
 use std::path::PathBuf;
 
-use crate::Mode;
 use crate::core::build_steps::dist::distdir;
 use crate::core::build_steps::test;
 use crate::core::build_steps::tool::{self, SourceType, Tool};
@@ -14,6 +13,7 @@ use crate::core::builder::{Builder, Kind, RunConfig, ShouldRun, Step};
 use crate::core::config::TargetSelection;
 use crate::core::config::flags::get_completion;
 use crate::utils::exec::command;
+use crate::{Mode, t};
 
 #[derive(Debug, PartialOrd, Ord, Clone, Hash, PartialEq, Eq)]
 pub struct BuildManifest;
@@ -118,15 +118,25 @@ impl Step for Miri {
     fn run(self, builder: &Builder<'_>) {
         let host = builder.build.build;
         let target = self.target;
-        let stage = builder.top_stage;
+
+        // `x run` uses stage 0 by default but miri does not work well with stage 0.
+        // Change the stage to 1 if it's not set explicitly.
+        let stage = if builder.config.is_explicit_stage() || builder.top_stage >= 1 {
+            builder.top_stage
+        } else {
+            1
+        };
+
         if stage == 0 {
             eprintln!("miri cannot be run at stage 0");
             std::process::exit(1);
         }
 
         // This compiler runs on the host, we'll just use it for the target.
-        let target_compiler = builder.compiler(stage, host);
-        let host_compiler = tool::get_tool_rustc_compiler(builder, target_compiler);
+        let target_compiler = builder.compiler(stage, target);
+        let miri_build = builder.ensure(tool::Miri { compiler: target_compiler, target });
+        // Rustc tools are off by one stage, so use the build compiler to run miri.
+        let host_compiler = miri_build.build_compiler;
 
         // Get a target sysroot for Miri.
         let miri_sysroot = test::Miri::build_miri_sysroot(builder, target_compiler, target);
@@ -243,6 +253,7 @@ impl Step for GenerateCopyright {
         cmd.env("SRC_DIR", &builder.src);
         cmd.env("VENDOR_DIR", &vendored_sources);
         cmd.env("CARGO", &builder.initial_cargo);
+        cmd.env("CARGO_HOME", t!(home::cargo_home()));
         // it is important that generate-copyright runs from the root of the
         // source tree, because it uses relative paths
         cmd.current_dir(&builder.src);
diff --git a/src/bootstrap/src/core/build_steps/setup.rs b/src/bootstrap/src/core/build_steps/setup.rs
index 5e22c2d1acb..25adfdf1601 100644
--- a/src/bootstrap/src/core/build_steps/setup.rs
+++ b/src/bootstrap/src/core/build_steps/setup.rs
@@ -241,10 +241,10 @@ impl Step for Link {
         if run.builder.config.dry_run() {
             return;
         }
-        if let [cmd] = &run.paths[..] {
-            if cmd.assert_single_path().path.as_path().as_os_str() == "link" {
-                run.builder.ensure(Link);
-            }
+        if let [cmd] = &run.paths[..]
+            && cmd.assert_single_path().path.as_path().as_os_str() == "link"
+        {
+            run.builder.ensure(Link);
         }
     }
     fn run(self, builder: &Builder<'_>) -> Self::Output {
@@ -457,10 +457,10 @@ impl Step for Hook {
     }
 
     fn make_run(run: RunConfig<'_>) {
-        if let [cmd] = &run.paths[..] {
-            if cmd.assert_single_path().path.as_path().as_os_str() == "hook" {
-                run.builder.ensure(Hook);
-            }
+        if let [cmd] = &run.paths[..]
+            && cmd.assert_single_path().path.as_path().as_os_str() == "hook"
+        {
+            run.builder.ensure(Hook);
         }
     }
 
@@ -672,10 +672,10 @@ impl Step for Editor {
         if run.builder.config.dry_run() {
             return;
         }
-        if let [cmd] = &run.paths[..] {
-            if cmd.assert_single_path().path.as_path().as_os_str() == "editor" {
-                run.builder.ensure(Editor);
-            }
+        if let [cmd] = &run.paths[..]
+            && cmd.assert_single_path().path.as_path().as_os_str() == "editor"
+        {
+            run.builder.ensure(Editor);
         }
     }
 
diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs
index acd6fc47705..22a458bac98 100644
--- a/src/bootstrap/src/core/build_steps/test.rs
+++ b/src/bootstrap/src/core/build_steps/test.rs
@@ -1576,7 +1576,7 @@ impl Step for Compiletest {
 
         if builder.top_stage == 0 && env::var("COMPILETEST_FORCE_STAGE0").is_err() {
             eprintln!("\
-ERROR: `--stage 0` runs compiletest on the beta compiler, not your local changes, and will almost always cause tests to fail
+ERROR: `--stage 0` runs compiletest on the stage0 (precompiled) compiler, not your local changes, and will almost always cause tests to fail
 HELP: to test the compiler, use `--stage 1` instead
 HELP: to test the standard library, use `--stage 0 library/std` instead
 NOTE: if you're sure you want to do this, please open an issue as to why. In the meantime, you can override this with `COMPILETEST_FORCE_STAGE0=1`."
@@ -1604,9 +1604,9 @@ NOTE: if you're sure you want to do this, please open an issue as to why. In the
         // NOTE: Only stage 1 is special cased because we need the rustc_private artifacts to match the
         // running compiler in stage 2 when plugins run.
         let (stage, stage_id) = if suite == "ui-fulldeps" && compiler.stage == 1 {
-            // At stage 0 (stage - 1) we are using the beta compiler. Using `self.target` can lead
-            // finding an incorrect compiler path on cross-targets, as the stage 0 beta compiler is
-            // always equal to `build.build` in the configuration.
+            // At stage 0 (stage - 1) we are using the stage0 compiler. Using `self.target` can lead
+            // finding an incorrect compiler path on cross-targets, as the stage 0 is always equal to
+            // `build.build` in the configuration.
             let build = builder.build.build;
             compiler = builder.compiler(compiler.stage - 1, build);
             let test_stage = compiler.stage + 1;
@@ -1692,7 +1692,7 @@ NOTE: if you're sure you want to do this, please open an issue as to why. In the
         }
 
         if mode == "rustdoc-json" {
-            // Use the beta compiler for jsondocck
+            // Use the stage0 compiler for jsondocck
             let json_compiler = compiler.with_stage(0);
             cmd.arg("--jsondocck-path")
                 .arg(builder.ensure(tool::JsonDocCk { compiler: json_compiler, target }).tool_path);
@@ -2417,10 +2417,10 @@ impl Step for ErrorIndex {
 }
 
 fn markdown_test(builder: &Builder<'_>, compiler: Compiler, markdown: &Path) -> bool {
-    if let Ok(contents) = fs::read_to_string(markdown) {
-        if !contents.contains("```") {
-            return true;
-        }
+    if let Ok(contents) = fs::read_to_string(markdown)
+        && !contents.contains("```")
+    {
+        return true;
     }
 
     builder.verbose(|| println!("doc tests for: {}", markdown.display()));
@@ -2964,7 +2964,14 @@ impl Step for Distcheck {
         run.builder.ensure(Distcheck);
     }
 
-    /// Runs "distcheck", a 'make check' from a tarball
+    /// Runs `distcheck`, which is a collection of smoke tests:
+    ///
+    /// - Run `make check` from an unpacked dist tarball to make sure we can at the minimum run
+    ///   check steps from those sources.
+    /// - Check that selected dist components (`rust-src` only at the moment) at least have expected
+    ///   directory shape and crate manifests that cargo can generate a lockfile from.
+    ///
+    /// FIXME(#136822): dist components are under-tested.
     fn run(self, builder: &Builder<'_>) {
         builder.info("Distcheck");
         let dir = builder.tempdir().join("distcheck");
@@ -3537,7 +3544,7 @@ impl Step for CodegenGCC {
 }
 
 /// Test step that does two things:
-/// - Runs `cargo test` for the `src/etc/test-float-parse` tool.
+/// - Runs `cargo test` for the `src/tools/test-float-parse` tool.
 /// - Invokes the `test-float-parse` tool to test the standard library's
 ///   float parsing routines.
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
@@ -3552,7 +3559,7 @@ impl Step for TestFloatParse {
     const DEFAULT: bool = true;
 
     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
-        run.path("src/etc/test-float-parse")
+        run.path("src/tools/test-float-parse")
     }
 
     fn make_run(run: RunConfig<'_>) {
diff --git a/src/bootstrap/src/core/build_steps/tool.rs b/src/bootstrap/src/core/build_steps/tool.rs
index 678aa9b01e4..21a119e331e 100644
--- a/src/bootstrap/src/core/build_steps/tool.rs
+++ b/src/bootstrap/src/core/build_steps/tool.rs
@@ -148,6 +148,17 @@ impl Step for ToolBuild {
             &self.extra_features,
         );
 
+        // The stage0 compiler changes infrequently and does not directly depend on code
+        // in the current working directory. Therefore, caching it with sccache should be
+        // useful.
+        // This is only performed for non-incremental builds, as ccache cannot deal with these.
+        if let Some(ref ccache) = builder.config.ccache
+            && matches!(self.mode, Mode::ToolBootstrap)
+            && !builder.config.incremental
+        {
+            cargo.env("RUSTC_WRAPPER", ccache);
+        }
+
         // Rustc tools (miri, clippy, cargo, rustfmt, rust-analyzer)
         // could use the additional optimizations.
         if self.mode == Mode::ToolRustc && is_lto_stage(&self.compiler) {
@@ -329,9 +340,9 @@ pub(crate) fn get_tool_rustc_compiler(
         return target_compiler;
     }
 
-    if builder.download_rustc() && target_compiler.stage > 0 {
-        // We already have the stage N compiler, we don't need to cut the stage.
-        return builder.compiler(target_compiler.stage, builder.config.build);
+    if builder.download_rustc() && target_compiler.stage == 1 {
+        // We shouldn't drop to stage0 compiler when using CI rustc.
+        return builder.compiler(1, builder.config.build);
     }
 
     // Similar to `compile::Assemble`, build with the previous stage's compiler. Otherwise
@@ -1197,9 +1208,9 @@ fn run_tool_build_step(
             artifact_kind: ToolArtifactKind::Binary,
         });
 
-    // FIXME: This should just be an if-let-chain, but those are unstable.
-    if let Some(add_bins_to_sysroot) =
-        add_bins_to_sysroot.filter(|bins| !bins.is_empty() && target_compiler.stage > 0)
+    if let Some(add_bins_to_sysroot) = add_bins_to_sysroot
+        && !add_bins_to_sysroot.is_empty()
+        && target_compiler.stage > 0
     {
         let bindir = builder.sysroot(target_compiler).join("bin");
         t!(fs::create_dir_all(&bindir));
@@ -1269,7 +1280,7 @@ impl Step for TestFloatParse {
     const DEFAULT: bool = false;
 
     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
-        run.path("src/etc/test-float-parse")
+        run.path("src/tools/test-float-parse")
     }
 
     fn run(self, builder: &Builder<'_>) -> ToolBuildResult {
@@ -1281,7 +1292,7 @@ impl Step for TestFloatParse {
             target: bootstrap_host,
             tool: "test-float-parse",
             mode: Mode::ToolStd,
-            path: "src/etc/test-float-parse",
+            path: "src/tools/test-float-parse",
             source_type: SourceType::InTree,
             extra_features: Vec::new(),
             allow_features: Self::ALLOW_FEATURES,
diff --git a/src/bootstrap/src/core/builder/cargo.rs b/src/bootstrap/src/core/builder/cargo.rs
index e41f6f16b02..1e9af68a92d 100644
--- a/src/bootstrap/src/core/builder/cargo.rs
+++ b/src/bootstrap/src/core/builder/cargo.rs
@@ -988,15 +988,15 @@ impl Builder<'_> {
         // requirement, but the `-L` library path is not propagated across
         // separate Cargo projects. We can add LLVM's library path to the
         // rustc args as a workaround.
-        if mode == Mode::ToolRustc || mode == Mode::Codegen {
-            if let Some(llvm_config) = self.llvm_config(target) {
-                let llvm_libdir =
-                    command(llvm_config).arg("--libdir").run_capture_stdout(self).stdout();
-                if target.is_msvc() {
-                    rustflags.arg(&format!("-Clink-arg=-LIBPATH:{llvm_libdir}"));
-                } else {
-                    rustflags.arg(&format!("-Clink-arg=-L{llvm_libdir}"));
-                }
+        if (mode == Mode::ToolRustc || mode == Mode::Codegen)
+            && let Some(llvm_config) = self.llvm_config(target)
+        {
+            let llvm_libdir =
+                command(llvm_config).arg("--libdir").run_capture_stdout(self).stdout();
+            if target.is_msvc() {
+                rustflags.arg(&format!("-Clink-arg=-LIBPATH:{llvm_libdir}"));
+            } else {
+                rustflags.arg(&format!("-Clink-arg=-L{llvm_libdir}"));
             }
         }
 
@@ -1004,7 +1004,12 @@ impl Builder<'_> {
         // efficient initial-exec TLS model. This doesn't work with `dlopen`,
         // so we can't use it by default in general, but we can use it for tools
         // and our own internal libraries.
-        if !mode.must_support_dlopen() && !target.triple.starts_with("powerpc-") {
+        //
+        // Cygwin only supports emutls.
+        if !mode.must_support_dlopen()
+            && !target.triple.starts_with("powerpc-")
+            && !target.triple.contains("cygwin")
+        {
             cargo.env("RUSTC_TLS_MODEL_INITIAL_EXEC", "1");
         }
 
@@ -1226,12 +1231,11 @@ impl Builder<'_> {
                 _ => None,
             };
 
-            if let Some(limit) = limit {
-                if stage == 0
-                    || self.config.default_codegen_backend(target).unwrap_or_default() == "llvm"
-                {
-                    rustflags.arg(&format!("-Cllvm-args=-import-instr-limit={limit}"));
-                }
+            if let Some(limit) = limit
+                && (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/tests.rs b/src/bootstrap/src/core/builder/tests.rs
index 51852099dc3..baa22fc7f72 100644
--- a/src/bootstrap/src/core/builder/tests.rs
+++ b/src/bootstrap/src/core/builder/tests.rs
@@ -237,7 +237,7 @@ fn alias_and_path_for_library() {
     );
     assert_eq!(
         first(cache.all::<doc::Std>()),
-        &[doc_std!(TEST_TRIPLE_1 => TEST_TRIPLE_1, stage = 0)]
+        &[doc_std!(TEST_TRIPLE_1 => TEST_TRIPLE_1, stage = 1)]
     );
 }
 
@@ -255,19 +255,6 @@ fn ci_rustc_if_unchanged_invalidate_on_compiler_changes() {
 }
 
 #[test]
-fn ci_rustc_if_unchanged_invalidate_on_library_changes_in_ci() {
-    git_test(|ctx| {
-        prepare_rustc_checkout(ctx);
-        ctx.create_upstream_merge(&["compiler/bar"]);
-        // This change should invalidate download-ci-rustc
-        ctx.create_nonupstream_merge(&["library/foo"]);
-
-        let config = parse_config_download_rustc_at(ctx.get_path(), "if-unchanged", true);
-        assert_eq!(config.download_rustc_commit, None);
-    });
-}
-
-#[test]
 fn ci_rustc_if_unchanged_do_not_invalidate_on_library_changes_outside_ci() {
     git_test(|ctx| {
         prepare_rustc_checkout(ctx);
@@ -433,14 +420,14 @@ mod defaults {
         assert_eq!(first(cache.all::<doc::ErrorIndex>()), &[doc::ErrorIndex { target: a },]);
         assert_eq!(
             first(cache.all::<tool::ErrorIndex>()),
-            &[tool::ErrorIndex { compiler: Compiler::new(0, a) }]
+            &[tool::ErrorIndex { compiler: Compiler::new(1, a) }]
         );
-        // docs should be built with the beta compiler, not with the stage0 artifacts.
+        // docs should be built with the stage0 compiler, not with the stage0 artifacts.
         // recall that rustdoc is off-by-one: `stage` is the compiler rustdoc is _linked_ to,
         // not the one it was built by.
         assert_eq!(
             first(cache.all::<tool::Rustdoc>()),
-            &[tool::Rustdoc { compiler: Compiler::new(0, a) },]
+            &[tool::Rustdoc { compiler: Compiler::new(1, a) },]
         );
     }
 }
diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs
index 3b8c3655b8d..03044d4fc80 100644
--- a/src/bootstrap/src/core/config/config.rs
+++ b/src/bootstrap/src/core/config/config.rs
@@ -45,6 +45,7 @@ use crate::utils::helpers::{self, exe, output, t};
 /// final output/compiler, which can be significantly affected by changes made to the bootstrap sources.
 #[rustfmt::skip] // We don't want rustfmt to oneline this list
 pub(crate) const RUSTC_IF_UNCHANGED_ALLOWED_PATHS: &[&str] = &[
+    ":!library",
     ":!src/tools",
     ":!src/librustdoc",
     ":!src/rustdoc-json-types",
@@ -1699,20 +1700,20 @@ impl Config {
             };
             // We want to be able to set string values without quotes,
             // like in `configure.py`. Try adding quotes around the right hand side
-            if let Some((key, value)) = option.split_once('=') {
-                if !value.contains('"') {
-                    match get_table(&format!(r#"{key}="{value}""#)) {
-                        Ok(v) => {
-                            override_toml.merge(
-                                None,
-                                &mut Default::default(),
-                                v,
-                                ReplaceOpt::ErrorOnDuplicate,
-                            );
-                            continue;
-                        }
-                        Err(e) => err = e,
+            if let Some((key, value)) = option.split_once('=')
+                && !value.contains('"')
+            {
+                match get_table(&format!(r#"{key}="{value}""#)) {
+                    Ok(v) => {
+                        override_toml.merge(
+                            None,
+                            &mut Default::default(),
+                            v,
+                            ReplaceOpt::ErrorOnDuplicate,
+                        );
+                        continue;
                     }
+                    Err(e) => err = e,
                 }
             }
             eprintln!("failed to parse override `{option}`: `{err}");
@@ -1832,7 +1833,9 @@ impl Config {
                 .join(exe("rustc", config.build))
         };
 
-        config.initial_sysroot = config.initial_rustc.ancestors().nth(2).unwrap().into();
+        config.initial_sysroot = t!(PathBuf::from_str(
+            output(Command::new(&config.initial_rustc).args(["--print", "sysroot"])).trim()
+        ));
 
         config.initial_cargo_clippy = cargo_clippy;
 
@@ -2054,16 +2057,15 @@ impl Config {
                 || (matches!(debug_toml, Some(true))
                     && !matches!(rustc_debug_assertions_toml, Some(false)));
 
-            if debug_assertions_requested {
-                if let Some(ref opt) = download_rustc {
-                    if opt.is_string_or_true() {
-                        eprintln!(
-                            "WARN: currently no CI rustc builds have rustc debug assertions \
+            if debug_assertions_requested
+                && let Some(ref opt) = download_rustc
+                && opt.is_string_or_true()
+            {
+                eprintln!(
+                    "WARN: currently no CI rustc builds have rustc debug assertions \
                             enabled. Please either set `rust.debug-assertions` to `false` if you \
                             want to use download CI rustc or set `rust.download-rustc` to `false`."
-                        );
-                    }
-                }
+                );
             }
 
             config.download_rustc_commit = config.download_ci_rustc_commit(
@@ -2174,19 +2176,17 @@ impl Config {
         // We need to override `rust.channel` if it's manually specified when using the CI rustc.
         // This is because if the compiler uses a different channel than the one specified in bootstrap.toml,
         // tests may fail due to using a different channel than the one used by the compiler during tests.
-        if let Some(commit) = &config.download_rustc_commit {
-            if is_user_configured_rust_channel {
-                println!(
-                    "WARNING: `rust.download-rustc` is enabled. The `rust.channel` option will be overridden by the CI rustc's channel."
-                );
+        if let Some(commit) = &config.download_rustc_commit
+            && is_user_configured_rust_channel
+        {
+            println!(
+                "WARNING: `rust.download-rustc` is enabled. The `rust.channel` option will be overridden by the CI rustc's channel."
+            );
 
-                let channel = config
-                    .read_file_by_commit(Path::new("src/ci/channel"), commit)
-                    .trim()
-                    .to_owned();
+            let channel =
+                config.read_file_by_commit(Path::new("src/ci/channel"), commit).trim().to_owned();
 
-                config.channel = channel;
-            }
+            config.channel = channel;
         }
 
         if let Some(llvm) = toml.llvm {
@@ -2532,9 +2532,10 @@ impl Config {
         // See https://github.com/rust-lang/compiler-team/issues/326
         config.stage = match config.cmd {
             Subcommand::Check { .. } => flags.stage.or(check_stage).unwrap_or(0),
+            Subcommand::Clippy { .. } | Subcommand::Fix => flags.stage.or(check_stage).unwrap_or(1),
             // `download-rustc` only has a speed-up for stage2 builds. Default to stage2 unless explicitly overridden.
             Subcommand::Doc { .. } => {
-                flags.stage.or(doc_stage).unwrap_or(if download_rustc { 2 } else { 0 })
+                flags.stage.or(doc_stage).unwrap_or(if download_rustc { 2 } else { 1 })
             }
             Subcommand::Build => {
                 flags.stage.or(build_stage).unwrap_or(if download_rustc { 2 } else { 1 })
@@ -2549,8 +2550,6 @@ impl Config {
             // These are all bootstrap tools, which don't depend on the compiler.
             // The stage we pass shouldn't matter, but use 0 just in case.
             Subcommand::Clean { .. }
-            | Subcommand::Clippy { .. }
-            | Subcommand::Fix
             | Subcommand::Run { .. }
             | Subcommand::Setup { .. }
             | Subcommand::Format { .. }
@@ -2696,10 +2695,10 @@ impl Config {
         let bindir = &self.bindir;
         if bindir.is_absolute() {
             // Try to make it relative to the prefix.
-            if let Some(prefix) = &self.prefix {
-                if let Ok(stripped) = bindir.strip_prefix(prefix) {
-                    return stripped;
-                }
+            if let Some(prefix) = &self.prefix
+                && let Ok(stripped) = bindir.strip_prefix(prefix)
+            {
+                return stripped;
             }
         }
         bindir
@@ -3148,24 +3147,10 @@ impl Config {
             }
         };
 
-        // RUSTC_IF_UNCHANGED_ALLOWED_PATHS
-        let mut allowed_paths = RUSTC_IF_UNCHANGED_ALLOWED_PATHS.to_vec();
-
-        // In CI, disable ci-rustc if there are changes in the library tree. But for non-CI, allow
-        // these changes to speed up the build process for library developers. This provides consistent
-        // functionality for library developers between `download-rustc=true` and `download-rustc="if-unchanged"`
-        // options.
-        //
-        // If you update "library" logic here, update `builder::tests::ci_rustc_if_unchanged_logic` test
-        // logic accordingly.
-        if !self.is_running_on_ci {
-            allowed_paths.push(":!library");
-        }
-
         let commit = if self.rust_info.is_managed_git_subrepository() {
             // Look for a version to compare to based on the current commit.
             // Only commits merged by bors will have CI artifacts.
-            let freshness = self.check_path_modifications(&allowed_paths);
+            let freshness = self.check_path_modifications(RUSTC_IF_UNCHANGED_ALLOWED_PATHS);
             self.verbose(|| {
                 eprintln!("rustc freshness: {freshness:?}");
             });
@@ -3491,19 +3476,19 @@ fn check_incompatible_options_for_ci_rustc(
     // We always build the in-tree compiler on cross targets, so we only care
     // about the host target here.
     let host_str = host.to_string();
-    if let Some(current_cfg) = current_config_toml.target.as_ref().and_then(|c| c.get(&host_str)) {
-        if current_cfg.profiler.is_some() {
-            let ci_target_toml = ci_config_toml.target.as_ref().and_then(|c| c.get(&host_str));
-            let ci_cfg = ci_target_toml.ok_or(format!(
-                "Target specific config for '{host_str}' is not present for CI-rustc"
-            ))?;
+    if let Some(current_cfg) = current_config_toml.target.as_ref().and_then(|c| c.get(&host_str))
+        && current_cfg.profiler.is_some()
+    {
+        let ci_target_toml = ci_config_toml.target.as_ref().and_then(|c| c.get(&host_str));
+        let ci_cfg = ci_target_toml.ok_or(format!(
+            "Target specific config for '{host_str}' is not present for CI-rustc"
+        ))?;
 
-            let profiler = &ci_cfg.profiler;
-            err!(current_cfg.profiler, profiler, "build");
+        let profiler = &ci_cfg.profiler;
+        err!(current_cfg.profiler, profiler, "build");
 
-            let optimized_compiler_builtins = &ci_cfg.optimized_compiler_builtins;
-            err!(current_cfg.optimized_compiler_builtins, optimized_compiler_builtins, "build");
-        }
+        let optimized_compiler_builtins = &ci_cfg.optimized_compiler_builtins;
+        err!(current_cfg.optimized_compiler_builtins, optimized_compiler_builtins, "build");
     }
 
     let (Some(current_rust_config), Some(ci_rust_config)) =
diff --git a/src/bootstrap/src/core/download.rs b/src/bootstrap/src/core/download.rs
index e0c9877cd55..d942334d1c3 100644
--- a/src/bootstrap/src/core/download.rs
+++ b/src/bootstrap/src/core/download.rs
@@ -666,7 +666,7 @@ impl Config {
             }
         };
 
-        // For the beta compiler, put special effort into ensuring the checksums are valid.
+        // For the stage0 compiler, put special effort into ensuring the checksums are valid.
         let checksum = if should_verify {
             let error = format!(
                 "src/stage0 doesn't contain a checksum for {url}. \
@@ -709,10 +709,10 @@ download-rustc = false
 ";
         }
         self.download_file(&format!("{base_url}/{url}"), &tarball, help_on_error);
-        if let Some(sha256) = checksum {
-            if !self.verify(&tarball, sha256) {
-                panic!("failed to verify {}", tarball.display());
-            }
+        if let Some(sha256) = checksum
+            && !self.verify(&tarball, sha256)
+        {
+            panic!("failed to verify {}", tarball.display());
         }
 
         self.unpack(&tarball, &bin_root, prefix);
diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs
index 9492ffaed75..cfb968f79ba 100644
--- a/src/bootstrap/src/lib.rs
+++ b/src/bootstrap/src/lib.rs
@@ -363,19 +363,35 @@ impl Build {
         let in_tree_llvm_info = config.in_tree_llvm_info.clone();
         let in_tree_gcc_info = config.in_tree_gcc_info.clone();
 
-        let initial_target_libdir_str =
-            config.initial_sysroot.join("lib/rustlib").join(config.build).join("lib");
+        let initial_target_libdir =
+            output(Command::new(&config.initial_rustc).args(["--print", "target-libdir"]))
+                .trim()
+                .to_owned();
+
+        let initial_target_dir = Path::new(&initial_target_libdir)
+            .parent()
+            .unwrap_or_else(|| panic!("{initial_target_libdir} has no parent"));
 
-        let initial_target_dir = Path::new(&initial_target_libdir_str).parent().unwrap();
         let initial_lld = initial_target_dir.join("bin").join("rust-lld");
 
-        let initial_relative_libdir = initial_target_dir
-            .ancestors()
-            .nth(2)
-            .unwrap()
-            .strip_prefix(&config.initial_sysroot)
-            .expect("Couldn’t determine initial relative libdir.")
-            .to_path_buf();
+        let initial_relative_libdir = if cfg!(test) {
+            // On tests, bootstrap uses the shim rustc, not the one from the stage0 toolchain.
+            PathBuf::default()
+        } else {
+            let ancestor = initial_target_dir.ancestors().nth(2).unwrap_or_else(|| {
+                panic!("Not enough ancestors for {}", initial_target_dir.display())
+            });
+
+            ancestor
+                .strip_prefix(&config.initial_sysroot)
+                .unwrap_or_else(|_| {
+                    panic!(
+                        "Couldn’t resolve the initial relative libdir from {}",
+                        initial_target_dir.display()
+                    )
+                })
+                .to_path_buf()
+        };
 
         let version = std::fs::read_to_string(src.join("src").join("version"))
             .expect("failed to read src/version");
@@ -1088,8 +1104,15 @@ Executed at: {executed_at}"#,
         &self,
         what: impl Display,
         target: impl Into<Option<TargetSelection>>,
+        custom_stage: Option<u32>,
     ) -> Option<gha::Group> {
-        self.msg(Kind::Check, self.config.stage, what, self.config.build, target)
+        self.msg(
+            Kind::Check,
+            custom_stage.unwrap_or(self.config.stage),
+            what,
+            self.config.build,
+            target,
+        )
     }
 
     #[must_use = "Groups should not be dropped until the Step finishes running"]
@@ -1435,23 +1458,23 @@ Executed at: {executed_at}"#,
         // Look for Wasmtime, and for its default options be sure to disable
         // its caching system since we're executing quite a lot of tests and
         // ideally shouldn't pollute the cache too much.
-        if let Some(path) = finder.maybe_have("wasmtime") {
-            if let Ok(mut path) = path.into_os_string().into_string() {
-                path.push_str(" run -C cache=n --dir .");
-                // Make sure that tests have access to RUSTC_BOOTSTRAP. This (for example) is
-                // required for libtest to work on beta/stable channels.
-                //
-                // NB: with Wasmtime 20 this can change to `-S inherit-env` to
-                // inherit the entire environment rather than just this single
-                // environment variable.
-                path.push_str(" --env RUSTC_BOOTSTRAP");
-
-                if target.contains("wasip2") {
-                    path.push_str(" --wasi inherit-network --wasi allow-ip-name-lookup");
-                }
-
-                return Some(path);
+        if let Some(path) = finder.maybe_have("wasmtime")
+            && let Ok(mut path) = path.into_os_string().into_string()
+        {
+            path.push_str(" run -C cache=n --dir .");
+            // Make sure that tests have access to RUSTC_BOOTSTRAP. This (for example) is
+            // required for libtest to work on beta/stable channels.
+            //
+            // NB: with Wasmtime 20 this can change to `-S inherit-env` to
+            // inherit the entire environment rather than just this single
+            // environment variable.
+            path.push_str(" --env RUSTC_BOOTSTRAP");
+
+            if target.contains("wasip2") {
+                path.push_str(" --wasi inherit-network --wasi allow-ip-name-lookup");
             }
+
+            return Some(path);
         }
 
         None
@@ -1621,12 +1644,12 @@ Executed at: {executed_at}"#,
     /// sha, version, etc.
     fn rust_version(&self) -> String {
         let mut version = self.rust_info().version(self, &self.version);
-        if let Some(ref s) = self.config.description {
-            if !s.is_empty() {
-                version.push_str(" (");
-                version.push_str(s);
-                version.push(')');
-            }
+        if let Some(ref s) = self.config.description
+            && !s.is_empty()
+        {
+            version.push_str(" (");
+            version.push_str(s);
+            version.push(')');
         }
         version
     }
@@ -1744,14 +1767,14 @@ Executed at: {executed_at}"#,
     pub fn copy_link(&self, src: &Path, dst: &Path, file_type: FileType) {
         self.copy_link_internal(src, dst, false);
 
-        if file_type.could_have_split_debuginfo() {
-            if let Some(dbg_file) = split_debuginfo(src) {
-                self.copy_link_internal(
-                    &dbg_file,
-                    &dst.with_extension(dbg_file.extension().unwrap()),
-                    false,
-                );
-            }
+        if file_type.could_have_split_debuginfo()
+            && let Some(dbg_file) = split_debuginfo(src)
+        {
+            self.copy_link_internal(
+                &dbg_file,
+                &dst.with_extension(dbg_file.extension().unwrap()),
+                false,
+            );
         }
     }
 
@@ -1763,13 +1786,14 @@ Executed at: {executed_at}"#,
         if src == dst {
             return;
         }
-        if let Err(e) = fs::remove_file(dst) {
-            if cfg!(windows) && e.kind() != io::ErrorKind::NotFound {
-                // workaround for https://github.com/rust-lang/rust/issues/127126
-                // if removing the file fails, attempt to rename it instead.
-                let now = t!(SystemTime::now().duration_since(SystemTime::UNIX_EPOCH));
-                let _ = fs::rename(dst, format!("{}-{}", dst.display(), now.as_nanos()));
-            }
+        if let Err(e) = fs::remove_file(dst)
+            && cfg!(windows)
+            && e.kind() != io::ErrorKind::NotFound
+        {
+            // workaround for https://github.com/rust-lang/rust/issues/127126
+            // if removing the file fails, attempt to rename it instead.
+            let now = t!(SystemTime::now().duration_since(SystemTime::UNIX_EPOCH));
+            let _ = fs::rename(dst, format!("{}-{}", dst.display(), now.as_nanos()));
         }
         let metadata = t!(src.symlink_metadata(), format!("src = {}", src.display()));
         let mut src = src.to_path_buf();
@@ -1878,10 +1902,10 @@ Executed at: {executed_at}"#,
         chmod(&dst, file_type.perms());
 
         // If this file can have debuginfo, look for split debuginfo and install it too.
-        if file_type.could_have_split_debuginfo() {
-            if let Some(dbg_file) = split_debuginfo(src) {
-                self.install(&dbg_file, dstdir, FileType::Regular);
-            }
+        if file_type.could_have_split_debuginfo()
+            && let Some(dbg_file) = split_debuginfo(src)
+        {
+            self.install(&dbg_file, dstdir, FileType::Regular);
         }
     }
 
diff --git a/src/bootstrap/src/utils/change_tracker.rs b/src/bootstrap/src/utils/change_tracker.rs
index 1d0ea3ebf61..459a34d14cc 100644
--- a/src/bootstrap/src/utils/change_tracker.rs
+++ b/src/bootstrap/src/utils/change_tracker.rs
@@ -46,10 +46,10 @@ pub fn find_recent_config_change_ids(current_id: usize) -> &'static [ChangeInfo]
         // an empty list (it may be due to switching from a recent branch to an
         // older one); otherwise, return the full list (assuming the user provided
         // the incorrect change-id by accident).
-        if let Some(config) = CONFIG_CHANGE_HISTORY.iter().max_by_key(|config| config.change_id) {
-            if current_id > config.change_id {
-                return &[];
-            }
+        if let Some(config) = CONFIG_CHANGE_HISTORY.iter().max_by_key(|config| config.change_id)
+            && current_id > config.change_id
+        {
+            return &[];
         }
 
         CONFIG_CHANGE_HISTORY
@@ -411,4 +411,9 @@ pub const CONFIG_CHANGE_HISTORY: &[ChangeInfo] = &[
         severity: ChangeSeverity::Info,
         summary: "`./x run` now supports running in-tree `rustfmt`, e.g., `./x run rustfmt -- --check /path/to/file.rs`.",
     },
+    ChangeInfo {
+        change_id: 119899,
+        severity: ChangeSeverity::Warning,
+        summary: "Stage0 library no longer matches the in-tree library, which means stage1 compiler now uses the beta library.",
+    },
 ];
diff --git a/src/bootstrap/src/utils/exec.rs b/src/bootstrap/src/utils/exec.rs
index d07300e21d0..64e46f10563 100644
--- a/src/bootstrap/src/utils/exec.rs
+++ b/src/bootstrap/src/utils/exec.rs
@@ -332,16 +332,19 @@ impl Default for CommandOutput {
 
 /// Helper trait to format both Command and BootstrapCommand as a short execution line,
 /// without all the other details (e.g. environment variables).
+#[cfg(feature = "tracing")]
 pub trait FormatShortCmd {
     fn format_short_cmd(&self) -> String;
 }
 
+#[cfg(feature = "tracing")]
 impl FormatShortCmd for BootstrapCommand {
     fn format_short_cmd(&self) -> String {
         self.command.format_short_cmd()
     }
 }
 
+#[cfg(feature = "tracing")]
 impl FormatShortCmd for Command {
     fn format_short_cmd(&self) -> String {
         let program = Path::new(self.get_program());
diff --git a/src/build_helper/src/lib.rs b/src/build_helper/src/lib.rs
index dceb5fdeeea..1f5cf723641 100644
--- a/src/build_helper/src/lib.rs
+++ b/src/build_helper/src/lib.rs
@@ -10,23 +10,24 @@ pub mod util;
 
 /// The default set of crates for opt-dist to collect LLVM profiles.
 pub const LLVM_PGO_CRATES: &[&str] = &[
-    "syn-1.0.89",
-    "cargo-0.60.0",
-    "serde-1.0.136",
-    "ripgrep-13.0.0",
-    "regex-1.5.5",
-    "clap-3.1.6",
-    "hyper-0.14.18",
+    "syn-2.0.101",
+    "cargo-0.87.1",
+    "serde-1.0.219",
+    "ripgrep-14.1.1",
+    "regex-automata-0.4.8",
+    "clap_derive-4.5.32",
+    "hyper-1.6.0",
 ];
 
 /// The default set of crates for opt-dist to collect rustc profiles.
 pub const RUSTC_PGO_CRATES: &[&str] = &[
     "externs",
     "ctfe-stress-5",
-    "cargo-0.60.0",
+    "cargo-0.87.1",
     "token-stream-stress",
     "match-stress",
     "tuple-stress",
-    "diesel-1.4.8",
-    "bitmaps-3.1.0",
+    "diesel-2.2.10",
+    "bitmaps-3.2.1",
+    "serde-1.0.219-new-solver",
 ];
diff --git a/src/ci/citool/src/jobs.rs b/src/ci/citool/src/jobs.rs
index 60cbf50c7a3..2884ae08ea8 100644
--- a/src/ci/citool/src/jobs.rs
+++ b/src/ci/citool/src/jobs.rs
@@ -13,7 +13,7 @@ use crate::utils::load_env_var;
 #[derive(serde::Deserialize, Debug, Clone)]
 #[serde(deny_unknown_fields)]
 pub struct Job {
-    /// Name of the job, e.g. mingw-check
+    /// Name of the job, e.g. mingw-check-1
     pub name: String,
     /// GitHub runner on which the job should be executed
     pub os: String,
diff --git a/src/ci/citool/src/jobs/tests.rs b/src/ci/citool/src/jobs/tests.rs
index a489656fa5d..ed5444d4333 100644
--- a/src/ci/citool/src/jobs/tests.rs
+++ b/src/ci/citool/src/jobs/tests.rs
@@ -1,4 +1,8 @@
+use std::path::Path;
+
+use super::Job;
 use crate::jobs::{JobDatabase, load_job_db};
+use crate::{DOCKER_DIRECTORY, JOBS_YML_PATH, utils};
 
 #[test]
 fn lookup_job_pattern() {
@@ -62,3 +66,65 @@ fn check_pattern(db: &JobDatabase, pattern: &str, expected: &[&str]) {
 
     assert_eq!(jobs, expected);
 }
+
+/// Validate that CodeBuild jobs use Docker images from ghcr.io registry.
+/// This is needed because otherwise from CodeBuild we get rate limited by Docker Hub.
+fn validate_codebuild_image(job: &Job) -> anyhow::Result<()> {
+    let is_job_on_codebuild = job.codebuild.unwrap_or(false);
+    if !is_job_on_codebuild {
+        // Jobs in GitHub Actions don't get rate limited by Docker Hub.
+        return Ok(());
+    }
+
+    let image_name = job.image();
+    // we hardcode host-x86_64 here, because in codebuild we only run jobs for this architecture.
+    let dockerfile_path =
+        Path::new(DOCKER_DIRECTORY).join("host-x86_64").join(&image_name).join("Dockerfile");
+
+    if !dockerfile_path.exists() {
+        return Err(anyhow::anyhow!(
+            "Dockerfile not found for CodeBuild job '{}' at path: {}",
+            job.name,
+            dockerfile_path.display()
+        ));
+    }
+
+    let dockerfile_content = utils::read_to_string(&dockerfile_path)?;
+
+    // Check if all FROM statement uses ghcr.io registry
+    let has_ghcr_from = dockerfile_content
+        .lines()
+        .filter(|line| line.trim_start().to_lowercase().starts_with("from "))
+        .all(|line| line.contains("ghcr.io"));
+
+    if !has_ghcr_from {
+        return Err(anyhow::anyhow!(
+            "CodeBuild job '{}' must use ghcr.io registry in its Dockerfile FROM statement. \
+                Dockerfile path: {dockerfile_path:?}",
+            job.name,
+        ));
+    }
+
+    Ok(())
+}
+
+#[test]
+fn validate_jobs() {
+    let db = {
+        let default_jobs_file = Path::new(JOBS_YML_PATH);
+        let db_str = utils::read_to_string(default_jobs_file).unwrap();
+        load_job_db(&db_str).expect("Failed to load job database")
+    };
+
+    let all_jobs =
+        db.pr_jobs.iter().chain(db.try_jobs.iter()).chain(db.auto_jobs.iter()).collect::<Vec<_>>();
+
+    let errors: Vec<anyhow::Error> =
+        all_jobs.into_iter().filter_map(|job| validate_codebuild_image(job).err()).collect();
+
+    if !errors.is_empty() {
+        let error_messages =
+            errors.into_iter().map(|e| format!("- {e}")).collect::<Vec<_>>().join("\n");
+        panic!("Job validation failed:\n{error_messages}");
+    }
+}
diff --git a/src/ci/citool/src/main.rs b/src/ci/citool/src/main.rs
index 87ce09cfb23..bb73a5ef909 100644
--- a/src/ci/citool/src/main.rs
+++ b/src/ci/citool/src/main.rs
@@ -27,7 +27,7 @@ use crate::test_dashboard::generate_test_dashboard;
 use crate::utils::{load_env_var, output_details};
 
 const CI_DIRECTORY: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/..");
-const DOCKER_DIRECTORY: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/../docker");
+pub const DOCKER_DIRECTORY: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/../docker");
 const JOBS_YML_PATH: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/../github-actions/jobs.yml");
 
 struct GitHubContext {
diff --git a/src/ci/citool/tests/jobs.rs b/src/ci/citool/tests/jobs.rs
index c644f885be3..fcdca899e06 100644
--- a/src/ci/citool/tests/jobs.rs
+++ b/src/ci/citool/tests/jobs.rs
@@ -40,7 +40,7 @@ try-job: dist-i686-msvc"#,
 fn pr_jobs() {
     let stdout = get_matrix("pull_request", "commit", "refs/heads/pr/1234");
     insta::assert_snapshot!(stdout, @r#"
-    jobs=[{"name":"mingw-check","full_name":"PR - mingw-check","os":"ubuntu-24.04","env":{"PR_CI_JOB":1},"free_disk":true},{"name":"mingw-check-tidy","full_name":"PR - mingw-check-tidy","os":"ubuntu-24.04","env":{"PR_CI_JOB":1},"continue_on_error":true,"free_disk":true,"doc_url":"https://foo.bar"}]
+    jobs=[{"name":"mingw-check-1","full_name":"PR - mingw-check-1","os":"ubuntu-24.04","env":{"PR_CI_JOB":1},"free_disk":true},{"name":"mingw-check-2","full_name":"PR - mingw-check-2","os":"ubuntu-24.04","env":{"PR_CI_JOB":1},"free_disk":true},{"name":"mingw-check-tidy","full_name":"PR - mingw-check-tidy","os":"ubuntu-24.04","env":{"PR_CI_JOB":1},"continue_on_error":true,"free_disk":true,"doc_url":"https://foo.bar"}]
     run_type=pr
     "#);
 }
@@ -51,6 +51,8 @@ fn get_matrix(event_name: &str, commit_msg: &str, branch_ref: &str) -> String {
         .env("GITHUB_EVENT_NAME", event_name)
         .env("COMMIT_MESSAGE", commit_msg)
         .env("GITHUB_REF", branch_ref)
+        .env("GITHUB_RUN_ID", "123")
+        .env("GITHUB_RUN_ATTEMPT", "1")
         .stdout(Stdio::piped())
         .output()
         .expect("Failed to execute command");
diff --git a/src/ci/citool/tests/test-jobs.yml b/src/ci/citool/tests/test-jobs.yml
index d81be88b708..d262da11102 100644
--- a/src/ci/citool/tests/test-jobs.yml
+++ b/src/ci/citool/tests/test-jobs.yml
@@ -64,7 +64,9 @@ envs:
 # These jobs automatically inherit envs.pr, to avoid repeating
 # it in each job definition.
 pr:
-  - name: mingw-check
+  - name: mingw-check-1
+    <<: *job-linux-4c
+  - name: mingw-check-2
     <<: *job-linux-4c
   - name: mingw-check-tidy
     continue_on_error: true
diff --git a/src/ci/docker/host-aarch64/aarch64-gnu-llvm-19/Dockerfile b/src/ci/docker/host-aarch64/aarch64-gnu-llvm-19/Dockerfile
new file mode 100644
index 00000000000..2f9d0010573
--- /dev/null
+++ b/src/ci/docker/host-aarch64/aarch64-gnu-llvm-19/Dockerfile
@@ -0,0 +1,58 @@
+FROM ubuntu:24.10
+
+ARG DEBIAN_FRONTEND=noninteractive
+
+RUN apt-get update && apt-get install -y --no-install-recommends \
+  bzip2 \
+  g++ \
+  make \
+  ninja-build \
+  file \
+  curl \
+  ca-certificates \
+  python3 \
+  git \
+  cmake \
+  sudo \
+  gdb \
+  llvm-19-tools \
+  llvm-19-dev \
+  libedit-dev \
+  libssl-dev \
+  pkg-config \
+  zlib1g-dev \
+  xz-utils \
+  nodejs \
+  mingw-w64 \
+  # libgccjit dependencies
+  flex \
+  libmpfr-dev \
+  libgmp-dev \
+  libmpc3 \
+  libmpc-dev \
+  && rm -rf /var/lib/apt/lists/*
+
+COPY scripts/sccache.sh /scripts/
+RUN sh /scripts/sccache.sh
+
+# We are disabling CI LLVM since this builder is intentionally using a host
+# LLVM, rather than the typical src/llvm-project LLVM.
+ENV NO_DOWNLOAD_CI_LLVM 1
+ENV EXTERNAL_LLVM 1
+
+# Using llvm-link-shared due to libffi issues -- see #34486
+ENV RUST_CONFIGURE_ARGS \
+      --build=aarch64-unknown-linux-gnu \
+      --llvm-root=/usr/lib/llvm-19 \
+      --enable-llvm-link-shared \
+      --set rust.randomize-layout=true \
+      --set rust.thin-lto-import-instr-limit=10
+
+COPY scripts/shared.sh /scripts/
+
+ARG SCRIPT_ARG
+
+COPY scripts/stage_2_test_set1.sh /tmp/
+COPY scripts/stage_2_test_set2.sh /tmp/
+
+ENV SCRIPT "/tmp/${SCRIPT_ARG}"
diff --git a/src/ci/docker/host-x86_64/mingw-check/Dockerfile b/src/ci/docker/host-x86_64/mingw-check-1/Dockerfile
index 418408e9242..a877de1f7b2 100644
--- a/src/ci/docker/host-x86_64/mingw-check/Dockerfile
+++ b/src/ci/docker/host-x86_64/mingw-check-1/Dockerfile
@@ -34,38 +34,27 @@ RUN npm install es-check@6.1.1 eslint@8.6.0 typescript@5.7.3 -g
 COPY scripts/sccache.sh /scripts/
 RUN sh /scripts/sccache.sh
 
-COPY host-x86_64/mingw-check/reuse-requirements.txt /tmp/
+COPY host-x86_64/mingw-check-1/reuse-requirements.txt /tmp/
 RUN pip3 install --no-deps --no-cache-dir --require-hashes -r /tmp/reuse-requirements.txt
 
-COPY host-x86_64/mingw-check/check-default-config-profiles.sh /scripts/
-COPY host-x86_64/mingw-check/validate-toolstate.sh /scripts/
-COPY host-x86_64/mingw-check/validate-error-codes.sh /scripts/
+COPY host-x86_64/mingw-check-1/check-default-config-profiles.sh /scripts/
+COPY host-x86_64/mingw-check-1/validate-toolstate.sh /scripts/
+COPY host-x86_64/mingw-check-1/validate-error-codes.sh /scripts/
 
 # Check library crates on all tier 1 targets.
 # We disable optimized compiler built-ins because that requires a C toolchain for the target.
 # We also skip the x86_64-unknown-linux-gnu target as it is well-tested by other jobs.
 ENV SCRIPT \
-           python3 ../x.py check --stage 0 --set build.optimized-compiler-builtins=false core alloc std --target=aarch64-unknown-linux-gnu,i686-pc-windows-msvc,i686-unknown-linux-gnu,x86_64-apple-darwin,x86_64-pc-windows-gnu,x86_64-pc-windows-msvc && \
            /scripts/check-default-config-profiles.sh && \
-           python3 ../x.py check compiletest --set build.compiletest-use-stage0-libtest=true && \
-           python3 ../x.py check --target=x86_64-pc-windows-gnu --host=x86_64-pc-windows-gnu && \
-           python3 ../x.py clippy ci && \
            python3 ../x.py build --stage 0 src/tools/build-manifest && \
            python3 ../x.py test --stage 0 src/tools/compiletest && \
-           python3 ../x.py test --stage 0 core alloc std test proc_macro && \
-           # Build both public and internal documentation.
-           RUSTDOCFLAGS=\"--document-private-items --document-hidden-items\" python3 ../x.py doc --stage 0 library && \
-           mkdir -p /checkout/obj/staging/doc && \
-           cp -r build/x86_64-unknown-linux-gnu/doc /checkout/obj/staging && \
-           RUSTDOCFLAGS=\"--document-private-items --document-hidden-items\" python3 ../x.py doc --stage 0 compiler && \
-           RUSTDOCFLAGS=\"--document-private-items --document-hidden-items\" python3 ../x.py doc --stage 0 library/test && \
+           python3 ../x.py check compiletest --set build.compiletest-use-stage0-libtest=true && \
+           python3 ../x.py check --stage 1 --target=i686-pc-windows-gnu --host=i686-pc-windows-gnu && \
+           python3 ../x.py check --stage 1 --set build.optimized-compiler-builtins=false core alloc std --target=aarch64-unknown-linux-gnu,i686-pc-windows-msvc,i686-unknown-linux-gnu,x86_64-apple-darwin,x86_64-pc-windows-gnu,x86_64-pc-windows-msvc && \
            /scripts/validate-toolstate.sh && \
            /scripts/validate-error-codes.sh && \
            reuse --include-submodules lint && \
            python3 ../x.py test collect-license-metadata && \
            # Runs checks to ensure that there are no issues in our JS code.
            es-check es2019 ../src/librustdoc/html/static/js/*.js && \
-           eslint -c ../src/librustdoc/html/static/.eslintrc.js ../src/librustdoc/html/static/js/*.js && \
-           eslint -c ../src/tools/rustdoc-js/.eslintrc.js ../src/tools/rustdoc-js/tester.js && \
-           eslint -c ../src/tools/rustdoc-gui/.eslintrc.js ../src/tools/rustdoc-gui/tester.js && \
            tsc --project ../src/librustdoc/html/static/js/tsconfig.json
diff --git a/src/ci/docker/host-x86_64/mingw-check/check-default-config-profiles.sh b/src/ci/docker/host-x86_64/mingw-check-1/check-default-config-profiles.sh
index 0c85d4b449d..0c85d4b449d 100755
--- a/src/ci/docker/host-x86_64/mingw-check/check-default-config-profiles.sh
+++ b/src/ci/docker/host-x86_64/mingw-check-1/check-default-config-profiles.sh
diff --git a/src/ci/docker/host-x86_64/mingw-check/reuse-requirements.in b/src/ci/docker/host-x86_64/mingw-check-1/reuse-requirements.in
index d7c2d3fde5b..d7c2d3fde5b 100644
--- a/src/ci/docker/host-x86_64/mingw-check/reuse-requirements.in
+++ b/src/ci/docker/host-x86_64/mingw-check-1/reuse-requirements.in
diff --git a/src/ci/docker/host-x86_64/mingw-check/reuse-requirements.txt b/src/ci/docker/host-x86_64/mingw-check-1/reuse-requirements.txt
index 8784e18864b..8784e18864b 100644
--- a/src/ci/docker/host-x86_64/mingw-check/reuse-requirements.txt
+++ b/src/ci/docker/host-x86_64/mingw-check-1/reuse-requirements.txt
diff --git a/src/ci/docker/host-x86_64/mingw-check/validate-error-codes.sh b/src/ci/docker/host-x86_64/mingw-check-1/validate-error-codes.sh
index e9aa948eb87..e9aa948eb87 100755
--- a/src/ci/docker/host-x86_64/mingw-check/validate-error-codes.sh
+++ b/src/ci/docker/host-x86_64/mingw-check-1/validate-error-codes.sh
diff --git a/src/ci/docker/host-x86_64/mingw-check/validate-toolstate.sh b/src/ci/docker/host-x86_64/mingw-check-1/validate-toolstate.sh
index a5691da8cda..a5691da8cda 100755
--- a/src/ci/docker/host-x86_64/mingw-check/validate-toolstate.sh
+++ b/src/ci/docker/host-x86_64/mingw-check-1/validate-toolstate.sh
diff --git a/src/ci/docker/host-x86_64/mingw-check-2/Dockerfile b/src/ci/docker/host-x86_64/mingw-check-2/Dockerfile
new file mode 100644
index 00000000000..11a66a1c013
--- /dev/null
+++ b/src/ci/docker/host-x86_64/mingw-check-2/Dockerfile
@@ -0,0 +1,38 @@
+FROM ubuntu:22.04
+
+ARG DEBIAN_FRONTEND=noninteractive
+RUN apt-get update && apt-get install -y --no-install-recommends \
+  g++ \
+  make \
+  ninja-build \
+  file \
+  curl \
+  ca-certificates \
+  python3 \
+  python3-pip \
+  python3-pkg-resources \
+  git \
+  cmake \
+  sudo \
+  gdb \
+  xz-utils \
+  libssl-dev \
+  pkg-config \
+  mingw-w64 \
+  && rm -rf /var/lib/apt/lists/*
+
+ENV RUST_CONFIGURE_ARGS="--set rust.validate-mir-opts=3"
+
+COPY scripts/sccache.sh /scripts/
+RUN sh /scripts/sccache.sh
+
+ENV SCRIPT \
+        python3 ../x.py check && \
+        python3 ../x.py clippy ci && \
+        python3 ../x.py test --stage 1 core alloc std test proc_macro && \
+        # Build both public and internal documentation.
+        RUSTDOCFLAGS=\"--document-private-items --document-hidden-items\" python3 ../x.py doc --stage 0 compiler && \
+        RUSTDOCFLAGS=\"--document-private-items --document-hidden-items\" python3 ../x.py doc --stage 1 library && \
+        mkdir -p /checkout/obj/staging/doc && \
+        cp -r build/x86_64-unknown-linux-gnu/doc /checkout/obj/staging && \
+        RUSTDOCFLAGS=\"--document-private-items --document-hidden-items\" python3 ../x.py doc --stage 1 library/test
diff --git a/src/ci/docker/host-x86_64/mingw-check-tidy/Dockerfile b/src/ci/docker/host-x86_64/mingw-check-tidy/Dockerfile
index 9ca8cc740a5..006a697af21 100644
--- a/src/ci/docker/host-x86_64/mingw-check-tidy/Dockerfile
+++ b/src/ci/docker/host-x86_64/mingw-check-tidy/Dockerfile
@@ -24,17 +24,24 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
   mingw-w64 \
   && rm -rf /var/lib/apt/lists/*
 
+COPY scripts/nodejs.sh /scripts/
+RUN sh /scripts/nodejs.sh /node
+ENV PATH="/node/bin:${PATH}"
+
+# Install eslint
+COPY host-x86_64/mingw-check-tidy/eslint.version /tmp/
+
 COPY scripts/sccache.sh /scripts/
 RUN sh /scripts/sccache.sh
 
-COPY host-x86_64/mingw-check/reuse-requirements.txt /tmp/
+COPY host-x86_64/mingw-check-1/reuse-requirements.txt /tmp/
 RUN pip3 install --no-deps --no-cache-dir --require-hashes -r /tmp/reuse-requirements.txt \
     && pip3 install virtualenv
 
-COPY host-x86_64/mingw-check/validate-toolstate.sh /scripts/
-COPY host-x86_64/mingw-check/validate-error-codes.sh /scripts/
+COPY host-x86_64/mingw-check-1/validate-toolstate.sh /scripts/
+COPY host-x86_64/mingw-check-1/validate-error-codes.sh /scripts/
 
 # NOTE: intentionally uses python2 for x.py so we can test it still works.
 # validate-toolstate only runs in our CI, so it's ok for it to only support python3.
-ENV SCRIPT TIDY_PRINT_DIFF=1 python2.7 ../x.py test \
-           --stage 0 src/tools/tidy tidyselftest --extra-checks=py,cpp
+ENV SCRIPT TIDY_PRINT_DIFF=1 npm install eslint@$(head -n 1 /tmp/eslint.version) && \
+ python2.7 ../x.py test --stage 0 src/tools/tidy tidyselftest --extra-checks=py,cpp
diff --git a/src/ci/docker/host-x86_64/mingw-check-tidy/eslint.version b/src/ci/docker/host-x86_64/mingw-check-tidy/eslint.version
new file mode 100644
index 00000000000..1acea15afd6
--- /dev/null
+++ b/src/ci/docker/host-x86_64/mingw-check-tidy/eslint.version
@@ -0,0 +1 @@
+8.6.0
\ No newline at end of file
diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-distcheck/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu-distcheck/Dockerfile
index 2217e6ee704..98fd31a22e9 100644
--- a/src/ci/docker/host-x86_64/x86_64-gnu-distcheck/Dockerfile
+++ b/src/ci/docker/host-x86_64/x86_64-gnu-distcheck/Dockerfile
@@ -1,3 +1,15 @@
+# Runs `distcheck`, which is a collection of smoke tests:
+# 
+# - Run `make check` from an unpacked dist tarball to make sure we can at the
+#   minimum run check steps from those sources.
+# - Check that selected dist components at least have expected directory shape
+#   and crate manifests that cargo can generate a lockfile from.
+#
+# Refer to `src/bootstrap/src/core/build_steps/test.rs` `Distcheck::run` for
+# specifics.
+#
+# FIXME(#136822): dist components are generally under-tested.
+
 FROM ubuntu:22.04
 
 ARG DEBIAN_FRONTEND=noninteractive
diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-nopt/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu-nopt/Dockerfile
index d8113e06723..1b57ae7c8da 100644
--- a/src/ci/docker/host-x86_64/x86_64-gnu-nopt/Dockerfile
+++ b/src/ci/docker/host-x86_64/x86_64-gnu-nopt/Dockerfile
@@ -29,5 +29,5 @@ RUN echo "optimize = false" >> /config/nopt-std-config.toml
 ENV RUST_CONFIGURE_ARGS --build=x86_64-unknown-linux-gnu \
   --disable-optimize-tests \
   --set rust.test-compare-mode
-ENV SCRIPT python3 ../x.py test --stage 0 --config /config/nopt-std-config.toml library/std \
+ENV SCRIPT python3 ../x.py test --stage 1 --config /config/nopt-std-config.toml library/std \
   && python3 ../x.py --stage 2 test
diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-tools/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu-tools/Dockerfile
index 05c90af7807..e770c58bd9c 100644
--- a/src/ci/docker/host-x86_64/x86_64-gnu-tools/Dockerfile
+++ b/src/ci/docker/host-x86_64/x86_64-gnu-tools/Dockerfile
@@ -1,4 +1,4 @@
-FROM ubuntu:22.04
+FROM ghcr.io/rust-lang/ubuntu:22.04
 
 ARG DEBIAN_FRONTEND=noninteractive
 RUN apt-get update && apt-get install -y --no-install-recommends \
diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-tools/checktools.sh b/src/ci/docker/host-x86_64/x86_64-gnu-tools/checktools.sh
index 9222710b843..62e0451814b 100755
--- a/src/ci/docker/host-x86_64/x86_64-gnu-tools/checktools.sh
+++ b/src/ci/docker/host-x86_64/x86_64-gnu-tools/checktools.sh
@@ -53,8 +53,8 @@ MIRIFLAGS="-Zmiri-force-intrinsic-fallback --cfg force_intrinsic_fallback -O -Zm
 case $HOST_TARGET in
   x86_64-unknown-linux-gnu)
     # Only this branch runs in PR CI.
-    # Fully test all main OSes, including a 32bit target.
-    python3 "$X_PY" test --stage 2 src/tools/miri src/tools/miri/cargo-miri --target x86_64-apple-darwin
+    # Fully test all main OSes, and all main architectures.
+    python3 "$X_PY" test --stage 2 src/tools/miri src/tools/miri/cargo-miri --target aarch64-apple-darwin
     python3 "$X_PY" test --stage 2 src/tools/miri src/tools/miri/cargo-miri --target i686-pc-windows-msvc
     # Only run "pass" tests for the remaining targets, which is quite a bit faster.
     python3 "$X_PY" test --stage 2 src/tools/miri --target x86_64-pc-windows-gnu --test-args pass
@@ -69,7 +69,7 @@ case $HOST_TARGET in
     #FIXME: Re-enable this once CI issues are fixed
     # See <https://github.com/rust-lang/rust/issues/127883>
     # For now, these tests are moved to `x86_64-msvc-ext2` in `src/ci/github-actions/jobs.yml`.
-    #python3 "$X_PY" test --stage 2 src/tools/miri --target aarch64-apple-darwin --test-args pass
+    #python3 "$X_PY" test --stage 2 src/tools/miri --target x86_64-apple-darwin --test-args pass
     ;;
   *)
     echo "FATAL: unexpected host $HOST_TARGET"
diff --git a/src/ci/docker/scripts/x86_64-gnu-llvm.sh b/src/ci/docker/scripts/x86_64-gnu-llvm.sh
index e0435a3ff5c..5fa17d954c3 100755
--- a/src/ci/docker/scripts/x86_64-gnu-llvm.sh
+++ b/src/ci/docker/scripts/x86_64-gnu-llvm.sh
@@ -2,8 +2,8 @@
 
 set -ex
 
-# NOTE: intentionally uses all of `x.py`, `x`, and `x.ps1` to make sure they all work on Linux.
-../x.py --stage 2 test --skip src/tools/tidy
+# NOTE: intentionally uses `x`, and `x.ps1` to make sure they work on Linux.
+#       Make sure that `x.py` is tested elsewhere.
 
 # Run the `mir-opt` tests again but this time for a 32-bit target.
 # This enforces that tests using `// EMIT_MIR_FOR_EACH_BIT_WIDTH` have
diff --git a/src/ci/github-actions/jobs.yml b/src/ci/github-actions/jobs.yml
index 2daa8624605..543b79b2f5d 100644
--- a/src/ci/github-actions/jobs.yml
+++ b/src/ci/github-actions/jobs.yml
@@ -30,8 +30,6 @@ runners:
     os: windows-2022
     <<: *base-job
 
-  # FIXME(#141022): Windows Server 2025 20250504.1.0 currently experiences
-  # insufficient disk space.
   - &job-windows-25
     os: windows-2025
     <<: *base-job
@@ -72,7 +70,6 @@ envs:
   env-x86_64-apple-tests: &env-x86_64-apple-tests
     SCRIPT: ./x.py check compiletest --set build.compiletest-use-stage0-libtest=true && ./x.py --stage 2 test --skip tests/ui --skip tests/rustdoc -- --exact
     RUST_CONFIGURE_ARGS: --build=x86_64-apple-darwin --enable-sanitizers --enable-profiler --set rust.jemalloc
-    RUSTC_RETRY_LINKER_ON_SEGFAULT: 1
     # Ensure that host tooling is tested on our minimum supported macOS version.
     MACOSX_DEPLOYMENT_TARGET: 10.12
     MACOSX_STD_DEPLOYMENT_TARGET: 10.12
@@ -112,7 +109,9 @@ envs:
 # These jobs automatically inherit envs.pr, to avoid repeating
 # it in each job definition.
 pr:
-  - name: mingw-check
+  - name: mingw-check-1
+    <<: *job-linux-4c
+  - name: mingw-check-2
     <<: *job-linux-4c
   - name: mingw-check-tidy
     continue_on_error: true
@@ -121,9 +120,19 @@ pr:
     env:
       ENABLE_GCC_CODEGEN: "1"
       DOCKER_SCRIPT: x86_64-gnu-llvm.sh
-    <<: *job-linux-16c
+    <<: *job-linux-4c
+  - name: aarch64-gnu-llvm-19-1
+    env:
+      IMAGE: aarch64-gnu-llvm-19
+      DOCKER_SCRIPT: stage_2_test_set1.sh
+    <<: *job-aarch64-linux
+  - name: aarch64-gnu-llvm-19-2
+    env:
+      IMAGE: aarch64-gnu-llvm-19
+      DOCKER_SCRIPT: stage_2_test_set2.sh
+    <<: *job-aarch64-linux
   - name: x86_64-gnu-tools
-    <<: *job-linux-16c
+    <<: *job-linux-36c-codebuild
 
 # Jobs that run when you perform a try build (@bors try)
 # These jobs automatically inherit envs.try, to avoid repeating
@@ -132,7 +141,7 @@ try:
   - name: dist-x86_64-linux
     env:
       CODEGEN_BACKENDS: llvm,cranelift
-    <<: *job-linux-16c
+    <<: *job-linux-36c-codebuild
 
 # Main CI jobs that have to be green to merge a commit into master
 # These jobs automatically inherit envs.auto, to avoid repeating
@@ -228,7 +237,7 @@ auto:
   - name: dist-x86_64-linux
     env:
       CODEGEN_BACKENDS: llvm,cranelift
-    <<: *job-linux-16c
+    <<: *job-linux-36c-codebuild
 
   - name: dist-x86_64-linux-alt
     env:
@@ -272,11 +281,14 @@ auto:
     env:
       IMAGE: i686-gnu-nopt
       DOCKER_SCRIPT: >-
-        python3 ../x.py test --stage 0 --config /config/nopt-std-config.toml library/std &&
+        python3 ../x.py test --stage 1 --config /config/nopt-std-config.toml library/std &&
         /scripts/stage_2_test_set2.sh
     <<: *job-linux-4c
 
-  - name: mingw-check
+  - name: mingw-check-1
+    <<: *job-linux-4c
+
+  - name: mingw-check-2
     <<: *job-linux-4c
 
   - name: test-various
@@ -332,7 +344,7 @@ auto:
     env:
       RUST_BACKTRACE: 1
       IMAGE: x86_64-gnu-llvm-20
-      DOCKER_SCRIPT: stage_2_test_set1.sh
+      DOCKER_SCRIPT: stage_2_test_set2.sh
     <<: *job-linux-4c
 
   # Skip tests that run in x86_64-gnu-llvm-20-{1,3}
@@ -357,7 +369,7 @@ auto:
     env:
       RUST_BACKTRACE: 1
       IMAGE: x86_64-gnu-llvm-19
-      DOCKER_SCRIPT: stage_2_test_set1.sh
+      DOCKER_SCRIPT: stage_2_test_set2.sh
     <<: *job-linux-4c
 
   # Skip tests that run in x86_64-gnu-llvm-19-{1,3}
@@ -392,7 +404,6 @@ auto:
     env:
       SCRIPT: ./x.py dist bootstrap --include-default-paths --host=x86_64-apple-darwin --target=x86_64-apple-darwin
       RUST_CONFIGURE_ARGS: --enable-full-tools --enable-sanitizers --enable-profiler --set rust.jemalloc --set rust.lto=thin --set rust.codegen-units=1
-      RUSTC_RETRY_LINKER_ON_SEGFAULT: 1
       # Ensure that host tooling is built to support our minimum support macOS version.
       MACOSX_DEPLOYMENT_TARGET: 10.12
       MACOSX_STD_DEPLOYMENT_TARGET: 10.12
@@ -410,7 +421,6 @@ auto:
       # Mac Catalyst cannot currently compile the sanitizer:
       # https://github.com/rust-lang/rust/issues/129069
       RUST_CONFIGURE_ARGS: --enable-sanitizers --enable-profiler --set rust.jemalloc --set target.aarch64-apple-ios-macabi.sanitizers=false --set target.x86_64-apple-ios-macabi.sanitizers=false
-      RUSTC_RETRY_LINKER_ON_SEGFAULT: 1
       # Ensure that host tooling is built to support our minimum support macOS version.
       # FIXME(madsmtm): This might be redundant, as we're not building host tooling here (?)
       MACOSX_DEPLOYMENT_TARGET: 10.12
@@ -443,7 +453,6 @@ auto:
         --set llvm.ninja=false
         --set rust.lto=thin
         --set rust.codegen-units=1
-      RUSTC_RETRY_LINKER_ON_SEGFAULT: 1
       SELECT_XCODE: /Applications/Xcode_15.4.app
       USE_XCODE_CLANG: 1
       # Aarch64 tooling only needs to support macOS 11.0 and up as nothing else
@@ -459,12 +468,13 @@ auto:
 
   - name: aarch64-apple
     env:
-      SCRIPT: ./x.py --stage 2 test --host=aarch64-apple-darwin --target=aarch64-apple-darwin
+      SCRIPT: >
+        ./x.py --stage 2 test --host=aarch64-apple-darwin --target=aarch64-apple-darwin &&
+        ./x.py --stage 2 test --host=aarch64-apple-darwin --target=aarch64-apple-darwin src/tools/cargo
       RUST_CONFIGURE_ARGS: >-
         --enable-sanitizers
         --enable-profiler
         --set rust.jemalloc
-      RUSTC_RETRY_LINKER_ON_SEGFAULT: 1
       SELECT_XCODE: /Applications/Xcode_15.4.app
       USE_XCODE_CLANG: 1
       # Aarch64 tooling only needs to support macOS 11.0 and up as nothing else
@@ -485,17 +495,13 @@ auto:
     env:
       RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-sanitizers --enable-profiler
       SCRIPT: make ci-msvc-py
-    # FIXME(#141022): Windows Server 2025 20250504.1.0 currently experiences
-    # insufficient disk space.
-    <<: *job-windows
+    <<: *job-windows-25
 
   - name: x86_64-msvc-2
     env:
       RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-sanitizers --enable-profiler
       SCRIPT: make ci-msvc-ps1
-    # FIXME(#141022): Windows Server 2025 20250504.1.0 currently experiences
-    # insufficient disk space.
-    <<: *job-windows
+    <<: *job-windows-25
 
   # i686-msvc is split into two jobs to run tests in parallel.
   - name: i686-msvc-1
@@ -523,11 +529,13 @@ auto:
   - name: x86_64-msvc-ext2
     env:
       SCRIPT: >
-        python x.py test --stage 2 src/tools/miri --target aarch64-apple-darwin --test-args pass &&
+        python x.py test --stage 2 src/tools/miri --target x86_64-apple-darwin --test-args pass &&
         python x.py test --stage 2 src/tools/miri --target x86_64-pc-windows-gnu --test-args pass &&
         python x.py miri --stage 2 library/core --test-args notest &&
         python x.py miri --stage 2 library/alloc --test-args notest &&
         python x.py miri --stage 2 library/std --test-args notest
+      # The last 3 lines smoke-test `x.py miri`. This doesn't run any actual tests (that would take
+      # too long), but it ensures that the crates build properly when tested with Miri.
       RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-lld
     <<: *job-windows
 
diff --git a/src/doc/book b/src/doc/book
-Subproject 230c68bc1e08f5f3228384a28cc228c81dfbd10
+Subproject 634724ea85ebb08a542970bf8871ac8b0f77fd1
diff --git a/src/doc/embedded-book b/src/doc/embedded-book
-Subproject 0b8219ac23a3e09464e4e0166c768cf1c4bba0d
+Subproject 10fa1e084365f23f24ad0000df541923385b73b
diff --git a/src/doc/nomicon b/src/doc/nomicon
-Subproject c76a20f0d987145dcedf05c5c073ce8d91f2e82
+Subproject 8b61acfaea822e9ac926190bc8f15791c33336e
diff --git a/src/doc/reference b/src/doc/reference
-Subproject 118fd1f1f0854f50e3ae1fe4b64862aad23009c
+Subproject 8e0f593a30f3b56ddb0908fb7ab9249974e0873
diff --git a/src/doc/rust-by-example b/src/doc/rust-by-example
-Subproject c9d151f9147c4808c77f0375ba3fa5d54443cb9
+Subproject 21f4e32b8b40d36453fae16ec07ad4b857c445b
diff --git a/src/doc/rustc-dev-guide/.mailmap b/src/doc/rustc-dev-guide/.mailmap
index 1a1f6ffb608..907495ed10d 100644
--- a/src/doc/rustc-dev-guide/.mailmap
+++ b/src/doc/rustc-dev-guide/.mailmap
@@ -3,3 +3,4 @@ Jynn Nelson <github@jyn.dev> <joshua@yottadb.com>
 Jynn Nelson <github@jyn.dev> <jyn.nelson@redjack.com>
 Jynn Nelson <github@jyn.dev> <jnelson@cloudflare.com>
 Jynn Nelson <github@jyn.dev>
+Tshepang Mbambo <hopsi@tuta.io> <tshepang@gmail.com>
diff --git a/src/doc/rustc-dev-guide/rust-version b/src/doc/rustc-dev-guide/rust-version
index 0d889a5d5b9..b1e9eec529e 100644
--- a/src/doc/rustc-dev-guide/rust-version
+++ b/src/doc/rustc-dev-guide/rust-version
@@ -1 +1 @@
-e42bbfe1f7c26f8760a99c4b1f27d33aba1040bb
+99e7c15e81385b38a8186b51edc4577d5d7b5bdd
diff --git a/src/doc/rustc-dev-guide/src/appendix/compiler-lecture.md b/src/doc/rustc-dev-guide/src/appendix/compiler-lecture.md
index dabd2f08703..90c4097cc3e 100644
--- a/src/doc/rustc-dev-guide/src/appendix/compiler-lecture.md
+++ b/src/doc/rustc-dev-guide/src/appendix/compiler-lecture.md
@@ -46,3 +46,4 @@ These are videos where various experts explain different parts of the compiler:
 
 ## Code Generation
 - [January 2019: Cranelift](https://www.youtube.com/watch?v=9OIA7DTFQWU)
+- [December 2024: LLVM Developers' Meeting - Rust ❤️ LLVM](https://www.youtube.com/watch?v=Kqz-umsAnk8)
\ No newline at end of file
diff --git a/src/doc/rustc-dev-guide/src/borrow_check/two_phase_borrows.md b/src/doc/rustc-dev-guide/src/borrow_check/two_phase_borrows.md
index bcd48782110..b77ae09465c 100644
--- a/src/doc/rustc-dev-guide/src/borrow_check/two_phase_borrows.md
+++ b/src/doc/rustc-dev-guide/src/borrow_check/two_phase_borrows.md
@@ -76,7 +76,7 @@ borrow.
 [`AutoBorrow`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/adjustment/enum.AutoBorrow.html
 [converted]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_build/thir/cx/expr/trait.ToBorrowKind.html#method.to_borrow_kind
 [`BorrowKind`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/enum.BorrowKind.html
-[`GatherBorrows`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/visit/trait.Visitor.html#method.visit_local
+[`GatherBorrows`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_borrowck/borrow_set/struct.GatherBorrows.html
 [`BorrowData`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_borrowck/borrow_set/struct.BorrowData.html
 
 ## Checking two-phase borrows
diff --git a/src/doc/rustc-dev-guide/src/building/bootstrapping/what-bootstrapping-does.md b/src/doc/rustc-dev-guide/src/building/bootstrapping/what-bootstrapping-does.md
index a2930b3e427..2793ad43815 100644
--- a/src/doc/rustc-dev-guide/src/building/bootstrapping/what-bootstrapping-does.md
+++ b/src/doc/rustc-dev-guide/src/building/bootstrapping/what-bootstrapping-does.md
@@ -45,13 +45,13 @@ compiler.
 
 ```mermaid
 graph TD
-    s0c["stage0 compiler (1.63)"]:::downloaded -->|A| s0l("stage0 std (1.64)"):::with-s0c;
+    s0c["stage0 compiler (1.86.0-beta.1)"]:::downloaded -->|A| s0l("stage0 std (1.86.0-beta.1)"):::downloaded;
     s0c & s0l --- stepb[ ]:::empty;
-    stepb -->|B| s0ca["stage0 compiler artifacts (1.64)"]:::with-s0c;
-    s0ca -->|copy| s1c["stage1 compiler (1.64)"]:::with-s0c;
-    s1c -->|C| s1l("stage1 std (1.64)"):::with-s1c;
+    stepb -->|B| s0ca["stage0 compiler artifacts (1.87.0-dev)"]:::with-s0c;
+    s0ca -->|copy| s1c["stage1 compiler (1.87.0-dev)"]:::with-s0c;
+    s1c -->|C| s1l("stage1 std (1.87.0-dev)"):::with-s1c;
     s1c & s1l --- stepd[ ]:::empty;
-    stepd -->|D| s1ca["stage1 compiler artifacts (1.64)"]:::with-s1c;
+    stepd -->|D| s1ca["stage1 compiler artifacts (1.87.0-dev)"]:::with-s1c;
     s1ca -->|copy| s2c["stage2 compiler"]:::with-s1c;
 
     classDef empty width:0px,height:0px;
@@ -62,19 +62,21 @@ graph TD
 
 ### Stage 0: the pre-compiled compiler
 
-The stage0 compiler is usually the current _beta_ `rustc` compiler and its
+The stage0 compiler is by default the very recent _beta_ `rustc` compiler and its
 associated dynamic libraries, which `./x.py` will download for you. (You can
-also configure `./x.py` to use something else.)
+also configure `./x.py` to change stage0 to something else.)
 
-The stage0 compiler is then used only to compile [`src/bootstrap`],
-[`library/std`], and [`compiler/rustc`]. When assembling the libraries and
-binaries that will become the stage1 `rustc` compiler, the freshly compiled
-`std` and `rustc` are used. There are two concepts at play here: a compiler
-(with its set of dependencies) and its 'target' or 'object' libraries (`std` and
-`rustc`). Both are staged, but in a staggered manner.
+The precompiled stage0 compiler is then used only to compile [`src/bootstrap`] and [`compiler/rustc`]
+with precompiled stage0 std.
+
+Note that to build the stage1 compiler we use the precompiled stage0 compiler and std.
+Therefore, to use a compiler with a std that is freshly built from the tree, you need to
+build the stage2 compiler.
+
+There are two concepts at play here: a compiler (with its set of dependencies) and its
+'target' or 'object' libraries (`std` and `rustc`). Both are staged, but in a staggered manner.
 
 [`compiler/rustc`]: https://github.com/rust-lang/rust/tree/master/compiler/rustc
-[`library/std`]: https://github.com/rust-lang/rust/tree/master/library/std
 [`src/bootstrap`]: https://github.com/rust-lang/rust/tree/master/src/bootstrap
 
 ### Stage 1: from current code, by an earlier compiler
@@ -84,16 +86,14 @@ The rustc source code is then compiled with the `stage0` compiler to produce the
 
 ### Stage 2: the truly current compiler
 
-We then rebuild our `stage1` compiler with itself to produce the `stage2`
+We then rebuild the compiler using `stage1` compiler with in-tree std to produce the `stage2`
 compiler.
 
-In theory, the `stage1` compiler is functionally identical to the `stage2`
-compiler, but in practice there are subtle differences. In particular, the
-`stage1` compiler itself was built by `stage0` and hence not by the source in
-your working directory. This means that the ABI generated by the `stage0`
-compiler may not match the ABI that would have been made by the `stage1`
-compiler, which can cause problems for dynamic libraries, tests, and tools using
-`rustc_private`.
+The `stage1` compiler itself was built by precompiled `stage0` compiler and std
+and hence not by the source in your working directory. This means that the ABI
+generated by the `stage0` compiler may not match the ABI that would have been made
+by the `stage1` compiler, which can cause problems for dynamic libraries, tests
+and tools using `rustc_private`.
 
 Note that the `proc_macro` crate avoids this issue with a `C` FFI layer called
 `proc_macro::bridge`, allowing it to be used with `stage1`.
@@ -101,9 +101,10 @@ Note that the `proc_macro` crate avoids this issue with a `C` FFI layer called
 The `stage2` compiler is the one distributed with `rustup` and all other install
 methods. However, it takes a very long time to build because one must first
 build the new compiler with an older compiler and then use that to build the new
-compiler with itself. For development, you usually only want the `stage1`
-compiler, which you can build with `./x build library`. See [Building the
-compiler](../how-to-build-and-run.html#building-the-compiler).
+compiler with itself.
+
+For development, you usually only want to use `--stage 1` flag to build things.
+See [Building the compiler](../how-to-build-and-run.html#building-the-compiler).
 
 ### Stage 3: the same-result test
 
@@ -114,10 +115,11 @@ something has broken.
 ### Building the stages
 
 The script [`./x`] tries to be helpful and pick the stage you most likely meant
-for each subcommand. These defaults are as follows:
+for each subcommand. Here are some `x` commands with their default stages:
 
-- `check`: `--stage 0`
-- `doc`: `--stage 0`
+- `check`: `--stage 1`
+- `clippy`: `--stage 1`
+- `doc`: `--stage 1`
 - `build`: `--stage 1`
 - `test`: `--stage 1`
 - `dist`: `--stage 2`
@@ -191,8 +193,8 @@ include, but are not limited to:
   without building `rustc` from source ('build with `stage0`, then test the
   artifacts'). If you're working on the standard library, this is normally the
   test command you want.
-- `./x build --stage 0` means to build with the beta `rustc`.
-- `./x doc --stage 0` means to document using the beta `rustdoc`.
+- `./x build --stage 0` means to build with the stage0 `rustc`.
+- `./x doc --stage 0` means to document using the stage0 `rustdoc`.
 
 #### Examples of what *not* to do
 
@@ -208,9 +210,6 @@ include, but are not limited to:
 
 ### Building vs. running
 
-Note that `build --stage N compiler/rustc` **does not** build the stage N
-compiler: instead it builds the stage N+1 compiler _using_ the stage N compiler.
-
 In short, _stage 0 uses the `stage0` compiler to create `stage0` artifacts which
 will later be uplifted to be the stage1 compiler_.
 
@@ -268,23 +267,6 @@ However, when cross-compiling, `stage1` `std` will only run on the host. So the
 
 (See in the table how `stage2` only builds non-host `std` targets).
 
-### Why does only libstd use `cfg(bootstrap)`?
-
-For docs on `cfg(bootstrap)` itself, see [Complications of
-Bootstrapping](#complications-of-bootstrapping).
-
-The `rustc` generated by the `stage0` compiler is linked to the freshly-built
-`std`, which means that for the most part only `std` needs to be `cfg`-gated, so
-that `rustc` can use features added to `std` immediately after their addition,
-without need for them to get into the downloaded `beta` compiler.
-
-Note this is different from any other Rust program: `stage1` `rustc` is built by
-the _beta_ compiler, but using the _master_ version of `libstd`!
-
-The only time `rustc` uses `cfg(bootstrap)` is when it adds internal lints that
-use diagnostic items, or when it uses unstable library features that were
-recently changed.
-
 ### What is a 'sysroot'?
 
 When you build a project with `cargo`, the build artifacts for dependencies are
@@ -459,7 +441,6 @@ compiler itself uses to run. These aren't actually used by artifacts the new
 compiler generates. This step also copies the `rustc` and `rustdoc` binaries we
 generated into `build/$HOST/stage/bin`.
 
-The `stage1/bin/rustc` is a fully functional compiler, but it doesn't yet have
-any libraries to link built binaries or libraries to. The next 3 steps will
-provide those libraries for it; they are mostly equivalent to constructing the
-`stage1/bin` compiler so we don't go through them individually here.
+The `stage1/bin/rustc` is a fully functional compiler built with stage0 (precompiled) compiler and std.
+To use a compiler built entirely from source with the in-tree compiler and std, you need to build the
+stage2 compiler, which is compiled using the stage1 (in-tree) compiler and std.
diff --git a/src/doc/rustc-dev-guide/src/building/how-to-build-and-run.md b/src/doc/rustc-dev-guide/src/building/how-to-build-and-run.md
index c3c1c41e3f6..c4783002b85 100644
--- a/src/doc/rustc-dev-guide/src/building/how-to-build-and-run.md
+++ b/src/doc/rustc-dev-guide/src/building/how-to-build-and-run.md
@@ -217,7 +217,6 @@ probably the best "go to" command for building a local compiler:
 This may *look* like it only builds the standard library, but that is not the case.
 What this command does is the following:
 
-- Build `std` using the stage0 compiler
 - Build `rustc` using the stage0 compiler
   - This produces the stage1 compiler
 - Build `std` using the stage1 compiler
@@ -241,8 +240,7 @@ build. The **full** `rustc` build (what you get with `./x build
 --stage 2 compiler/rustc`) has quite a few more steps:
 
 - Build `rustc` with the stage1 compiler.
-  - The resulting compiler here is called the "stage2" compiler.
-- Build `std` with stage2 compiler.
+  - The resulting compiler here is called the "stage2" compiler, which uses stage1 std from the previous command.
 - Build `librustdoc` and a bunch of other things with the stage2 compiler.
 
 You almost never need to do this.
@@ -250,14 +248,14 @@ You almost never need to do this.
 ### Build specific components
 
 If you are working on the standard library, you probably don't need to build
-the compiler unless you are planning to use a recently added nightly feature.
-Instead, you can just build using the bootstrap compiler.
+every other default component. Instead, you can build a specific component by
+providing its name, like this:
 
 ```bash
-./x build --stage 0 library
+./x build --stage 1 library
 ```
 
-If you choose the `library` profile when running `x setup`, you can omit `--stage 0` (it's the
+If you choose the `library` profile when running `x setup`, you can omit `--stage 1` (it's the
 default).
 
 ## Creating a rustup toolchain
@@ -271,7 +269,6 @@ you will likely need to build at some point; for example, if you want
 to run the entire test suite).
 
 ```bash
-rustup toolchain link stage0 build/host/stage0-sysroot # beta compiler + stage0 std
 rustup toolchain link stage1 build/host/stage1
 rustup toolchain link stage2 build/host/stage2
 ```
diff --git a/src/doc/rustc-dev-guide/src/building/new-target.md b/src/doc/rustc-dev-guide/src/building/new-target.md
index 09ffbe8c882..8d323ba9646 100644
--- a/src/doc/rustc-dev-guide/src/building/new-target.md
+++ b/src/doc/rustc-dev-guide/src/building/new-target.md
@@ -85,7 +85,7 @@ Look for existing targets to use as examples.
 After adding your target to the `rustc_target` crate you may want to add
 `core`, `std`, ... with support for your new target. In that case you will
 probably need access to some `target_*` cfg. Unfortunately when building with
-stage0 (the beta compiler), you'll get an error that the target cfg is
+stage0 (a precompiled compiler), you'll get an error that the target cfg is
 unexpected because stage0 doesn't know about the new target specification and
 we pass `--check-cfg` in order to tell it to check.
 
diff --git a/src/doc/rustc-dev-guide/src/building/suggested.md b/src/doc/rustc-dev-guide/src/building/suggested.md
index f8a28b7f2e9..76c39608449 100644
--- a/src/doc/rustc-dev-guide/src/building/suggested.md
+++ b/src/doc/rustc-dev-guide/src/building/suggested.md
@@ -91,7 +91,7 @@ for two reasons:
   additional rebuilds in some cases.
 
 To avoid these problems:
-- Add `--build-dir=build-rust-analyzer` to all of the custom `x` commands in
+- Add `--build-dir=build/rust-analyzer` to all of the custom `x` commands in
   your editor's rust-analyzer configuration.
   (Feel free to choose a different directory name if desired.)
 - Modify the `rust-analyzer.rustfmt.overrideCommand` setting so that it points
@@ -100,10 +100,7 @@ To avoid these problems:
   copy of `rust-analyzer-proc-macro-srv` in that other build directory.
 
 Using separate build directories for command-line builds and rust-analyzer
-requires extra disk space, and also means that running `./x clean` on the
-command-line will not clean out the separate build directory. To clean the
-separate build directory, run `./x clean --build-dir=build-rust-analyzer`
-instead.
+requires extra disk space.
 
 ### Visual Studio Code
 
@@ -137,7 +134,7 @@ Task] instead:
 
 ### Neovim
 
-For Neovim users there are several options for configuring for rustc. The
+For Neovim users, there are a few options. The
 easiest way is by using [neoconf.nvim](https://github.com/folke/neoconf.nvim/),
 which allows for project-local configuration files with the native LSP. The
 steps for how to use it are below. Note that they require rust-analyzer to
@@ -310,51 +307,15 @@ lets you use `cargo fmt`.
 [the section on vscode]: suggested.md#configuring-rust-analyzer-for-rustc
 [the section on rustup]: how-to-build-and-run.md?highlight=rustup#creating-a-rustup-toolchain
 
-## Faster builds with `--keep-stage`.
+## Faster Builds with CI-rustc  
 
-Sometimes just checking whether the compiler builds is not enough. A common
-example is that you need to add a `debug!` statement to inspect the value of
-some state or better understand the problem. In that case, you don't really need
-a full build. By bypassing bootstrap's cache invalidation, you can often get
-these builds to complete very fast (e.g., around 30 seconds). The only catch is
-this requires a bit of fudging and may produce compilers that don't work (but
-that is easily detected and fixed).
-
-The sequence of commands you want is as follows:
-
-- Initial build: `./x build library`
-  - As [documented previously], this will build a functional stage1 compiler as
-    part of running all stage0 commands (which include building a `std`
-    compatible with the stage1 compiler) as well as the first few steps of the
-    "stage 1 actions" up to "stage1 (sysroot stage1) builds std".
-- Subsequent builds: `./x build library --keep-stage 1`
-  - Note that we added the `--keep-stage 1` flag here
-
-[documented previously]: ./how-to-build-and-run.md#building-the-compiler
-
-As mentioned, the effect of `--keep-stage 1` is that we just _assume_ that the
-old standard library can be re-used. If you are editing the compiler, this is
-almost always true: you haven't changed the standard library, after all. But
-sometimes, it's not true: for example, if you are editing the "metadata" part of
-the compiler, which controls how the compiler encodes types and other states
-into the `rlib` files, or if you are editing things that wind up in the metadata
-(such as the definition of the MIR).
-
-**The TL;DR is that you might get weird behavior from a compile when using
-`--keep-stage 1`** -- for example, strange [ICEs](../appendix/glossary.html#ice)
-or other panics. In that case, you should simply remove the `--keep-stage 1`
-from the command and rebuild. That ought to fix the problem.
-
-You can also use `--keep-stage 1` when running tests. Something like this:
-
-- Initial test run: `./x test tests/ui`
-- Subsequent test run: `./x test tests/ui --keep-stage 1`
-
-### Iterating the standard library with `--keep-stage`
-
-If you are making changes to the standard library, you can use `./x build
---keep-stage 0 library` to iteratively rebuild the standard library without
-rebuilding the compiler.
+If you are not working on the compiler, you often don't need to build the compiler tree.
+For example, you can skip building the compiler and only build the `library` tree or the
+tools under `src/tools`. To achieve that, you have to enable this by setting the `download-rustc`
+option in your configuration. This tells bootstrap to use the latest nightly compiler for `stage > 0`
+steps, meaning it will have two precompiled compilers: stage0 compiler and `download-rustc` compiler
+for `stage > 0` steps. This way, it will never need to build the in-tree compiler. As a result, your
+build time will be significantly reduced by not building the in-tree compiler.
 
 ## Using incremental compilation
 
diff --git a/src/doc/rustc-dev-guide/src/diagnostics.md b/src/doc/rustc-dev-guide/src/diagnostics.md
index 2f8f4b0ab8a..01e59c91904 100644
--- a/src/doc/rustc-dev-guide/src/diagnostics.md
+++ b/src/doc/rustc-dev-guide/src/diagnostics.md
@@ -866,19 +866,17 @@ struct](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_errors/json/struct
 (and sub-structs) for the JSON serialization. Don't confuse this with
 [`errors::Diag`](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_errors/struct.Diag.html)!
 
-## `#[rustc_on_unimplemented(...)]`
+## `#[rustc_on_unimplemented]`
 
-The `#[rustc_on_unimplemented]` attribute allows trait definitions to add specialized
-notes to error messages when an implementation was expected but not found.
-You can refer to the trait's generic arguments by name and to the resolved type using `Self`.
-
-For example:
+This attribute allows trait definitions to modify error messages when an implementation was
+expected but not found. The string literals in the attribute are format strings and can be
+formatted with named parameters. See the Formatting
+section below for what parameters are permitted.
 
 ```rust,ignore
-#![feature(rustc_attrs)]
-
-#[rustc_on_unimplemented="an iterator over elements of type `{A}` \
-    cannot be built from a collection of type `{Self}`"]
+#[rustc_on_unimplemented(message = "an iterator over \
+    elements of type `{A}` cannot be built from a \
+    collection of type `{Self}`")]
 trait MyIterator<A> {
     fn next(&mut self) -> A;
 }
@@ -895,32 +893,26 @@ fn main() {
 When the user compiles this, they will see the following;
 
 ```txt
-error[E0277]: the trait bound `&[{integer}]: MyIterator<char>` is not satisfied
-  --> <anon>:14:5
+error[E0277]: an iterator over elements of type `char` cannot be built from a collection of type `&[{integer}]`
+  --> src/main.rs:13:19
    |
-14 |     iterate_chars(&[1, 2, 3][..]);
-   |     ^^^^^^^^^^^^^ an iterator over elements of type `char` cannot be built from a collection of type `&[{integer}]`
+13 |     iterate_chars(&[1, 2, 3][..]);
+   |     ------------- ^^^^^^^^^^^^^^ the trait `MyIterator<char>` is not implemented for `&[{integer}]`
+   |     |
+   |     required by a bound introduced by this call
    |
-   = help: the trait `MyIterator<char>` is not implemented for `&[{integer}]`
-   = note: required by `iterate_chars`
+note: required by a bound in `iterate_chars`
 ```
 
-`rustc_on_unimplemented` also supports advanced filtering for better targeting
-of messages, as well as modifying specific parts of the error message. You
-target the text of:
-
+You can modify the contents of:
  - the main error message (`message`)
  - the label (`label`)
- - an extra note (`note`)
+ - the note(s) (`note`)
 
 For example, the following attribute
 
 ```rust,ignore
-#[rustc_on_unimplemented(
-    message="message",
-    label="label",
-    note="note"
-)]
+#[rustc_on_unimplemented(message = "message", label = "label", note = "note")]
 trait MyIterator<A> {
     fn next(&mut self) -> A;
 }
@@ -930,45 +922,61 @@ Would generate the following output:
 
 ```text
 error[E0277]: message
-  --> <anon>:14:5
+  --> <file>:10:19
    |
-14 |     iterate_chars(&[1, 2, 3][..]);
-   |     ^^^^^^^^^^^^^ label
+10 |     iterate_chars(&[1, 2, 3][..]);
+   |     ------------- ^^^^^^^^^^^^^^ label
+   |     |
+   |     required by a bound introduced by this call
    |
-   = note: note
    = help: the trait `MyIterator<char>` is not implemented for `&[{integer}]`
-   = note: required by `iterate_chars`
+   = note: note
+note: required by a bound in `iterate_chars`
 ```
 
+The functionality discussed so far is also available with
+[`#[diagnostic::on_unimplemented]`](https://doc.rust-lang.org/nightly/reference/attributes/diagnostics.html#the-diagnosticon_unimplemented-attribute).
+If you can, you should use that instead.
+
+### Filtering
+
 To allow more targeted error messages, it is possible to filter the
-application of these fields based on a variety of attributes when using
-`on`:
+application of these fields with `on`.
 
+You can filter on the following boolean flags:
  - `crate_local`: whether the code causing the trait bound to not be
    fulfilled is part of the user's crate. This is used to avoid suggesting
    code changes that would require modifying a dependency.
- - Any of the generic arguments that can be substituted in the text can be
-   referred by name as well for filtering, like `Rhs="i32"`, except for
-   `Self`.
- - `_Self`: to filter only on a particular calculated trait resolution, like
-   `Self="std::iter::Iterator<char>"`. This is needed because `Self` is a
-   keyword which cannot appear in attributes.
- - `direct`: user-specified rather than derived obligation.
- - `from_desugaring`: usable both as boolean (whether the flag is present)
-   or matching against a particular desugaring. The desugaring is identified
-   with its variant name in the `DesugaringKind` enum.
-
-For example, the `Iterator` trait can be annotated in the following way:
+ - `direct`: whether this is an user-specified rather than derived obligation.
+ - `from_desugaring`: whether we are in some kind of desugaring, like `?`
+   or a `try` block for example. This flag can also be matched on, see below.
+
+You can match on the following names and values, using `name = "value"`:
+ - `cause`: Match against one variant of the `ObligationCauseCode`
+   enum. Only `"MainFunctionType"` is supported.
+ - `from_desugaring`: Match against a particular variant of the `DesugaringKind`
+   enum. The desugaring is identified by its variant name, for example
+   `"QuestionMark"` for `?` desugaring or `"TryBlock"` for `try` blocks.
+ - `Self` and any generic arguments of the trait, like `Self = "alloc::string::String"`
+   or `Rhs="i32"`.
+   
+The compiler can provide several values to match on, for example:
+  - the self_ty, pretty printed with and without type arguments resolved.
+  - `"{integral}"`, if self_ty is an integral of which the type is known.
+  - `"[]"`, `"[{ty}]"`, `"[{ty}; _]"`, `"[{ty}; $N]"` when applicable.
+  - references to said slices and arrays.
+  - `"fn"`, `"unsafe fn"` or `"#[target_feature] fn"` when self is a function.
+  - `"{integer}"` and `"{float}"` if the type is a number but we haven't inferred it yet.
+  - combinations of the above, like `"[{integral}; _]"`.
+
+For example, the `Iterator` trait can be filtered in the following way:
 
 ```rust,ignore
 #[rustc_on_unimplemented(
-    on(
-        _Self="&str",
-        note="call `.chars()` or `.as_bytes()` on `{Self}`"
-    ),
-    message="`{Self}` is not an iterator",
-    label="`{Self}` is not an iterator",
-    note="maybe try calling `.iter()` or a similar method"
+    on(Self = "&str", note = "call `.chars()` or `.as_bytes()` on `{Self}`"),
+    message = "`{Self}` is not an iterator",
+    label = "`{Self}` is not an iterator",
+    note = "maybe try calling `.iter()` or a similar method"
 )]
 pub trait Iterator {}
 ```
@@ -997,15 +1005,47 @@ error[E0277]: `&str` is not an iterator
   = note: required by `std::iter::IntoIterator::into_iter`
 ```
 
-If you need to filter on multiple attributes, you can use `all`, `any` or
-`not` in the following way:
+The `on` filter accepts `all`, `any` and `not` predicates similar to the `cfg` attribute:
 
 ```rust,ignore
-#[rustc_on_unimplemented(
-    on(
-        all(_Self="&str", T="std::string::String"),
-        note="you can coerce a `{T}` into a `{Self}` by writing `&*variable`"
-    )
-)]
-pub trait From<T>: Sized { /* ... */ }
+#[rustc_on_unimplemented(on(
+    all(Self = "&str", T = "alloc::string::String"),
+    note = "you can coerce a `{T}` into a `{Self}` by writing `&*variable`"
+))]
+pub trait From<T>: Sized {
+    /* ... */
+}
+```
+
+### Formatting 
+
+The string literals are format strings that accept parameters wrapped in braces
+but positional and listed parameters and format specifiers are not accepted.
+The following parameter names are valid:
+- `Self` and all generic parameters of the trait.
+- `This`: the name of the trait the attribute is on, without generics.
+- `Trait`: the name of the "sugared" trait. See `TraitRefPrintSugared`.
+- `ItemContext`: the kind of `hir::Node` we're in, things like `"an async block"`,
+   `"a function"`, `"an async function"`, etc.
+
+Something like:
+
+```rust,ignore
+#![feature(rustc_attrs)]
+
+#[rustc_on_unimplemented(message = "Self = `{Self}`, \
+    T = `{T}`, this = `{This}`, trait = `{Trait}`, \
+    context = `{ItemContext}`")]
+pub trait From<T>: Sized {
+    fn from(x: T) -> Self;
+}
+
+fn main() {
+    let x: i8 = From::from(42_i32);
+}
+```
+
+Will format the message into 
+```text
+"Self = `i8`, T = `i32`, this = `From`, trait = `From<i32>`, context = `a function`"
 ```
diff --git a/src/doc/rustc-dev-guide/src/early_late_parameters.md b/src/doc/rustc-dev-guide/src/early_late_parameters.md
index 3b2a5e8a155..3f94b090566 100644
--- a/src/doc/rustc-dev-guide/src/early_late_parameters.md
+++ b/src/doc/rustc-dev-guide/src/early_late_parameters.md
@@ -174,7 +174,8 @@ As mentioned previously, the distinction between early and late bound parameters
 - When naming a function (early)
 - When calling a function (late)
 
-There currently is no syntax for explicitly specifying generic arguments for late bound parameters as part of the call step, only specifying generic arguments when naming a function. The syntax `foo::<'static>();`, despite being part of a function call, behaves as `(foo::<'static>)();` and instantiates the early bound generic parameters on the function item type.
+There is currently no syntax for explicitly specifying generic arguments for late bound parameters during the call step; generic arguments can only be specified for early bound parameters when naming a function.
+The syntax `foo::<'static>();`, despite being part of a function call, behaves as `(foo::<'static>)();` and instantiates the early bound generic parameters on the function item type.
 
 See the following example:
 ```rust
diff --git a/src/doc/rustc-dev-guide/src/fuzzing.md b/src/doc/rustc-dev-guide/src/fuzzing.md
index b588ca104cb..30005378617 100644
--- a/src/doc/rustc-dev-guide/src/fuzzing.md
+++ b/src/doc/rustc-dev-guide/src/fuzzing.md
@@ -73,21 +73,32 @@ To build a corpus, you may want to use:
 
 - The rustc/rust-analyzer/clippy test suites (or even source code) --- though avoid
   tests that are already known to cause failures, which often begin with comments
-  like `// failure-status: 101` or `// known-bug: #NNN`.
-- The already-fixed ICEs in [Glacier][glacier] --- though avoid the unfixed
-  ones in `ices/`!
+  like `//@ failure-status: 101` or `//@ known-bug: #NNN`.
+- The already-fixed ICEs in the archived [Glacier][glacier] repository --- though
+  avoid the unfixed ones in `ices/`!
+
+[glacier]: https://github.com/rust-lang/glacier
 
 ## Extra credit
 
 Here are a few things you can do to help the Rust project after filing an ICE.
 
-- [Bisect][bisect] the bug to figure out when it was introduced 
+- [Bisect][bisect] the bug to figure out when it was introduced.
+  If you find the regressing PR / commit, you can mark the issue with the label
+  `S-has-bisection`. If not, consider applying `E-needs-bisection` instead.
 - Fix "distractions": problems with the test case that don't contribute to
   triggering the ICE, such as syntax errors or borrow-checking errors
-- Minimize the test case (see below)
-- Add the minimal test case to [Glacier][glacier]
+- Minimize the test case (see below). If successful, you can label the
+  issue with `S-has-mcve`. Otherwise, you can apply `E-needs-mcve`.
+- Add the minimal test case to the rust-lang/rust repo as a [crashes test].
+  While you're at it, consider including other "untracked" crashes in your PR.
+  Please don't forget to mark your issue with `S-bug-has-test` afterwards.
+
+See also [applying and removing labels][labeling].
 
 [bisect]: https://rust-lang.github.io/cargo-bisect-rustc/
+[crashes test]: tests/compiletest.html#crashes-tests
+[labeling]: https://forge.rust-lang.org/release/issue-triaging.html#applying-and-removing-labels
 
 ## Minimization
 
@@ -143,7 +154,6 @@ ICEs that require debug assertions to reproduce should be tagged
 - [tree-splicer][tree-splicer] generates new source files by combining existing
   ones while maintaining correct syntax
 
-[glacier]: https://github.com/rust-lang/glacier
 [fuzz-rustc]: https://github.com/dwrensha/fuzz-rustc
 [icemaker]: https://github.com/matthiaskrgr/icemaker/
 [tree-splicer]: https://github.com/langston-barrett/tree-splicer/
diff --git a/src/doc/rustc-dev-guide/src/getting-started.md b/src/doc/rustc-dev-guide/src/getting-started.md
index 0e5b32a06f8..435202ca6c8 100644
--- a/src/doc/rustc-dev-guide/src/getting-started.md
+++ b/src/doc/rustc-dev-guide/src/getting-started.md
@@ -89,7 +89,7 @@ filtering the search to areas you're interested in. For example:
 Not all important or beginner work has issue labels.
 See below for how to find work that isn't labelled.
 
-[help-wanted-search]: https://github.com/issues?q=is%3Aopen+is%3Aissue+org%3Arust-lang+no%3Aassignee+label%3AE-easy%2C%22good+first+issue%22%2Cgood-first-issue%2CE-medium%2CEasy%2CE-help-wanted%2CE-mentor+-label%3AS-blocked+-linked:pr+
+[help-wanted-search]: https://github.com/issues?q=is%3Aopen+is%3Aissue+org%3Arust-lang+no%3Aassignee+label%3AE-easy%2C%22good+first+issue%22%2Cgood-first-issue%2CE-medium%2CEasy%2CE-help-wanted%2CE-mentor+-label%3AS-blocked+-linked%3Apr+
 [Triage]: ./contributing.md#issue-triage
 
 ### Recurring work
@@ -98,8 +98,6 @@ Some work is too large to be done by a single person. In this case, it's common
 issues" to co-ordinate the work between contributors. Here are some example tracking issues where
 it's easy to pick up work without a large time commitment:
 
-- [Rustdoc Askama Migration](https://github.com/rust-lang/rust/issues/108868)
-- [Diagnostic Translation](https://github.com/rust-lang/rust/issues/100717)
 - [Move UI tests to subdirectories](https://github.com/rust-lang/rust/issues/73494)
 
 If you find more recurring work, please feel free to add it here!
diff --git a/src/doc/rustc-dev-guide/src/memory.md b/src/doc/rustc-dev-guide/src/memory.md
index eeb4a813980..f766a51898e 100644
--- a/src/doc/rustc-dev-guide/src/memory.md
+++ b/src/doc/rustc-dev-guide/src/memory.md
@@ -63,7 +63,7 @@ represented as a slice `&'tcx [tcx.types.i32, tcx.types.u32]`).
 [`mk_args`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/context/struct.TyCtxt.html#method.mk_args
 [adtdefid]: ./ty_module/generic_arguments.md#adtdef-and-defid
 [`Predicate`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.Predicate.html
-[`TraitRef`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.TraitRef.html
+[`TraitRef`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/type.TraitRef.html
 [`ty::TyKind`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/sty/type.TyKind.html
 [traits]: ./traits/resolution.md
 
diff --git a/src/doc/rustc-dev-guide/src/normalization.md b/src/doc/rustc-dev-guide/src/normalization.md
index ef530ccc5ed..9705b1a244a 100644
--- a/src/doc/rustc-dev-guide/src/normalization.md
+++ b/src/doc/rustc-dev-guide/src/normalization.md
@@ -166,7 +166,10 @@ In this example:
 
 When interfacing with the type system it will often be the case that it's necessary to request a type be normalized. There are a number of different entry points to the underlying normalization logic and each entry point should only be used in specific parts of the compiler.
 
-An additional complication is that the compiler is currently undergoing a transition from the old trait solver to the new trait solver. As part of this transition our approach to normalization in the compiler has changed somewhat significantly, resulting in some normalization entry points being "old solver only" slated for removal in the long-term once the new solver has stabilized.
+<!-- date-check: May 2025 -->
+An additional complication is that the compiler is currently undergoing a transition from the old trait solver to the new trait solver.
+As part of this transition our approach to normalization in the compiler has changed somewhat significantly, resulting in some normalization entry points being "old solver only" slated for removal in the long-term once the new solver has stabilized.
+The transition can be tracked via the [WG-trait-system-refactor](https://github.com/rust-lang/rust/labels/WG-trait-system-refactor) label in Github.
 
 Here is a rough overview of the different entry points to normalization in the compiler:
 - `infcx.at.structurally_normalize`
@@ -306,4 +309,4 @@ Const aliases differ from type aliases a bit here; well formedness of const alia
 
 [^5]: Const aliases certainly wouldn't be *less* sound than type aliases if we stopped doing this
 
-[const_evaluatable]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/type.ClauseKind.html#variant.ConstEvaluatable
\ No newline at end of file
+[const_evaluatable]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/type.ClauseKind.html#variant.ConstEvaluatable
diff --git a/src/doc/rustc-dev-guide/src/opaque-types-impl-trait-inference.md b/src/doc/rustc-dev-guide/src/opaque-types-impl-trait-inference.md
index bdf4e4cd870..42600ad87f8 100644
--- a/src/doc/rustc-dev-guide/src/opaque-types-impl-trait-inference.md
+++ b/src/doc/rustc-dev-guide/src/opaque-types-impl-trait-inference.md
@@ -13,13 +13,16 @@ it can work across functions and function bodies.
 To help explain how it works, let's consider an example.
 
 ```rust
+#![feature(type_alias_impl_trait)]
 mod m {
     pub type Seq<T> = impl IntoIterator<Item = T>;
 
+    #[define_opaque(Seq)]
     pub fn produce_singleton<T>(t: T) -> Seq<T> {
         vec![t]
     }
 
+    #[define_opaque(Seq)]
     pub fn produce_doubleton<T>(t: T, u: T) -> Seq<T> {
         vec![t, u]
     }
diff --git a/src/doc/rustc-dev-guide/src/return-position-impl-trait-in-trait.md b/src/doc/rustc-dev-guide/src/return-position-impl-trait-in-trait.md
index 5f358819c36..85cece2acd4 100644
--- a/src/doc/rustc-dev-guide/src/return-position-impl-trait-in-trait.md
+++ b/src/doc/rustc-dev-guide/src/return-position-impl-trait-in-trait.md
@@ -356,7 +356,7 @@ trait Foo {
 
 Failing because a down-stream impl could theoretically provide an
 implementation for `RPITIT` without providing an implementation of
-`foo`:
+`bar`:
 
 ```text
 error[E0308]: mismatched types
diff --git a/src/doc/rustc-dev-guide/src/rustdoc-internals.md b/src/doc/rustc-dev-guide/src/rustdoc-internals.md
index 80421b85bf0..bc91c62d873 100644
--- a/src/doc/rustc-dev-guide/src/rustdoc-internals.md
+++ b/src/doc/rustc-dev-guide/src/rustdoc-internals.md
@@ -281,10 +281,10 @@ using `XPath` notation to get a precise look at the output. The full
 description of all the commands available to `rustdoc` tests (e.g. [`@has`] and
 [`@matches`]) is in [`htmldocck.py`].
 
-To use multiple crates in a `rustdoc` test, add `// aux-build:filename.rs`
+To use multiple crates in a `rustdoc` test, add `//@ aux-build:filename.rs`
 to the top of the test file. `filename.rs` should be placed in an `auxiliary`
 directory relative to the test file with the comment. If you need to build
-docs for the auxiliary file, use `// build-aux-docs`.
+docs for the auxiliary file, use `//@ build-aux-docs`.
 
 In addition, there are separate tests for the search index and `rustdoc`'s
 ability to query it. The files in `tests/rustdoc-js` each contain a
diff --git a/src/doc/rustc-dev-guide/src/rustdoc.md b/src/doc/rustc-dev-guide/src/rustdoc.md
index e36d6a388a9..de70ba63823 100644
--- a/src/doc/rustc-dev-guide/src/rustdoc.md
+++ b/src/doc/rustc-dev-guide/src/rustdoc.md
@@ -93,13 +93,13 @@ does is call the `main()` that's in this crate's `lib.rs`, though.)
   interactivity.  For information on how to write this form of test,
   see [`tests/rustdoc-gui/README.md`][rustdoc-gui-readme]
   as well as [the description of the `.goml` format][goml-script]
-* Additionally, JavaScript type annotations are written using [TypeScript-flavored JSDoc]
-  comments and an external d.ts file. The code itself is plain, valid JavaScript; we only
-  use tsc as a linter.
-* The tests on the structure of rustdoc HTML output are located in `tests/rustdoc`,
+* Tests on the structure of rustdoc HTML output are located in `tests/rustdoc`,
   where they're handled by the test runner of bootstrap and
   the supplementary script `src/etc/htmldocck.py`.
   [These tests have several extra directives available to them](./rustdoc-internals/rustdoc-test-suite.md).
+* Additionally, JavaScript type annotations are written using [TypeScript-flavored JSDoc]
+  comments and an external d.ts file. The code itself is plain, valid JavaScript; we only
+  use tsc as a linter.
 
 [TypeScript-flavored JSDoc]: https://www.typescriptlang.org/docs/handbook/jsdoc-supported-types.html
 [rustdoc-gui-readme]: https://github.com/rust-lang/rust/blob/master/tests/rustdoc-gui/README.md
@@ -116,6 +116,28 @@ Certain browser features that require secure origins, like `localStorage` and
 Service Workers, don't work reliably. We can still use such features but we
 should make sure pages are still usable without them.
 
+Rustdoc [does not type-check function bodies][platform-specific docs].
+This works by [overriding the built-in queries for typeck][override queries],
+by [silencing name resolution errors], and by [not resolving opaque types].
+This comes with several caveats: in particular, rustdoc *cannot* run any parts of the compiler that
+require type-checking bodies; for example it cannot generate `.rlib` files or run most lints.
+We want to move away from this model eventually, but we need some alternative for
+[the people using it][async-std]; see [various][zulip stop accepting broken code]
+[previous][rustdoc meeting 2024-07-08] [zulip][compiler meeting 2023-01-26] [discussion][notriddle rfc].
+For examples of code that breaks if this hack is removed, see
+[`tests/rustdoc-ui/error-in-impl-trait`].
+
+[platform-specific docs]: https://doc.rust-lang.org/rustdoc/advanced-features.html#interactions-between-platform-specific-docs
+[override queries]: https://github.com/rust-lang/rust/blob/52bf0cf795dfecc8b929ebb1c1e2545c3f41d4c9/src/librustdoc/core.rs#L299-L323
+[silencing name resolution errors]: https://github.com/rust-lang/rust/blob/52bf0cf795dfecc8b929ebb1c1e2545c3f41d4c9/compiler/rustc_resolve/src/late.rs#L4517
+[not resolving opaque types]: https://github.com/rust-lang/rust/blob/52bf0cf795dfecc8b929ebb1c1e2545c3f41d4c9/compiler/rustc_hir_analysis/src/check/check.rs#L188-L194
+[async-std]: https://github.com/rust-lang/rust/issues/75100
+[rustdoc meeting 2024-07-08]: https://rust-lang.zulipchat.com/#narrow/channel/393423-t-rustdoc.2Fmeetings/topic/meeting.202024-07-08/near/449969836
+[compiler meeting 2023-01-26]: https://rust-lang.zulipchat.com/#narrow/channel/238009-t-compiler.2Fmeetings/topic/.5Bweekly.5D.202023-01-26/near/323755789
+[zulip stop accepting broken code]: https://rust-lang.zulipchat.com/#narrow/stream/266220-rustdoc/topic/stop.20accepting.20broken.20code
+[notriddle rfc]: https://rust-lang.zulipchat.com/#narrow/channel/266220-t-rustdoc/topic/Pre-RFC.3A.20stop.20accepting.20broken.20code
+[`tests/rustdoc-ui/error-in-impl-trait`]: https://github.com/rust-lang/rust/tree/163cb4ea3f0ae3bc7921cc259a08a7bf92e73ee6/tests/rustdoc-ui/error-in-impl-trait
+
 ## Multiple runs, same output directory
 
 Rustdoc can be run multiple times for varying inputs, with its output set to the
diff --git a/src/doc/rustc-dev-guide/src/solve/coinduction.md b/src/doc/rustc-dev-guide/src/solve/coinduction.md
index c682e002db7..9753f7539c2 100644
--- a/src/doc/rustc-dev-guide/src/solve/coinduction.md
+++ b/src/doc/rustc-dev-guide/src/solve/coinduction.md
@@ -237,14 +237,14 @@ Alternatively, we could simply always treat the equate branch of `normalizes_to`
 Any cycles should result in infinite types, which aren't supported anyways and would only
 result in overflow when deeply normalizing for codegen.
 
-experimentation and examples: https://hackmd.io/-8p0AHnzSq2VAE6HE_wX-w?view
+experimentation and examples: <https://hackmd.io/-8p0AHnzSq2VAE6HE_wX-w?view>
 
 Another attempt at a summary.
 - in projection eq, we must make progress with constraining the rhs
 - a cycle is only ok if while equating we have a rigid ty on the lhs after norm at least once
 - cycles outside of the recursive `eq` call of `normalizes_to` are always fine
 
-[^1]: related: https://coq.inria.fr/refman/language/core/coinductive.html#top-level-definitions-of-corecursive-functions
+[^1]: related: <https://coq.inria.fr/refman/language/core/coinductive.html#top-level-definitions-of-corecursive-functions>
 
 [perfect derive]: https://smallcultfollowing.com/babysteps/blog/2022/04/12/implied-bounds-and-perfect-derive
 [ex1]: https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=0a9c3830b93a2380e6978d6328df8f72
diff --git a/src/doc/rustc-dev-guide/src/solve/opaque-types.md b/src/doc/rustc-dev-guide/src/solve/opaque-types.md
index 509c34a4d3a..6898ef3aa78 100644
--- a/src/doc/rustc-dev-guide/src/solve/opaque-types.md
+++ b/src/doc/rustc-dev-guide/src/solve/opaque-types.md
@@ -1,8 +1,10 @@
 # Opaque types in the new solver
 
-The way opaque types are handled in the new solver differs from the old implementation.
+The way [opaque types] are handled in the new solver differs from the old implementation.
 This should be a self-contained explanation of the behavior in the new solver.
 
+[opaque types]: ../opaque-types-type-alias-impl-trait.md
+
 ## opaques are alias types
 
 Opaque types are treated the same as other aliases, most notabily associated types,
diff --git a/src/doc/rustc-dev-guide/src/tests/ci.md b/src/doc/rustc-dev-guide/src/tests/ci.md
index 825be11c82a..ef3f4c7070c 100644
--- a/src/doc/rustc-dev-guide/src/tests/ci.md
+++ b/src/doc/rustc-dev-guide/src/tests/ci.md
@@ -66,9 +66,9 @@ kinds of builds (sets of jobs).
 ### Pull Request builds
 
 After each push to a pull request, a set of `pr` jobs are executed. Currently,
-these execute the `x86_64-gnu-llvm-X`, `x86_64-gnu-tools`, `mingw-check` and
-`mingw-check-tidy` jobs, all running on Linux. These execute a relatively short
-(~30 minutes) and lightweight test suite that should catch common issues. More
+these execute the `x86_64-gnu-llvm-X`, `x86_64-gnu-tools`, `mingw-check-1`, `mingw-check-2`
+and `mingw-check-tidy` jobs, all running on Linux. These execute a relatively short
+(~40 minutes) and lightweight test suite that should catch common issues. More
 specifically, they run a set of lints, they try to perform a cross-compile check
 build to Windows mingw (without producing any artifacts) and they test the
 compiler using a *system* version of LLVM. Unfortunately, it would take too many
@@ -100,8 +100,8 @@ Most platforms only run the build steps, some run a restricted set of tests,
 only a subset run the full suite of tests (see Rust's [platform tiers]).
 
 Auto jobs are defined in the `auto` section of [`jobs.yml`]. They are executed
-on the `auto` branch under the `rust-lang-ci/rust` repository[^rust-lang-ci] and
-their results can be seen [here](https://github.com/rust-lang-ci/rust/actions),
+on the `auto` branch under the `rust-lang/rust` repository and
+their results can be seen [here](https://github.com/rust-lang/rust/actions),
 although usually you will be notified of the result by a comment made by bors on
 the corresponding PR.
 
@@ -110,9 +110,6 @@ more [here](#merging-prs-serially-with-bors).
 
 [platform tiers]: https://forge.rust-lang.org/release/platform-support.html#rust-platform-support
 
-[^rust-lang-ci]: The `auto` and `try` jobs run under the `rust-lang-ci` fork for
-    historical reasons. This may change in the future.
-
 ### Try builds
 
 Sometimes we want to run a subset of the test suite on CI for a given PR, or
@@ -179,8 +176,8 @@ the pattern as Markdown.
 > that are exercised this way.
 
 Try jobs are defined in the `try` section of [`jobs.yml`]. They are executed on
-the `try` branch under the `rust-lang-ci/rust` repository[^rust-lang-ci] and
-their results can be seen [here](https://github.com/rust-lang-ci/rust/actions),
+the `try` branch under the `rust-lang/rust` repository and
+their results can be seen [here](https://github.com/rust-lang/rust/actions),
 although usually you will be notified of the result by a comment made by bors on
 the corresponding PR.
 
@@ -355,7 +352,7 @@ invalidated if one of the following changes:
 - Files copied into the Docker image in the Dockerfile
 - The architecture of the GitHub runner (x86 or ARM)
 
-[ghcr.io]: https://github.com/rust-lang-ci/rust/pkgs/container/rust-ci
+[ghcr.io]: https://github.com/rust-lang/rust/pkgs/container/rust-ci
 [Docker registry caching]: https://docs.docker.com/build/cache/backends/registry/
 
 ### LLVM caching with sccache
@@ -446,7 +443,7 @@ particular job, it is probably easiest to just look at the build log. To do
 this:
 
 1. Go to
-   <https://github.com/rust-lang-ci/rust/actions?query=branch%3Aauto+is%3Asuccess>
+   <https://github.com/rust-lang/rust/actions?query=branch%3Aauto+is%3Asuccess>
    to find the most recently successful build, and click on it.
 2. Choose the job you are interested in on the left-hand side.
 3. Click on the gear icon and choose "View raw logs"
@@ -458,7 +455,6 @@ this:
 [`jobs.yml`]: https://github.com/rust-lang/rust/blob/master/src/ci/github-actions/jobs.yml
 [`.github/workflows/ci.yml`]: https://github.com/rust-lang/rust/blob/master/.github/workflows/ci.yml
 [`src/ci/citool`]: https://github.com/rust-lang/rust/blob/master/src/ci/citool
-[rust-lang-ci]: https://github.com/rust-lang-ci/rust/actions
 [bors]: https://github.com/bors
 [homu]: https://github.com/rust-lang/homu
 [merge queue]: https://bors.rust-lang.org/queue/rust
diff --git a/src/doc/rustc-dev-guide/src/tests/compiletest.md b/src/doc/rustc-dev-guide/src/tests/compiletest.md
index 0ba078f0b49..e1b23748de3 100644
--- a/src/doc/rustc-dev-guide/src/tests/compiletest.md
+++ b/src/doc/rustc-dev-guide/src/tests/compiletest.md
@@ -546,10 +546,10 @@ only running the main `coverage` suite.
 
 [`tests/crashes`] serve as a collection of tests that are expected to cause the
 compiler to ICE, panic or crash in some other way, so that accidental fixes are
-tracked. This was formally done at <https://github.com/rust-lang/glacier> but
+tracked. Formerly, this was done at <https://github.com/rust-lang/glacier> but
 doing it inside the rust-lang/rust testsuite is more convenient.
 
-It is imperative that a test in the suite causes rustc to ICE, panic or crash
+It is imperative that a test in the suite causes rustc to ICE, panic, or
 crash in some other way. A test will "pass" if rustc exits with an exit status
 other than 1 or 0.
 
@@ -560,9 +560,12 @@ If you want to see verbose stdout/stderr, you need to set
 $ COMPILETEST_VERBOSE_CRASHES=1 ./x test tests/crashes/999999.rs --stage 1
 ```
 
-When adding crashes from <https://github.com/rust-lang/rust/issues>, the issue
-number should be noted in the file name (`12345.rs` should suffice) and also
-inside the file include a `//@ known-bug: #4321` directive.
+Anyone can add ["untracked" crashes] from the issue tracker. It's strongly
+recommended to include test cases from several issues in a single PR.
+When you do so, each issue number should be noted in the file name (`12345.rs`
+should suffice) and also inside the file by means of a `//@ known-bug: #12345`
+directive. Please [label][labeling] the relevant issues with `S-bug-has-test`
+afterwards.
 
 If you happen to fix one of the crashes, please move it to a fitting
 subdirectory in `tests/ui` and give it a meaningful name. Please add a doc
@@ -585,6 +588,8 @@ a subset first. The issue numbers can be found in the file name or the `//@
 known-bug` directive inside the test file.
 
 [`tests/crashes`]: https://github.com/rust-lang/rust/tree/master/tests/crashes
+["untracked" crashes]: https://github.com/rust-lang/rust/issues?q=is%3Aissue+state%3Aopen+label%3AI-ICE%2CI-crash+label%3AT-compiler+label%3AS-has-mcve+-label%3AS-bug-has-test
+[labeling]: https://forge.rust-lang.org/release/issue-triaging.html#applying-and-removing-labels
 
 ## Building auxiliary crates
 
@@ -614,7 +619,7 @@ file). The `-L` flag is used to find the extern crates.
 `aux-crate` is very similar to `aux-build`. However, it uses the `--extern` flag
 to link to the extern crate to make the crate be available as an extern prelude.
 That allows you to specify the additional syntax of the `--extern` flag, such as
-renaming a dependency. For example, `// aux-crate:foo=bar.rs` will compile
+renaming a dependency. For example, `//@ aux-crate:foo=bar.rs` will compile
 `auxiliary/bar.rs` and make it available under then name `foo` within the test.
 This is similar to how Cargo does dependency renaming.
 
diff --git a/src/doc/rustc-dev-guide/src/tests/directives.md b/src/doc/rustc-dev-guide/src/tests/directives.md
index dae659e6317..8a862417b0d 100644
--- a/src/doc/rustc-dev-guide/src/tests/directives.md
+++ b/src/doc/rustc-dev-guide/src/tests/directives.md
@@ -59,7 +59,7 @@ not be exhaustive. Directives can generally be found by browsing the
 | `aux-crate`           | Like `aux-build` but makes available as extern prelude                                                | All except `run-make` | `<extern_prelude_name>=<path/to/aux/file.rs>` |
 | `aux-codegen-backend` | Similar to `aux-build` but pass the compiled dylib to `-Zcodegen-backend` when building the main file | `ui-fulldeps`         | Path to codegen backend file                  |
 | `proc-macro`          | Similar to `aux-build`, but for aux forces host and don't use `-Cprefer-dynamic`[^pm].                | All except `run-make` | Path to auxiliary proc-macro `.rs` file       |
-| `build_aux_docs`      | Build docs for auxiliaries as well                                                                    | All except `run-make` | N/A                                           |
+| `build-aux-docs`      | Build docs for auxiliaries as well                                                                    | All except `run-make` | N/A                                           |
 
 [^pm]: please see the Auxiliary proc-macro section in the
     [compiletest](./compiletest.md) chapter for specifics.
diff --git a/src/doc/rustc-dev-guide/src/tests/ui.md b/src/doc/rustc-dev-guide/src/tests/ui.md
index 721d20b65c5..3402838da87 100644
--- a/src/doc/rustc-dev-guide/src/tests/ui.md
+++ b/src/doc/rustc-dev-guide/src/tests/ui.md
@@ -192,7 +192,7 @@ They have several forms, but generally are a comment with the diagnostic level
 to write out the entire message, just make sure to include the important part of
 the message to make it self-documenting.
 
-The error annotation needs to match with the line of the diagnostic. There are
+Most error annotations need to match with the line of the diagnostic. There are
 several ways to match the message with the line (see the examples below):
 
 * `~`: Associates the error level and message with the *current* line
@@ -205,9 +205,6 @@ several ways to match the message with the line (see the examples below):
 * `~v`: Associates the error level and message with the *next* error
   annotation line. Each symbol (`v`) that you add adds a line to this, so `~vvv`
   is three lines below the error annotation line.
-* `~?`: Used to match error levels and messages with errors not having line
-  information. These can be placed on any line in the test file, but are
-  conventionally placed at the end.
 
 Example:
 
@@ -222,6 +219,10 @@ The space character between `//~` (or other variants) and the subsequent text is
 negligible (i.e. there is no semantic difference between `//~ ERROR` and
 `//~ERROR` although the former is more common in the codebase).
 
+`~? <diagnostic kind>` (example being `~? ERROR`)
+is used to match diagnostics without line information.
+These can be placed on any line in the test file, but are conventionally placed at the end.
+
 ### Error annotation examples
 
 Here are examples of error annotations on different lines of UI test source.
diff --git a/src/doc/rustc-dev-guide/src/ty_module/binders.md b/src/doc/rustc-dev-guide/src/ty_module/binders.md
index 71157eca9b1..7fd9eeed54a 100644
--- a/src/doc/rustc-dev-guide/src/ty_module/binders.md
+++ b/src/doc/rustc-dev-guide/src/ty_module/binders.md
@@ -1,6 +1,6 @@
 # `Binder` and Higher ranked regions
 
-Sometimes we define generic parameters not on an item but as part of a type or a where clauses. As an example the type `for<'a> fn(&'a u32)` or the where clause `for<'a> T: Trait<'a>` both introduce a generic lifetime named `'a`. Currently there is no stable syntax for `for<T>` or `for<const N: usize>` but on nightly `feature(non_lifetime_binders)` feature can be used to write where clauses (but not types) using `for<T>`/`for<const N: usize>`.
+Sometimes we define generic parameters not on an item but as part of a type or a where clause. As an example the type `for<'a> fn(&'a u32)` or the where clause `for<'a> T: Trait<'a>` both introduce a generic lifetime named `'a`. Currently there is no stable syntax for `for<T>` or `for<const N: usize>` but on nightly `feature(non_lifetime_binders)` can be used to write where clauses (but not types) using `for<T>`/`for<const N: usize>`.
 
 The `for` is referred to as a "binder" because it brings new names into scope. In rustc we use the `Binder` type to track where these parameters are introduced and what the parameters are (i.e. how many and whether the parameter is a type/const/region). A type such as `for<'a> fn(&'a u32)` would be
 represented in rustc as:
@@ -13,8 +13,9 @@ Binder(
 
 Usages of these parameters is represented by the `RegionKind::Bound` (or `TyKind::Bound`/`ConstKind::Bound` variants). These bound regions/types/consts are composed of two main pieces of data:
 - A [DebruijnIndex](../appendix/background.md#what-is-a-de-bruijn-index) to specify which binder we are referring to.
-- A [`BoundVar`] which specifies which of the parameters the `Binder` introduces we are referring to.
-- We also sometimes store some extra information for diagnostics reasons via the [`BoundTyKind`]/[`BoundRegionKind`] but this is not important for type equality or more generally the semantics of `Ty`. (omitted from the above example)
+- A [`BoundVar`] which specifies which of the parameters that the `Binder` introduces we are referring to.
+
+We also sometimes store some extra information for diagnostics reasons via the [`BoundTyKind`]/[`BoundRegionKind`] but this is not important for type equality or more generally the semantics of `Ty`. (omitted from the above example)
 
 In debug output (and also informally when talking to each other) we tend to write these bound variables in the format of `^DebruijnIndex_BoundVar`. The above example would instead be written as `Binder(fn(&'^0_0), &[BoundVariableKind::Region])`. Sometimes when the `DebruijnIndex` is `0` we just omit it and would write `^0`.
 
@@ -43,7 +44,7 @@ Binder(
     &[BoundVariableKind::Region(...)],
 )
 ```
-This would cause all kinds of issues as the region `'^1_0` refers to a binder at a higher level than the outermost binder i.e. it is an escaping bound var. The `'^1` region (also writeable as `'^0_1`) is also ill formed as the binder it refers to does not introduce a second parameter. Modern day rustc will ICE when constructing this binder due to both of those regions, in the past we would have simply allowed this to work and then ran into issues in other parts of the codebase. 
+This would cause all kinds of issues as the region `'^1_0` refers to a binder at a higher level than the outermost binder i.e. it is an escaping bound var. The `'^1` region (also writeable as `'^0_1`) is also ill formed as the binder it refers to does not introduce a second parameter. Modern day rustc will ICE when constructing this binder due to both of those reasons, in the past we would have simply allowed this to work and then ran into issues in other parts of the codebase. 
 
 [`Binder`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.Binder.html
 [`BoundVar`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.BoundVar.html
diff --git a/src/doc/rustc-dev-guide/src/ty_module/instantiating_binders.md b/src/doc/rustc-dev-guide/src/ty_module/instantiating_binders.md
index 04d56ccbc63..e3f091ca45f 100644
--- a/src/doc/rustc-dev-guide/src/ty_module/instantiating_binders.md
+++ b/src/doc/rustc-dev-guide/src/ty_module/instantiating_binders.md
@@ -105,7 +105,8 @@ the `RePlaceholder` for the `'b` parameter is in a higher universe to track the
 
 ## Instantiating with `ReLateParam`
 
-As discussed in a previous chapter, `RegionKind` has two variants for representing generic parameters, `ReLateParam` and `ReEarlyParam`. `ReLateParam` is conceptually a `Placeholder` that is always in the root universe (`U0`). It is used when instantiating late bound parameters of functions/closures while inside of them. Its actual representation is relatively different from both `ReEarlyParam` and `RePlaceholder`:
+As discussed in [the chapter about representing types][representing-types], `RegionKind` has two variants for representing generic parameters, `ReLateParam` and `ReEarlyParam`.
+`ReLateParam` is conceptually a `Placeholder` that is always in the root universe (`U0`). It is used when instantiating late bound parameters of functions/closures while inside of them. Its actual representation is relatively different from both `ReEarlyParam` and `RePlaceholder`:
 - A `DefId` for the item that introduced the late bound generic parameter
 - A [`BoundRegionKind`] which either specifies the `DefId` of the generic parameter and its name (via a `Symbol`), or that this placeholder is representing the anonymous lifetime of a `Fn`/`FnMut` closure's self borrow. There is also a variant for `BrAnon` but this is not used for `ReLateParam`.
 
@@ -133,6 +134,7 @@ Generally whenever we have a `Binder` for late bound parameters on a function/cl
 As a concrete example, accessing the signature of a function we are type checking will be represented as `EarlyBinder<Binder<FnSig>>`. As we are already "inside" of these binders, we would call `instantiate_identity` followed by `liberate_late_bound_regions`.
 
 [`liberate_late_bound_regions`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/context/struct.TyCtxt.html#method.liberate_late_bound_regions
+[representing-types]: param_ty_const_regions.md
 [`BoundRegionKind`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/enum.BoundRegionKind.html
 [`enter_forall`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_trait_selection/infer/struct.InferCtxt.html#method.enter_forall
 [ch_placeholders_universes]: ../borrow_check/region_inference/placeholders_and_universes.md
diff --git a/src/doc/rustc-dev-guide/src/ty_module/param_ty_const_regions.md b/src/doc/rustc-dev-guide/src/ty_module/param_ty_const_regions.md
index c52f0c0df2a..493693c9a44 100644
--- a/src/doc/rustc-dev-guide/src/ty_module/param_ty_const_regions.md
+++ b/src/doc/rustc-dev-guide/src/ty_module/param_ty_const_regions.md
@@ -11,15 +11,15 @@ TyKind::Ref(
 
 There are three separate ways we represent usages of generic parameters:
 - [`TyKind::Param`]/[`ConstKind::Param`]/[`RegionKind::EarlyParam`] for early bound generic parameters (note: all type and const parameters are considered early bound, see the [chapter on early vs late bound parameters][ch_early_late_bound] for more information)
-- [`TyKind::Bound`]/[`ConstKind::Bound`]/[`RegionKind::Bound`] for references to parameters introduced via higher ranked bounds or higher ranked types i.e. `for<'a> fn(&'a u32)` or `for<'a> T: Trait<'a>`. This will be discussed in the [chapter on `Binder`s][ch_binders].
-- [`RegionKind::LateParam`] for late bound lifetime parameters, `LateParam` will be discussed in the [chapter on instantiating `Binder`s][ch_instantiating_binders].
+- [`TyKind::Bound`]/[`ConstKind::Bound`]/[`RegionKind::Bound`] for references to parameters introduced via higher ranked bounds or higher ranked types i.e. `for<'a> fn(&'a u32)` or `for<'a> T: Trait<'a>`. This is discussed in the [chapter on `Binder`s][ch_binders].
+- [`RegionKind::LateParam`] for late bound lifetime parameters, `LateParam` is discussed in the [chapter on instantiating `Binder`s][ch_instantiating_binders].
 
-This chapter will only cover `TyKind::Param` `ConstKind::Param` and `RegionKind::EarlyParam`.
+This chapter only covers `TyKind::Param` `ConstKind::Param` and `RegionKind::EarlyParam`.
 
 ## Ty/Const Parameters
 
-As `TyKind::Param` and `ConstKind::Param` are implemented identically this section will only refer to `TyKind::Param` for simplicity. However
-you should keep in mind that everything here also is true of `ConstKind::Param`
+As `TyKind::Param` and `ConstKind::Param` are implemented identically this section only refers to `TyKind::Param` for simplicity.
+However you should keep in mind that everything here also is true of `ConstKind::Param`
 
 Each `TyKind::Param` contains two things: the name of the parameter and an index.
 
@@ -83,7 +83,7 @@ fn foo<'a, 'b, T: 'a>(one: T, two: &'a &'b u32) -> &'b u32 {
 }
 ```
 
-`RegionKind::LateParam` will be discussed more in the chapter on [instantiating binders][ch_instantiating_binders].
+`RegionKind::LateParam` is discussed more in the chapter on [instantiating binders][ch_instantiating_binders].
 
 [ch_early_late_bound]: ../early_late_parameters.md
 [ch_binders]: ./binders.md
diff --git a/src/doc/rustc-dev-guide/src/typing_parameter_envs.md b/src/doc/rustc-dev-guide/src/typing_parameter_envs.md
index 67eaf51bf29..e21bc5155da 100644
--- a/src/doc/rustc-dev-guide/src/typing_parameter_envs.md
+++ b/src/doc/rustc-dev-guide/src/typing_parameter_envs.md
@@ -32,7 +32,7 @@ where
     <T as Trait>::Assoc: Clone,
 {}
 ```
-If we were conceptually inside of `foo` (for example, type-checking or linting it) we would use this `ParamEnv` everywhere that we interact with the type system. This would allow things such as normalization (TODO: write a chapter about normalization and link it), evaluating generic constants, and proving where clauses/goals, to rely on `T` being sized, implementing `Trait`, etc.
+If we were conceptually inside of `foo` (for example, type-checking or linting it) we would use this `ParamEnv` everywhere that we interact with the type system. This would allow things such as [normalization], evaluating generic constants, and proving where clauses/goals, to rely on `T` being sized, implementing `Trait`, etc.
 
 A more concrete example:
 ```rust
@@ -70,6 +70,7 @@ fn foo2<T>(a: T) {
 [predicates_of]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir_analysis/collect/predicates_of/fn.predicates_of.html
 [method_pred_entailment]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir_analysis/check/compare_impl_item/fn.compare_method_predicate_entailment.html
 [query]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/context/struct.TyCtxt.html#method.param_env
+[normalization]: normalization.md
 
 ### Acquiring a `ParamEnv`
 
@@ -199,8 +200,8 @@ In the next-gen trait solver the requirement for all where clauses in the `Param
 
 Depending on what context we are performing type system operations in, different behaviour may be required. For example during coherence there are stronger requirements about when we can consider goals to not hold or when we can consider types to be unequal.
 
-Tracking which "phase" of the compiler type system operations are being performed in is done by the [`TypingMode`][tenv] enum. The documentation on the `TypingMode` enum is quite good so instead of repeating it here verbatim we would recommend reading the API documentation directly.
+Tracking which "phase" of the compiler type system operations are being performed in is done by the [`TypingMode`][tmode] enum. The documentation on the `TypingMode` enum is quite good so instead of repeating it here verbatim we would recommend reading the API documentation directly.
 
 [penv]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.ParamEnv.html
-[tenv]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_type_ir/infer_ctxt/enum.TypingMode.html
+[tenv]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.TypingEnv.html
 [tmode]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/type.TypingMode.html
diff --git a/src/doc/rustc-dev-guide/triagebot.toml b/src/doc/rustc-dev-guide/triagebot.toml
index 53fa72469fd..978802edf3f 100644
--- a/src/doc/rustc-dev-guide/triagebot.toml
+++ b/src/doc/rustc-dev-guide/triagebot.toml
@@ -1,18 +1,82 @@
-[assign]
+# This file's format is documented at
+# https://forge.rust-lang.org/triagebot/pr-assignment.html#configuration
+
+[autolabel."needs-triage"]
+new_issue = true
+exclude_labels = [
+    "A-diagnostics",
+    "C-tracking-issue",
+]
+
+[review-submitted]
+# This label is added when a "request changes" review is submitted.
+reviewed_label = "S-waiting-on-author"
+# These labels are removed when a "request changes" review is submitted.
+review_labels = ["S-waiting-on-review"]
+
+[review-requested]
+# Those labels are removed when PR author requests a review from an assignee
+remove_labels = ["S-waiting-on-author"]
+# Those labels are added when PR author requests a review from an assignee
+add_labels = ["S-waiting-on-review"]
+
+# Enable shortcuts like `@rustbot ready`
+# Documentation at: https://forge.rust-lang.org/triagebot/shortcuts.html
+[shortcut]
+
+[autolabel."S-waiting-on-review"]
+new_pr = true
+
+# Enable issue transfers within the org
+# Documentation at: https://forge.rust-lang.org/triagebot/transfer.html
+[transfer]
 
 [relabel]
 allow-unauthenticated = [
-    "waiting-on-review",
-    "waiting-on-author",
-    "blocked",
+    "-Z*",
+    "A-*",
+    "C-*",
+    "D-*",
+    "E-*",
+    "F-*",
+    "I-*",
+    "L-*",
+    "O-*",
+    "PG-*",
+    "S-*",
+    "T-*",
+    "WG-*",
+    "needs-triage",
 ]
 
+# Enable `@rustbot note` functionality
+# Documentation at: https://forge.rust-lang.org/triagebot/note.html
+[note]
+
+# Prevents mentions in commits to avoid users being spammed
+# Documentation at: https://forge.rust-lang.org/triagebot/no-mentions.html
 [no-mentions]
 
-[canonicalize-issue-links]
+# Canonicalize issue numbers to avoid closing the wrong issue
+# when commits are included in subtrees, as well as warning links in commits.
+# Documentation at: https://forge.rust-lang.org/triagebot/issue-links.html
+[issue-links]
 
 # Automatically close and reopen PRs made by bots to run CI on them
 [bot-pull-requests]
 
 [behind-upstream]
-days-threshold = 7
\ No newline at end of file
+days-threshold = 7
+
+# Enable triagebot (PR) assignment.
+# Documentation at: https://forge.rust-lang.org/triagebot/pr-assignment.html
+[assign]
+
+# Keep members alphanumerically sorted.
+[assign.adhoc_groups]
+rustc-dev-guide = [
+    "@BoxyUwU",
+    "@jieyouxu",
+    "@jyn514",
+    "@tshepang",
+]
diff --git a/src/doc/rustc/src/check-cfg/cargo-specifics.md b/src/doc/rustc/src/check-cfg/cargo-specifics.md
index 371bbd26e94..62a4dd1a390 100644
--- a/src/doc/rustc/src/check-cfg/cargo-specifics.md
+++ b/src/doc/rustc/src/check-cfg/cargo-specifics.md
@@ -9,8 +9,8 @@ rustc, not Cargo.
 -->
 
 This document is intended to summarize the principal ways Cargo interacts with
-the `unexpected_cfgs` lint and `--check-cfg` flag. It is not intended to provide
-individual details, for that refer to the [`--check-cfg` documentation](../check-cfg.md) and
+the `unexpected_cfgs` lint and `--check-cfg` flag.
+For individual details, refer to the [`--check-cfg` documentation](../check-cfg.md) and
 to the [Cargo book](../../cargo/index.html).
 
 > The full list of well known cfgs (aka builtins) can be found under [Checking conditional configurations / Well known names and values](../check-cfg.md#well-known-names-and-values).
diff --git a/src/doc/rustc/src/codegen-options/index.md b/src/doc/rustc/src/codegen-options/index.md
index a3b70e7f977..95e6afae8a1 100644
--- a/src/doc/rustc/src/codegen-options/index.md
+++ b/src/doc/rustc/src/codegen-options/index.md
@@ -192,6 +192,8 @@ to save information after compiling a crate to be reused when recompiling the
 crate, improving re-compile times. This takes a path to a directory where
 incremental files will be stored.
 
+Using incremental compilation inhibits certain optimizations (for example by increasing the amount of codegen units) and is therefore not recommend for release builds.
+
 ## inline-threshold
 
 This option is deprecated and does nothing.
@@ -213,6 +215,8 @@ This flag lets you append a single extra argument to the linker invocation.
 
 "Append" is significant; you can pass this flag multiple times to add multiple arguments.
 
+On Unix-like targets that use `cc` as the linker driver, use `-Clink-arg=-Wl,$ARG` to pass an argument to the actual linker.
+
 ## link-args
 
 This flag lets you append multiple extra arguments to the linker invocation. The
@@ -248,6 +252,10 @@ path to the linker executable. If this flag is not specified, the linker will
 be inferred based on the target. See also the [linker-flavor](#linker-flavor)
 flag for another way to specify the linker.
 
+Note that on Unix-like targets (for example, `*-unknown-linux-gnu` or `*-unknown-freebsd`)
+the C compiler (for example `cc` or `clang`) is used as the "linker" here, serving as a linker driver.
+It will invoke the actual linker with all the necessary flags to be able to link against the system libraries like libc.
+
 ## linker-flavor
 
 This flag controls the linker flavor used by `rustc`. If a linker is given with
@@ -301,6 +309,12 @@ The list must be separated by spaces.
 
 Pass `--help` to see a list of options.
 
+<div class="warning">
+
+Because this flag directly talks to LLVM, it is not subject to the usual stability guarantees of rustc's CLI interface.
+
+</div>
+
 ## lto
 
 This flag controls whether LLVM uses [link time
@@ -315,6 +329,7 @@ linking time. It takes one of the following values:
   LTO](http://blog.llvm.org/2016/06/thinlto-scalable-and-incremental-lto.html).
   This is similar to "fat", but takes substantially less time to run while
   still achieving performance gains similar to "fat".
+  For larger projects like the Rust compiler, ThinLTO can even result in better performance than fat LTO.
 
 If `-C lto` is not specified, then the compiler will attempt to perform "thin
 local LTO" which performs "thin" LTO on the local crate only across its
@@ -343,6 +358,8 @@ between two different versions of the same crate being linked.
 This flag tells the pass manager to use an empty list of passes, instead of the
 usual pre-populated list of passes.
 
+When combined with `-O --emit llvm-ir`, it can be used to see the optimized LLVM IR emitted by rustc before any optimizations are applied by LLVM.
+
 ## no-redzone
 
 This flag allows you to disable [the
@@ -379,7 +396,7 @@ This flag controls the optimization level.
 * `2`: some optimizations.
 * `3`: all optimizations.
 * `s`: optimize for binary size.
-* `z`: optimize for binary size, but also turn off loop vectorization.
+* `z`: optimize for binary size, but more aggressively. Often results in larger binaries than `s`
 
 Note: The [`-O` flag][option-o-optimize] is an alias for `-C opt-level=3`.
 
@@ -407,6 +424,9 @@ This option lets you control what happens when the code panics.
 
 If not specified, the default depends on the target.
 
+If any crate in the crate graph uses `abort`, the final binary (`bin`, `dylib`, `cdylib`, `staticlib`) must also use `abort`.
+If `std` is used as a `dylib` with `unwind`, the final binary must also use `unwind`.
+
 ## passes
 
 This flag can be used to add extra [LLVM
@@ -416,6 +436,12 @@ The list must be separated by spaces.
 
 See also the [`no-prepopulate-passes`](#no-prepopulate-passes) flag.
 
+<div class="warning">
+
+Because this flag directly talks to LLVM, it not subject to the usual stability guarantees of rustc's CLI interface.
+
+</div>
+
 ## prefer-dynamic
 
 By default, `rustc` prefers to statically link dependencies. This option will
@@ -523,12 +549,30 @@ The list of passes should be separated by spaces.
 
 ## rpath
 
-This flag controls whether [`rpath`](https://en.wikipedia.org/wiki/Rpath) is
-enabled. It takes one of the following values:
+This flag controls whether rustc sets an [`rpath`](https://en.wikipedia.org/wiki/Rpath) for the binary.
+It takes one of the following values:
 
 * `y`, `yes`, `on`, `true` or no value: enable rpath.
 * `n`, `no`, `off` or `false`: disable rpath (the default).
 
+This flag only does something on Unix-like platforms (Mach-O and ELF), it is ignored on other platforms.
+
+If enabled, rustc will add output-relative (using `@load_path` on Mach-O and `$ORIGIN` on ELF respectively) rpaths to all `dylib` dependencies.
+
+For example, for the following directory structure, with `libdep.so` being a `dylib` crate compiled with `-Cprefer-dynamic`:
+
+```text
+dep
+ |- libdep.so
+a.rs
+```
+
+`rustc a.rs --extern dep=dep/libdep.so -Crpath` will, on x86-64 Linux, result in approximately the following `DT_RUNPATH`: `$ORIGIN/dep:$ORIGIN/$RELATIVE_PATH_TO_SYSROOT/lib/rustlib/x86_64-unknown-linux-gnu/lib` (where `RELATIVE_PATH_TO_SYSROOT` depends on the build directory location).
+
+This is primarily useful for local development, to ensure that all the `dylib` dependencies can be found appropriately.
+
+To set the rpath to a different value (which can be useful for distribution), `-Clink-arg` with a platform-specific linker argument can be used to set the rpath directly.
+
 ## save-temps
 
 This flag controls whether temporary files generated during compilation are
@@ -545,6 +589,8 @@ point instructions in software. It takes one of the following values:
 * `y`, `yes`, `on`, `true` or no value: use soft floats.
 * `n`, `no`, `off` or `false`: use hardware floats (the default).
 
+This flag only works on `*eabihf` targets and **is unsound and deprecated**.
+
 ## split-debuginfo
 
 This option controls the emission of "split debuginfo" for debug information
diff --git a/src/doc/rustc/src/platform-support/x86_64-fortanix-unknown-sgx.md b/src/doc/rustc/src/platform-support/x86_64-fortanix-unknown-sgx.md
index e52ad1ce828..42662fbc0a1 100644
--- a/src/doc/rustc/src/platform-support/x86_64-fortanix-unknown-sgx.md
+++ b/src/doc/rustc/src/platform-support/x86_64-fortanix-unknown-sgx.md
@@ -11,7 +11,7 @@ based on the ABI defined by Fortanix for the [Enclave Development Platform
 
 [@jethrogb](https://github.com/jethrogb)
 [@raoulstrackx](https://github.com/raoulstrackx)
-[@mzohreva](https://github.com/mzohreva)
+[@aditijannu](https://github.com/aditijannu)
 
 Further contacts:
 
diff --git a/src/doc/unstable-book/README.md b/src/doc/unstable-book/README.md
new file mode 100644
index 00000000000..7acdd32857f
--- /dev/null
+++ b/src/doc/unstable-book/README.md
@@ -0,0 +1,8 @@
+# Unstable Book
+
+These are the sources for <https://doc.rust-lang.org/nightly/unstable-book/>.
+To generate them, run `./x doc unstable-book`, which will generate HTML files in `build/host/doc/unstable-book` using `src/tools/rustbook`.
+If you need to change the overall structure, modify `src/tools/unstable-book-gen/src/SUMMARY.md`.
+
+Note that most of this book is autogenerated by `unstable-book-gen`, with the exception of `compiler-flags` and `compiler-environment-variables`.
+As a result, it does not integrate well with `mdbook`. Use `./x doc` instead.
diff --git a/src/doc/unstable-book/src/compiler-environment-variables.md b/src/doc/unstable-book/src/compiler-environment-variables.md
new file mode 100644
index 00000000000..db912fdf3ba
--- /dev/null
+++ b/src/doc/unstable-book/src/compiler-environment-variables.md
@@ -0,0 +1 @@
+# Compiler environment variables
diff --git a/src/doc/unstable-book/src/compiler-flags/rustc-bootstrap.md b/src/doc/unstable-book/src/compiler-environment-variables/RUSTC_BOOTSTRAP.md
index 1520b86341b..fed28a33266 100644
--- a/src/doc/unstable-book/src/compiler-flags/rustc-bootstrap.md
+++ b/src/doc/unstable-book/src/compiler-environment-variables/RUSTC_BOOTSTRAP.md
@@ -14,7 +14,7 @@ Cargo disallows setting `cargo::rustc-env=RUSTC_BOOTSTRAP` in build scripts.
 Build systems can limit the features they enable with [`-Z allow-features=feature1,feature2`][Z-allow-features].
 Crates can fully opt out of unstable features by using [`#![forbid(unstable_features)]`][unstable-features] at the crate root (or any other way of enabling lints, such as `-F unstable-features`).
 
-[Z-allow-features]: ./allow-features.html
+[Z-allow-features]: ../compiler-flags/allow-features.html
 [unstable-features]: ../../rustc/lints/listing/allowed-by-default.html#unstable-features
 
 ## Why does this environment variable exist?
diff --git a/src/doc/unstable-book/src/compiler-flags/rustc-override-version-string.md b/src/doc/unstable-book/src/compiler-environment-variables/RUSTC_OVERRIDE_VERSION_STRING.md
index 3d867b5f714..3d867b5f714 100644
--- a/src/doc/unstable-book/src/compiler-flags/rustc-override-version-string.md
+++ b/src/doc/unstable-book/src/compiler-environment-variables/RUSTC_OVERRIDE_VERSION_STRING.md
diff --git a/src/doc/unstable-book/src/compiler-flags/allow-features.md b/src/doc/unstable-book/src/compiler-flags/allow-features.md
index 84fa465c89b..49a41a8c5a3 100644
--- a/src/doc/unstable-book/src/compiler-flags/allow-features.md
+++ b/src/doc/unstable-book/src/compiler-flags/allow-features.md
@@ -11,4 +11,4 @@ Features are comma-separated, for example `-Z allow-features=ffi_pure,f16`.
 If the flag is present, any feature listed will be allowed and any feature not listed will be disallowed.
 Any unrecognized feature is ignored.
 
-[`RUSTC_BOOTSTRAP`]: ./rustc-bootstrap.html
+[`RUSTC_BOOTSTRAP`]: ../compiler-environment-variables/RUSTC_BOOTSTRAP.html
diff --git a/src/doc/unstable-book/src/compiler-flags/no-steal-thir.md b/src/doc/unstable-book/src/compiler-flags/no-steal-thir.md
new file mode 100644
index 00000000000..d83677d1711
--- /dev/null
+++ b/src/doc/unstable-book/src/compiler-flags/no-steal-thir.md
@@ -0,0 +1,7 @@
+# `no-steal-thir`
+
+By default, to save on memory, the THIR body (obtained from the `tcx.thir_body` query) is stolen
+once no longer used. This is inconvenient for authors of rustc drivers who want to access the THIR.
+
+This option disables the stealing. This has no observable effect on compiler behavior, only on
+memory usage.
diff --git a/src/doc/unstable-book/src/language-features/repr128.md b/src/doc/unstable-book/src/language-features/repr128.md
deleted file mode 100644
index 146f50ee67b..00000000000
--- a/src/doc/unstable-book/src/language-features/repr128.md
+++ /dev/null
@@ -1,18 +0,0 @@
-# `repr128`
-
-The tracking issue for this feature is: [#56071]
-
-[#56071]: https://github.com/rust-lang/rust/issues/56071
-
-------------------------
-
-The `repr128` feature adds support for `#[repr(u128)]` on `enum`s.
-
-```rust
-#![feature(repr128)]
-
-#[repr(u128)]
-enum Foo {
-    Bar(u64),
-}
-```
diff --git a/src/librustdoc/clean/cfg.rs b/src/librustdoc/clean/cfg.rs
index 439777843fb..ebc276b38fb 100644
--- a/src/librustdoc/clean/cfg.rs
+++ b/src/librustdoc/clean/cfg.rs
@@ -171,10 +171,15 @@ impl Cfg {
 
     /// Renders the configuration for long display, as a long HTML description.
     pub(crate) fn render_long_html(&self) -> String {
-        let on = if self.should_use_with_in_description() { "with" } else { "on" };
+        let on = if self.omit_preposition() {
+            ""
+        } else if self.should_use_with_in_description() {
+            "with "
+        } else {
+            "on "
+        };
 
-        let mut msg =
-            format!("Available {on} <strong>{}</strong>", Display(self, Format::LongHtml));
+        let mut msg = format!("Available {on}<strong>{}</strong>", Display(self, Format::LongHtml));
         if self.should_append_only_to_description() {
             msg.push_str(" only");
         }
@@ -244,6 +249,10 @@ impl Cfg {
             Some(self.clone())
         }
     }
+
+    fn omit_preposition(&self) -> bool {
+        matches!(self, Cfg::True | Cfg::False)
+    }
 }
 
 impl ops::Not for Cfg {
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 28dfa01534e..e8cf25b1906 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -449,7 +449,7 @@ fn clean_middle_term<'tcx>(
     term: ty::Binder<'tcx, ty::Term<'tcx>>,
     cx: &mut DocContext<'tcx>,
 ) -> Term {
-    match term.skip_binder().unpack() {
+    match term.skip_binder().kind() {
         ty::TermKind::Ty(ty) => Term::Type(clean_middle_ty(term.rebind(ty), cx, None, None)),
         ty::TermKind::Const(c) => Term::Constant(clean_middle_const(term.rebind(c), cx)),
     }
@@ -1606,7 +1606,7 @@ fn first_non_private<'tcx>(
                     && let hir::Node::Item(item) = cx.tcx.hir_node_by_def_id(local_use_def_id)
                     && let hir::ItemKind::Use(path, hir::UseKind::Single(_)) = item.kind
                 {
-                    for res in &path.res {
+                    for res in path.res.present_items() {
                         if let Res::Def(DefKind::Ctor(..), _) | Res::SelfCtor(..) = res {
                             continue;
                         }
@@ -1749,7 +1749,7 @@ fn maybe_expand_private_type_alias<'tcx>(
     } else {
         return None;
     };
-    let hir::ItemKind::TyAlias(_, ty, generics) = alias else { return None };
+    let hir::ItemKind::TyAlias(_, generics, ty) = alias else { return None };
 
     let final_seg = &path.segments.last().expect("segments were empty");
     let mut args = DefIdMap::default();
@@ -2803,21 +2803,21 @@ fn clean_maybe_renamed_item<'tcx>(
         let mut name = get_name(cx, item, renamed).unwrap();
 
         let kind = match item.kind {
-            ItemKind::Static(_, ty, mutability, body_id) => StaticItem(Static {
+            ItemKind::Static(mutability, _, ty, body_id) => StaticItem(Static {
                 type_: Box::new(clean_ty(ty, cx)),
                 mutability,
                 expr: Some(body_id),
             }),
-            ItemKind::Const(_, ty, generics, body_id) => ConstantItem(Box::new(Constant {
+            ItemKind::Const(_, generics, ty, body_id) => ConstantItem(Box::new(Constant {
                 generics: clean_generics(generics, cx),
                 type_: clean_ty(ty, cx),
                 kind: ConstantKind::Local { body: body_id, def_id },
             })),
-            ItemKind::TyAlias(_, hir_ty, generics) => {
+            ItemKind::TyAlias(_, generics, ty) => {
                 *cx.current_type_aliases.entry(def_id).or_insert(0) += 1;
-                let rustdoc_ty = clean_ty(hir_ty, cx);
+                let rustdoc_ty = clean_ty(ty, cx);
                 let type_ =
-                    clean_middle_ty(ty::Binder::dummy(lower_ty(cx.tcx, hir_ty)), cx, None, None);
+                    clean_middle_ty(ty::Binder::dummy(lower_ty(cx.tcx, ty)), cx, None, None);
                 let generics = clean_generics(generics, cx);
                 if let Some(count) = cx.current_type_aliases.get_mut(&def_id) {
                     *count -= 1;
@@ -2846,7 +2846,7 @@ fn clean_maybe_renamed_item<'tcx>(
                 ));
                 return ret;
             }
-            ItemKind::Enum(_, def, generics) => EnumItem(Enum {
+            ItemKind::Enum(_, generics, def) => EnumItem(Enum {
                 variants: def.variants.iter().map(|v| clean_variant(v, cx)).collect(),
                 generics: clean_generics(generics, cx),
             }),
@@ -2854,11 +2854,11 @@ fn clean_maybe_renamed_item<'tcx>(
                 generics: clean_generics(generics, cx),
                 bounds: bounds.iter().filter_map(|x| clean_generic_bound(x, cx)).collect(),
             }),
-            ItemKind::Union(_, variant_data, generics) => UnionItem(Union {
+            ItemKind::Union(_, generics, variant_data) => UnionItem(Union {
                 generics: clean_generics(generics, cx),
                 fields: variant_data.fields().iter().map(|x| clean_field(x, cx)).collect(),
             }),
-            ItemKind::Struct(_, variant_data, generics) => StructItem(Struct {
+            ItemKind::Struct(_, generics, variant_data) => StructItem(Struct {
                 ctor_kind: variant_data.ctor_kind(),
                 generics: clean_generics(generics, cx),
                 fields: variant_data.fields().iter().map(|x| clean_field(x, cx)).collect(),
@@ -3014,7 +3014,7 @@ fn clean_use_statement<'tcx>(
 ) -> Vec<Item> {
     let mut items = Vec::new();
     let hir::UsePath { segments, ref res, span } = *path;
-    for &res in res {
+    for res in res.present_items() {
         let path = hir::Path { segments, res, span };
         items.append(&mut clean_use_statement_inner(import, name, &path, kind, cx, inlined_names));
     }
diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs
index 07ecd98f775..9e46d0b47e9 100644
--- a/src/librustdoc/clean/types.rs
+++ b/src/librustdoc/clean/types.rs
@@ -106,7 +106,7 @@ impl From<DefId> for ItemId {
 }
 
 /// The crate currently being documented.
-#[derive(Clone, Debug)]
+#[derive(Debug)]
 pub(crate) struct Crate {
     pub(crate) module: Item,
     /// Only here so that they can be filtered through the rustdoc passes.
@@ -610,6 +610,9 @@ impl Item {
             UnionItem(ref union_) => Some(union_.has_stripped_entries()),
             EnumItem(ref enum_) => Some(enum_.has_stripped_entries()),
             VariantItem(ref v) => v.has_stripped_entries(),
+            TypeAliasItem(ref type_alias) => {
+                type_alias.inner_type.as_ref().and_then(|t| t.has_stripped_entries())
+            }
             _ => None,
         }
     }
@@ -761,14 +764,11 @@ impl Item {
         Some(tcx.visibility(def_id))
     }
 
-    pub(crate) fn attributes(&self, tcx: TyCtxt<'_>, cache: &Cache, is_json: bool) -> Vec<String> {
+    pub(crate) fn attributes_without_repr(&self, tcx: TyCtxt<'_>, is_json: bool) -> Vec<String> {
         const ALLOWED_ATTRIBUTES: &[Symbol] =
             &[sym::export_name, sym::link_section, sym::no_mangle, sym::non_exhaustive];
 
-        use rustc_abi::IntegerType;
-
-        let mut attrs: Vec<String> = self
-            .attrs
+        self.attrs
             .other_attrs
             .iter()
             .filter_map(|attr| {
@@ -796,74 +796,28 @@ impl Item {
                     None
                 }
             })
-            .collect();
+            .collect()
+    }
 
-        // Add #[repr(...)]
-        if let Some(def_id) = self.def_id()
-            && let ItemType::Struct | ItemType::Enum | ItemType::Union = self.type_()
-        {
-            let adt = tcx.adt_def(def_id);
-            let repr = adt.repr();
-            let mut out = Vec::new();
-            if repr.c() {
-                out.push("C");
-            }
-            if repr.transparent() {
-                // Render `repr(transparent)` iff the non-1-ZST field is public or at least one
-                // field is public in case all fields are 1-ZST fields.
-                let render_transparent = is_json
-                    || cache.document_private
-                    || adt
-                        .all_fields()
-                        .find(|field| {
-                            let ty =
-                                field.ty(tcx, ty::GenericArgs::identity_for_item(tcx, field.did));
-                            tcx.layout_of(
-                                ty::TypingEnv::post_analysis(tcx, field.did).as_query_input(ty),
-                            )
-                            .is_ok_and(|layout| !layout.is_1zst())
-                        })
-                        .map_or_else(
-                            || adt.all_fields().any(|field| field.vis.is_public()),
-                            |field| field.vis.is_public(),
-                        );
+    pub(crate) fn attributes_and_repr(
+        &self,
+        tcx: TyCtxt<'_>,
+        cache: &Cache,
+        is_json: bool,
+    ) -> Vec<String> {
+        let mut attrs = self.attributes_without_repr(tcx, is_json);
 
-                if render_transparent {
-                    out.push("transparent");
-                }
-            }
-            if repr.simd() {
-                out.push("simd");
-            }
-            let pack_s;
-            if let Some(pack) = repr.pack {
-                pack_s = format!("packed({})", pack.bytes());
-                out.push(&pack_s);
-            }
-            let align_s;
-            if let Some(align) = repr.align {
-                align_s = format!("align({})", align.bytes());
-                out.push(&align_s);
-            }
-            let int_s;
-            if let Some(int) = repr.int {
-                int_s = match int {
-                    IntegerType::Pointer(is_signed) => {
-                        format!("{}size", if is_signed { 'i' } else { 'u' })
-                    }
-                    IntegerType::Fixed(size, is_signed) => {
-                        format!("{}{}", if is_signed { 'i' } else { 'u' }, size.size().bytes() * 8)
-                    }
-                };
-                out.push(&int_s);
-            }
-            if !out.is_empty() {
-                attrs.push(format!("#[repr({})]", out.join(", ")));
-            }
+        if let Some(repr_attr) = self.repr(tcx, cache, is_json) {
+            attrs.push(repr_attr);
         }
         attrs
     }
 
+    /// Returns a stringified `#[repr(...)]` attribute.
+    pub(crate) fn repr(&self, tcx: TyCtxt<'_>, cache: &Cache, is_json: bool) -> Option<String> {
+        repr_attributes(tcx, cache, self.def_id()?, self.type_(), is_json)
+    }
+
     pub fn is_doc_hidden(&self) -> bool {
         self.attrs.is_doc_hidden()
     }
@@ -873,6 +827,73 @@ impl Item {
     }
 }
 
+pub(crate) fn repr_attributes(
+    tcx: TyCtxt<'_>,
+    cache: &Cache,
+    def_id: DefId,
+    item_type: ItemType,
+    is_json: bool,
+) -> Option<String> {
+    use rustc_abi::IntegerType;
+
+    if !matches!(item_type, ItemType::Struct | ItemType::Enum | ItemType::Union) {
+        return None;
+    }
+    let adt = tcx.adt_def(def_id);
+    let repr = adt.repr();
+    let mut out = Vec::new();
+    if repr.c() {
+        out.push("C");
+    }
+    if repr.transparent() {
+        // Render `repr(transparent)` iff the non-1-ZST field is public or at least one
+        // field is public in case all fields are 1-ZST fields.
+        let render_transparent = cache.document_private
+            || is_json
+            || adt
+                .all_fields()
+                .find(|field| {
+                    let ty = field.ty(tcx, ty::GenericArgs::identity_for_item(tcx, field.did));
+                    tcx.layout_of(ty::TypingEnv::post_analysis(tcx, field.did).as_query_input(ty))
+                        .is_ok_and(|layout| !layout.is_1zst())
+                })
+                .map_or_else(
+                    || adt.all_fields().any(|field| field.vis.is_public()),
+                    |field| field.vis.is_public(),
+                );
+
+        if render_transparent {
+            out.push("transparent");
+        }
+    }
+    if repr.simd() {
+        out.push("simd");
+    }
+    let pack_s;
+    if let Some(pack) = repr.pack {
+        pack_s = format!("packed({})", pack.bytes());
+        out.push(&pack_s);
+    }
+    let align_s;
+    if let Some(align) = repr.align {
+        align_s = format!("align({})", align.bytes());
+        out.push(&align_s);
+    }
+    let int_s;
+    if let Some(int) = repr.int {
+        int_s = match int {
+            IntegerType::Pointer(is_signed) => {
+                format!("{}size", if is_signed { 'i' } else { 'u' })
+            }
+            IntegerType::Fixed(size, is_signed) => {
+                format!("{}{}", if is_signed { 'i' } else { 'u' }, size.size().bytes() * 8)
+            }
+        };
+        out.push(&int_s);
+    }
+    if !out.is_empty() { Some(format!("#[repr({})]", out.join(", "))) } else { None }
+}
+
 #[derive(Clone, Debug)]
 pub(crate) enum ItemKind {
     ExternCrateItem {
@@ -1035,17 +1056,11 @@ pub(crate) fn extract_cfg_from_attrs<'a, I: Iterator<Item = &'a hir::Attribute>
             .peekable();
         if doc_cfg.peek().is_some() && doc_cfg_active {
             let sess = tcx.sess;
+
             doc_cfg.fold(Cfg::True, |mut cfg, item| {
                 if let Some(cfg_mi) =
                     item.meta_item().and_then(|item| rustc_expand::config::parse_cfg(item, sess))
                 {
-                    // The result is unused here but we can gate unstable predicates
-                    rustc_attr_parsing::cfg_matches(
-                        cfg_mi,
-                        tcx.sess,
-                        rustc_ast::CRATE_NODE_ID,
-                        Some(tcx.features()),
-                    );
                     match Cfg::parse(cfg_mi) {
                         Ok(new_cfg) => cfg &= new_cfg,
                         Err(e) => {
@@ -1601,9 +1616,7 @@ impl Type {
                 a.def_id() == b.def_id()
                     && a.generics()
                         .zip(b.generics())
-                        .map(|(ag, bg)| {
-                            ag.iter().zip(bg.iter()).all(|(at, bt)| at.is_doc_subtype_of(bt, cache))
-                        })
+                        .map(|(ag, bg)| ag.zip(bg).all(|(at, bt)| at.is_doc_subtype_of(bt, cache)))
                         .unwrap_or(true)
             }
             // Other cases, such as primitives, just use recursion.
@@ -1676,7 +1689,7 @@ impl Type {
         }
     }
 
-    pub(crate) fn generics(&self) -> Option<Vec<&Type>> {
+    pub(crate) fn generics<'a>(&'a self) -> Option<impl Iterator<Item = &'a Type>> {
         match self {
             Type::Path { path, .. } => path.generics(),
             _ => None,
@@ -2107,7 +2120,7 @@ impl Enum {
         self.variants.iter().any(|f| f.is_stripped())
     }
 
-    pub(crate) fn variants(&self) -> impl Iterator<Item = &Item> {
+    pub(crate) fn non_stripped_variants(&self) -> impl Iterator<Item = &Item> {
         self.variants.iter().filter(|v| !v.is_stripped())
     }
 }
@@ -2234,17 +2247,13 @@ impl Path {
         self.segments.last().map(|seg| &seg.args)
     }
 
-    pub(crate) fn generics(&self) -> Option<Vec<&Type>> {
+    pub(crate) fn generics<'a>(&'a self) -> Option<impl Iterator<Item = &'a Type>> {
         self.segments.last().and_then(|seg| {
             if let GenericArgs::AngleBracketed { ref args, .. } = seg.args {
-                Some(
-                    args.iter()
-                        .filter_map(|arg| match arg {
-                            GenericArg::Type(ty) => Some(ty),
-                            _ => None,
-                        })
-                        .collect(),
-                )
+                Some(args.iter().filter_map(|arg| match arg {
+                    GenericArg::Type(ty) => Some(ty),
+                    _ => None,
+                }))
             } else {
                 None
             }
@@ -2345,6 +2354,17 @@ pub(crate) enum TypeAliasInnerType {
     Struct { ctor_kind: Option<CtorKind>, fields: Vec<Item> },
 }
 
+impl TypeAliasInnerType {
+    fn has_stripped_entries(&self) -> Option<bool> {
+        Some(match self {
+            Self::Enum { variants, .. } => variants.iter().any(|v| v.is_stripped()),
+            Self::Union { fields } | Self::Struct { fields, .. } => {
+                fields.iter().any(|f| f.is_stripped())
+            }
+        })
+    }
+}
+
 #[derive(Clone, Debug)]
 pub(crate) struct TypeAlias {
     pub(crate) type_: Type,
diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs
index 2e38b6cdc65..c58b07a5b67 100644
--- a/src/librustdoc/clean/utils.rs
+++ b/src/librustdoc/clean/utils.rs
@@ -124,7 +124,7 @@ pub(crate) fn clean_middle_generic_args<'tcx>(
             elision_has_failed_once_before = true;
         }
 
-        match arg.skip_binder().unpack() {
+        match arg.skip_binder().kind() {
             GenericArgKind::Lifetime(lt) => {
                 Some(GenericArg::Lifetime(clean_middle_region(lt).unwrap_or(Lifetime::elided())))
             }
@@ -161,7 +161,7 @@ fn can_elide_generic_arg<'tcx>(
     default: ty::Binder<'tcx, ty::GenericArg<'tcx>>,
 ) -> bool {
     debug_assert_matches!(
-        (actual.skip_binder().unpack(), default.skip_binder().unpack()),
+        (actual.skip_binder().kind(), default.skip_binder().kind()),
         (ty::GenericArgKind::Lifetime(_), ty::GenericArgKind::Lifetime(_))
             | (ty::GenericArgKind::Type(_), ty::GenericArgKind::Type(_))
             | (ty::GenericArgKind::Const(_), ty::GenericArgKind::Const(_))
diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs
index 486d4ae932d..e9a7f4367a3 100644
--- a/src/librustdoc/html/format.rs
+++ b/src/librustdoc/html/format.rs
@@ -7,13 +7,12 @@
 //! some of them support an alternate format that emits text, but that should
 //! not be used external to this module.
 
-use std::borrow::Cow;
 use std::cmp::Ordering;
 use std::fmt::{self, Display, Write};
 use std::iter::{self, once};
 use std::slice;
 
-use itertools::Either;
+use itertools::{Either, Itertools};
 use rustc_abi::ExternAbi;
 use rustc_attr_data_structures::{ConstStability, StabilityLevel, StableSince};
 use rustc_data_structures::fx::FxHashSet;
@@ -483,12 +482,12 @@ fn generate_item_def_id_path(
     let mut is_remote = false;
 
     let url_parts = url_parts(cx.cache(), def_id, module_fqp, &cx.current, &mut is_remote)?;
-    let (url_parts, shortty, fqp) = make_href(root_path, shortty, url_parts, &fqp, is_remote)?;
-    if def_id == original_def_id {
-        return Ok((url_parts, shortty, fqp));
-    }
-    let kind = ItemType::from_def_kind(original_def_kind, Some(def_kind));
-    Ok((format!("{url_parts}#{kind}.{}", tcx.item_name(original_def_id)), shortty, fqp))
+    let mut url_parts = make_href(root_path, shortty, url_parts, &fqp, is_remote);
+    if def_id != original_def_id {
+        let kind = ItemType::from_def_kind(original_def_kind, Some(def_kind));
+        url_parts = format!("{url_parts}#{kind}.{}", tcx.item_name(original_def_id))
+    };
+    Ok((url_parts, shortty, fqp))
 }
 
 fn to_module_fqp(shortty: ItemType, fqp: &[Symbol]) -> &[Symbol] {
@@ -510,7 +509,7 @@ fn url_parts(
             builder.extend(module_fqp.iter().copied());
             Ok(builder)
         }
-        ExternalLocation::Local => Ok(href_relative_parts(module_fqp, relative_to).collect()),
+        ExternalLocation::Local => Ok(href_relative_parts(module_fqp, relative_to)),
         ExternalLocation::Unknown => Err(HrefError::DocumentationNotBuilt),
     }
 }
@@ -521,7 +520,7 @@ fn make_href(
     mut url_parts: UrlPartsBuilder,
     fqp: &[Symbol],
     is_remote: bool,
-) -> Result<(String, ItemType, Vec<Symbol>), HrefError> {
+) -> String {
     if !is_remote && let Some(root_path) = root_path {
         let root = root_path.trim_end_matches('/');
         url_parts.push_front(root);
@@ -536,7 +535,7 @@ fn make_href(
             url_parts.push_fmt(format_args!("{shortty}.{last}.html"));
         }
     }
-    Ok((url_parts.finish(), shortty, fqp.to_vec()))
+    url_parts.finish()
 }
 
 pub(crate) fn href_with_root_path(
@@ -587,7 +586,7 @@ pub(crate) fn href_with_root_path(
         Some(&(ref fqp, shortty)) => (fqp, shortty, {
             let module_fqp = to_module_fqp(shortty, fqp.as_slice());
             debug!(?fqp, ?shortty, ?module_fqp);
-            href_relative_parts(module_fqp, relative_to).collect()
+            href_relative_parts(module_fqp, relative_to)
         }),
         None => {
             // Associated items are handled differently with "jump to def". The anchor is generated
@@ -606,7 +605,8 @@ pub(crate) fn href_with_root_path(
             }
         }
     };
-    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()))
 }
 
 pub(crate) fn href(
@@ -619,34 +619,30 @@ pub(crate) fn href(
 /// Both paths should only be modules.
 /// This is because modules get their own directories; that is, `std::vec` and `std::vec::Vec` will
 /// both need `../iter/trait.Iterator.html` to get at the iterator trait.
-pub(crate) fn href_relative_parts<'fqp>(
-    fqp: &'fqp [Symbol],
-    relative_to_fqp: &[Symbol],
-) -> Box<dyn Iterator<Item = Symbol> + 'fqp> {
+pub(crate) fn href_relative_parts(fqp: &[Symbol], relative_to_fqp: &[Symbol]) -> UrlPartsBuilder {
     for (i, (f, r)) in fqp.iter().zip(relative_to_fqp.iter()).enumerate() {
         // e.g. linking to std::iter from std::vec (`dissimilar_part_count` will be 1)
         if f != r {
             let dissimilar_part_count = relative_to_fqp.len() - i;
             let fqp_module = &fqp[i..];
-            return Box::new(
-                iter::repeat_n(sym::dotdot, dissimilar_part_count)
-                    .chain(fqp_module.iter().copied()),
-            );
+            return iter::repeat_n(sym::dotdot, dissimilar_part_count)
+                .chain(fqp_module.iter().copied())
+                .collect();
         }
     }
     match relative_to_fqp.len().cmp(&fqp.len()) {
         Ordering::Less => {
             // e.g. linking to std::sync::atomic from std::sync
-            Box::new(fqp[relative_to_fqp.len()..fqp.len()].iter().copied())
+            fqp[relative_to_fqp.len()..fqp.len()].iter().copied().collect()
         }
         Ordering::Greater => {
             // e.g. linking to std::sync from std::sync::atomic
             let dissimilar_part_count = relative_to_fqp.len() - fqp.len();
-            Box::new(iter::repeat_n(sym::dotdot, dissimilar_part_count))
+            iter::repeat_n(sym::dotdot, dissimilar_part_count).collect()
         }
         Ordering::Equal => {
             // linking to the same module
-            Box::new(iter::empty())
+            UrlPartsBuilder::new()
         }
     }
 }
@@ -708,13 +704,13 @@ fn resolved_path(
                         f,
                         "{path}::{anchor}",
                         path = join_with_double_colon(&fqp[..fqp.len() - 1]),
-                        anchor = anchor(did, *fqp.last().unwrap(), cx)
+                        anchor = print_anchor(did, *fqp.last().unwrap(), cx)
                     )
                 } else {
                     write!(f, "{}", last.name)
                 }
             } else {
-                write!(f, "{}", anchor(did, last.name, cx))
+                write!(f, "{}", print_anchor(did, last.name, cx))
             }
         });
         write!(w, "{path}{args}", args = last.args.print(cx))?;
@@ -800,7 +796,7 @@ fn primitive_link_fragment(
     Ok(())
 }
 
-fn tybounds(
+fn print_tybounds(
     bounds: &[clean::PolyTrait],
     lt: &Option<clean::Lifetime>,
     cx: &Context<'_>,
@@ -832,7 +828,7 @@ fn print_higher_ranked_params_with_space(
     })
 }
 
-pub(crate) fn anchor(did: DefId, text: Symbol, cx: &Context<'_>) -> impl Display {
+pub(crate) fn print_anchor(did: DefId, text: Symbol, cx: &Context<'_>) -> impl Display {
     fmt::from_fn(move |f| {
         let parts = href(did, cx);
         if let Ok((url, short_ty, fqp)) = parts {
@@ -866,7 +862,7 @@ fn fmt_type(
         }
         clean::DynTrait(bounds, lt) => {
             f.write_str("dyn ")?;
-            tybounds(bounds, lt, cx).fmt(f)
+            print_tybounds(bounds, lt, cx).fmt(f)
         }
         clean::Infer => write!(f, "_"),
         clean::Primitive(clean::PrimitiveType::Never) => {
@@ -1122,8 +1118,8 @@ impl clean::Impl {
                     write!(f, "!")?;
                 }
                 if self.kind.is_fake_variadic()
-                    && let generics = ty.generics()
-                    && let &[inner_type] = generics.as_ref().map_or(&[][..], |v| &v[..])
+                    && let Some(generics) = ty.generics()
+                    && let Ok(inner_type) = generics.exactly_one()
                 {
                     let last = ty.last();
                     if f.alternate() {
@@ -1131,7 +1127,7 @@ impl clean::Impl {
                         self.print_type(inner_type, f, use_absolute, cx)?;
                         write!(f, ">")?;
                     } else {
-                        write!(f, "{}&lt;", anchor(ty.def_id(), last, cx))?;
+                        write!(f, "{}&lt;", print_anchor(ty.def_id(), last, cx))?;
                         self.print_type(inner_type, f, use_absolute, cx)?;
                         write!(f, "&gt;")?;
                     }
@@ -1202,11 +1198,10 @@ impl clean::Impl {
             }
         } else if let clean::Type::Path { path } = type_
             && let Some(generics) = path.generics()
-            && generics.len() == 1
+            && let Ok(ty) = generics.exactly_one()
             && self.kind.is_fake_variadic()
         {
-            let ty = generics[0];
-            let wrapper = anchor(path.def_id(), path.last(), cx);
+            let wrapper = print_anchor(path.def_id(), path.last(), cx);
             if f.alternate() {
                 write!(f, "{wrapper:#}&lt;")?;
             } else {
@@ -1394,50 +1389,47 @@ impl clean::FnDecl {
 }
 
 pub(crate) fn visibility_print_with_space(item: &clean::Item, cx: &Context<'_>) -> impl Display {
-    use std::fmt::Write as _;
-    let vis: Cow<'static, str> = match item.visibility(cx.tcx()) {
-        None => "".into(),
-        Some(ty::Visibility::Public) => "pub ".into(),
-        Some(ty::Visibility::Restricted(vis_did)) => {
-            // FIXME(camelid): This may not work correctly if `item_did` is a module.
-            //                 However, rustdoc currently never displays a module's
-            //                 visibility, so it shouldn't matter.
-            let parent_module = find_nearest_parent_module(cx.tcx(), item.item_id.expect_def_id());
-
-            if vis_did.is_crate_root() {
-                "pub(crate) ".into()
-            } else if parent_module == Some(vis_did) {
-                // `pub(in foo)` where `foo` is the parent module
-                // is the same as no visibility modifier
-                "".into()
-            } else if parent_module.and_then(|parent| find_nearest_parent_module(cx.tcx(), parent))
-                == Some(vis_did)
-            {
-                "pub(super) ".into()
-            } else {
-                let path = cx.tcx().def_path(vis_did);
-                debug!("path={path:?}");
-                // modified from `resolved_path()` to work with `DefPathData`
-                let last_name = path.data.last().unwrap().data.get_opt_name().unwrap();
-                let anchor = anchor(vis_did, last_name, cx);
-
-                let mut s = "pub(in ".to_owned();
-                for seg in &path.data[..path.data.len() - 1] {
-                    let _ = write!(s, "{}::", seg.data.get_opt_name().unwrap());
-                }
-                let _ = write!(s, "{anchor}) ");
-                s.into()
-            }
-        }
-    };
-
-    let is_doc_hidden = item.is_doc_hidden();
     fmt::from_fn(move |f| {
-        if is_doc_hidden {
+        if item.is_doc_hidden() {
             f.write_str("#[doc(hidden)] ")?;
         }
 
-        f.write_str(&vis)
+        match item.visibility(cx.tcx()) {
+            None => {}
+            Some(ty::Visibility::Public) => f.write_str("pub ")?,
+            Some(ty::Visibility::Restricted(vis_did)) => {
+                // FIXME(camelid): This may not work correctly if `item_did` is a module.
+                //                 However, rustdoc currently never displays a module's
+                //                 visibility, so it shouldn't matter.
+                let parent_module =
+                    find_nearest_parent_module(cx.tcx(), item.item_id.expect_def_id());
+
+                if vis_did.is_crate_root() {
+                    f.write_str("pub(crate) ")?;
+                } else if parent_module == Some(vis_did) {
+                    // `pub(in foo)` where `foo` is the parent module
+                    // is the same as no visibility modifier; do nothing
+                } else if parent_module
+                    .and_then(|parent| find_nearest_parent_module(cx.tcx(), parent))
+                    == Some(vis_did)
+                {
+                    f.write_str("pub(super) ")?;
+                } else {
+                    let path = cx.tcx().def_path(vis_did);
+                    debug!("path={path:?}");
+                    // modified from `resolved_path()` to work with `DefPathData`
+                    let last_name = path.data.last().unwrap().data.get_opt_name().unwrap();
+                    let anchor = print_anchor(vis_did, last_name, cx);
+
+                    f.write_str("pub(in ")?;
+                    for seg in &path.data[..path.data.len() - 1] {
+                        write!(f, "{}::", seg.data.get_opt_name().unwrap())?;
+                    }
+                    write!(f, "{anchor}) ")?;
+                }
+            }
+        }
+        Ok(())
     })
 }
 
diff --git a/src/librustdoc/html/highlight.rs b/src/librustdoc/html/highlight.rs
index 2db1ea8450c..b2feee36c93 100644
--- a/src/librustdoc/html/highlight.rs
+++ b/src/librustdoc/html/highlight.rs
@@ -6,7 +6,7 @@
 //! Use the `render_with_highlighting` to highlight some rust code.
 
 use std::collections::VecDeque;
-use std::fmt::{Display, Write};
+use std::fmt::{self, Display, Write};
 
 use rustc_data_structures::fx::FxIndexMap;
 use rustc_lexer::{Cursor, FrontmatterAllowed, LiteralKind, TokenKind};
@@ -36,9 +36,10 @@ pub(crate) struct HrefContext<'a, 'tcx> {
 #[derive(Default)]
 pub(crate) struct DecorationInfo(pub(crate) FxIndexMap<&'static str, Vec<(u32, u32)>>);
 
-#[derive(Eq, PartialEq, Clone, Copy)]
+#[derive(Eq, PartialEq, Clone)]
 pub(crate) enum Tooltip {
-    Ignore,
+    IgnoreAll,
+    IgnoreSome(Vec<String>),
     CompileFail,
     ShouldPanic,
     Edition(Edition),
@@ -70,7 +71,7 @@ fn write_header(
         format_args!(
             "<div class=\"example-wrap{}\">",
             match tooltip {
-                Tooltip::Ignore => " ignore",
+                Tooltip::IgnoreAll | Tooltip::IgnoreSome(_) => " ignore",
                 Tooltip::CompileFail => " compile_fail",
                 Tooltip::ShouldPanic => " should_panic",
                 Tooltip::Edition(_) => " edition",
@@ -80,23 +81,29 @@ fn write_header(
     );
 
     if tooltip != Tooltip::None {
-        let edition_code;
-        write_str(
-            out,
-            format_args!(
-                "<a href=\"#\" class=\"tooltip\" title=\"{}\">ⓘ</a>",
-                match tooltip {
-                    Tooltip::Ignore => "This example is not tested",
-                    Tooltip::CompileFail => "This example deliberately fails to compile",
-                    Tooltip::ShouldPanic => "This example panics",
-                    Tooltip::Edition(edition) => {
-                        edition_code = format!("This example runs with edition {edition}");
-                        &edition_code
+        let tooltip = fmt::from_fn(|f| match &tooltip {
+            Tooltip::IgnoreAll => f.write_str("This example is not tested"),
+            Tooltip::IgnoreSome(platforms) => {
+                f.write_str("This example is not tested on ")?;
+                match &platforms[..] {
+                    [] => unreachable!(),
+                    [platform] => f.write_str(platform)?,
+                    [first, second] => write!(f, "{first} or {second}")?,
+                    [platforms @ .., last] => {
+                        for platform in platforms {
+                            write!(f, "{platform}, ")?;
+                        }
+                        write!(f, "or {last}")?;
                     }
-                    Tooltip::None => unreachable!(),
                 }
-            ),
-        );
+                Ok(())
+            }
+            Tooltip::CompileFail => f.write_str("This example deliberately fails to compile"),
+            Tooltip::ShouldPanic => f.write_str("This example panics"),
+            Tooltip::Edition(edition) => write!(f, "This example runs with edition {edition}"),
+            Tooltip::None => unreachable!(),
+        });
+        write_str(out, format_args!("<a href=\"#\" class=\"tooltip\" title=\"{tooltip}\">ⓘ</a>"));
     }
 
     if let Some(extra) = extra_content {
diff --git a/src/librustdoc/html/layout.rs b/src/librustdoc/html/layout.rs
index 3b5f9b5a458..50320cb231d 100644
--- a/src/librustdoc/html/layout.rs
+++ b/src/librustdoc/html/layout.rs
@@ -8,7 +8,6 @@ use super::static_files::{STATIC_FILES, StaticFiles};
 use crate::externalfiles::ExternalHtml;
 use crate::html::render::{StylePath, ensure_trailing_slash};
 
-#[derive(Clone)]
 pub(crate) struct Layout {
     pub(crate) logo: String,
     pub(crate) favicon: String,
diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs
index ad7dfafd90c..68ba1245520 100644
--- a/src/librustdoc/html/markdown.rs
+++ b/src/librustdoc/html/markdown.rs
@@ -195,7 +195,7 @@ fn slugify(c: char) -> Option<char> {
     }
 }
 
-#[derive(Clone, Debug)]
+#[derive(Debug)]
 pub struct Playground {
     pub crate_name: Option<Symbol>,
     pub url: String,
@@ -320,8 +320,10 @@ impl<'a, I: Iterator<Item = Event<'a>>> Iterator for CodeBlocks<'_, 'a, I> {
             ))
         });
 
-        let tooltip = if ignore != Ignore::None {
-            highlight::Tooltip::Ignore
+        let tooltip = if ignore == Ignore::All {
+            highlight::Tooltip::IgnoreAll
+        } else if let Ignore::Some(platforms) = ignore {
+            highlight::Tooltip::IgnoreSome(platforms)
         } else if compile_fail {
             highlight::Tooltip::CompileFail
         } else if should_panic {
diff --git a/src/librustdoc/html/render/context.rs b/src/librustdoc/html/render/context.rs
index 1f7201b8ca8..5984dcd74ca 100644
--- a/src/librustdoc/html/render/context.rs
+++ b/src/librustdoc/html/render/context.rs
@@ -14,7 +14,7 @@ use rustc_span::edition::Edition;
 use rustc_span::{FileName, Symbol, sym};
 use tracing::info;
 
-use super::print_item::{full_path, item_path, print_item};
+use super::print_item::{full_path, print_item, print_item_path};
 use super::sidebar::{ModuleLike, Sidebar, print_sidebar, sidebar_module_like};
 use super::{AllTypes, LinkFromSrc, StylePath, collect_spans_and_sources, scrape_examples_help};
 use crate::clean::types::ExternalLocation;
@@ -266,7 +266,7 @@ impl<'tcx> Context<'tcx> {
                         for name in &names[..names.len() - 1] {
                             write!(f, "{name}/")?;
                         }
-                        write!(f, "{}", item_path(ty, names.last().unwrap().as_str()))
+                        write!(f, "{}", print_item_path(ty, names.last().unwrap().as_str()))
                     });
                     match self.shared.redirections {
                         Some(ref redirections) => {
@@ -278,7 +278,7 @@ impl<'tcx> Context<'tcx> {
                             let _ = write!(
                                 current_path,
                                 "{}",
-                                item_path(ty, names.last().unwrap().as_str())
+                                print_item_path(ty, names.last().unwrap().as_str())
                             );
                             redirections.borrow_mut().insert(current_path, path.to_string());
                         }
@@ -847,7 +847,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
         if !buf.is_empty() {
             let name = item.name.as_ref().unwrap();
             let item_type = item.type_();
-            let file_name = item_path(item_type, name.as_str()).to_string();
+            let file_name = print_item_path(item_type, name.as_str()).to_string();
             self.shared.ensure_dir(&self.dst)?;
             let joint_dst = self.dst.join(&file_name);
             self.shared.fs.write(joint_dst, buf)?;
diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs
index 06cb9269cc8..66d5aafa3c1 100644
--- a/src/librustdoc/html/render/mod.rs
+++ b/src/librustdoc/html/render/mod.rs
@@ -1194,18 +1194,36 @@ fn render_assoc_item(
 // a whitespace prefix and newline.
 fn render_attributes_in_pre(it: &clean::Item, prefix: &str, cx: &Context<'_>) -> impl fmt::Display {
     fmt::from_fn(move |f| {
-        for a in it.attributes(cx.tcx(), cx.cache(), false) {
+        for a in it.attributes_and_repr(cx.tcx(), cx.cache(), false) {
             writeln!(f, "{prefix}{a}")?;
         }
         Ok(())
     })
 }
 
+struct CodeAttribute(String);
+
+fn render_code_attribute(code_attr: CodeAttribute, w: &mut impl fmt::Write) {
+    write!(w, "<div class=\"code-attribute\">{}</div>", code_attr.0).unwrap();
+}
+
 // When an attribute is rendered inside a <code> tag, it is formatted using
 // a div to produce a newline after it.
 fn render_attributes_in_code(w: &mut impl fmt::Write, it: &clean::Item, cx: &Context<'_>) {
-    for attr in it.attributes(cx.tcx(), cx.cache(), false) {
-        write!(w, "<div class=\"code-attribute\">{attr}</div>").unwrap();
+    for attr in it.attributes_and_repr(cx.tcx(), cx.cache(), false) {
+        render_code_attribute(CodeAttribute(attr), w);
+    }
+}
+
+/// used for type aliases to only render their `repr` attribute.
+fn render_repr_attributes_in_code(
+    w: &mut impl fmt::Write,
+    cx: &Context<'_>,
+    def_id: DefId,
+    item_type: ItemType,
+) {
+    if let Some(repr) = clean::repr_attributes(cx.tcx(), cx.cache(), def_id, item_type, false) {
+        render_code_attribute(CodeAttribute(repr), w);
     }
 }
 
@@ -2530,7 +2548,7 @@ fn item_ty_to_section(ty: ItemType) -> ItemSection {
 /// types are re-exported, we don't use the corresponding
 /// entry from the js file, as inlining will have already
 /// picked up the impl
-fn collect_paths_for_type(first_ty: clean::Type, cache: &Cache) -> Vec<String> {
+fn collect_paths_for_type(first_ty: &clean::Type, cache: &Cache) -> Vec<String> {
     let mut out = Vec::new();
     let mut visited = FxHashSet::default();
     let mut work = VecDeque::new();
@@ -2547,7 +2565,7 @@ fn collect_paths_for_type(first_ty: clean::Type, cache: &Cache) -> Vec<String> {
     work.push_back(first_ty);
 
     while let Some(ty) = work.pop_front() {
-        if !visited.insert(ty.clone()) {
+        if !visited.insert(ty) {
             continue;
         }
 
@@ -2557,16 +2575,16 @@ fn collect_paths_for_type(first_ty: clean::Type, cache: &Cache) -> Vec<String> {
                 work.extend(tys.into_iter());
             }
             clean::Type::Slice(ty) => {
-                work.push_back(*ty);
+                work.push_back(ty);
             }
             clean::Type::Array(ty, _) => {
-                work.push_back(*ty);
+                work.push_back(ty);
             }
             clean::Type::RawPointer(_, ty) => {
-                work.push_back(*ty);
+                work.push_back(ty);
             }
             clean::Type::BorrowedRef { type_, .. } => {
-                work.push_back(*type_);
+                work.push_back(type_);
             }
             clean::Type::QPath(box clean::QPathData { self_type, trait_, .. }) => {
                 work.push_back(self_type);
diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs
index 39a631b637b..a75088d27cc 100644
--- a/src/librustdoc/html/render/print_item.rs
+++ b/src/librustdoc/html/render/print_item.rs
@@ -20,7 +20,7 @@ use super::{
     collect_paths_for_type, document, ensure_trailing_slash, get_filtered_impls_for_reference,
     item_ty_to_section, notable_traits_button, notable_traits_json, render_all_impls,
     render_assoc_item, render_assoc_items, render_attributes_in_code, render_attributes_in_pre,
-    render_impl, render_rightside, render_stability_since_raw,
+    render_impl, render_repr_attributes_in_code, render_rightside, render_stability_since_raw,
     render_stability_since_raw_with_extra, write_section_heading,
 };
 use crate::clean;
@@ -413,7 +413,7 @@ fn item_module(cx: &Context<'_>, item: &clean::Item, items: &[clean::Item]) -> i
 
             match myitem.kind {
                 clean::ExternCrateItem { ref src } => {
-                    use crate::html::format::anchor;
+                    use crate::html::format::print_anchor;
 
                     match *src {
                         Some(src) => {
@@ -421,7 +421,7 @@ fn item_module(cx: &Context<'_>, item: &clean::Item, items: &[clean::Item]) -> i
                                 w,
                                 "<dt><code>{}extern crate {} as {};",
                                 visibility_print_with_space(myitem, cx),
-                                anchor(myitem.item_id.expect_def_id(), src, cx),
+                                print_anchor(myitem.item_id.expect_def_id(), src, cx),
                                 EscapeBodyTextWithWbr(myitem.name.unwrap().as_str())
                             )?;
                         }
@@ -430,7 +430,11 @@ fn item_module(cx: &Context<'_>, item: &clean::Item, items: &[clean::Item]) -> i
                                 w,
                                 "<dt><code>{}extern crate {};",
                                 visibility_print_with_space(myitem, cx),
-                                anchor(myitem.item_id.expect_def_id(), myitem.name.unwrap(), cx)
+                                print_anchor(
+                                    myitem.item_id.expect_def_id(),
+                                    myitem.name.unwrap(),
+                                    cx
+                                )
                             )?;
                         }
                     }
@@ -439,7 +443,7 @@ fn item_module(cx: &Context<'_>, item: &clean::Item, items: &[clean::Item]) -> i
 
                 clean::ImportItem(ref import) => {
                     let stab_tags = import.source.did.map_or_else(String::new, |import_def_id| {
-                        extra_info_tags(tcx, myitem, item, Some(import_def_id)).to_string()
+                        print_extra_info_tags(tcx, myitem, item, Some(import_def_id)).to_string()
                     });
 
                     let id = match import.kind {
@@ -497,7 +501,9 @@ fn item_module(cx: &Context<'_>, item: &clean::Item, items: &[clean::Item]) -> i
                     write!(
                         w,
                         "<dt>\
-                            <a class=\"{class}\" href=\"{href}\" title=\"{title}\">{name}</a>\
+                            <a class=\"{class}\" href=\"{href}\" title=\"{title1} {title2}\">\
+                            {name}\
+                            </a>\
                             {visibility_and_hidden}\
                             {unsafety_flag}\
                             {stab_tags}\
@@ -505,11 +511,12 @@ fn item_module(cx: &Context<'_>, item: &clean::Item, items: &[clean::Item]) -> i
                         {docs_before}{docs}{docs_after}",
                         name = EscapeBodyTextWithWbr(myitem.name.unwrap().as_str()),
                         visibility_and_hidden = visibility_and_hidden,
-                        stab_tags = extra_info_tags(tcx, myitem, item, None),
+                        stab_tags = print_extra_info_tags(tcx, myitem, item, None),
                         class = myitem.type_(),
                         unsafety_flag = unsafety_flag,
-                        href = item_path(myitem.type_(), myitem.name.unwrap().as_str()),
-                        title = format_args!("{} {}", myitem.type_(), full_path(cx, myitem)),
+                        href = print_item_path(myitem.type_(), myitem.name.unwrap().as_str()),
+                        title1 = myitem.type_(),
+                        title2 = full_path(cx, myitem),
                     )?;
                 }
             }
@@ -524,7 +531,7 @@ fn item_module(cx: &Context<'_>, item: &clean::Item, items: &[clean::Item]) -> i
 
 /// Render the stability, deprecation and portability tags that are displayed in the item's summary
 /// at the module level.
-fn extra_info_tags(
+fn print_extra_info_tags(
     tcx: TyCtxt<'_>,
     item: &clean::Item,
     parent: &clean::Item,
@@ -639,7 +646,7 @@ fn item_function(cx: &Context<'_>, it: &clean::Item, f: &clean::Function) -> imp
 fn item_trait(cx: &Context<'_>, it: &clean::Item, t: &clean::Trait) -> impl fmt::Display {
     fmt::from_fn(|w| {
         let tcx = cx.tcx();
-        let bounds = bounds(&t.bounds, false, cx);
+        let bounds = print_bounds(&t.bounds, false, cx);
         let required_types =
             t.items.iter().filter(|m| m.is_required_associated_type()).collect::<Vec<_>>();
         let provided_types = t.items.iter().filter(|m| m.is_associated_type()).collect::<Vec<_>>();
@@ -652,7 +659,7 @@ fn item_trait(cx: &Context<'_>, it: &clean::Item, t: &clean::Trait) -> impl fmt:
         let count_types = required_types.len() + provided_types.len();
         let count_consts = required_consts.len() + provided_consts.len();
         let count_methods = required_methods.len() + provided_methods.len();
-        let must_implement_one_of_functions = tcx.trait_def(t.def_id).must_implement_one_of.clone();
+        let must_implement_one_of_functions = &tcx.trait_def(t.def_id).must_implement_one_of;
 
         // Output the trait definition
         wrap_item(w, |mut w| {
@@ -1088,7 +1095,7 @@ fn item_trait(cx: &Context<'_>, it: &clean::Item, t: &clean::Trait) -> impl fmt:
                             it,
                             &implementor_dups,
                             &collect_paths_for_type(
-                                implementor.inner_impl().for_.clone(),
+                                &implementor.inner_impl().for_,
                                 &cx.shared.cache,
                             ),
                         )
@@ -1236,7 +1243,7 @@ fn item_trait_alias(
                 attrs = render_attributes_in_pre(it, "", cx),
                 name = it.name.unwrap(),
                 generics = t.generics.print(cx),
-                bounds = bounds(&t.bounds, true, cx),
+                bounds = print_bounds(&t.bounds, true, cx),
                 where_clause =
                     print_where_clause(&t.generics, cx, 0, Ending::NoNewline).maybe_display(),
             )
@@ -1278,94 +1285,58 @@ fn item_type_alias(cx: &Context<'_>, it: &clean::Item, t: &clean::TypeAlias) ->
 
             match inner_type {
                 clean::TypeAliasInnerType::Enum { variants, is_non_exhaustive } => {
-                    let variants_iter = || variants.iter().filter(|i| !i.is_stripped());
                     let ty = cx.tcx().type_of(it.def_id().unwrap()).instantiate_identity();
                     let enum_def_id = ty.ty_adt_def().unwrap().did();
 
-                    wrap_item(w, |w| {
-                        let variants_len = variants.len();
-                        let variants_count = variants_iter().count();
-                        let has_stripped_entries = variants_len != variants_count;
-
-                        write!(
-                            w,
-                            "enum {}{}{}",
-                            it.name.unwrap(),
-                            t.generics.print(cx),
-                            render_enum_fields(
-                                cx,
-                                Some(&t.generics),
-                                variants,
-                                variants_count,
-                                has_stripped_entries,
-                                *is_non_exhaustive,
-                                enum_def_id,
-                            )
-                        )
-                    })?;
-                    write!(w, "{}", item_variants(cx, it, variants, enum_def_id))?;
+                    DisplayEnum {
+                        variants,
+                        generics: &t.generics,
+                        is_non_exhaustive: *is_non_exhaustive,
+                        def_id: enum_def_id,
+                    }
+                    .render_into(cx, it, true, w)?;
                 }
                 clean::TypeAliasInnerType::Union { fields } => {
-                    wrap_item(w, |w| {
-                        let fields_count = fields.iter().filter(|i| !i.is_stripped()).count();
-                        let has_stripped_fields = fields.len() != fields_count;
+                    let ty = cx.tcx().type_of(it.def_id().unwrap()).instantiate_identity();
+                    let union_def_id = ty.ty_adt_def().unwrap().did();
 
-                        write!(
-                            w,
-                            "union {}{}{}",
-                            it.name.unwrap(),
-                            t.generics.print(cx),
-                            render_struct_fields(
-                                Some(&t.generics),
-                                None,
-                                fields,
-                                "",
-                                true,
-                                has_stripped_fields,
-                                cx,
-                            ),
-                        )
-                    })?;
-                    write!(w, "{}", item_fields(cx, it, fields, None))?;
+                    ItemUnion {
+                        cx,
+                        it,
+                        fields,
+                        generics: &t.generics,
+                        is_type_alias: true,
+                        def_id: union_def_id,
+                    }
+                    .render_into(w)?;
                 }
                 clean::TypeAliasInnerType::Struct { ctor_kind, fields } => {
-                    wrap_item(w, |w| {
-                        let fields_count = fields.iter().filter(|i| !i.is_stripped()).count();
-                        let has_stripped_fields = fields.len() != fields_count;
+                    let ty = cx.tcx().type_of(it.def_id().unwrap()).instantiate_identity();
+                    let struct_def_id = ty.ty_adt_def().unwrap().did();
 
-                        write!(
-                            w,
-                            "struct {}{}{}",
-                            it.name.unwrap(),
-                            t.generics.print(cx),
-                            render_struct_fields(
-                                Some(&t.generics),
-                                *ctor_kind,
-                                fields,
-                                "",
-                                true,
-                                has_stripped_fields,
-                                cx,
-                            ),
-                        )
-                    })?;
-                    write!(w, "{}", item_fields(cx, it, fields, None))?;
+                    DisplayStruct {
+                        ctor_kind: *ctor_kind,
+                        generics: &t.generics,
+                        fields,
+                        def_id: struct_def_id,
+                    }
+                    .render_into(cx, it, true, w)?;
                 }
             }
+        } else {
+            let def_id = it.item_id.expect_def_id();
+            // Render any items associated directly to this alias, as otherwise they
+            // won't be visible anywhere in the docs. It would be nice to also show
+            // associated items from the aliased type (see discussion in #32077), but
+            // we need #14072 to make sense of the generics.
+            write!(
+                w,
+                "{}{}",
+                render_assoc_items(cx, it, def_id, AssocItemRender::All),
+                document_type_layout(cx, def_id)
+            )?;
         }
 
-        let def_id = it.item_id.expect_def_id();
-        // Render any items associated directly to this alias, as otherwise they
-        // won't be visible anywhere in the docs. It would be nice to also show
-        // associated items from the aliased type (see discussion in #32077), but
-        // we need #14072 to make sense of the generics.
-        write!(
-            w,
-            "{}{}",
-            render_assoc_items(cx, it, def_id, AssocItemRender::All),
-            document_type_layout(cx, def_id)
-        )?;
-
         // [RUSTDOCIMPL] type.impl
         //
         // Include type definitions from the alias target type.
@@ -1463,50 +1434,83 @@ fn item_type_alias(cx: &Context<'_>, it: &clean::Item, t: &clean::TypeAlias) ->
     })
 }
 
-fn item_union(cx: &Context<'_>, it: &clean::Item, s: &clean::Union) -> impl fmt::Display {
-    item_template!(
-        #[template(path = "item_union.html")]
-        struct ItemUnion<'a, 'cx> {
-            cx: &'a Context<'cx>,
-            it: &'a clean::Item,
-            s: &'a clean::Union,
-        },
-        methods = [document, document_type_layout, render_attributes_in_pre, render_assoc_items]
-    );
+item_template!(
+    #[template(path = "item_union.html")]
+    struct ItemUnion<'a, 'cx> {
+        cx: &'a Context<'cx>,
+        it: &'a clean::Item,
+        fields: &'a [clean::Item],
+        generics: &'a clean::Generics,
+        is_type_alias: bool,
+        def_id: DefId,
+    },
+    methods = [document, document_type_layout, render_assoc_items]
+);
+
+impl<'a, 'cx: 'a> ItemUnion<'a, 'cx> {
+    fn render_union(&self) -> impl Display {
+        render_union(self.it, Some(&self.generics), &self.fields, self.cx)
+    }
 
-    impl<'a, 'cx: 'a> ItemUnion<'a, 'cx> {
-        fn render_union(&self) -> impl Display {
-            render_union(self.it, Some(&self.s.generics), &self.s.fields, self.cx)
-        }
+    fn document_field(&self, field: &'a clean::Item) -> impl Display {
+        document(self.cx, field, Some(self.it), HeadingOffset::H3)
+    }
 
-        fn document_field(&self, field: &'a clean::Item) -> impl Display {
-            document(self.cx, field, Some(self.it), HeadingOffset::H3)
-        }
+    fn stability_field(&self, field: &clean::Item) -> Option<String> {
+        field.stability_class(self.cx.tcx())
+    }
 
-        fn stability_field(&self, field: &clean::Item) -> Option<String> {
-            field.stability_class(self.cx.tcx())
-        }
+    fn print_ty(&self, ty: &'a clean::Type) -> impl Display {
+        ty.print(self.cx)
+    }
 
-        fn print_ty(&self, ty: &'a clean::Type) -> impl Display {
-            ty.print(self.cx)
-        }
+    // FIXME (GuillaumeGomez): When <https://github.com/askama-rs/askama/issues/452> is implemented,
+    // we can replace the returned value with:
+    //
+    // `iter::Peekable<impl Iterator<Item = (&'a clean::Item, &'a clean::Type)>>`
+    //
+    // And update `item_union.html`.
+    fn fields_iter(&self) -> impl Iterator<Item = (&'a clean::Item, &'a clean::Type)> {
+        self.fields.iter().filter_map(|f| match f.kind {
+            clean::StructFieldItem(ref ty) => Some((f, ty)),
+            _ => None,
+        })
+    }
 
-        fn fields_iter(
-            &self,
-        ) -> iter::Peekable<impl Iterator<Item = (&'a clean::Item, &'a clean::Type)>> {
-            self.s
-                .fields
-                .iter()
-                .filter_map(|f| match f.kind {
-                    clean::StructFieldItem(ref ty) => Some((f, ty)),
-                    _ => None,
-                })
-                .peekable()
-        }
+    fn render_attributes_in_pre(&self) -> impl fmt::Display {
+        fmt::from_fn(move |f| {
+            if self.is_type_alias {
+                // For now the only attributes we render for type aliases are `repr` attributes.
+                if let Some(repr) = clean::repr_attributes(
+                    self.cx.tcx(),
+                    self.cx.cache(),
+                    self.def_id,
+                    ItemType::Union,
+                    false,
+                ) {
+                    writeln!(f, "{repr}")?;
+                };
+            } else {
+                for a in self.it.attributes_and_repr(self.cx.tcx(), self.cx.cache(), false) {
+                    writeln!(f, "{a}")?;
+                }
+            }
+            Ok(())
+        })
     }
+}
 
+fn item_union(cx: &Context<'_>, it: &clean::Item, s: &clean::Union) -> impl fmt::Display {
     fmt::from_fn(|w| {
-        ItemUnion { cx, it, s }.render_into(w).unwrap();
+        ItemUnion {
+            cx,
+            it,
+            fields: &s.fields,
+            generics: &s.generics,
+            is_type_alias: false,
+            def_id: it.def_id().unwrap(),
+        }
+        .render_into(w)?;
         Ok(())
     })
 }
@@ -1533,41 +1537,81 @@ fn print_tuple_struct_fields(cx: &Context<'_>, s: &[clean::Item]) -> impl Displa
     })
 }
 
-fn item_enum(cx: &Context<'_>, it: &clean::Item, e: &clean::Enum) -> impl fmt::Display {
-    fmt::from_fn(|w| {
-        let count_variants = e.variants().count();
+struct DisplayEnum<'clean> {
+    variants: &'clean IndexVec<VariantIdx, clean::Item>,
+    generics: &'clean clean::Generics,
+    is_non_exhaustive: bool,
+    def_id: DefId,
+}
+
+impl<'clean> DisplayEnum<'clean> {
+    fn render_into<W: fmt::Write>(
+        self,
+        cx: &Context<'_>,
+        it: &clean::Item,
+        is_type_alias: bool,
+        w: &mut W,
+    ) -> fmt::Result {
+        let non_stripped_variant_count = self.variants.iter().filter(|i| !i.is_stripped()).count();
+        let variants_len = self.variants.len();
+        let has_stripped_entries = variants_len != non_stripped_variant_count;
+
         wrap_item(w, |w| {
-            render_attributes_in_code(w, it, cx);
+            if is_type_alias {
+                // For now the only attributes we render for type aliases are `repr` attributes.
+                render_repr_attributes_in_code(w, cx, self.def_id, ItemType::Enum);
+            } else {
+                render_attributes_in_code(w, it, cx);
+            }
             write!(
                 w,
                 "{}enum {}{}{}",
                 visibility_print_with_space(it, cx),
                 it.name.unwrap(),
-                e.generics.print(cx),
+                self.generics.print(cx),
                 render_enum_fields(
                     cx,
-                    Some(&e.generics),
-                    &e.variants,
-                    count_variants,
-                    e.has_stripped_entries(),
-                    it.is_non_exhaustive(),
-                    it.def_id().unwrap(),
+                    Some(self.generics),
+                    self.variants,
+                    non_stripped_variant_count,
+                    has_stripped_entries,
+                    self.is_non_exhaustive,
+                    self.def_id,
                 ),
             )
         })?;
 
-        write!(w, "{}", document(cx, it, None, HeadingOffset::H2))?;
+        let def_id = it.item_id.expect_def_id();
+        let layout_def_id = if is_type_alias {
+            self.def_id
+        } else {
+            write!(w, "{}", document(cx, it, None, HeadingOffset::H2))?;
+            // We don't return the same `DefId` since the layout size of the type alias might be
+            // different since we might have more information on the generics.
+            def_id
+        };
 
-        if count_variants != 0 {
-            write!(w, "{}", item_variants(cx, it, &e.variants, it.def_id().unwrap()))?;
+        if non_stripped_variant_count != 0 {
+            write!(w, "{}", item_variants(cx, it, self.variants, self.def_id))?;
         }
-        let def_id = it.item_id.expect_def_id();
         write!(
             w,
             "{}{}",
             render_assoc_items(cx, it, def_id, AssocItemRender::All),
-            document_type_layout(cx, def_id)
+            document_type_layout(cx, layout_def_id)
         )
+    }
+}
+
+fn item_enum(cx: &Context<'_>, it: &clean::Item, e: &clean::Enum) -> impl fmt::Display {
+    fmt::from_fn(|w| {
+        DisplayEnum {
+            variants: &e.variants,
+            generics: &e.generics,
+            is_non_exhaustive: it.is_non_exhaustive(),
+            def_id: it.def_id().unwrap(),
+        }
+        .render_into(cx, it, false, w)
     })
 }
 
@@ -1955,27 +1999,59 @@ fn item_constant(
     })
 }
 
-fn item_struct(cx: &Context<'_>, it: &clean::Item, s: &clean::Struct) -> impl fmt::Display {
-    fmt::from_fn(|w| {
+struct DisplayStruct<'a> {
+    ctor_kind: Option<CtorKind>,
+    generics: &'a clean::Generics,
+    fields: &'a [clean::Item],
+    def_id: DefId,
+}
+
+impl<'a> DisplayStruct<'a> {
+    fn render_into<W: fmt::Write>(
+        self,
+        cx: &Context<'_>,
+        it: &clean::Item,
+        is_type_alias: bool,
+        w: &mut W,
+    ) -> fmt::Result {
         wrap_item(w, |w| {
-            render_attributes_in_code(w, it, cx);
+            if is_type_alias {
+                // For now the only attributes we render for type aliases are `repr` attributes.
+                render_repr_attributes_in_code(w, cx, self.def_id, ItemType::Struct);
+            } else {
+                render_attributes_in_code(w, it, cx);
+            }
             write!(
                 w,
                 "{}",
-                render_struct(it, Some(&s.generics), s.ctor_kind, &s.fields, "", true, cx)
+                render_struct(it, Some(self.generics), self.ctor_kind, self.fields, "", true, cx)
             )
         })?;
 
-        let def_id = it.item_id.expect_def_id();
+        if !is_type_alias {
+            write!(w, "{}", document(cx, it, None, HeadingOffset::H2))?;
+        }
 
+        let def_id = it.item_id.expect_def_id();
         write!(
             w,
-            "{}{}{}{}",
-            document(cx, it, None, HeadingOffset::H2),
-            item_fields(cx, it, &s.fields, s.ctor_kind),
+            "{}{}{}",
+            item_fields(cx, it, self.fields, self.ctor_kind),
             render_assoc_items(cx, it, def_id, AssocItemRender::All),
             document_type_layout(cx, def_id),
         )
+    }
+}
+
+fn item_struct(cx: &Context<'_>, it: &clean::Item, s: &clean::Struct) -> impl fmt::Display {
+    fmt::from_fn(|w| {
+        DisplayStruct {
+            ctor_kind: s.ctor_kind,
+            generics: &s.generics,
+            fields: s.fields.as_slice(),
+            def_id: it.def_id().unwrap(),
+        }
+        .render_into(cx, it, false, w)
     })
 }
 
@@ -2185,14 +2261,18 @@ pub(super) fn full_path(cx: &Context<'_>, item: &clean::Item) -> String {
     s
 }
 
-pub(super) fn item_path(ty: ItemType, name: &str) -> impl Display {
+pub(super) fn print_item_path(ty: ItemType, name: &str) -> impl Display {
     fmt::from_fn(move |f| match ty {
         ItemType::Module => write!(f, "{}index.html", ensure_trailing_slash(name)),
         _ => write!(f, "{ty}.{name}.html"),
     })
 }
 
-fn bounds(bounds: &[clean::GenericBound], trait_alias: bool, cx: &Context<'_>) -> impl Display {
+fn print_bounds(
+    bounds: &[clean::GenericBound],
+    trait_alias: bool,
+    cx: &Context<'_>,
+) -> impl Display {
     (!bounds.is_empty())
         .then_some(fmt::from_fn(move |f| {
             let has_lots_of_bounds = bounds.len() > 2;
diff --git a/src/librustdoc/html/render/sidebar.rs b/src/librustdoc/html/render/sidebar.rs
index 361966325fb..91540e06e33 100644
--- a/src/librustdoc/html/render/sidebar.rs
+++ b/src/librustdoc/html/render/sidebar.rs
@@ -599,7 +599,7 @@ fn sidebar_enum<'a>(
     deref_id_map: &'a DefIdMap<String>,
 ) {
     let mut variants = e
-        .variants()
+        .non_stripped_variants()
         .filter_map(|v| v.name)
         .map(|name| Link::new(format!("variant.{name}"), name.to_string()))
         .collect::<Vec<_>>();
diff --git a/src/librustdoc/html/render/write_shared.rs b/src/librustdoc/html/render/write_shared.rs
index 4f6e9abdbca..33738f7a242 100644
--- a/src/librustdoc/html/render/write_shared.rs
+++ b/src/librustdoc/html/render/write_shared.rs
@@ -607,16 +607,9 @@ impl TypeAliasPart {
         let cx = type_impl_collector.cx;
         let aliased_types = type_impl_collector.aliased_types;
         for aliased_type in aliased_types.values() {
-            let impls = aliased_type
-                .impl_
-                .values()
-                .flat_map(|AliasedTypeImpl { impl_, type_aliases }| {
-                    let mut ret: Vec<AliasSerializableImpl> = Vec::new();
-                    let trait_ = impl_
-                        .inner_impl()
-                        .trait_
-                        .as_ref()
-                        .map(|trait_| format!("{:#}", trait_.print(cx)));
+            let impls = aliased_type.impl_.values().filter_map(
+                |AliasedTypeImpl { impl_, type_aliases }| {
+                    let mut ret: Option<AliasSerializableImpl> = None;
                     // render_impl will filter out "impossible-to-call" methods
                     // to make that functionality work here, it needs to be called with
                     // each type alias, and if it gives a different result, split the impl
@@ -624,8 +617,8 @@ impl TypeAliasPart {
                         cx.id_map.borrow_mut().clear();
                         cx.deref_id_map.borrow_mut().clear();
                         let type_alias_fqp = (*type_alias_fqp).iter().join("::");
-                        if let Some(last) = ret.last_mut() {
-                            last.aliases.push(type_alias_fqp);
+                        if let Some(ret) = &mut ret {
+                            ret.aliases.push(type_alias_fqp);
                         } else {
                             let target_did = impl_
                                 .inner_impl()
@@ -660,16 +653,22 @@ impl TypeAliasPart {
                                 },
                             )
                             .to_string();
-                            ret.push(AliasSerializableImpl {
+                            // The alternate display prints it as plaintext instead of HTML.
+                            let trait_ = impl_
+                                .inner_impl()
+                                .trait_
+                                .as_ref()
+                                .map(|trait_| format!("{:#}", trait_.print(cx)));
+                            ret = Some(AliasSerializableImpl {
                                 text,
-                                trait_: trait_.clone(),
+                                trait_,
                                 aliases: vec![type_alias_fqp],
                             })
                         }
                     }
                     ret
-                })
-                .collect::<Vec<_>>();
+                },
+            );
 
             let mut path = PathBuf::from("type.impl");
             for component in &aliased_type.target_fqp[..aliased_type.target_fqp.len() - 1] {
@@ -682,7 +681,7 @@ impl TypeAliasPart {
             ));
 
             let part = OrderedJson::array_sorted(
-                impls.iter().map(OrderedJson::serialize).collect::<Result<Vec<_>, _>>().unwrap(),
+                impls.map(|impl_| OrderedJson::serialize(impl_).unwrap()),
             );
             path_parts.push(path, OrderedJson::array_unsorted([crate_name_json, &part]));
         }
@@ -760,7 +759,7 @@ impl TraitAliasPart {
                         Some(Implementor {
                             text: imp.inner_impl().print(false, cx).to_string(),
                             synthetic: imp.inner_impl().kind.is_auto(),
-                            types: collect_paths_for_type(imp.inner_impl().for_.clone(), cache),
+                            types: collect_paths_for_type(&imp.inner_impl().for_, cache),
                         })
                     }
                 })
diff --git a/src/librustdoc/html/templates/item_union.html b/src/librustdoc/html/templates/item_union.html
index b1c1d5a63a0..b5d3367a6a1 100644
--- a/src/librustdoc/html/templates/item_union.html
+++ b/src/librustdoc/html/templates/item_union.html
@@ -2,15 +2,16 @@
     {{ self.render_attributes_in_pre()|safe }}
     {{ self.render_union()|safe }}
 </code></pre>
-{{ self.document()|safe }}
-{% if self.fields_iter().peek().is_some() %}
+{% if !self.is_type_alias %}
+    {{ self.document()|safe }}
+{% endif %}
+{% if self.fields_iter().next().is_some() %}
     <h2 id="fields" class="fields section-header"> {# #}
         Fields<a href="#fields" class="anchor">§</a> {# #}
     </h2>
     {% for (field, ty) in self.fields_iter() %}
         {% let name = field.name.expect("union field name") %}
-        <span id="structfield.{{ name }}" {#+ #}
-            class="{{ ItemType::StructField +}} section-header"> {# #}
+        <span id="structfield.{{ name }}" class="{{ ItemType::StructField +}} section-header"> {# #}
             <a href="#structfield.{{ name }}" class="anchor field">§</a> {# #}
             <code>{{ name }}: {{+ self.print_ty(ty)|safe }}</code> {# #}
         </span>
diff --git a/src/librustdoc/html/tests.rs b/src/librustdoc/html/tests.rs
index b568942bbcb..873462bbeba 100644
--- a/src/librustdoc/html/tests.rs
+++ b/src/librustdoc/html/tests.rs
@@ -1,51 +1,51 @@
-use rustc_span::{Symbol, sym};
+use rustc_span::{Symbol, create_default_session_globals_then, sym};
 
 use crate::html::format::href_relative_parts;
 
-fn assert_relative_path(expected: &[Symbol], relative_to_fqp: &[Symbol], fqp: &[Symbol]) {
-    // No `create_default_session_globals_then` call is needed here because all
-    // the symbols used are static, and no `Symbol::intern` calls occur.
-    assert_eq!(expected, href_relative_parts(&fqp, &relative_to_fqp).collect::<Vec<_>>());
+fn assert_relative_path(expected: &str, relative_to_fqp: &[Symbol], fqp: &[Symbol]) {
+    create_default_session_globals_then(|| {
+        assert_eq!(expected, href_relative_parts(&fqp, &relative_to_fqp).finish());
+    });
 }
 
 #[test]
 fn href_relative_parts_basic() {
     let relative_to_fqp = &[sym::std, sym::vec];
     let fqp = &[sym::std, sym::iter];
-    assert_relative_path(&[sym::dotdot, sym::iter], relative_to_fqp, fqp);
+    assert_relative_path("../iter", relative_to_fqp, fqp);
 }
 
 #[test]
 fn href_relative_parts_parent_module() {
     let relative_to_fqp = &[sym::std, sym::vec];
     let fqp = &[sym::std];
-    assert_relative_path(&[sym::dotdot], relative_to_fqp, fqp);
+    assert_relative_path("..", relative_to_fqp, fqp);
 }
 
 #[test]
 fn href_relative_parts_different_crate() {
     let relative_to_fqp = &[sym::std, sym::vec];
     let fqp = &[sym::core, sym::iter];
-    assert_relative_path(&[sym::dotdot, sym::dotdot, sym::core, sym::iter], relative_to_fqp, fqp);
+    assert_relative_path("../../core/iter", relative_to_fqp, fqp);
 }
 
 #[test]
 fn href_relative_parts_same_module() {
     let relative_to_fqp = &[sym::std, sym::vec];
     let fqp = &[sym::std, sym::vec];
-    assert_relative_path(&[], relative_to_fqp, fqp);
+    assert_relative_path("", relative_to_fqp, fqp);
 }
 
 #[test]
 fn href_relative_parts_child_module() {
     let relative_to_fqp = &[sym::std];
     let fqp = &[sym::std, sym::vec];
-    assert_relative_path(&[sym::vec], relative_to_fqp, fqp);
+    assert_relative_path("vec", relative_to_fqp, fqp);
 }
 
 #[test]
 fn href_relative_parts_root() {
     let relative_to_fqp = &[];
     let fqp = &[sym::std];
-    assert_relative_path(&[sym::std], relative_to_fqp, fqp);
+    assert_relative_path("std", relative_to_fqp, fqp);
 }
diff --git a/src/librustdoc/html/url_parts_builder.rs b/src/librustdoc/html/url_parts_builder.rs
index 1e6af6af63c..9a533827441 100644
--- a/src/librustdoc/html/url_parts_builder.rs
+++ b/src/librustdoc/html/url_parts_builder.rs
@@ -14,7 +14,6 @@ pub(crate) struct UrlPartsBuilder {
 
 impl UrlPartsBuilder {
     /// Create an empty buffer.
-    #[allow(dead_code)]
     pub(crate) fn new() -> Self {
         Self { buf: String::new() }
     }
diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs
index 705f9b2202c..bfcb794b89a 100644
--- a/src/librustdoc/json/conversions.rs
+++ b/src/librustdoc/json/conversions.rs
@@ -40,7 +40,7 @@ impl JsonRenderer<'_> {
             })
             .collect();
         let docs = item.opt_doc_value();
-        let attrs = item.attributes(self.tcx, self.cache(), true);
+        let attrs = item.attributes_and_repr(self.tcx, self.cache(), true);
         let span = item.span(self.tcx);
         let visibility = item.visibility(self.tcx);
         let clean::ItemInner { name, item_id, .. } = *item.inner;
diff --git a/src/librustdoc/passes/calculate_doc_coverage.rs b/src/librustdoc/passes/calculate_doc_coverage.rs
index c9f0baaaa4c..66d8b667a4c 100644
--- a/src/librustdoc/passes/calculate_doc_coverage.rs
+++ b/src/librustdoc/passes/calculate_doc_coverage.rs
@@ -241,7 +241,7 @@ impl DocVisitor<'_> for CoverageCalculator<'_, '_> {
                                 data: hir::VariantData::Tuple(_, _, _),
                                 ..
                             }) | hir::Node::Item(hir::Item {
-                                kind: hir::ItemKind::Struct(_, hir::VariantData::Tuple(_, _, _), _),
+                                kind: hir::ItemKind::Struct(_, _, hir::VariantData::Tuple(_, _, _)),
                                 ..
                             })
                         )
diff --git a/src/librustdoc/passes/check_doc_cfg.rs b/src/librustdoc/passes/check_doc_cfg.rs
new file mode 100644
index 00000000000..3284da77a02
--- /dev/null
+++ b/src/librustdoc/passes/check_doc_cfg.rs
@@ -0,0 +1,76 @@
+use rustc_hir::HirId;
+use rustc_hir::def_id::LocalDefId;
+use rustc_middle::ty::TyCtxt;
+use rustc_span::sym;
+
+use super::Pass;
+use crate::clean::{Attributes, Crate, Item};
+use crate::core::DocContext;
+use crate::visit::DocVisitor;
+
+pub(crate) const CHECK_DOC_CFG: Pass = Pass {
+    name: "check-doc-cfg",
+    run: Some(check_doc_cfg),
+    description: "checks `#[doc(cfg(...))]` for stability feature and unexpected cfgs",
+};
+
+pub(crate) fn check_doc_cfg(krate: Crate, cx: &mut DocContext<'_>) -> Crate {
+    let mut checker = DocCfgChecker { cx };
+    checker.visit_crate(&krate);
+    krate
+}
+
+struct RustdocCfgMatchesLintEmitter<'a>(TyCtxt<'a>, HirId);
+
+impl<'a> rustc_attr_parsing::CfgMatchesLintEmitter for RustdocCfgMatchesLintEmitter<'a> {
+    fn emit_span_lint(
+        &self,
+        sess: &rustc_session::Session,
+        lint: &'static rustc_lint::Lint,
+        sp: rustc_span::Span,
+        builtin_diag: rustc_lint_defs::BuiltinLintDiag,
+    ) {
+        self.0.node_span_lint(lint, self.1, sp, |diag| {
+            rustc_lint::decorate_builtin_lint(sess, Some(self.0), builtin_diag, diag)
+        });
+    }
+}
+
+struct DocCfgChecker<'a, 'tcx> {
+    cx: &'a mut DocContext<'tcx>,
+}
+
+impl DocCfgChecker<'_, '_> {
+    fn check_attrs(&mut self, attrs: &Attributes, did: LocalDefId) {
+        let doc_cfgs = attrs
+            .other_attrs
+            .iter()
+            .filter(|attr| attr.has_name(sym::doc))
+            .flat_map(|attr| attr.meta_item_list().unwrap_or_default())
+            .filter(|attr| attr.has_name(sym::cfg));
+
+        for doc_cfg in doc_cfgs {
+            if let Some([cfg_mi]) = doc_cfg.meta_item_list() {
+                let _ = rustc_attr_parsing::cfg_matches(
+                    cfg_mi,
+                    &self.cx.tcx.sess,
+                    RustdocCfgMatchesLintEmitter(
+                        self.cx.tcx,
+                        self.cx.tcx.local_def_id_to_hir_id(did),
+                    ),
+                    Some(self.cx.tcx.features()),
+                );
+            }
+        }
+    }
+}
+
+impl DocVisitor<'_> for DocCfgChecker<'_, '_> {
+    fn visit_item(&mut self, item: &'_ Item) {
+        if let Some(Some(local_did)) = item.def_id().map(|did| did.as_local()) {
+            self.check_attrs(&item.attrs, local_did);
+        }
+
+        self.visit_item_recur(item);
+    }
+}
diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs
index 37628f16600..1daaba3b86c 100644
--- a/src/librustdoc/passes/collect_intra_doc_links.rs
+++ b/src/librustdoc/passes/collect_intra_doc_links.rs
@@ -22,6 +22,7 @@ use rustc_resolve::rustdoc::{
     MalformedGenerics, has_primitive_or_keyword_docs, prepare_to_doc_link_resolution,
     source_span_for_markdown_range, strip_generics_from_path,
 };
+use rustc_session::config::CrateType;
 use rustc_session::lint::Lint;
 use rustc_span::BytePos;
 use rustc_span::hygiene::MacroKind;
@@ -1169,7 +1170,6 @@ impl LinkCollector<'_, '_> {
     #[allow(rustc::potential_query_instability)]
     pub(crate) fn resolve_ambiguities(&mut self) {
         let mut ambiguous_links = mem::take(&mut self.ambiguous_links);
-
         for ((item_id, path_str), info_items) in ambiguous_links.iter_mut() {
             for info in info_items {
                 info.resolved.retain(|(res, _)| match res {
@@ -2227,15 +2227,35 @@ fn ambiguity_error(
     emit_error: bool,
 ) -> bool {
     let mut descrs = FxHashSet::default();
-    let kinds = candidates
+    // 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 mut kinds = candidates
         .iter()
-        .map(
-            |(res, def_id)| {
-                if let Some(def_id) = def_id { Res::from_def_id(cx.tcx, *def_id) } else { *res }
-            },
-        )
-        .filter(|res| descrs.insert(res.descr()))
+        .map(|(res, def_id)| {
+            let r =
+                if let Some(def_id) = def_id { Res::from_def_id(cx.tcx, *def_id) } else { *res };
+            if is_proc_macro_crate && let Res::Def(DefKind::Macro(_), id) = r {
+                possible_proc_macro_id = Some(id);
+            }
+            r
+        })
         .collect::<Vec<_>>();
+    // In order to properly dedup proc macros, we have to do it in two passes:
+    // 1. Completing the full traversal to find the possible duplicate in the macro namespace,
+    // 2. Another full traversal to eliminate the candidate in the fn namespace.
+    //
+    // Thus, we have to do an iteration after collection is finished.
+    //
+    // As an optimization, we only deduplicate if we're in a proc-macro crate,
+    // and only if we already found something that looks like a proc macro.
+    if is_proc_macro_crate && let Some(macro_id) = possible_proc_macro_id {
+        kinds.retain(|res| !matches!(res, Res::Def(DefKind::Fn, fn_id) if macro_id == *fn_id));
+    }
+
+    kinds.retain(|res| descrs.insert(res.descr()));
+
     if descrs.len() == 1 {
         // There is no way for users to disambiguate at this point, so better return the first
         // candidate and not show a warning.
diff --git a/src/librustdoc/passes/mod.rs b/src/librustdoc/passes/mod.rs
index 9ba63d34144..475d05b7d0e 100644
--- a/src/librustdoc/passes/mod.rs
+++ b/src/librustdoc/passes/mod.rs
@@ -32,6 +32,9 @@ pub(crate) use self::collect_intra_doc_links::COLLECT_INTRA_DOC_LINKS;
 mod check_doc_test_visibility;
 pub(crate) use self::check_doc_test_visibility::CHECK_DOC_TEST_VISIBILITY;
 
+mod check_doc_cfg;
+pub(crate) use self::check_doc_cfg::CHECK_DOC_CFG;
+
 mod collect_trait_impls;
 pub(crate) use self::collect_trait_impls::COLLECT_TRAIT_IMPLS;
 
@@ -72,6 +75,7 @@ pub(crate) enum Condition {
 
 /// The full list of passes.
 pub(crate) const PASSES: &[Pass] = &[
+    CHECK_DOC_CFG,
     CHECK_DOC_TEST_VISIBILITY,
     STRIP_ALIASED_NON_LOCAL,
     STRIP_HIDDEN,
@@ -89,6 +93,7 @@ pub(crate) const PASSES: &[Pass] = &[
 pub(crate) const DEFAULT_PASSES: &[ConditionalPass] = &[
     ConditionalPass::always(COLLECT_TRAIT_IMPLS),
     ConditionalPass::always(CHECK_DOC_TEST_VISIBILITY),
+    ConditionalPass::always(CHECK_DOC_CFG),
     ConditionalPass::always(STRIP_ALIASED_NON_LOCAL),
     ConditionalPass::new(STRIP_HIDDEN, WhenNotDocumentHidden),
     ConditionalPass::new(STRIP_PRIVATE, WhenNotDocumentPrivate),
diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs
index 254549e72c6..5b52e785b8f 100644
--- a/src/librustdoc/visit_ast.rs
+++ b/src/librustdoc/visit_ast.rs
@@ -440,7 +440,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
             hir::ItemKind::GlobalAsm { .. } => {}
             hir::ItemKind::Use(_, hir::UseKind::ListStem) => {}
             hir::ItemKind::Use(path, kind) => {
-                for &res in &path.res {
+                for res in path.res.present_items() {
                     // Struct and variant constructors and proc macro stubs always show up alongside
                     // their definitions, we've already processed them so just discard these.
                     if should_ignore_res(res) {
diff --git a/src/rustdoc-json-types/lib.rs b/src/rustdoc-json-types/lib.rs
index c091c955ed5..f1c375bd2fe 100644
--- a/src/rustdoc-json-types/lib.rs
+++ b/src/rustdoc-json-types/lib.rs
@@ -388,7 +388,7 @@ pub enum AssocItemConstraintKind {
 /// Rustdoc makes no guarantees about the inner value of Id's. Applications
 /// should treat them as opaque keys to lookup items, and avoid attempting
 /// to parse them, or otherwise depend on any implementation details.
-#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
+#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
 // FIXME(aDotInTheVoid): Consider making this non-public in rustdoc-types.
 pub struct Id(pub u32);
 
diff --git a/src/stage0 b/src/stage0
index 8ca6860490c..4cff7bafa5d 100644
--- a/src/stage0
+++ b/src/stage0
@@ -13,466 +13,466 @@ nightly_branch=master
 # All changes below this comment will be overridden the next time the
 # tool is executed.
 
-compiler_date=2025-05-12
+compiler_date=2025-05-26
 compiler_version=beta
-rustfmt_date=2025-05-12
+rustfmt_date=2025-05-27
 rustfmt_version=nightly
 
-dist/2025-05-12/rustc-beta-aarch64-apple-darwin.tar.gz=e5ec8453efc1f51d37d5031d87d45a327647614b00993d1b7f477c7d2e6c7b16
-dist/2025-05-12/rustc-beta-aarch64-apple-darwin.tar.xz=6711902d59079cd57d6f93e951d3028acb5cef0f59a2ab87e1688edee96f6471
-dist/2025-05-12/rustc-beta-aarch64-pc-windows-msvc.tar.gz=7168682081144b8eacab42efe6c9ddb9ee6964712d271988345e63d2d6faac9c
-dist/2025-05-12/rustc-beta-aarch64-pc-windows-msvc.tar.xz=5794e0d6bed097d349e138c7602a083f4025604f711328c0a4548e27f191444b
-dist/2025-05-12/rustc-beta-aarch64-unknown-linux-gnu.tar.gz=c4d31776d1b74dcc6184c2ed6064667b1ade59c68fb355bee812a805f61234f9
-dist/2025-05-12/rustc-beta-aarch64-unknown-linux-gnu.tar.xz=970b0c910f8ba2b5b470ffa7959466526b0f99211578f7d8ceca8d0aaa23fe1d
-dist/2025-05-12/rustc-beta-aarch64-unknown-linux-musl.tar.gz=8e9c80f826b4571136f082d3cadbb4668167f19688a3da91fc732464b5a604b5
-dist/2025-05-12/rustc-beta-aarch64-unknown-linux-musl.tar.xz=09731185aeb15263cfed5786ccc78fee0db70f82aeb5409f8bd8b03b0566d491
-dist/2025-05-12/rustc-beta-arm-unknown-linux-gnueabi.tar.gz=4ae8dec81d8f2d1aff7710a357e3c56323cae56bacd6b014fdb4058c06bb75f0
-dist/2025-05-12/rustc-beta-arm-unknown-linux-gnueabi.tar.xz=4767de7ea81913c6ed33907d93dfb56664d9bce0d095f33f0ca5662b284a94d7
-dist/2025-05-12/rustc-beta-arm-unknown-linux-gnueabihf.tar.gz=d2233f4e687bb1bd407593f6d7a8c288581b7209d758be49f0681e1f556083e4
-dist/2025-05-12/rustc-beta-arm-unknown-linux-gnueabihf.tar.xz=a8f9778a765d9fa8a0651b7d6fac8fdebcbaa61e903a32e7cbcd88bcd9418bd3
-dist/2025-05-12/rustc-beta-armv7-unknown-linux-gnueabihf.tar.gz=bd2ee7918df85f24a34911b91a233663b4cf706e7c54784c78fea8e58c12ca91
-dist/2025-05-12/rustc-beta-armv7-unknown-linux-gnueabihf.tar.xz=9b1a1c4eb35d3c1ec97132e33fc6551ffb280d6b2c9d049bf0392441674d338c
-dist/2025-05-12/rustc-beta-i686-pc-windows-gnu.tar.gz=729e4d7a116d8ee2a42489484429b138bafc14b43c87adfedaad442515e61c15
-dist/2025-05-12/rustc-beta-i686-pc-windows-gnu.tar.xz=8272b95f1d99dff28f22161d0181ac0e64e1909d51448f9ba4bcbe09690e79a9
-dist/2025-05-12/rustc-beta-i686-pc-windows-msvc.tar.gz=13a7327d08d26ba1911071c798d520b74422e320f5cc1c41d4e215a5615e692e
-dist/2025-05-12/rustc-beta-i686-pc-windows-msvc.tar.xz=0f9ce8fb06bb1ae460ee82601c269b885c109729df342e5b6b05b9dd9b51560a
-dist/2025-05-12/rustc-beta-i686-unknown-linux-gnu.tar.gz=82b54be8042baa56e1e6c0346f2044a84c4a50b3df6fe813d45eab21e1fe8935
-dist/2025-05-12/rustc-beta-i686-unknown-linux-gnu.tar.xz=48c9a8181b6ac7b7b6fb4535391c0498965127f5b5ac694de7eb1dba7ed8e9d5
-dist/2025-05-12/rustc-beta-loongarch64-unknown-linux-gnu.tar.gz=768156149054211735ec45d0091a8e7dfac16a39c44e122af5b28b316a45fd00
-dist/2025-05-12/rustc-beta-loongarch64-unknown-linux-gnu.tar.xz=50a38f72a253bfb8005a9cdd49621289f8b4a2373247957f520f5c5d1f12db29
-dist/2025-05-12/rustc-beta-loongarch64-unknown-linux-musl.tar.gz=f79bb58d8e2c80270a4c9d7076ce8645b2ea3f64db5077b085cb4cc6763f5e17
-dist/2025-05-12/rustc-beta-loongarch64-unknown-linux-musl.tar.xz=eafeaea2813e34ef0606a9f935fe1a104417604686ef9144b899fe97de53aa67
-dist/2025-05-12/rustc-beta-powerpc-unknown-linux-gnu.tar.gz=f557e00500071835712afdc9d91161a95b1cca5cc4e32abebcf5d35a9147eb2b
-dist/2025-05-12/rustc-beta-powerpc-unknown-linux-gnu.tar.xz=72fc4d26e06d74349e65415da211429ec92cd479aae78f82e223f3f760b0e63a
-dist/2025-05-12/rustc-beta-powerpc64-unknown-linux-gnu.tar.gz=a67b7e5e0b30227b07a41829c5e88180d9c404c2ce37fcb10d8df702c2b3c222
-dist/2025-05-12/rustc-beta-powerpc64-unknown-linux-gnu.tar.xz=0c4cfeb6555283e58b75533930783e7cc3c838f9c8eb34938fa60656b15568a1
-dist/2025-05-12/rustc-beta-powerpc64le-unknown-linux-gnu.tar.gz=7e6f02eede8d87cd5bbcd8dcf8235ebabd1237fb294cf1d0dcfaf961f3628d95
-dist/2025-05-12/rustc-beta-powerpc64le-unknown-linux-gnu.tar.xz=a5e9612d42f999a7b0fe22b2d5d5def21162aeb604c4625fc70259c5ec2b669e
-dist/2025-05-12/rustc-beta-powerpc64le-unknown-linux-musl.tar.gz=8fc92b9e35110a53458e08b49db1809a23060f8d05e742561cd746fd206085f2
-dist/2025-05-12/rustc-beta-powerpc64le-unknown-linux-musl.tar.xz=8b3fc4ac4423bc71b7402554436d1e6e62ff06b36c69f7be724e8ec5ebf96352
-dist/2025-05-12/rustc-beta-riscv64gc-unknown-linux-gnu.tar.gz=d0777e5ea794a9d19a2a1744acff649a1bac8fc616f6df41410553ac0b3c275d
-dist/2025-05-12/rustc-beta-riscv64gc-unknown-linux-gnu.tar.xz=849039740272c91141862a028f45889d4874ddc83842a66b906df37b7a30f9de
-dist/2025-05-12/rustc-beta-s390x-unknown-linux-gnu.tar.gz=3230ab1516a19cf803952138ef7f815ce321d7123539539249b76f6afadcf9ed
-dist/2025-05-12/rustc-beta-s390x-unknown-linux-gnu.tar.xz=12c8e476a73d71d58d5438ce94bb2fa822a8d043015b0961af14096d68c52daf
-dist/2025-05-12/rustc-beta-x86_64-apple-darwin.tar.gz=01717cd3b5141d29896caeab17ad61a27b8b7af6460745f245d67dd066a09924
-dist/2025-05-12/rustc-beta-x86_64-apple-darwin.tar.xz=fceb7e0f431f84621a22ae50ec9694cd0ecdf90801f953295b1975b0aedb4fff
-dist/2025-05-12/rustc-beta-x86_64-pc-windows-gnu.tar.gz=1f7abd7650cab64cd09848ac8de9b7e0047f6c77eb433140fbae8ae8b522c019
-dist/2025-05-12/rustc-beta-x86_64-pc-windows-gnu.tar.xz=4e3e07967e44907cb2b2ccb733b969014ee6efedb82412dc81f95533d2d473be
-dist/2025-05-12/rustc-beta-x86_64-pc-windows-msvc.tar.gz=3cc10eb4187e09a48efa5351250e09c83edda4296d605dcb886eb81f9d6580af
-dist/2025-05-12/rustc-beta-x86_64-pc-windows-msvc.tar.xz=9ce5c89a9b2e7360c7991c3f976bbbe9bf9685854d1019aa6dc1cc5b9d13eb88
-dist/2025-05-12/rustc-beta-x86_64-unknown-freebsd.tar.gz=3a9e92319e91c0498a3e54ff5ae00f4e1ecfac9b0d4f291885c9feef89d356df
-dist/2025-05-12/rustc-beta-x86_64-unknown-freebsd.tar.xz=6930ccd83b6b63d0a876eb5ac52c32a8449fd4cea8666b919494ce6358c6122c
-dist/2025-05-12/rustc-beta-x86_64-unknown-illumos.tar.gz=c1a4ad2cfa4b7c3181ea0facc3b18baea7f4138d089825915eb41630e5bac500
-dist/2025-05-12/rustc-beta-x86_64-unknown-illumos.tar.xz=44ae303a09cbc8a198c0cd947f958229b0e605842666a3b0aadb0f1f69f34ffc
-dist/2025-05-12/rustc-beta-x86_64-unknown-linux-gnu.tar.gz=fc55fe3f5b2d206417452de880a177f59004762e58fbfa4404f0b59fdd7075dd
-dist/2025-05-12/rustc-beta-x86_64-unknown-linux-gnu.tar.xz=a5ce304c4798bbacc998b2350d6ef79e9845a7ffb28bdf0af6066869667a0c86
-dist/2025-05-12/rustc-beta-x86_64-unknown-linux-musl.tar.gz=391cb81e61589377ab0a6780289628a805a5b1d842adc29e66ee5731f36372af
-dist/2025-05-12/rustc-beta-x86_64-unknown-linux-musl.tar.xz=7c3ac5df14b28b99e3e2d0072b5aacc59acc08621731fdebaa3199059ccbeb76
-dist/2025-05-12/rustc-beta-x86_64-unknown-netbsd.tar.gz=670beaf2ec21118fb099a1b034b33665e360b8f1920b9cbd5fb58271a8aab9ca
-dist/2025-05-12/rustc-beta-x86_64-unknown-netbsd.tar.xz=e4982c3e4b9f757485ff9aee183d973e31b2c485dbb39387c1afe4bee0fdbc30
-dist/2025-05-12/rust-std-beta-aarch64-apple-darwin.tar.gz=c2786d9e874eecea00935c62c58e2e3ddfbe11b4c99f9ce807e2251640c8f7f8
-dist/2025-05-12/rust-std-beta-aarch64-apple-darwin.tar.xz=0f2a6b28befa7d44055f32683d7b9c4de19ffd39c02fe6ce44aeffbdd1d13ea8
-dist/2025-05-12/rust-std-beta-aarch64-apple-ios.tar.gz=3cccf751678cc229a7ca3b39cbee4467230bec235e16b48acc576c825e0be15c
-dist/2025-05-12/rust-std-beta-aarch64-apple-ios.tar.xz=9ed9b7f1672d887fac4a0386027440651ef99c682ff21b1bd9c1ddd850934613
-dist/2025-05-12/rust-std-beta-aarch64-apple-ios-macabi.tar.gz=e7e6c0c7d9fa99f268d7601a127c6ce07df620fb27462dbaf933124a5786ef8a
-dist/2025-05-12/rust-std-beta-aarch64-apple-ios-macabi.tar.xz=abcecf3ecdb72714f35981847a91190c3f038dd5dce23a68253c7129fa6abf3b
-dist/2025-05-12/rust-std-beta-aarch64-apple-ios-sim.tar.gz=c50ac5245e87b5e251fce3ff847ddf7d62df4490843e8a5f592515517b04d406
-dist/2025-05-12/rust-std-beta-aarch64-apple-ios-sim.tar.xz=1c913535759d008327eef49e47870d3afcf609c29aab4a188209c3cfea954682
-dist/2025-05-12/rust-std-beta-aarch64-linux-android.tar.gz=6120c1b159fa4f0279f8952aebf8cf1513f5b843905d64d1efaccaceac79c1f1
-dist/2025-05-12/rust-std-beta-aarch64-linux-android.tar.xz=57ab4652b879df33556cf04596f0f9ad9b0eee832b67e33c8c8cdf812c229a6e
-dist/2025-05-12/rust-std-beta-aarch64-pc-windows-gnullvm.tar.gz=7afcbb49691f8286ac21107598a7a44363a8e385eaa648ab2e7711f87ddedfca
-dist/2025-05-12/rust-std-beta-aarch64-pc-windows-gnullvm.tar.xz=ea8af597e49e924f1e04eb3435afa09720c81f43dc467461de1058265d36dd64
-dist/2025-05-12/rust-std-beta-aarch64-pc-windows-msvc.tar.gz=2d8791f8ebff5f5f679c8b1735fdd1f0a4d7968983a5c2ddc5e036ad35b31f1e
-dist/2025-05-12/rust-std-beta-aarch64-pc-windows-msvc.tar.xz=a7f7bb3269dd7312edea5c6fef81d373499a670804259cf7853ef346fff42ee0
-dist/2025-05-12/rust-std-beta-aarch64-unknown-fuchsia.tar.gz=9469cb7871dc724148489180df240dd51c0388cd9bb478adf272934e38916b73
-dist/2025-05-12/rust-std-beta-aarch64-unknown-fuchsia.tar.xz=315f3dea48c50819f925bd32a3a5181591d4370eee4def8e37448828e622ab06
-dist/2025-05-12/rust-std-beta-aarch64-unknown-linux-gnu.tar.gz=abfaa164202c7d5d3c7e956b10a5ea612b092ee45d6c05d5c19a097617cfd703
-dist/2025-05-12/rust-std-beta-aarch64-unknown-linux-gnu.tar.xz=71ef1275726f6c61113bf1d23099a7557461205b6be243a952fa806ef15d9413
-dist/2025-05-12/rust-std-beta-aarch64-unknown-linux-musl.tar.gz=d651e5e46e1251952e719237dde30ed7ecdb6b95a7cc0398fc635a76b94c552a
-dist/2025-05-12/rust-std-beta-aarch64-unknown-linux-musl.tar.xz=0a67ebf159539bc7f5a4e5698a0c74550da3c5e2cb0b5e1dd694ad29e1f35834
-dist/2025-05-12/rust-std-beta-aarch64-unknown-linux-ohos.tar.gz=c0f1ecbbdd5234230d2439620c0ebe9b1c3d331388cd174cdeaf48d724172aab
-dist/2025-05-12/rust-std-beta-aarch64-unknown-linux-ohos.tar.xz=e2ba0a2853d685679422c065f266ee57f269bb5a231c5af5a791559a3609fb25
-dist/2025-05-12/rust-std-beta-aarch64-unknown-none.tar.gz=04b4eaf5910e662364b5ac3ee08ddffc2eda3957892ba99c8c945f5e1a18747a
-dist/2025-05-12/rust-std-beta-aarch64-unknown-none.tar.xz=065751b346f9c3d76e164a9edc123f277492ebfaf1d00db61027e4fb17d50f79
-dist/2025-05-12/rust-std-beta-aarch64-unknown-none-softfloat.tar.gz=056a135278dfdafb5b22c8f01bfc77b17396511d67b55c1404693d801e584262
-dist/2025-05-12/rust-std-beta-aarch64-unknown-none-softfloat.tar.xz=fc086ae7ca3a5c05790cb41dfc382fc65f929c669efd540c07131b851b78a743
-dist/2025-05-12/rust-std-beta-aarch64-unknown-uefi.tar.gz=97a6301cdd34da68d5c6b243cc125f7e34215853e405d9b34bc715aeda3223ab
-dist/2025-05-12/rust-std-beta-aarch64-unknown-uefi.tar.xz=3f2055ce638671316dc074595a35b893eea7be596cff218ec1416f3259ff86cb
-dist/2025-05-12/rust-std-beta-arm-linux-androideabi.tar.gz=299158c865df15424564be4d72921b8b25993b0671e4d462ff69f49ea29367db
-dist/2025-05-12/rust-std-beta-arm-linux-androideabi.tar.xz=6e71d518bf5f4a29b91938ee28b3c9b22509f3d97d4331ddd8ae0c1069192310
-dist/2025-05-12/rust-std-beta-arm-unknown-linux-gnueabi.tar.gz=0a00703833d46720e470ed90f81a08d9c20f63932d852e379fe63df955e61c9b
-dist/2025-05-12/rust-std-beta-arm-unknown-linux-gnueabi.tar.xz=57be85e4c2d4eeb4cbb19f48150693d4e6dd2969d380b1d55feb431c858e4c35
-dist/2025-05-12/rust-std-beta-arm-unknown-linux-gnueabihf.tar.gz=7b96461125b04d98a550bac5a7c3dad9c1df65ce849758d867c72ffc0b475012
-dist/2025-05-12/rust-std-beta-arm-unknown-linux-gnueabihf.tar.xz=a66602af671667fe5686c7a4e395d3dca8374ddae10cc9260e23e20f65022549
-dist/2025-05-12/rust-std-beta-arm-unknown-linux-musleabi.tar.gz=deaf5c7ed339c8a7bc2af94888841b647f8118854f698ece4ddbf900df921bd9
-dist/2025-05-12/rust-std-beta-arm-unknown-linux-musleabi.tar.xz=eac2d4d330a5300ee297c2eb61914b86efded3d494c5a73e2f91d989cb2896c4
-dist/2025-05-12/rust-std-beta-arm-unknown-linux-musleabihf.tar.gz=479a5941193d14e2d4d50fcdbecb31103f6a143bcd3afae887d068c2ebe14163
-dist/2025-05-12/rust-std-beta-arm-unknown-linux-musleabihf.tar.xz=2483258323175c1e338be84ce52d44e15177096643beabba9d806c69cbed23dd
-dist/2025-05-12/rust-std-beta-arm64ec-pc-windows-msvc.tar.gz=528803fac28b0a0025dc50324a6980a4b561e7e3b99d7428b8ed0a73fd3dd462
-dist/2025-05-12/rust-std-beta-arm64ec-pc-windows-msvc.tar.xz=6603b9aa82cfd563d7c462ebe50058c36aff403aa9e3a1d6a305780126aee481
-dist/2025-05-12/rust-std-beta-armebv7r-none-eabi.tar.gz=6ae7f3e39e974e20e9cbfae276fd4995063c5702c41085c2b764f3c37cbbfdec
-dist/2025-05-12/rust-std-beta-armebv7r-none-eabi.tar.xz=404ae1fc0f5a6995ced2f66fa863cfff17c863096e99b5a04c841b97e6f0e28f
-dist/2025-05-12/rust-std-beta-armebv7r-none-eabihf.tar.gz=bf6aaeeba558ac148b693c4e4d231415f6e72506b50ee06b0a1f987374a08df7
-dist/2025-05-12/rust-std-beta-armebv7r-none-eabihf.tar.xz=ed3f8767f5e824c5b81178e56c6084c45c67653793128d2c08146533333cc0ba
-dist/2025-05-12/rust-std-beta-armv5te-unknown-linux-gnueabi.tar.gz=7d2fae89c459d65fe2cd28acaa225f0ccc35b3f49c84ce6aa86e2c40dba38e03
-dist/2025-05-12/rust-std-beta-armv5te-unknown-linux-gnueabi.tar.xz=fc05ce5ee26be4a233181b9841975c0975fc45ad5466d1001a24a01e2a31123b
-dist/2025-05-12/rust-std-beta-armv5te-unknown-linux-musleabi.tar.gz=0335813546a1f905e274135b2bd97c3a0c95f2e0d992d7396bc110b800d3ca8c
-dist/2025-05-12/rust-std-beta-armv5te-unknown-linux-musleabi.tar.xz=7031aeca445d4f8fa351c7ad2e0e06df0386ed11f91080ea65968f1716006bd3
-dist/2025-05-12/rust-std-beta-armv7-linux-androideabi.tar.gz=9abd7fe0b7163a141d758ccdca422bd32ed4ad3618066ac022671b082f4641f9
-dist/2025-05-12/rust-std-beta-armv7-linux-androideabi.tar.xz=2bcdeb652d42755528a17b86a3b64b13b32d1ba9207cd2c9ccb43fa0d7a1c6bc
-dist/2025-05-12/rust-std-beta-armv7-unknown-linux-gnueabi.tar.gz=1bad15b2e9806e7858d5d4d58f6b2864c3f04e65d4ecb1cc448efdbf0e0030b0
-dist/2025-05-12/rust-std-beta-armv7-unknown-linux-gnueabi.tar.xz=f2d9039c903e5c309bbd17c7567462d4663665cbb7e1d98154022d98a9883719
-dist/2025-05-12/rust-std-beta-armv7-unknown-linux-gnueabihf.tar.gz=13aa4a3ef68a87de259726c7c2a3906cbf013836f753b707a453bf91879f023b
-dist/2025-05-12/rust-std-beta-armv7-unknown-linux-gnueabihf.tar.xz=8c4f8c044aa4ec6813cec1fed11326f67b0f2db3f20e4b441aba5656af7f0ae3
-dist/2025-05-12/rust-std-beta-armv7-unknown-linux-musleabi.tar.gz=4c2e5ae8c903577e963af32fdbb39de6180db52907c3f508064a87a21feb9390
-dist/2025-05-12/rust-std-beta-armv7-unknown-linux-musleabi.tar.xz=c1a12c15792f6b0de81a6e24317d7bea9af023a977ae0558ee3b4598539aa7cb
-dist/2025-05-12/rust-std-beta-armv7-unknown-linux-musleabihf.tar.gz=f789db5aebd9395daf198d5248323fee1eec27533f6d95d0f454339cbc997950
-dist/2025-05-12/rust-std-beta-armv7-unknown-linux-musleabihf.tar.xz=0376d2f2ad8f82719eabb378de3404e066da7d603e27ae4e1620509ccd6eb5b6
-dist/2025-05-12/rust-std-beta-armv7-unknown-linux-ohos.tar.gz=9312a8d530c6ca1e72ed35ef82700853e1fba8a1f39bcaad61277a86a974ab18
-dist/2025-05-12/rust-std-beta-armv7-unknown-linux-ohos.tar.xz=8c7d99202e5468bbd6fcd818cb832376c00a7c4b09973e5d00b84aa4964b7ff6
-dist/2025-05-12/rust-std-beta-armv7a-none-eabi.tar.gz=c4fb94b25d21802136bc36289eea9b95e50b101f64de925a1e9d8ad8ee70aef6
-dist/2025-05-12/rust-std-beta-armv7a-none-eabi.tar.xz=6ac88ec457fd554268da3307d40664d2926174cf8e89eb173112c7248776e060
-dist/2025-05-12/rust-std-beta-armv7r-none-eabi.tar.gz=c436c2c58d224e1f9bea4703f8ab57cd3f427c60432cca50eb294dde65994002
-dist/2025-05-12/rust-std-beta-armv7r-none-eabi.tar.xz=220906e1eca686d6e4a76a80417f527d37b0659adbec940566570292496715f8
-dist/2025-05-12/rust-std-beta-armv7r-none-eabihf.tar.gz=eee1788aec77c48c76bc5ba807d42d4bbb7c8f3e9220ba1135764061a9ddf3d9
-dist/2025-05-12/rust-std-beta-armv7r-none-eabihf.tar.xz=136f3486bdd8a7e91d738a3f8c1c3b96b853aa054a76c4e83e427ea56d3eea0d
-dist/2025-05-12/rust-std-beta-i586-unknown-linux-gnu.tar.gz=72e3c031fa55d131a206d5815899a48ff7bcb19c9ac4b3dbaeab38a3cc4a3630
-dist/2025-05-12/rust-std-beta-i586-unknown-linux-gnu.tar.xz=91ca56a1e5a07e1c147a8906d366985548bd961af2aa31dfba60938e457ddece
-dist/2025-05-12/rust-std-beta-i586-unknown-linux-musl.tar.gz=839ece94670a9295148231c77573f5b2d8ec5fb9727ab6aa45b8f320201f40d5
-dist/2025-05-12/rust-std-beta-i586-unknown-linux-musl.tar.xz=27ec97a6e24184edf4a51de5500d5bb4d4833ad2b7bc771a4506589ce2190062
-dist/2025-05-12/rust-std-beta-i686-linux-android.tar.gz=d8f529a63a46bba2bd358e491d7fe0be10fee6dabf0075c40177402aeeb49721
-dist/2025-05-12/rust-std-beta-i686-linux-android.tar.xz=a061a703858aa0770d51c6c8bcdfca048efe96b561c460464b835b4ccfdca387
-dist/2025-05-12/rust-std-beta-i686-pc-windows-gnu.tar.gz=8b7eb90ad7edb050599dd477c520455ad7e02696426692a0a72094381e189285
-dist/2025-05-12/rust-std-beta-i686-pc-windows-gnu.tar.xz=f99e1d82a3cfaef05e6f088e766932a3860e7df60e1f392162746bb08eb72ddc
-dist/2025-05-12/rust-std-beta-i686-pc-windows-gnullvm.tar.gz=5d57965f2a6ffff01619e84acdc0f7d9b2afe3c361e5094eecccfa9893eaa501
-dist/2025-05-12/rust-std-beta-i686-pc-windows-gnullvm.tar.xz=c1b218aac6370cef9564043c98f361a2938c6ebc7784cb49b361aad3a1bfb6f1
-dist/2025-05-12/rust-std-beta-i686-pc-windows-msvc.tar.gz=fdcd4b6f391338fc0f7b72d11fc8dad9df903fb4639b893b57e729de387a9cf9
-dist/2025-05-12/rust-std-beta-i686-pc-windows-msvc.tar.xz=c8faa9123c9df0d764cac59e10e94f1562ec7bc7a792f5c63f9a9decd48a3280
-dist/2025-05-12/rust-std-beta-i686-unknown-freebsd.tar.gz=e8882425b127d01afcf6269e820bb8c4b813619b6d10f0422fea17c87d5921bf
-dist/2025-05-12/rust-std-beta-i686-unknown-freebsd.tar.xz=dabd3bb2560a7949f8984e1dcab35aa46f8e46b09e68c7f2ff32894370ed80b7
-dist/2025-05-12/rust-std-beta-i686-unknown-linux-gnu.tar.gz=dd296784ed2199b4c2d85053bce686e01cf867851b175b24781e7e8e6f6ef8bb
-dist/2025-05-12/rust-std-beta-i686-unknown-linux-gnu.tar.xz=3bb9069b4456de27cc9fba5dd2b350e5e8215f0460ce9ee375f65856958e4a82
-dist/2025-05-12/rust-std-beta-i686-unknown-linux-musl.tar.gz=008ea77ae8d982461c65c25bfcc0c41642ca51a33007a4c8d1ede8612df8f20f
-dist/2025-05-12/rust-std-beta-i686-unknown-linux-musl.tar.xz=fdfeb6df04afe1f4e414ad8292a7b75191c2507d020e69f402f97ee9ab3ccf90
-dist/2025-05-12/rust-std-beta-i686-unknown-uefi.tar.gz=dbca5a983d2eb2bd84aa7779fc54562bccf9043b31a7f52a3043f1e1e59695c8
-dist/2025-05-12/rust-std-beta-i686-unknown-uefi.tar.xz=c0d9abf38ba7b1847fc70b9dbe68f4c27d5a1adb9726dbbee77911f1d271b6aa
-dist/2025-05-12/rust-std-beta-loongarch64-unknown-linux-gnu.tar.gz=c923562d0a1d2830d41212ba140225b9c36087087dde6753e7a891383a095a10
-dist/2025-05-12/rust-std-beta-loongarch64-unknown-linux-gnu.tar.xz=5ca633c2e218939983d77cbf5738ab7d5fc4aa89093a0d1fb701ab06ed7ecf51
-dist/2025-05-12/rust-std-beta-loongarch64-unknown-linux-musl.tar.gz=a38b4748085b3c06f2154376cdda41fcee2154f1fb409ac5137b63034cfe8cab
-dist/2025-05-12/rust-std-beta-loongarch64-unknown-linux-musl.tar.xz=43601e0aecb02535ee46b0ddd076867248cd8654be302ae6580a81af33660faa
-dist/2025-05-12/rust-std-beta-loongarch64-unknown-none.tar.gz=04dc49b516a638589d907f885aeafa19170683b023d0ee1bf5d78f0d91d0b94a
-dist/2025-05-12/rust-std-beta-loongarch64-unknown-none.tar.xz=123f388b208842b3ee46a01ae8efab900c0b5b01b97eb896d26b12bb3aecdeaf
-dist/2025-05-12/rust-std-beta-loongarch64-unknown-none-softfloat.tar.gz=a57452e86c5b768f1feb7f903e4ef8e76518e625c09b5f555885e1d9aaf9b76f
-dist/2025-05-12/rust-std-beta-loongarch64-unknown-none-softfloat.tar.xz=e9d8b99bc4686e199f3aeda5cbfd99d49416a7ba104b494c18ae67a8d1133d9d
-dist/2025-05-12/rust-std-beta-nvptx64-nvidia-cuda.tar.gz=3a9f4744fc128be61877967586e6c163cd6ef4e017e04578cb9101c8a9a60cdc
-dist/2025-05-12/rust-std-beta-nvptx64-nvidia-cuda.tar.xz=0e693f7c27a34876728565152f7b6b407e1773a187742792ea2ac3f53d6c9839
-dist/2025-05-12/rust-std-beta-powerpc-unknown-linux-gnu.tar.gz=9d0f6d9cc2b7d1ceff5934a00c780337d2fa77cd9a81cbe9e041e5b18adb43ff
-dist/2025-05-12/rust-std-beta-powerpc-unknown-linux-gnu.tar.xz=afcd5c9d2e67d6c514630443d9e50d37d36722712e9275e3eaf4f460f7eb779f
-dist/2025-05-12/rust-std-beta-powerpc64-unknown-linux-gnu.tar.gz=9c02e0eb75361a024d25863456c3906b845314481cd9173a6708104a21265e88
-dist/2025-05-12/rust-std-beta-powerpc64-unknown-linux-gnu.tar.xz=5b0628ca22f762796c9215606314babc1237baea075c990e146ee9f9ba1ed834
-dist/2025-05-12/rust-std-beta-powerpc64le-unknown-linux-gnu.tar.gz=9e12bd3f2b61b8753aca3a1ed117cae0b4bae2267634a6e24afc0c642d998784
-dist/2025-05-12/rust-std-beta-powerpc64le-unknown-linux-gnu.tar.xz=70a6cf1d3e6767656657e5f76e8dd35049bd20a30517f85832c35847c9f63bf7
-dist/2025-05-12/rust-std-beta-powerpc64le-unknown-linux-musl.tar.gz=e2feb3c8bf2390281c71f3b76f07a5a9700e454236bdd2c8f75403cb2247b252
-dist/2025-05-12/rust-std-beta-powerpc64le-unknown-linux-musl.tar.xz=0b533328ff7dfffdfb11826811fa9474c36faebe909f176d60898477d5b9d23b
-dist/2025-05-12/rust-std-beta-riscv32i-unknown-none-elf.tar.gz=42b46c1d8ebec202131d08aa21fb6ead760a630199822b4fe88c94a5447f0491
-dist/2025-05-12/rust-std-beta-riscv32i-unknown-none-elf.tar.xz=24bb2a24d41bfdb76dfb8817e99759dfd314ce52309d51b294db7a558114f936
-dist/2025-05-12/rust-std-beta-riscv32im-unknown-none-elf.tar.gz=5d50c5a766344cacc6e7ebdabddfe720199fca74d1d4284a80ff5625150d7bcc
-dist/2025-05-12/rust-std-beta-riscv32im-unknown-none-elf.tar.xz=f6f6e68c0d495b2833566deacac8a6154a220fe1f92deacd031e6b649a63a04f
-dist/2025-05-12/rust-std-beta-riscv32imac-unknown-none-elf.tar.gz=a80d128b4d0b3b5bb9316da1297b0c1cfee026eea3e9e23c546d62dda9cebd3d
-dist/2025-05-12/rust-std-beta-riscv32imac-unknown-none-elf.tar.xz=03e27d02bf685f6eb1281fc48d417dcf9f934587fbc743d6e7aac6e0c3691d5c
-dist/2025-05-12/rust-std-beta-riscv32imafc-unknown-none-elf.tar.gz=67185b764c3423704af10318f44f0f310349191d62785bd8cb85ca2bac7f935a
-dist/2025-05-12/rust-std-beta-riscv32imafc-unknown-none-elf.tar.xz=8ef88ac6044c84815bbbcd2b5ce4128349633addf40bb8c439b9a0a07fc5e179
-dist/2025-05-12/rust-std-beta-riscv32imc-unknown-none-elf.tar.gz=2ab3bbb6de6a5281f8aa586e5fc15d575a34b17b4f44908347d7a776c924add2
-dist/2025-05-12/rust-std-beta-riscv32imc-unknown-none-elf.tar.xz=321b0167c9481ab88ff44bf920fa15bdb4e07c864a90b6777f3c8dfd0e5c5ec6
-dist/2025-05-12/rust-std-beta-riscv64gc-unknown-linux-gnu.tar.gz=bede2674247df8ff2153808f499ee1c1a7a909ff87600513ebc2998f43c7c1ea
-dist/2025-05-12/rust-std-beta-riscv64gc-unknown-linux-gnu.tar.xz=b903c9ca2344fd1323695052f74b9562f6dd3cdde4872f935bcba6c0fb988dce
-dist/2025-05-12/rust-std-beta-riscv64gc-unknown-linux-musl.tar.gz=ad90fed7ed9137d04aa8c41d1c7e856dd8cc57a0f4b7836b22c9b1932a24a769
-dist/2025-05-12/rust-std-beta-riscv64gc-unknown-linux-musl.tar.xz=78372e3e32174a2cfa12dcd426e36fe29ff76779d8815944e6f6c7be4a3c55fe
-dist/2025-05-12/rust-std-beta-riscv64gc-unknown-none-elf.tar.gz=a781d0ee95ae3012e3d016ae1b029ca8507ff549a6b1e0a6f052bca6d4afbc7b
-dist/2025-05-12/rust-std-beta-riscv64gc-unknown-none-elf.tar.xz=23b1cf7192f044a0f46ccedd654aa203dc0e9fad47c5ffc2a1e6717bf6598d69
-dist/2025-05-12/rust-std-beta-riscv64imac-unknown-none-elf.tar.gz=dfb15324b8047bd26a58a26d373af441182808203c06a3d4e595d79bca21b757
-dist/2025-05-12/rust-std-beta-riscv64imac-unknown-none-elf.tar.xz=432dfeb9231b67537dc5c77941ee26fd73404ea16dc1be4071b98c13680ddcaf
-dist/2025-05-12/rust-std-beta-s390x-unknown-linux-gnu.tar.gz=cff18fbbbe323c67779651dd6e3b94a76a573567720985d59a091c26a3c33110
-dist/2025-05-12/rust-std-beta-s390x-unknown-linux-gnu.tar.xz=c5f25038ba5be3ffddb6966e89017de862a0d9f267a57eeaae81b3b2a44d5690
-dist/2025-05-12/rust-std-beta-sparc64-unknown-linux-gnu.tar.gz=104d762d5a45fea227880d2395068824f9202e5a7fbd30bea478bb1ee6899ee2
-dist/2025-05-12/rust-std-beta-sparc64-unknown-linux-gnu.tar.xz=de1f15d6cfafc275108c4584a294128962dabe54bf5a1f6e81da3508ea9e8a14
-dist/2025-05-12/rust-std-beta-sparcv9-sun-solaris.tar.gz=531562c65d558a993128054fcfb29f0d408a40318ecd5623b5b24636bd7b0a07
-dist/2025-05-12/rust-std-beta-sparcv9-sun-solaris.tar.xz=af866deae0c10ce2b11c0ebe37fdafef79285bc694eaba75213316ab125b198d
-dist/2025-05-12/rust-std-beta-thumbv6m-none-eabi.tar.gz=ff623d437bda1c0b8cd8affd2a6bc165b8224a5467894aa54dee63b1b6939fc6
-dist/2025-05-12/rust-std-beta-thumbv6m-none-eabi.tar.xz=d8743e42057014ef2742cec5b93e34d5cde5a658d3ed9e7e738276387985122e
-dist/2025-05-12/rust-std-beta-thumbv7em-none-eabi.tar.gz=0b097cef25dfe72f692cd6d9dd2df85a2fc5ea9db87b8c06b8f310c239c74624
-dist/2025-05-12/rust-std-beta-thumbv7em-none-eabi.tar.xz=e7fd61ad7660c7f8c62ae6dbbd238305d997fe7539dfffb8fd0df2205656b5a9
-dist/2025-05-12/rust-std-beta-thumbv7em-none-eabihf.tar.gz=d6b3c40bd84fe352c1a88dfbc3c0f9012dcc1d82b860ce68c1d21a8d452fa662
-dist/2025-05-12/rust-std-beta-thumbv7em-none-eabihf.tar.xz=b2be1305ae382359f81e0bff16341719b6ea7731ff833205dc3fd99e7e978fb9
-dist/2025-05-12/rust-std-beta-thumbv7m-none-eabi.tar.gz=5452dc0f152065e887178423e324bf3082885b922ac57ff22c156cf7c432e184
-dist/2025-05-12/rust-std-beta-thumbv7m-none-eabi.tar.xz=5331de420a79f521351a1ea3dd501cb00b21e1979eb23dfc871ce33abca68dd7
-dist/2025-05-12/rust-std-beta-thumbv7neon-linux-androideabi.tar.gz=0b2ffb463dca747f00cf063d8fb07971df80882d3890c34ba82fbf1b77655dd0
-dist/2025-05-12/rust-std-beta-thumbv7neon-linux-androideabi.tar.xz=2f7c2bde8ae4b911889dc24a8fbe2d1539685d46c71689e5e8362cf46c391019
-dist/2025-05-12/rust-std-beta-thumbv7neon-unknown-linux-gnueabihf.tar.gz=1d29e86aa77e277ce1598313d6851f2f077b023217f1712d59eb76305fc773fb
-dist/2025-05-12/rust-std-beta-thumbv7neon-unknown-linux-gnueabihf.tar.xz=73dc975b217329d6ad44b8e8b3f72a3396597a207df7d7222d983a155ca05758
-dist/2025-05-12/rust-std-beta-thumbv8m.base-none-eabi.tar.gz=c34c686a62afb45b9e57b3d487dcc1f66396bd7804a9c0d9696def0936a2ba1f
-dist/2025-05-12/rust-std-beta-thumbv8m.base-none-eabi.tar.xz=1527843f87588ee28aaedbb0590bb809c24cbde6a5264151ce5fe01baf70176d
-dist/2025-05-12/rust-std-beta-thumbv8m.main-none-eabi.tar.gz=8225d6b35a55d7937bbcb7f2e74ab8ec0f23fcd69a48c59391e9016d9863151f
-dist/2025-05-12/rust-std-beta-thumbv8m.main-none-eabi.tar.xz=8c59ed4aa0a62ff8999570b60a6b9c468ea52c45642ecfdc515d6f2722fd821b
-dist/2025-05-12/rust-std-beta-thumbv8m.main-none-eabihf.tar.gz=6a5804a7dc199f696867e4612d1381910ff9a13b5516b2906e651451d8ec23e8
-dist/2025-05-12/rust-std-beta-thumbv8m.main-none-eabihf.tar.xz=11205a43892169cd0aad2764f5d7604a52d13292978e7e851cef2d8e65ae6fe5
-dist/2025-05-12/rust-std-beta-wasm32-unknown-emscripten.tar.gz=962e092960bd3074dc966c1928a4adfdc16d6d811060e719dc1a84061132566c
-dist/2025-05-12/rust-std-beta-wasm32-unknown-emscripten.tar.xz=5d7fe7b3fe3b022c95d96e4027767b44a7e7980ca5c894839868919a0bb4b5bc
-dist/2025-05-12/rust-std-beta-wasm32-unknown-unknown.tar.gz=38afbfef695bad377ac9d3a4d7d9037b500795c3a75f907bf60acd4cac2b4cd4
-dist/2025-05-12/rust-std-beta-wasm32-unknown-unknown.tar.xz=f5f670d35a843cda6f5213ae02a99c3c6d1e30f3ab651be0087bf8e4de0911f2
-dist/2025-05-12/rust-std-beta-wasm32-wasip1.tar.gz=e7faeb24fac65f565e0145166d67a30b02b26f0df20791f3bdc31169846a0e2b
-dist/2025-05-12/rust-std-beta-wasm32-wasip1.tar.xz=0136f4434e8a0edbbe050899a17ae2b2825aeb4b98c4fb80f8eb25c9ea6623ab
-dist/2025-05-12/rust-std-beta-wasm32-wasip1-threads.tar.gz=2ed823ff5c3704f91048300fa31624cddeea8086cfc654fa2fea4adff58fd901
-dist/2025-05-12/rust-std-beta-wasm32-wasip1-threads.tar.xz=6f156a460db83c271b43c37709ce5724fb8059c44b29e08c2b2da27c32c06e5c
-dist/2025-05-12/rust-std-beta-wasm32-wasip2.tar.gz=ecd1ba1fec2e1e87b5f30b341e8228ca98545143adb8acd6ba53c7503f581e34
-dist/2025-05-12/rust-std-beta-wasm32-wasip2.tar.xz=593976f715c77796cecf6f7f2b79fbd4f49c10ded0349762e8312052497f1e28
-dist/2025-05-12/rust-std-beta-wasm32v1-none.tar.gz=396eb4c1e4cd930f045b092bbc8203315f494ea32c836d62e84f63ead124d886
-dist/2025-05-12/rust-std-beta-wasm32v1-none.tar.xz=9b827d1941a1d67a32a255342b476a19f57de06e53a9e6798bf00688b86eb2e0
-dist/2025-05-12/rust-std-beta-x86_64-apple-darwin.tar.gz=2796de44843d68141c6330f0e09fbabb5c3a8f34470d2948f1ed93b1b9dac088
-dist/2025-05-12/rust-std-beta-x86_64-apple-darwin.tar.xz=881e98599e5b2475e8c9f6b81e0ad6a51e8058cb2c7fc893ab57c19cdcc80804
-dist/2025-05-12/rust-std-beta-x86_64-apple-ios.tar.gz=8203faeaf21dc2c86b35d4362413c12d01de33da4524008c6261d3c87be9e51d
-dist/2025-05-12/rust-std-beta-x86_64-apple-ios.tar.xz=13a59816008d3d4b0fb20680bfe2f1c2ae8ca7eed0bdf717817e03693724eb25
-dist/2025-05-12/rust-std-beta-x86_64-apple-ios-macabi.tar.gz=5b906fe2d801c572696cd93564723338385eb574587769f79506cb3e6c87452d
-dist/2025-05-12/rust-std-beta-x86_64-apple-ios-macabi.tar.xz=1624a408800a895d8fe71bfc71876e52349c3508e9ddabd46d89d3274ede2dd7
-dist/2025-05-12/rust-std-beta-x86_64-fortanix-unknown-sgx.tar.gz=6722e76457289c6551f77fd462058862d7fb8597e1714cf66925b21e5af75c7b
-dist/2025-05-12/rust-std-beta-x86_64-fortanix-unknown-sgx.tar.xz=8097f509383cab4e8e444ccbf7f5d91fe35bcd2cd2017ab78bcc692c9fd1ecf4
-dist/2025-05-12/rust-std-beta-x86_64-linux-android.tar.gz=eb3124653c908003185b36aa9829ea983f4b44e11a96da69c2585664a67bfeaf
-dist/2025-05-12/rust-std-beta-x86_64-linux-android.tar.xz=4f29c6a0458ed5e37ee7a17643ff7854bd6ed029c46cdd0707019d01523a7a62
-dist/2025-05-12/rust-std-beta-x86_64-pc-solaris.tar.gz=319663b24b449df3f8063f64bd849969999a441b9376c86e6eea15cf3b872e5b
-dist/2025-05-12/rust-std-beta-x86_64-pc-solaris.tar.xz=13280470aa4c84ed6ca200664ebf3a6aa084550a82c06505b3178caefe3072ef
-dist/2025-05-12/rust-std-beta-x86_64-pc-windows-gnu.tar.gz=d97cf2b52f013b5cfdd9c5a3885ea70accdf52e2f957e086018d88731c8c1964
-dist/2025-05-12/rust-std-beta-x86_64-pc-windows-gnu.tar.xz=a2685ab1c204823b19809e47b00f2c48c5f2cc2faea05ac2df935732a7412441
-dist/2025-05-12/rust-std-beta-x86_64-pc-windows-gnullvm.tar.gz=50c0f770a938123f704837bd3313dcb12842aba75b687282a9aca6c11b11ba8e
-dist/2025-05-12/rust-std-beta-x86_64-pc-windows-gnullvm.tar.xz=8f0d04c8d55f23235f8dec94c5d5035405afd513b082f00b257bbb86cd481240
-dist/2025-05-12/rust-std-beta-x86_64-pc-windows-msvc.tar.gz=e633aebc178d4846a3d26f796405dde13115560c23bd2955c82afea8ab7c8d7b
-dist/2025-05-12/rust-std-beta-x86_64-pc-windows-msvc.tar.xz=8125d5bb9a9205ffab43d0dcd56402320643101169a49098a98ee6ae785c0ed3
-dist/2025-05-12/rust-std-beta-x86_64-unknown-freebsd.tar.gz=c089415c86c9f74a454b82955911e84c9138ad66757e4da689381a1bfbd4cee5
-dist/2025-05-12/rust-std-beta-x86_64-unknown-freebsd.tar.xz=a930b94bc005ce2b09b4d67abf47bfeafad8c7ab6ca5c15acc10e023818e7b25
-dist/2025-05-12/rust-std-beta-x86_64-unknown-fuchsia.tar.gz=f74e77eb803d1ca244e1e97272578ec008e9c373af92887318d9281204a798fa
-dist/2025-05-12/rust-std-beta-x86_64-unknown-fuchsia.tar.xz=2fa583fcde17c1ab2f2d148af9467fa65f6bf6a0a1801e957fa15a79e6de4f78
-dist/2025-05-12/rust-std-beta-x86_64-unknown-illumos.tar.gz=20d16ce11adf468da51b30c0b55a46ce3bd030eea9f9fdb3f65f36aa442a3d71
-dist/2025-05-12/rust-std-beta-x86_64-unknown-illumos.tar.xz=dc1f2d3c1a0ae59cbfaa09b2d646645cb4fabb151edbf92975e4c8a0bfa54eba
-dist/2025-05-12/rust-std-beta-x86_64-unknown-linux-gnu.tar.gz=05b2e5ded14501cbdc86c0510faecbf873e30d2d70724013bbb176b6f4039b44
-dist/2025-05-12/rust-std-beta-x86_64-unknown-linux-gnu.tar.xz=a18281579cb61ea26ae0062428f7a49e51c4a928102a5eba7ff96b0ca38490c0
-dist/2025-05-12/rust-std-beta-x86_64-unknown-linux-gnux32.tar.gz=a5285ae02217d64c7bbddaa3dd1f68c361f2849479a6d75edf1d551751886f7d
-dist/2025-05-12/rust-std-beta-x86_64-unknown-linux-gnux32.tar.xz=4c41edc4f4cd1f24107b1b003a1713af3b456ff3e933781c5d4ef21a490df5e7
-dist/2025-05-12/rust-std-beta-x86_64-unknown-linux-musl.tar.gz=2d4c1666d456e810353f8b386d0d331812f84d9a17344953e5f4f4370bdccb0f
-dist/2025-05-12/rust-std-beta-x86_64-unknown-linux-musl.tar.xz=287f51dbc6e4273208869140b9c2e0de2896c0cd40f7492396ec0bbb8989a82b
-dist/2025-05-12/rust-std-beta-x86_64-unknown-linux-ohos.tar.gz=e20af62d1900a5e10cf766ddcda9550176ab5f41111e09d57167e4e23e68d005
-dist/2025-05-12/rust-std-beta-x86_64-unknown-linux-ohos.tar.xz=7837f4880ce5d5251213d17867a6c61977504840678388fe245e0433086f409e
-dist/2025-05-12/rust-std-beta-x86_64-unknown-netbsd.tar.gz=17d2a43bc24e4e49d54315c7eb0e4952c3118b278b0a564fd588ea4ce0e8d90e
-dist/2025-05-12/rust-std-beta-x86_64-unknown-netbsd.tar.xz=ab34b5b10273c639805956665cd6543749cff2748c53980f80342facb9171b2d
-dist/2025-05-12/rust-std-beta-x86_64-unknown-none.tar.gz=d8387a8478f6a937944d684f852dee18d584344ab84425d228489dee324c318c
-dist/2025-05-12/rust-std-beta-x86_64-unknown-none.tar.xz=6ed8c2c72d547c7cc6b32a6080c346915de02a1ac02f032b6320fc7e3d45e330
-dist/2025-05-12/rust-std-beta-x86_64-unknown-redox.tar.gz=7f3a62578694121ef90fd08ab7a82a8fb27d86f164d7f73edb56a2e360198f41
-dist/2025-05-12/rust-std-beta-x86_64-unknown-redox.tar.xz=44f7ba0ca447050ad3eb7be0a0e41fee304dad2ce359c854848b7430c42b22d8
-dist/2025-05-12/rust-std-beta-x86_64-unknown-uefi.tar.gz=f78e6eca6ff517571480a6bbe20099d170f6a6b2ff0e64544c41dc77588ed890
-dist/2025-05-12/rust-std-beta-x86_64-unknown-uefi.tar.xz=d2a733aad6929be6135676307bd4576eb168e11192c24051e0be4a713b5733c5
-dist/2025-05-12/cargo-beta-aarch64-apple-darwin.tar.gz=43afffa0c5f7287e205a63871b555be144e900f8d8d67e4ed0654b50809b7338
-dist/2025-05-12/cargo-beta-aarch64-apple-darwin.tar.xz=705f051543ed8cc7011d7a866f345c3aa22c9d24f5325bffb9d9676e3c26142b
-dist/2025-05-12/cargo-beta-aarch64-pc-windows-msvc.tar.gz=c0911e84ca85de5e8c9550e2be08dd85458ba31516e282044c9149bf8bb56fa1
-dist/2025-05-12/cargo-beta-aarch64-pc-windows-msvc.tar.xz=7335470fc1338b95edc81777eb0975cd5cf5cdcdcaefc7658f356ef3e0c54fda
-dist/2025-05-12/cargo-beta-aarch64-unknown-linux-gnu.tar.gz=99071e036041b47f78b71f1ff2ef5699b96a126ea84010ac031ee8d52d7c5873
-dist/2025-05-12/cargo-beta-aarch64-unknown-linux-gnu.tar.xz=a9be2eeeed37905e83beb4265f4f45086675a0f5ff25db0e6bc0c5164257e1e1
-dist/2025-05-12/cargo-beta-aarch64-unknown-linux-musl.tar.gz=b38fa8d68c27b4989b1dc94caaf6bec833cc8e6d4464b859451d495b081c5b1b
-dist/2025-05-12/cargo-beta-aarch64-unknown-linux-musl.tar.xz=95a839bd2f928afafbe1058cb185b95e0099ae15d5d3030a3493724f40300ae9
-dist/2025-05-12/cargo-beta-arm-unknown-linux-gnueabi.tar.gz=34cef4599ece9c218c3841ccff9a627a69909eb733c19441c19de5b68841845b
-dist/2025-05-12/cargo-beta-arm-unknown-linux-gnueabi.tar.xz=cedfde42e95a0e86c3be841965c20f1c8bcebd20d88f38b2e694017a8afa745e
-dist/2025-05-12/cargo-beta-arm-unknown-linux-gnueabihf.tar.gz=b8f1a0fca9b32362da6169b41fd58d53af6b02992ac5666cdeed03aa6150dd0c
-dist/2025-05-12/cargo-beta-arm-unknown-linux-gnueabihf.tar.xz=8f5b040e4099a03418b72b5975419089e7fa15a947b04ce6dd18f450cc21f2b4
-dist/2025-05-12/cargo-beta-armv7-unknown-linux-gnueabihf.tar.gz=2f526034ad1280d152861e700fad2aef95759eaf17780a3a00d71e8fc6d8520a
-dist/2025-05-12/cargo-beta-armv7-unknown-linux-gnueabihf.tar.xz=b6fdc7a08740d06e29aa678f4f9cb2dfb57fb863605fba1cce67d71ae1c1ace7
-dist/2025-05-12/cargo-beta-i686-pc-windows-gnu.tar.gz=f8b1e0227f5c1c2334cbcf53ebe5e94e01215ce21de2c5c9846e0ea7dce8e777
-dist/2025-05-12/cargo-beta-i686-pc-windows-gnu.tar.xz=149bc0d8cba9924db3b882795b6dd17f3d0a01bedfa75143dfdb7623cc7c4684
-dist/2025-05-12/cargo-beta-i686-pc-windows-msvc.tar.gz=b8462286bb1746bb789f580a14f1c5c37b108037633d9e8fbc5e2e6638e12a5c
-dist/2025-05-12/cargo-beta-i686-pc-windows-msvc.tar.xz=f07104b3439e4cfcf5c96dbf6bf4428f677f45449ce2a5595551884ab0a6870a
-dist/2025-05-12/cargo-beta-i686-unknown-linux-gnu.tar.gz=f68dece61dc087622d9e622944c4c13cdfb056eecdd93c9527c71637c73a708a
-dist/2025-05-12/cargo-beta-i686-unknown-linux-gnu.tar.xz=3272d868a2bc44b80d0ab11d133f66ed7a40b75d00fbb7a341adbee083dfd8c0
-dist/2025-05-12/cargo-beta-loongarch64-unknown-linux-gnu.tar.gz=2fa7ef9b0f5247a650c1cf649e7f5514989a22b6c7927fa1df809e54466bc18f
-dist/2025-05-12/cargo-beta-loongarch64-unknown-linux-gnu.tar.xz=3eddae3525cd8b446a4b31ea933cb859d335b0309900379868230d4a63979afe
-dist/2025-05-12/cargo-beta-loongarch64-unknown-linux-musl.tar.gz=88d56208387b4aa9707729f0b9337c32a0516dacc4c891b3c80140874dec6043
-dist/2025-05-12/cargo-beta-loongarch64-unknown-linux-musl.tar.xz=8e4ceefb3d64560d989bf69f3d58cc07ab2e6a68d1f761ef92cb1826351834bb
-dist/2025-05-12/cargo-beta-powerpc-unknown-linux-gnu.tar.gz=ed5705fb6dba34981727e4af215d8875de2c39d41b1c3e8653a93cdc06873975
-dist/2025-05-12/cargo-beta-powerpc-unknown-linux-gnu.tar.xz=be618816cd7706709fc13ab268249a74f7b905e7ae6abe6ca1fda336dd38baa2
-dist/2025-05-12/cargo-beta-powerpc64-unknown-linux-gnu.tar.gz=8b53a21201661914e3291ebc6912083e1cd86ed5d202d6940c2be15724371bc7
-dist/2025-05-12/cargo-beta-powerpc64-unknown-linux-gnu.tar.xz=546260a68ec029f228f280fc439e93dc1f64b3e597cf615ff3915548ab67b435
-dist/2025-05-12/cargo-beta-powerpc64le-unknown-linux-gnu.tar.gz=343a00f2cc571ac779fd7647560b215650a01e877c9b15f95668cfc33c67ec77
-dist/2025-05-12/cargo-beta-powerpc64le-unknown-linux-gnu.tar.xz=efc6a23ffb467e1459f3fe5932e8303d0ee550853ad13b3ace12c9aa6514f24c
-dist/2025-05-12/cargo-beta-powerpc64le-unknown-linux-musl.tar.gz=5c4e53aca46fcfb7d669b74872130fa2b8bf05b09d14bdce34f0322030450e47
-dist/2025-05-12/cargo-beta-powerpc64le-unknown-linux-musl.tar.xz=c2e33c9522924cbfde1109f87d12d27225ceb23c7ad801d3a5559a72715ca402
-dist/2025-05-12/cargo-beta-riscv64gc-unknown-linux-gnu.tar.gz=91d578317c8fa147c22e81728da411fd01c1fcb0bdf2e054948537476b8371e8
-dist/2025-05-12/cargo-beta-riscv64gc-unknown-linux-gnu.tar.xz=83fc425704b7673943583e38c31a944695984ffabcdaa4ab79b43aea03cef48e
-dist/2025-05-12/cargo-beta-s390x-unknown-linux-gnu.tar.gz=dac65289a906a32908ff0af9e9b829111295b49099fd5d9f90b2e454b4ecb422
-dist/2025-05-12/cargo-beta-s390x-unknown-linux-gnu.tar.xz=02a3972bfd62d4097da252fed278d741193f2c4face2e35ce8e84974e42cb1e1
-dist/2025-05-12/cargo-beta-x86_64-apple-darwin.tar.gz=148d0410ec2d3e540cfc27b6756e50d98b7ed214c2e5a702a9f2326e75ec249c
-dist/2025-05-12/cargo-beta-x86_64-apple-darwin.tar.xz=65e993adfc14eb7a9c3946a3d1ce35f5aa9767ece65cd759669bb82deda0adc8
-dist/2025-05-12/cargo-beta-x86_64-pc-windows-gnu.tar.gz=a69c23bfe9ec73737c22d0b6ce308a4f19625aab2f1846bc223ec6974cdd9163
-dist/2025-05-12/cargo-beta-x86_64-pc-windows-gnu.tar.xz=56b33a8c9e0bcbbdb2c6be13d7b84d077a896b21d800a3c6da64aa2ef64ecada
-dist/2025-05-12/cargo-beta-x86_64-pc-windows-msvc.tar.gz=cfd22dda3987642606f9e869264fa709d87b8ac5894547f809f60abce268ff76
-dist/2025-05-12/cargo-beta-x86_64-pc-windows-msvc.tar.xz=7075d67ef2dbf1e0d3889039d4db66042db538304c53cacd3e983eb9aa9d0275
-dist/2025-05-12/cargo-beta-x86_64-unknown-freebsd.tar.gz=419ce0f856113509f58f2fbccf9e5f864aa56c3c1a2c4029ecdb546464393214
-dist/2025-05-12/cargo-beta-x86_64-unknown-freebsd.tar.xz=d8f73cb808471883a5f6ee8db3dd5165fff5084ae744f4ffdca89fb545faaba8
-dist/2025-05-12/cargo-beta-x86_64-unknown-illumos.tar.gz=69e63b33c7f8d469232504c373a4e35df97016735be633a818023ea21de8f0be
-dist/2025-05-12/cargo-beta-x86_64-unknown-illumos.tar.xz=aa86cbf46dd2e35c10bb5725c627dc40ecb33329a866c2b0c5c274728f384ed3
-dist/2025-05-12/cargo-beta-x86_64-unknown-linux-gnu.tar.gz=f77e6d762e13eb95d6369a26971e4108de448eb23690554914f650fadd2898de
-dist/2025-05-12/cargo-beta-x86_64-unknown-linux-gnu.tar.xz=8e4b379bd88e8f18e5b6efe6058bad4ee60fb6c2e734ec165fee188f893f948d
-dist/2025-05-12/cargo-beta-x86_64-unknown-linux-musl.tar.gz=a04b711f9a07eee991b1ab13ab56e0f9e2c2ba2a16186be6c0d04529ca68af59
-dist/2025-05-12/cargo-beta-x86_64-unknown-linux-musl.tar.xz=587b214ddf5b85697b78d8baa9164a4b81604b8dccc969a03b1bf06ae7c11240
-dist/2025-05-12/cargo-beta-x86_64-unknown-netbsd.tar.gz=81a468f1db3cbdaddf6a1785297457d4780fbec472d0bdfda64fb7a398782a78
-dist/2025-05-12/cargo-beta-x86_64-unknown-netbsd.tar.xz=32212f4273171d78e10170c4a863d6f9990e29e26fdf6857dd3d134eb803161d
-dist/2025-05-12/clippy-beta-aarch64-apple-darwin.tar.gz=e5de69a84edb22eeaaeea2d94aafb07ed408508f68fc0989268e6dec8bae6a8e
-dist/2025-05-12/clippy-beta-aarch64-apple-darwin.tar.xz=03a9ebedbf11cf151d19f46b9eeb3f8ea765ac779b55356b51db21e83195c610
-dist/2025-05-12/clippy-beta-aarch64-pc-windows-msvc.tar.gz=5a9e27ab31a382ba91f9621508cf28fb4f5d0f2521452369ea2441598d34b2bf
-dist/2025-05-12/clippy-beta-aarch64-pc-windows-msvc.tar.xz=951c9f03a6fe0de1e94ab8f064cfc1b29b06606c38e891c2f9f1c550e9d94678
-dist/2025-05-12/clippy-beta-aarch64-unknown-linux-gnu.tar.gz=1a241694ef544259a3c87bf271b1248ebb6fd32ac35b3ac16154e509b80c6e47
-dist/2025-05-12/clippy-beta-aarch64-unknown-linux-gnu.tar.xz=679c8ed606c22490fb0a5a8503d898e61199e3cd17d9dd7a34c121781ca7306a
-dist/2025-05-12/clippy-beta-aarch64-unknown-linux-musl.tar.gz=26ba8ec943e4f8cfa27afcde06fd34dcf546c3a5c7668acf703a9b962a1977c8
-dist/2025-05-12/clippy-beta-aarch64-unknown-linux-musl.tar.xz=051112fc6bd906c62cf14d2fa9c7f1505540a6aa86ee0b1889e11b1925274c23
-dist/2025-05-12/clippy-beta-arm-unknown-linux-gnueabi.tar.gz=a44d29c794e49742417de03a955922ff3634ad45a5e6b5799c767f3feb2ae7ea
-dist/2025-05-12/clippy-beta-arm-unknown-linux-gnueabi.tar.xz=1650c464df6d87fcf3cea65722a515a1f1625d9e1ad6d27359455ecab849a592
-dist/2025-05-12/clippy-beta-arm-unknown-linux-gnueabihf.tar.gz=1c4f6c22361665705334faf35a0a7c17d55fb3fbd2622721e8cd7c76418cfc41
-dist/2025-05-12/clippy-beta-arm-unknown-linux-gnueabihf.tar.xz=f75400fc72fd358be80cbedefc53a9002fe6cc22637687e941835acb8c5eced0
-dist/2025-05-12/clippy-beta-armv7-unknown-linux-gnueabihf.tar.gz=f1a2db6029e9d881dbfe7c6589873b323358d8317865824705c0cd358fa3ef49
-dist/2025-05-12/clippy-beta-armv7-unknown-linux-gnueabihf.tar.xz=9cc0a2212a36bfb39379008b781304da67c74ab4ce0909da18f8cad50fcbbfd0
-dist/2025-05-12/clippy-beta-i686-pc-windows-gnu.tar.gz=06051eca41cbd1b570725847b4d8b79f29bd20ac06878ef5689167626fd4b137
-dist/2025-05-12/clippy-beta-i686-pc-windows-gnu.tar.xz=857d43d424e718e04714562132802aa5fc9028945a3c40c34508abd165a909c1
-dist/2025-05-12/clippy-beta-i686-pc-windows-msvc.tar.gz=58bf660a2f3ecf4671de4624b12b5a35f1e530d3c16f47eb7e114d1deb1891ad
-dist/2025-05-12/clippy-beta-i686-pc-windows-msvc.tar.xz=5a36ec9ff4e35f1a49775e6657ea4f65543b47ebbb776fa1c60fa7898666de62
-dist/2025-05-12/clippy-beta-i686-unknown-linux-gnu.tar.gz=30df536f3cf6fbea2cf745ca8177f88831ed5b5e25d8fbdeee5f300fb35b97fe
-dist/2025-05-12/clippy-beta-i686-unknown-linux-gnu.tar.xz=a491efcade35834adcbcfa8f08004b6a181a8d8fbe36f6a1bfd8e092443a82ad
-dist/2025-05-12/clippy-beta-loongarch64-unknown-linux-gnu.tar.gz=a16579fb92973f609f0eb215d81e1125ad9dfa9e22d5d869236bbe0a7bf8050c
-dist/2025-05-12/clippy-beta-loongarch64-unknown-linux-gnu.tar.xz=45ff10aa52e6162b015b1a927dd23ef7404fbbec554e5a1b655c085d59a378e7
-dist/2025-05-12/clippy-beta-loongarch64-unknown-linux-musl.tar.gz=37e4ca4776fb278cac2ac05ece43ae569780503d0b122545eebc7a746dca69f3
-dist/2025-05-12/clippy-beta-loongarch64-unknown-linux-musl.tar.xz=9c33b12b9c0a6d94b16a52066e3a1a8a2581db1c7549de002f0d6f4670021f0f
-dist/2025-05-12/clippy-beta-powerpc-unknown-linux-gnu.tar.gz=a7939ed010f6cef23e23e17c7ad905c6c0f4e549c85a8ae38d743232fe8de321
-dist/2025-05-12/clippy-beta-powerpc-unknown-linux-gnu.tar.xz=21046d6fe31c0930e4611a18dcd48f5cacdcf3b64b5d035b4449b8b5af417254
-dist/2025-05-12/clippy-beta-powerpc64-unknown-linux-gnu.tar.gz=a03df872f97472d9a4310c8097042ef80ca859485fdb95ed9bcd853de3cbe9ec
-dist/2025-05-12/clippy-beta-powerpc64-unknown-linux-gnu.tar.xz=925ff3b371f6c4ec871920c5e9fa5ab046f203c0af95f10f0996a750bd125582
-dist/2025-05-12/clippy-beta-powerpc64le-unknown-linux-gnu.tar.gz=5f159a1913f6a5d10b5d5140093c9af4277d8a632db5cc116065a08fc0ff8bb6
-dist/2025-05-12/clippy-beta-powerpc64le-unknown-linux-gnu.tar.xz=a2385ac96c42af4d77eb84ca70931e005aff1dc0e1ba272483ee82a837d96709
-dist/2025-05-12/clippy-beta-powerpc64le-unknown-linux-musl.tar.gz=9c289ed719cd18c8e5b883aeecc03e46f35b6b90d191b4fb0d0b4b6c7fc5073c
-dist/2025-05-12/clippy-beta-powerpc64le-unknown-linux-musl.tar.xz=1a62cf477d5ad2ce4904a4438ab5756f75b894288a7449ae70c9f63d3b7badda
-dist/2025-05-12/clippy-beta-riscv64gc-unknown-linux-gnu.tar.gz=c1abab08e81632db27613f3ac7036d8ffdeaf92e345b345bf2c3535f4d9c16f0
-dist/2025-05-12/clippy-beta-riscv64gc-unknown-linux-gnu.tar.xz=611252f8b142af9a86e511ae783f41cc97104d2e5ec5835c7d5006421ff6207c
-dist/2025-05-12/clippy-beta-s390x-unknown-linux-gnu.tar.gz=d436be0f0f72db3c4933e8e34fcbb71e33b90ddcca58bc4b4360fe22e7a89404
-dist/2025-05-12/clippy-beta-s390x-unknown-linux-gnu.tar.xz=9f8086f13b6f53d44f03bc53fa3d750a9f4dc13b3612b10dba48958f4b61706d
-dist/2025-05-12/clippy-beta-x86_64-apple-darwin.tar.gz=1b4a51c42bcc9e3241ceaceab3fb22bbf8060e9f4c2c55357603c1bf2fbf75f2
-dist/2025-05-12/clippy-beta-x86_64-apple-darwin.tar.xz=42556126bad0e0554dc5464396383c75a1fcb76257249c62ca4e40971129c458
-dist/2025-05-12/clippy-beta-x86_64-pc-windows-gnu.tar.gz=59a2a00a0c4e05cd0900fd119f43d4354b9f6b9df9dd9a9b44a1cfee9c674eb3
-dist/2025-05-12/clippy-beta-x86_64-pc-windows-gnu.tar.xz=35290a11740a2fc0c02d534375ca4ac0392de41f281383d7396179f670ddf309
-dist/2025-05-12/clippy-beta-x86_64-pc-windows-msvc.tar.gz=db01970a436b89d5fe3cb5eb65ea075f7dfd15b649958b35ea8d88835d8fe1c3
-dist/2025-05-12/clippy-beta-x86_64-pc-windows-msvc.tar.xz=9df8c8ed117b2e975bcb0520601c9b4e19e0440b14d9e510d09c9b54b872379f
-dist/2025-05-12/clippy-beta-x86_64-unknown-freebsd.tar.gz=736361d62d33e969bda4cb98ea592ee7128e88c047f05b77cc025c982c27acb6
-dist/2025-05-12/clippy-beta-x86_64-unknown-freebsd.tar.xz=72f50e46dd2697c32b20ac2d0ae9ae2ea10485225dfd41dc9fa4e24d3b61a26e
-dist/2025-05-12/clippy-beta-x86_64-unknown-illumos.tar.gz=4c856630844d01f655dc9855efb3685c2c30fcf199edfe665d9cf4230774ae0d
-dist/2025-05-12/clippy-beta-x86_64-unknown-illumos.tar.xz=70bad50bffa518c4658e44dda7b6723558d68a545511228b97e18efc37a3ad0b
-dist/2025-05-12/clippy-beta-x86_64-unknown-linux-gnu.tar.gz=4c1e0fc35732f19effc50e67f637c57699ed7e846e4201db3897740c1e34a43a
-dist/2025-05-12/clippy-beta-x86_64-unknown-linux-gnu.tar.xz=fe53a5340c93485ac496453752a15222d323755cb20427b29b952b49f317a4bc
-dist/2025-05-12/clippy-beta-x86_64-unknown-linux-musl.tar.gz=c56f80644373fbe9bb87310d26876a86325fccb1756716db30a5bf70293d328c
-dist/2025-05-12/clippy-beta-x86_64-unknown-linux-musl.tar.xz=f4597f7ed6d0def07a32e952330cc964e49d42f84d65eead84192a29978c1a41
-dist/2025-05-12/clippy-beta-x86_64-unknown-netbsd.tar.gz=ecbc80189d470c1cc221360b94964fbd26d52b7583ea065cdd52795a48bf6271
-dist/2025-05-12/clippy-beta-x86_64-unknown-netbsd.tar.xz=f08204b9216fcb127934f2ceefeb7abe4338bb2ab79576a3a2e2077201f521e6
-dist/2025-05-12/rustfmt-nightly-aarch64-apple-darwin.tar.gz=269b22b568f60889c4841feff1c11d9c151d2655d134e966f7344f7affc6db57
-dist/2025-05-12/rustfmt-nightly-aarch64-apple-darwin.tar.xz=474f13aa57c73f4f9e3c63edb9a126ca845e63a376b7b8e35b5c6aa8fb0d9573
-dist/2025-05-12/rustfmt-nightly-aarch64-pc-windows-msvc.tar.gz=9f24753d7abc9aa196a72ac54bb574f5eb375ecd5b2da42d0ed34bf0fb8eb947
-dist/2025-05-12/rustfmt-nightly-aarch64-pc-windows-msvc.tar.xz=daae34864734810ff8ea563db7bf691f6c0fa56b9087fe285f7a3060247ef6e3
-dist/2025-05-12/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.gz=c21f59bc03b8097f066be7bd3a7d0febe873f321583a4c7a9a0cdf5448d92ced
-dist/2025-05-12/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.xz=574fce0d0ff06850db47da008fdc6c6551f2cc459f63f69dcf8edae5e5ff51eb
-dist/2025-05-12/rustfmt-nightly-aarch64-unknown-linux-musl.tar.gz=6379365fb729e0f5d57873ad028f0c2641d60bc19ac5c905a2d1772b6730cb93
-dist/2025-05-12/rustfmt-nightly-aarch64-unknown-linux-musl.tar.xz=a274c20436d31f74b4144f165a2b383297316f1f96b0d89b2b86bbf38e57be98
-dist/2025-05-12/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.gz=03c3270a78c5d62517ec1b5c61414634ad58e5d4afb914f31bdc12ee0893ff2b
-dist/2025-05-12/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.xz=b309c052cdae48b23c2e89dcd7362af97f50181745191dee596ac176c2ade8a0
-dist/2025-05-12/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.gz=300baf318827928f0c824e20ccc8966d3fe9e5b5f62a0d1aeba5feae1d183a11
-dist/2025-05-12/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.xz=09b764e2038499d23b28b8cbdb01c9480f2100a01d864b7f03905bc78412fa00
-dist/2025-05-12/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.gz=47c087899d4155750e71a261a0c93c9f736530d991dfa7e34c1a7bb7f2aedd8b
-dist/2025-05-12/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.xz=7e589aaaac2ab2c1211e5f5e1090b2ce1633f8b8682425aff01afd4dbd25e088
-dist/2025-05-12/rustfmt-nightly-i686-pc-windows-gnu.tar.gz=0169fb75018dd644d7ed842472c04a5c82d46f3bfebe6d49931839809d1824b7
-dist/2025-05-12/rustfmt-nightly-i686-pc-windows-gnu.tar.xz=96f3e288c8ccf073b1ea983ba382e341c8f6664135ad9aed7168bc05cf06ac4e
-dist/2025-05-12/rustfmt-nightly-i686-pc-windows-msvc.tar.gz=29b1f7a4b1454bb1c6af1e720e05bda846725a8e866266a147335920e99e66a9
-dist/2025-05-12/rustfmt-nightly-i686-pc-windows-msvc.tar.xz=71a2f81ff29fd7e4c8dbdb2ce85bebf5e8ea5889cbb41f98fd3c3816918a6a3d
-dist/2025-05-12/rustfmt-nightly-i686-unknown-linux-gnu.tar.gz=ae5458b4c0d58bc3e307c289aa44daf82218aaafc7911dadd4a09f4ca7cf6e12
-dist/2025-05-12/rustfmt-nightly-i686-unknown-linux-gnu.tar.xz=cf19b582a8336aa3f3959803cb24ad4499bc529bd58cd0766e668af5083de93b
-dist/2025-05-12/rustfmt-nightly-loongarch64-unknown-linux-gnu.tar.gz=474a34a9566402e313f5fcfaefe29188a6db1c0bd17caa20f186787267ac8e5d
-dist/2025-05-12/rustfmt-nightly-loongarch64-unknown-linux-gnu.tar.xz=c02f75eaa71f6c4d613a80dc7092d57cd4f6ef8a7de7511711fa818c0612da24
-dist/2025-05-12/rustfmt-nightly-loongarch64-unknown-linux-musl.tar.gz=95b47139ab6e9c16acee5ac78744c3e9ac917a5e811f45adfec4fddd45e98cf3
-dist/2025-05-12/rustfmt-nightly-loongarch64-unknown-linux-musl.tar.xz=fe13340e51d7d81629e03019d375a72874b80f19420c77ea083292a22a9be589
-dist/2025-05-12/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.gz=a95ed14a5bc2f926c2ffb5dfe49813817638154edef7f29522661c57ec2dec09
-dist/2025-05-12/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.xz=d9060c0aa08e0ade2fb54fb5381f0f69dc94166741200b2ed35a46b5d9885036
-dist/2025-05-12/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.gz=060213e707c6b8911517e786b21515e169e062bbbf96302e012a442d260789e1
-dist/2025-05-12/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.xz=f1d4dd54017937490f559a472893fb8a00236b46bf0f57ef9222ec3bbd191004
-dist/2025-05-12/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.gz=38a57b7fac63608992995b3b983643ae213f6fa3d6a1021691334d84a5491542
-dist/2025-05-12/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.xz=f26658ea60a6424707a027b1e36488f99490bce045978c3919c7320638f60d68
-dist/2025-05-12/rustfmt-nightly-powerpc64le-unknown-linux-musl.tar.gz=07fbca58abf5fc57560e20fe7aede77137dd3f2f4cf2a6da11a80eaf6672bed3
-dist/2025-05-12/rustfmt-nightly-powerpc64le-unknown-linux-musl.tar.xz=f56f7bb1091fbb1a8d1583beb586194e5dd526f7a0268b4ebe997e0ce7c9d9cb
-dist/2025-05-12/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.gz=3ec40438a95a086a1c4c522c6ae018393469f605b03d392562fca4926bdf0631
-dist/2025-05-12/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.xz=d7c342edbefe3fc22631961c2aca53cb808bc8f1df17673ec5cafcc56eaf0475
-dist/2025-05-12/rustfmt-nightly-s390x-unknown-linux-gnu.tar.gz=4c1a2aa84e8e1c67a111b9a622b2c6ed96eebcec9752ccc5e940460ce048f22e
-dist/2025-05-12/rustfmt-nightly-s390x-unknown-linux-gnu.tar.xz=e26a0359223ca793d34ac9e4e5731923c4531dcdbf32aa8789bc9d1bda17013f
-dist/2025-05-12/rustfmt-nightly-x86_64-apple-darwin.tar.gz=dbf20af35cbe11baab7ead72ec254717642b01fdf30140589510413058af3e49
-dist/2025-05-12/rustfmt-nightly-x86_64-apple-darwin.tar.xz=7beb25f2df0877ee74231abe03e74a09c6e41a356d0cea27956b2091382dbf47
-dist/2025-05-12/rustfmt-nightly-x86_64-pc-windows-gnu.tar.gz=527d2d68bfd519d49936fd8941a04d787df1edf8c2c3ecc39103d55d1683a970
-dist/2025-05-12/rustfmt-nightly-x86_64-pc-windows-gnu.tar.xz=8744bef9d00d6f7397ef2b1b36971ad7af6389e93b5286ca60feb6137c4f6b10
-dist/2025-05-12/rustfmt-nightly-x86_64-pc-windows-msvc.tar.gz=50f8f2db4f410e60a6cd4ad03a762ea636076d85af05d511f40d2d2ea98bc833
-dist/2025-05-12/rustfmt-nightly-x86_64-pc-windows-msvc.tar.xz=183f8742c505ab1d0488ca915509c1b0558166c6d19d8dc864d0a1686d66a791
-dist/2025-05-12/rustfmt-nightly-x86_64-unknown-freebsd.tar.gz=f042a8c4ef96911b2cc6cc2228ff832229196b4ab5b1b04b05b22b5b9a90649d
-dist/2025-05-12/rustfmt-nightly-x86_64-unknown-freebsd.tar.xz=9b93acd9cb8c8e062f3e47f5415adb8eae67479318b6201bf66119d467b81e11
-dist/2025-05-12/rustfmt-nightly-x86_64-unknown-illumos.tar.gz=fe9073a3bbd3b6513ba0fc38005b8ab1d44052e1bb10c1976bc98a62f8df5934
-dist/2025-05-12/rustfmt-nightly-x86_64-unknown-illumos.tar.xz=4c99f67e351758fe0db0bc7cdfe177018083b9ada2feeee952180b420e2c6ac9
-dist/2025-05-12/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.gz=c5a5702c66ae7de6b7a10d1c8c39af6c973c6eeebbc1fdba3b427c1ec9588756
-dist/2025-05-12/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.xz=8da51f6150fa5c53dead4c3db2c2d7493cc46b36d64b978e605a9d5755dfd779
-dist/2025-05-12/rustfmt-nightly-x86_64-unknown-linux-musl.tar.gz=3d77d2579fcb53a9bb6d942d44353f7b818b10504b64b790ecc3630d8b17a565
-dist/2025-05-12/rustfmt-nightly-x86_64-unknown-linux-musl.tar.xz=7e75748bcb8b25bebeb1b5aeb2afc2fc1c48f38ccff9c624cd002a8e051424b7
-dist/2025-05-12/rustfmt-nightly-x86_64-unknown-netbsd.tar.gz=9c05c902b0db8fd8f8b44d83a95bc8722bb714d333d2a61a2e1ef140092b6d83
-dist/2025-05-12/rustfmt-nightly-x86_64-unknown-netbsd.tar.xz=d614cb69e1484f3653bc148280e7518640ec830ab8f02ddf512206ac265d6746
-dist/2025-05-12/rustc-nightly-aarch64-apple-darwin.tar.gz=ac2c35cd19b85e6356bcdb987031314afbb7e41f26418ddb0d943fc3482245c6
-dist/2025-05-12/rustc-nightly-aarch64-apple-darwin.tar.xz=a3c53f15d7b6f7c7e5f1e55c107663ef102cdb123394bcbe8a8c9c32a7e715f5
-dist/2025-05-12/rustc-nightly-aarch64-pc-windows-msvc.tar.gz=29e3bae16967111ce72d00b931d32410ab526617bf1c88bbf90e4d32825ea7dd
-dist/2025-05-12/rustc-nightly-aarch64-pc-windows-msvc.tar.xz=116103ab4251b366644239f8ef8d7129ae3d9588d768b8e66671497b1fa36c95
-dist/2025-05-12/rustc-nightly-aarch64-unknown-linux-gnu.tar.gz=911acda80c362dd7690e5a4596e166b8ea49425f6dbbfd78ef697e69dc826c85
-dist/2025-05-12/rustc-nightly-aarch64-unknown-linux-gnu.tar.xz=9cabea351ef05117d8cdfae0df334c98b12a99c4191d3e4f382c336c326520dc
-dist/2025-05-12/rustc-nightly-aarch64-unknown-linux-musl.tar.gz=81c9ed04939e8d363e060ef2808bee8dbd63435b111f37325bc8fd2891726560
-dist/2025-05-12/rustc-nightly-aarch64-unknown-linux-musl.tar.xz=a44b2f887aeafd5ff57ff67d8c4eeaa94cb4edd2f7d5912618ee186a4d609c73
-dist/2025-05-12/rustc-nightly-arm-unknown-linux-gnueabi.tar.gz=7a4047a85297d3012c00377241f3daa50b34ddc54d68d67787d76eb45f5db616
-dist/2025-05-12/rustc-nightly-arm-unknown-linux-gnueabi.tar.xz=09acd09fbfa3c43738c43c8c423d3fce6dc4451ca4ee8650ab3392279cfc288a
-dist/2025-05-12/rustc-nightly-arm-unknown-linux-gnueabihf.tar.gz=88ffa28a612cfb661a731dd4feeb6d6fae88d7236469ded88ee74a06a1576a8f
-dist/2025-05-12/rustc-nightly-arm-unknown-linux-gnueabihf.tar.xz=7c5747fb16062a786ffba5d00e1bc0e3c81ccf6154f09e21a6aa5b87c2fc9594
-dist/2025-05-12/rustc-nightly-armv7-unknown-linux-gnueabihf.tar.gz=c1bd5074d4664f0ac8019151aea13e051cf2d89b8bd8fa77b9ed3831a1b7c217
-dist/2025-05-12/rustc-nightly-armv7-unknown-linux-gnueabihf.tar.xz=20fa9e5531e4be0e54af97c8d033722c68d54ef984be3619ad84be6b579d0c73
-dist/2025-05-12/rustc-nightly-i686-pc-windows-gnu.tar.gz=fe7511b5bf7830efeec083d3414e389286ec117b53db0501d5c314eba24e3bdd
-dist/2025-05-12/rustc-nightly-i686-pc-windows-gnu.tar.xz=95677d845a5c7677b951300f17d810301397df022145f16674a58ebb1cd52a56
-dist/2025-05-12/rustc-nightly-i686-pc-windows-msvc.tar.gz=a8f1e4852ffab09aeab1ccc09fff930444871fd3b490e68a1f9ae504c0dce6ed
-dist/2025-05-12/rustc-nightly-i686-pc-windows-msvc.tar.xz=11fd3093a95e379d6472f063bfdccf6f3cf6c44956d68d121adcd1c927812eba
-dist/2025-05-12/rustc-nightly-i686-unknown-linux-gnu.tar.gz=d95876f9a84ebcc97033c81dd07fe8852f0f472db94c074f5029458fec512d2e
-dist/2025-05-12/rustc-nightly-i686-unknown-linux-gnu.tar.xz=766182f4d375138f4871abba6a8b50c3ca342edb7842b6d4bf7162e466cb32fe
-dist/2025-05-12/rustc-nightly-loongarch64-unknown-linux-gnu.tar.gz=58e41cb37fb5b974a78e7891c7aca2786bdf8153ac9cd134b713fc73771017b3
-dist/2025-05-12/rustc-nightly-loongarch64-unknown-linux-gnu.tar.xz=ec6990871579f86c0587a6f7262bb53dd7de3a79a39ca55b994475ad96f20f4f
-dist/2025-05-12/rustc-nightly-loongarch64-unknown-linux-musl.tar.gz=39b7b026e95bdee7eba78804d2f8f3703a141ff37c24ac636deb755fc669f081
-dist/2025-05-12/rustc-nightly-loongarch64-unknown-linux-musl.tar.xz=0b066061a1a55836b3b81667c0c35d864055578370f00365db7226fc41f0f11c
-dist/2025-05-12/rustc-nightly-powerpc-unknown-linux-gnu.tar.gz=040b0718e4f460bb6136628ce24dca390608671b609d8e222e4ccbfedff43d6e
-dist/2025-05-12/rustc-nightly-powerpc-unknown-linux-gnu.tar.xz=f9206ff2fad2acaab1b3a30e1d7a634384533329f71ceed5ef2fce0bd288bd43
-dist/2025-05-12/rustc-nightly-powerpc64-unknown-linux-gnu.tar.gz=9c6c12d9d5486c4d26d1f7d9a61625a20e3e7703af79195ec4cb7e7e22358f4e
-dist/2025-05-12/rustc-nightly-powerpc64-unknown-linux-gnu.tar.xz=2cace3cec2973aa8f93f1d5bbe8cdcb36134fc2313b0131c51d2d4885bb18492
-dist/2025-05-12/rustc-nightly-powerpc64le-unknown-linux-gnu.tar.gz=60adf24efc4a8207709ccb39bf45ff5fb08c4a853de816c239a2aec795c22e46
-dist/2025-05-12/rustc-nightly-powerpc64le-unknown-linux-gnu.tar.xz=038e9220451a497885e7886a293986b37b83979a4a6f70b112d42245f9e4a924
-dist/2025-05-12/rustc-nightly-powerpc64le-unknown-linux-musl.tar.gz=66d700e4a734f1a1a4f2c5d9125fee2c20e400b85a4a72ec4d6963f7d438a591
-dist/2025-05-12/rustc-nightly-powerpc64le-unknown-linux-musl.tar.xz=1198a73d12b6f556a5016a2181e1c95adf929f24df1be5a17b1ff8cf6635656f
-dist/2025-05-12/rustc-nightly-riscv64gc-unknown-linux-gnu.tar.gz=e1b12d459eeed0496a93db5ca6962bd15bd307a400e8bb870623d20479d75aa0
-dist/2025-05-12/rustc-nightly-riscv64gc-unknown-linux-gnu.tar.xz=2339af50b563056c4ad58cff24b1d59198e71e06c85f1860461e9384a0aeac0a
-dist/2025-05-12/rustc-nightly-s390x-unknown-linux-gnu.tar.gz=4977999e15a893215a7f86ad55e195249f63c416b7a0bee3423950575a952d1e
-dist/2025-05-12/rustc-nightly-s390x-unknown-linux-gnu.tar.xz=5745e2dd22c39abd35b19117b5514ba383058c057265b3003cda3da4aadfa18b
-dist/2025-05-12/rustc-nightly-x86_64-apple-darwin.tar.gz=008b5b604e3fb66026eca67f29ed65262f85a2e305286a5ad11642edc8eaee2a
-dist/2025-05-12/rustc-nightly-x86_64-apple-darwin.tar.xz=b2c071998e209e6b4989eae799938268dee9d8ada531956d41147e747128f328
-dist/2025-05-12/rustc-nightly-x86_64-pc-windows-gnu.tar.gz=8791712c5513a077d2936dd26c7157b12fd8b4bfc93180f97273eb534461837f
-dist/2025-05-12/rustc-nightly-x86_64-pc-windows-gnu.tar.xz=02fd232fa95660aa19665089a191fe350d0dfc44fcee4436be28fad82324fd00
-dist/2025-05-12/rustc-nightly-x86_64-pc-windows-msvc.tar.gz=9f7d67cadca7abf25c5445a9f7c911a3e0a2db2e52c088cc6833e40b52bef0de
-dist/2025-05-12/rustc-nightly-x86_64-pc-windows-msvc.tar.xz=ef2853ac4f2a5c6932f16768fb1df277b9edb8d91615869b8cfa574d6bda026a
-dist/2025-05-12/rustc-nightly-x86_64-unknown-freebsd.tar.gz=117efae53fc69e481498c1f268bbb12e382f479dc6859ad04fdfc4a84659d677
-dist/2025-05-12/rustc-nightly-x86_64-unknown-freebsd.tar.xz=14b67230c06ed6ec7597e31c6b7385782ab6a1f6bc723c5d2f171defa02c669d
-dist/2025-05-12/rustc-nightly-x86_64-unknown-illumos.tar.gz=881a6c5ff0222eaca1fa278fb517963b30f51714c3724956bb2d29c142af0add
-dist/2025-05-12/rustc-nightly-x86_64-unknown-illumos.tar.xz=3e708bcafdf8da1ceb92ad0e27407ea210144d91e30ba2486bd6758085153caf
-dist/2025-05-12/rustc-nightly-x86_64-unknown-linux-gnu.tar.gz=b264a719d90f6842e3cbc8dc7d74ec356328f0a94cca279795ada5f4b22c54ed
-dist/2025-05-12/rustc-nightly-x86_64-unknown-linux-gnu.tar.xz=fbe22ac8c9995feac7b13f92b8d4c16fc1cdfb4a15c06e127420762db0198443
-dist/2025-05-12/rustc-nightly-x86_64-unknown-linux-musl.tar.gz=48cf6d33fdba4e38dcc19710efd24eb863fe13bbca634e0ca02fc1647255bd6a
-dist/2025-05-12/rustc-nightly-x86_64-unknown-linux-musl.tar.xz=7767dd1b6baf7065dfc74b4e9ce4c200616294ecd664243c6fe756522fb4a328
-dist/2025-05-12/rustc-nightly-x86_64-unknown-netbsd.tar.gz=bde7b39870fbce418257278ae56159af3f80f1688efd01d6d52b16127fd0b64a
-dist/2025-05-12/rustc-nightly-x86_64-unknown-netbsd.tar.xz=6018c06dda8f5a0ff5ef7754bf2e8692b2dfd48be525d896261aea27d682f4e5
+dist/2025-05-26/rustc-beta-aarch64-apple-darwin.tar.gz=4dbdbac9216bb9a1e277f02d1fbbe6125709456a26440d0b8b852f615c8d0e5e
+dist/2025-05-26/rustc-beta-aarch64-apple-darwin.tar.xz=14cfac4d029e4960d3d822d2a02fd5a604b4d545ccf9b2a6c8ce7d1a7fffd2a2
+dist/2025-05-26/rustc-beta-aarch64-pc-windows-msvc.tar.gz=af901ff979cb9ec448ca8d5ae8dd70987b015614265dc7d8c5fbcf0c7d7f06f1
+dist/2025-05-26/rustc-beta-aarch64-pc-windows-msvc.tar.xz=afe5ac02574f8b996a8eb7dd7e95d717655da8a49f652694a31f52fdb39eb044
+dist/2025-05-26/rustc-beta-aarch64-unknown-linux-gnu.tar.gz=f2eaa46be24e7d5504628f05f799e58dd993d8ac3158328c238b834c14b5ad33
+dist/2025-05-26/rustc-beta-aarch64-unknown-linux-gnu.tar.xz=2c4a949aee410d9ed6602c3f95d58895fb0051fe7a3f1d0abd585f3d952a31d7
+dist/2025-05-26/rustc-beta-aarch64-unknown-linux-musl.tar.gz=e8aec1f37de24b6532056f5e3be512f5ddde86e536a9b68dab0baac76df36778
+dist/2025-05-26/rustc-beta-aarch64-unknown-linux-musl.tar.xz=64457bd80c7575c0792a5b998d407dea844d38d102560d1fce824ac8241efa7c
+dist/2025-05-26/rustc-beta-arm-unknown-linux-gnueabi.tar.gz=fd5dac6844caaccc15f29bea41b81e9d271f4408057580a86fdd7f5a032f4233
+dist/2025-05-26/rustc-beta-arm-unknown-linux-gnueabi.tar.xz=3095a4442404eb8e958ab9205fca9cfff13ca52cc18602fb322b410d497e6849
+dist/2025-05-26/rustc-beta-arm-unknown-linux-gnueabihf.tar.gz=d02a4cd721a8fa1f82f64bd9953f4867e1628dbb9e223e04c3ab7954f7eec055
+dist/2025-05-26/rustc-beta-arm-unknown-linux-gnueabihf.tar.xz=84c1a1e5e8dfb796c1c6b643329dfb65f53df372455fc70f4f3abd5dc8f614d8
+dist/2025-05-26/rustc-beta-armv7-unknown-linux-gnueabihf.tar.gz=86b675fa61c7cfd494e7e6ed514e9ccf6beab425238c236f8425052df7800724
+dist/2025-05-26/rustc-beta-armv7-unknown-linux-gnueabihf.tar.xz=078b1d00b8c6a37823d724b7993e7b2bcc73f433230a25bcbeb191eb2a0e8714
+dist/2025-05-26/rustc-beta-i686-pc-windows-gnu.tar.gz=08b47eca900f48b51ad4da927dca1a29b761e4e62b8e8eed7486cb150101afe1
+dist/2025-05-26/rustc-beta-i686-pc-windows-gnu.tar.xz=da0701faa92f4cfab71a78e707068d4840fb79393a00b14984a2bb37c24d99f5
+dist/2025-05-26/rustc-beta-i686-pc-windows-msvc.tar.gz=35de6670fbf76f3455be1630c8a3f628baea46473a69f0281e0dee20121b44be
+dist/2025-05-26/rustc-beta-i686-pc-windows-msvc.tar.xz=45bd16224593ae586358343ceb5c845af01b053800bc0dd9ddb3fca352abeb09
+dist/2025-05-26/rustc-beta-i686-unknown-linux-gnu.tar.gz=1de0f032ca7755c2b2c7d79d048bb8e25279a728619b9bec65f8e373ef58ff0f
+dist/2025-05-26/rustc-beta-i686-unknown-linux-gnu.tar.xz=00506ca8eeca547c844c48165e80afc71fa5bc9ad5734c2b90ebd9d6184540f5
+dist/2025-05-26/rustc-beta-loongarch64-unknown-linux-gnu.tar.gz=3067489dbd5bd1713e0d256a13061f484d662b4dad46e502a0d7507db69506c4
+dist/2025-05-26/rustc-beta-loongarch64-unknown-linux-gnu.tar.xz=09337bbecb0933162c1dcd5c85a5fa430b85c4b541b70f01ba77a82d5e64cbdb
+dist/2025-05-26/rustc-beta-loongarch64-unknown-linux-musl.tar.gz=aac2f6ca44fd4541ec6acdb658631e7907365f27b874c5cb14a15bd1fd23ee78
+dist/2025-05-26/rustc-beta-loongarch64-unknown-linux-musl.tar.xz=51505bc92660d2e206ea35218b682e23155f5d006ab200cbb1398f6a23c63fcf
+dist/2025-05-26/rustc-beta-powerpc-unknown-linux-gnu.tar.gz=35e4fa7207810cd8490e3d7ba181356d55e946d740a7a4f36e18d38e8a3b35a2
+dist/2025-05-26/rustc-beta-powerpc-unknown-linux-gnu.tar.xz=4cc9f12877323f5ebcf7f3d2878800dbc4d0930615b9baeb40e0a2824536d5d9
+dist/2025-05-26/rustc-beta-powerpc64-unknown-linux-gnu.tar.gz=9d8b217d6733c5f0375eaf6a38aa1a1b596ac5ef979f9440ff51ec7e7df25b08
+dist/2025-05-26/rustc-beta-powerpc64-unknown-linux-gnu.tar.xz=b32b303840f35d6a2f42751cada1f833b4c55b7d83634b1cc6d469902539d168
+dist/2025-05-26/rustc-beta-powerpc64le-unknown-linux-gnu.tar.gz=2fb8b2e97e7d1adea24302e2d2cf47b04200c6ad0299498d07b4ab59b6d4df08
+dist/2025-05-26/rustc-beta-powerpc64le-unknown-linux-gnu.tar.xz=33c763eeedd8f3a3ca885f94ade5c3a2355a479a0186ddae33e4cb068529de72
+dist/2025-05-26/rustc-beta-powerpc64le-unknown-linux-musl.tar.gz=6f59fecc08d6e84616bb89c2ee73b2f285c4bb2ebdfb122538c49b2fda41d1f9
+dist/2025-05-26/rustc-beta-powerpc64le-unknown-linux-musl.tar.xz=4723d0b463897004959e91675aa50aff0c9a9beca943267d77d11d5beee257cb
+dist/2025-05-26/rustc-beta-riscv64gc-unknown-linux-gnu.tar.gz=96a0400a43b8bc948619b51a9b8dbe778584b4225baf11f97bb59a443dfad1bb
+dist/2025-05-26/rustc-beta-riscv64gc-unknown-linux-gnu.tar.xz=cee9ff6682f8c87d5b81082dd6dd7eea26c59c246ef34c70c934b07a2d520817
+dist/2025-05-26/rustc-beta-s390x-unknown-linux-gnu.tar.gz=fa4d770e564aa0863825d5111a4b6c01d8486c65e8b9ef06db25ef778a448813
+dist/2025-05-26/rustc-beta-s390x-unknown-linux-gnu.tar.xz=945070094b80ac73cb013d3f556767caf6437258121f76921227e44d18249678
+dist/2025-05-26/rustc-beta-x86_64-apple-darwin.tar.gz=cf87e17e8f2fd18d9146671a393f31ab40ccfaf4c781bb81cdf02dff8bab5435
+dist/2025-05-26/rustc-beta-x86_64-apple-darwin.tar.xz=7cf73955adfb107f454829d3503d6cf91430e4cf5c4640466073c2c0f8a42732
+dist/2025-05-26/rustc-beta-x86_64-pc-windows-gnu.tar.gz=12b7528b31d971ccd36a44fff62ccc377dfa322a22af85fbcc7dcf2c8f2e0539
+dist/2025-05-26/rustc-beta-x86_64-pc-windows-gnu.tar.xz=21a305e0b085d73db5d79dabb61e1aad213b623f12708f94ff448a2db60d7651
+dist/2025-05-26/rustc-beta-x86_64-pc-windows-msvc.tar.gz=444aa1eea6824d1b73c0f653a2703806bd04154da160f96b9700c39b9e201dc3
+dist/2025-05-26/rustc-beta-x86_64-pc-windows-msvc.tar.xz=16c6000c46bab4f46ec2084d7e920d2099b8759870057e62bf0e8df8eb4ccb9f
+dist/2025-05-26/rustc-beta-x86_64-unknown-freebsd.tar.gz=6ad9c67484aa6598c4f0f70799980f57e4749560306ce1190dcb38476006247d
+dist/2025-05-26/rustc-beta-x86_64-unknown-freebsd.tar.xz=b8f921568dbca553484936adb267d384b8ce6bfd40efa0b54d22cd98a6638c43
+dist/2025-05-26/rustc-beta-x86_64-unknown-illumos.tar.gz=14083e187d62529058dc0de8657024f5dc2ac5af37986053fc21f2334e1217af
+dist/2025-05-26/rustc-beta-x86_64-unknown-illumos.tar.xz=2410d5423581ec2d205a47bfeb3c95bf3071303b5b71343254492d53fa27cd48
+dist/2025-05-26/rustc-beta-x86_64-unknown-linux-gnu.tar.gz=6561e72c72b5a2a10ef97632c0af2ce8112fe0faf6d12d83da0ec9f0b347b88f
+dist/2025-05-26/rustc-beta-x86_64-unknown-linux-gnu.tar.xz=14b944631444b666019e0c2f3590b78b3de3dcd499c0f7254dd22a95703e8585
+dist/2025-05-26/rustc-beta-x86_64-unknown-linux-musl.tar.gz=cd09f6ef2c26b2f192cf1a05badd3603e8cab4141e120ec98c1afbcda7036aa5
+dist/2025-05-26/rustc-beta-x86_64-unknown-linux-musl.tar.xz=53745c050956b886e5e3f523b1a77f40c6c73c1df867505cb9f1ec2cb5026f56
+dist/2025-05-26/rustc-beta-x86_64-unknown-netbsd.tar.gz=d88ccdea31b269ad513cd8106c0aec60124ee1ec50c839dbc7218dc1d2b80e0a
+dist/2025-05-26/rustc-beta-x86_64-unknown-netbsd.tar.xz=d10add7b925f1492d2b1c9ecd76df2065bac118fa6a27fde7b73d5ec55f30c0c
+dist/2025-05-26/rust-std-beta-aarch64-apple-darwin.tar.gz=4076b5062f1e3f098c0b5ce5cacbaed784afcae6f7db740c0939fcf3a58025e6
+dist/2025-05-26/rust-std-beta-aarch64-apple-darwin.tar.xz=91c94ea57ca9eebf103d89532c6b1b24f3a2529f3a755b1c29ae0897b759dec6
+dist/2025-05-26/rust-std-beta-aarch64-apple-ios.tar.gz=8b89d32f731c103945efedaf2d9050d96e525d50f066239175f629cc0e3b944c
+dist/2025-05-26/rust-std-beta-aarch64-apple-ios.tar.xz=b139ea399a96514732007ba26488cc6f75cd86e710938638dc3b1c7913a8b103
+dist/2025-05-26/rust-std-beta-aarch64-apple-ios-macabi.tar.gz=7bb6dd559ef08d5e8bbfee75243eca8760d411f952ff646356ce4fe74564dc2a
+dist/2025-05-26/rust-std-beta-aarch64-apple-ios-macabi.tar.xz=c17c372f13bddd9d0629fc1bab0dac6004f7356752db20b196da0e46860b174d
+dist/2025-05-26/rust-std-beta-aarch64-apple-ios-sim.tar.gz=a2a01f111d234d89b820591428b036cc6de2b74e6c0e96c32211b085e537b4f6
+dist/2025-05-26/rust-std-beta-aarch64-apple-ios-sim.tar.xz=06380c88a781e584feea822c91b1b6f98412ed5699d4d00d65e5ef7075dbf4c4
+dist/2025-05-26/rust-std-beta-aarch64-linux-android.tar.gz=1ab07c597044c1eed2224aa72893e14055494d8fcf0e746426578055ee881087
+dist/2025-05-26/rust-std-beta-aarch64-linux-android.tar.xz=c55be970bcde2866cb2d66830476cd7fd52692a791fbe3f198e84913a4247a4b
+dist/2025-05-26/rust-std-beta-aarch64-pc-windows-gnullvm.tar.gz=7445b8979d6d325a1a6714e28048ce965159b7fa326c9b7d663c771129f81a7b
+dist/2025-05-26/rust-std-beta-aarch64-pc-windows-gnullvm.tar.xz=f3fe861b5d81b54c7861663519324a5d305f3300c733cb7f146b6a93770fb73b
+dist/2025-05-26/rust-std-beta-aarch64-pc-windows-msvc.tar.gz=57be8b656ae0f4fa9164803155c9af5eafdd961bac752ff3833e5ceba4accb18
+dist/2025-05-26/rust-std-beta-aarch64-pc-windows-msvc.tar.xz=e64807cbdf82117a127d85a35a1303683dbe3c95366bf469c13a2781ed66916b
+dist/2025-05-26/rust-std-beta-aarch64-unknown-fuchsia.tar.gz=d8d4737d031170d5c6f8bb1aede6c863a3ad6c32007de2e1b7ff03242710ab17
+dist/2025-05-26/rust-std-beta-aarch64-unknown-fuchsia.tar.xz=27998ee47c29ba860a5c56155332091275e7e9669e035fcf11a02c9089b6e8f2
+dist/2025-05-26/rust-std-beta-aarch64-unknown-linux-gnu.tar.gz=9dc717d80d91e833580748c831c2a80bca2f8d7bce9af51d21f0375c44cce395
+dist/2025-05-26/rust-std-beta-aarch64-unknown-linux-gnu.tar.xz=88ffb04366bc06c331113026ea64b04ce970f01f13a0e80736fd59676e4e974a
+dist/2025-05-26/rust-std-beta-aarch64-unknown-linux-musl.tar.gz=5ac4a726e875af3387a2214f722b676e21e3d0afbfbcf1969107c34c6eeb1706
+dist/2025-05-26/rust-std-beta-aarch64-unknown-linux-musl.tar.xz=7fe9cd0d76f9c4778d53b5fba083616ac06d04b622e9e783e3e0fd3e0d3756e8
+dist/2025-05-26/rust-std-beta-aarch64-unknown-linux-ohos.tar.gz=5813b23bccf3fe10ec2ab540149bed4739668d9f9b198a476300e50e53721d52
+dist/2025-05-26/rust-std-beta-aarch64-unknown-linux-ohos.tar.xz=383a1758e3f2f1d20b23b8095f3772f79ea5377312602cd577a2b047ed062115
+dist/2025-05-26/rust-std-beta-aarch64-unknown-none.tar.gz=3589b1e3c4367b369050062e9df8838a797059056c98662e47d1cf71ecdcd787
+dist/2025-05-26/rust-std-beta-aarch64-unknown-none.tar.xz=47e290959699c9bc9093cd6603bf3357492ef7a05a5c2335393d41ef94955c30
+dist/2025-05-26/rust-std-beta-aarch64-unknown-none-softfloat.tar.gz=e690ad47757a726cfe621e936dd0ac76d96dd4b838ba3e5dd582565d5b2c3618
+dist/2025-05-26/rust-std-beta-aarch64-unknown-none-softfloat.tar.xz=2d17e86eaaddc93e81b3bd39d3faeed3ccb1765a9a13144d4bab726d384f8eba
+dist/2025-05-26/rust-std-beta-aarch64-unknown-uefi.tar.gz=a5f8b8e8ee3859d877430760132180ef956e597de3ab539e980aa48c937e3e10
+dist/2025-05-26/rust-std-beta-aarch64-unknown-uefi.tar.xz=225b50bb3500d46291bdf877cdce57d8bf8133f1302b98c3b8d07d34a91cfadc
+dist/2025-05-26/rust-std-beta-arm-linux-androideabi.tar.gz=aa93b2e198a1ea5f586851ecde2b1fc56a0e28e2c16e7210cd77b4357e327196
+dist/2025-05-26/rust-std-beta-arm-linux-androideabi.tar.xz=00e020d2654c6324b6c8070c9ac32b0838470ad74df711ea7c9940a4bdcbb71f
+dist/2025-05-26/rust-std-beta-arm-unknown-linux-gnueabi.tar.gz=c0ed57ac290b57f654419e35f7950c6b2b2594638bfca5a060a49dff6febd2de
+dist/2025-05-26/rust-std-beta-arm-unknown-linux-gnueabi.tar.xz=bcb7a661e83d7973ac0cf9ead4588595cbcf39e71867d1e2fb3e6e94f2506d39
+dist/2025-05-26/rust-std-beta-arm-unknown-linux-gnueabihf.tar.gz=baf206be5648992a7280836ed7520b5fd6ca59a28d9aecfbf3769022ececc753
+dist/2025-05-26/rust-std-beta-arm-unknown-linux-gnueabihf.tar.xz=a86cb2309e93b7a0ff92199e47e0a36f192221eb376966b1e4a49c8d5d5de7bd
+dist/2025-05-26/rust-std-beta-arm-unknown-linux-musleabi.tar.gz=703b6baab5a33e6ed1acaad52781c1779146e1fa5d5974d19d354dc2279ccec6
+dist/2025-05-26/rust-std-beta-arm-unknown-linux-musleabi.tar.xz=55e56cda5e2af49b0ccab4baeb0e8051c416c0321832742609edde9b1ebae8ee
+dist/2025-05-26/rust-std-beta-arm-unknown-linux-musleabihf.tar.gz=7080221a8911393a012306c934043df6aa4d483411c90ca275d2539704d38120
+dist/2025-05-26/rust-std-beta-arm-unknown-linux-musleabihf.tar.xz=8d9ed7e57a37f328aeb4004f043887edd980e7ac0df8ff714566b0bf474bce99
+dist/2025-05-26/rust-std-beta-arm64ec-pc-windows-msvc.tar.gz=85cd1a37bc2977c116264a6e84f2c578c7a698e26bf7bd99e0713b14ec6c74c5
+dist/2025-05-26/rust-std-beta-arm64ec-pc-windows-msvc.tar.xz=6ee7ea565266040310050a4cf3e2afb1e85f956e0ad54a9642291949e1b376bc
+dist/2025-05-26/rust-std-beta-armebv7r-none-eabi.tar.gz=8c41876321a8bec594d028460c93396786739ed82f79ed8703cf54dfc1e7d51b
+dist/2025-05-26/rust-std-beta-armebv7r-none-eabi.tar.xz=fb1a88a048e1945dc2bb84aa47e027455c5a94acf416865c5ef26c6a1616414f
+dist/2025-05-26/rust-std-beta-armebv7r-none-eabihf.tar.gz=61561a8324bced38f5ee6c1c65348750162655315ddb5eb0f0142a48872faa8c
+dist/2025-05-26/rust-std-beta-armebv7r-none-eabihf.tar.xz=3e57bdf2dfb8cbcdd4b4f7e2523cd7946dd0d64d0ee17cf794b5a04dab26a46b
+dist/2025-05-26/rust-std-beta-armv5te-unknown-linux-gnueabi.tar.gz=c2586abead3190b936f1cdb46c472ee4c4b6bdfeb9c33165765922d3da0151a0
+dist/2025-05-26/rust-std-beta-armv5te-unknown-linux-gnueabi.tar.xz=24a64cbdabd8074219f7a27f266f695109bcd7fc3646cc78652cf2f3bc2ea099
+dist/2025-05-26/rust-std-beta-armv5te-unknown-linux-musleabi.tar.gz=a6b7e5ec522eb29582c7ca2d9a2a79f1658058c4db6b0442ccfae40e1403ff07
+dist/2025-05-26/rust-std-beta-armv5te-unknown-linux-musleabi.tar.xz=94f88e141605997ae9578b062de3f750761648847d0ed6fd18394d8dbb81afff
+dist/2025-05-26/rust-std-beta-armv7-linux-androideabi.tar.gz=e50086fac3b8e433d1a59724349122bde2172bc22db1175c7826635d978973c0
+dist/2025-05-26/rust-std-beta-armv7-linux-androideabi.tar.xz=2700b25ce1e6db9eadd2b3f63582fc3759963449781799216239b9e2daa9e51b
+dist/2025-05-26/rust-std-beta-armv7-unknown-linux-gnueabi.tar.gz=e507fd70d155f17fc3cd5e1b38b97a871d51090d4dd7069366d3e3e2a48c0355
+dist/2025-05-26/rust-std-beta-armv7-unknown-linux-gnueabi.tar.xz=8988863479cb0280851e1765de2810eebcfc1592100b052e88c51386a88c4c87
+dist/2025-05-26/rust-std-beta-armv7-unknown-linux-gnueabihf.tar.gz=519cfee0178123e15bea3544113ac3f4914a72fd619fdf11044ccc1b8b31c848
+dist/2025-05-26/rust-std-beta-armv7-unknown-linux-gnueabihf.tar.xz=5cf09c2f66482863ca9586782f56aa453c3fbe8ab48d80c18d5570b1d7a80455
+dist/2025-05-26/rust-std-beta-armv7-unknown-linux-musleabi.tar.gz=9949d9684b83610bcba9fd91cc66587d6216dc850cc7b6413a7dc0f80dc4ca2b
+dist/2025-05-26/rust-std-beta-armv7-unknown-linux-musleabi.tar.xz=cd87009d6362cc5777a664e537261227fda510a5e9ac1080a42b0f2fa7b4d364
+dist/2025-05-26/rust-std-beta-armv7-unknown-linux-musleabihf.tar.gz=a9a5280fc64bcb40dbd43f3fae1ee01dfffb06d4bbf1a635b79b923343f97060
+dist/2025-05-26/rust-std-beta-armv7-unknown-linux-musleabihf.tar.xz=bf1e9ef03fc1d727b59ffcd991c207c503db884b14134154ff674b6435dd7c92
+dist/2025-05-26/rust-std-beta-armv7-unknown-linux-ohos.tar.gz=9171f328fc67817f3f2e10209e0122ec7e9f0138ad8ffb4b19b64d21a72b9414
+dist/2025-05-26/rust-std-beta-armv7-unknown-linux-ohos.tar.xz=9d9974ccdd87fb741a568ca8966e21a044f8c40415b4e58bcf359605c6c3d8fb
+dist/2025-05-26/rust-std-beta-armv7a-none-eabi.tar.gz=402f7b7b4c132ec6a1d51c0528608291a423e16090b9f4327e447fdef5d8e771
+dist/2025-05-26/rust-std-beta-armv7a-none-eabi.tar.xz=9a8d857299c24a54a5c49b25d5b07bdd9eb77b4a4be853d6d12e5df4ac404c56
+dist/2025-05-26/rust-std-beta-armv7r-none-eabi.tar.gz=c8fc641d53bc04751d16283d50696ade8925e22d530cdd4f97facd7e2e4f878c
+dist/2025-05-26/rust-std-beta-armv7r-none-eabi.tar.xz=4773a4a02fa088d3c4231695cc698edeef39c2a0ac3f4d3a0eb272d7b8663705
+dist/2025-05-26/rust-std-beta-armv7r-none-eabihf.tar.gz=4ffc1f544f164f5e4a803fb9aacff693e00abcead950bde2d7065739e189058a
+dist/2025-05-26/rust-std-beta-armv7r-none-eabihf.tar.xz=e64d238b9468ecc3df0e3a20cbc0c2b3bd5a12500fad4b7194382106ee5c4aa3
+dist/2025-05-26/rust-std-beta-i586-unknown-linux-gnu.tar.gz=82ac2e07233a629ff1ea556be728fb1617ce085f5909ae3f3b9d8a792f73baca
+dist/2025-05-26/rust-std-beta-i586-unknown-linux-gnu.tar.xz=2c54755349f8d94511b15b29b527533be186f6865ee1b2022e5345f42b00f5bf
+dist/2025-05-26/rust-std-beta-i586-unknown-linux-musl.tar.gz=5debce1f9edbbbf0b8e2e8055525296d2d7c4a14bf561c7bc05e7eb953b5a034
+dist/2025-05-26/rust-std-beta-i586-unknown-linux-musl.tar.xz=e559611ce05ba79894c4e3bd9066701ea851708ca44c0189c93607fe8721640a
+dist/2025-05-26/rust-std-beta-i686-linux-android.tar.gz=17be4d733c597bc7ff5aefe1b5944df0d2f3f2274773f2691e863fcf18877251
+dist/2025-05-26/rust-std-beta-i686-linux-android.tar.xz=2603b3e9fa2b8a2f769ea3558037e4a20b1bd13101c518f05a5800935bb5b02b
+dist/2025-05-26/rust-std-beta-i686-pc-windows-gnu.tar.gz=3c2c9283b1fb0196bfedd8f87f1aaf00dbcadd52ca8fb40382262f86e21701d9
+dist/2025-05-26/rust-std-beta-i686-pc-windows-gnu.tar.xz=3067d576128325449174c9220d10c543644e94d6045764e32bfccd30cd94e94b
+dist/2025-05-26/rust-std-beta-i686-pc-windows-gnullvm.tar.gz=6df448b2a49f2f9f3f4fd0cb0ef758f31f00fbf2008b4a9ae2a1cc5818bbb21c
+dist/2025-05-26/rust-std-beta-i686-pc-windows-gnullvm.tar.xz=537a695b2377b1aa4ed31970b8170ddc575c18c180faec5602febe71bc44088d
+dist/2025-05-26/rust-std-beta-i686-pc-windows-msvc.tar.gz=d45afe32951d926702d62d5a94b5343c3cd2f1d04497af3412dc6d1ccb97be05
+dist/2025-05-26/rust-std-beta-i686-pc-windows-msvc.tar.xz=bd8a25921b63d3d4fe13219422a324a538a08284dac681153d960cd25fd02c6c
+dist/2025-05-26/rust-std-beta-i686-unknown-freebsd.tar.gz=e8ad2a8eae371b8a99251bc3337732f3e47457a8d740a9609f96206291589f43
+dist/2025-05-26/rust-std-beta-i686-unknown-freebsd.tar.xz=e2edeb9636cab8ba8489d28e829c039d4e547ccdbfd4023f98943341f5cad96c
+dist/2025-05-26/rust-std-beta-i686-unknown-linux-gnu.tar.gz=9b319357a2c6d75d0140bad5241a72e4d858e06962c024414449299f83bce9b4
+dist/2025-05-26/rust-std-beta-i686-unknown-linux-gnu.tar.xz=b4447663123e42a950943829f661283d6b36f3da14750c811d6704a2edc64b40
+dist/2025-05-26/rust-std-beta-i686-unknown-linux-musl.tar.gz=4391070bdb67171c4063df3d801dc66e16c097165873c5c219659e1e706028fb
+dist/2025-05-26/rust-std-beta-i686-unknown-linux-musl.tar.xz=48e566d549dff7bde2a1cb07c55ee0a2537147f66e4ca8a7bc9ac9ebe104de28
+dist/2025-05-26/rust-std-beta-i686-unknown-uefi.tar.gz=3176685b3b5b3d0f44655f5449b328ff8c2e4a577d1076a2692f2e7062004e3d
+dist/2025-05-26/rust-std-beta-i686-unknown-uefi.tar.xz=2c0983eaec9d5cca76fdf0fceb3461960e5bcb162c2409169d0c6ddfc5497f8a
+dist/2025-05-26/rust-std-beta-loongarch64-unknown-linux-gnu.tar.gz=17e49779ef3931acbc2828a5a674e1d9032f08ca6166cb62a9ba7dc156b06ee8
+dist/2025-05-26/rust-std-beta-loongarch64-unknown-linux-gnu.tar.xz=7411b776b6fb10d0a10e3de19183caeb9980f523aa014a5b320bb4422f2301a8
+dist/2025-05-26/rust-std-beta-loongarch64-unknown-linux-musl.tar.gz=1a54d2d8b31a84693738a896068e38506b9d8e94f660368c6674ca66d38fee89
+dist/2025-05-26/rust-std-beta-loongarch64-unknown-linux-musl.tar.xz=1023907e072bf083168497dea8801544d2f407cdba1ad3157977032c92e7c4d8
+dist/2025-05-26/rust-std-beta-loongarch64-unknown-none.tar.gz=86135dbb69909d33a0d6bf0caeb35f190299f594b062238e3d18ec7ffab26150
+dist/2025-05-26/rust-std-beta-loongarch64-unknown-none.tar.xz=3e9733daceb421f6a2e00a1c8d7ba2ad87332127ca0fedfc391bd0715836da2f
+dist/2025-05-26/rust-std-beta-loongarch64-unknown-none-softfloat.tar.gz=6190b439b569ef1a5aa832445ac60bb5b4ef605ff8f41a0ad1cdc5f5cb0de28b
+dist/2025-05-26/rust-std-beta-loongarch64-unknown-none-softfloat.tar.xz=8e5a7224d8abd8010a4278f7e767aecdcde7060ffb16e0a5c8de579c5d86e21b
+dist/2025-05-26/rust-std-beta-nvptx64-nvidia-cuda.tar.gz=2006ea99dcecccabf97d74f3f582f8a29c4e69caf27fa9a689a28702a6d9b1ad
+dist/2025-05-26/rust-std-beta-nvptx64-nvidia-cuda.tar.xz=7baffc71f0e9279439775b95280206411ef04bea7eb4ad38096a11a38e38dd47
+dist/2025-05-26/rust-std-beta-powerpc-unknown-linux-gnu.tar.gz=9650a6a1812492df104c0df20c5db422678e2f7a84e33a83aedf1d9c602369d6
+dist/2025-05-26/rust-std-beta-powerpc-unknown-linux-gnu.tar.xz=4a265f557aca1b2cc3d377be693bf9fe90c4b0ced99e77a406849aaaf3ad7eff
+dist/2025-05-26/rust-std-beta-powerpc64-unknown-linux-gnu.tar.gz=6aedb018d3758c3f1e8d5d3e69f0c996c35fba18338346b43ad7e9099621d714
+dist/2025-05-26/rust-std-beta-powerpc64-unknown-linux-gnu.tar.xz=3886265ec1bd94ae47146db67bc2a72fdd9d70b64c74878fc1ef9c50498b9f23
+dist/2025-05-26/rust-std-beta-powerpc64le-unknown-linux-gnu.tar.gz=60c8355e9f6c59a329b111b4abd7b8feeb493dc0e4d8d4ec1b07809a9ac6923e
+dist/2025-05-26/rust-std-beta-powerpc64le-unknown-linux-gnu.tar.xz=0c687a9b04b1b36a14c972913dfb9f0d230551f301a895593f1623677b59a26d
+dist/2025-05-26/rust-std-beta-powerpc64le-unknown-linux-musl.tar.gz=29fc686f26c6258a542e118a035924167c3c6b2b007980f89101cd50ca3543f4
+dist/2025-05-26/rust-std-beta-powerpc64le-unknown-linux-musl.tar.xz=a6d643c2c794a405ee6bfa7e8f3c19cf2b94a17c61d743763dd6939ed8641d0e
+dist/2025-05-26/rust-std-beta-riscv32i-unknown-none-elf.tar.gz=781b81baa8dfd9a5e7eb346176e9cac1e83cba42d1943677b08c689d535debd4
+dist/2025-05-26/rust-std-beta-riscv32i-unknown-none-elf.tar.xz=ca46997729ba43239372bda073a20c1a5d6d25c00cfd79105dd44ff634cacf84
+dist/2025-05-26/rust-std-beta-riscv32im-unknown-none-elf.tar.gz=d0173b18212cf346c5477b8fa1292f51db7fa7275455417ede405f6e822548b1
+dist/2025-05-26/rust-std-beta-riscv32im-unknown-none-elf.tar.xz=6357a65bf47d918d8375e0f7f0f3cfa137026a3be7123a2ae1ae827a71e96c31
+dist/2025-05-26/rust-std-beta-riscv32imac-unknown-none-elf.tar.gz=dc0b7a21b4e597320bcf63c84812ae9caab0aafd215aafa10187820ba91d6490
+dist/2025-05-26/rust-std-beta-riscv32imac-unknown-none-elf.tar.xz=f42b4e807be249463cb9e4f3781b45c45492c0badc45ee6baacb50d61fd3fd42
+dist/2025-05-26/rust-std-beta-riscv32imafc-unknown-none-elf.tar.gz=78cfa47f2376a73f7247ac69968ce0752129cc57f7961fe0c12509b27411e232
+dist/2025-05-26/rust-std-beta-riscv32imafc-unknown-none-elf.tar.xz=2b2ba34b8c6992e4f253e30d80df578e9ac8063264f61cfec0b0fedb9b823ef6
+dist/2025-05-26/rust-std-beta-riscv32imc-unknown-none-elf.tar.gz=27ef3d52ca7b2e1294506f3e105fb5753f468e5a29f1a84804213a055a885719
+dist/2025-05-26/rust-std-beta-riscv32imc-unknown-none-elf.tar.xz=71b0a54a82cf5f69da177559494b2601c55c3e3bd0bea539ce69e7499c3150a1
+dist/2025-05-26/rust-std-beta-riscv64gc-unknown-linux-gnu.tar.gz=d11ccac57c31274b7b3dac4b1761a04a806ddf368c00e7a16644390ba221154a
+dist/2025-05-26/rust-std-beta-riscv64gc-unknown-linux-gnu.tar.xz=f636c9cee16b8e676597b31956d6827e1bac7ccd83c730653953affce9724a96
+dist/2025-05-26/rust-std-beta-riscv64gc-unknown-linux-musl.tar.gz=806dab8bfe031f0043706992a9426e8580e82a92df11ef5728e6a00da13cb40a
+dist/2025-05-26/rust-std-beta-riscv64gc-unknown-linux-musl.tar.xz=b48f6e9641db567e8728db48a062b0cc570ee2712af7adfc64dcb4f4ab355396
+dist/2025-05-26/rust-std-beta-riscv64gc-unknown-none-elf.tar.gz=8d779f261e4c0e62e8c6a616f2635dc74cb4637366386b0857f31fb015fcf152
+dist/2025-05-26/rust-std-beta-riscv64gc-unknown-none-elf.tar.xz=7d12366c1c1166e50d2a78f1ac3fe3166935b4920eac8f64e878a6b5f8653a6a
+dist/2025-05-26/rust-std-beta-riscv64imac-unknown-none-elf.tar.gz=6c01c064a5812f55004ecce5c514c1aeead262dda2525fc7225bbc68d0020d5b
+dist/2025-05-26/rust-std-beta-riscv64imac-unknown-none-elf.tar.xz=1be564ed4d96e15ed8eaad48a0b64112d05a9096a2fc56245e38ef9fc3098865
+dist/2025-05-26/rust-std-beta-s390x-unknown-linux-gnu.tar.gz=9329f4c55d1c9216ddbe684d0b246f65724d0919a009d066987052bb27a867db
+dist/2025-05-26/rust-std-beta-s390x-unknown-linux-gnu.tar.xz=3e164f2c3af1850902a7852d5b043f6ac2065b02d0786912b66c83c1371f71e6
+dist/2025-05-26/rust-std-beta-sparc64-unknown-linux-gnu.tar.gz=613cd5db53ae3f2c69eddbbbf39957a6931b9b5ab1766135b150e01396cff220
+dist/2025-05-26/rust-std-beta-sparc64-unknown-linux-gnu.tar.xz=03d9f75b9a4126c81b1896dcfafadecbbb6f4e81fdc774023f81acc28ed125c9
+dist/2025-05-26/rust-std-beta-sparcv9-sun-solaris.tar.gz=fd5aad29a1ac50b469629fa7ead7d503060909f2640750084f0a72f8d9699456
+dist/2025-05-26/rust-std-beta-sparcv9-sun-solaris.tar.xz=942a34da917069072ac610dbc3667cd847dfadfe3df09d6ff3aebefd49311041
+dist/2025-05-26/rust-std-beta-thumbv6m-none-eabi.tar.gz=91024331bd867a1ed71b687509fe694f924bef58047a9137c7a759ae783179f3
+dist/2025-05-26/rust-std-beta-thumbv6m-none-eabi.tar.xz=e3b5096e07f3587c87fd6832b852882f7d63fbc6b8819de452ce5883e26742e1
+dist/2025-05-26/rust-std-beta-thumbv7em-none-eabi.tar.gz=40f0dcf8654464732add7e8b3e1a1d898699fbf50be74b116650c8251209f913
+dist/2025-05-26/rust-std-beta-thumbv7em-none-eabi.tar.xz=6193c72b9c4c7ca27b12da0f13dca0ac1d11b1cb2a8868a7f2e7f24ab3e7a78f
+dist/2025-05-26/rust-std-beta-thumbv7em-none-eabihf.tar.gz=a008f4debee859f5c5b90aa4000774cdaae045f8161b8e7fbfaab68db7f2341e
+dist/2025-05-26/rust-std-beta-thumbv7em-none-eabihf.tar.xz=bb96feab15991aea5fa38f22848a715422c0b1da060b34a7273f3ec077d4a4e3
+dist/2025-05-26/rust-std-beta-thumbv7m-none-eabi.tar.gz=46e8c8f891c22cee04de8c02aa1e0f5604a9bcd33219cfd1a299c43b4005f93f
+dist/2025-05-26/rust-std-beta-thumbv7m-none-eabi.tar.xz=d4dbed9d96c6b57e185ede566a3dc610f03d854ff696466e9c68815b85dee963
+dist/2025-05-26/rust-std-beta-thumbv7neon-linux-androideabi.tar.gz=222d18565a0d40edc3d6cb051f2647b5416b417933fcdcd25bba54fc55de625f
+dist/2025-05-26/rust-std-beta-thumbv7neon-linux-androideabi.tar.xz=4190060ea541ad1f1f5eb91815027ba475d0e1281ded77ee3116561660919550
+dist/2025-05-26/rust-std-beta-thumbv7neon-unknown-linux-gnueabihf.tar.gz=bf99b1d2a8997d36f994f31bcb48482ec3d48f962ed66beb8642025859c53d97
+dist/2025-05-26/rust-std-beta-thumbv7neon-unknown-linux-gnueabihf.tar.xz=477fe3a269b43ca2f795fef83b50697600021129678aa6af1594858bfeb9479d
+dist/2025-05-26/rust-std-beta-thumbv8m.base-none-eabi.tar.gz=bbd981f00bdad617fdaf823d78cd6f500807b742e050a3d4cbd42ed2966ac7d7
+dist/2025-05-26/rust-std-beta-thumbv8m.base-none-eabi.tar.xz=8a8c004818d5fe2eb9f99d77f65810f577bc1e8cbba0ba2ec6e045234c6a700b
+dist/2025-05-26/rust-std-beta-thumbv8m.main-none-eabi.tar.gz=7e015ea2920c65337b61d5fc1a5f619cfef6589483a4e6c09d8dfbe1529972b2
+dist/2025-05-26/rust-std-beta-thumbv8m.main-none-eabi.tar.xz=37b2b934afd57a81c4007cb4b8b901fe7b15334588625e98d79b037876f18725
+dist/2025-05-26/rust-std-beta-thumbv8m.main-none-eabihf.tar.gz=919db1cc7cbe3e52a6e33f03fe4e79504bef2825ffe58895e24130907bad7b6b
+dist/2025-05-26/rust-std-beta-thumbv8m.main-none-eabihf.tar.xz=59b8ced330f72dc06635aff3de2cc7c796baee86320ff8458d8dc995ba11b909
+dist/2025-05-26/rust-std-beta-wasm32-unknown-emscripten.tar.gz=5d5298f0a3d9a8a8cee3ad9003c409adeed1b3fcacac449a5827f14099b052a6
+dist/2025-05-26/rust-std-beta-wasm32-unknown-emscripten.tar.xz=e9b8868b05e0d210419f3b041839f60e0d4fdd7bd54eca6b0f96b5f90148cdf9
+dist/2025-05-26/rust-std-beta-wasm32-unknown-unknown.tar.gz=35a70b6c8369ca487d93c9cf445a0011ff13dd5cea485a4d01558167473130f0
+dist/2025-05-26/rust-std-beta-wasm32-unknown-unknown.tar.xz=5243ebcffd4880cecae8c3a90c9c76bae1da188478d5e572a8a71cf4442ca991
+dist/2025-05-26/rust-std-beta-wasm32-wasip1.tar.gz=f39ae9fc833c1e0d6b3aa3a3782f7dd1e547c7f6b0141c52e0c7cb5b6fa30def
+dist/2025-05-26/rust-std-beta-wasm32-wasip1.tar.xz=caa1d6e9eb7663ba34dc7db1d47bbd972b41f22f458afd95a6a0aaa0d7e26f59
+dist/2025-05-26/rust-std-beta-wasm32-wasip1-threads.tar.gz=9f0de2858a6ee7de500562fb9639e68cdebc45a6181778ffb41be77af74fdead
+dist/2025-05-26/rust-std-beta-wasm32-wasip1-threads.tar.xz=98523168355e334dbcf0730c314ad9fe901751eefd61d567878c34f21c30ec98
+dist/2025-05-26/rust-std-beta-wasm32-wasip2.tar.gz=8cfdd1d718208fead76aaebd54ad44e9f98145664e475914f7b9951372c1813d
+dist/2025-05-26/rust-std-beta-wasm32-wasip2.tar.xz=64fed08a0d9b09097a9370ee4b013332d19587b5de67b0f0af49bc09625c765c
+dist/2025-05-26/rust-std-beta-wasm32v1-none.tar.gz=ff212273e3d5c4e465d8a3d8838716f2b2e2380f82c158d13dba997df4a8fb0b
+dist/2025-05-26/rust-std-beta-wasm32v1-none.tar.xz=8300711696bc8988e6e00baea2d15012f373525436f1415f54037e10511acd83
+dist/2025-05-26/rust-std-beta-x86_64-apple-darwin.tar.gz=77d89abf4d00195e240b8f55ab2bc5558d21f0f1fee33bf419d14a3e3f2b3ab1
+dist/2025-05-26/rust-std-beta-x86_64-apple-darwin.tar.xz=817dc01f12d7a2c388b001bd708aab2967afce42a11aecfa278a40235800e1cf
+dist/2025-05-26/rust-std-beta-x86_64-apple-ios.tar.gz=cdcbeb20884c7782e080ae38ec6dd955706fa2e924ddfd235d775e39be2cb446
+dist/2025-05-26/rust-std-beta-x86_64-apple-ios.tar.xz=378d04709658b08a24edff046bbc6b3fbee7d0127fff93818e92cda0234e0837
+dist/2025-05-26/rust-std-beta-x86_64-apple-ios-macabi.tar.gz=81d68c70d385f38f526856d021aa1b5b25e9bddff52b8098d76a87c53721784f
+dist/2025-05-26/rust-std-beta-x86_64-apple-ios-macabi.tar.xz=e9cd869473a379a72364b1246fee3007d9b45801e40a3cd2eecc7831edba5bb4
+dist/2025-05-26/rust-std-beta-x86_64-fortanix-unknown-sgx.tar.gz=49c18132004107623e554264b000d07ea0a1dc51ee1e21d02b833b9fdb07b855
+dist/2025-05-26/rust-std-beta-x86_64-fortanix-unknown-sgx.tar.xz=be2269500b5522f677eebf74c0a201751c74481568ba235200716fe368f443e2
+dist/2025-05-26/rust-std-beta-x86_64-linux-android.tar.gz=25801215e0bfa5af3b2b84aa0b881fa723cef308872de58e36d2de943746e51b
+dist/2025-05-26/rust-std-beta-x86_64-linux-android.tar.xz=f692f2f3c69c8fa62d5344faa75375fd2a48a1b81284a7fbfe4b41f575c7263f
+dist/2025-05-26/rust-std-beta-x86_64-pc-solaris.tar.gz=7d79359bc70414d23174aac81b1e5c341b541f6a8361142a3d48ddfc956dc7fd
+dist/2025-05-26/rust-std-beta-x86_64-pc-solaris.tar.xz=ec42340a3bbaeb9723ec77a48b4c49496ee61a928ae20c1bdf3ca33859a3fa52
+dist/2025-05-26/rust-std-beta-x86_64-pc-windows-gnu.tar.gz=6ad0c0a19a92af2749dc8680dcc14bc1fa9fc1d3f4bcf8e28b0646c3bb50859b
+dist/2025-05-26/rust-std-beta-x86_64-pc-windows-gnu.tar.xz=e3e1ecbf40411fa9216a43573b765c526652205f2978409b5488c25b19e98375
+dist/2025-05-26/rust-std-beta-x86_64-pc-windows-gnullvm.tar.gz=a62671dc133e7cc059ed4ad004946e9030e8b882094ddd81b282c56363b0644a
+dist/2025-05-26/rust-std-beta-x86_64-pc-windows-gnullvm.tar.xz=16aac5f5f78f067dd4e2106d62a31fff071757bebf53742eb72f25a5abb2d7af
+dist/2025-05-26/rust-std-beta-x86_64-pc-windows-msvc.tar.gz=d2c5c7a89dc122a7edf1120c3765e55001b3ecca57fb8077b6f4e6085c9fb6af
+dist/2025-05-26/rust-std-beta-x86_64-pc-windows-msvc.tar.xz=14b0a62b8dca999d96ff6cbc7fa8dfc3486555be9aae4d509dd95fba01db8f65
+dist/2025-05-26/rust-std-beta-x86_64-unknown-freebsd.tar.gz=fc3ead4c4599e5371668c610658538dc2bab3b3db2ca9aa1645da087649df131
+dist/2025-05-26/rust-std-beta-x86_64-unknown-freebsd.tar.xz=9e7477e05192ce11190e9b1291a5e171a9cd9da9ca2f4c53d08b98025a697255
+dist/2025-05-26/rust-std-beta-x86_64-unknown-fuchsia.tar.gz=b21552a046715dabb5b14d82fc9707c6622073b013b839f1b08e0463dcf536ac
+dist/2025-05-26/rust-std-beta-x86_64-unknown-fuchsia.tar.xz=1ed92b1672f0d18ff0d6f8365326478cdcf60af25837924f54d3c7459a4dcdf4
+dist/2025-05-26/rust-std-beta-x86_64-unknown-illumos.tar.gz=14d1ffa188c1e4b64d9ac941698922d2a46d0fab78498c6499d5782edd529968
+dist/2025-05-26/rust-std-beta-x86_64-unknown-illumos.tar.xz=41cca6d938e5c39e4032f94256ecb4efdd76c1569e29f84191d58be5d3c0773a
+dist/2025-05-26/rust-std-beta-x86_64-unknown-linux-gnu.tar.gz=444f4875970842d935d1a42a46ac524b6bac248d4bb5993e5ac578ee88f519cf
+dist/2025-05-26/rust-std-beta-x86_64-unknown-linux-gnu.tar.xz=354c0e9396e7b241a7e8c69e3670d98a42ed8bb7359d4f06deefa4fdf81df675
+dist/2025-05-26/rust-std-beta-x86_64-unknown-linux-gnux32.tar.gz=efb7bc1afab8d3f3f6de3fbf41bfb3ae17bb3e193644ae40be5d497aba20d1cb
+dist/2025-05-26/rust-std-beta-x86_64-unknown-linux-gnux32.tar.xz=c717608c4378ecf44cf3ef9d3ab8c5e6bc29db0b1c9b04054b42c60fb5109ff0
+dist/2025-05-26/rust-std-beta-x86_64-unknown-linux-musl.tar.gz=1e4f8c03396b130a284a3a11c20da15185d3a9cbbb6d9a219a76e0e192cbd2a0
+dist/2025-05-26/rust-std-beta-x86_64-unknown-linux-musl.tar.xz=b5639086009cc35a8fd493fc885cebbf2dc68b4d4fc956b00bd5061ec4ed75b1
+dist/2025-05-26/rust-std-beta-x86_64-unknown-linux-ohos.tar.gz=cd577082d0fb089e42ea31509f92321b40221b54f73edb0f80510f6e170acc6d
+dist/2025-05-26/rust-std-beta-x86_64-unknown-linux-ohos.tar.xz=2257286555b3208b43390284db141d2db7282a7d2d4c438fd3b217de3ede790a
+dist/2025-05-26/rust-std-beta-x86_64-unknown-netbsd.tar.gz=61205a7f309f18f9e1a8c12c9b74902f014475ea357fdadf728858f9f81d6e73
+dist/2025-05-26/rust-std-beta-x86_64-unknown-netbsd.tar.xz=d11ae113c9d4156ef31561c002a9b65ef702302c89b0dd2b3005bef57ba92d01
+dist/2025-05-26/rust-std-beta-x86_64-unknown-none.tar.gz=8583686c6aa8eaeb57b64dbc288d564fdaf4939d6f552143e7cdc0641147192d
+dist/2025-05-26/rust-std-beta-x86_64-unknown-none.tar.xz=64a654c790902abf4f936a3194757eb6885d88a68cbd8de19767a8e7a0f21335
+dist/2025-05-26/rust-std-beta-x86_64-unknown-redox.tar.gz=b80e62b6982c684d5550233c15299533fa709e540e53bf20e7ed06fc09e396d1
+dist/2025-05-26/rust-std-beta-x86_64-unknown-redox.tar.xz=63a195aab6fe29882c7a0688ca2368a611127381320349c7cb1097dcde2b4603
+dist/2025-05-26/rust-std-beta-x86_64-unknown-uefi.tar.gz=3f285485b3a7bd957ad69cb76ff717d7987ad0bc50368aeb1b813f9b2d3b5af5
+dist/2025-05-26/rust-std-beta-x86_64-unknown-uefi.tar.xz=dc1e9a9952adbb65711ebcb79b7afc149ac1c9f73b69b97f6b059a53ac71067c
+dist/2025-05-26/cargo-beta-aarch64-apple-darwin.tar.gz=368b6cb43f573346237012bdc23e5c44d476db779795464cecc2065f6fda8b8f
+dist/2025-05-26/cargo-beta-aarch64-apple-darwin.tar.xz=4bbf76bc026d740269c09658a3218eee2dfcc7422fe233db192cfee4dc4a371e
+dist/2025-05-26/cargo-beta-aarch64-pc-windows-msvc.tar.gz=afd53341d1c84f86ddcb4ee85affc0413715c05bd43c075ef193306e86126488
+dist/2025-05-26/cargo-beta-aarch64-pc-windows-msvc.tar.xz=2cf06c20e07ab905f329c8ffcf275b7cd528488893c7014a1cc03faafb13d2c6
+dist/2025-05-26/cargo-beta-aarch64-unknown-linux-gnu.tar.gz=8ca26bf35ed608b6b6ebdff67f7949bf8219f32edb1ece3ca9f8d49a182cd8ed
+dist/2025-05-26/cargo-beta-aarch64-unknown-linux-gnu.tar.xz=61a8743d62dd505d7d76b2ffd282e2b41653b0b30eb96e7f950f144201270a21
+dist/2025-05-26/cargo-beta-aarch64-unknown-linux-musl.tar.gz=8cd37cda7f2f2c323ebda896fc2fb8d8a83b30f2b9c102a1305bf724c261566c
+dist/2025-05-26/cargo-beta-aarch64-unknown-linux-musl.tar.xz=fa5f4fa4da574b2bc79db4dd37969ba5549b32acb65554e35735b55913ab6e53
+dist/2025-05-26/cargo-beta-arm-unknown-linux-gnueabi.tar.gz=30a29adc0c331a3cdff5c1f1d8b541f720212a3b8b2c96795e95f96ffb5982b2
+dist/2025-05-26/cargo-beta-arm-unknown-linux-gnueabi.tar.xz=069071883eee8226003b1cd8501868b3aa51ec8d0f0637e4538b30b920d05823
+dist/2025-05-26/cargo-beta-arm-unknown-linux-gnueabihf.tar.gz=0151634d3a2a1757b9671cf9d48cbfd5fa34df77744ffeac02d8cb5f6949cdc1
+dist/2025-05-26/cargo-beta-arm-unknown-linux-gnueabihf.tar.xz=524386061e1b6b212cd9f94d9d7baf2cd1eb9b2ee105c334aaffcc192cb38e19
+dist/2025-05-26/cargo-beta-armv7-unknown-linux-gnueabihf.tar.gz=d392c9fac6521b2377928305d87e1d65f70e6a5472d4ded3475e08118186f2b1
+dist/2025-05-26/cargo-beta-armv7-unknown-linux-gnueabihf.tar.xz=b1ff6f50dd621d7af5224dce74a25ae895e6b06216fe8e1501ff4199c04f0374
+dist/2025-05-26/cargo-beta-i686-pc-windows-gnu.tar.gz=52ebc95b1c29d3c0714c66505f0ef838c13d12d9436f1d2c2291cf027a38697f
+dist/2025-05-26/cargo-beta-i686-pc-windows-gnu.tar.xz=c6acb26d5e9a4f8c51c13f8b92560849cc4df822a80d04b0e61b1407e93555d5
+dist/2025-05-26/cargo-beta-i686-pc-windows-msvc.tar.gz=af54473c85c035105c429138cfc0d5ab30dcc1b13ea01a3e4d12a8342c309e98
+dist/2025-05-26/cargo-beta-i686-pc-windows-msvc.tar.xz=3a44659128f07fe5953659506c1b6c93fbea96a327401064dbe0393ddb28542d
+dist/2025-05-26/cargo-beta-i686-unknown-linux-gnu.tar.gz=39632af7bcf55760161ddd4ebfe40a3c9a49b6191ec88d1b1d66390668d09905
+dist/2025-05-26/cargo-beta-i686-unknown-linux-gnu.tar.xz=190e8b6bda864b4316f530e5d693e779074de8665a5abe6a4f5cbd01ce8fe6b7
+dist/2025-05-26/cargo-beta-loongarch64-unknown-linux-gnu.tar.gz=87d25663fa5b4b09fff9ea02c07bdddf760873bad7c425015d6e1750a24f66a4
+dist/2025-05-26/cargo-beta-loongarch64-unknown-linux-gnu.tar.xz=b0789d6fe6d8f7e07f0858211e59ae9278adee7d14dee64fc359b3079773993d
+dist/2025-05-26/cargo-beta-loongarch64-unknown-linux-musl.tar.gz=d0f43421313fb6d43ec9b165dc2c9f6be91daee61f201eaea6735fa6ddaadda7
+dist/2025-05-26/cargo-beta-loongarch64-unknown-linux-musl.tar.xz=3e2de8fe7062494c260d0560253e03fc45baa680f9a62171350c5caf2e5fb426
+dist/2025-05-26/cargo-beta-powerpc-unknown-linux-gnu.tar.gz=93a901615aeaa14dcaa0ccd2fe870ccd29bb4f52601cb7ff3b2da7bc6c3e1b22
+dist/2025-05-26/cargo-beta-powerpc-unknown-linux-gnu.tar.xz=28ab251856c6a252beb72a5db0e18e68e40b342fcbd903dd75811ba393b44194
+dist/2025-05-26/cargo-beta-powerpc64-unknown-linux-gnu.tar.gz=6c1f5cb9ec7787cf004c3efa6da81a93155ff3b5319ba7c6ffd29ba631a0feb2
+dist/2025-05-26/cargo-beta-powerpc64-unknown-linux-gnu.tar.xz=9a09c0f8d027310b26909c193227466402ef616c27b943ec16cd5a7eabca5ca9
+dist/2025-05-26/cargo-beta-powerpc64le-unknown-linux-gnu.tar.gz=c5c81cbf63206e47989c5a11953289f99e72647aff4d876d18fb8d2c99a54d1a
+dist/2025-05-26/cargo-beta-powerpc64le-unknown-linux-gnu.tar.xz=d187d131e679bebcdae5a7b9e828285f55b61cbc124e72d233725e4e0f2dbc39
+dist/2025-05-26/cargo-beta-powerpc64le-unknown-linux-musl.tar.gz=883c45f3a2a659560187cbc7696a3132163d6385dd155007c4d5fd2fb068dfb7
+dist/2025-05-26/cargo-beta-powerpc64le-unknown-linux-musl.tar.xz=f9d36abf952bed0e4df94dbeab0ef732ed731e6f8740c5be0ff96f603c46f4c1
+dist/2025-05-26/cargo-beta-riscv64gc-unknown-linux-gnu.tar.gz=23e25b899432df81b660105786f038e95bbddb3bab60a7917e4ca077d5b7520a
+dist/2025-05-26/cargo-beta-riscv64gc-unknown-linux-gnu.tar.xz=885a2c1e30eb3d489a1234034663131c8762645ec1c03ce94198053a21debfa7
+dist/2025-05-26/cargo-beta-s390x-unknown-linux-gnu.tar.gz=f9b69f26f868a5a2173de74424be26cb0d4e6db6867e1a8c32db799e9fb03ede
+dist/2025-05-26/cargo-beta-s390x-unknown-linux-gnu.tar.xz=bf3d01fc0202bcdea158e22821e1ffb8b07e4324ce487be96cde2cf1f1e5eaf6
+dist/2025-05-26/cargo-beta-x86_64-apple-darwin.tar.gz=65b4ee4359e402e06cee2c574a03389e36acb4e1caee4aa83cb281f95c48576a
+dist/2025-05-26/cargo-beta-x86_64-apple-darwin.tar.xz=2906bd00506ada8cffb743f355aa918531273f45f449616410dd0c3f913013b3
+dist/2025-05-26/cargo-beta-x86_64-pc-windows-gnu.tar.gz=7b4c8ad29c72d619c2977f5d79cb5c959bdd8acaae2364495962db5473478609
+dist/2025-05-26/cargo-beta-x86_64-pc-windows-gnu.tar.xz=0dfddbc3218d921ac75affe9d3b8595c8d49df9a98d91fe0f92341754f2b6296
+dist/2025-05-26/cargo-beta-x86_64-pc-windows-msvc.tar.gz=43a110d4e7cd3c8a764e4a2836fe368a347ba7fdfd40c8f565969244964d20c1
+dist/2025-05-26/cargo-beta-x86_64-pc-windows-msvc.tar.xz=703d2cce50711a9753c5b7a72c9468d73144a8f6015db913920795590c54ac97
+dist/2025-05-26/cargo-beta-x86_64-unknown-freebsd.tar.gz=9236099e0ffff060c483cc8996e66ca2e906a2c030941aa49163bdc4dfb7bd3b
+dist/2025-05-26/cargo-beta-x86_64-unknown-freebsd.tar.xz=ff50d29e650cf85f6aadee0618ffef15ac4f3c9b30f02f9a678129e9bf8f5ad3
+dist/2025-05-26/cargo-beta-x86_64-unknown-illumos.tar.gz=ea5bd3cd42867e5174f7661fb5254d2f3effadcf0551cf3cbe6fa60d718f48ae
+dist/2025-05-26/cargo-beta-x86_64-unknown-illumos.tar.xz=e3249f14d4467644a73b950d3d9a4f5ac20146923c961bdec3689bbbd4330a38
+dist/2025-05-26/cargo-beta-x86_64-unknown-linux-gnu.tar.gz=e0c5dc6ee9250c0ddbd7db218878fffc5a38641fc773ded5dc28d92a1750eed6
+dist/2025-05-26/cargo-beta-x86_64-unknown-linux-gnu.tar.xz=53921721c33e20275eb7a912ae80af22aa3e888a232360baa3f00f272114833f
+dist/2025-05-26/cargo-beta-x86_64-unknown-linux-musl.tar.gz=18ea106ff675f15b112c4f4dabcb068857a54c6dbd25e9e8661184b2ee3db556
+dist/2025-05-26/cargo-beta-x86_64-unknown-linux-musl.tar.xz=ea4db9c40954dd72896ef9323767384f2da48064465f8961b775f87c8944d0a8
+dist/2025-05-26/cargo-beta-x86_64-unknown-netbsd.tar.gz=05e8398cb96e2c5ebc2db71edd0965c6da755bd14b1598197f5d375d2b0c1cf3
+dist/2025-05-26/cargo-beta-x86_64-unknown-netbsd.tar.xz=ede3da14f0e405398aa9cfe3743d568a37b1adf62aa2a16489b710d773b1744f
+dist/2025-05-26/clippy-beta-aarch64-apple-darwin.tar.gz=43cbc31dce5ca5abc1efcf87fc4609d148d456429d41836c502f217de50aaaab
+dist/2025-05-26/clippy-beta-aarch64-apple-darwin.tar.xz=1ea6c9615a8c3101acb36585d12ec3a61ba55ec069155324675aeb0005738bf4
+dist/2025-05-26/clippy-beta-aarch64-pc-windows-msvc.tar.gz=eec62be5aaa28c856954a2d5e3fbdce10377bd164929ea6d18e43c085ff5044f
+dist/2025-05-26/clippy-beta-aarch64-pc-windows-msvc.tar.xz=76e60d581deb1989f93ec88e94fc984568c69486c9b50c88e1059f18560cf649
+dist/2025-05-26/clippy-beta-aarch64-unknown-linux-gnu.tar.gz=be69d0e6ac05d624dece95d6e6f9a90f8f8e52be2c1fde4b5d64fd9da8d89c7b
+dist/2025-05-26/clippy-beta-aarch64-unknown-linux-gnu.tar.xz=198c679a62e71d108688d3b64a5be76ecd6462f3301c0ee411943678bae640ce
+dist/2025-05-26/clippy-beta-aarch64-unknown-linux-musl.tar.gz=c9012719c15ed4fddd04d4ac3618018a1c194f048e9879acbbb580346a72bda9
+dist/2025-05-26/clippy-beta-aarch64-unknown-linux-musl.tar.xz=7f10e2a9164ae2cd916e82ef569a1f729853ecdc8edfd92012c63e03ff9b5786
+dist/2025-05-26/clippy-beta-arm-unknown-linux-gnueabi.tar.gz=8388777a665a098add359f5dfb10c2e85e6d5ff344b71844267750c589d9dd9f
+dist/2025-05-26/clippy-beta-arm-unknown-linux-gnueabi.tar.xz=ecbd41ae30412624507a6338c25b398b34153762d127bcb413321510334b7036
+dist/2025-05-26/clippy-beta-arm-unknown-linux-gnueabihf.tar.gz=47b420620eae76da5db8fbb2e0a7f23988b436bfce22d17cd44885daac011d7a
+dist/2025-05-26/clippy-beta-arm-unknown-linux-gnueabihf.tar.xz=21fe8e08a556bc6c70bff20e13ea2b54fc6f97656911b960f27c665c6d9d45d2
+dist/2025-05-26/clippy-beta-armv7-unknown-linux-gnueabihf.tar.gz=ded5cec25a893481d0735228946518b3bbf22becb298d5bd72ffa80c338d423b
+dist/2025-05-26/clippy-beta-armv7-unknown-linux-gnueabihf.tar.xz=26ce2e33c7434e2da0d3dd48ea2d57d2cb08eb52d041ff6539bc7d6e6f6ec13c
+dist/2025-05-26/clippy-beta-i686-pc-windows-gnu.tar.gz=e38aa8d7ee0d74e73ed07ebd173549be67654ecf3e781e8386d47c11175d150e
+dist/2025-05-26/clippy-beta-i686-pc-windows-gnu.tar.xz=e35de2fd0152277780464f80bed8aa78feb2e1e64b818888b32522d36ddc6ef2
+dist/2025-05-26/clippy-beta-i686-pc-windows-msvc.tar.gz=b4d259b042439f1324c91580b5d050eebfab04afb86715bc7571f17174f7622f
+dist/2025-05-26/clippy-beta-i686-pc-windows-msvc.tar.xz=7183a9094ebe14baf68a42e7879953c8d433febdad5b32153371d21c65dd86ca
+dist/2025-05-26/clippy-beta-i686-unknown-linux-gnu.tar.gz=d42ba45cc7f6ecec2cfad85fd15d69b17a84d19206fa5c33f1016d135ee29e6f
+dist/2025-05-26/clippy-beta-i686-unknown-linux-gnu.tar.xz=ef98b85f80e434c49b0c19eca16baab3d10345237642c7252b3ab5ddeb494fba
+dist/2025-05-26/clippy-beta-loongarch64-unknown-linux-gnu.tar.gz=6d2e11bbe7c0a1a9249146193e6879176460b90bb9b7909ec01065c02a20f801
+dist/2025-05-26/clippy-beta-loongarch64-unknown-linux-gnu.tar.xz=1eeb173bc287d7fba22091a7083c472aeace48679aae3450c77435376a5285b5
+dist/2025-05-26/clippy-beta-loongarch64-unknown-linux-musl.tar.gz=3d75d8f697609fd3ff857d9aba4947d5efcbe1791994a5a29204d87c625ad3b1
+dist/2025-05-26/clippy-beta-loongarch64-unknown-linux-musl.tar.xz=70ee5bd276113f98b2913c72564c0bf0d364167986d7db776669fb6e4e08e9e7
+dist/2025-05-26/clippy-beta-powerpc-unknown-linux-gnu.tar.gz=010fcc2d0e9724d6162383002d0c63039b9e24c0cb6e2d5187edbb869bc7e1b0
+dist/2025-05-26/clippy-beta-powerpc-unknown-linux-gnu.tar.xz=6b0bcca51760ec121f7ec64e2f6eaf91eeebb9da0318642a115f6852647ae806
+dist/2025-05-26/clippy-beta-powerpc64-unknown-linux-gnu.tar.gz=3b2306a5b60fd2f67eb805189457e1dc0350854eb3a47ae9dd53cc89df9f668d
+dist/2025-05-26/clippy-beta-powerpc64-unknown-linux-gnu.tar.xz=ccafe9b4403c6bcb87a244eb6afadcbab799e65dc105f60551a8a3b6153c31d9
+dist/2025-05-26/clippy-beta-powerpc64le-unknown-linux-gnu.tar.gz=d70a86b08254f64cb2c4d37e911f70aaa0c22f464e1c906d63e61a6b29d39184
+dist/2025-05-26/clippy-beta-powerpc64le-unknown-linux-gnu.tar.xz=2db59bb48172923ad3db736f51ccf1226bdb8ebc76daa29e220007897d76bf6d
+dist/2025-05-26/clippy-beta-powerpc64le-unknown-linux-musl.tar.gz=cf6915d74c6e8789380f5b986c2ed1b17e8709c2a41abd4cfe89033b45cd8642
+dist/2025-05-26/clippy-beta-powerpc64le-unknown-linux-musl.tar.xz=60c647b9fe5ab19522ef94dc5d5e6a03ce58e922ac55dd85feded92812b40879
+dist/2025-05-26/clippy-beta-riscv64gc-unknown-linux-gnu.tar.gz=36614d7f77357fbdcdaf35bebb4222e41617cb684a3daf69e2a1cbfe46ea60d1
+dist/2025-05-26/clippy-beta-riscv64gc-unknown-linux-gnu.tar.xz=0876fae91f3d54a745a73876b901d6551089264b408b7d1954475d3e6195f72b
+dist/2025-05-26/clippy-beta-s390x-unknown-linux-gnu.tar.gz=72247770c08147d59d93ece7d6fc97f46c091fc71c65d3a215f682608aecb2ba
+dist/2025-05-26/clippy-beta-s390x-unknown-linux-gnu.tar.xz=12d12c1c6a277af5c203ad0fbf6dcb4b04ea74614740734466ea7754f13696f6
+dist/2025-05-26/clippy-beta-x86_64-apple-darwin.tar.gz=a9e255811a75cba14ee0789c2263655407b8d293273252217a4fd7d0de813cec
+dist/2025-05-26/clippy-beta-x86_64-apple-darwin.tar.xz=8bac948774490e48e4193eef0415fd02ce0b7e6855d6cc59314e0f6234da927c
+dist/2025-05-26/clippy-beta-x86_64-pc-windows-gnu.tar.gz=fc5d7c3712d8be85f3992f01e2ade695e6c443983b46b4e1eaa3bbad9bc951a8
+dist/2025-05-26/clippy-beta-x86_64-pc-windows-gnu.tar.xz=0e20c9f824ac305c0fa0370376f977f5fd27aff485223ae1ce32c3de0e12b119
+dist/2025-05-26/clippy-beta-x86_64-pc-windows-msvc.tar.gz=c85932e32236b3365351b775cd382744fb47b3bb3117a65cee537ad79fc78881
+dist/2025-05-26/clippy-beta-x86_64-pc-windows-msvc.tar.xz=b4198fac7d359f3fea4240ab81b2f4f013c938e520a350ca21878c84c5ec16f5
+dist/2025-05-26/clippy-beta-x86_64-unknown-freebsd.tar.gz=e3e5d327a35c467ad44151db010a10ad61b0377d8f5c1844d79678d9388cd6e5
+dist/2025-05-26/clippy-beta-x86_64-unknown-freebsd.tar.xz=94637cf9f7715155e530fc9c295fb41555ebbac18255a8750255b13e2f691641
+dist/2025-05-26/clippy-beta-x86_64-unknown-illumos.tar.gz=8ea5ed861bbc11d47b8f6710b95b29acdeaf6d7a80562216a5e8094bfe440d90
+dist/2025-05-26/clippy-beta-x86_64-unknown-illumos.tar.xz=b14302a36f11794b181125c22af92eb5777f7f5f898c73194e82361ddbfacacb
+dist/2025-05-26/clippy-beta-x86_64-unknown-linux-gnu.tar.gz=611504bffef243a1ac873c7d18c42731d6e24caa6d4b370be1ab1858603bb201
+dist/2025-05-26/clippy-beta-x86_64-unknown-linux-gnu.tar.xz=52f4b0a2bd2a5d0bdbccfc1a8ad9cf24572c103c8713911e121fde4935c22854
+dist/2025-05-26/clippy-beta-x86_64-unknown-linux-musl.tar.gz=7af7df177e64881dd68fa1e8207fb4a0bd7ba4e642468024fa34fc3d5c839df8
+dist/2025-05-26/clippy-beta-x86_64-unknown-linux-musl.tar.xz=f2f9575cbd3e3f067aeda5f9b7ab424e0dc119448d12872692cb7c6669f61ae0
+dist/2025-05-26/clippy-beta-x86_64-unknown-netbsd.tar.gz=5e1dc30da47902c52ab1fbfa2216a6952385184b44854c47b8eb988bdd1b040d
+dist/2025-05-26/clippy-beta-x86_64-unknown-netbsd.tar.xz=23f21905caa5824a463fac01e18e0055009cecdfd406da76b838105eb78127e7
+dist/2025-05-27/rustfmt-nightly-aarch64-apple-darwin.tar.gz=5a3b21df1d525a049b9bd1fca0e32eb5aad1a82a2800e094af80f121e90878c0
+dist/2025-05-27/rustfmt-nightly-aarch64-apple-darwin.tar.xz=3f7edd6997839f12d70246edb672a13d808bd871bfaa4bda66bb4db4fb1158fc
+dist/2025-05-27/rustfmt-nightly-aarch64-pc-windows-msvc.tar.gz=99ecb24920480c06482d8b10f6dbc23247c66033991ad807f8228dff35626fac
+dist/2025-05-27/rustfmt-nightly-aarch64-pc-windows-msvc.tar.xz=fc716e83a694792c0b2355457cbe6f0a820ed85be725d6b3e742b257cc9cd245
+dist/2025-05-27/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.gz=cc6bbe1ea77372ea927329aeb6e4d7602829b307a407466d9c6a3417c62b6ce0
+dist/2025-05-27/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.xz=2018c51986de7be37f11ae05aa101b50f2d8f0e06f7ed8e3c6e4891b580a122f
+dist/2025-05-27/rustfmt-nightly-aarch64-unknown-linux-musl.tar.gz=11cbb36b62563209127c1c8b1f4c32ec1ebc6ca04f18a8e067333402120da00b
+dist/2025-05-27/rustfmt-nightly-aarch64-unknown-linux-musl.tar.xz=5bcdcf88ece597956dea20d63cf568a92cb841df529fb0c0b277f469c58bc742
+dist/2025-05-27/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.gz=507753792ca1668ffb7ea4e4467f2ecbfee8753e269a29050cd4e22b1ff20b33
+dist/2025-05-27/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.xz=3e2b0b89c373dc935dc6c0a882b7723d252792d831a6a81889f77df0964df819
+dist/2025-05-27/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.gz=40c728833bee43b25bf81eea8e9e6e3330d455729ec34c6b1c45d6c8b04f3ff4
+dist/2025-05-27/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.xz=c8dc03a4b1c1ed9f853f4c548d94d44b87fcdf52095e7b84d9ddd3be7be7a11a
+dist/2025-05-27/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.gz=fefed8cce0ab0b90b7b58e1a417e031b0969148a427dbbf2f29a9170fb386646
+dist/2025-05-27/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.xz=77b787221ec106ceb20e58e684f348bc5542bac506fc4a3084d4d2931164878a
+dist/2025-05-27/rustfmt-nightly-i686-pc-windows-gnu.tar.gz=3cd4ed08fe7dd4d921d60f15e7593d71db450c9e2e6d5a1f4fca3f409dabe8fe
+dist/2025-05-27/rustfmt-nightly-i686-pc-windows-gnu.tar.xz=df210bf84e04e83ff77cad6acd156393d687e89fd74fff4c288762edfa0853de
+dist/2025-05-27/rustfmt-nightly-i686-pc-windows-msvc.tar.gz=1f3b532d841f5c78fbdb5d0a1c513ab45bd942de27ce650dfca459e33db9b27c
+dist/2025-05-27/rustfmt-nightly-i686-pc-windows-msvc.tar.xz=e9e52af5658861dfa2d1caed954b078a2630b42de08205727b368098348fa0dd
+dist/2025-05-27/rustfmt-nightly-i686-unknown-linux-gnu.tar.gz=c81689ec620c0fbdd4a4daed7a3de6ecbc0b13b98fa06dd1f2d1beb5cc98d5c8
+dist/2025-05-27/rustfmt-nightly-i686-unknown-linux-gnu.tar.xz=a9cb725755e64fff80dfcd2fddf8cb3a62508dee90c6b6aa6786d8e03a2dd232
+dist/2025-05-27/rustfmt-nightly-loongarch64-unknown-linux-gnu.tar.gz=96fae51d3f3443e28f2789a7117510840f24a3270f8a77cf3103c6e7100079b7
+dist/2025-05-27/rustfmt-nightly-loongarch64-unknown-linux-gnu.tar.xz=78a3298fa4f70001326aec0d080873fd8c64b18beca91c8eb93f2d2786b27b5e
+dist/2025-05-27/rustfmt-nightly-loongarch64-unknown-linux-musl.tar.gz=a87af95c57af0edacceb7072fb81291f9e935d548fa5c68afa58d2d5f53d4497
+dist/2025-05-27/rustfmt-nightly-loongarch64-unknown-linux-musl.tar.xz=924b5fbbec1a00b714787b7489ab592a6c0ec9c72d57f06f3ac4ff9960a610a5
+dist/2025-05-27/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.gz=c11fc36cf2ae84737ca5d1fc441acbf755053eba26fd962f12a9b1a76a0a52ec
+dist/2025-05-27/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.xz=6f2fa0295e91031a1f9f1e6c344435021a6b18212c2e21c50a46baafd6694071
+dist/2025-05-27/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.gz=40e7a2d6986084a630161809132213cf3a2858f04c60902fa09eedbf9caa8bb0
+dist/2025-05-27/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.xz=112d9a416fb43ed6dcc8b066133ded75354977ea9e2d14e6d8310b35bfdf338e
+dist/2025-05-27/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.gz=6c30107bfcc9c5b72be06570efa37d356ba9ee9a14385fb84e392095533a8352
+dist/2025-05-27/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.xz=6e80b773b5e2353bad7a5e01e3b330dd569133aae505bceaf605864fda12d55c
+dist/2025-05-27/rustfmt-nightly-powerpc64le-unknown-linux-musl.tar.gz=b250ceb2e2360bf0366a91f6533aff91e17d7c9f3ca48fe448ca18008da3aedb
+dist/2025-05-27/rustfmt-nightly-powerpc64le-unknown-linux-musl.tar.xz=62cebf6541b0d3b2f247f3e43492160750eabb227be9ca98b34714538e176cbc
+dist/2025-05-27/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.gz=ac31569b7367b4a44fd64c6cc778849196a7d02ca4b413c08568a4318100246d
+dist/2025-05-27/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.xz=0ef0aa7518da52dcea41e979aba1e4e93268bfc43140a83e00dff566ea2ee0e1
+dist/2025-05-27/rustfmt-nightly-s390x-unknown-linux-gnu.tar.gz=811c1024ca9b92a9512105c6589f557ddc409df6ce7dda3f1ad537f0b5e5520c
+dist/2025-05-27/rustfmt-nightly-s390x-unknown-linux-gnu.tar.xz=f0deb894b1f9921ab401c8e4fe3a1eb2cef4c2b51352f54c87fad0dc8689d927
+dist/2025-05-27/rustfmt-nightly-x86_64-apple-darwin.tar.gz=18b3231a7df8e5ab2fa961de699880878aa234f56cff9d7a1126c17b8f249846
+dist/2025-05-27/rustfmt-nightly-x86_64-apple-darwin.tar.xz=74a69eb74ebd5ae965f2f7fd251743ad81efc2e6e5684886d47427414d39b2e7
+dist/2025-05-27/rustfmt-nightly-x86_64-pc-windows-gnu.tar.gz=815169fe5a0bced72ae2a7a187597d56bfc402cd5c318f9258d5576c178a19e2
+dist/2025-05-27/rustfmt-nightly-x86_64-pc-windows-gnu.tar.xz=0849e77b370332530f51bc486cb3b67a26a13369267e1978aeb895e66d8c62a1
+dist/2025-05-27/rustfmt-nightly-x86_64-pc-windows-msvc.tar.gz=b003015eb6622e2ee16a4471e9d1b6908556b4f544ee8574d793e94e866258b9
+dist/2025-05-27/rustfmt-nightly-x86_64-pc-windows-msvc.tar.xz=2fb0722be5ecec129175e74928464f57b4595208e87b5295186f163389aee8c3
+dist/2025-05-27/rustfmt-nightly-x86_64-unknown-freebsd.tar.gz=d780af4579941b6a1d1825a3d512cf541486cd365699243634f134af1af80661
+dist/2025-05-27/rustfmt-nightly-x86_64-unknown-freebsd.tar.xz=7109ac35f05e8d0f013eaa530c6271cc943ae8076cb7056383b93422329dbc0a
+dist/2025-05-27/rustfmt-nightly-x86_64-unknown-illumos.tar.gz=9e3d61435933b25f5e489cfd97cc3d9737fc99403e72fd2b2c302a2850d6e7ac
+dist/2025-05-27/rustfmt-nightly-x86_64-unknown-illumos.tar.xz=8a8dfcea26c974826693c776a64e89b3ef9104f61772e84918c780c92c5a13a5
+dist/2025-05-27/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.gz=c4b37e59ef93c647a1533bb7427cfc97a3766a40dd551ae8eb3668a44702e1df
+dist/2025-05-27/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.xz=5ad72eb343c31b8da7edd7c1fe56e9920a4f7662190fab6e20dfb258e3c38c60
+dist/2025-05-27/rustfmt-nightly-x86_64-unknown-linux-musl.tar.gz=f99a565ea5a7d2238f7cd79364c39fdd2b83559f4cc668cee10c0e3564a5420c
+dist/2025-05-27/rustfmt-nightly-x86_64-unknown-linux-musl.tar.xz=a470498028404e7c64cb5fb77f88dfac560772320fd6aa620eb25c37bf879c9a
+dist/2025-05-27/rustfmt-nightly-x86_64-unknown-netbsd.tar.gz=e9c10350ba54a7d8a190a32aa913cc581e918cfdda14c12553e0278db8e78239
+dist/2025-05-27/rustfmt-nightly-x86_64-unknown-netbsd.tar.xz=63e5effaf0b5bfaf8fc9350d1bc0eb30cf0e8076da85c805fbb4988fff1b8f3c
+dist/2025-05-27/rustc-nightly-aarch64-apple-darwin.tar.gz=16ca9b794c74a72cf9ca68fff71b9f56db1e832feb919c3ff95b65133718719d
+dist/2025-05-27/rustc-nightly-aarch64-apple-darwin.tar.xz=52c42f611e409b50e857c3ce2857afd5f45f19d30f0c8ca1d0a7e1add6fadcbe
+dist/2025-05-27/rustc-nightly-aarch64-pc-windows-msvc.tar.gz=687337020aca4e3e97a5313aafecbbce548cd54fe599c6d62b07f530c39ea755
+dist/2025-05-27/rustc-nightly-aarch64-pc-windows-msvc.tar.xz=2d558352e8f441d1eba929dd5598db5f717a5dec3f813dcc34c4c43da169aea2
+dist/2025-05-27/rustc-nightly-aarch64-unknown-linux-gnu.tar.gz=1eab60c4ce6e7e8e0e245a5928f26ab0b76dc9a4545eb89e481eae0673bc9c84
+dist/2025-05-27/rustc-nightly-aarch64-unknown-linux-gnu.tar.xz=be47b529deb209ae5120a359047b6353114e7a7cceeee5b038a2fa1464fc9c14
+dist/2025-05-27/rustc-nightly-aarch64-unknown-linux-musl.tar.gz=a9985e558669e2f8f6142c3ae25010b834a4d9069344abeb69e4d4cf5c244777
+dist/2025-05-27/rustc-nightly-aarch64-unknown-linux-musl.tar.xz=ce8e9f473ef4247d011055ac6787a9b92b2fb0e932a8b0f08278c8db2529655e
+dist/2025-05-27/rustc-nightly-arm-unknown-linux-gnueabi.tar.gz=709f050c2c73b2788d0c5bbe388296c94db9bc014996015e41688d119b42b0cd
+dist/2025-05-27/rustc-nightly-arm-unknown-linux-gnueabi.tar.xz=010b92069ba7a9de01966e54f09bda22b9ff436929a2e17ea1e9f5b379114780
+dist/2025-05-27/rustc-nightly-arm-unknown-linux-gnueabihf.tar.gz=0685aa646c5bcf6c2b6a70e6384023bd79571f1f87bf85c74c452ea7adbcab32
+dist/2025-05-27/rustc-nightly-arm-unknown-linux-gnueabihf.tar.xz=f3cb40e7a13f75e40c36dea7b916ed245976e9d82a37299c94b6d6245e697f66
+dist/2025-05-27/rustc-nightly-armv7-unknown-linux-gnueabihf.tar.gz=a4c876c4d4c8829ec4755f71ac8efa69baa2875782a371a9aa6ae84d13270ae1
+dist/2025-05-27/rustc-nightly-armv7-unknown-linux-gnueabihf.tar.xz=5e64186cdb993c1ff56fbe10ee1fed73fe71384db6bfdfc57e15cc93924df816
+dist/2025-05-27/rustc-nightly-i686-pc-windows-gnu.tar.gz=92b706e06dc7b656038437b0c281436a28d8508ef13081b61438133d2fe952ef
+dist/2025-05-27/rustc-nightly-i686-pc-windows-gnu.tar.xz=fb8d2d68ac3600befba96f67acbeefec581e2b1eada7c33887fb792101eb2dda
+dist/2025-05-27/rustc-nightly-i686-pc-windows-msvc.tar.gz=8322ce000c9660d86b5a376da11b7da482b78e7e47a56f1fa2fe151b597d8024
+dist/2025-05-27/rustc-nightly-i686-pc-windows-msvc.tar.xz=4612835d7ba71cfe226d04d55c06222bd8b2dd56a8dcba07133dd02cac69fb16
+dist/2025-05-27/rustc-nightly-i686-unknown-linux-gnu.tar.gz=8663c35fe6371fe7ae91c391933a7165cefd5f9f26fe75bcedf6f9977cb4ad0f
+dist/2025-05-27/rustc-nightly-i686-unknown-linux-gnu.tar.xz=17c937f85f59fa7a876540ea60ecd5729c85409a64655041707865fd5f7cc849
+dist/2025-05-27/rustc-nightly-loongarch64-unknown-linux-gnu.tar.gz=639e0b5ed5b0afa3d8304189ed674e9d39b742dc61cc267043628b4c458ba157
+dist/2025-05-27/rustc-nightly-loongarch64-unknown-linux-gnu.tar.xz=faa19a69d37059f67afe8f031b8f743823422dc23939513877125cc2c4a9db2c
+dist/2025-05-27/rustc-nightly-loongarch64-unknown-linux-musl.tar.gz=3dffa8b59899fd9f4d0d7a999212a1737745883f6b6d1a15cee7ff75d7dda417
+dist/2025-05-27/rustc-nightly-loongarch64-unknown-linux-musl.tar.xz=1d5368b7d616d42b81b82d0f46e5ddfc2b7033bc13e06b06520dca4489631388
+dist/2025-05-27/rustc-nightly-powerpc-unknown-linux-gnu.tar.gz=66b1ef67218c651844ffa481e8a9dbbb81a2ef4b40e673bcde2a0c9612eaac95
+dist/2025-05-27/rustc-nightly-powerpc-unknown-linux-gnu.tar.xz=48306f0162b762424e5e7da9e8920c1be982e6e0989536f2d89e922cf7fe7d64
+dist/2025-05-27/rustc-nightly-powerpc64-unknown-linux-gnu.tar.gz=7d7557024f84240fa7cb0d42bbe223c49615eeadcff6c757a755a2e500f8f623
+dist/2025-05-27/rustc-nightly-powerpc64-unknown-linux-gnu.tar.xz=62ebda3f8a44be8c1498defb5059b93add29e95f867e2e7cfd648185fc21b6e5
+dist/2025-05-27/rustc-nightly-powerpc64le-unknown-linux-gnu.tar.gz=5f3579be74da3329e3af32b034fcae002c781f7933b522638cb84876e00efa56
+dist/2025-05-27/rustc-nightly-powerpc64le-unknown-linux-gnu.tar.xz=6191553b2216ef7e9f43763736708a50c9ba972ae51997676244c52795ac5486
+dist/2025-05-27/rustc-nightly-powerpc64le-unknown-linux-musl.tar.gz=70fe263d30c9ed08e00d4d10f9bcbdfda571e5468dcda304a137f7d980e027ac
+dist/2025-05-27/rustc-nightly-powerpc64le-unknown-linux-musl.tar.xz=973c090d6f72c9962fec065d99c02a79f857243306cc6b34a2f77f9c8f7f567c
+dist/2025-05-27/rustc-nightly-riscv64gc-unknown-linux-gnu.tar.gz=bcf3f416152378bac430f88da0fc79e34a7fcbb65e7e06ac890b8de9f2793e98
+dist/2025-05-27/rustc-nightly-riscv64gc-unknown-linux-gnu.tar.xz=cf0cce7680f97a7c248869e44c5571dcc46c5b85e8f00c567efbf9ca3c4af80e
+dist/2025-05-27/rustc-nightly-s390x-unknown-linux-gnu.tar.gz=e6e6094edf1a44f7f08e9d2cb814d3023f0261d5595be89d968b75b0ba0e368c
+dist/2025-05-27/rustc-nightly-s390x-unknown-linux-gnu.tar.xz=0f4b4c5d07b8cc6815094f49ad53e8520245da428afd80e0497676a0863764cf
+dist/2025-05-27/rustc-nightly-x86_64-apple-darwin.tar.gz=c9c5ff52a78d80c74ce0c40c0a2947dedfe99b195f06885d0e405c7f5b6bde28
+dist/2025-05-27/rustc-nightly-x86_64-apple-darwin.tar.xz=1cc3250c923e8647d6668c6e8ee14f2c92c50a73b080a2991768e3a88a9a99ca
+dist/2025-05-27/rustc-nightly-x86_64-pc-windows-gnu.tar.gz=04d2f910571ce2e2e32ab655589989538516cfc023cb6401c605973465054927
+dist/2025-05-27/rustc-nightly-x86_64-pc-windows-gnu.tar.xz=a420f9a4cc7fd01da0b86e56ed4d72f45cfd10c725f381d047dd701bd4e84178
+dist/2025-05-27/rustc-nightly-x86_64-pc-windows-msvc.tar.gz=ea454055258e3ccb6710ba86fc58e1d629c807aa52353d48d754eafe6e4f3522
+dist/2025-05-27/rustc-nightly-x86_64-pc-windows-msvc.tar.xz=9570ad0c65bc3226e3ec05185b01dbf5a1d9822de9aeabedcb4921cc8fbc2639
+dist/2025-05-27/rustc-nightly-x86_64-unknown-freebsd.tar.gz=08f400e47513fe7b8a3d3f5fb86510e28f87d5bfbd661fa8b106b16c0e22b444
+dist/2025-05-27/rustc-nightly-x86_64-unknown-freebsd.tar.xz=5c6467a38bff56ca4fa1722b092a157d0e258eb037bd5f784fae0827af842088
+dist/2025-05-27/rustc-nightly-x86_64-unknown-illumos.tar.gz=f007908e9cbc7defab2719a4f734f6f327952d59d6939b0e85ccb36dca670e0c
+dist/2025-05-27/rustc-nightly-x86_64-unknown-illumos.tar.xz=620be77081b1564ff626b1926d8242d8fc2e6f2c0308002f01cc214f8843701b
+dist/2025-05-27/rustc-nightly-x86_64-unknown-linux-gnu.tar.gz=8749217fd22d81ee2f380b1af63116e4c540fd11f617752e552f66568d50868c
+dist/2025-05-27/rustc-nightly-x86_64-unknown-linux-gnu.tar.xz=545ff3e0ac1c7c303b47bc062d029033a3d8de77c6fb54bad39a6a34b099c711
+dist/2025-05-27/rustc-nightly-x86_64-unknown-linux-musl.tar.gz=d146af52aa7fad3b198b9dd5242793bfc2dc8aad81642bf34702e409d5ae7f3b
+dist/2025-05-27/rustc-nightly-x86_64-unknown-linux-musl.tar.xz=d72ed1096917a5789f26564ddc920c3fdcd29056cf97452371e5141bcc2c8a8e
+dist/2025-05-27/rustc-nightly-x86_64-unknown-netbsd.tar.gz=94b608796d12feff92c54f942318e711879d86b1a3114a710b8366b7415ae025
+dist/2025-05-27/rustc-nightly-x86_64-unknown-netbsd.tar.xz=7d870360a35a34dffede096d62734d97a7bf60d0661e638f73d913cb93bd49ec
diff --git a/src/tools/cargo b/src/tools/cargo
-Subproject 68db37499f2de8acef704c73d9031be6fbcbaee
+Subproject 64a12460708cf146e16cc61f28aba5dc2463bbb
diff --git a/src/tools/clippy/Cargo.toml b/src/tools/clippy/Cargo.toml
index f69e5bee4bb..3a76c61489e 100644
--- a/src/tools/clippy/Cargo.toml
+++ b/src/tools/clippy/Cargo.toml
@@ -42,7 +42,7 @@ walkdir = "2.3"
 filetime = "0.2.9"
 itertools = "0.12"
 pulldown-cmark = { version = "0.11", default-features = false, features = ["html"] }
-askama = { version = "0.13", default-features = false, features = ["alloc", "config", "derive"] }
+askama = { version = "0.14", default-features = false, features = ["alloc", "config", "derive"] }
 
 # UI test dependencies
 if_chain = "1.0"
diff --git a/src/tools/clippy/book/src/development/trait_checking.md b/src/tools/clippy/book/src/development/trait_checking.md
index cc4eb966f59..6d01496eebe 100644
--- a/src/tools/clippy/book/src/development/trait_checking.md
+++ b/src/tools/clippy/book/src/development/trait_checking.md
@@ -17,7 +17,7 @@ providing the `LateContext` (`cx`), our expression at hand, and
 the symbol of the trait in question:
 
 ```rust
-use clippy_utils::is_trait_method;
+use clippy_utils::ty::implements_trait;
 use rustc_hir::Expr;
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_span::symbol::sym;
@@ -25,7 +25,7 @@ use rustc_span::symbol::sym;
 impl LateLintPass<'_> for CheckIteratorTraitLint {
     fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
 		let implements_iterator = cx.tcx.get_diagnostic_item(sym::Iterator).map_or(false, |id| {
-    		implements_trait(cx, cx.typeck_results().expr_ty(arg), id, &[])
+    		implements_trait(cx, cx.typeck_results().expr_ty(expr), id, &[])
 		});
 		if implements_iterator {
 			// [...]
diff --git a/src/tools/clippy/book/src/lint_configuration.md b/src/tools/clippy/book/src/lint_configuration.md
index 9809e32de8a..7c850b4b023 100644
--- a/src/tools/clippy/book/src/lint_configuration.md
+++ b/src/tools/clippy/book/src/lint_configuration.md
@@ -1026,7 +1026,7 @@ The order of associated items in traits.
 The maximum size (in bytes) to consider a `Copy` type for passing by value instead of by
 reference.
 
-**Default Value:** `target_pointer_width * 2`
+**Default Value:** `target_pointer_width`
 
 ---
 **Affected lints:**
diff --git a/src/tools/clippy/clippy_config/src/conf.rs b/src/tools/clippy/clippy_config/src/conf.rs
index 4ce8d001c2f..87158cec42b 100644
--- a/src/tools/clippy/clippy_config/src/conf.rs
+++ b/src/tools/clippy/clippy_config/src/conf.rs
@@ -828,7 +828,7 @@ define_Conf! {
     trait_assoc_item_kinds_order: SourceItemOrderingTraitAssocItemKinds = DEFAULT_TRAIT_ASSOC_ITEM_KINDS_ORDER.into(),
     /// The maximum size (in bytes) to consider a `Copy` type for passing by value instead of by
     /// reference.
-    #[default_text = "target_pointer_width * 2"]
+    #[default_text = "target_pointer_width"]
     #[lints(trivially_copy_pass_by_ref)]
     trivial_copy_size_limit: Option<u64> = None,
     /// The maximum complexity a type can have
diff --git a/src/tools/clippy/clippy_dev/src/fmt.rs b/src/tools/clippy/clippy_dev/src/fmt.rs
index 13d6b1285dc..c1b6b370706 100644
--- a/src/tools/clippy/clippy_dev/src/fmt.rs
+++ b/src/tools/clippy/clippy_dev/src/fmt.rs
@@ -1,5 +1,6 @@
 use crate::utils::{
-    ClippyInfo, ErrAction, FileUpdater, UpdateMode, UpdateStatus, panic_action, run_with_args_split, run_with_output,
+    ErrAction, FileUpdater, UpdateMode, UpdateStatus, expect_action, run_with_output, split_args_for_threads,
+    walk_dir_no_dot_or_target,
 };
 use itertools::Itertools;
 use rustc_lexer::{TokenKind, tokenize};
@@ -9,7 +10,6 @@ use std::io::{self, Read};
 use std::ops::ControlFlow;
 use std::path::PathBuf;
 use std::process::{self, Command, Stdio};
-use walkdir::WalkDir;
 
 pub enum Error {
     Io(io::Error),
@@ -260,7 +260,7 @@ fn fmt_syms(update_mode: UpdateMode) {
     );
 }
 
-fn run_rustfmt(clippy: &ClippyInfo, update_mode: UpdateMode) {
+fn run_rustfmt(update_mode: UpdateMode) {
     let mut rustfmt_path = String::from_utf8(run_with_output(
         "rustup which rustfmt",
         Command::new("rustup").args(["which", "rustfmt"]),
@@ -268,42 +268,19 @@ fn run_rustfmt(clippy: &ClippyInfo, update_mode: UpdateMode) {
     .expect("invalid rustfmt path");
     rustfmt_path.truncate(rustfmt_path.trim_end().len());
 
-    let mut cargo_path = String::from_utf8(run_with_output(
-        "rustup which cargo",
-        Command::new("rustup").args(["which", "cargo"]),
-    ))
-    .expect("invalid cargo path");
-    cargo_path.truncate(cargo_path.trim_end().len());
-
-    // Start all format jobs first before waiting on the results.
-    let mut children = Vec::with_capacity(16);
-    for &path in &[
-        ".",
-        "clippy_config",
-        "clippy_dev",
-        "clippy_lints",
-        "clippy_lints_internal",
-        "clippy_utils",
-        "rustc_tools_util",
-        "lintcheck",
-    ] {
-        let mut cmd = Command::new(&cargo_path);
-        cmd.current_dir(clippy.path.join(path))
-            .args(["fmt"])
-            .env("RUSTFMT", &rustfmt_path)
-            .stdout(Stdio::null())
-            .stdin(Stdio::null())
-            .stderr(Stdio::piped());
-        if update_mode.is_check() {
-            cmd.arg("--check");
-        }
-        match cmd.spawn() {
-            Ok(x) => children.push(("cargo fmt", x)),
-            Err(ref e) => panic_action(&e, ErrAction::Run, "cargo fmt".as_ref()),
-        }
-    }
+    let args: Vec<_> = walk_dir_no_dot_or_target()
+        .filter_map(|e| {
+            let e = expect_action(e, ErrAction::Read, ".");
+            e.path()
+                .as_os_str()
+                .as_encoded_bytes()
+                .ends_with(b".rs")
+                .then(|| e.into_path().into_os_string())
+        })
+        .collect();
 
-    run_with_args_split(
+    let mut children: Vec<_> = split_args_for_threads(
+        32,
         || {
             let mut cmd = Command::new(&rustfmt_path);
             if update_mode.is_check() {
@@ -312,66 +289,44 @@ fn run_rustfmt(clippy: &ClippyInfo, update_mode: UpdateMode) {
             cmd.stdout(Stdio::null())
                 .stdin(Stdio::null())
                 .stderr(Stdio::piped())
-                .args(["--config", "show_parse_errors=false"]);
+                .args(["--unstable-features", "--skip-children"]);
             cmd
         },
-        |cmd| match cmd.spawn() {
-            Ok(x) => children.push(("rustfmt", x)),
-            Err(ref e) => panic_action(&e, ErrAction::Run, "rustfmt".as_ref()),
-        },
-        WalkDir::new("tests")
-            .into_iter()
-            .filter_entry(|p| p.path().file_name().is_none_or(|x| x != "skip_rustfmt"))
-            .filter_map(|e| {
-                let e = e.expect("error reading `tests`");
-                e.path()
-                    .as_os_str()
-                    .as_encoded_bytes()
-                    .ends_with(b".rs")
-                    .then(|| e.into_path().into_os_string())
-            }),
-    );
+        args.iter(),
+    )
+    .map(|mut cmd| expect_action(cmd.spawn(), ErrAction::Run, "rustfmt"))
+    .collect();
 
-    for (name, child) in &mut children {
-        match child.wait() {
-            Ok(status) => match (update_mode, status.exit_ok()) {
-                (UpdateMode::Check | UpdateMode::Change, Ok(())) => {},
-                (UpdateMode::Check, Err(_)) => {
-                    let mut s = String::new();
-                    if let Some(mut stderr) = child.stderr.take()
-                        && stderr.read_to_string(&mut s).is_ok()
-                    {
-                        eprintln!("{s}");
-                    }
-                    eprintln!("Formatting check failed!\nRun `cargo dev fmt` to update.");
-                    process::exit(1);
-                },
-                (UpdateMode::Change, Err(e)) => {
-                    let mut s = String::new();
-                    if let Some(mut stderr) = child.stderr.take()
-                        && stderr.read_to_string(&mut s).is_ok()
-                    {
-                        eprintln!("{s}");
-                    }
-                    panic_action(&e, ErrAction::Run, name.as_ref());
-                },
+    for child in &mut children {
+        let status = expect_action(child.wait(), ErrAction::Run, "rustfmt");
+        match (update_mode, status.exit_ok()) {
+            (UpdateMode::Check | UpdateMode::Change, Ok(())) => {},
+            (UpdateMode::Check, Err(_)) => {
+                let mut s = String::new();
+                if let Some(mut stderr) = child.stderr.take()
+                    && stderr.read_to_string(&mut s).is_ok()
+                {
+                    eprintln!("{s}");
+                }
+                eprintln!("Formatting check failed!\nRun `cargo dev fmt` to update.");
+                process::exit(1);
+            },
+            (UpdateMode::Change, e) => {
+                let mut s = String::new();
+                if let Some(mut stderr) = child.stderr.take()
+                    && stderr.read_to_string(&mut s).is_ok()
+                {
+                    eprintln!("{s}");
+                }
+                expect_action(e, ErrAction::Run, "rustfmt");
             },
-            Err(ref e) => panic_action(e, ErrAction::Run, name.as_ref()),
         }
     }
 }
 
 // the "main" function of cargo dev fmt
-pub fn run(clippy: &ClippyInfo, update_mode: UpdateMode) {
-    if clippy.has_intellij_hook {
-        eprintln!(
-            "error: a local rustc repo is enabled as path dependency via `cargo dev setup intellij`.\n\
-            Not formatting because that would format the local repo as well!\n\
-            Please revert the changes to `Cargo.toml`s with `cargo dev remove intellij`."
-        );
-        return;
-    }
-    run_rustfmt(clippy, update_mode);
+pub fn run(update_mode: UpdateMode) {
+    run_rustfmt(update_mode);
     fmt_syms(update_mode);
     if let Err(e) = fmt_conf(update_mode.is_check()) {
         e.display();
diff --git a/src/tools/clippy/clippy_dev/src/main.rs b/src/tools/clippy/clippy_dev/src/main.rs
index ebcd8611d78..26aa269fb63 100644
--- a/src/tools/clippy/clippy_dev/src/main.rs
+++ b/src/tools/clippy/clippy_dev/src/main.rs
@@ -26,7 +26,7 @@ fn main() {
             allow_staged,
             allow_no_vcs,
         } => dogfood::dogfood(fix, allow_dirty, allow_staged, allow_no_vcs),
-        DevCommand::Fmt { check } => fmt::run(&clippy, utils::UpdateMode::from_check(check)),
+        DevCommand::Fmt { check } => fmt::run(utils::UpdateMode::from_check(check)),
         DevCommand::UpdateLints { check } => update_lints::update(utils::UpdateMode::from_check(check)),
         DevCommand::NewLint {
             pass,
diff --git a/src/tools/clippy/clippy_dev/src/rename_lint.rs b/src/tools/clippy/clippy_dev/src/rename_lint.rs
index be8b27c7a9e..d62597428e2 100644
--- a/src/tools/clippy/clippy_dev/src/rename_lint.rs
+++ b/src/tools/clippy/clippy_dev/src/rename_lint.rs
@@ -1,13 +1,12 @@
 use crate::update_lints::{RenamedLint, find_lint_decls, generate_lint_files, read_deprecated_lints};
 use crate::utils::{
-    FileUpdater, RustSearcher, Token, UpdateMode, UpdateStatus, Version, delete_dir_if_exists, delete_file_if_exists,
-    try_rename_dir, try_rename_file,
+    ErrAction, FileUpdater, RustSearcher, Token, UpdateMode, UpdateStatus, Version, delete_dir_if_exists,
+    delete_file_if_exists, expect_action, try_rename_dir, try_rename_file, walk_dir_no_dot_or_target,
 };
 use rustc_lexer::TokenKind;
 use std::ffi::OsString;
 use std::fs;
 use std::path::Path;
-use walkdir::WalkDir;
 
 /// Runs the `rename_lint` command.
 ///
@@ -133,17 +132,10 @@ pub fn rename(clippy_version: Version, old_name: &str, new_name: &str, uplift: b
     }
 
     let mut update_fn = file_update_fn(old_name, new_name, mod_edit);
-    for file in WalkDir::new(".").into_iter().filter_entry(|e| {
-        // Skip traversing some of the larger directories.
-        e.path()
-            .as_os_str()
-            .as_encoded_bytes()
-            .get(2..)
-            .is_none_or(|x| x != "target".as_bytes() && x != ".git".as_bytes())
-    }) {
-        let file = file.expect("error reading clippy directory");
-        if file.path().as_os_str().as_encoded_bytes().ends_with(b".rs") {
-            updater.update_file(file.path(), &mut update_fn);
+    for e in walk_dir_no_dot_or_target() {
+        let e = expect_action(e, ErrAction::Read, ".");
+        if e.path().as_os_str().as_encoded_bytes().ends_with(b".rs") {
+            updater.update_file(e.path(), &mut update_fn);
         }
     }
     generate_lint_files(UpdateMode::Change, &lints, &deprecated_lints, &renamed_lints);
diff --git a/src/tools/clippy/clippy_dev/src/update_lints.rs b/src/tools/clippy/clippy_dev/src/update_lints.rs
index 25ba2c72049..320462a2c96 100644
--- a/src/tools/clippy/clippy_dev/src/update_lints.rs
+++ b/src/tools/clippy/clippy_dev/src/update_lints.rs
@@ -1,5 +1,5 @@
 use crate::utils::{
-    ErrAction, File, FileUpdater, RustSearcher, Token, UpdateMode, UpdateStatus, panic_action, update_text_region_fn,
+    ErrAction, File, FileUpdater, RustSearcher, Token, UpdateMode, UpdateStatus, expect_action, update_text_region_fn,
 };
 use itertools::Itertools;
 use std::collections::HashSet;
@@ -201,10 +201,7 @@ pub fn find_lint_decls() -> Vec<Lint> {
 /// Reads the source files from the given root directory
 fn read_src_with_module(src_root: &Path) -> impl use<'_> + Iterator<Item = (DirEntry, String)> {
     WalkDir::new(src_root).into_iter().filter_map(move |e| {
-        let e = match e {
-            Ok(e) => e,
-            Err(ref e) => panic_action(e, ErrAction::Read, src_root),
-        };
+        let e = expect_action(e, ErrAction::Read, src_root);
         let path = e.path().as_os_str().as_encoded_bytes();
         if let Some(path) = path.strip_suffix(b".rs")
             && let Some(path) = path.get("clippy_lints/src/".len()..)
diff --git a/src/tools/clippy/clippy_dev/src/utils.rs b/src/tools/clippy/clippy_dev/src/utils.rs
index 255e36afe69..c4808b7048b 100644
--- a/src/tools/clippy/clippy_dev/src/utils.rs
+++ b/src/tools/clippy/clippy_dev/src/utils.rs
@@ -1,14 +1,16 @@
 use core::fmt::{self, Display};
+use core::num::NonZero;
 use core::ops::Range;
 use core::slice;
 use core::str::FromStr;
 use rustc_lexer::{self as lexer, FrontmatterAllowed};
-use std::env;
 use std::ffi::OsStr;
 use std::fs::{self, OpenOptions};
 use std::io::{self, Read as _, Seek as _, SeekFrom, Write};
 use std::path::{Path, PathBuf};
 use std::process::{self, Command, ExitStatus, Stdio};
+use std::{env, thread};
+use walkdir::WalkDir;
 
 #[cfg(not(windows))]
 static CARGO_CLIPPY_EXE: &str = "cargo-clippy";
@@ -45,6 +47,14 @@ pub fn panic_action(err: &impl Display, action: ErrAction, path: &Path) -> ! {
     panic!("error {} `{}`: {}", action.as_str(), path.display(), *err)
 }
 
+#[track_caller]
+pub fn expect_action<T>(res: Result<T, impl Display>, action: ErrAction, path: impl AsRef<Path>) -> T {
+    match res {
+        Ok(x) => x,
+        Err(ref e) => panic_action(e, action, path.as_ref()),
+    }
+}
+
 /// Wrapper around `std::fs::File` which panics with a path on failure.
 pub struct File<'a> {
     pub inner: fs::File,
@@ -55,9 +65,9 @@ impl<'a> File<'a> {
     #[track_caller]
     pub fn open(path: &'a (impl AsRef<Path> + ?Sized), options: &mut OpenOptions) -> Self {
         let path = path.as_ref();
-        match options.open(path) {
-            Ok(inner) => Self { inner, path },
-            Err(e) => panic_action(&e, ErrAction::Open, path),
+        Self {
+            inner: expect_action(options.open(path), ErrAction::Open, path),
+            path,
         }
     }
 
@@ -84,10 +94,7 @@ impl<'a> File<'a> {
     /// Read the entire contents of a file to the given buffer.
     #[track_caller]
     pub fn read_append_to_string<'dst>(&mut self, dst: &'dst mut String) -> &'dst mut String {
-        match self.inner.read_to_string(dst) {
-            Ok(_) => {},
-            Err(e) => panic_action(&e, ErrAction::Read, self.path),
-        }
+        expect_action(self.inner.read_to_string(dst), ErrAction::Read, self.path);
         dst
     }
 
@@ -107,9 +114,7 @@ impl<'a> File<'a> {
             },
             Err(e) => Err(e),
         };
-        if let Err(e) = res {
-            panic_action(&e, ErrAction::Write, self.path);
-        }
+        expect_action(res, ErrAction::Write, self.path);
     }
 }
 
@@ -660,47 +665,91 @@ pub fn try_rename_dir(old_name: &Path, new_name: &Path) -> bool {
 }
 
 pub fn write_file(path: &Path, contents: &str) {
-    fs::write(path, contents).unwrap_or_else(|e| panic_action(&e, ErrAction::Write, path));
+    expect_action(fs::write(path, contents), ErrAction::Write, path);
 }
 
 #[must_use]
 pub fn run_with_output(path: &(impl AsRef<Path> + ?Sized), cmd: &mut Command) -> Vec<u8> {
     fn f(path: &Path, cmd: &mut Command) -> Vec<u8> {
-        match cmd
-            .stdin(Stdio::null())
-            .stdout(Stdio::piped())
-            .stderr(Stdio::inherit())
-            .output()
-        {
-            Ok(x) => match x.status.exit_ok() {
-                Ok(()) => x.stdout,
-                Err(ref e) => panic_action(e, ErrAction::Run, path),
-            },
-            Err(ref e) => panic_action(e, ErrAction::Run, path),
-        }
+        let output = expect_action(
+            cmd.stdin(Stdio::null())
+                .stdout(Stdio::piped())
+                .stderr(Stdio::inherit())
+                .output(),
+            ErrAction::Run,
+            path,
+        );
+        expect_action(output.status.exit_ok(), ErrAction::Run, path);
+        output.stdout
     }
     f(path.as_ref(), cmd)
 }
 
-pub fn run_with_args_split(
-    mut make_cmd: impl FnMut() -> Command,
-    mut run_cmd: impl FnMut(&mut Command),
-    args: impl Iterator<Item: AsRef<OsStr>>,
-) {
-    let mut cmd = make_cmd();
-    let mut len = 0;
-    for arg in args {
-        len += arg.as_ref().len();
-        cmd.arg(arg);
-        // Very conservative limit
-        if len > 10000 {
-            run_cmd(&mut cmd);
-            cmd = make_cmd();
-            len = 0;
+/// Splits an argument list across multiple `Command` invocations.
+///
+/// The argument list will be split into a number of batches based on
+/// `thread::available_parallelism`, with `min_batch_size` setting a lower bound on the size of each
+/// batch.
+///
+/// If the size of the arguments would exceed the system limit additional batches will be created.
+pub fn split_args_for_threads(
+    min_batch_size: usize,
+    make_cmd: impl FnMut() -> Command,
+    args: impl ExactSizeIterator<Item: AsRef<OsStr>>,
+) -> impl Iterator<Item = Command> {
+    struct Iter<F, I> {
+        make_cmd: F,
+        args: I,
+        min_batch_size: usize,
+        batch_size: usize,
+        thread_count: usize,
+    }
+    impl<F, I> Iterator for Iter<F, I>
+    where
+        F: FnMut() -> Command,
+        I: ExactSizeIterator<Item: AsRef<OsStr>>,
+    {
+        type Item = Command;
+        fn next(&mut self) -> Option<Self::Item> {
+            if self.thread_count > 1 {
+                self.thread_count -= 1;
+            }
+            let mut cmd = (self.make_cmd)();
+            let mut cmd_len = 0usize;
+            for arg in self.args.by_ref().take(self.batch_size) {
+                cmd.arg(arg.as_ref());
+                // `+ 8` to account for the `argv` pointer on unix.
+                // Windows is complicated since the arguments are first converted to UTF-16ish,
+                // but this needs to account for the space between arguments and whatever additional
+                // is needed to escape within an argument.
+                cmd_len += arg.as_ref().len() + 8;
+                cmd_len += 8;
+
+                // Windows has a command length limit of 32767. For unix systems this is more
+                // complicated since the limit includes environment variables and room needs to be
+                // left to edit them once the program starts, but the total size comes from
+                // `getconf ARG_MAX`.
+                //
+                // For simplicity we use 30000 here under a few assumptions.
+                // * Individual arguments aren't super long (the final argument is still added)
+                // * `ARG_MAX` is set to a reasonable amount. Basically every system will be configured way above
+                //   what windows supports, but POSIX only requires `4096`.
+                if cmd_len > 30000 {
+                    self.batch_size = self.args.len().div_ceil(self.thread_count).max(self.min_batch_size);
+                    break;
+                }
+            }
+            (cmd_len != 0).then_some(cmd)
         }
     }
-    if len != 0 {
-        run_cmd(&mut cmd);
+    let thread_count = thread::available_parallelism().map_or(1, NonZero::get);
+    let batch_size = args.len().div_ceil(thread_count).max(min_batch_size);
+    Iter {
+        make_cmd,
+        args,
+        min_batch_size,
+        batch_size,
+        thread_count,
     }
 }
 
@@ -720,3 +769,12 @@ pub fn delete_dir_if_exists(path: &Path) {
         Err(ref e) => panic_action(e, ErrAction::Delete, path),
     }
 }
+
+/// Walks all items excluding top-level dot files/directories and any target directories.
+pub fn walk_dir_no_dot_or_target() -> impl Iterator<Item = ::walkdir::Result<::walkdir::DirEntry>> {
+    WalkDir::new(".").into_iter().filter_entry(|e| {
+        e.path()
+            .file_name()
+            .is_none_or(|x| x != "target" && x.as_encoded_bytes().first().copied() != Some(b'.'))
+    })
+}
diff --git a/src/tools/clippy/clippy_lints/src/arbitrary_source_item_ordering.rs b/src/tools/clippy/clippy_lints/src/arbitrary_source_item_ordering.rs
index 5c1c85d3918..59a0c7c8868 100644
--- a/src/tools/clippy/clippy_lints/src/arbitrary_source_item_ordering.rs
+++ b/src/tools/clippy/clippy_lints/src/arbitrary_source_item_ordering.rs
@@ -272,7 +272,7 @@ impl<'tcx> LateLintPass<'tcx> for ArbitrarySourceItemOrdering {
             return;
         }
         match &item.kind {
-            ItemKind::Enum(_, enum_def, _generics) if self.enable_ordering_for_enum => {
+            ItemKind::Enum(_, _generics, enum_def) if self.enable_ordering_for_enum => {
                 let mut cur_v: Option<&Variant<'_>> = None;
                 for variant in enum_def.variants {
                     if variant.span.in_external_macro(cx.sess().source_map()) {
@@ -288,7 +288,7 @@ impl<'tcx> LateLintPass<'tcx> for ArbitrarySourceItemOrdering {
                     cur_v = Some(variant);
                 }
             },
-            ItemKind::Struct(_, VariantData::Struct { fields, .. }, _generics) if self.enable_ordering_for_struct => {
+            ItemKind::Struct(_, _generics, VariantData::Struct { fields, .. }) if self.enable_ordering_for_struct => {
                 let mut cur_f: Option<&FieldDef<'_>> = None;
                 for field in *fields {
                     if field.span.in_external_macro(cx.sess().source_map()) {
diff --git a/src/tools/clippy/clippy_lints/src/arc_with_non_send_sync.rs b/src/tools/clippy/clippy_lints/src/arc_with_non_send_sync.rs
index 2643f850879..9e09fb5bb43 100644
--- a/src/tools/clippy/clippy_lints/src/arc_with_non_send_sync.rs
+++ b/src/tools/clippy/clippy_lints/src/arc_with_non_send_sync.rs
@@ -50,7 +50,7 @@ impl<'tcx> LateLintPass<'tcx> for ArcWithNonSendSync {
             && let arg_ty = cx.typeck_results().expr_ty(arg)
             // make sure that the type is not and does not contain any type parameters
             && arg_ty.walk().all(|arg| {
-                !matches!(arg.unpack(), GenericArgKind::Type(ty) if matches!(ty.kind(), ty::Param(_)))
+                !matches!(arg.kind(), GenericArgKind::Type(ty) if matches!(ty.kind(), ty::Param(_)))
             })
             && let Some(send) = cx.tcx.get_diagnostic_item(sym::Send)
             && let Some(sync) = cx.tcx.lang_items().sync_trait()
diff --git a/src/tools/clippy/clippy_lints/src/dbg_macro.rs b/src/tools/clippy/clippy_lints/src/dbg_macro.rs
index 06376c57119..152516baf73 100644
--- a/src/tools/clippy/clippy_lints/src/dbg_macro.rs
+++ b/src/tools/clippy/clippy_lints/src/dbg_macro.rs
@@ -5,7 +5,7 @@ use clippy_utils::macros::{MacroCall, macro_backtrace};
 use clippy_utils::source::snippet_with_applicability;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::Applicability;
-use rustc_hir::{Expr, ExprKind, Node};
+use rustc_hir::{Closure, ClosureKind, CoroutineKind, Expr, ExprKind, LetStmt, LocalSource, Node, Stmt, StmtKind};
 use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_session::impl_lint_pass;
 use rustc_span::{Span, SyntaxContext, sym};
@@ -60,6 +60,8 @@ impl LateLintPass<'_> for DbgMacro {
         if cur_syntax_ctxt != self.prev_ctxt &&
             let Some(macro_call) = first_dbg_macro_in_expansion(cx, expr.span) &&
             !macro_call.span.in_external_macro(cx.sess().source_map()) &&
+            // avoids exprs generated by the desugaring of coroutines
+            !is_coroutine_desugar(expr) &&
             self.checked_dbg_call_site.insert(macro_call.span) &&
             // allows `dbg!` in test code if allow-dbg-in-test is set to true in clippy.toml
             !(self.allow_dbg_in_tests && is_in_test(cx.tcx, expr.hir_id))
@@ -73,50 +75,51 @@ impl LateLintPass<'_> for DbgMacro {
                 "the `dbg!` macro is intended as a debugging tool",
                 |diag| {
                     let mut applicability = Applicability::MachineApplicable;
-
-                    let (sugg_span, suggestion) = match expr.peel_drop_temps().kind {
-                        // dbg!()
-                        ExprKind::Block(..) => {
-                            // If the `dbg!` macro is a "free" statement and not contained within other expressions,
-                            // remove the whole statement.
-                            if let Node::Stmt(_) = cx.tcx.parent_hir_node(expr.hir_id)
-                                && let Some(semi_span) = cx.sess().source_map().mac_call_stmt_semi_span(macro_call.span)
-                            {
-                                (macro_call.span.to(semi_span), String::new())
-                            } else {
-                                (macro_call.span, String::from("()"))
-                            }
-                        },
-                        // dbg!(1)
-                        ExprKind::Match(val, ..) => (
-                            macro_call.span,
-                            snippet_with_applicability(cx, val.span.source_callsite(), "..", &mut applicability)
-                                .to_string(),
-                        ),
-                        // dbg!(2, 3)
-                        ExprKind::Tup(
-                            [
-                                Expr {
-                                    kind: ExprKind::Match(first, ..),
-                                    ..
-                                },
-                                ..,
-                                Expr {
-                                    kind: ExprKind::Match(last, ..),
-                                    ..
-                                },
-                            ],
-                        ) => {
-                            let snippet = snippet_with_applicability(
-                                cx,
-                                first.span.source_callsite().to(last.span.source_callsite()),
-                                "..",
-                                &mut applicability,
-                            );
-                            (macro_call.span, format!("({snippet})"))
-                        },
-                        _ => unreachable!(),
-                    };
+                    let (sugg_span, suggestion) =
+                        match is_async_move_desugar(expr).unwrap_or(expr).peel_drop_temps().kind {
+                            // dbg!()
+                            ExprKind::Block(..) => {
+                                // If the `dbg!` macro is a "free" statement and not contained within other expressions,
+                                // remove the whole statement.
+                                if let Node::Stmt(_) = cx.tcx.parent_hir_node(expr.hir_id)
+                                    && let Some(semi_span) =
+                                        cx.sess().source_map().mac_call_stmt_semi_span(macro_call.span)
+                                {
+                                    (macro_call.span.to(semi_span), String::new())
+                                } else {
+                                    (macro_call.span, String::from("()"))
+                                }
+                            },
+                            // dbg!(1)
+                            ExprKind::Match(val, ..) => (
+                                macro_call.span,
+                                snippet_with_applicability(cx, val.span.source_callsite(), "..", &mut applicability)
+                                    .to_string(),
+                            ),
+                            // dbg!(2, 3)
+                            ExprKind::Tup(
+                                [
+                                    Expr {
+                                        kind: ExprKind::Match(first, ..),
+                                        ..
+                                    },
+                                    ..,
+                                    Expr {
+                                        kind: ExprKind::Match(last, ..),
+                                        ..
+                                    },
+                                ],
+                            ) => {
+                                let snippet = snippet_with_applicability(
+                                    cx,
+                                    first.span.source_callsite().to(last.span.source_callsite()),
+                                    "..",
+                                    &mut applicability,
+                                );
+                                (macro_call.span, format!("({snippet})"))
+                            },
+                            _ => unreachable!(),
+                        };
 
                     diag.span_suggestion(
                         sugg_span,
@@ -134,6 +137,35 @@ impl LateLintPass<'_> for DbgMacro {
     }
 }
 
+fn is_coroutine_desugar(expr: &Expr<'_>) -> bool {
+    matches!(
+        expr.kind,
+        ExprKind::Closure(Closure {
+            kind: ClosureKind::Coroutine(CoroutineKind::Desugared(..)) | ClosureKind::CoroutineClosure(..),
+            ..
+        })
+    )
+}
+
+fn is_async_move_desugar<'tcx>(expr: &'tcx Expr<'tcx>) -> Option<&'tcx Expr<'tcx>> {
+    if let ExprKind::Block(block, _) = expr.kind
+        && let [
+            Stmt {
+                kind:
+                    StmtKind::Let(LetStmt {
+                        source: LocalSource::AsyncFn,
+                        ..
+                    }),
+                ..
+            },
+        ] = block.stmts
+    {
+        return block.expr;
+    }
+
+    None
+}
+
 fn first_dbg_macro_in_expansion(cx: &LateContext<'_>, span: Span) -> Option<MacroCall> {
     macro_backtrace(span).find(|mc| cx.tcx.is_diagnostic_item(sym::dbg_macro, mc.def_id))
 }
diff --git a/src/tools/clippy/clippy_lints/src/dereference.rs b/src/tools/clippy/clippy_lints/src/dereference.rs
index a22a2ee66d2..cde9528cd87 100644
--- a/src/tools/clippy/clippy_lints/src/dereference.rs
+++ b/src/tools/clippy/clippy_lints/src/dereference.rs
@@ -305,7 +305,7 @@ impl<'tcx> LateLintPass<'tcx> for Dereferencing<'tcx> {
                     RefOp::Method { mutbl, is_ufcs }
                         if !is_lint_allowed(cx, EXPLICIT_DEREF_METHODS, expr.hir_id)
                             // Allow explicit deref in method chains. e.g. `foo.deref().bar()`
-                            && (is_ufcs || !in_postfix_position(cx, expr)) =>
+                            && (is_ufcs || !is_in_method_chain(cx, expr)) =>
                     {
                         let ty_changed_count = usize::from(!deref_method_same_type(expr_ty, typeck.expr_ty(sub_expr)));
                         self.state = Some((
@@ -728,7 +728,13 @@ fn deref_method_same_type<'tcx>(result_ty: Ty<'tcx>, arg_ty: Ty<'tcx>) -> bool {
     }
 }
 
-fn in_postfix_position<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'tcx>) -> bool {
+fn is_in_method_chain<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'tcx>) -> bool {
+    if let ExprKind::MethodCall(_, recv, _, _) = e.kind
+        && matches!(recv.kind, ExprKind::MethodCall(..))
+    {
+        return true;
+    }
+
     if let Some(parent) = get_parent_expr(cx, e)
         && parent.span.eq_ctxt(e.span)
     {
@@ -986,6 +992,15 @@ fn report<'tcx>(
             );
         },
         State::DerefedBorrow(state) => {
+            // Do not suggest removing a non-mandatory `&` in `&*rawptr` in an `unsafe` context,
+            // as this may make rustc trigger its `dangerous_implicit_autorefs` lint.
+            if let ExprKind::AddrOf(BorrowKind::Ref, _, subexpr) = data.first_expr.kind
+                && let ExprKind::Unary(UnOp::Deref, subsubexpr) = subexpr.kind
+                && cx.typeck_results().expr_ty_adjusted(subsubexpr).is_raw_ptr()
+            {
+                return;
+            }
+
             let mut app = Applicability::MachineApplicable;
             let (snip, snip_is_macro) =
                 snippet_with_context(cx, expr.span, data.first_expr.span.ctxt(), "..", &mut app);
diff --git a/src/tools/clippy/clippy_lints/src/derive.rs b/src/tools/clippy/clippy_lints/src/derive.rs
index 3443b36eb4f..062f7cef3a7 100644
--- a/src/tools/clippy/clippy_lints/src/derive.rs
+++ b/src/tools/clippy/clippy_lints/src/derive.rs
@@ -345,7 +345,7 @@ fn check_copy_clone<'tcx>(cx: &LateContext<'tcx>, item: &Item<'_>, trait_ref: &h
     if ty_adt.repr().packed()
         && ty_subs
             .iter()
-            .any(|arg| matches!(arg.unpack(), GenericArgKind::Type(_) | GenericArgKind::Const(_)))
+            .any(|arg| matches!(arg.kind(), GenericArgKind::Type(_) | GenericArgKind::Const(_)))
     {
         return;
     }
diff --git a/src/tools/clippy/clippy_lints/src/disallowed_types.rs b/src/tools/clippy/clippy_lints/src/disallowed_types.rs
index d0b2f0c8407..821bb25d2ce 100644
--- a/src/tools/clippy/clippy_lints/src/disallowed_types.rs
+++ b/src/tools/clippy/clippy_lints/src/disallowed_types.rs
@@ -106,8 +106,8 @@ impl_lint_pass!(DisallowedTypes => [DISALLOWED_TYPES]);
 impl<'tcx> LateLintPass<'tcx> for DisallowedTypes {
     fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) {
         if let ItemKind::Use(path, UseKind::Single(_)) = &item.kind {
-            for res in &path.res {
-                self.check_res_emit(cx, res, item.span);
+            if let Some(res) = path.res.type_ns {
+                self.check_res_emit(cx, &res, item.span);
             }
         }
     }
diff --git a/src/tools/clippy/clippy_lints/src/doc/lazy_continuation.rs b/src/tools/clippy/clippy_lints/src/doc/lazy_continuation.rs
index 8aeb835fe39..cb9d68224db 100644
--- a/src/tools/clippy/clippy_lints/src/doc/lazy_continuation.rs
+++ b/src/tools/clippy/clippy_lints/src/doc/lazy_continuation.rs
@@ -2,11 +2,10 @@ use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then};
 use itertools::Itertools;
 use rustc_errors::Applicability;
 use rustc_lint::LateContext;
-use rustc_span::{BytePos, Span};
-use std::cmp::Ordering;
+use rustc_span::BytePos;
 use std::ops::Range;
 
-use super::{DOC_LAZY_CONTINUATION, DOC_OVERINDENTED_LIST_ITEMS};
+use super::{DOC_LAZY_CONTINUATION, DOC_OVERINDENTED_LIST_ITEMS, Fragments};
 
 fn map_container_to_text(c: &super::Container) -> &'static str {
     match c {
@@ -19,29 +18,27 @@ fn map_container_to_text(c: &super::Container) -> &'static str {
 pub(super) fn check(
     cx: &LateContext<'_>,
     doc: &str,
-    range: Range<usize>,
-    mut span: Span,
+    cooked_range: Range<usize>,
+    fragments: &Fragments<'_>,
     containers: &[super::Container],
 ) {
-    if doc[range.clone()].contains('\t') {
-        // We don't do tab stops correctly.
-        return;
-    }
-
-    // Blockquote
-    let ccount = doc[range.clone()].chars().filter(|c| *c == '>').count();
+    // Get blockquotes
+    let ccount = doc[cooked_range.clone()].chars().filter(|c| *c == '>').count();
     let blockquote_level = containers
         .iter()
         .filter(|c| matches!(c, super::Container::Blockquote))
         .count();
-    if ccount < blockquote_level {
+
+    if ccount < blockquote_level
+        && let Some(mut span) = fragments.span(cx, cooked_range.clone())
+    {
         span_lint_and_then(
             cx,
             DOC_LAZY_CONTINUATION,
             span,
             "doc quote line without `>` marker",
             |diag| {
-                let mut doc_start_range = &doc[range];
+                let mut doc_start_range = &doc[cooked_range];
                 let mut suggested = String::new();
                 for c in containers {
                     let text = map_container_to_text(c);
@@ -78,7 +75,7 @@ pub(super) fn check(
     }
 
     // List
-    let leading_spaces = doc[range].chars().filter(|c| *c == ' ').count();
+    let leading_spaces = doc[cooked_range.clone()].chars().filter(|c| *c == ' ').count();
     let list_indentation = containers
         .iter()
         .map(|c| {
@@ -89,36 +86,41 @@ pub(super) fn check(
             }
         })
         .sum();
-    match leading_spaces.cmp(&list_indentation) {
-        Ordering::Less => span_lint_and_then(
-            cx,
-            DOC_LAZY_CONTINUATION,
-            span,
-            "doc list item without indentation",
-            |diag| {
-                // simpler suggestion style for indentation
-                let indent = list_indentation - leading_spaces;
-                diag.span_suggestion_verbose(
-                    span.shrink_to_hi(),
-                    "indent this line",
-                    std::iter::repeat_n(" ", indent).join(""),
-                    Applicability::MaybeIncorrect,
-                );
-                diag.help("if this is supposed to be its own paragraph, add a blank line");
-            },
-        ),
-        Ordering::Greater => {
-            let sugg = std::iter::repeat_n(" ", list_indentation).join("");
-            span_lint_and_sugg(
+
+    if leading_spaces != list_indentation
+        && let Some(span) = fragments.span(cx, cooked_range.clone())
+    {
+        if leading_spaces < list_indentation {
+            span_lint_and_then(
                 cx,
-                DOC_OVERINDENTED_LIST_ITEMS,
+                DOC_LAZY_CONTINUATION,
                 span,
-                "doc list item overindented",
-                format!("try using `{sugg}` ({list_indentation} spaces)"),
-                sugg,
-                Applicability::MaybeIncorrect,
+                "doc list item without indentation",
+                |diag| {
+                    // simpler suggestion style for indentation
+                    let indent = list_indentation - leading_spaces;
+                    diag.span_suggestion_verbose(
+                        span.shrink_to_hi(),
+                        "indent this line",
+                        std::iter::repeat_n(" ", indent).join(""),
+                        Applicability::MaybeIncorrect,
+                    );
+                    diag.help("if this is supposed to be its own paragraph, add a blank line");
+                },
             );
-        },
-        Ordering::Equal => {},
+
+            return;
+        }
+
+        let sugg = std::iter::repeat_n(" ", list_indentation).join("");
+        span_lint_and_sugg(
+            cx,
+            DOC_OVERINDENTED_LIST_ITEMS,
+            span,
+            "doc list item overindented",
+            format!("try using `{sugg}` ({list_indentation} spaces)"),
+            sugg,
+            Applicability::MaybeIncorrect,
+        );
     }
 }
diff --git a/src/tools/clippy/clippy_lints/src/doc/markdown.rs b/src/tools/clippy/clippy_lints/src/doc/markdown.rs
index 7a1c7c675d2..69c3b9150c3 100644
--- a/src/tools/clippy/clippy_lints/src/doc/markdown.rs
+++ b/src/tools/clippy/clippy_lints/src/doc/markdown.rs
@@ -6,13 +6,15 @@ use rustc_lint::LateContext;
 use rustc_span::{BytePos, Pos, Span};
 use url::Url;
 
-use crate::doc::DOC_MARKDOWN;
+use crate::doc::{DOC_MARKDOWN, Fragments};
+use std::ops::Range;
 
 pub fn check(
     cx: &LateContext<'_>,
     valid_idents: &FxHashSet<String>,
     text: &str,
-    span: Span,
+    fragments: &Fragments<'_>,
+    fragment_range: Range<usize>,
     code_level: isize,
     blockquote_level: isize,
 ) {
@@ -64,20 +66,31 @@ pub fn check(
             close_parens += 1;
         }
 
+        // We'll use this offset to calculate the span to lint.
+        let fragment_offset = word.as_ptr() as usize - text.as_ptr() as usize;
+
         // Adjust for the current word
-        let offset = word.as_ptr() as usize - text.as_ptr() as usize;
-        let span = Span::new(
-            span.lo() + BytePos::from_usize(offset),
-            span.lo() + BytePos::from_usize(offset + word.len()),
-            span.ctxt(),
-            span.parent(),
+        check_word(
+            cx,
+            word,
+            fragments,
+            &fragment_range,
+            fragment_offset,
+            code_level,
+            blockquote_level,
         );
-
-        check_word(cx, word, span, code_level, blockquote_level);
     }
 }
 
-fn check_word(cx: &LateContext<'_>, word: &str, span: Span, code_level: isize, blockquote_level: isize) {
+fn check_word(
+    cx: &LateContext<'_>,
+    word: &str,
+    fragments: &Fragments<'_>,
+    range: &Range<usize>,
+    fragment_offset: usize,
+    code_level: isize,
+    blockquote_level: isize,
+) {
     /// Checks if a string is upper-camel-case, i.e., starts with an uppercase and
     /// contains at least two uppercase letters (`Clippy` is ok) and one lower-case
     /// letter (`NASA` is ok).
@@ -117,6 +130,16 @@ fn check_word(cx: &LateContext<'_>, word: &str, span: Span, code_level: isize, b
         // try to get around the fact that `foo::bar` parses as a valid URL
         && !url.cannot_be_a_base()
     {
+        let Some(fragment_span) = fragments.span(cx, range.clone()) else {
+            return;
+        };
+        let span = Span::new(
+            fragment_span.lo() + BytePos::from_usize(fragment_offset),
+            fragment_span.lo() + BytePos::from_usize(fragment_offset + word.len()),
+            fragment_span.ctxt(),
+            fragment_span.parent(),
+        );
+
         span_lint_and_sugg(
             cx,
             DOC_MARKDOWN,
@@ -137,6 +160,17 @@ fn check_word(cx: &LateContext<'_>, word: &str, span: Span, code_level: isize, b
     }
 
     if has_underscore(word) || word.contains("::") || is_camel_case(word) || word.ends_with("()") {
+        let Some(fragment_span) = fragments.span(cx, range.clone()) else {
+            return;
+        };
+
+        let span = Span::new(
+            fragment_span.lo() + BytePos::from_usize(fragment_offset),
+            fragment_span.lo() + BytePos::from_usize(fragment_offset + word.len()),
+            fragment_span.ctxt(),
+            fragment_span.parent(),
+        );
+
         span_lint_and_then(
             cx,
             DOC_MARKDOWN,
diff --git a/src/tools/clippy/clippy_lints/src/doc/mod.rs b/src/tools/clippy/clippy_lints/src/doc/mod.rs
index 87da380e954..c46dd09d60c 100644
--- a/src/tools/clippy/clippy_lints/src/doc/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/doc/mod.rs
@@ -3,7 +3,6 @@
 use clippy_config::Conf;
 use clippy_utils::attrs::is_doc_hidden;
 use clippy_utils::diagnostics::{span_lint, span_lint_and_help, span_lint_and_then};
-use clippy_utils::source::snippet_opt;
 use clippy_utils::{is_entrypoint_fn, is_trait_impl_item};
 use pulldown_cmark::Event::{
     Code, DisplayMath, End, FootnoteReference, HardBreak, Html, InlineHtml, InlineMath, Rule, SoftBreak, Start,
@@ -730,7 +729,10 @@ struct Fragments<'a> {
 }
 
 impl Fragments<'_> {
-    fn span(self, cx: &LateContext<'_>, range: Range<usize>) -> Option<Span> {
+    /// get the span for the markdown range. Note that this function is not cheap, use it with
+    /// caution.
+    #[must_use]
+    fn span(&self, cx: &LateContext<'_>, range: Range<usize>) -> Option<Span> {
         source_span_for_markdown_range(cx.tcx, self.doc, &range, self.fragments)
     }
 }
@@ -1068,9 +1070,7 @@ fn check_doc<'a, Events: Iterator<Item = (pulldown_cmark::Event<'a>, Range<usize
                     );
                 } else {
                     for (text, range, assoc_code_level) in text_to_check {
-                        if let Some(span) = fragments.span(cx, range) {
-                            markdown::check(cx, valid_idents, &text, span, assoc_code_level, blockquote_level);
-                        }
+                        markdown::check(cx, valid_idents, &text, &fragments, range, assoc_code_level, blockquote_level);
                     }
                 }
                 text_to_check = Vec::new();
@@ -1081,26 +1081,27 @@ fn check_doc<'a, Events: Iterator<Item = (pulldown_cmark::Event<'a>, Range<usize
             | TaskListMarker(_) | Code(_) | Rule | InlineMath(..) | DisplayMath(..) => (),
             SoftBreak | HardBreak => {
                 if !containers.is_empty()
-                    && let Some((next_event, next_range)) = events.peek()
-                    && let Some(next_span) = fragments.span(cx, next_range.clone())
-                    && let Some(span) = fragments.span(cx, range.clone())
                     && !in_footnote_definition
+                    // Tabs aren't handled correctly vvvv
+                    && !doc[range.clone()].contains('\t')
+                    && let Some((next_event, next_range)) = events.peek()
                     && !matches!(next_event, End(_))
                 {
                     lazy_continuation::check(
                         cx,
                         doc,
                         range.end..next_range.start,
-                        Span::new(span.hi(), next_span.lo(), span.ctxt(), span.parent()),
+                        &fragments,
                         &containers[..],
                     );
                 }
 
-                if let Some(span) = fragments.span(cx, range.clone())
+
+                if event == HardBreak
+                    && !doc[range.clone()].trim().starts_with('\\')
+                    && let Some(span) = fragments.span(cx, range.clone())
                     && !span.from_expansion()
-                    && let Some(snippet) = snippet_opt(cx, span)
-                    && !snippet.trim().starts_with('\\')
-                    && event == HardBreak {
+                    {
                     collected_breaks.push(span);
                 }
             },
diff --git a/src/tools/clippy/clippy_lints/src/empty_with_brackets.rs b/src/tools/clippy/clippy_lints/src/empty_with_brackets.rs
index 8c12364883c..4414aebbf9a 100644
--- a/src/tools/clippy/clippy_lints/src/empty_with_brackets.rs
+++ b/src/tools/clippy/clippy_lints/src/empty_with_brackets.rs
@@ -92,7 +92,7 @@ impl_lint_pass!(EmptyWithBrackets => [EMPTY_STRUCTS_WITH_BRACKETS, EMPTY_ENUM_VA
 
 impl LateLintPass<'_> for EmptyWithBrackets {
     fn check_item(&mut self, cx: &LateContext<'_>, item: &Item<'_>) {
-        if let ItemKind::Struct(ident, var_data, _) = &item.kind
+        if let ItemKind::Struct(ident, _, var_data) = &item.kind
             && !item.span.from_expansion()
             && has_brackets(var_data)
             && let span_after_ident = item.span.with_lo(ident.span.hi())
diff --git a/src/tools/clippy/clippy_lints/src/enum_clike.rs b/src/tools/clippy/clippy_lints/src/enum_clike.rs
index ec81294624e..098571a5351 100644
--- a/src/tools/clippy/clippy_lints/src/enum_clike.rs
+++ b/src/tools/clippy/clippy_lints/src/enum_clike.rs
@@ -38,7 +38,7 @@ impl<'tcx> LateLintPass<'tcx> for UnportableVariant {
         if cx.tcx.data_layout.pointer_size.bits() != 64 {
             return;
         }
-        if let ItemKind::Enum(_, def, _) = &item.kind {
+        if let ItemKind::Enum(_, _, def) = &item.kind {
             for var in def.variants {
                 if let Some(anon_const) = &var.disr_expr {
                     let def_id = cx.tcx.hir_body_owner_def_id(anon_const.body);
diff --git a/src/tools/clippy/clippy_lints/src/eta_reduction.rs b/src/tools/clippy/clippy_lints/src/eta_reduction.rs
index 645f9306849..6ed7c87915b 100644
--- a/src/tools/clippy/clippy_lints/src/eta_reduction.rs
+++ b/src/tools/clippy/clippy_lints/src/eta_reduction.rs
@@ -306,7 +306,7 @@ fn has_late_bound_to_non_late_bound_regions(from_sig: FnSig<'_>, to_sig: FnSig<'
             return true;
         }
         for (from_arg, to_arg) in to_subs.iter().zip(from_subs) {
-            match (from_arg.unpack(), to_arg.unpack()) {
+            match (from_arg.kind(), to_arg.kind()) {
                 (GenericArgKind::Lifetime(from_region), GenericArgKind::Lifetime(to_region)) => {
                     if check_region(from_region, to_region) {
                         return true;
@@ -354,5 +354,5 @@ fn has_late_bound_to_non_late_bound_regions(from_sig: FnSig<'_>, to_sig: FnSig<'
 
 fn ty_has_static(ty: Ty<'_>) -> bool {
     ty.walk()
-        .any(|arg| matches!(arg.unpack(), GenericArgKind::Lifetime(re) if re.is_static()))
+        .any(|arg| matches!(arg.kind(), GenericArgKind::Lifetime(re) if re.is_static()))
 }
diff --git a/src/tools/clippy/clippy_lints/src/excessive_bools.rs b/src/tools/clippy/clippy_lints/src/excessive_bools.rs
index 38d115b878c..686dc5c3c4f 100644
--- a/src/tools/clippy/clippy_lints/src/excessive_bools.rs
+++ b/src/tools/clippy/clippy_lints/src/excessive_bools.rs
@@ -127,7 +127,7 @@ fn check_fn_decl(cx: &LateContext<'_>, decl: &FnDecl<'_>, sp: Span, max: u64) {
 
 impl<'tcx> LateLintPass<'tcx> for ExcessiveBools {
     fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) {
-        if let ItemKind::Struct(_, variant_data, _) = &item.kind
+        if let ItemKind::Struct(_, _, variant_data) = &item.kind
             && variant_data.fields().len() as u64 > self.max_struct_bools
             && has_n_bools(
                 variant_data.fields().iter().map(|field| field.ty),
diff --git a/src/tools/clippy/clippy_lints/src/exhaustive_items.rs b/src/tools/clippy/clippy_lints/src/exhaustive_items.rs
index 5a74e97c97c..1fb0e4d24d0 100644
--- a/src/tools/clippy/clippy_lints/src/exhaustive_items.rs
+++ b/src/tools/clippy/clippy_lints/src/exhaustive_items.rs
@@ -76,7 +76,7 @@ impl LateLintPass<'_> for ExhaustiveItems {
                 "exported enums should not be exhaustive",
                 [].as_slice(),
             ),
-            ItemKind::Struct(_, v, ..) => (
+            ItemKind::Struct(_, _, v) => (
                 EXHAUSTIVE_STRUCTS,
                 "exported structs should not be exhaustive",
                 v.fields(),
diff --git a/src/tools/clippy/clippy_lints/src/field_scoped_visibility_modifiers.rs b/src/tools/clippy/clippy_lints/src/field_scoped_visibility_modifiers.rs
index aae8291905d..dfb0b4f103c 100644
--- a/src/tools/clippy/clippy_lints/src/field_scoped_visibility_modifiers.rs
+++ b/src/tools/clippy/clippy_lints/src/field_scoped_visibility_modifiers.rs
@@ -51,7 +51,7 @@ declare_lint_pass!(FieldScopedVisibilityModifiers => [FIELD_SCOPED_VISIBILITY_MO
 
 impl EarlyLintPass for FieldScopedVisibilityModifiers {
     fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) {
-        let ItemKind::Struct(_, ref st, _) = item.kind else {
+        let ItemKind::Struct(_, _, ref st) = item.kind else {
             return;
         };
         for field in st.fields() {
diff --git a/src/tools/clippy/clippy_lints/src/functions/ref_option.rs b/src/tools/clippy/clippy_lints/src/functions/ref_option.rs
index aba0fbcb9fe..106202d00d4 100644
--- a/src/tools/clippy/clippy_lints/src/functions/ref_option.rs
+++ b/src/tools/clippy/clippy_lints/src/functions/ref_option.rs
@@ -17,7 +17,7 @@ fn check_ty<'a>(cx: &LateContext<'a>, param: &rustc_hir::Ty<'a>, param_ty: Ty<'a
         && is_type_diagnostic_item(cx, *opt_ty, sym::Option)
         && let ty::Adt(_, opt_gen_args) = opt_ty.kind()
         && let [gen_arg] = opt_gen_args.as_slice()
-        && let GenericArgKind::Type(gen_ty) = gen_arg.unpack()
+        && let GenericArgKind::Type(gen_ty) = gen_arg.kind()
         && !gen_ty.is_ref()
         // Need to gen the original spans, so first parsing mid, and hir parsing afterward
         && let hir::TyKind::Ref(lifetime, hir::MutTy { ty, .. }) = param.kind
diff --git a/src/tools/clippy/clippy_lints/src/functions/result.rs b/src/tools/clippy/clippy_lints/src/functions/result.rs
index 00ce4cfcc52..bb98ae82611 100644
--- a/src/tools/clippy/clippy_lints/src/functions/result.rs
+++ b/src/tools/clippy/clippy_lints/src/functions/result.rs
@@ -103,7 +103,7 @@ fn check_result_large_err<'tcx>(cx: &LateContext<'tcx>, err_ty: Ty<'tcx>, hir_ty
             .did()
             .as_local()
         && let hir::Node::Item(item) = cx.tcx.hir_node_by_def_id(local_def_id)
-        && let hir::ItemKind::Enum(_, ref def, _) = item.kind
+        && let hir::ItemKind::Enum(_, _, ref def) = item.kind
     {
         let variants_size = AdtVariantInfo::new(cx, *adt, subst);
         if let Some((first_variant, variants)) = variants_size.split_first()
diff --git a/src/tools/clippy/clippy_lints/src/index_refutable_slice.rs b/src/tools/clippy/clippy_lints/src/index_refutable_slice.rs
index 0b1cae30ca5..3d131a7825a 100644
--- a/src/tools/clippy/clippy_lints/src/index_refutable_slice.rs
+++ b/src/tools/clippy/clippy_lints/src/index_refutable_slice.rs
@@ -12,7 +12,6 @@ use rustc_hir::HirId;
 use rustc_hir::intravisit::{self, Visitor};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::hir::nested_filter;
-use rustc_middle::ty;
 use rustc_session::impl_lint_pass;
 use rustc_span::Span;
 use rustc_span::symbol::Ident;
@@ -109,11 +108,11 @@ fn find_slice_values(cx: &LateContext<'_>, pat: &hir::Pat<'_>) -> FxIndexMap<Hir
             }
 
             let bound_ty = cx.typeck_results().node_type(pat.hir_id);
-            if let ty::Slice(inner_ty) | ty::Array(inner_ty, _) = bound_ty.peel_refs().kind() {
+            if let Some(inner_ty) = bound_ty.peel_refs().builtin_index() {
                 // The values need to use the `ref` keyword if they can't be copied.
                 // This will need to be adjusted if the lint want to support mutable access in the future
                 let src_is_ref = bound_ty.is_ref() && by_ref == hir::ByRef::No;
-                let needs_ref = !(src_is_ref || is_copy(cx, *inner_ty));
+                let needs_ref = !(src_is_ref || is_copy(cx, inner_ty));
 
                 let slice_info = slices
                     .entry(value_hir_id)
diff --git a/src/tools/clippy/clippy_lints/src/item_name_repetitions.rs b/src/tools/clippy/clippy_lints/src/item_name_repetitions.rs
index 3d4dcd02070..9c91cf68085 100644
--- a/src/tools/clippy/clippy_lints/src/item_name_repetitions.rs
+++ b/src/tools/clippy/clippy_lints/src/item_name_repetitions.rs
@@ -535,10 +535,10 @@ impl LateLintPass<'_> for ItemNameRepetitions {
 
         if span_is_local(item.span) {
             match item.kind {
-                ItemKind::Enum(_, def, _) => {
+                ItemKind::Enum(_, _, def) => {
                     self.check_variants(cx, item, &def);
                 },
-                ItemKind::Struct(_, VariantData::Struct { fields, .. }, _) => {
+                ItemKind::Struct(_, _, VariantData::Struct { fields, .. }) => {
                     self.check_fields(cx, item, fields);
                 },
                 _ => (),
diff --git a/src/tools/clippy/clippy_lints/src/large_const_arrays.rs b/src/tools/clippy/clippy_lints/src/large_const_arrays.rs
index 394005e9912..cee8ca1261e 100644
--- a/src/tools/clippy/clippy_lints/src/large_const_arrays.rs
+++ b/src/tools/clippy/clippy_lints/src/large_const_arrays.rs
@@ -48,7 +48,7 @@ impl_lint_pass!(LargeConstArrays => [LARGE_CONST_ARRAYS]);
 
 impl<'tcx> LateLintPass<'tcx> for LargeConstArrays {
     fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
-        if let ItemKind::Const(ident, _, generics, _) = &item.kind
+        if let ItemKind::Const(ident, generics, _, _) = &item.kind
             // Since static items may not have generics, skip generic const items.
             // FIXME(generic_const_items): I don't think checking `generics.hwcp` suffices as it
             // doesn't account for empty where-clauses that only consist of keyword `where` IINM.
diff --git a/src/tools/clippy/clippy_lints/src/large_enum_variant.rs b/src/tools/clippy/clippy_lints/src/large_enum_variant.rs
index d08efa0ec9c..e85d779b488 100644
--- a/src/tools/clippy/clippy_lints/src/large_enum_variant.rs
+++ b/src/tools/clippy/clippy_lints/src/large_enum_variant.rs
@@ -73,7 +73,7 @@ impl_lint_pass!(LargeEnumVariant => [LARGE_ENUM_VARIANT]);
 
 impl<'tcx> LateLintPass<'tcx> for LargeEnumVariant {
     fn check_item(&mut self, cx: &LateContext<'tcx>, item: &Item<'tcx>) {
-        if let ItemKind::Enum(ident, ref def, _) = item.kind
+        if let ItemKind::Enum(ident, _, ref def) = item.kind
             && let ty = cx.tcx.type_of(item.owner_id).instantiate_identity()
             && let ty::Adt(adt, subst) = ty.kind()
             && adt.variants().len() > 1
diff --git a/src/tools/clippy/clippy_lints/src/legacy_numeric_constants.rs b/src/tools/clippy/clippy_lints/src/legacy_numeric_constants.rs
index 01b49403cac..b3c63f022d3 100644
--- a/src/tools/clippy/clippy_lints/src/legacy_numeric_constants.rs
+++ b/src/tools/clippy/clippy_lints/src/legacy_numeric_constants.rs
@@ -51,7 +51,9 @@ impl<'tcx> LateLintPass<'tcx> for LegacyNumericConstants {
         // so lint on the `use` statement directly.
         if let ItemKind::Use(path, kind @ (UseKind::Single(_) | UseKind::Glob)) = item.kind
             && !item.span.in_external_macro(cx.sess().source_map())
-            && let Some(def_id) = path.res[0].opt_def_id()
+            // use `present_items` because it could be in either type_ns or value_ns
+            && let Some(res) = path.res.present_items().next()
+            && let Some(def_id) = res.opt_def_id()
             && self.msrv.meets(cx, msrvs::NUMERIC_ASSOCIATED_CONSTANTS)
         {
             let module = if is_integer_module(cx, def_id) {
diff --git a/src/tools/clippy/clippy_lints/src/let_underscore.rs b/src/tools/clippy/clippy_lints/src/let_underscore.rs
index 916191b2a7b..b72e14246db 100644
--- a/src/tools/clippy/clippy_lints/src/let_underscore.rs
+++ b/src/tools/clippy/clippy_lints/src/let_underscore.rs
@@ -137,7 +137,7 @@ impl<'tcx> LateLintPass<'tcx> for LetUnderscore {
             && !local.span.in_external_macro(cx.tcx.sess.source_map())
         {
             let init_ty = cx.typeck_results().expr_ty(init);
-            let contains_sync_guard = init_ty.walk().any(|inner| match inner.unpack() {
+            let contains_sync_guard = init_ty.walk().any(|inner| match inner.kind() {
                 GenericArgKind::Type(inner_ty) => inner_ty
                     .ty_adt_def()
                     .is_some_and(|adt| paths::PARKING_LOT_GUARDS.iter().any(|path| path.matches(cx, adt.did()))),
diff --git a/src/tools/clippy/clippy_lints/src/loops/manual_find.rs b/src/tools/clippy/clippy_lints/src/loops/manual_find.rs
index 35737f3eafe..f99989ec6ba 100644
--- a/src/tools/clippy/clippy_lints/src/loops/manual_find.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/manual_find.rs
@@ -83,6 +83,13 @@ pub(super) fn check<'tcx>(
                 )[..],
             );
         }
+
+        // If the return type requires adjustments, we need to add a `.map` after the iterator
+        let inner_ret_adjust = cx.typeck_results().expr_adjustments(inner_ret);
+        if !inner_ret_adjust.is_empty() {
+            snippet.push_str(".map(|v| v as _)");
+        }
+
         // Extends to `last_stmt` to include semicolon in case of `return None;`
         let lint_span = span.to(last_stmt.span).to(last_ret.span);
         span_lint_and_then(
diff --git a/src/tools/clippy/clippy_lints/src/loops/manual_flatten.rs b/src/tools/clippy/clippy_lints/src/loops/manual_flatten.rs
index 9b6f97b9a2e..81f14b7b2b0 100644
--- a/src/tools/clippy/clippy_lints/src/loops/manual_flatten.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/manual_flatten.rs
@@ -3,7 +3,7 @@ use super::utils::make_iterator_snippet;
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::msrvs::{self, Msrv};
 use clippy_utils::visitors::is_local_used;
-use clippy_utils::{higher, path_to_local_id, peel_blocks_with_stmt};
+use clippy_utils::{higher, is_refutable, path_to_local_id, peel_blocks_with_stmt};
 use rustc_errors::Applicability;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::{Expr, Pat, PatKind};
@@ -28,7 +28,7 @@ pub(super) fn check<'tcx>(
         && let PatKind::Binding(_, pat_hir_id, _, _) = pat.kind
         && path_to_local_id(let_expr, pat_hir_id)
         // Ensure the `if let` statement is for the `Some` variant of `Option` or the `Ok` variant of `Result`
-        && let PatKind::TupleStruct(ref qpath, _, _) = let_pat.kind
+        && let PatKind::TupleStruct(ref qpath, [inner_pat], _) = let_pat.kind
         && let Res::Def(DefKind::Ctor(..), ctor_id) = cx.qpath_res(qpath, let_pat.hir_id)
         && let Some(variant_id) = cx.tcx.opt_parent(ctor_id)
         && let some_ctor = cx.tcx.lang_items().option_some_variant() == Some(variant_id)
@@ -37,6 +37,7 @@ pub(super) fn check<'tcx>(
         // Ensure expr in `if let` is not used afterwards
         && !is_local_used(cx, if_then, pat_hir_id)
         && msrv.meets(cx, msrvs::ITER_FLATTEN)
+        && !is_refutable(cx, inner_pat)
     {
         let if_let_type = if some_ctor { "Some" } else { "Ok" };
         // Prepare the error message
diff --git a/src/tools/clippy/clippy_lints/src/loops/while_let_loop.rs b/src/tools/clippy/clippy_lints/src/loops/while_let_loop.rs
index bd04827a1f0..845edb9cae1 100644
--- a/src/tools/clippy/clippy_lints/src/loops/while_let_loop.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/while_let_loop.rs
@@ -1,68 +1,65 @@
 use super::WHILE_LET_LOOP;
 use clippy_utils::diagnostics::span_lint_and_sugg;
-use clippy_utils::higher;
-use clippy_utils::source::snippet_with_applicability;
+use clippy_utils::source::{snippet, snippet_indent, snippet_opt};
 use clippy_utils::ty::needs_ordered_drop;
 use clippy_utils::visitors::any_temporaries_need_ordered_drop;
+use clippy_utils::{higher, peel_blocks};
+use rustc_ast::BindingMode;
 use rustc_errors::Applicability;
-use rustc_hir::{Block, Expr, ExprKind, LetStmt, MatchSource, Pat, StmtKind};
+use rustc_hir::{Block, Expr, ExprKind, LetStmt, MatchSource, Pat, PatKind, Path, QPath, StmtKind, Ty};
 use rustc_lint::LateContext;
 
 pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, loop_block: &'tcx Block<'_>) {
-    let (init, has_trailing_exprs) = match (loop_block.stmts, loop_block.expr) {
-        ([stmt, stmts @ ..], expr) => {
-            if let StmtKind::Let(&LetStmt {
+    let (init, let_info) = match (loop_block.stmts, loop_block.expr) {
+        ([stmt, ..], _) => match stmt.kind {
+            StmtKind::Let(LetStmt {
                 init: Some(e),
                 els: None,
+                pat,
+                ty,
                 ..
-            })
-            | StmtKind::Semi(e)
-            | StmtKind::Expr(e) = stmt.kind
-            {
-                (e, !stmts.is_empty() || expr.is_some())
-            } else {
-                return;
-            }
+            }) => (*e, Some((*pat, *ty))),
+            StmtKind::Semi(e) | StmtKind::Expr(e) => (e, None),
+            _ => return,
         },
-        ([], Some(e)) => (e, false),
+        ([], Some(e)) => (e, None),
         _ => return,
     };
+    let has_trailing_exprs = loop_block.stmts.len() + usize::from(loop_block.expr.is_some()) > 1;
 
     if let Some(if_let) = higher::IfLet::hir(cx, init)
         && let Some(else_expr) = if_let.if_else
         && is_simple_break_expr(else_expr)
     {
-        could_be_while_let(cx, expr, if_let.let_pat, if_let.let_expr, has_trailing_exprs);
+        could_be_while_let(
+            cx,
+            expr,
+            if_let.let_pat,
+            if_let.let_expr,
+            has_trailing_exprs,
+            let_info,
+            if_let.if_then,
+        );
     } else if let ExprKind::Match(scrutinee, [arm1, arm2], MatchSource::Normal) = init.kind
         && arm1.guard.is_none()
         && arm2.guard.is_none()
         && is_simple_break_expr(arm2.body)
     {
-        could_be_while_let(cx, expr, arm1.pat, scrutinee, has_trailing_exprs);
+        could_be_while_let(cx, expr, arm1.pat, scrutinee, has_trailing_exprs, let_info, arm1.body);
     }
 }
 
-/// Returns `true` if expr contains a single break expression without a label or eub-expression.
+/// Returns `true` if expr contains a single break expression without a label or sub-expression,
+/// possibly embedded in blocks.
 fn is_simple_break_expr(e: &Expr<'_>) -> bool {
-    matches!(peel_blocks(e).kind, ExprKind::Break(dest, None) if dest.label.is_none())
-}
-
-/// Removes any blocks containing only a single expression.
-fn peel_blocks<'tcx>(e: &'tcx Expr<'tcx>) -> &'tcx Expr<'tcx> {
     if let ExprKind::Block(b, _) = e.kind {
         match (b.stmts, b.expr) {
-            ([s], None) => {
-                if let StmtKind::Expr(e) | StmtKind::Semi(e) = s.kind {
-                    peel_blocks(e)
-                } else {
-                    e
-                }
-            },
-            ([], Some(e)) => peel_blocks(e),
-            _ => e,
+            ([s], None) => matches!(s.kind, StmtKind::Expr(e) | StmtKind::Semi(e) if is_simple_break_expr(e)),
+            ([], Some(e)) => is_simple_break_expr(e),
+            _ => false,
         }
     } else {
-        e
+        matches!(e.kind, ExprKind::Break(dest, None) if dest.label.is_none())
     }
 }
 
@@ -72,6 +69,8 @@ fn could_be_while_let<'tcx>(
     let_pat: &'tcx Pat<'_>,
     let_expr: &'tcx Expr<'_>,
     has_trailing_exprs: bool,
+    let_info: Option<(&Pat<'_>, Option<&Ty<'_>>)>,
+    inner_expr: &Expr<'_>,
 ) {
     if has_trailing_exprs
         && (needs_ordered_drop(cx, cx.typeck_results().expr_ty(let_expr))
@@ -86,7 +85,24 @@ fn could_be_while_let<'tcx>(
     // 1) it was ugly with big bodies;
     // 2) it was not indented properly;
     // 3) it wasn’t very smart (see #675).
-    let mut applicability = Applicability::HasPlaceholders;
+    let inner_content = if let Some((pat, ty)) = let_info
+        // Prevent trivial reassignments such as `let x = x;` or `let _ = …;`, but
+        // keep them if the type has been explicitly specified.
+        && (!is_trivial_assignment(pat, peel_blocks(inner_expr)) || ty.is_some())
+        && let Some(pat_str) = snippet_opt(cx, pat.span)
+        && let Some(init_str) = snippet_opt(cx, peel_blocks(inner_expr).span)
+    {
+        let ty_str = ty
+            .map(|ty| format!(": {}", snippet(cx, ty.span, "_")))
+            .unwrap_or_default();
+        format!(
+            "\n{indent}    let {pat_str}{ty_str} = {init_str};\n{indent}    ..\n{indent}",
+            indent = snippet_indent(cx, expr.span).unwrap_or_default(),
+        )
+    } else {
+        " .. ".into()
+    };
+
     span_lint_and_sugg(
         cx,
         WHILE_LET_LOOP,
@@ -94,10 +110,21 @@ fn could_be_while_let<'tcx>(
         "this loop could be written as a `while let` loop",
         "try",
         format!(
-            "while let {} = {} {{ .. }}",
-            snippet_with_applicability(cx, let_pat.span, "..", &mut applicability),
-            snippet_with_applicability(cx, let_expr.span, "..", &mut applicability),
+            "while let {} = {} {{{inner_content}}}",
+            snippet(cx, let_pat.span, ".."),
+            snippet(cx, let_expr.span, ".."),
         ),
-        applicability,
+        Applicability::HasPlaceholders,
     );
 }
+
+fn is_trivial_assignment(pat: &Pat<'_>, init: &Expr<'_>) -> bool {
+    match (pat.kind, init.kind) {
+        (PatKind::Wild, _) => true,
+        (
+            PatKind::Binding(BindingMode::NONE, _, pat_ident, None),
+            ExprKind::Path(QPath::Resolved(None, Path { segments: [init], .. })),
+        ) => pat_ident.name == init.ident.name,
+        _ => false,
+    }
+}
diff --git a/src/tools/clippy/clippy_lints/src/macro_use.rs b/src/tools/clippy/clippy_lints/src/macro_use.rs
index 98ad1f6a160..c1a26c5a9c7 100644
--- a/src/tools/clippy/clippy_lints/src/macro_use.rs
+++ b/src/tools/clippy/clippy_lints/src/macro_use.rs
@@ -100,10 +100,7 @@ impl LateLintPass<'_> for MacroUseImports {
             && let hir_id = item.hir_id()
             && let attrs = cx.tcx.hir_attrs(hir_id)
             && let Some(mac_attr) = attrs.iter().find(|attr| attr.has_name(sym::macro_use))
-            && let Some(id) = path.res.iter().find_map(|res| match res {
-                Res::Def(DefKind::Mod, id) => Some(id),
-                _ => None,
-            })
+            && let Some(Res::Def(DefKind::Mod, id)) = path.res.type_ns
             && !id.is_local()
         {
             for kid in cx.tcx.module_children(id) {
diff --git a/src/tools/clippy/clippy_lints/src/manual_non_exhaustive.rs b/src/tools/clippy/clippy_lints/src/manual_non_exhaustive.rs
index 067b92cd46e..3562b1ff5cc 100644
--- a/src/tools/clippy/clippy_lints/src/manual_non_exhaustive.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_non_exhaustive.rs
@@ -87,7 +87,7 @@ impl<'tcx> LateLintPass<'tcx> for ManualNonExhaustive {
         }
 
         match item.kind {
-            ItemKind::Enum(_, def, _) if def.variants.len() > 1 => {
+            ItemKind::Enum(_, _, def) if def.variants.len() > 1 => {
                 let iter = def.variants.iter().filter_map(|v| {
                     (matches!(v.data, VariantData::Unit(_, _)) && is_doc_hidden(cx.tcx.hir_attrs(v.hir_id)))
                         .then_some((v.def_id, v.span))
@@ -98,7 +98,7 @@ impl<'tcx> LateLintPass<'tcx> for ManualNonExhaustive {
                     self.potential_enums.push((item.owner_id.def_id, id, item.span, span));
                 }
             },
-            ItemKind::Struct(_, variant_data, _) => {
+            ItemKind::Struct(_, _, variant_data) => {
                 let fields = variant_data.fields();
                 let private_fields = fields
                     .iter()
diff --git a/src/tools/clippy/clippy_lints/src/matches/manual_unwrap_or.rs b/src/tools/clippy/clippy_lints/src/matches/manual_unwrap_or.rs
index 3ac2c9fc2b3..8c3f52542d9 100644
--- a/src/tools/clippy/clippy_lints/src/matches/manual_unwrap_or.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/manual_unwrap_or.rs
@@ -109,7 +109,7 @@ fn handle(
             && implements_trait(cx, expr_type, default_trait_id, &[])
             // We check if the initial condition implements Default.
             && let Some(condition_ty) = cx.typeck_results().expr_ty(condition).walk().nth(1)
-            && let GenericArgKind::Type(condition_ty) = condition_ty.unpack()
+            && let GenericArgKind::Type(condition_ty) = condition_ty.kind()
             && implements_trait(cx, condition_ty, default_trait_id, &[])
             && is_default_equivalent(cx, peel_blocks(body_none))
         {
diff --git a/src/tools/clippy/clippy_lints/src/matches/redundant_pattern_match.rs b/src/tools/clippy/clippy_lints/src/matches/redundant_pattern_match.rs
index aa9be61bf4d..c936c96f971 100644
--- a/src/tools/clippy/clippy_lints/src/matches/redundant_pattern_match.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/redundant_pattern_match.rs
@@ -108,7 +108,7 @@ fn find_match_true<'tcx>(
 fn try_get_generic_ty(ty: Ty<'_>, index: usize) -> Option<Ty<'_>> {
     if let ty::Adt(_, subs) = ty.kind()
         && let Some(sub) = subs.get(index)
-        && let GenericArgKind::Type(sub_ty) = sub.unpack()
+        && let GenericArgKind::Type(sub_ty) = sub.kind()
     {
         Some(sub_ty)
     } else {
diff --git a/src/tools/clippy/clippy_lints/src/matches/significant_drop_in_scrutinee.rs b/src/tools/clippy/clippy_lints/src/matches/significant_drop_in_scrutinee.rs
index 0f3ad40784d..88b4d9b7d54 100644
--- a/src/tools/clippy/clippy_lints/src/matches/significant_drop_in_scrutinee.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/significant_drop_in_scrutinee.rs
@@ -208,12 +208,12 @@ impl<'a, 'tcx> SigDropChecker<'a, 'tcx> {
                     // (to avoid false positive on `Ref<'a, MutexGuard<Foo>>`)
                     || (args
                         .iter()
-                        .all(|arg| !matches!(arg.unpack(), GenericArgKind::Lifetime(_)))
+                        .all(|arg| !matches!(arg.kind(), GenericArgKind::Lifetime(_)))
                         // some generic parameter has significant drop
                         // (to avoid false negative on `Box<MutexGuard<Foo>>`)
                         && args
                             .iter()
-                            .filter_map(|arg| match arg.unpack() {
+                            .filter_map(|arg| match arg.kind() {
                                 GenericArgKind::Type(ty) => Some(ty),
                                 _ => None,
                             })
diff --git a/src/tools/clippy/clippy_lints/src/methods/manual_is_variant_and.rs b/src/tools/clippy/clippy_lints/src/methods/manual_is_variant_and.rs
index 40aad03960c..4a61c223d2c 100644
--- a/src/tools/clippy/clippy_lints/src/methods/manual_is_variant_and.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/manual_is_variant_and.rs
@@ -1,18 +1,22 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::get_parent_expr;
 use clippy_utils::msrvs::{self, Msrv};
-use clippy_utils::source::snippet;
+use clippy_utils::source::{snippet, snippet_opt};
 use clippy_utils::ty::is_type_diagnostic_item;
 use rustc_errors::Applicability;
+use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res};
+use rustc_hir::{BinOpKind, Expr, ExprKind, QPath};
 use rustc_lint::LateContext;
-use rustc_span::{Span, sym};
+use rustc_middle::ty;
+use rustc_span::{BytePos, Span, sym};
 
 use super::MANUAL_IS_VARIANT_AND;
 
-pub(super) fn check<'tcx>(
+pub(super) fn check(
     cx: &LateContext<'_>,
-    expr: &'tcx rustc_hir::Expr<'_>,
-    map_recv: &'tcx rustc_hir::Expr<'_>,
-    map_arg: &'tcx rustc_hir::Expr<'_>,
+    expr: &Expr<'_>,
+    map_recv: &Expr<'_>,
+    map_arg: &Expr<'_>,
     map_span: Span,
     msrv: Msrv,
 ) {
@@ -57,3 +61,57 @@ pub(super) fn check<'tcx>(
         Applicability::MachineApplicable,
     );
 }
+
+fn emit_lint(cx: &LateContext<'_>, op: BinOpKind, parent: &Expr<'_>, method_span: Span, is_option: bool) {
+    if let Some(before_map_snippet) = snippet_opt(cx, parent.span.with_hi(method_span.lo()))
+        && let Some(after_map_snippet) = snippet_opt(cx, method_span.with_lo(method_span.lo() + BytePos(3)))
+    {
+        span_lint_and_sugg(
+            cx,
+            MANUAL_IS_VARIANT_AND,
+            parent.span,
+            format!(
+                "called `.map() {}= {}()`",
+                if op == BinOpKind::Eq { '=' } else { '!' },
+                if is_option { "Some" } else { "Ok" },
+            ),
+            "use",
+            if is_option && op == BinOpKind::Ne {
+                format!("{before_map_snippet}is_none_or{after_map_snippet}",)
+            } else {
+                format!(
+                    "{}{before_map_snippet}{}{after_map_snippet}",
+                    if op == BinOpKind::Eq { "" } else { "!" },
+                    if is_option { "is_some_and" } else { "is_ok_and" },
+                )
+            },
+            Applicability::MachineApplicable,
+        );
+    }
+}
+
+pub(super) fn check_map(cx: &LateContext<'_>, expr: &Expr<'_>) {
+    if let Some(parent_expr) = get_parent_expr(cx, expr)
+        && let ExprKind::Binary(op, left, right) = parent_expr.kind
+        && matches!(op.node, BinOpKind::Eq | BinOpKind::Ne)
+        && op.span.eq_ctxt(expr.span)
+    {
+        // Check `left` and `right` expression in any order, and for `Option` and `Result`
+        for (expr1, expr2) in [(left, right), (right, left)] {
+            for item in [sym::Option, sym::Result] {
+                if let ExprKind::Call(call, ..) = expr1.kind
+                    && let ExprKind::Path(QPath::Resolved(_, path)) = call.kind
+                    && let Res::Def(DefKind::Ctor(CtorOf::Variant, CtorKind::Fn), _) = path.res
+                    && let ty = cx.typeck_results().expr_ty(expr1)
+                    && let ty::Adt(adt, args) = ty.kind()
+                    && cx.tcx.is_diagnostic_item(item, adt.did())
+                    && args.type_at(0).is_bool()
+                    && let ExprKind::MethodCall(_, recv, _, span) = expr2.kind
+                    && is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(recv), item)
+                {
+                    return emit_lint(cx, op.node, parent_expr, span, item == sym::Option);
+                }
+            }
+        }
+    }
+}
diff --git a/src/tools/clippy/clippy_lints/src/methods/mod.rs b/src/tools/clippy/clippy_lints/src/methods/mod.rs
index d2d59f0013c..bc159206985 100644
--- a/src/tools/clippy/clippy_lints/src/methods/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/mod.rs
@@ -4439,7 +4439,7 @@ declare_clippy_lint! {
     /// Checks for usage of `iter().any()` on slices when it can be replaced with `contains()` and suggests doing so.
     ///
     /// ### Why is this bad?
-    /// `contains()` is more concise and idiomatic, sometimes more fast.
+    /// `contains()` is more concise and idiomatic, while also being faster in some cases.
     ///
     /// ### Example
     /// ```no_run
@@ -5203,6 +5203,7 @@ impl Methods {
                         unused_enumerate_index::check(cx, expr, recv, m_arg);
                         map_clone::check(cx, expr, recv, m_arg, self.msrv);
                         map_with_unused_argument_over_ranges::check(cx, expr, recv, m_arg, self.msrv, span);
+                        manual_is_variant_and::check_map(cx, expr);
                         match method_call(recv) {
                             Some((map_name @ (sym::iter | sym::into_iter), recv2, _, _, _)) => {
                                 iter_kv_map::check(cx, map_name, expr, recv2, m_arg, self.msrv);
diff --git a/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs b/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs
index 4c1ed6a1d83..2b75d6a8248 100644
--- a/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs
@@ -508,7 +508,7 @@ fn get_captured_ids(cx: &LateContext<'_>, ty: Ty<'_>) -> HirIdSet {
         match ty.kind() {
             ty::Adt(_, generics) => {
                 for generic in *generics {
-                    if let GenericArgKind::Type(ty) = generic.unpack() {
+                    if let GenericArgKind::Type(ty) = generic.kind() {
                         get_captured_ids_recursive(cx, ty, set);
                     }
                 }
diff --git a/src/tools/clippy/clippy_lints/src/methods/or_fun_call.rs b/src/tools/clippy/clippy_lints/src/methods/or_fun_call.rs
index 38cb4d51ca0..7bdd999bbba 100644
--- a/src/tools/clippy/clippy_lints/src/methods/or_fun_call.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/or_fun_call.rs
@@ -11,8 +11,7 @@ use clippy_utils::{
 use rustc_errors::Applicability;
 use rustc_lint::LateContext;
 use rustc_middle::ty;
-use rustc_span::Span;
-use rustc_span::Symbol;
+use rustc_span::{Span, Symbol};
 use {rustc_ast as ast, rustc_hir as hir};
 
 use super::{OR_FUN_CALL, UNWRAP_OR_DEFAULT};
diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_sort_by.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_sort_by.rs
index fb4984914eb..dbff08bc51c 100644
--- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_sort_by.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_sort_by.rs
@@ -188,7 +188,7 @@ fn detect_lint(cx: &LateContext<'_>, expr: &Expr<'_>, recv: &Expr<'_>, arg: &Exp
 
 fn expr_borrows(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
     let ty = cx.typeck_results().expr_ty(expr);
-    matches!(ty.kind(), ty::Ref(..)) || ty.walk().any(|arg| matches!(arg.unpack(), GenericArgKind::Lifetime(_)))
+    matches!(ty.kind(), ty::Ref(..)) || ty.walk().any(|arg| matches!(arg.kind(), GenericArgKind::Lifetime(_)))
 }
 
 pub(super) fn check<'tcx>(
diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs
index 29a0d2950bc..fdccf1fb33d 100644
--- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs
@@ -44,7 +44,7 @@ pub fn check<'tcx>(
                 return;
             }
             // At this point, we know the call is of a `to_owned`-like function. The functions
-            // `check_addr_of_expr` and `check_call_arg` determine whether the call is unnecessary
+            // `check_addr_of_expr` and `check_into_iter_call_arg` determine whether the call is unnecessary
             // based on its context, that is, whether it is a referent in an `AddrOf` expression, an
             // argument in a `into_iter` call, or an argument in the call of some other function.
             if check_addr_of_expr(cx, expr, method_name, method_def_id, receiver) {
@@ -608,7 +608,7 @@ fn can_change_type<'a>(cx: &LateContext<'a>, mut expr: &'a Expr<'a>, mut ty: Ty<
 }
 
 fn has_lifetime(ty: Ty<'_>) -> bool {
-    ty.walk().any(|t| matches!(t.unpack(), GenericArgKind::Lifetime(_)))
+    ty.walk().any(|t| matches!(t.kind(), GenericArgKind::Lifetime(_)))
 }
 
 /// Returns true if the named method is `Iterator::cloned` or `Iterator::copied`.
@@ -643,7 +643,7 @@ fn is_to_string_on_string_like<'a>(
 
     if let Some(args) = cx.typeck_results().node_args_opt(call_expr.hir_id)
         && let [generic_arg] = args.as_slice()
-        && let GenericArgKind::Type(ty) = generic_arg.unpack()
+        && let GenericArgKind::Type(ty) = generic_arg.kind()
         && let Some(deref_trait_id) = cx.tcx.get_diagnostic_item(sym::Deref)
         && let Some(as_ref_trait_id) = cx.tcx.get_diagnostic_item(sym::AsRef)
         && (cx.get_associated_type(ty, deref_trait_id, sym::Target) == Some(cx.tcx.types.str_)
diff --git a/src/tools/clippy/clippy_lints/src/min_ident_chars.rs b/src/tools/clippy/clippy_lints/src/min_ident_chars.rs
index 00ea9bba0d1..99f01c8001a 100644
--- a/src/tools/clippy/clippy_lints/src/min_ident_chars.rs
+++ b/src/tools/clippy/clippy_lints/src/min_ident_chars.rs
@@ -131,8 +131,9 @@ impl Visitor<'_> for IdentVisitor<'_, '_> {
             // If however the identifier is different, this means it is an alias (`use foo::bar as baz`). In
             // this case, we need to emit the warning for `baz`.
             if let Some(imported_item_path) = usenode
-                && let Some(Res::Def(_, imported_item_defid)) = imported_item_path.res.first()
-                && cx.tcx.item_name(*imported_item_defid).as_str() == str
+                // use `present_items` because it could be in any of type_ns, value_ns, macro_ns
+                && let Some(Res::Def(_, imported_item_defid)) = imported_item_path.res.value_ns
+                && cx.tcx.item_name(imported_item_defid).as_str() == str
             {
                 return;
             }
diff --git a/src/tools/clippy/clippy_lints/src/missing_enforced_import_rename.rs b/src/tools/clippy/clippy_lints/src/missing_enforced_import_rename.rs
index a1e621cc9f6..eeea6dfd5f4 100644
--- a/src/tools/clippy/clippy_lints/src/missing_enforced_import_rename.rs
+++ b/src/tools/clippy/clippy_lints/src/missing_enforced_import_rename.rs
@@ -72,7 +72,8 @@ impl_lint_pass!(ImportRename => [MISSING_ENFORCED_IMPORT_RENAMES]);
 impl LateLintPass<'_> for ImportRename {
     fn check_item(&mut self, cx: &LateContext<'_>, item: &Item<'_>) {
         if let ItemKind::Use(path, UseKind::Single(_)) = &item.kind {
-            for &res in &path.res {
+            // use `present_items` because it could be in any of type_ns, value_ns, macro_ns
+            for res in path.res.present_items() {
                 if let Res::Def(_, id) = res
                     && let Some(name) = self.renames.get(&id)
                     // Remove semicolon since it is not present for nested imports
diff --git a/src/tools/clippy/clippy_lints/src/missing_fields_in_debug.rs b/src/tools/clippy/clippy_lints/src/missing_fields_in_debug.rs
index be7dd74fd62..d4d33029dbd 100644
--- a/src/tools/clippy/clippy_lints/src/missing_fields_in_debug.rs
+++ b/src/tools/clippy/clippy_lints/src/missing_fields_in_debug.rs
@@ -225,7 +225,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingFieldsInDebug {
             && let typeck_results = cx.tcx.typeck_body(*body_id)
             && should_lint(cx, typeck_results, block)
             // we intentionally only lint structs, see lint description
-            && let ItemKind::Struct(_, data, _) = &self_item.kind
+            && let ItemKind::Struct(_, _, data) = &self_item.kind
         {
             check_struct(cx, typeck_results, block, self_ty, item, data);
         }
diff --git a/src/tools/clippy/clippy_lints/src/mut_reference.rs b/src/tools/clippy/clippy_lints/src/mut_reference.rs
index 2fd1049f42e..2f1ab3d2652 100644
--- a/src/tools/clippy/clippy_lints/src/mut_reference.rs
+++ b/src/tools/clippy/clippy_lints/src/mut_reference.rs
@@ -79,25 +79,19 @@ fn check_arguments<'tcx>(
     name: &str,
     fn_kind: &str,
 ) {
-    match type_definition.kind() {
-        ty::FnDef(..) | ty::FnPtr(..) => {
-            let parameters = type_definition.fn_sig(cx.tcx).skip_binder().inputs();
-            for (argument, parameter) in iter::zip(arguments, parameters) {
-                match parameter.kind() {
-                    ty::Ref(_, _, Mutability::Not) | ty::RawPtr(_, Mutability::Not) => {
-                        if let ExprKind::AddrOf(BorrowKind::Ref, Mutability::Mut, _) = argument.kind {
-                            span_lint(
-                                cx,
-                                UNNECESSARY_MUT_PASSED,
-                                argument.span,
-                                format!("the {fn_kind} `{name}` doesn't need a mutable reference"),
-                            );
-                        }
-                    },
-                    _ => (),
-                }
+    if let ty::FnDef(..) | ty::FnPtr(..) = type_definition.kind() {
+        let parameters = type_definition.fn_sig(cx.tcx).skip_binder().inputs();
+        for (argument, parameter) in iter::zip(arguments, parameters) {
+            if let ty::Ref(_, _, Mutability::Not) | ty::RawPtr(_, Mutability::Not) = parameter.kind()
+                && let ExprKind::AddrOf(BorrowKind::Ref, Mutability::Mut, _) = argument.kind
+            {
+                span_lint(
+                    cx,
+                    UNNECESSARY_MUT_PASSED,
+                    argument.span,
+                    format!("the {fn_kind} `{name}` doesn't need a mutable reference"),
+                );
             }
-        },
-        _ => (),
+        }
     }
 }
diff --git a/src/tools/clippy/clippy_lints/src/needless_borrows_for_generic_args.rs b/src/tools/clippy/clippy_lints/src/needless_borrows_for_generic_args.rs
index e579dd5947d..2efb55b9880 100644
--- a/src/tools/clippy/clippy_lints/src/needless_borrows_for_generic_args.rs
+++ b/src/tools/clippy/clippy_lints/src/needless_borrows_for_generic_args.rs
@@ -269,7 +269,7 @@ fn needless_borrow_count<'tcx>(
                     .tcx
                     .is_diagnostic_item(sym::IntoIterator, trait_predicate.trait_ref.def_id)
                 && let ty::Param(param_ty) = trait_predicate.self_ty().kind()
-                && let GenericArgKind::Type(ty) = args_with_referent_ty[param_ty.index as usize].unpack()
+                && let GenericArgKind::Type(ty) = args_with_referent_ty[param_ty.index as usize].kind()
                 && ty.is_array()
                 && !msrv.meets(cx, msrvs::ARRAY_INTO_ITERATOR)
             {
diff --git a/src/tools/clippy/clippy_lints/src/needless_for_each.rs b/src/tools/clippy/clippy_lints/src/needless_for_each.rs
index 7dd96f1f037..6a7c8436bad 100644
--- a/src/tools/clippy/clippy_lints/src/needless_for_each.rs
+++ b/src/tools/clippy/clippy_lints/src/needless_for_each.rs
@@ -74,7 +74,7 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessForEach {
             && let body = cx.tcx.hir_body(body)
             // Skip the lint if the body is not safe, so as not to suggest `for … in … unsafe {}`
             // and suggesting `for … in … { unsafe { } }` is a little ugly.
-            && let ExprKind::Block(Block { rules: BlockCheckMode::DefaultBlock, .. }, ..) = body.value.kind
+            && !matches!(body.value.kind, ExprKind::Block(Block { rules: BlockCheckMode::UnsafeBlock(_), .. }, ..))
         {
             let mut ret_collector = RetCollector::default();
             ret_collector.visit_expr(body.value);
@@ -99,11 +99,21 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessForEach {
                 )
             };
 
+            let body_param_sugg = snippet_with_applicability(cx, body.params[0].pat.span, "..", &mut applicability);
+            let for_each_rev_sugg = snippet_with_applicability(cx, for_each_recv.span, "..", &mut applicability);
+            let body_value_sugg = snippet_with_applicability(cx, body.value.span, "..", &mut applicability);
+
             let sugg = format!(
                 "for {} in {} {}",
-                snippet_with_applicability(cx, body.params[0].pat.span, "..", &mut applicability),
-                snippet_with_applicability(cx, for_each_recv.span, "..", &mut applicability),
-                snippet_with_applicability(cx, body.value.span, "..", &mut applicability),
+                body_param_sugg,
+                for_each_rev_sugg,
+                match body.value.kind {
+                    ExprKind::Block(block, _) if is_let_desugar(block) => {
+                        format!("{{ {body_value_sugg} }}")
+                    },
+                    ExprKind::Block(_, _) => body_value_sugg.to_string(),
+                    _ => format!("{{ {body_value_sugg}; }}"),
+                }
             );
 
             span_lint_and_then(cx, NEEDLESS_FOR_EACH, stmt.span, "needless use of `for_each`", |diag| {
@@ -116,6 +126,20 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessForEach {
     }
 }
 
+/// Check if the block is a desugared `_ = expr` statement.
+fn is_let_desugar(block: &Block<'_>) -> bool {
+    matches!(
+        block,
+        Block {
+            stmts: [Stmt {
+                kind: StmtKind::Let(_),
+                ..
+            },],
+            ..
+        }
+    )
+}
+
 /// This type plays two roles.
 /// 1. Collect spans of `return` in the closure body.
 /// 2. Detect use of `return` in `Loop` in the closure body.
diff --git a/src/tools/clippy/clippy_lints/src/non_send_fields_in_send_ty.rs b/src/tools/clippy/clippy_lints/src/non_send_fields_in_send_ty.rs
index 9542fed3875..8ff78ec7c58 100644
--- a/src/tools/clippy/clippy_lints/src/non_send_fields_in_send_ty.rs
+++ b/src/tools/clippy/clippy_lints/src/non_send_fields_in_send_ty.rs
@@ -172,7 +172,7 @@ impl NonSendField<'_> {
 /// Example: `MyStruct<P, Box<Q, R>>` => `vec![P, Q, R]`
 fn collect_generic_params(ty: Ty<'_>) -> Vec<Ty<'_>> {
     ty.walk()
-        .filter_map(|inner| match inner.unpack() {
+        .filter_map(|inner| match inner.kind() {
             GenericArgKind::Type(inner_ty) => Some(inner_ty),
             _ => None,
         })
@@ -208,7 +208,7 @@ fn ty_allowed_with_raw_pointer_heuristic<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'t
         ty::Adt(_, args) => {
             if contains_pointer_like(cx, ty) {
                 // descends only if ADT contains any raw pointers
-                args.iter().all(|generic_arg| match generic_arg.unpack() {
+                args.iter().all(|generic_arg| match generic_arg.kind() {
                     GenericArgKind::Type(ty) => ty_allowed_with_raw_pointer_heuristic(cx, ty, send_trait),
                     // Lifetimes and const generics are not solid part of ADT and ignored
                     GenericArgKind::Lifetime(_) | GenericArgKind::Const(_) => true,
@@ -226,7 +226,7 @@ fn ty_allowed_with_raw_pointer_heuristic<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'t
 /// Checks if the type contains any pointer-like types in args (including nested ones)
 fn contains_pointer_like<'tcx>(cx: &LateContext<'tcx>, target_ty: Ty<'tcx>) -> bool {
     for ty_node in target_ty.walk() {
-        if let GenericArgKind::Type(inner_ty) = ty_node.unpack() {
+        if let GenericArgKind::Type(inner_ty) = ty_node.kind() {
             match inner_ty.kind() {
                 ty::RawPtr(_, _) => {
                     return true;
diff --git a/src/tools/clippy/clippy_lints/src/non_std_lazy_statics.rs b/src/tools/clippy/clippy_lints/src/non_std_lazy_statics.rs
index f66b9519317..abee3c44c5a 100644
--- a/src/tools/clippy/clippy_lints/src/non_std_lazy_statics.rs
+++ b/src/tools/clippy/clippy_lints/src/non_std_lazy_statics.rs
@@ -187,7 +187,7 @@ struct LazyInfo {
 impl LazyInfo {
     fn from_item(cx: &LateContext<'_>, item: &Item<'_>) -> Option<Self> {
         // Check if item is a `once_cell:sync::Lazy` static.
-        if let ItemKind::Static(_, ty, _, body_id) = item.kind
+        if let ItemKind::Static(_, _, ty, body_id) = item.kind
             && let Some(path_def_id) = path_def_id(cx, ty)
             && let hir::TyKind::Path(hir::QPath::Resolved(_, path)) = ty.kind
             && paths::ONCE_CELL_SYNC_LAZY.matches(cx, path_def_id)
diff --git a/src/tools/clippy/clippy_lints/src/only_used_in_recursion.rs b/src/tools/clippy/clippy_lints/src/only_used_in_recursion.rs
index 6de203e068b..ba8f6354d97 100644
--- a/src/tools/clippy/clippy_lints/src/only_used_in_recursion.rs
+++ b/src/tools/clippy/clippy_lints/src/only_used_in_recursion.rs
@@ -385,7 +385,7 @@ impl<'tcx> LateLintPass<'tcx> for OnlyUsedInRecursion {
 fn has_matching_args(kind: FnKind, args: GenericArgsRef<'_>) -> bool {
     match kind {
         FnKind::Fn => true,
-        FnKind::TraitFn => args.iter().enumerate().all(|(idx, subst)| match subst.unpack() {
+        FnKind::TraitFn => args.iter().enumerate().all(|(idx, subst)| match subst.kind() {
             GenericArgKind::Lifetime(_) => true,
             GenericArgKind::Type(ty) => matches!(*ty.kind(), ty::Param(ty) if ty.index as usize == idx),
             GenericArgKind::Const(c) => matches!(c.kind(), ConstKind::Param(c) if c.index as usize == idx),
diff --git a/src/tools/clippy/clippy_lints/src/operators/assign_op_pattern.rs b/src/tools/clippy/clippy_lints/src/operators/assign_op_pattern.rs
index 4be42267b14..9c6141d8222 100644
--- a/src/tools/clippy/clippy_lints/src/operators/assign_op_pattern.rs
+++ b/src/tools/clippy/clippy_lints/src/operators/assign_op_pattern.rs
@@ -1,8 +1,10 @@
 use clippy_utils::diagnostics::span_lint_and_then;
+use clippy_utils::msrvs::Msrv;
+use clippy_utils::qualify_min_const_fn::is_stable_const_fn;
 use clippy_utils::source::SpanRangeExt;
 use clippy_utils::ty::implements_trait;
 use clippy_utils::visitors::for_each_expr_without_closures;
-use clippy_utils::{binop_traits, eq_expr_value, trait_ref_of_method};
+use clippy_utils::{binop_traits, eq_expr_value, is_in_const_context, trait_ref_of_method};
 use core::ops::ControlFlow;
 use rustc_errors::Applicability;
 use rustc_hir as hir;
@@ -19,6 +21,7 @@ pub(super) fn check<'tcx>(
     expr: &'tcx hir::Expr<'_>,
     assignee: &'tcx hir::Expr<'_>,
     e: &'tcx hir::Expr<'_>,
+    msrv: Msrv,
 ) {
     if let hir::ExprKind::Binary(op, l, r) = &e.kind {
         let lint = |assignee: &hir::Expr<'_>, rhs: &hir::Expr<'_>| {
@@ -40,6 +43,15 @@ pub(super) fn check<'tcx>(
                         return;
                     }
                 }
+
+                // Skip if the trait is not stable in const contexts
+                if is_in_const_context(cx)
+                    && let Some(binop_id) = cx.tcx.associated_item_def_ids(trait_id).first()
+                    && !is_stable_const_fn(cx, *binop_id, msrv)
+                {
+                    return;
+                }
+
                 span_lint_and_then(
                     cx,
                     ASSIGN_OP_PATTERN,
diff --git a/src/tools/clippy/clippy_lints/src/operators/mod.rs b/src/tools/clippy/clippy_lints/src/operators/mod.rs
index d32c062cf56..2f4e8e99588 100644
--- a/src/tools/clippy/clippy_lints/src/operators/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/operators/mod.rs
@@ -919,7 +919,7 @@ impl<'tcx> LateLintPass<'tcx> for Operators {
                 modulo_arithmetic::check(cx, e, bin_op, lhs, rhs, false);
             },
             ExprKind::Assign(lhs, rhs, _) => {
-                assign_op_pattern::check(cx, e, lhs, rhs);
+                assign_op_pattern::check(cx, e, lhs, rhs, self.msrv);
                 self_assignment::check(cx, e, lhs, rhs);
             },
             ExprKind::Unary(op, arg) => {
diff --git a/src/tools/clippy/clippy_lints/src/operators/modulo_arithmetic.rs b/src/tools/clippy/clippy_lints/src/operators/modulo_arithmetic.rs
index 691d7b904ef..b79461663d7 100644
--- a/src/tools/clippy/clippy_lints/src/operators/modulo_arithmetic.rs
+++ b/src/tools/clippy/clippy_lints/src/operators/modulo_arithmetic.rs
@@ -34,14 +34,10 @@ pub(super) fn check<'tcx>(
 }
 
 fn used_in_comparison_with_zero(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
-    let Node::Expr(parent_expr) = cx.tcx.parent_hir_node(expr.hir_id) else {
-        return false;
-    };
-    let ExprKind::Binary(op, lhs, rhs) = parent_expr.kind else {
-        return false;
-    };
-
-    if op.node == BinOpKind::Eq || op.node == BinOpKind::Ne {
+    if let Node::Expr(parent_expr) = cx.tcx.parent_hir_node(expr.hir_id)
+        && let ExprKind::Binary(op, lhs, rhs) = parent_expr.kind
+        && let BinOpKind::Eq | BinOpKind::Ne = op.node
+    {
         let ecx = ConstEvalCtxt::new(cx);
         matches!(ecx.eval(lhs), Some(Constant::Int(0))) || matches!(ecx.eval(rhs), Some(Constant::Int(0)))
     } else {
@@ -56,35 +52,28 @@ struct OperandInfo {
 }
 
 fn analyze_operand(operand: &Expr<'_>, cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<OperandInfo> {
-    match ConstEvalCtxt::new(cx).eval(operand) {
-        Some(Constant::Int(v)) => match *cx.typeck_results().expr_ty(expr).kind() {
+    match ConstEvalCtxt::new(cx).eval(operand)? {
+        Constant::Int(v) => match *cx.typeck_results().expr_ty(expr).kind() {
             ty::Int(ity) => {
                 let value = sext(cx.tcx, v, ity);
-                return Some(OperandInfo {
+                Some(OperandInfo {
                     string_representation: Some(value.to_string()),
                     is_negative: value < 0,
                     is_integral: true,
-                });
-            },
-            ty::Uint(_) => {
-                return Some(OperandInfo {
-                    string_representation: None,
-                    is_negative: false,
-                    is_integral: true,
-                });
+                })
             },
-            _ => {},
+            ty::Uint(_) => Some(OperandInfo {
+                string_representation: None,
+                is_negative: false,
+                is_integral: true,
+            }),
+            _ => None,
         },
         // FIXME(f16_f128): add when casting is available on all platforms
-        Some(Constant::F32(f)) => {
-            return Some(floating_point_operand_info(&f));
-        },
-        Some(Constant::F64(f)) => {
-            return Some(floating_point_operand_info(&f));
-        },
-        _ => {},
+        Constant::F32(f) => Some(floating_point_operand_info(&f)),
+        Constant::F64(f) => Some(floating_point_operand_info(&f)),
+        _ => None,
     }
-    None
 }
 
 fn floating_point_operand_info<T: Display + PartialOrd + From<f32>>(f: &T) -> OperandInfo {
diff --git a/src/tools/clippy/clippy_lints/src/panic_unimplemented.rs b/src/tools/clippy/clippy_lints/src/panic_unimplemented.rs
index 8962f36db1e..449d3da7639 100644
--- a/src/tools/clippy/clippy_lints/src/panic_unimplemented.rs
+++ b/src/tools/clippy/clippy_lints/src/panic_unimplemented.rs
@@ -152,7 +152,6 @@ impl<'tcx> LateLintPass<'tcx> for PanicUnimplemented {
                 expr.span,
                 "`panic_any` should not be present in production code",
             );
-            return;
         }
     }
 }
diff --git a/src/tools/clippy/clippy_lints/src/partial_pub_fields.rs b/src/tools/clippy/clippy_lints/src/partial_pub_fields.rs
index cda752d003f..65e93af9420 100644
--- a/src/tools/clippy/clippy_lints/src/partial_pub_fields.rs
+++ b/src/tools/clippy/clippy_lints/src/partial_pub_fields.rs
@@ -41,7 +41,7 @@ declare_lint_pass!(PartialPubFields => [PARTIAL_PUB_FIELDS]);
 
 impl EarlyLintPass for PartialPubFields {
     fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) {
-        let ItemKind::Struct(_, ref st, _) = item.kind else {
+        let ItemKind::Struct(_, _, ref st) = item.kind else {
             return;
         };
 
diff --git a/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs b/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs
index 5d30b66def2..dadf49b64e5 100644
--- a/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs
+++ b/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs
@@ -1,5 +1,3 @@
-use std::{cmp, iter};
-
 use clippy_config::Conf;
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::source::snippet;
@@ -20,6 +18,7 @@ use rustc_middle::ty::{self, RegionKind, TyCtxt};
 use rustc_session::impl_lint_pass;
 use rustc_span::def_id::LocalDefId;
 use rustc_span::{Span, sym};
+use std::iter;
 
 declare_clippy_lint! {
     /// ### What it does
@@ -33,10 +32,8 @@ declare_clippy_lint! {
     /// registers.
     ///
     /// ### Known problems
-    /// This lint is target register size dependent, it is
-    /// limited to 32-bit to try and reduce portability problems between 32 and
-    /// 64-bit, but if you are compiling for 8 or 16-bit targets then the limit
-    /// will be different.
+    /// This lint is target dependent, some cases will lint on 64-bit targets but
+    /// not 32-bit or lower targets.
     ///
     /// The configuration option `trivial_copy_size_limit` can be set to override
     /// this limit for a project.
@@ -112,16 +109,9 @@ pub struct PassByRefOrValue {
 
 impl PassByRefOrValue {
     pub fn new(tcx: TyCtxt<'_>, conf: &'static Conf) -> Self {
-        let ref_min_size = conf.trivial_copy_size_limit.unwrap_or_else(|| {
-            let bit_width = u64::from(tcx.sess.target.pointer_width);
-            // Cap the calculated bit width at 32-bits to reduce
-            // portability problems between 32 and 64-bit targets
-            let bit_width = cmp::min(bit_width, 32);
-            #[expect(clippy::integer_division)]
-            let byte_width = bit_width / 8;
-            // Use a limit of 2 times the register byte width
-            byte_width * 2
-        });
+        let ref_min_size = conf
+            .trivial_copy_size_limit
+            .unwrap_or_else(|| u64::from(tcx.sess.target.pointer_width / 8));
 
         Self {
             ref_min_size,
diff --git a/src/tools/clippy/clippy_lints/src/pub_underscore_fields.rs b/src/tools/clippy/clippy_lints/src/pub_underscore_fields.rs
index e4a9bf7a848..66c59cb70d3 100644
--- a/src/tools/clippy/clippy_lints/src/pub_underscore_fields.rs
+++ b/src/tools/clippy/clippy_lints/src/pub_underscore_fields.rs
@@ -58,7 +58,7 @@ impl PubUnderscoreFields {
 impl<'tcx> LateLintPass<'tcx> for PubUnderscoreFields {
     fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
         // This lint only pertains to structs.
-        let ItemKind::Struct(_, variant_data, _) = &item.kind else {
+        let ItemKind::Struct(_, _, variant_data) = &item.kind else {
             return;
         };
 
diff --git a/src/tools/clippy/clippy_lints/src/redundant_pub_crate.rs b/src/tools/clippy/clippy_lints/src/redundant_pub_crate.rs
index 7b381fac5f1..3828aff4164 100644
--- a/src/tools/clippy/clippy_lints/src/redundant_pub_crate.rs
+++ b/src/tools/clippy/clippy_lints/src/redundant_pub_crate.rs
@@ -2,7 +2,7 @@ use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::source::HasSession;
 use rustc_errors::Applicability;
 use rustc_hir::def::{DefKind, Res};
-use rustc_hir::{Item, ItemKind};
+use rustc_hir::{Item, ItemKind, UseKind};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::ty;
 use rustc_session::impl_lint_pass;
@@ -49,7 +49,7 @@ impl<'tcx> LateLintPass<'tcx> for RedundantPubCrate {
         if cx.tcx.visibility(item.owner_id.def_id) == ty::Visibility::Restricted(CRATE_DEF_ID.to_def_id())
             && !cx.effective_visibilities.is_exported(item.owner_id.def_id)
             && self.is_exported.last() == Some(&false)
-            && is_not_macro_export(item)
+            && !is_ignorable_export(item)
             && !item.span.in_external_macro(cx.sess().source_map())
         {
             let span = item
@@ -86,18 +86,17 @@ impl<'tcx> LateLintPass<'tcx> for RedundantPubCrate {
     }
 }
 
-fn is_not_macro_export<'tcx>(item: &'tcx Item<'tcx>) -> bool {
-    if let ItemKind::Use(path, _) = item.kind {
-        if path
-            .res
-            .iter()
-            .all(|res| matches!(res, Res::Def(DefKind::Macro(MacroKind::Bang), _)))
-        {
-            return false;
+// We ignore macro exports. And `ListStem` uses, which aren't interesting.
+fn is_ignorable_export<'tcx>(item: &'tcx Item<'tcx>) -> bool {
+    if let ItemKind::Use(path, kind) = item.kind {
+        let ignore = matches!(path.res.macro_ns, Some(Res::Def(DefKind::Macro(MacroKind::Bang), _)))
+            || kind == UseKind::ListStem;
+        if ignore {
+            return true;
         }
     } else if let ItemKind::Macro(..) = item.kind {
-        return false;
+        return true;
     }
 
-    true
+    false
 }
diff --git a/src/tools/clippy/clippy_lints/src/returns.rs b/src/tools/clippy/clippy_lints/src/returns.rs
index ab9b0f88f93..e0c93153a77 100644
--- a/src/tools/clippy/clippy_lints/src/returns.rs
+++ b/src/tools/clippy/clippy_lints/src/returns.rs
@@ -435,7 +435,9 @@ fn check_final_expr<'tcx>(
         ExprKind::If(_, then, else_clause_opt) => {
             check_block_return(cx, &then.kind, peeled_drop_expr.span, semi_spans.clone());
             if let Some(else_clause) = else_clause_opt {
-                check_block_return(cx, &else_clause.kind, peeled_drop_expr.span, semi_spans);
+                // The `RetReplacement` won't be used there as `else_clause` will be either a block or
+                // a `if` expression.
+                check_final_expr(cx, else_clause, semi_spans, RetReplacement::Empty, match_ty_opt);
             }
         },
         // a match expr, check all arms
@@ -487,7 +489,7 @@ fn last_statement_borrows<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>)
                 .skip_binder()
                 .output()
                 .walk()
-                .any(|arg| matches!(arg.unpack(), GenericArgKind::Lifetime(re) if !re.is_static()))
+                .any(|arg| matches!(arg.kind(), GenericArgKind::Lifetime(re) if !re.is_static()))
         {
             ControlFlow::Break(())
         } else {
diff --git a/src/tools/clippy/clippy_lints/src/significant_drop_tightening.rs b/src/tools/clippy/clippy_lints/src/significant_drop_tightening.rs
index f3fea3add59..521754f7bab 100644
--- a/src/tools/clippy/clippy_lints/src/significant_drop_tightening.rs
+++ b/src/tools/clippy/clippy_lints/src/significant_drop_tightening.rs
@@ -184,7 +184,7 @@ impl<'cx, 'others, 'tcx> AttrChecker<'cx, 'others, 'tcx> {
                     }
                 }
                 for generic_arg in *b {
-                    if let GenericArgKind::Type(ty) = generic_arg.unpack()
+                    if let GenericArgKind::Type(ty) = generic_arg.kind()
                         && self.has_sig_drop_attr(ty, depth)
                     {
                         return true;
diff --git a/src/tools/clippy/clippy_lints/src/trailing_empty_array.rs b/src/tools/clippy/clippy_lints/src/trailing_empty_array.rs
index 20bf3a0bff1..75a82770af0 100644
--- a/src/tools/clippy/clippy_lints/src/trailing_empty_array.rs
+++ b/src/tools/clippy/clippy_lints/src/trailing_empty_array.rs
@@ -57,7 +57,7 @@ impl<'tcx> LateLintPass<'tcx> for TrailingEmptyArray {
 }
 
 fn is_struct_with_trailing_zero_sized_array<'tcx>(cx: &LateContext<'tcx>, item: &Item<'tcx>) -> bool {
-    if let ItemKind::Struct(_, data, _) = &item.kind
+    if let ItemKind::Struct(_, _, data) = &item.kind
         && let Some(last_field) = data.fields().last()
         && let field_ty = cx.tcx.normalize_erasing_regions(
             cx.typing_env(),
diff --git a/src/tools/clippy/clippy_lints/src/tuple_array_conversions.rs b/src/tools/clippy/clippy_lints/src/tuple_array_conversions.rs
index 95ce19975c7..3c21d194b81 100644
--- a/src/tools/clippy/clippy_lints/src/tuple_array_conversions.rs
+++ b/src/tools/clippy/clippy_lints/src/tuple_array_conversions.rs
@@ -66,7 +66,7 @@ impl LateLintPass<'_> for TupleArrayConversions {
 }
 
 fn check_array<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>, elements: &'tcx [Expr<'tcx>]) {
-    let (ty::Array(ty, _) | ty::Slice(ty)) = cx.typeck_results().expr_ty(expr).kind() else {
+    let Some(ty) = cx.typeck_results().expr_ty(expr).builtin_index() else {
         unreachable!("`expr` must be an array or slice due to `ExprKind::Array`");
     };
 
@@ -85,7 +85,7 @@ fn check_array<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>, elements: &
             ExprKind::Path(_) => Some(elements.iter().collect()),
             _ => None,
         })
-        && all_bindings_are_for_conv(cx, &[*ty], expr, elements, &locals, ToType::Array)
+        && all_bindings_are_for_conv(cx, &[ty], expr, elements, &locals, ToType::Array)
         && !is_from_proc_macro(cx, expr)
     {
         span_lint_and_help(
diff --git a/src/tools/clippy/clippy_lints/src/types/mod.rs b/src/tools/clippy/clippy_lints/src/types/mod.rs
index c1c7cc51656..515be5adeed 100644
--- a/src/tools/clippy/clippy_lints/src/types/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/types/mod.rs
@@ -447,7 +447,7 @@ impl<'tcx> LateLintPass<'tcx> for Types {
         let is_exported = cx.effective_visibilities.is_exported(item.owner_id.def_id);
 
         match item.kind {
-            ItemKind::Static(_, ty, _, _) | ItemKind::Const(_, ty, _, _) => self.check_ty(
+            ItemKind::Static(_, _, ty, _) | ItemKind::Const(_, _, ty, _) => self.check_ty(
                 cx,
                 ty,
                 CheckTyContext {
diff --git a/src/tools/clippy/clippy_lints/src/unit_return_expecting_ord.rs b/src/tools/clippy/clippy_lints/src/unit_return_expecting_ord.rs
index 67ceac92dbc..39f4130afcf 100644
--- a/src/tools/clippy/clippy_lints/src/unit_return_expecting_ord.rs
+++ b/src/tools/clippy/clippy_lints/src/unit_return_expecting_ord.rs
@@ -5,7 +5,7 @@ use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::ty;
 use rustc_middle::ty::{ClauseKind, GenericPredicates, ProjectionPredicate, TraitPredicate};
 use rustc_session::declare_lint_pass;
-use rustc_span::{BytePos, Span, sym};
+use rustc_span::{BytePos, Span, Symbol, sym};
 
 declare_clippy_lint! {
     /// ### What it does
@@ -36,21 +36,26 @@ declare_clippy_lint! {
 
 declare_lint_pass!(UnitReturnExpectingOrd => [UNIT_RETURN_EXPECTING_ORD]);
 
-fn get_trait_predicates_for_trait_id<'tcx>(
+// For each
+fn get_trait_predicates_for_trait_ids<'tcx>(
     cx: &LateContext<'tcx>,
     generics: GenericPredicates<'tcx>,
-    trait_id: Option<DefId>,
-) -> Vec<TraitPredicate<'tcx>> {
-    let mut preds = Vec::new();
+    trait_ids: &[Option<DefId>], // At least 2 ids
+) -> [Vec<TraitPredicate<'tcx>>; 3] {
+    debug_assert!(trait_ids.len() >= 2);
+    let mut preds = [Vec::new(), Vec::new(), Vec::new()];
     for (pred, _) in generics.predicates {
-        if let ClauseKind::Trait(poly_trait_pred) = pred.kind().skip_binder()
-            && let trait_pred = cx
+        if let ClauseKind::Trait(poly_trait_pred) = pred.kind().skip_binder() {
+            let trait_pred = cx
                 .tcx
-                .instantiate_bound_regions_with_erased(pred.kind().rebind(poly_trait_pred))
-            && let Some(trait_def_id) = trait_id
-            && trait_def_id == trait_pred.trait_ref.def_id
-        {
-            preds.push(trait_pred);
+                .instantiate_bound_regions_with_erased(pred.kind().rebind(poly_trait_pred));
+            for (i, tid) in trait_ids.iter().enumerate() {
+                if let Some(tid) = tid
+                    && *tid == trait_pred.trait_ref.def_id
+                {
+                    preds[i].push(trait_pred);
+                }
+            }
         }
     }
     preds
@@ -74,15 +79,24 @@ fn get_projection_pred<'tcx>(
     })
 }
 
-fn get_args_to_check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> Vec<(usize, String)> {
+fn get_args_to_check<'tcx>(
+    cx: &LateContext<'tcx>,
+    expr: &'tcx Expr<'tcx>,
+    args_len: usize,
+    fn_mut_trait: DefId,
+    ord_trait: Option<DefId>,
+    partial_ord_trait: Option<DefId>,
+) -> Vec<(usize, Symbol)> {
     let mut args_to_check = Vec::new();
     if let Some(def_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id) {
         let fn_sig = cx.tcx.fn_sig(def_id).instantiate_identity();
         let generics = cx.tcx.predicates_of(def_id);
-        let fn_mut_preds = get_trait_predicates_for_trait_id(cx, generics, cx.tcx.lang_items().fn_mut_trait());
-        let ord_preds = get_trait_predicates_for_trait_id(cx, generics, cx.tcx.get_diagnostic_item(sym::Ord));
-        let partial_ord_preds =
-            get_trait_predicates_for_trait_id(cx, generics, cx.tcx.lang_items().partial_ord_trait());
+        let [fn_mut_preds, ord_preds, partial_ord_preds] =
+            get_trait_predicates_for_trait_ids(cx, generics, &[Some(fn_mut_trait), ord_trait, partial_ord_trait]);
+        if fn_mut_preds.is_empty() {
+            return vec![];
+        }
+
         // Trying to call instantiate_bound_regions_with_erased on fn_sig.inputs() gives the following error
         // The trait `rustc::ty::TypeFoldable<'_>` is not implemented for
         // `&[rustc_middle::ty::Ty<'_>]`
@@ -102,12 +116,18 @@ fn get_args_to_check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> Ve
                             .iter()
                             .any(|ord| Some(ord.self_ty()) == return_ty_pred.term.as_type())
                         {
-                            args_to_check.push((i, "Ord".to_string()));
+                            args_to_check.push((i, sym::Ord));
+                            if args_to_check.len() == args_len - 1 {
+                                break;
+                            }
                         } else if partial_ord_preds
                             .iter()
                             .any(|pord| pord.self_ty() == return_ty_pred.term.expect_type())
                         {
-                            args_to_check.push((i, "PartialOrd".to_string()));
+                            args_to_check.push((i, sym::PartialOrd));
+                            if args_to_check.len() == args_len - 1 {
+                                break;
+                            }
                         }
                     }
                 }
@@ -142,38 +162,50 @@ fn check_arg<'tcx>(cx: &LateContext<'tcx>, arg: &'tcx Expr<'tcx>) -> Option<(Spa
 
 impl<'tcx> LateLintPass<'tcx> for UnitReturnExpectingOrd {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
-        if let ExprKind::MethodCall(_, receiver, args, _) = expr.kind {
-            let arg_indices = get_args_to_check(cx, expr);
+        if let ExprKind::MethodCall(_, receiver, args, _) = expr.kind
+            && args.iter().any(|arg| {
+                matches!(
+                    arg.peel_blocks().peel_borrows().peel_drop_temps().kind,
+                    ExprKind::Path(_) | ExprKind::Closure(_)
+                )
+            })
+            && let Some(fn_mut_trait) = cx.tcx.lang_items().fn_mut_trait()
+        {
+            let ord_trait = cx.tcx.get_diagnostic_item(sym::Ord);
+            let partial_ord_trait = cx.tcx.lang_items().partial_ord_trait();
+            if (ord_trait, partial_ord_trait) == (None, None) {
+                return;
+            }
+
             let args = std::iter::once(receiver).chain(args.iter()).collect::<Vec<_>>();
+            let arg_indices = get_args_to_check(cx, expr, args.len(), fn_mut_trait, ord_trait, partial_ord_trait);
             for (i, trait_name) in arg_indices {
-                if i < args.len() {
-                    match check_arg(cx, args[i]) {
-                        Some((span, None)) => {
-                            span_lint(
-                                cx,
-                                UNIT_RETURN_EXPECTING_ORD,
-                                span,
-                                format!(
-                                    "this closure returns \
+                match check_arg(cx, args[i]) {
+                    Some((span, None)) => {
+                        span_lint(
+                            cx,
+                            UNIT_RETURN_EXPECTING_ORD,
+                            span,
+                            format!(
+                                "this closure returns \
                                    the unit type which also implements {trait_name}"
-                                ),
-                            );
-                        },
-                        Some((span, Some(last_semi))) => {
-                            span_lint_and_help(
-                                cx,
-                                UNIT_RETURN_EXPECTING_ORD,
-                                span,
-                                format!(
-                                    "this closure returns \
+                            ),
+                        );
+                    },
+                    Some((span, Some(last_semi))) => {
+                        span_lint_and_help(
+                            cx,
+                            UNIT_RETURN_EXPECTING_ORD,
+                            span,
+                            format!(
+                                "this closure returns \
                                    the unit type which also implements {trait_name}"
-                                ),
-                                Some(last_semi),
-                                "probably caused by this trailing semicolon",
-                            );
-                        },
-                        None => {},
-                    }
+                            ),
+                            Some(last_semi),
+                            "probably caused by this trailing semicolon",
+                        );
+                    },
+                    None => {},
                 }
             }
         }
diff --git a/src/tools/clippy/clippy_lints/src/unused_trait_names.rs b/src/tools/clippy/clippy_lints/src/unused_trait_names.rs
index 14ac65cf4df..610cec7b8c8 100644
--- a/src/tools/clippy/clippy_lints/src/unused_trait_names.rs
+++ b/src/tools/clippy/clippy_lints/src/unused_trait_names.rs
@@ -64,7 +64,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedTraitNames {
             // Ignore imports that already use Underscore
             && ident.name != kw::Underscore
             // Only check traits
-            && let Some(Res::Def(DefKind::Trait, _)) = path.res.first()
+            && let Some(Res::Def(DefKind::Trait, _)) = path.res.type_ns
             && cx.tcx.maybe_unused_trait_imports(()).contains(&item.owner_id.def_id)
             // Only check this import if it is visible to its module only (no pub, pub(crate), ...)
             && let module = cx.tcx.parent_module_from_def_id(item.owner_id.def_id)
diff --git a/src/tools/clippy/clippy_lints/src/upper_case_acronyms.rs b/src/tools/clippy/clippy_lints/src/upper_case_acronyms.rs
index 8922478e718..02281b9e922 100644
--- a/src/tools/clippy/clippy_lints/src/upper_case_acronyms.rs
+++ b/src/tools/clippy/clippy_lints/src/upper_case_acronyms.rs
@@ -134,7 +134,7 @@ impl LateLintPass<'_> for UpperCaseAcronyms {
             ItemKind::TyAlias(ident, ..) | ItemKind::Struct(ident, ..) | ItemKind::Trait(_, _, ident, ..) => {
                 check_ident(cx, &ident, it.hir_id(), self.upper_case_acronyms_aggressive);
             },
-            ItemKind::Enum(ident, ref enumdef, _) => {
+            ItemKind::Enum(ident, _, ref enumdef) => {
                 check_ident(cx, &ident, it.hir_id(), self.upper_case_acronyms_aggressive);
                 // check enum variants separately because again we only want to lint on private enums and
                 // the fn check_variant does not know about the vis of the enum of its variants
diff --git a/src/tools/clippy/clippy_lints/src/use_self.rs b/src/tools/clippy/clippy_lints/src/use_self.rs
index 743f54ca993..aeda864b7eb 100644
--- a/src/tools/clippy/clippy_lints/src/use_self.rs
+++ b/src/tools/clippy/clippy_lints/src/use_self.rs
@@ -319,7 +319,7 @@ fn same_lifetimes<'tcx>(a: MiddleTy<'tcx>, b: MiddleTy<'tcx>) -> bool {
             args_a
                 .iter()
                 .zip(args_b.iter())
-                .all(|(arg_a, arg_b)| match (arg_a.unpack(), arg_b.unpack()) {
+                .all(|(arg_a, arg_b)| match (arg_a.kind(), arg_b.kind()) {
                     // TODO: Handle inferred lifetimes
                     (GenericArgKind::Lifetime(inner_a), GenericArgKind::Lifetime(inner_b)) => inner_a == inner_b,
                     (GenericArgKind::Type(type_a), GenericArgKind::Type(type_b)) => same_lifetimes(type_a, type_b),
@@ -337,7 +337,7 @@ fn has_no_lifetime(ty: MiddleTy<'_>) -> bool {
         &Adt(_, args) => !args
             .iter()
             // TODO: Handle inferred lifetimes
-            .any(|arg| matches!(arg.unpack(), GenericArgKind::Lifetime(..))),
+            .any(|arg| matches!(arg.kind(), GenericArgKind::Lifetime(..))),
         _ => true,
     }
 }
diff --git a/src/tools/clippy/clippy_lints/src/wildcard_imports.rs b/src/tools/clippy/clippy_lints/src/wildcard_imports.rs
index 45a5dbabeb4..467811c586b 100644
--- a/src/tools/clippy/clippy_lints/src/wildcard_imports.rs
+++ b/src/tools/clippy/clippy_lints/src/wildcard_imports.rs
@@ -169,8 +169,8 @@ impl LateLintPass<'_> for WildcardImports {
                 format!("{import_source_snippet}::{imports_string}")
             };
 
-            // Glob imports always have a single resolution.
-            let (lint, message) = if let Res::Def(DefKind::Enum, _) = use_path.res[0] {
+            // Glob imports always have a single resolution. Enums are in the value namespace.
+            let (lint, message) = if let Some(Res::Def(DefKind::Enum, _)) = use_path.res.value_ns {
                 (ENUM_GLOB_USE, "usage of wildcard import for enum variants")
             } else {
                 (WILDCARD_IMPORTS, "usage of wildcard import")
diff --git a/src/tools/clippy/clippy_lints_internal/src/msrv_attr_impl.rs b/src/tools/clippy/clippy_lints_internal/src/msrv_attr_impl.rs
index 441c6884852..70b3c03d2bb 100644
--- a/src/tools/clippy/clippy_lints_internal/src/msrv_attr_impl.rs
+++ b/src/tools/clippy/clippy_lints_internal/src/msrv_attr_impl.rs
@@ -37,7 +37,7 @@ impl LateLintPass<'_> for MsrvAttrImpl {
                     .type_of(f.did)
                     .instantiate_identity()
                     .walk()
-                    .filter(|t| matches!(t.unpack(), GenericArgKind::Type(_)))
+                    .filter(|t| matches!(t.kind(), GenericArgKind::Type(_)))
                     .any(|t| internal_paths::MSRV_STACK.matches_ty(cx, t.expect_ty()))
             })
             && !items.iter().any(|item| item.ident.name.as_str() == "check_attributes")
diff --git a/src/tools/clippy/clippy_utils/README.md b/src/tools/clippy/clippy_utils/README.md
index c9083f654c4..efbacbd72db 100644
--- a/src/tools/clippy/clippy_utils/README.md
+++ b/src/tools/clippy/clippy_utils/README.md
@@ -8,7 +8,7 @@ This crate is only guaranteed to build with this `nightly` toolchain:
 
 <!-- begin autogenerated nightly -->
 ```
-nightly-2025-05-21
+nightly-2025-05-31
 ```
 <!-- end autogenerated nightly -->
 
diff --git a/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs b/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs
index 8996b694ed8..6c186ab4a6f 100644
--- a/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs
+++ b/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs
@@ -436,11 +436,11 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool {
                 && over(lb, rb, eq_generic_bound)
                 && both(lt.as_ref(), rt.as_ref(), |l, r| eq_ty(l, r))
         },
-        (Enum(li, le, lg), Enum(ri, re, rg)) => {
-            eq_id(*li, *ri) && over(&le.variants, &re.variants, eq_variant) && eq_generics(lg, rg)
+        (Enum(li, lg, le), Enum(ri, rg, re)) => {
+            eq_id(*li, *ri) && eq_generics(lg, rg) && over(&le.variants, &re.variants, eq_variant)
         },
-        (Struct(li, lv, lg), Struct(ri, rv, rg)) | (Union(li, lv, lg), Union(ri, rv, rg)) => {
-            eq_id(*li, *ri) && eq_variant_data(lv, rv) && eq_generics(lg, rg)
+        (Struct(li, lg, lv), Struct(ri, rg, rv)) | (Union(li, lg, lv), Union(ri, rg, rv)) => {
+            eq_id(*li, *ri) && eq_generics(lg, rg) && eq_variant_data(lv, rv)
         },
         (
             Trait(box ast::Trait {
diff --git a/src/tools/clippy/clippy_utils/src/check_proc_macro.rs b/src/tools/clippy/clippy_utils/src/check_proc_macro.rs
index 004c840c331..407e92d88fb 100644
--- a/src/tools/clippy/clippy_utils/src/check_proc_macro.rs
+++ b/src/tools/clippy/clippy_utils/src/check_proc_macro.rs
@@ -249,7 +249,7 @@ fn item_search_pat(item: &Item<'_>) -> (Pat, Pat) {
         ItemKind::ForeignMod { .. } => (Pat::Str("extern"), Pat::Str("}")),
         ItemKind::TyAlias(..) => (Pat::Str("type"), Pat::Str(";")),
         ItemKind::Enum(..) => (Pat::Str("enum"), Pat::Str("}")),
-        ItemKind::Struct(_, VariantData::Struct { .. }, _) => (Pat::Str("struct"), Pat::Str("}")),
+        ItemKind::Struct(_, _, VariantData::Struct { .. }) => (Pat::Str("struct"), Pat::Str("}")),
         ItemKind::Struct(..) => (Pat::Str("struct"), Pat::Str(";")),
         ItemKind::Union(..) => (Pat::Str("union"), Pat::Str("}")),
         ItemKind::Trait(_, Safety::Unsafe, ..)
diff --git a/src/tools/clippy/clippy_utils/src/consts.rs b/src/tools/clippy/clippy_utils/src/consts.rs
index 6f5b0ec54cd..1ec5d11384f 100644
--- a/src/tools/clippy/clippy_utils/src/consts.rs
+++ b/src/tools/clippy/clippy_utils/src/consts.rs
@@ -235,9 +235,7 @@ impl Constant<'_> {
                 _ => None,
             },
             (Self::Vec(l), Self::Vec(r)) => {
-                let (ty::Array(cmp_type, _) | ty::Slice(cmp_type)) = *cmp_type.kind() else {
-                    return None;
-                };
+                let cmp_type = cmp_type.builtin_index()?;
                 iter::zip(l, r)
                     .map(|(li, ri)| Self::partial_cmp(tcx, cmp_type, li, ri))
                     .find(|r| r.is_none_or(|o| o != Ordering::Equal))
diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs
index 3a319176571..f6ef638e618 100644
--- a/src/tools/clippy/clippy_utils/src/lib.rs
+++ b/src/tools/clippy/clippy_utils/src/lib.rs
@@ -1565,10 +1565,10 @@ pub fn is_ctor_or_promotable_const_function(cx: &LateContext<'_>, expr: &Expr<'_
 /// Returns `true` if a pattern is refutable.
 // TODO: should be implemented using rustc/mir_build/thir machinery
 pub fn is_refutable(cx: &LateContext<'_>, pat: &Pat<'_>) -> bool {
-    fn is_enum_variant(cx: &LateContext<'_>, qpath: &QPath<'_>, id: HirId) -> bool {
-        matches!(
+    fn is_qpath_refutable(cx: &LateContext<'_>, qpath: &QPath<'_>, id: HirId) -> bool {
+        !matches!(
             cx.qpath_res(qpath, id),
-            Res::Def(DefKind::Variant, ..) | Res::Def(DefKind::Ctor(def::CtorOf::Variant, _), _)
+            Res::Def(DefKind::Struct, ..) | Res::Def(DefKind::Ctor(def::CtorOf::Struct, _), _)
         )
     }
 
@@ -1585,16 +1585,18 @@ pub fn is_refutable(cx: &LateContext<'_>, pat: &Pat<'_>) -> bool {
             kind: PatExprKind::Path(qpath),
             hir_id,
             ..
-        }) => is_enum_variant(cx, qpath, *hir_id),
+        }) => is_qpath_refutable(cx, qpath, *hir_id),
         PatKind::Or(pats) => {
             // TODO: should be the honest check, that pats is exhaustive set
             are_refutable(cx, pats)
         },
         PatKind::Tuple(pats, _) => are_refutable(cx, pats),
         PatKind::Struct(ref qpath, fields, _) => {
-            is_enum_variant(cx, qpath, pat.hir_id) || are_refutable(cx, fields.iter().map(|field| field.pat))
+            is_qpath_refutable(cx, qpath, pat.hir_id) || are_refutable(cx, fields.iter().map(|field| field.pat))
+        },
+        PatKind::TupleStruct(ref qpath, pats, _) => {
+            is_qpath_refutable(cx, qpath, pat.hir_id) || are_refutable(cx, pats)
         },
-        PatKind::TupleStruct(ref qpath, pats, _) => is_enum_variant(cx, qpath, pat.hir_id) || are_refutable(cx, pats),
         PatKind::Slice(head, middle, tail) => {
             match &cx.typeck_results().node_type(pat.hir_id).kind() {
                 rustc_ty::Slice(..) => {
@@ -2362,7 +2364,7 @@ fn with_test_item_names(tcx: TyCtxt<'_>, module: LocalModDefId, f: impl FnOnce(&
             for id in tcx.hir_module_free_items(module) {
                 if matches!(tcx.def_kind(id.owner_id), DefKind::Const)
                     && let item = tcx.hir_item(id)
-                    && let ItemKind::Const(ident, ty, _generics, _body) = item.kind
+                    && let ItemKind::Const(ident, _generics, ty, _body) = item.kind
                     && let TyKind::Path(QPath::Resolved(_, path)) = ty.kind
                         // We could also check for the type name `test::TestDescAndFn`
                         && let Res::Def(DefKind::Struct, _) = path.res
@@ -3316,7 +3318,7 @@ pub fn leaks_droppable_temporary_with_limited_lifetime<'tcx>(cx: &LateContext<'t
         if temporary_ty.has_significant_drop(cx.tcx, cx.typing_env())
             && temporary_ty
                 .walk()
-                .any(|arg| matches!(arg.unpack(), GenericArgKind::Lifetime(re) if !re.is_static()))
+                .any(|arg| matches!(arg.kind(), GenericArgKind::Lifetime(re) if !re.is_static()))
         {
             ControlFlow::Break(())
         } else {
diff --git a/src/tools/clippy/clippy_utils/src/paths.rs b/src/tools/clippy/clippy_utils/src/paths.rs
index 9d7f3086b05..f37a609497e 100644
--- a/src/tools/clippy/clippy_utils/src/paths.rs
+++ b/src/tools/clippy/clippy_utils/src/paths.rs
@@ -306,10 +306,13 @@ fn local_item_child_by_name(tcx: TyCtxt<'_>, local_id: LocalDefId, ns: PathNS, n
             let item = tcx.hir_item(item_id);
             if let ItemKind::Use(path, UseKind::Single(ident)) = item.kind {
                 if ident.name == name {
-                    path.res
-                        .iter()
-                        .find(|res| ns.matches(res.ns()))
-                        .and_then(Res::opt_def_id)
+                    let opt_def_id = |ns: Option<Res>| ns.and_then(|res| res.opt_def_id());
+                    match ns {
+                        PathNS::Type => opt_def_id(path.res.type_ns),
+                        PathNS::Value => opt_def_id(path.res.value_ns),
+                        PathNS::Macro => opt_def_id(path.res.macro_ns),
+                        PathNS::Arbitrary => unreachable!(),
+                    }
                 } else {
                     None
                 }
diff --git a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs
index 45da266fd8a..5b4ec12cbec 100644
--- a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs
+++ b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs
@@ -55,7 +55,7 @@ pub fn is_min_const_fn<'tcx>(cx: &LateContext<'tcx>, body: &Body<'tcx>, msrv: Ms
 
 fn check_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, span: Span, msrv: Msrv) -> McfResult {
     for arg in ty.walk() {
-        let ty = match arg.unpack() {
+        let ty = match arg.kind() {
             GenericArgKind::Type(ty) => ty,
 
             // No constraints on lifetimes or constants, except potentially
@@ -393,7 +393,8 @@ fn check_terminator<'tcx>(
     }
 }
 
-fn is_stable_const_fn(cx: &LateContext<'_>, def_id: DefId, msrv: Msrv) -> bool {
+/// Checks if the given `def_id` is a stable const fn, in respect to the given MSRV.
+pub fn is_stable_const_fn(cx: &LateContext<'_>, def_id: DefId, msrv: Msrv) -> bool {
     cx.tcx.is_const_fn(def_id)
         && cx
             .tcx
diff --git a/src/tools/clippy/clippy_utils/src/sugg.rs b/src/tools/clippy/clippy_utils/src/sugg.rs
index 93dec113d31..6974e6512e2 100644
--- a/src/tools/clippy/clippy_utils/src/sugg.rs
+++ b/src/tools/clippy/clippy_utils/src/sugg.rs
@@ -940,7 +940,9 @@ impl<'tcx> Delegate<'tcx> for DerefDelegate<'_, 'tcx> {
                         // note: unable to trigger `Subslice` kind in tests
                         ProjectionKind::Subslice |
                         // Doesn't have surface syntax. Only occurs in patterns.
-                        ProjectionKind::OpaqueCast => (),
+                        ProjectionKind::OpaqueCast |
+                        // Only occurs in closure captures.
+                        ProjectionKind::UnwrapUnsafeBinder => (),
                         ProjectionKind::Deref => {
                             // Explicit derefs are typically handled later on, but
                             // some items do not need explicit deref, such as array accesses,
diff --git a/src/tools/clippy/clippy_utils/src/ty/mod.rs b/src/tools/clippy/clippy_utils/src/ty/mod.rs
index c50ad17bfad..61e70b3fa0b 100644
--- a/src/tools/clippy/clippy_utils/src/ty/mod.rs
+++ b/src/tools/clippy/clippy_utils/src/ty/mod.rs
@@ -78,7 +78,7 @@ pub fn can_partially_move_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool
 /// Walks into `ty` and returns `true` if any inner type is an instance of the given adt
 /// constructor.
 pub fn contains_adt_constructor<'tcx>(ty: Ty<'tcx>, adt: AdtDef<'tcx>) -> bool {
-    ty.walk().any(|inner| match inner.unpack() {
+    ty.walk().any(|inner| match inner.kind() {
         GenericArgKind::Type(inner_ty) => inner_ty.ty_adt_def() == Some(adt),
         GenericArgKind::Lifetime(_) | GenericArgKind::Const(_) => false,
     })
@@ -96,7 +96,7 @@ pub fn contains_ty_adt_constructor_opaque<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'
         needle: Ty<'tcx>,
         seen: &mut FxHashSet<DefId>,
     ) -> bool {
-        ty.walk().any(|inner| match inner.unpack() {
+        ty.walk().any(|inner| match inner.kind() {
             GenericArgKind::Type(inner_ty) => {
                 if inner_ty == needle {
                     return true;
@@ -129,7 +129,7 @@ pub fn contains_ty_adt_constructor_opaque<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'
                             // For `impl Trait<Assoc=U>`, it will register a predicate of `<T as Trait>::Assoc = U`,
                             // so we check the term for `U`.
                             ty::ClauseKind::Projection(projection_predicate) => {
-                                if let ty::TermKind::Ty(ty) = projection_predicate.term.unpack()
+                                if let ty::TermKind::Ty(ty) = projection_predicate.term.kind()
                                     && contains_ty_adt_constructor_opaque_inner(cx, ty, needle, seen)
                                 {
                                     return true;
@@ -526,7 +526,7 @@ pub fn same_type_and_consts<'tcx>(a: Ty<'tcx>, b: Ty<'tcx>) -> bool {
             args_a
                 .iter()
                 .zip(args_b.iter())
-                .all(|(arg_a, arg_b)| match (arg_a.unpack(), arg_b.unpack()) {
+                .all(|(arg_a, arg_b)| match (arg_a.kind(), arg_b.kind()) {
                     (GenericArgKind::Const(inner_a), GenericArgKind::Const(inner_b)) => inner_a == inner_b,
                     (GenericArgKind::Type(type_a), GenericArgKind::Type(type_b)) => {
                         same_type_and_consts(type_a, type_b)
@@ -996,7 +996,7 @@ fn assert_generic_args_match<'tcx>(tcx: TyCtxt<'tcx>, did: DefId, args: &[Generi
     if let Some((idx, (param, arg))) =
         params
             .clone()
-            .zip(args.iter().map(|&x| x.unpack()))
+            .zip(args.iter().map(|&x| x.kind()))
             .enumerate()
             .find(|(_, (param, arg))| match (param, arg) {
                 (GenericParamDefKind::Lifetime, GenericArgKind::Lifetime(_))
diff --git a/src/tools/clippy/clippy_utils/src/ty/type_certainty/mod.rs b/src/tools/clippy/clippy_utils/src/ty/type_certainty/mod.rs
index 6e358662327..84df36c75bf 100644
--- a/src/tools/clippy/clippy_utils/src/ty/type_certainty/mod.rs
+++ b/src/tools/clippy/clippy_utils/src/ty/type_certainty/mod.rs
@@ -326,5 +326,5 @@ fn adt_def_id(ty: Ty<'_>) -> Option<DefId> {
 
 fn contains_param(ty: Ty<'_>, index: u32) -> bool {
     ty.walk()
-        .any(|arg| matches!(arg.unpack(), GenericArgKind::Type(ty) if ty.is_param(index)))
+        .any(|arg| matches!(arg.kind(), GenericArgKind::Type(ty) if ty.is_param(index)))
 }
diff --git a/src/tools/clippy/lintcheck/src/input.rs b/src/tools/clippy/lintcheck/src/input.rs
index 83eb0a577d6..408a2e087af 100644
--- a/src/tools/clippy/lintcheck/src/input.rs
+++ b/src/tools/clippy/lintcheck/src/input.rs
@@ -8,7 +8,7 @@ use std::time::Duration;
 use serde::Deserialize;
 use walkdir::{DirEntry, WalkDir};
 
-use crate::{Crate, LINTCHECK_DOWNLOADS, LINTCHECK_SOURCES};
+use crate::{Crate, lintcheck_sources, target_dir};
 
 const DEFAULT_DOCS_LINK: &str = "https://docs.rs/{krate}/{version}/src/{krate_}/{file}.html#{line}";
 const DEFAULT_GITHUB_LINK: &str = "{url}/blob/{hash}/src/{file}#L{line}";
@@ -201,8 +201,10 @@ impl CrateWithSource {
         let file_link = &self.file_link;
         match &self.source {
             CrateSource::CratesIo { version } => {
-                let extract_dir = PathBuf::from(LINTCHECK_SOURCES);
-                let krate_download_dir = PathBuf::from(LINTCHECK_DOWNLOADS);
+                let extract_dir = PathBuf::from(lintcheck_sources());
+                // Keep constant downloads path to avoid repeating work and
+                // filling up disk space unnecessarily.
+                let krate_download_dir = PathBuf::from("target/lintcheck/downloads/");
 
                 // url to download the crate from crates.io
                 let url = format!("https://crates.io/api/v1/crates/{name}/{version}/download");
@@ -211,7 +213,7 @@ impl CrateWithSource {
 
                 let krate_file_path = krate_download_dir.join(format!("{name}-{version}.crate.tar.gz"));
                 // don't download/extract if we already have done so
-                if !krate_file_path.is_file() {
+                if !krate_file_path.is_file() || !extract_dir.join(format!("{name}-{version}")).exists() {
                     // create a file path to download and write the crate data into
                     let mut krate_dest = fs::File::create(&krate_file_path).unwrap();
                     let mut krate_req = get(&url).unwrap().into_reader();
@@ -236,7 +238,7 @@ impl CrateWithSource {
             },
             CrateSource::Git { url, commit } => {
                 let repo_path = {
-                    let mut repo_path = PathBuf::from(LINTCHECK_SOURCES);
+                    let mut repo_path = PathBuf::from(lintcheck_sources());
                     // add a -git suffix in case we have the same crate from crates.io and a git repo
                     repo_path.push(format!("{name}-git"));
                     repo_path
@@ -286,7 +288,7 @@ impl CrateWithSource {
                 // copy path into the dest_crate_root but skip directories that contain a CACHEDIR.TAG file.
                 // The target/ directory contains a CACHEDIR.TAG file so it is the most commonly skipped directory
                 // as a result of this filter.
-                let dest_crate_root = PathBuf::from(LINTCHECK_SOURCES).join(name);
+                let dest_crate_root = PathBuf::from(lintcheck_sources()).join(name);
                 if dest_crate_root.exists() {
                     println!("Deleting existing directory at `{}`", dest_crate_root.display());
                     fs::remove_dir_all(&dest_crate_root).unwrap();
@@ -326,15 +328,16 @@ impl CrateWithSource {
 ///
 /// This function panics if creating one of the dirs fails.
 fn create_dirs(krate_download_dir: &Path, extract_dir: &Path) {
-    fs::create_dir("target/lintcheck/").unwrap_or_else(|err| {
+    fs::create_dir(format!("{}/lintcheck/", target_dir())).unwrap_or_else(|err| {
         assert_eq!(
             err.kind(),
             ErrorKind::AlreadyExists,
             "cannot create lintcheck target dir"
         );
     });
-    fs::create_dir(krate_download_dir).unwrap_or_else(|err| {
-        assert_eq!(err.kind(), ErrorKind::AlreadyExists, "cannot create crate download dir");
+    fs::create_dir_all(krate_download_dir).unwrap_or_else(|err| {
+        // We are allowed to reuse download dirs
+        assert_ne!(err.kind(), ErrorKind::AlreadyExists);
     });
     fs::create_dir(extract_dir).unwrap_or_else(|err| {
         assert_eq!(
diff --git a/src/tools/clippy/lintcheck/src/main.rs b/src/tools/clippy/lintcheck/src/main.rs
index d4bf6cd48a1..84183831432 100644
--- a/src/tools/clippy/lintcheck/src/main.rs
+++ b/src/tools/clippy/lintcheck/src/main.rs
@@ -43,8 +43,14 @@ use input::read_crates;
 use output::{ClippyCheckOutput, ClippyWarning, RustcIce};
 use rayon::prelude::*;
 
-const LINTCHECK_DOWNLOADS: &str = "target/lintcheck/downloads";
-const LINTCHECK_SOURCES: &str = "target/lintcheck/sources";
+#[must_use]
+pub fn target_dir() -> String {
+    env::var("CARGO_TARGET_DIR").unwrap_or("target".to_owned())
+}
+
+fn lintcheck_sources() -> String {
+    format!("{}/lintcheck/sources", target_dir())
+}
 
 /// Represents the actual source code of a crate that we ran "cargo clippy" on
 #[derive(Debug)]
@@ -307,7 +313,8 @@ fn main() {
 fn lintcheck(config: LintcheckConfig) {
     let clippy_ver = build_clippy(config.perf);
     let clippy_driver_path = fs::canonicalize(format!(
-        "target/{}/clippy-driver{EXE_SUFFIX}",
+        "{}/{}/clippy-driver{EXE_SUFFIX}",
+        target_dir(),
         if config.perf { "release" } else { "debug" }
     ))
     .unwrap();
@@ -315,7 +322,8 @@ fn lintcheck(config: LintcheckConfig) {
     // assert that clippy is found
     assert!(
         clippy_driver_path.is_file(),
-        "target/{}/clippy-driver binary not found! {}",
+        "{}/{}/clippy-driver binary not found! {}",
+        target_dir(),
         if config.perf { "release" } else { "debug" },
         clippy_driver_path.display()
     );
@@ -386,7 +394,7 @@ fn lintcheck(config: LintcheckConfig) {
         .unwrap();
 
     let server = config.recursive.then(|| {
-        let _: io::Result<()> = fs::remove_dir_all("target/lintcheck/shared_target_dir/recursive");
+        let _: io::Result<()> = fs::remove_dir_all(format!("{}/lintcheck/shared_target_dir/recursive", target_dir()));
 
         LintcheckServer::spawn(recursive_options)
     });
@@ -488,7 +496,7 @@ fn clippy_project_root() -> &'static Path {
 #[must_use]
 fn shared_target_dir(qualifier: &str) -> PathBuf {
     clippy_project_root()
-        .join("target/lintcheck/shared_target_dir")
+        .join(format!("{}/lintcheck/shared_target_dir", target_dir()))
         .join(qualifier)
 }
 
diff --git a/src/tools/clippy/lintcheck/src/output.rs b/src/tools/clippy/lintcheck/src/output.rs
index dcc1ec339ef..d7fe0915121 100644
--- a/src/tools/clippy/lintcheck/src/output.rs
+++ b/src/tools/clippy/lintcheck/src/output.rs
@@ -162,9 +162,9 @@ pub fn summarize_and_print_changes(
 fn gather_stats(warnings: &[ClippyWarning]) -> (String, HashMap<&String, usize>) {
     // count lint type occurrences
     let mut counter: HashMap<&String, usize> = HashMap::new();
-    warnings
-        .iter()
-        .for_each(|wrn| *counter.entry(&wrn.name).or_insert(0) += 1);
+    for wrn in warnings {
+        *counter.entry(&wrn.name).or_insert(0) += 1;
+    }
 
     // collect into a tupled list for sorting
     let mut stats: Vec<(&&String, &usize)> = counter.iter().collect();
diff --git a/src/tools/clippy/rust-toolchain.toml b/src/tools/clippy/rust-toolchain.toml
index 0b9ebe554f5..b6817d9a146 100644
--- a/src/tools/clippy/rust-toolchain.toml
+++ b/src/tools/clippy/rust-toolchain.toml
@@ -1,6 +1,6 @@
 [toolchain]
 # begin autogenerated nightly
-channel = "nightly-2025-05-21"
+channel = "nightly-2025-05-31"
 # end autogenerated nightly
 components = ["cargo", "llvm-tools", "rust-src", "rust-std", "rustc", "rustc-dev", "rustfmt"]
 profile = "minimal"
diff --git a/src/tools/clippy/rustfmt.toml b/src/tools/clippy/rustfmt.toml
index 0dc6adce7bf..0ed58a2dfc1 100644
--- a/src/tools/clippy/rustfmt.toml
+++ b/src/tools/clippy/rustfmt.toml
@@ -6,4 +6,8 @@ edition = "2024"
 error_on_line_overflow = true
 imports_granularity = "Module"
 style_edition = "2024"
-ignore = ["tests/ui/crashes/ice-10912.rs"]
+ignore = [
+    "tests/ui/crashes/ice-9405.rs",
+    "tests/ui/crashes/ice-10912.rs",
+    "tests/ui/non_expressive_names_error_recovery.rs",
+]
diff --git a/src/tools/clippy/tests/headers.rs b/src/tools/clippy/tests/headers.rs
deleted file mode 100644
index d1f986ef526..00000000000
--- a/src/tools/clippy/tests/headers.rs
+++ /dev/null
@@ -1,34 +0,0 @@
-use regex::Regex;
-use std::fs;
-use walkdir::WalkDir;
-
-#[test]
-fn old_test_headers() {
-    let old_headers = Regex::new(
-        r"^//( ?\[\w+\])? ?((check|build|run|ignore|aux|only|needs|rustc|unset|no|normalize|run|compile)-|edition|incremental|revisions).*",
-    )
-    .unwrap();
-    let mut failed = false;
-
-    for entry in WalkDir::new("tests") {
-        let entry = entry.unwrap();
-        let is_hidden_file = entry
-            .file_name()
-            .to_str()
-            .expect("non-UTF-8 file name")
-            .starts_with('.');
-        if is_hidden_file || !entry.file_type().is_file() {
-            continue;
-        }
-
-        let file = fs::read_to_string(entry.path()).unwrap_or_else(|err| panic!("{}: {err}", entry.path().display()));
-
-        if let Some(header) = old_headers.find(&file) {
-            println!("Found header `{}` in {}", header.as_str(), entry.path().display());
-
-            failed = true;
-        }
-    }
-
-    assert!(!failed, "use `//@foo` style test headers instead");
-}
diff --git a/src/tools/clippy/tests/ui/assign_ops.fixed b/src/tools/clippy/tests/ui/assign_ops.fixed
index 429c20f95e9..3bc6885d7c3 100644
--- a/src/tools/clippy/tests/ui/assign_ops.fixed
+++ b/src/tools/clippy/tests/ui/assign_ops.fixed
@@ -1,5 +1,6 @@
 #![allow(clippy::useless_vec)]
 #![warn(clippy::assign_op_pattern)]
+#![feature(const_trait_impl, const_ops)]
 
 use core::num::Wrapping;
 use std::ops::{Mul, MulAssign};
@@ -73,3 +74,33 @@ impl MulAssign<i64> for Wrap {
         *self = *self * rhs
     }
 }
+
+mod issue14871 {
+
+    use std::ops::{Add, AddAssign};
+
+    pub trait Number: Copy + Add<Self, Output = Self> + AddAssign {
+        const ZERO: Self;
+        const ONE: Self;
+    }
+
+    #[const_trait]
+    pub trait NumberConstants {
+        fn constant(value: usize) -> Self;
+    }
+
+    impl<T> const NumberConstants for T
+    where
+        T: Number + ~const core::ops::Add,
+    {
+        fn constant(value: usize) -> Self {
+            let mut res = Self::ZERO;
+            let mut count = 0;
+            while count < value {
+                res = res + Self::ONE;
+                count += 1;
+            }
+            res
+        }
+    }
+}
diff --git a/src/tools/clippy/tests/ui/assign_ops.rs b/src/tools/clippy/tests/ui/assign_ops.rs
index 480ff07f150..f1f8f9daff9 100644
--- a/src/tools/clippy/tests/ui/assign_ops.rs
+++ b/src/tools/clippy/tests/ui/assign_ops.rs
@@ -1,5 +1,6 @@
 #![allow(clippy::useless_vec)]
 #![warn(clippy::assign_op_pattern)]
+#![feature(const_trait_impl, const_ops)]
 
 use core::num::Wrapping;
 use std::ops::{Mul, MulAssign};
@@ -73,3 +74,33 @@ impl MulAssign<i64> for Wrap {
         *self = *self * rhs
     }
 }
+
+mod issue14871 {
+
+    use std::ops::{Add, AddAssign};
+
+    pub trait Number: Copy + Add<Self, Output = Self> + AddAssign {
+        const ZERO: Self;
+        const ONE: Self;
+    }
+
+    #[const_trait]
+    pub trait NumberConstants {
+        fn constant(value: usize) -> Self;
+    }
+
+    impl<T> const NumberConstants for T
+    where
+        T: Number + ~const core::ops::Add,
+    {
+        fn constant(value: usize) -> Self {
+            let mut res = Self::ZERO;
+            let mut count = 0;
+            while count < value {
+                res = res + Self::ONE;
+                count += 1;
+            }
+            res
+        }
+    }
+}
diff --git a/src/tools/clippy/tests/ui/assign_ops.stderr b/src/tools/clippy/tests/ui/assign_ops.stderr
index 881a333fbe4..c5e698b3ee1 100644
--- a/src/tools/clippy/tests/ui/assign_ops.stderr
+++ b/src/tools/clippy/tests/ui/assign_ops.stderr
@@ -1,5 +1,5 @@
 error: manual implementation of an assign operation
-  --> tests/ui/assign_ops.rs:9:5
+  --> tests/ui/assign_ops.rs:10:5
    |
 LL |     a = a + 1;
    |     ^^^^^^^^^ help: replace it with: `a += 1`
@@ -8,67 +8,67 @@ LL |     a = a + 1;
    = help: to override `-D warnings` add `#[allow(clippy::assign_op_pattern)]`
 
 error: manual implementation of an assign operation
-  --> tests/ui/assign_ops.rs:11:5
+  --> tests/ui/assign_ops.rs:12:5
    |
 LL |     a = 1 + a;
    |     ^^^^^^^^^ help: replace it with: `a += 1`
 
 error: manual implementation of an assign operation
-  --> tests/ui/assign_ops.rs:13:5
+  --> tests/ui/assign_ops.rs:14:5
    |
 LL |     a = a - 1;
    |     ^^^^^^^^^ help: replace it with: `a -= 1`
 
 error: manual implementation of an assign operation
-  --> tests/ui/assign_ops.rs:15:5
+  --> tests/ui/assign_ops.rs:16:5
    |
 LL |     a = a * 99;
    |     ^^^^^^^^^^ help: replace it with: `a *= 99`
 
 error: manual implementation of an assign operation
-  --> tests/ui/assign_ops.rs:17:5
+  --> tests/ui/assign_ops.rs:18:5
    |
 LL |     a = 42 * a;
    |     ^^^^^^^^^^ help: replace it with: `a *= 42`
 
 error: manual implementation of an assign operation
-  --> tests/ui/assign_ops.rs:19:5
+  --> tests/ui/assign_ops.rs:20:5
    |
 LL |     a = a / 2;
    |     ^^^^^^^^^ help: replace it with: `a /= 2`
 
 error: manual implementation of an assign operation
-  --> tests/ui/assign_ops.rs:21:5
+  --> tests/ui/assign_ops.rs:22:5
    |
 LL |     a = a % 5;
    |     ^^^^^^^^^ help: replace it with: `a %= 5`
 
 error: manual implementation of an assign operation
-  --> tests/ui/assign_ops.rs:23:5
+  --> tests/ui/assign_ops.rs:24:5
    |
 LL |     a = a & 1;
    |     ^^^^^^^^^ help: replace it with: `a &= 1`
 
 error: manual implementation of an assign operation
-  --> tests/ui/assign_ops.rs:30:5
+  --> tests/ui/assign_ops.rs:31:5
    |
 LL |     s = s + "bla";
    |     ^^^^^^^^^^^^^ help: replace it with: `s += "bla"`
 
 error: manual implementation of an assign operation
-  --> tests/ui/assign_ops.rs:35:5
+  --> tests/ui/assign_ops.rs:36:5
    |
 LL |     a = a + Wrapping(1u32);
    |     ^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `a += Wrapping(1u32)`
 
 error: manual implementation of an assign operation
-  --> tests/ui/assign_ops.rs:38:5
+  --> tests/ui/assign_ops.rs:39:5
    |
 LL |     v[0] = v[0] + v[1];
    |     ^^^^^^^^^^^^^^^^^^ help: replace it with: `v[0] += v[1]`
 
 error: manual implementation of an assign operation
-  --> tests/ui/assign_ops.rs:51:5
+  --> tests/ui/assign_ops.rs:52:5
    |
 LL |     buf = buf + cows.clone();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `buf += cows.clone()`
diff --git a/src/tools/clippy/tests/ui/auxiliary/proc_macro_attr.rs b/src/tools/clippy/tests/ui/auxiliary/proc_macro_attr.rs
index 4c61c5accd3..9b8e62867f0 100644
--- a/src/tools/clippy/tests/ui/auxiliary/proc_macro_attr.rs
+++ b/src/tools/clippy/tests/ui/auxiliary/proc_macro_attr.rs
@@ -1,5 +1,4 @@
-#![feature(repr128, proc_macro_hygiene, proc_macro_quote, box_patterns)]
-#![allow(incomplete_features)]
+#![feature(proc_macro_hygiene, proc_macro_quote, box_patterns)]
 #![allow(clippy::useless_conversion, clippy::uninlined_format_args)]
 
 extern crate proc_macro;
diff --git a/src/tools/clippy/tests/ui/auxiliary/proc_macro_derive.rs b/src/tools/clippy/tests/ui/auxiliary/proc_macro_derive.rs
index 1815dd58f51..5992d15935d 100644
--- a/src/tools/clippy/tests/ui/auxiliary/proc_macro_derive.rs
+++ b/src/tools/clippy/tests/ui/auxiliary/proc_macro_derive.rs
@@ -1,5 +1,4 @@
-#![feature(repr128, proc_macro_quote, proc_macro_span)]
-#![allow(incomplete_features)]
+#![feature(proc_macro_quote, proc_macro_span)]
 #![allow(clippy::field_reassign_with_default)]
 #![allow(clippy::eq_op)]
 #![allow(clippy::literal_string_with_formatting_args)]
diff --git a/src/tools/clippy/tests/ui/cast.rs b/src/tools/clippy/tests/ui/cast.rs
index 77329cf5455..525be821650 100644
--- a/src/tools/clippy/tests/ui/cast.rs
+++ b/src/tools/clippy/tests/ui/cast.rs
@@ -1,7 +1,5 @@
 //@no-rustfix: only some diagnostics have suggestions
 
-#![feature(repr128)]
-#![allow(incomplete_features)]
 #![warn(
     clippy::cast_precision_loss,
     clippy::cast_possible_truncation,
diff --git a/src/tools/clippy/tests/ui/cast.stderr b/src/tools/clippy/tests/ui/cast.stderr
index 4d03282f667..1cb30d95667 100644
--- a/src/tools/clippy/tests/ui/cast.stderr
+++ b/src/tools/clippy/tests/ui/cast.stderr
@@ -1,5 +1,5 @@
 error: casting `i32` to `f32` causes a loss of precision (`i32` is 32 bits wide, but `f32`'s mantissa is only 23 bits wide)
-  --> tests/ui/cast.rs:25:5
+  --> tests/ui/cast.rs:23:5
    |
 LL |     x0 as f32;
    |     ^^^^^^^^^
@@ -8,37 +8,37 @@ LL |     x0 as f32;
    = help: to override `-D warnings` add `#[allow(clippy::cast_precision_loss)]`
 
 error: casting `i64` to `f32` causes a loss of precision (`i64` is 64 bits wide, but `f32`'s mantissa is only 23 bits wide)
-  --> tests/ui/cast.rs:29:5
+  --> tests/ui/cast.rs:27:5
    |
 LL |     x1 as f32;
    |     ^^^^^^^^^
 
 error: casting `i64` to `f64` causes a loss of precision (`i64` is 64 bits wide, but `f64`'s mantissa is only 52 bits wide)
-  --> tests/ui/cast.rs:32:5
+  --> tests/ui/cast.rs:30:5
    |
 LL |     x1 as f64;
    |     ^^^^^^^^^
 
 error: casting `u32` to `f32` causes a loss of precision (`u32` is 32 bits wide, but `f32`'s mantissa is only 23 bits wide)
-  --> tests/ui/cast.rs:36:5
+  --> tests/ui/cast.rs:34:5
    |
 LL |     x2 as f32;
    |     ^^^^^^^^^
 
 error: casting `u64` to `f32` causes a loss of precision (`u64` is 64 bits wide, but `f32`'s mantissa is only 23 bits wide)
-  --> tests/ui/cast.rs:40:5
+  --> tests/ui/cast.rs:38:5
    |
 LL |     x3 as f32;
    |     ^^^^^^^^^
 
 error: casting `u64` to `f64` causes a loss of precision (`u64` is 64 bits wide, but `f64`'s mantissa is only 52 bits wide)
-  --> tests/ui/cast.rs:43:5
+  --> tests/ui/cast.rs:41:5
    |
 LL |     x3 as f64;
    |     ^^^^^^^^^
 
 error: casting `f32` to `i32` may truncate the value
-  --> tests/ui/cast.rs:47:5
+  --> tests/ui/cast.rs:45:5
    |
 LL |     1f32 as i32;
    |     ^^^^^^^^^^^
@@ -48,7 +48,7 @@ LL |     1f32 as i32;
    = help: to override `-D warnings` add `#[allow(clippy::cast_possible_truncation)]`
 
 error: casting `f32` to `u32` may truncate the value
-  --> tests/ui/cast.rs:50:5
+  --> tests/ui/cast.rs:48:5
    |
 LL |     1f32 as u32;
    |     ^^^^^^^^^^^
@@ -56,7 +56,7 @@ LL |     1f32 as u32;
    = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
 
 error: casting `f32` to `u32` may lose the sign of the value
-  --> tests/ui/cast.rs:50:5
+  --> tests/ui/cast.rs:48:5
    |
 LL |     1f32 as u32;
    |     ^^^^^^^^^^^
@@ -65,7 +65,7 @@ LL |     1f32 as u32;
    = help: to override `-D warnings` add `#[allow(clippy::cast_sign_loss)]`
 
 error: casting `f64` to `f32` may truncate the value
-  --> tests/ui/cast.rs:54:5
+  --> tests/ui/cast.rs:52:5
    |
 LL |     1f64 as f32;
    |     ^^^^^^^^^^^
@@ -73,7 +73,7 @@ LL |     1f64 as f32;
    = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
 
 error: casting `i32` to `i8` may truncate the value
-  --> tests/ui/cast.rs:57:5
+  --> tests/ui/cast.rs:55:5
    |
 LL |     1i32 as i8;
    |     ^^^^^^^^^^
@@ -86,7 +86,7 @@ LL +     i8::try_from(1i32);
    |
 
 error: casting `i32` to `u8` may truncate the value
-  --> tests/ui/cast.rs:60:5
+  --> tests/ui/cast.rs:58:5
    |
 LL |     1i32 as u8;
    |     ^^^^^^^^^^
@@ -99,7 +99,7 @@ LL +     u8::try_from(1i32);
    |
 
 error: casting `f64` to `isize` may truncate the value
-  --> tests/ui/cast.rs:63:5
+  --> tests/ui/cast.rs:61:5
    |
 LL |     1f64 as isize;
    |     ^^^^^^^^^^^^^
@@ -107,7 +107,7 @@ LL |     1f64 as isize;
    = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
 
 error: casting `f64` to `usize` may truncate the value
-  --> tests/ui/cast.rs:66:5
+  --> tests/ui/cast.rs:64:5
    |
 LL |     1f64 as usize;
    |     ^^^^^^^^^^^^^
@@ -115,13 +115,13 @@ LL |     1f64 as usize;
    = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
 
 error: casting `f64` to `usize` may lose the sign of the value
-  --> tests/ui/cast.rs:66:5
+  --> tests/ui/cast.rs:64:5
    |
 LL |     1f64 as usize;
    |     ^^^^^^^^^^^^^
 
 error: casting `u32` to `u16` may truncate the value
-  --> tests/ui/cast.rs:70:5
+  --> tests/ui/cast.rs:68:5
    |
 LL |     1f32 as u32 as u16;
    |     ^^^^^^^^^^^^^^^^^^
@@ -134,7 +134,7 @@ LL +     u16::try_from(1f32 as u32);
    |
 
 error: casting `f32` to `u32` may truncate the value
-  --> tests/ui/cast.rs:70:5
+  --> tests/ui/cast.rs:68:5
    |
 LL |     1f32 as u32 as u16;
    |     ^^^^^^^^^^^
@@ -142,13 +142,13 @@ LL |     1f32 as u32 as u16;
    = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
 
 error: casting `f32` to `u32` may lose the sign of the value
-  --> tests/ui/cast.rs:70:5
+  --> tests/ui/cast.rs:68:5
    |
 LL |     1f32 as u32 as u16;
    |     ^^^^^^^^^^^
 
 error: casting `i32` to `i8` may truncate the value
-  --> tests/ui/cast.rs:76:22
+  --> tests/ui/cast.rs:74:22
    |
 LL |         let _x: i8 = 1i32 as _;
    |                      ^^^^^^^^^
@@ -161,7 +161,7 @@ LL +         let _x: i8 = 1i32.try_into();
    |
 
 error: casting `f32` to `i32` may truncate the value
-  --> tests/ui/cast.rs:79:9
+  --> tests/ui/cast.rs:77:9
    |
 LL |         1f32 as i32;
    |         ^^^^^^^^^^^
@@ -169,7 +169,7 @@ LL |         1f32 as i32;
    = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
 
 error: casting `f64` to `i32` may truncate the value
-  --> tests/ui/cast.rs:82:9
+  --> tests/ui/cast.rs:80:9
    |
 LL |         1f64 as i32;
    |         ^^^^^^^^^^^
@@ -177,7 +177,7 @@ LL |         1f64 as i32;
    = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
 
 error: casting `f32` to `u8` may truncate the value
-  --> tests/ui/cast.rs:85:9
+  --> tests/ui/cast.rs:83:9
    |
 LL |         1f32 as u8;
    |         ^^^^^^^^^^
@@ -185,13 +185,13 @@ LL |         1f32 as u8;
    = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
 
 error: casting `f32` to `u8` may lose the sign of the value
-  --> tests/ui/cast.rs:85:9
+  --> tests/ui/cast.rs:83:9
    |
 LL |         1f32 as u8;
    |         ^^^^^^^^^^
 
 error: casting `u8` to `i8` may wrap around the value
-  --> tests/ui/cast.rs:90:5
+  --> tests/ui/cast.rs:88:5
    |
 LL |     1u8 as i8;
    |     ^^^^^^^^^
@@ -200,31 +200,31 @@ LL |     1u8 as i8;
    = help: to override `-D warnings` add `#[allow(clippy::cast_possible_wrap)]`
 
 error: casting `u16` to `i16` may wrap around the value
-  --> tests/ui/cast.rs:93:5
+  --> tests/ui/cast.rs:91:5
    |
 LL |     1u16 as i16;
    |     ^^^^^^^^^^^
 
 error: casting `u32` to `i32` may wrap around the value
-  --> tests/ui/cast.rs:96:5
+  --> tests/ui/cast.rs:94:5
    |
 LL |     1u32 as i32;
    |     ^^^^^^^^^^^
 
 error: casting `u64` to `i64` may wrap around the value
-  --> tests/ui/cast.rs:99:5
+  --> tests/ui/cast.rs:97:5
    |
 LL |     1u64 as i64;
    |     ^^^^^^^^^^^
 
 error: casting `usize` to `isize` may wrap around the value
-  --> tests/ui/cast.rs:102:5
+  --> tests/ui/cast.rs:100:5
    |
 LL |     1usize as isize;
    |     ^^^^^^^^^^^^^^^
 
 error: casting `usize` to `i8` may truncate the value
-  --> tests/ui/cast.rs:106:5
+  --> tests/ui/cast.rs:104:5
    |
 LL |     1usize as i8;
    |     ^^^^^^^^^^^^
@@ -237,7 +237,7 @@ LL +     i8::try_from(1usize);
    |
 
 error: casting `usize` to `i16` may truncate the value
-  --> tests/ui/cast.rs:110:5
+  --> tests/ui/cast.rs:108:5
    |
 LL |     1usize as i16;
    |     ^^^^^^^^^^^^^
@@ -250,7 +250,7 @@ LL +     i16::try_from(1usize);
    |
 
 error: casting `usize` to `i16` may wrap around the value on targets with 16-bit wide pointers
-  --> tests/ui/cast.rs:110:5
+  --> tests/ui/cast.rs:108:5
    |
 LL |     1usize as i16;
    |     ^^^^^^^^^^^^^
@@ -259,7 +259,7 @@ LL |     1usize as i16;
    = note: for more information see https://doc.rust-lang.org/reference/types/numeric.html#machine-dependent-integer-types
 
 error: casting `usize` to `i32` may truncate the value on targets with 64-bit wide pointers
-  --> tests/ui/cast.rs:115:5
+  --> tests/ui/cast.rs:113:5
    |
 LL |     1usize as i32;
    |     ^^^^^^^^^^^^^
@@ -272,19 +272,19 @@ LL +     i32::try_from(1usize);
    |
 
 error: casting `usize` to `i32` may wrap around the value on targets with 32-bit wide pointers
-  --> tests/ui/cast.rs:115:5
+  --> tests/ui/cast.rs:113:5
    |
 LL |     1usize as i32;
    |     ^^^^^^^^^^^^^
 
 error: casting `usize` to `i64` may wrap around the value on targets with 64-bit wide pointers
-  --> tests/ui/cast.rs:120:5
+  --> tests/ui/cast.rs:118:5
    |
 LL |     1usize as i64;
    |     ^^^^^^^^^^^^^
 
 error: casting `u16` to `isize` may wrap around the value on targets with 16-bit wide pointers
-  --> tests/ui/cast.rs:126:5
+  --> tests/ui/cast.rs:124:5
    |
 LL |     1u16 as isize;
    |     ^^^^^^^^^^^^^
@@ -293,13 +293,13 @@ LL |     1u16 as isize;
    = note: for more information see https://doc.rust-lang.org/reference/types/numeric.html#machine-dependent-integer-types
 
 error: casting `u32` to `isize` may wrap around the value on targets with 32-bit wide pointers
-  --> tests/ui/cast.rs:130:5
+  --> tests/ui/cast.rs:128:5
    |
 LL |     1u32 as isize;
    |     ^^^^^^^^^^^^^
 
 error: casting `u64` to `isize` may truncate the value on targets with 32-bit wide pointers
-  --> tests/ui/cast.rs:134:5
+  --> tests/ui/cast.rs:132:5
    |
 LL |     1u64 as isize;
    |     ^^^^^^^^^^^^^
@@ -312,55 +312,55 @@ LL +     isize::try_from(1u64);
    |
 
 error: casting `u64` to `isize` may wrap around the value on targets with 64-bit wide pointers
-  --> tests/ui/cast.rs:134:5
+  --> tests/ui/cast.rs:132:5
    |
 LL |     1u64 as isize;
    |     ^^^^^^^^^^^^^
 
 error: casting `i32` to `u32` may lose the sign of the value
-  --> tests/ui/cast.rs:140:5
+  --> tests/ui/cast.rs:138:5
    |
 LL |     -1i32 as u32;
    |     ^^^^^^^^^^^^
 
 error: casting `isize` to `usize` may lose the sign of the value
-  --> tests/ui/cast.rs:144:5
+  --> tests/ui/cast.rs:142:5
    |
 LL |     -1isize as usize;
    |     ^^^^^^^^^^^^^^^^
 
 error: casting `i8` to `u8` may lose the sign of the value
-  --> tests/ui/cast.rs:156:5
+  --> tests/ui/cast.rs:154:5
    |
 LL |     (i8::MIN).abs() as u8;
    |     ^^^^^^^^^^^^^^^^^^^^^
 
 error: casting `i64` to `u64` may lose the sign of the value
-  --> tests/ui/cast.rs:161:5
+  --> tests/ui/cast.rs:159:5
    |
 LL |     (-1i64).abs() as u64;
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: casting `isize` to `usize` may lose the sign of the value
-  --> tests/ui/cast.rs:163:5
+  --> tests/ui/cast.rs:161:5
    |
 LL |     (-1isize).abs() as usize;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: casting `i64` to `u64` may lose the sign of the value
-  --> tests/ui/cast.rs:171:5
+  --> tests/ui/cast.rs:169:5
    |
 LL |     (unsafe { (-1i64).checked_abs().unwrap_unchecked() }) as u64;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: casting `i64` to `u64` may lose the sign of the value
-  --> tests/ui/cast.rs:187:5
+  --> tests/ui/cast.rs:185:5
    |
 LL |     (unsafe { (-1i64).checked_isqrt().unwrap_unchecked() }) as u64;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: casting `i64` to `i8` may truncate the value
-  --> tests/ui/cast.rs:239:5
+  --> tests/ui/cast.rs:237:5
    |
 LL |     (-99999999999i64).min(1) as i8;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -373,7 +373,7 @@ LL +     i8::try_from((-99999999999i64).min(1));
    |
 
 error: casting `u64` to `u8` may truncate the value
-  --> tests/ui/cast.rs:253:5
+  --> tests/ui/cast.rs:251:5
    |
 LL |     999999u64.clamp(0, 256) as u8;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -386,7 +386,7 @@ LL +     u8::try_from(999999u64.clamp(0, 256));
    |
 
 error: casting `main::E2` to `u8` may truncate the value
-  --> tests/ui/cast.rs:276:21
+  --> tests/ui/cast.rs:274:21
    |
 LL |             let _ = self as u8;
    |                     ^^^^^^^^^^
@@ -399,7 +399,7 @@ LL +             let _ = u8::try_from(self);
    |
 
 error: casting `main::E2::B` to `u8` will truncate the value
-  --> tests/ui/cast.rs:279:21
+  --> tests/ui/cast.rs:277:21
    |
 LL |             let _ = Self::B as u8;
    |                     ^^^^^^^^^^^^^
@@ -408,7 +408,7 @@ LL |             let _ = Self::B as u8;
    = help: to override `-D warnings` add `#[allow(clippy::cast_enum_truncation)]`
 
 error: casting `main::E5` to `i8` may truncate the value
-  --> tests/ui/cast.rs:321:21
+  --> tests/ui/cast.rs:319:21
    |
 LL |             let _ = self as i8;
    |                     ^^^^^^^^^^
@@ -421,13 +421,13 @@ LL +             let _ = i8::try_from(self);
    |
 
 error: casting `main::E5::A` to `i8` will truncate the value
-  --> tests/ui/cast.rs:324:21
+  --> tests/ui/cast.rs:322:21
    |
 LL |             let _ = Self::A as i8;
    |                     ^^^^^^^^^^^^^
 
 error: casting `main::E6` to `i16` may truncate the value
-  --> tests/ui/cast.rs:342:21
+  --> tests/ui/cast.rs:340:21
    |
 LL |             let _ = self as i16;
    |                     ^^^^^^^^^^^
@@ -440,7 +440,7 @@ LL +             let _ = i16::try_from(self);
    |
 
 error: casting `main::E7` to `usize` may truncate the value on targets with 32-bit wide pointers
-  --> tests/ui/cast.rs:362:21
+  --> tests/ui/cast.rs:360:21
    |
 LL |             let _ = self as usize;
    |                     ^^^^^^^^^^^^^
@@ -453,7 +453,7 @@ LL +             let _ = usize::try_from(self);
    |
 
 error: casting `main::E10` to `u16` may truncate the value
-  --> tests/ui/cast.rs:410:21
+  --> tests/ui/cast.rs:408:21
    |
 LL |             let _ = self as u16;
    |                     ^^^^^^^^^^^
@@ -466,7 +466,7 @@ LL +             let _ = u16::try_from(self);
    |
 
 error: casting `u32` to `u8` may truncate the value
-  --> tests/ui/cast.rs:422:13
+  --> tests/ui/cast.rs:420:13
    |
 LL |     let c = (q >> 16) as u8;
    |             ^^^^^^^^^^^^^^^
@@ -479,7 +479,7 @@ LL +     let c = u8::try_from(q >> 16);
    |
 
 error: casting `u32` to `u8` may truncate the value
-  --> tests/ui/cast.rs:427:13
+  --> tests/ui/cast.rs:425:13
    |
 LL |     let c = (q / 1000) as u8;
    |             ^^^^^^^^^^^^^^^^
@@ -492,85 +492,85 @@ LL +     let c = u8::try_from(q / 1000);
    |
 
 error: casting `i32` to `u32` may lose the sign of the value
-  --> tests/ui/cast.rs:440:9
+  --> tests/ui/cast.rs:438:9
    |
 LL |         (x * x) as u32;
    |         ^^^^^^^^^^^^^^
 
 error: casting `i32` to `u32` may lose the sign of the value
-  --> tests/ui/cast.rs:446:32
+  --> tests/ui/cast.rs:444:32
    |
 LL |     let _a = |x: i32| -> u32 { (x * x * x * x) as u32 };
    |                                ^^^^^^^^^^^^^^^^^^^^^^
 
 error: casting `i32` to `u32` may lose the sign of the value
-  --> tests/ui/cast.rs:449:5
+  --> tests/ui/cast.rs:447:5
    |
 LL |     (2_i32).checked_pow(3).unwrap() as u32;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: casting `i32` to `u32` may lose the sign of the value
-  --> tests/ui/cast.rs:451:5
+  --> tests/ui/cast.rs:449:5
    |
 LL |     (-2_i32).pow(3) as u32;
    |     ^^^^^^^^^^^^^^^^^^^^^^
 
 error: casting `i32` to `u32` may lose the sign of the value
-  --> tests/ui/cast.rs:456:5
+  --> tests/ui/cast.rs:454:5
    |
 LL |     (-5_i32 % 2) as u32;
    |     ^^^^^^^^^^^^^^^^^^^
 
 error: casting `i32` to `u32` may lose the sign of the value
-  --> tests/ui/cast.rs:459:5
+  --> tests/ui/cast.rs:457:5
    |
 LL |     (-5_i32 % -2) as u32;
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: casting `i32` to `u32` may lose the sign of the value
-  --> tests/ui/cast.rs:463:5
+  --> tests/ui/cast.rs:461:5
    |
 LL |     (-2_i32 >> 1) as u32;
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: casting `i32` to `u32` may lose the sign of the value
-  --> tests/ui/cast.rs:467:5
+  --> tests/ui/cast.rs:465:5
    |
 LL |     (x * x) as u32;
    |     ^^^^^^^^^^^^^^
 
 error: casting `i32` to `u32` may lose the sign of the value
-  --> tests/ui/cast.rs:469:5
+  --> tests/ui/cast.rs:467:5
    |
 LL |     (x * x * x) as u32;
    |     ^^^^^^^^^^^^^^^^^^
 
 error: casting `i16` to `u16` may lose the sign of the value
-  --> tests/ui/cast.rs:473:5
+  --> tests/ui/cast.rs:471:5
    |
 LL |     (y * y * y * y * -2) as u16;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: casting `i16` to `u16` may lose the sign of the value
-  --> tests/ui/cast.rs:476:5
+  --> tests/ui/cast.rs:474:5
    |
 LL |     (y * y * y / y * 2) as u16;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: casting `i16` to `u16` may lose the sign of the value
-  --> tests/ui/cast.rs:478:5
+  --> tests/ui/cast.rs:476:5
    |
 LL |     (y * y / y * 2) as u16;
    |     ^^^^^^^^^^^^^^^^^^^^^^
 
 error: casting `i16` to `u16` may lose the sign of the value
-  --> tests/ui/cast.rs:481:5
+  --> tests/ui/cast.rs:479:5
    |
 LL |     (y / y * y * -2) as u16;
    |     ^^^^^^^^^^^^^^^^^^^^^^^
 
 error: equal expressions as operands to `/`
-  --> tests/ui/cast.rs:481:6
+  --> tests/ui/cast.rs:479:6
    |
 LL |     (y / y * y * -2) as u16;
    |      ^^^^^
@@ -578,97 +578,97 @@ LL |     (y / y * y * -2) as u16;
    = note: `#[deny(clippy::eq_op)]` on by default
 
 error: casting `i16` to `u16` may lose the sign of the value
-  --> tests/ui/cast.rs:485:5
+  --> tests/ui/cast.rs:483:5
    |
 LL |     (y + y + y + -2) as u16;
    |     ^^^^^^^^^^^^^^^^^^^^^^^
 
 error: casting `i16` to `u16` may lose the sign of the value
-  --> tests/ui/cast.rs:488:5
+  --> tests/ui/cast.rs:486:5
    |
 LL |     (y + y + y + 2) as u16;
    |     ^^^^^^^^^^^^^^^^^^^^^^
 
 error: casting `i16` to `u16` may lose the sign of the value
-  --> tests/ui/cast.rs:492:5
+  --> tests/ui/cast.rs:490:5
    |
 LL |     (z + -2) as u16;
    |     ^^^^^^^^^^^^^^^
 
 error: casting `i16` to `u16` may lose the sign of the value
-  --> tests/ui/cast.rs:495:5
+  --> tests/ui/cast.rs:493:5
    |
 LL |     (z + z + 2) as u16;
    |     ^^^^^^^^^^^^^^^^^^
 
 error: casting `i32` to `u32` may lose the sign of the value
-  --> tests/ui/cast.rs:499:9
+  --> tests/ui/cast.rs:497:9
    |
 LL |         (a * a * b * b * c * c) as u32;
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: casting `i32` to `u32` may lose the sign of the value
-  --> tests/ui/cast.rs:501:9
+  --> tests/ui/cast.rs:499:9
    |
 LL |         (a * b * c) as u32;
    |         ^^^^^^^^^^^^^^^^^^
 
 error: casting `i32` to `u32` may lose the sign of the value
-  --> tests/ui/cast.rs:504:9
+  --> tests/ui/cast.rs:502:9
    |
 LL |         (a * -b * c) as u32;
    |         ^^^^^^^^^^^^^^^^^^^
 
 error: casting `i32` to `u32` may lose the sign of the value
-  --> tests/ui/cast.rs:507:9
+  --> tests/ui/cast.rs:505:9
    |
 LL |         (a * b * c * c) as u32;
    |         ^^^^^^^^^^^^^^^^^^^^^^
 
 error: casting `i32` to `u32` may lose the sign of the value
-  --> tests/ui/cast.rs:509:9
+  --> tests/ui/cast.rs:507:9
    |
 LL |         (a * -2) as u32;
    |         ^^^^^^^^^^^^^^^
 
 error: casting `i32` to `u32` may lose the sign of the value
-  --> tests/ui/cast.rs:512:9
+  --> tests/ui/cast.rs:510:9
    |
 LL |         (a * b * c * -2) as u32;
    |         ^^^^^^^^^^^^^^^^^^^^^^^
 
 error: casting `i32` to `u32` may lose the sign of the value
-  --> tests/ui/cast.rs:515:9
+  --> tests/ui/cast.rs:513:9
    |
 LL |         (a / b) as u32;
    |         ^^^^^^^^^^^^^^
 
 error: casting `i32` to `u32` may lose the sign of the value
-  --> tests/ui/cast.rs:517:9
+  --> tests/ui/cast.rs:515:9
    |
 LL |         (a / b * c) as u32;
    |         ^^^^^^^^^^^^^^^^^^
 
 error: casting `i32` to `u32` may lose the sign of the value
-  --> tests/ui/cast.rs:520:9
+  --> tests/ui/cast.rs:518:9
    |
 LL |         (a / b + b * c) as u32;
    |         ^^^^^^^^^^^^^^^^^^^^^^
 
 error: casting `i32` to `u32` may lose the sign of the value
-  --> tests/ui/cast.rs:523:9
+  --> tests/ui/cast.rs:521:9
    |
 LL |         a.saturating_pow(3) as u32;
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: casting `i32` to `u32` may lose the sign of the value
-  --> tests/ui/cast.rs:526:9
+  --> tests/ui/cast.rs:524:9
    |
 LL |         (a.abs() * b.pow(2) / c.abs()) as u32
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: casting `i32` to `u32` may lose the sign of the value
-  --> tests/ui/cast.rs:534:21
+  --> tests/ui/cast.rs:532:21
    |
 LL |             let _ = i32::MIN as u32; // cast_sign_loss
    |                     ^^^^^^^^^^^^^^^
@@ -679,7 +679,7 @@ LL |     m!();
    = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: casting `u32` to `u8` may truncate the value
-  --> tests/ui/cast.rs:537:21
+  --> tests/ui/cast.rs:535:21
    |
 LL |             let _ = u32::MAX as u8; // cast_possible_truncation
    |                     ^^^^^^^^^^^^^^
@@ -696,7 +696,7 @@ LL +             let _ = u8::try_from(u32::MAX); // cast_possible_truncation
    |
 
 error: casting `f64` to `f32` may truncate the value
-  --> tests/ui/cast.rs:540:21
+  --> tests/ui/cast.rs:538:21
    |
 LL |             let _ = std::f64::consts::PI as f32; // cast_possible_truncation
    |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -708,7 +708,7 @@ LL |     m!();
    = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: casting `i64` to `usize` may truncate the value on targets with 32-bit wide pointers
-  --> tests/ui/cast.rs:551:5
+  --> tests/ui/cast.rs:549:5
    |
 LL |     bar.unwrap().unwrap() as usize
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -721,13 +721,13 @@ LL +     usize::try_from(bar.unwrap().unwrap())
    |
 
 error: casting `i64` to `usize` may lose the sign of the value
-  --> tests/ui/cast.rs:551:5
+  --> tests/ui/cast.rs:549:5
    |
 LL |     bar.unwrap().unwrap() as usize
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: casting `u64` to `u8` may truncate the value
-  --> tests/ui/cast.rs:568:5
+  --> tests/ui/cast.rs:566:5
    |
 LL |     (256 & 999999u64) as u8;
    |     ^^^^^^^^^^^^^^^^^^^^^^^
@@ -740,7 +740,7 @@ LL +     u8::try_from(256 & 999999u64);
    |
 
 error: casting `u64` to `u8` may truncate the value
-  --> tests/ui/cast.rs:571:5
+  --> tests/ui/cast.rs:569:5
    |
 LL |     (255 % 999999u64) as u8;
    |     ^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/tools/clippy/tests/ui/crashes/auxiliary/proc_macro_crash.rs b/src/tools/clippy/tests/ui/crashes/auxiliary/proc_macro_crash.rs
index 5dffddc119a..cf37a4c5c4b 100644
--- a/src/tools/clippy/tests/ui/crashes/auxiliary/proc_macro_crash.rs
+++ b/src/tools/clippy/tests/ui/crashes/auxiliary/proc_macro_crash.rs
@@ -1,6 +1,3 @@
-#![feature(repr128)]
-#![allow(incomplete_features)]
-
 extern crate proc_macro;
 
 use proc_macro::{Delimiter, Group, Ident, Span, TokenStream, TokenTree};
diff --git a/src/tools/clippy/tests/ui/dbg_macro/dbg_macro.fixed b/src/tools/clippy/tests/ui/dbg_macro/dbg_macro.fixed
index 3b9dee81898..5993c2faf0d 100644
--- a/src/tools/clippy/tests/ui/dbg_macro/dbg_macro.fixed
+++ b/src/tools/clippy/tests/ui/dbg_macro/dbg_macro.fixed
@@ -123,3 +123,19 @@ mod issue12131 {
         //~^ dbg_macro
     }
 }
+
+mod issue14914 {
+    use std::future::Future;
+
+    fn takes_async_fn<F, Fut>(_f: F)
+    where
+        F: FnOnce(i32) -> Fut,
+        Fut: Future<Output = i32>,
+    {
+    }
+
+    fn should_not_panic() {
+        takes_async_fn(async |val| val);
+        //~^ dbg_macro
+    }
+}
diff --git a/src/tools/clippy/tests/ui/dbg_macro/dbg_macro.rs b/src/tools/clippy/tests/ui/dbg_macro/dbg_macro.rs
index 1dbbc6fe984..58d7e106e23 100644
--- a/src/tools/clippy/tests/ui/dbg_macro/dbg_macro.rs
+++ b/src/tools/clippy/tests/ui/dbg_macro/dbg_macro.rs
@@ -123,3 +123,19 @@ mod issue12131 {
         //~^ dbg_macro
     }
 }
+
+mod issue14914 {
+    use std::future::Future;
+
+    fn takes_async_fn<F, Fut>(_f: F)
+    where
+        F: FnOnce(i32) -> Fut,
+        Fut: Future<Output = i32>,
+    {
+    }
+
+    fn should_not_panic() {
+        takes_async_fn(async |val| dbg!(val));
+        //~^ dbg_macro
+    }
+}
diff --git a/src/tools/clippy/tests/ui/dbg_macro/dbg_macro.stderr b/src/tools/clippy/tests/ui/dbg_macro/dbg_macro.stderr
index f1412023cc8..5a65b38a85c 100644
--- a/src/tools/clippy/tests/ui/dbg_macro/dbg_macro.stderr
+++ b/src/tools/clippy/tests/ui/dbg_macro/dbg_macro.stderr
@@ -230,5 +230,17 @@ LL -         print!("{}", dbg!(s));
 LL +         print!("{}", s);
    |
 
-error: aborting due to 19 previous errors
+error: the `dbg!` macro is intended as a debugging tool
+  --> tests/ui/dbg_macro/dbg_macro.rs:138:36
+   |
+LL |         takes_async_fn(async |val| dbg!(val));
+   |                                    ^^^^^^^^^
+   |
+help: remove the invocation before committing it to a version control system
+   |
+LL -         takes_async_fn(async |val| dbg!(val));
+LL +         takes_async_fn(async |val| val);
+   |
+
+error: aborting due to 20 previous errors
 
diff --git a/src/tools/clippy/tests/ui/doc/doc_markdown-issue_13097.fixed b/src/tools/clippy/tests/ui/doc/doc_markdown-issue_13097.fixed
index fb0f40b34a4..e0136584f3d 100644
--- a/src/tools/clippy/tests/ui/doc/doc_markdown-issue_13097.fixed
+++ b/src/tools/clippy/tests/ui/doc/doc_markdown-issue_13097.fixed
@@ -1,11 +1,37 @@
-// This test checks that words starting with capital letters and ending with "ified" don't
-// trigger the lint.
-
 #![deny(clippy::doc_markdown)]
+#![allow(clippy::doc_lazy_continuation)]
+
+mod issue13097 {
+    // This test checks that words starting with capital letters and ending with "ified" don't
+    // trigger the lint.
+    pub enum OutputFormat {
+        /// `HumaNified`
+        //~^ ERROR: item in documentation is missing backticks
+        Plain,
+        // Should not warn!
+        /// JSONified console output
+        Json,
+    }
+}
 
+#[rustfmt::skip]
 pub enum OutputFormat {
-    /// `HumaNified`
-    //~^ ERROR: item in documentation is missing backticks
+    /**
+     * `HumaNified`
+     //~^ ERROR: item in documentation is missing backticks
+     * Before \u{08888} `HumaNified` \{u08888} After
+     //~^ ERROR: item in documentation is missing backticks
+     * meow meow \[`meow_meow`\] meow meow?
+     //~^ ERROR: item in documentation is missing backticks
+     * \u{08888} `meow_meow` \[meow meow] meow?
+     //~^ ERROR: item in documentation is missing backticks
+     * Above
+     * \u{08888}
+     * \[hi\](<https://example.com>) `HumaNified` \[example](<https://example.com>)
+     //~^ ERROR: item in documentation is missing backticks
+     * \u{08888}
+     * Below
+     */
     Plain,
     // Should not warn!
     /// JSONified console output
diff --git a/src/tools/clippy/tests/ui/doc/doc_markdown-issue_13097.rs b/src/tools/clippy/tests/ui/doc/doc_markdown-issue_13097.rs
index 8c1e1a3cd6c..2e89fe6c56b 100644
--- a/src/tools/clippy/tests/ui/doc/doc_markdown-issue_13097.rs
+++ b/src/tools/clippy/tests/ui/doc/doc_markdown-issue_13097.rs
@@ -1,11 +1,37 @@
-// This test checks that words starting with capital letters and ending with "ified" don't
-// trigger the lint.
-
 #![deny(clippy::doc_markdown)]
+#![allow(clippy::doc_lazy_continuation)]
+
+mod issue13097 {
+    // This test checks that words starting with capital letters and ending with "ified" don't
+    // trigger the lint.
+    pub enum OutputFormat {
+        /// HumaNified
+        //~^ ERROR: item in documentation is missing backticks
+        Plain,
+        // Should not warn!
+        /// JSONified console output
+        Json,
+    }
+}
 
+#[rustfmt::skip]
 pub enum OutputFormat {
-    /// HumaNified
-    //~^ ERROR: item in documentation is missing backticks
+    /**
+     * HumaNified
+     //~^ ERROR: item in documentation is missing backticks
+     * Before \u{08888} HumaNified \{u08888} After
+     //~^ ERROR: item in documentation is missing backticks
+     * meow meow \[meow_meow\] meow meow?
+     //~^ ERROR: item in documentation is missing backticks
+     * \u{08888} meow_meow \[meow meow] meow?
+     //~^ ERROR: item in documentation is missing backticks
+     * Above
+     * \u{08888}
+     * \[hi\](<https://example.com>) HumaNified \[example](<https://example.com>)
+     //~^ ERROR: item in documentation is missing backticks
+     * \u{08888}
+     * Below
+     */
     Plain,
     // Should not warn!
     /// JSONified console output
diff --git a/src/tools/clippy/tests/ui/doc/doc_markdown-issue_13097.stderr b/src/tools/clippy/tests/ui/doc/doc_markdown-issue_13097.stderr
index 65b8f2ed80b..cea788301d4 100644
--- a/src/tools/clippy/tests/ui/doc/doc_markdown-issue_13097.stderr
+++ b/src/tools/clippy/tests/ui/doc/doc_markdown-issue_13097.stderr
@@ -1,19 +1,79 @@
 error: item in documentation is missing backticks
-  --> tests/ui/doc/doc_markdown-issue_13097.rs:7:9
+  --> tests/ui/doc/doc_markdown-issue_13097.rs:8:13
    |
-LL |     /// HumaNified
-   |         ^^^^^^^^^^
+LL |         /// HumaNified
+   |             ^^^^^^^^^^
    |
 note: the lint level is defined here
-  --> tests/ui/doc/doc_markdown-issue_13097.rs:4:9
+  --> tests/ui/doc/doc_markdown-issue_13097.rs:1:9
    |
 LL | #![deny(clippy::doc_markdown)]
    |         ^^^^^^^^^^^^^^^^^^^^
 help: try
    |
-LL -     /// HumaNified
-LL +     /// `HumaNified`
+LL -         /// HumaNified
+LL +         /// `HumaNified`
    |
 
-error: aborting due to 1 previous error
+error: item in documentation is missing backticks
+  --> tests/ui/doc/doc_markdown-issue_13097.rs:20:8
+   |
+LL |      * HumaNified
+   |        ^^^^^^^^^^
+   |
+help: try
+   |
+LL -      * HumaNified
+LL +      * `HumaNified`
+   |
+
+error: item in documentation is missing backticks
+  --> tests/ui/doc/doc_markdown-issue_13097.rs:22:25
+   |
+LL |      * Before \u{08888} HumaNified \{u08888} After
+   |                         ^^^^^^^^^^
+   |
+help: try
+   |
+LL -      * Before \u{08888} HumaNified \{u08888} After
+LL +      * Before \u{08888} `HumaNified` \{u08888} After
+   |
+
+error: item in documentation is missing backticks
+  --> tests/ui/doc/doc_markdown-issue_13097.rs:24:20
+   |
+LL |      * meow meow \[meow_meow\] meow meow?
+   |                    ^^^^^^^^^
+   |
+help: try
+   |
+LL -      * meow meow \[meow_meow\] meow meow?
+LL +      * meow meow \[`meow_meow`\] meow meow?
+   |
+
+error: item in documentation is missing backticks
+  --> tests/ui/doc/doc_markdown-issue_13097.rs:26:18
+   |
+LL |      * \u{08888} meow_meow \[meow meow] meow?
+   |                  ^^^^^^^^^
+   |
+help: try
+   |
+LL -      * \u{08888} meow_meow \[meow meow] meow?
+LL +      * \u{08888} `meow_meow` \[meow meow] meow?
+   |
+
+error: item in documentation is missing backticks
+  --> tests/ui/doc/doc_markdown-issue_13097.rs:30:38
+   |
+LL |      * \[hi\](<https://example.com>) HumaNified \[example](<https://example.com>)
+   |                                      ^^^^^^^^^^
+   |
+help: try
+   |
+LL -      * \[hi\](<https://example.com>) HumaNified \[example](<https://example.com>)
+LL +      * \[hi\](<https://example.com>) `HumaNified` \[example](<https://example.com>)
+   |
+
+error: aborting due to 6 previous errors
 
diff --git a/src/tools/clippy/tests/ui/explicit_deref_methods.fixed b/src/tools/clippy/tests/ui/explicit_deref_methods.fixed
index 619329a6ade..52c4d1b1f30 100644
--- a/src/tools/clippy/tests/ui/explicit_deref_methods.fixed
+++ b/src/tools/clippy/tests/ui/explicit_deref_methods.fixed
@@ -81,12 +81,10 @@ fn main() {
     let b: String = concat(just_return(a));
     //~^ explicit_deref_methods
 
-    let b: &str = &**a;
-    //~^ explicit_deref_methods
+    let b: &str = a.deref().deref();
 
     let opt_a = Some(a.clone());
-    let b = &*opt_a.unwrap();
-    //~^ explicit_deref_methods
+    let b = opt_a.unwrap().deref();
 
     Aaa::deref(&Aaa);
     Aaa::deref_mut(&mut Aaa);
diff --git a/src/tools/clippy/tests/ui/explicit_deref_methods.rs b/src/tools/clippy/tests/ui/explicit_deref_methods.rs
index 9f2d513283c..706d6cb2b79 100644
--- a/src/tools/clippy/tests/ui/explicit_deref_methods.rs
+++ b/src/tools/clippy/tests/ui/explicit_deref_methods.rs
@@ -82,11 +82,9 @@ fn main() {
     //~^ explicit_deref_methods
 
     let b: &str = a.deref().deref();
-    //~^ explicit_deref_methods
 
     let opt_a = Some(a.clone());
     let b = opt_a.unwrap().deref();
-    //~^ explicit_deref_methods
 
     Aaa::deref(&Aaa);
     Aaa::deref_mut(&mut Aaa);
diff --git a/src/tools/clippy/tests/ui/explicit_deref_methods.stderr b/src/tools/clippy/tests/ui/explicit_deref_methods.stderr
index a81e2f60317..5036884366c 100644
--- a/src/tools/clippy/tests/ui/explicit_deref_methods.stderr
+++ b/src/tools/clippy/tests/ui/explicit_deref_methods.stderr
@@ -56,40 +56,28 @@ LL |     let b: String = concat(just_return(a).deref());
    |                            ^^^^^^^^^^^^^^^^^^^^^^ help: try: `just_return(a)`
 
 error: explicit `deref` method call
-  --> tests/ui/explicit_deref_methods.rs:84:19
-   |
-LL |     let b: &str = a.deref().deref();
-   |                   ^^^^^^^^^^^^^^^^^ help: try: `&**a`
-
-error: explicit `deref` method call
-  --> tests/ui/explicit_deref_methods.rs:88:13
-   |
-LL |     let b = opt_a.unwrap().deref();
-   |             ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*opt_a.unwrap()`
-
-error: explicit `deref` method call
-  --> tests/ui/explicit_deref_methods.rs:123:31
+  --> tests/ui/explicit_deref_methods.rs:121:31
    |
 LL |     let b: &str = expr_deref!(a.deref());
    |                               ^^^^^^^^^ help: try: `&*a`
 
 error: explicit `deref` method call
-  --> tests/ui/explicit_deref_methods.rs:141:14
+  --> tests/ui/explicit_deref_methods.rs:139:14
    |
 LL |     let _ = &Deref::deref(&"foo");
    |              ^^^^^^^^^^^^^^^^^^^^ help: try: `*&"foo"`
 
 error: explicit `deref_mut` method call
-  --> tests/ui/explicit_deref_methods.rs:143:14
+  --> tests/ui/explicit_deref_methods.rs:141:14
    |
 LL |     let _ = &DerefMut::deref_mut(&mut x);
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&mut **&mut x`
 
 error: explicit `deref_mut` method call
-  --> tests/ui/explicit_deref_methods.rs:144:14
+  --> tests/ui/explicit_deref_methods.rs:142:14
    |
 LL |     let _ = &DerefMut::deref_mut((&mut &mut x).deref_mut());
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&mut ***(&mut &mut x)`
 
-error: aborting due to 15 previous errors
+error: aborting due to 13 previous errors
 
diff --git a/src/tools/clippy/tests/ui/manual_find_fixable.fixed b/src/tools/clippy/tests/ui/manual_find_fixable.fixed
index 5e6849a4dfb..01b3ebacbeb 100644
--- a/src/tools/clippy/tests/ui/manual_find_fixable.fixed
+++ b/src/tools/clippy/tests/ui/manual_find_fixable.fixed
@@ -179,3 +179,13 @@ fn two_bindings(v: Vec<(u8, u8)>) -> Option<u8> {
 }
 
 fn main() {}
+
+mod issue14826 {
+    fn adjust_fixable(needle: &str) -> Option<&'static str> {
+        ["foo", "bar"].iter().find(|&candidate| candidate.eq_ignore_ascii_case(needle)).map(|v| v as _)
+    }
+
+    fn adjust_unfixable(needle: &str) -> Option<*const str> {
+        ["foo", "bar"].iter().find(|&&candidate| candidate.eq_ignore_ascii_case(needle)).copied().map(|v| v as _)
+    }
+}
diff --git a/src/tools/clippy/tests/ui/manual_find_fixable.rs b/src/tools/clippy/tests/ui/manual_find_fixable.rs
index 08a7dd2c6ee..ce62a4beba1 100644
--- a/src/tools/clippy/tests/ui/manual_find_fixable.rs
+++ b/src/tools/clippy/tests/ui/manual_find_fixable.rs
@@ -251,3 +251,25 @@ fn two_bindings(v: Vec<(u8, u8)>) -> Option<u8> {
 }
 
 fn main() {}
+
+mod issue14826 {
+    fn adjust_fixable(needle: &str) -> Option<&'static str> {
+        for candidate in &["foo", "bar"] {
+            //~^ manual_find
+            if candidate.eq_ignore_ascii_case(needle) {
+                return Some(candidate);
+            }
+        }
+        None
+    }
+
+    fn adjust_unfixable(needle: &str) -> Option<*const str> {
+        for &candidate in &["foo", "bar"] {
+            //~^ manual_find
+            if candidate.eq_ignore_ascii_case(needle) {
+                return Some(candidate);
+            }
+        }
+        None
+    }
+}
diff --git a/src/tools/clippy/tests/ui/manual_find_fixable.stderr b/src/tools/clippy/tests/ui/manual_find_fixable.stderr
index afa453c5a87..020635d90bb 100644
--- a/src/tools/clippy/tests/ui/manual_find_fixable.stderr
+++ b/src/tools/clippy/tests/ui/manual_find_fixable.stderr
@@ -139,5 +139,27 @@ LL | |                 return Some(x);
 LL | |         None
    | |____________^ help: replace with an iterator: `arr.into_iter().find(|&x| x < 1)`
 
-error: aborting due to 12 previous errors
+error: manual implementation of `Iterator::find`
+  --> tests/ui/manual_find_fixable.rs:257:9
+   |
+LL | /         for candidate in &["foo", "bar"] {
+LL | |
+LL | |             if candidate.eq_ignore_ascii_case(needle) {
+LL | |                 return Some(candidate);
+...  |
+LL | |         None
+   | |____________^ help: replace with an iterator: `["foo", "bar"].iter().find(|&candidate| candidate.eq_ignore_ascii_case(needle)).map(|v| v as _)`
+
+error: manual implementation of `Iterator::find`
+  --> tests/ui/manual_find_fixable.rs:267:9
+   |
+LL | /         for &candidate in &["foo", "bar"] {
+LL | |
+LL | |             if candidate.eq_ignore_ascii_case(needle) {
+LL | |                 return Some(candidate);
+...  |
+LL | |         None
+   | |____________^ help: replace with an iterator: `["foo", "bar"].iter().find(|&&candidate| candidate.eq_ignore_ascii_case(needle)).copied().map(|v| v as _)`
+
+error: aborting due to 14 previous errors
 
diff --git a/src/tools/clippy/tests/ui/manual_flatten.rs b/src/tools/clippy/tests/ui/manual_flatten.rs
index 97f35c36e24..f1a0053ef38 100644
--- a/src/tools/clippy/tests/ui/manual_flatten.rs
+++ b/src/tools/clippy/tests/ui/manual_flatten.rs
@@ -123,6 +123,13 @@ fn main() {
         println!("{}", n);
     }
 
+    // Using nested `Some` pattern should not trigger the lint
+    for n in vec![Some((1, Some(2)))] {
+        if let Some((_, Some(n))) = n {
+            println!("{}", n);
+        }
+    }
+
     run_unformatted_tests();
 }
 
diff --git a/src/tools/clippy/tests/ui/manual_flatten.stderr b/src/tools/clippy/tests/ui/manual_flatten.stderr
index 5ab25658017..9a846fe17f3 100644
--- a/src/tools/clippy/tests/ui/manual_flatten.stderr
+++ b/src/tools/clippy/tests/ui/manual_flatten.stderr
@@ -178,7 +178,7 @@ LL | |         }
    | |_________^
 
 error: unnecessary `if let` since only the `Some` variant of the iterator element is used
-  --> tests/ui/manual_flatten.rs:132:5
+  --> tests/ui/manual_flatten.rs:139:5
    |
 LL | /     for n in vec![
 LL | |
@@ -189,7 +189,7 @@ LL | |     }
    | |_____^
    |
 help: remove the `if let` statement in the for loop and then...
-  --> tests/ui/manual_flatten.rs:139:9
+  --> tests/ui/manual_flatten.rs:146:9
    |
 LL | /         if let Some(n) = n {
 LL | |             println!("{:?}", n);
diff --git a/src/tools/clippy/tests/ui/manual_is_variant_and.fixed b/src/tools/clippy/tests/ui/manual_is_variant_and.fixed
index c9c184561dd..18a72188ab5 100644
--- a/src/tools/clippy/tests/ui/manual_is_variant_and.fixed
+++ b/src/tools/clippy/tests/ui/manual_is_variant_and.fixed
@@ -4,6 +4,44 @@
 #[macro_use]
 extern crate option_helpers;
 
+struct Foo<T>(T);
+
+impl<T> Foo<T> {
+    fn map<F: FnMut(T) -> bool>(self, mut f: F) -> Option<bool> {
+        Some(f(self.0))
+    }
+}
+
+fn foo() -> Option<bool> {
+    Some(true)
+}
+
+macro_rules! some_true {
+    () => {
+        Some(true)
+    };
+}
+macro_rules! some_false {
+    () => {
+        Some(false)
+    };
+}
+
+macro_rules! mac {
+    (some $e:expr) => {
+        Some($e)
+    };
+    (some_map $e:expr) => {
+        Some($e).map(|x| x % 2 == 0)
+    };
+    (map $e:expr) => {
+        $e.map(|x| x % 2 == 0)
+    };
+    (eq $a:expr, $b:expr) => {
+        $a == $b
+    };
+}
+
 #[rustfmt::skip]
 fn option_methods() {
     let opt = Some(1);
@@ -21,6 +59,15 @@ fn option_methods() {
     let _ = opt
         .is_some_and(|x| x > 1);
 
+    let _ = Some(2).is_some_and(|x| x % 2 == 0);
+    //~^ manual_is_variant_and
+    let _ = Some(2).is_none_or(|x| x % 2 == 0);
+    //~^ manual_is_variant_and
+    let _ = Some(2).is_some_and(|x| x % 2 == 0);
+    //~^ manual_is_variant_and
+    let _ = Some(2).is_none_or(|x| x % 2 == 0);
+    //~^ manual_is_variant_and
+
     // won't fix because the return type of the closure is not `bool`
     let _ = opt.map(|x| x + 1).unwrap_or_default();
 
@@ -28,6 +75,14 @@ fn option_methods() {
     let _ = opt2.is_some_and(char::is_alphanumeric); // should lint
     //~^ manual_is_variant_and
     let _ = opt_map!(opt2, |x| x == 'a').unwrap_or_default(); // should not lint
+
+    // Should not lint.
+    let _ = Foo::<u32>(0).map(|x| x % 2 == 0) == Some(true);
+    let _ = Some(2).map(|x| x % 2 == 0) != foo();
+    let _ = mac!(eq Some(2).map(|x| x % 2 == 0), Some(true));
+    let _ = mac!(some 2).map(|x| x % 2 == 0) == Some(true);
+    let _ = mac!(some_map 2) == Some(true);
+    let _ = mac!(map Some(2)) == Some(true);
 }
 
 #[rustfmt::skip]
@@ -41,6 +96,13 @@ fn result_methods() {
     });
     let _ = res.is_ok_and(|x| x > 1);
 
+    let _ = Ok::<usize, ()>(2).is_ok_and(|x| x % 2 == 0);
+    //~^ manual_is_variant_and
+    let _ = !Ok::<usize, ()>(2).is_ok_and(|x| x % 2 == 0);
+    //~^ manual_is_variant_and
+    let _ = !Ok::<usize, ()>(2).is_ok_and(|x| x % 2 == 0);
+    //~^ manual_is_variant_and
+
     // won't fix because the return type of the closure is not `bool`
     let _ = res.map(|x| x + 1).unwrap_or_default();
 
diff --git a/src/tools/clippy/tests/ui/manual_is_variant_and.rs b/src/tools/clippy/tests/ui/manual_is_variant_and.rs
index 52c7b56804c..a92f7c04369 100644
--- a/src/tools/clippy/tests/ui/manual_is_variant_and.rs
+++ b/src/tools/clippy/tests/ui/manual_is_variant_and.rs
@@ -4,6 +4,44 @@
 #[macro_use]
 extern crate option_helpers;
 
+struct Foo<T>(T);
+
+impl<T> Foo<T> {
+    fn map<F: FnMut(T) -> bool>(self, mut f: F) -> Option<bool> {
+        Some(f(self.0))
+    }
+}
+
+fn foo() -> Option<bool> {
+    Some(true)
+}
+
+macro_rules! some_true {
+    () => {
+        Some(true)
+    };
+}
+macro_rules! some_false {
+    () => {
+        Some(false)
+    };
+}
+
+macro_rules! mac {
+    (some $e:expr) => {
+        Some($e)
+    };
+    (some_map $e:expr) => {
+        Some($e).map(|x| x % 2 == 0)
+    };
+    (map $e:expr) => {
+        $e.map(|x| x % 2 == 0)
+    };
+    (eq $a:expr, $b:expr) => {
+        $a == $b
+    };
+}
+
 #[rustfmt::skip]
 fn option_methods() {
     let opt = Some(1);
@@ -27,6 +65,15 @@ fn option_methods() {
         //~^ manual_is_variant_and
         .unwrap_or_default();
 
+    let _ = Some(2).map(|x| x % 2 == 0) == Some(true);
+    //~^ manual_is_variant_and
+    let _ = Some(2).map(|x| x % 2 == 0) != Some(true);
+    //~^ manual_is_variant_and
+    let _ = Some(2).map(|x| x % 2 == 0) == some_true!();
+    //~^ manual_is_variant_and
+    let _ = Some(2).map(|x| x % 2 == 0) != some_false!();
+    //~^ manual_is_variant_and
+
     // won't fix because the return type of the closure is not `bool`
     let _ = opt.map(|x| x + 1).unwrap_or_default();
 
@@ -34,6 +81,14 @@ fn option_methods() {
     let _ = opt2.map(char::is_alphanumeric).unwrap_or_default(); // should lint
     //~^ manual_is_variant_and
     let _ = opt_map!(opt2, |x| x == 'a').unwrap_or_default(); // should not lint
+
+    // Should not lint.
+    let _ = Foo::<u32>(0).map(|x| x % 2 == 0) == Some(true);
+    let _ = Some(2).map(|x| x % 2 == 0) != foo();
+    let _ = mac!(eq Some(2).map(|x| x % 2 == 0), Some(true));
+    let _ = mac!(some 2).map(|x| x % 2 == 0) == Some(true);
+    let _ = mac!(some_map 2) == Some(true);
+    let _ = mac!(map Some(2)) == Some(true);
 }
 
 #[rustfmt::skip]
@@ -50,6 +105,13 @@ fn result_methods() {
     //~^ manual_is_variant_and
         .unwrap_or_default();
 
+    let _ = Ok::<usize, ()>(2).map(|x| x % 2 == 0) == Ok(true);
+    //~^ manual_is_variant_and
+    let _ = Ok::<usize, ()>(2).map(|x| x % 2 == 0) != Ok(true);
+    //~^ manual_is_variant_and
+    let _ = Ok::<usize, ()>(2).map(|x| x % 2 == 0) != Ok(true);
+    //~^ manual_is_variant_and
+
     // won't fix because the return type of the closure is not `bool`
     let _ = res.map(|x| x + 1).unwrap_or_default();
 
diff --git a/src/tools/clippy/tests/ui/manual_is_variant_and.stderr b/src/tools/clippy/tests/ui/manual_is_variant_and.stderr
index a4fa500580d..1fb437a8bc7 100644
--- a/src/tools/clippy/tests/ui/manual_is_variant_and.stderr
+++ b/src/tools/clippy/tests/ui/manual_is_variant_and.stderr
@@ -1,5 +1,5 @@
 error: called `map(<f>).unwrap_or_default()` on an `Option` value
-  --> tests/ui/manual_is_variant_and.rs:13:17
+  --> tests/ui/manual_is_variant_and.rs:51:17
    |
 LL |       let _ = opt.map(|x| x > 1)
    |  _________________^
@@ -11,7 +11,7 @@ LL | |         .unwrap_or_default();
    = help: to override `-D warnings` add `#[allow(clippy::manual_is_variant_and)]`
 
 error: called `map(<f>).unwrap_or_default()` on an `Option` value
-  --> tests/ui/manual_is_variant_and.rs:18:17
+  --> tests/ui/manual_is_variant_and.rs:56:17
    |
 LL |       let _ = opt.map(|x| {
    |  _________________^
@@ -30,13 +30,13 @@ LL ~     });
    |
 
 error: called `map(<f>).unwrap_or_default()` on an `Option` value
-  --> tests/ui/manual_is_variant_and.rs:23:17
+  --> tests/ui/manual_is_variant_and.rs:61:17
    |
 LL |     let _ = opt.map(|x| x > 1).unwrap_or_default();
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `is_some_and(|x| x > 1)`
 
 error: called `map(<f>).unwrap_or_default()` on an `Option` value
-  --> tests/ui/manual_is_variant_and.rs:26:10
+  --> tests/ui/manual_is_variant_and.rs:64:10
    |
 LL |           .map(|x| x > 1)
    |  __________^
@@ -44,14 +44,38 @@ LL | |
 LL | |         .unwrap_or_default();
    | |____________________________^ help: use: `is_some_and(|x| x > 1)`
 
+error: called `.map() == Some()`
+  --> tests/ui/manual_is_variant_and.rs:68:13
+   |
+LL |     let _ = Some(2).map(|x| x % 2 == 0) == Some(true);
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `Some(2).is_some_and(|x| x % 2 == 0)`
+
+error: called `.map() != Some()`
+  --> tests/ui/manual_is_variant_and.rs:70:13
+   |
+LL |     let _ = Some(2).map(|x| x % 2 == 0) != Some(true);
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `Some(2).is_none_or(|x| x % 2 == 0)`
+
+error: called `.map() == Some()`
+  --> tests/ui/manual_is_variant_and.rs:72:13
+   |
+LL |     let _ = Some(2).map(|x| x % 2 == 0) == some_true!();
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `Some(2).is_some_and(|x| x % 2 == 0)`
+
+error: called `.map() != Some()`
+  --> tests/ui/manual_is_variant_and.rs:74:13
+   |
+LL |     let _ = Some(2).map(|x| x % 2 == 0) != some_false!();
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `Some(2).is_none_or(|x| x % 2 == 0)`
+
 error: called `map(<f>).unwrap_or_default()` on an `Option` value
-  --> tests/ui/manual_is_variant_and.rs:34:18
+  --> tests/ui/manual_is_variant_and.rs:81:18
    |
 LL |     let _ = opt2.map(char::is_alphanumeric).unwrap_or_default(); // should lint
    |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `is_some_and(char::is_alphanumeric)`
 
 error: called `map(<f>).unwrap_or_default()` on a `Result` value
-  --> tests/ui/manual_is_variant_and.rs:44:17
+  --> tests/ui/manual_is_variant_and.rs:99:17
    |
 LL |       let _ = res.map(|x| {
    |  _________________^
@@ -70,7 +94,7 @@ LL ~     });
    |
 
 error: called `map(<f>).unwrap_or_default()` on a `Result` value
-  --> tests/ui/manual_is_variant_and.rs:49:17
+  --> tests/ui/manual_is_variant_and.rs:104:17
    |
 LL |       let _ = res.map(|x| x > 1)
    |  _________________^
@@ -78,11 +102,29 @@ LL | |
 LL | |         .unwrap_or_default();
    | |____________________________^ help: use: `is_ok_and(|x| x > 1)`
 
+error: called `.map() == Ok()`
+  --> tests/ui/manual_is_variant_and.rs:108:13
+   |
+LL |     let _ = Ok::<usize, ()>(2).map(|x| x % 2 == 0) == Ok(true);
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `Ok::<usize, ()>(2).is_ok_and(|x| x % 2 == 0)`
+
+error: called `.map() != Ok()`
+  --> tests/ui/manual_is_variant_and.rs:110:13
+   |
+LL |     let _ = Ok::<usize, ()>(2).map(|x| x % 2 == 0) != Ok(true);
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `!Ok::<usize, ()>(2).is_ok_and(|x| x % 2 == 0)`
+
+error: called `.map() != Ok()`
+  --> tests/ui/manual_is_variant_and.rs:112:13
+   |
+LL |     let _ = Ok::<usize, ()>(2).map(|x| x % 2 == 0) != Ok(true);
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `!Ok::<usize, ()>(2).is_ok_and(|x| x % 2 == 0)`
+
 error: called `map(<f>).unwrap_or_default()` on a `Result` value
-  --> tests/ui/manual_is_variant_and.rs:57:18
+  --> tests/ui/manual_is_variant_and.rs:119:18
    |
 LL |     let _ = res2.map(char::is_alphanumeric).unwrap_or_default(); // should lint
    |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `is_ok_and(char::is_alphanumeric)`
 
-error: aborting due to 8 previous errors
+error: aborting due to 15 previous errors
 
diff --git a/src/tools/clippy/tests/ui/map_flatten.rs b/src/tools/clippy/tests/ui/map_flatten.rs
index d7e9c9d9900..0970da8039a 100644
--- a/src/tools/clippy/tests/ui/map_flatten.rs
+++ b/src/tools/clippy/tests/ui/map_flatten.rs
@@ -1,5 +1,5 @@
 #![warn(clippy::map_flatten)]
-#![feature(result_flattening)]
+
 //@no-rustfix
 // issue #8506, multi-line
 #[rustfmt::skip]
diff --git a/src/tools/clippy/tests/ui/map_flatten_fixable.fixed b/src/tools/clippy/tests/ui/map_flatten_fixable.fixed
index f8379ed23c5..6d8a27d3018 100644
--- a/src/tools/clippy/tests/ui/map_flatten_fixable.fixed
+++ b/src/tools/clippy/tests/ui/map_flatten_fixable.fixed
@@ -1,4 +1,3 @@
-#![feature(result_flattening)]
 #![allow(
     clippy::let_underscore_untyped,
     clippy::missing_docs_in_private_items,
diff --git a/src/tools/clippy/tests/ui/map_flatten_fixable.rs b/src/tools/clippy/tests/ui/map_flatten_fixable.rs
index 040a9ca85f6..845e3a79ae2 100644
--- a/src/tools/clippy/tests/ui/map_flatten_fixable.rs
+++ b/src/tools/clippy/tests/ui/map_flatten_fixable.rs
@@ -1,4 +1,3 @@
-#![feature(result_flattening)]
 #![allow(
     clippy::let_underscore_untyped,
     clippy::missing_docs_in_private_items,
diff --git a/src/tools/clippy/tests/ui/map_flatten_fixable.stderr b/src/tools/clippy/tests/ui/map_flatten_fixable.stderr
index fe68eb7e4ab..05d4d9a6ad8 100644
--- a/src/tools/clippy/tests/ui/map_flatten_fixable.stderr
+++ b/src/tools/clippy/tests/ui/map_flatten_fixable.stderr
@@ -1,5 +1,5 @@
 error: called `map(..).flatten()` on `Iterator`
-  --> tests/ui/map_flatten_fixable.rs:17:47
+  --> tests/ui/map_flatten_fixable.rs:16:47
    |
 LL |     let _: Vec<_> = vec![5_i8; 6].into_iter().map(option_id).flatten().collect();
    |                                               ^^^^^^^^^^^^^^^^^^^^^^^^ help: try replacing `map` with `filter_map` and remove the `.flatten()`: `filter_map(option_id)`
@@ -8,43 +8,43 @@ LL |     let _: Vec<_> = vec![5_i8; 6].into_iter().map(option_id).flatten().coll
    = help: to override `-D warnings` add `#[allow(clippy::map_flatten)]`
 
 error: called `map(..).flatten()` on `Iterator`
-  --> tests/ui/map_flatten_fixable.rs:19:47
+  --> tests/ui/map_flatten_fixable.rs:18:47
    |
 LL |     let _: Vec<_> = vec![5_i8; 6].into_iter().map(option_id_ref).flatten().collect();
    |                                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try replacing `map` with `filter_map` and remove the `.flatten()`: `filter_map(option_id_ref)`
 
 error: called `map(..).flatten()` on `Iterator`
-  --> tests/ui/map_flatten_fixable.rs:21:47
+  --> tests/ui/map_flatten_fixable.rs:20:47
    |
 LL |     let _: Vec<_> = vec![5_i8; 6].into_iter().map(option_id_closure).flatten().collect();
    |                                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try replacing `map` with `filter_map` and remove the `.flatten()`: `filter_map(option_id_closure)`
 
 error: called `map(..).flatten()` on `Iterator`
-  --> tests/ui/map_flatten_fixable.rs:23:47
+  --> tests/ui/map_flatten_fixable.rs:22:47
    |
 LL |     let _: Vec<_> = vec![5_i8; 6].into_iter().map(|x| x.checked_add(1)).flatten().collect();
    |                                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try replacing `map` with `filter_map` and remove the `.flatten()`: `filter_map(|x| x.checked_add(1))`
 
 error: called `map(..).flatten()` on `Iterator`
-  --> tests/ui/map_flatten_fixable.rs:27:47
+  --> tests/ui/map_flatten_fixable.rs:26:47
    |
 LL |     let _: Vec<_> = vec![5_i8; 6].into_iter().map(|x| 0..x).flatten().collect();
    |                                               ^^^^^^^^^^^^^^^^^^^^^^^ help: try replacing `map` with `flat_map` and remove the `.flatten()`: `flat_map(|x| 0..x)`
 
 error: called `map(..).flatten()` on `Option`
-  --> tests/ui/map_flatten_fixable.rs:31:40
+  --> tests/ui/map_flatten_fixable.rs:30:40
    |
 LL |     let _: Option<_> = (Some(Some(1))).map(|x| x).flatten();
    |                                        ^^^^^^^^^^^^^^^^^^^^ help: try replacing `map` with `and_then` and remove the `.flatten()`: `and_then(|x| x)`
 
 error: called `map(..).flatten()` on `Result`
-  --> tests/ui/map_flatten_fixable.rs:35:42
+  --> tests/ui/map_flatten_fixable.rs:34:42
    |
 LL |     let _: Result<_, &str> = (Ok(Ok(1))).map(|x| x).flatten();
    |                                          ^^^^^^^^^^^^^^^^^^^^ help: try replacing `map` with `and_then` and remove the `.flatten()`: `and_then(|x| x)`
 
 error: called `map(..).flatten()` on `Iterator`
-  --> tests/ui/map_flatten_fixable.rs:45:10
+  --> tests/ui/map_flatten_fixable.rs:44:10
    |
 LL |           .map(|n| match n {
    |  __________^
@@ -74,7 +74,7 @@ LL ~         });
    |
 
 error: called `map(..).flatten()` on `Option`
-  --> tests/ui/map_flatten_fixable.rs:66:10
+  --> tests/ui/map_flatten_fixable.rs:65:10
    |
 LL |           .map(|_| {
    |  __________^
diff --git a/src/tools/clippy/tests/ui/needless_borrow.fixed b/src/tools/clippy/tests/ui/needless_borrow.fixed
index d7d344452c5..54cad2e393f 100644
--- a/src/tools/clippy/tests/ui/needless_borrow.fixed
+++ b/src/tools/clippy/tests/ui/needless_borrow.fixed
@@ -107,9 +107,6 @@ fn main() {
     let x = (1, 2);
     let _ = x.0;
     //~^ needless_borrow
-    let x = &x as *const (i32, i32);
-    let _ = unsafe { (*x).0 };
-    //~^ needless_borrow
 
     // Issue #8367
     trait Foo {
@@ -289,3 +286,15 @@ fn issue_12268() {
 
     // compiler
 }
+
+fn issue_14743<T>(slice: &[T]) {
+    let _ = slice.len();
+    //~^ needless_borrow
+
+    let slice = slice as *const [T];
+    let _ = unsafe { (&*slice).len() };
+
+    // Check that rustc would actually warn if Clippy had suggested removing the reference
+    #[expect(dangerous_implicit_autorefs)]
+    let _ = unsafe { (*slice).len() };
+}
diff --git a/src/tools/clippy/tests/ui/needless_borrow.rs b/src/tools/clippy/tests/ui/needless_borrow.rs
index 1f05b90b472..b698c6bfc96 100644
--- a/src/tools/clippy/tests/ui/needless_borrow.rs
+++ b/src/tools/clippy/tests/ui/needless_borrow.rs
@@ -107,9 +107,6 @@ fn main() {
     let x = (1, 2);
     let _ = (&x).0;
     //~^ needless_borrow
-    let x = &x as *const (i32, i32);
-    let _ = unsafe { (&*x).0 };
-    //~^ needless_borrow
 
     // Issue #8367
     trait Foo {
@@ -289,3 +286,15 @@ fn issue_12268() {
 
     // compiler
 }
+
+fn issue_14743<T>(slice: &[T]) {
+    let _ = (&slice).len();
+    //~^ needless_borrow
+
+    let slice = slice as *const [T];
+    let _ = unsafe { (&*slice).len() };
+
+    // Check that rustc would actually warn if Clippy had suggested removing the reference
+    #[expect(dangerous_implicit_autorefs)]
+    let _ = unsafe { (*slice).len() };
+}
diff --git a/src/tools/clippy/tests/ui/needless_borrow.stderr b/src/tools/clippy/tests/ui/needless_borrow.stderr
index b036b1e47d1..172d36bd73a 100644
--- a/src/tools/clippy/tests/ui/needless_borrow.stderr
+++ b/src/tools/clippy/tests/ui/needless_borrow.stderr
@@ -103,71 +103,71 @@ error: this expression borrows a value the compiler would automatically borrow
 LL |     let _ = (&x).0;
    |             ^^^^ help: change this to: `x`
 
-error: this expression borrows a value the compiler would automatically borrow
-  --> tests/ui/needless_borrow.rs:111:22
-   |
-LL |     let _ = unsafe { (&*x).0 };
-   |                      ^^^^^ help: change this to: `(*x)`
-
 error: this expression creates a reference which is immediately dereferenced by the compiler
-  --> tests/ui/needless_borrow.rs:122:5
+  --> tests/ui/needless_borrow.rs:119:5
    |
 LL |     (&&()).foo();
    |     ^^^^^^ help: change this to: `(&())`
 
 error: this expression creates a reference which is immediately dereferenced by the compiler
-  --> tests/ui/needless_borrow.rs:132:5
+  --> tests/ui/needless_borrow.rs:129:5
    |
 LL |     (&&5).foo();
    |     ^^^^^ help: change this to: `(&5)`
 
 error: this expression creates a reference which is immediately dereferenced by the compiler
-  --> tests/ui/needless_borrow.rs:159:23
+  --> tests/ui/needless_borrow.rs:156:23
    |
 LL |     let x: (&str,) = (&"",);
    |                       ^^^ help: change this to: `""`
 
 error: this expression borrows a value the compiler would automatically borrow
-  --> tests/ui/needless_borrow.rs:202:13
+  --> tests/ui/needless_borrow.rs:199:13
    |
 LL |             (&self.f)()
    |             ^^^^^^^^^ help: change this to: `(self.f)`
 
 error: this expression borrows a value the compiler would automatically borrow
-  --> tests/ui/needless_borrow.rs:212:13
+  --> tests/ui/needless_borrow.rs:209:13
    |
 LL |             (&mut self.f)()
    |             ^^^^^^^^^^^^^ help: change this to: `(self.f)`
 
 error: this expression borrows a value the compiler would automatically borrow
-  --> tests/ui/needless_borrow.rs:250:22
+  --> tests/ui/needless_borrow.rs:247:22
    |
 LL |         let _ = &mut (&mut { x.u }).x;
    |                      ^^^^^^^^^^^^^^ help: change this to: `{ x.u }`
 
 error: this expression borrows a value the compiler would automatically borrow
-  --> tests/ui/needless_borrow.rs:258:22
+  --> tests/ui/needless_borrow.rs:255:22
    |
 LL |         let _ = &mut (&mut { x.u }).x;
    |                      ^^^^^^^^^^^^^^ help: change this to: `{ x.u }`
 
 error: this expression borrows a value the compiler would automatically borrow
-  --> tests/ui/needless_borrow.rs:263:22
+  --> tests/ui/needless_borrow.rs:260:22
    |
 LL |         let _ = &mut (&mut x.u).x;
    |                      ^^^^^^^^^^ help: change this to: `x.u`
 
 error: this expression borrows a value the compiler would automatically borrow
-  --> tests/ui/needless_borrow.rs:265:22
+  --> tests/ui/needless_borrow.rs:262:22
    |
 LL |         let _ = &mut (&mut { x.u }).x;
    |                      ^^^^^^^^^^^^^^ help: change this to: `{ x.u }`
 
 error: this expression creates a reference which is immediately dereferenced by the compiler
-  --> tests/ui/needless_borrow.rs:287:23
+  --> tests/ui/needless_borrow.rs:284:23
    |
 LL |     option.unwrap_or((&x.0,));
    |                       ^^^^ help: change this to: `x.0`
 
+error: this expression creates a reference which is immediately dereferenced by the compiler
+  --> tests/ui/needless_borrow.rs:291:13
+   |
+LL |     let _ = (&slice).len();
+   |             ^^^^^^^^ help: change this to: `slice`
+
 error: aborting due to 28 previous errors
 
diff --git a/src/tools/clippy/tests/ui/needless_for_each_fixable.fixed b/src/tools/clippy/tests/ui/needless_for_each_fixable.fixed
index fa23e18318f..a73aff55639 100644
--- a/src/tools/clippy/tests/ui/needless_for_each_fixable.fixed
+++ b/src/tools/clippy/tests/ui/needless_for_each_fixable.fixed
@@ -128,3 +128,18 @@ fn should_not_lint() {
 }
 
 fn main() {}
+
+mod issue14734 {
+    fn let_desugar(rows: &[u8]) {
+        let mut v = vec![];
+        for x in rows.iter() { _ = v.push(x) }
+        //~^ needless_for_each
+    }
+
+    fn do_something(_: &u8, _: u8) {}
+
+    fn single_expr(rows: &[u8]) {
+        for x in rows.iter() { do_something(x, 1u8); }
+        //~^ needless_for_each
+    }
+}
diff --git a/src/tools/clippy/tests/ui/needless_for_each_fixable.rs b/src/tools/clippy/tests/ui/needless_for_each_fixable.rs
index 2c7e68a6f51..d92f055d3f4 100644
--- a/src/tools/clippy/tests/ui/needless_for_each_fixable.rs
+++ b/src/tools/clippy/tests/ui/needless_for_each_fixable.rs
@@ -128,3 +128,18 @@ fn should_not_lint() {
 }
 
 fn main() {}
+
+mod issue14734 {
+    fn let_desugar(rows: &[u8]) {
+        let mut v = vec![];
+        rows.iter().for_each(|x| _ = v.push(x));
+        //~^ needless_for_each
+    }
+
+    fn do_something(_: &u8, _: u8) {}
+
+    fn single_expr(rows: &[u8]) {
+        rows.iter().for_each(|x| do_something(x, 1u8));
+        //~^ needless_for_each
+    }
+}
diff --git a/src/tools/clippy/tests/ui/needless_for_each_fixable.stderr b/src/tools/clippy/tests/ui/needless_for_each_fixable.stderr
index 013a3fa3e36..f8014456097 100644
--- a/src/tools/clippy/tests/ui/needless_for_each_fixable.stderr
+++ b/src/tools/clippy/tests/ui/needless_for_each_fixable.stderr
@@ -136,5 +136,17 @@ LL +         acc += elem;
 LL +     }
    |
 
-error: aborting due to 8 previous errors
+error: needless use of `for_each`
+  --> tests/ui/needless_for_each_fixable.rs:135:9
+   |
+LL |         rows.iter().for_each(|x| _ = v.push(x));
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for x in rows.iter() { _ = v.push(x) }`
+
+error: needless use of `for_each`
+  --> tests/ui/needless_for_each_fixable.rs:142:9
+   |
+LL |         rows.iter().for_each(|x| do_something(x, 1u8));
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for x in rows.iter() { do_something(x, 1u8); }`
+
+error: aborting due to 10 previous errors
 
diff --git a/src/tools/clippy/tests/ui/needless_return.fixed b/src/tools/clippy/tests/ui/needless_return.fixed
index 17d3862cd86..d571b97f519 100644
--- a/src/tools/clippy/tests/ui/needless_return.fixed
+++ b/src/tools/clippy/tests/ui/needless_return.fixed
@@ -452,3 +452,68 @@ pub unsafe fn issue_12157() -> *const i32 {
     (unsafe { todo() } as *const i32)
     //~^ needless_return
 }
+
+mod else_ifs {
+    fn test1(a: i32) -> u32 {
+        if a == 0 {
+            1
+        //~^ needless_return
+        } else if a < 10 {
+            2
+        //~^ needless_return
+        } else {
+            3
+            //~^ needless_return
+        }
+    }
+
+    fn test2(a: i32) -> u32 {
+        if a == 0 {
+            1
+        //~^ needless_return
+        } else if a < 10 {
+            2
+        } else {
+            3
+            //~^ needless_return
+        }
+    }
+
+    fn test3(a: i32) -> u32 {
+        if a == 0 {
+            1
+        //~^ needless_return
+        } else if a < 10 {
+            2
+        } else {
+            3
+            //~^ needless_return
+        }
+    }
+
+    #[allow(clippy::match_single_binding, clippy::redundant_pattern)]
+    fn test4(a: i32) -> u32 {
+        if a == 0 {
+            1
+            //~^ needless_return
+        } else if if if a > 0x1_1 {
+            return 2;
+        } else {
+            return 5;
+        } {
+            true
+        } else {
+            true
+        } {
+            0xDEADC0DE
+        } else if match a {
+            b @ _ => {
+                return 1;
+            },
+        } {
+            0xDEADBEEF
+        } else {
+            1
+        }
+    }
+}
diff --git a/src/tools/clippy/tests/ui/needless_return.rs b/src/tools/clippy/tests/ui/needless_return.rs
index 1c6e7ffa1ee..2e4348ea338 100644
--- a/src/tools/clippy/tests/ui/needless_return.rs
+++ b/src/tools/clippy/tests/ui/needless_return.rs
@@ -461,3 +461,68 @@ pub unsafe fn issue_12157() -> *const i32 {
     return unsafe { todo() } as *const i32;
     //~^ needless_return
 }
+
+mod else_ifs {
+    fn test1(a: i32) -> u32 {
+        if a == 0 {
+            return 1;
+        //~^ needless_return
+        } else if a < 10 {
+            return 2;
+        //~^ needless_return
+        } else {
+            return 3;
+            //~^ needless_return
+        }
+    }
+
+    fn test2(a: i32) -> u32 {
+        if a == 0 {
+            return 1;
+        //~^ needless_return
+        } else if a < 10 {
+            2
+        } else {
+            return 3;
+            //~^ needless_return
+        }
+    }
+
+    fn test3(a: i32) -> u32 {
+        if a == 0 {
+            return 1;
+        //~^ needless_return
+        } else if a < 10 {
+            2
+        } else {
+            return 3;
+            //~^ needless_return
+        }
+    }
+
+    #[allow(clippy::match_single_binding, clippy::redundant_pattern)]
+    fn test4(a: i32) -> u32 {
+        if a == 0 {
+            return 1;
+            //~^ needless_return
+        } else if if if a > 0x1_1 {
+            return 2;
+        } else {
+            return 5;
+        } {
+            true
+        } else {
+            true
+        } {
+            0xDEADC0DE
+        } else if match a {
+            b @ _ => {
+                return 1;
+            },
+        } {
+            0xDEADBEEF
+        } else {
+            1
+        }
+    }
+}
diff --git a/src/tools/clippy/tests/ui/needless_return.stderr b/src/tools/clippy/tests/ui/needless_return.stderr
index 26dd265379b..206bd8ee5af 100644
--- a/src/tools/clippy/tests/ui/needless_return.stderr
+++ b/src/tools/clippy/tests/ui/needless_return.stderr
@@ -685,5 +685,101 @@ LL -     return unsafe { todo() } as *const i32;
 LL +     (unsafe { todo() } as *const i32)
    |
 
-error: aborting due to 55 previous errors
+error: unneeded `return` statement
+  --> tests/ui/needless_return.rs:468:13
+   |
+LL |             return 1;
+   |             ^^^^^^^^
+   |
+help: remove `return`
+   |
+LL -             return 1;
+LL +             1
+   |
+
+error: unneeded `return` statement
+  --> tests/ui/needless_return.rs:471:13
+   |
+LL |             return 2;
+   |             ^^^^^^^^
+   |
+help: remove `return`
+   |
+LL -             return 2;
+LL +             2
+   |
+
+error: unneeded `return` statement
+  --> tests/ui/needless_return.rs:474:13
+   |
+LL |             return 3;
+   |             ^^^^^^^^
+   |
+help: remove `return`
+   |
+LL -             return 3;
+LL +             3
+   |
+
+error: unneeded `return` statement
+  --> tests/ui/needless_return.rs:481:13
+   |
+LL |             return 1;
+   |             ^^^^^^^^
+   |
+help: remove `return`
+   |
+LL -             return 1;
+LL +             1
+   |
+
+error: unneeded `return` statement
+  --> tests/ui/needless_return.rs:486:13
+   |
+LL |             return 3;
+   |             ^^^^^^^^
+   |
+help: remove `return`
+   |
+LL -             return 3;
+LL +             3
+   |
+
+error: unneeded `return` statement
+  --> tests/ui/needless_return.rs:493:13
+   |
+LL |             return 1;
+   |             ^^^^^^^^
+   |
+help: remove `return`
+   |
+LL -             return 1;
+LL +             1
+   |
+
+error: unneeded `return` statement
+  --> tests/ui/needless_return.rs:498:13
+   |
+LL |             return 3;
+   |             ^^^^^^^^
+   |
+help: remove `return`
+   |
+LL -             return 3;
+LL +             3
+   |
+
+error: unneeded `return` statement
+  --> tests/ui/needless_return.rs:506:13
+   |
+LL |             return 1;
+   |             ^^^^^^^^
+   |
+help: remove `return`
+   |
+LL -             return 1;
+LL +             1
+   |
+
+error: aborting due to 63 previous errors
 
diff --git a/src/tools/clippy/tests/ui/skip_rustfmt/non_expressive_names_error_recovery.fixed b/src/tools/clippy/tests/ui/non_expressive_names_error_recovery.fixed
index c96a53ba2cd..c96a53ba2cd 100644
--- a/src/tools/clippy/tests/ui/skip_rustfmt/non_expressive_names_error_recovery.fixed
+++ b/src/tools/clippy/tests/ui/non_expressive_names_error_recovery.fixed
diff --git a/src/tools/clippy/tests/ui/skip_rustfmt/non_expressive_names_error_recovery.rs b/src/tools/clippy/tests/ui/non_expressive_names_error_recovery.rs
index a3a35eb26d1..a3a35eb26d1 100644
--- a/src/tools/clippy/tests/ui/skip_rustfmt/non_expressive_names_error_recovery.rs
+++ b/src/tools/clippy/tests/ui/non_expressive_names_error_recovery.rs
diff --git a/src/tools/clippy/tests/ui/skip_rustfmt/non_expressive_names_error_recovery.stderr b/src/tools/clippy/tests/ui/non_expressive_names_error_recovery.stderr
index 4998b9bd2cc..28d9a42a9a1 100644
--- a/src/tools/clippy/tests/ui/skip_rustfmt/non_expressive_names_error_recovery.stderr
+++ b/src/tools/clippy/tests/ui/non_expressive_names_error_recovery.stderr
@@ -1,5 +1,5 @@
 error: expected one of `!`, `(`, `+`, `,`, `::`, `<`, or `>`, found `)`
-  --> tests/ui/skip_rustfmt/non_expressive_names_error_recovery.rs:6:19
+  --> tests/ui/non_expressive_names_error_recovery.rs:6:19
    |
 LL | fn aa(a: Aa<String) {
    |                   ^ expected one of 7 possible tokens
diff --git a/src/tools/clippy/tests/ui/question_mark.fixed b/src/tools/clippy/tests/ui/question_mark.fixed
index 507bc2b29d8..60dc1c101b6 100644
--- a/src/tools/clippy/tests/ui/question_mark.fixed
+++ b/src/tools/clippy/tests/ui/question_mark.fixed
@@ -443,3 +443,13 @@ fn issue_14615(a: MutexGuard<Option<u32>>) -> Option<String> {
     //~^^^ question_mark
     Some(format!("{a}"))
 }
+
+fn const_in_pattern(x: Option<(i32, i32)>) -> Option<()> {
+    const N: i32 = 0;
+
+    let Some((x, N)) = x else {
+        return None;
+    };
+
+    None
+}
diff --git a/src/tools/clippy/tests/ui/question_mark.rs b/src/tools/clippy/tests/ui/question_mark.rs
index 64b51b849ed..99d0122a98f 100644
--- a/src/tools/clippy/tests/ui/question_mark.rs
+++ b/src/tools/clippy/tests/ui/question_mark.rs
@@ -539,3 +539,13 @@ fn issue_14615(a: MutexGuard<Option<u32>>) -> Option<String> {
     //~^^^ question_mark
     Some(format!("{a}"))
 }
+
+fn const_in_pattern(x: Option<(i32, i32)>) -> Option<()> {
+    const N: i32 = 0;
+
+    let Some((x, N)) = x else {
+        return None;
+    };
+
+    None
+}
diff --git a/src/tools/clippy/tests/ui/trivially_copy_pass_by_ref.fixed b/src/tools/clippy/tests/ui/trivially_copy_pass_by_ref.fixed
new file mode 100644
index 00000000000..af7d82130f0
--- /dev/null
+++ b/src/tools/clippy/tests/ui/trivially_copy_pass_by_ref.fixed
@@ -0,0 +1,179 @@
+//@normalize-stderr-test: "\(\d+ byte\)" -> "(N byte)"
+//@normalize-stderr-test: "\(limit: \d+ byte\)" -> "(limit: N byte)"
+#![deny(clippy::trivially_copy_pass_by_ref)]
+#![allow(
+    clippy::disallowed_names,
+    clippy::extra_unused_lifetimes,
+    clippy::needless_lifetimes,
+    clippy::needless_pass_by_ref_mut,
+    clippy::redundant_field_names,
+    clippy::uninlined_format_args
+)]
+
+#[derive(Copy, Clone)]
+struct Foo(u32);
+
+#[derive(Copy, Clone)]
+struct Bar([u8; 24]);
+
+#[derive(Copy, Clone)]
+pub struct Color {
+    pub r: u8,
+    pub g: u8,
+    pub b: u8,
+    pub a: u8,
+}
+
+struct FooRef<'a> {
+    foo: &'a Foo,
+}
+
+type Baz = u32;
+
+fn good(a: &mut u32, b: u32, c: &Bar) {}
+
+fn good_return_implicit_lt_ref(foo: &Foo) -> &u32 {
+    &foo.0
+}
+
+#[allow(clippy::needless_lifetimes)]
+fn good_return_explicit_lt_ref<'a>(foo: &'a Foo) -> &'a u32 {
+    &foo.0
+}
+
+fn good_return_implicit_lt_struct(foo: &Foo) -> FooRef {
+    FooRef { foo }
+}
+
+#[allow(clippy::needless_lifetimes)]
+fn good_return_explicit_lt_struct<'a>(foo: &'a Foo) -> FooRef<'a> {
+    FooRef { foo }
+}
+
+fn bad(x: u32, y: Foo, z: Baz) {}
+//~^ ERROR: this argument (4 byte) is passed by reference, but would be more efficient if passed by
+//~| ERROR: this argument (4 byte) is passed by reference, but would be more efficient if passed by
+//~| ERROR: this argument (4 byte) is passed by reference, but would be more efficient if passed by
+
+impl Foo {
+    fn good(self, a: &mut u32, b: u32, c: &Bar) {}
+
+    fn good2(&mut self) {}
+
+    fn bad(self, x: u32, y: Foo, z: Baz) {}
+    //~^ ERROR: this argument (4 byte) is passed by reference, but would be more efficient if passed by
+    //~| ERROR: this argument (4 byte) is passed by reference, but would be more efficient if passed by
+    //~| ERROR: this argument (4 byte) is passed by reference, but would be more efficient if passed by
+    //~| ERROR: this argument (4 byte) is passed by reference, but would be more efficient if passed by
+
+    fn bad2(x: u32, y: Foo, z: Baz) {}
+    //~^ ERROR: this argument (4 byte) is passed by reference, but would be more efficient if passed by
+    //~| ERROR: this argument (4 byte) is passed by reference, but would be more efficient if passed by
+    //~| ERROR: this argument (4 byte) is passed by reference, but would be more efficient if passed by
+
+    fn bad_issue7518(self, other: Self) {}
+    //~^ ERROR: this argument (4 byte) is passed by reference, but would be more efficient if
+}
+
+impl AsRef<u32> for Foo {
+    fn as_ref(&self) -> &u32 {
+        &self.0
+    }
+}
+
+impl Bar {
+    fn good(&self, a: &mut u32, b: u32, c: &Bar) {}
+
+    fn bad2(x: u32, y: Foo, z: Baz) {}
+    //~^ ERROR: this argument (4 byte) is passed by reference, but would be more efficient if
+    //~| ERROR: this argument (4 byte) is passed by reference, but would be more efficient if
+    //~| ERROR: this argument (4 byte) is passed by reference, but would be more efficient if
+}
+
+trait MyTrait {
+    fn trait_method(&self, foo: Foo);
+    //~^ ERROR: this argument (4 byte) is passed by reference, but would be more efficient if
+}
+
+pub trait MyTrait2 {
+    fn trait_method2(&self, color: &Color);
+}
+
+trait MyTrait3 {
+    #[expect(clippy::trivially_copy_pass_by_ref)]
+    fn trait_method(&self, foo: &Foo);
+}
+
+// Trait impls should not warn
+impl MyTrait3 for Foo {
+    fn trait_method(&self, foo: &Foo) {
+        unimplemented!()
+    }
+}
+
+mod issue3992 {
+    pub trait A {
+        #[allow(clippy::trivially_copy_pass_by_ref)]
+        fn a(b: &u16) {}
+    }
+
+    #[allow(clippy::trivially_copy_pass_by_ref)]
+    pub fn c(d: &u16) {}
+}
+
+mod issue5876 {
+    // Don't lint here as it is always inlined
+    #[inline(always)]
+    fn foo_always(x: &i32) {
+        println!("{}", x);
+    }
+
+    #[inline(never)]
+    fn foo_never(x: i32) {
+        //~^ ERROR: this argument (4 byte) is passed by reference, but would be more efficient if passed by
+        println!("{}", x);
+    }
+
+    #[inline]
+    fn foo(x: i32) {
+        //~^ ERROR: this argument (4 byte) is passed by reference, but would be more efficient if passed by
+        println!("{}", x);
+    }
+}
+
+fn ref_to_opt_ref_implicit(x: &u32) -> Option<&u32> {
+    Some(x)
+}
+
+fn ref_to_opt_ref_explicit<'a>(x: &'a u32) -> Option<&'a u32> {
+    Some(x)
+}
+
+fn with_constraint<'a, 'b: 'a>(x: &'b u32, y: &'a u32) -> &'a u32 {
+    if true { x } else { y }
+}
+
+async fn async_implicit(x: &u32) -> &u32 {
+    x
+}
+
+async fn async_explicit<'a>(x: &'a u32) -> &'a u32 {
+    x
+}
+
+fn unrelated_lifetimes<'a, 'b>(_x: u32, y: &'b u32) -> &'b u32 {
+    //~^ ERROR: this argument (4 byte) is passed by reference, but would be more efficient if passed by
+    y
+}
+
+fn return_ptr(x: &u32) -> *const u32 {
+    x
+}
+
+fn return_field_ptr(x: &(u32, u32)) -> *const u32 {
+    &x.0
+}
+
+fn return_field_ptr_addr_of(x: &(u32, u32)) -> *const u32 {
+    core::ptr::addr_of!(x.0)
+}
diff --git a/src/tools/clippy/tests/ui/trivially_copy_pass_by_ref.rs b/src/tools/clippy/tests/ui/trivially_copy_pass_by_ref.rs
index 37bc6f89a20..00e11a1ea28 100644
--- a/src/tools/clippy/tests/ui/trivially_copy_pass_by_ref.rs
+++ b/src/tools/clippy/tests/ui/trivially_copy_pass_by_ref.rs
@@ -1,14 +1,15 @@
 //@normalize-stderr-test: "\(\d+ byte\)" -> "(N byte)"
-//@normalize-stderr-test: "\(limit: \d+ byte\)" -> "(limit: 8 byte)"
+//@normalize-stderr-test: "\(limit: \d+ byte\)" -> "(limit: N byte)"
 #![deny(clippy::trivially_copy_pass_by_ref)]
 #![allow(
     clippy::disallowed_names,
+    clippy::extra_unused_lifetimes,
     clippy::needless_lifetimes,
+    clippy::needless_pass_by_ref_mut,
     clippy::redundant_field_names,
-    clippy::uninlined_format_args,
-    clippy::needless_pass_by_ref_mut
+    clippy::uninlined_format_args
 )]
-//@no-rustfix
+
 #[derive(Copy, Clone)]
 struct Foo(u32);
 
@@ -90,21 +91,26 @@ impl Bar {
 }
 
 trait MyTrait {
-    fn trait_method(&self, _foo: &Foo);
+    fn trait_method(&self, foo: &Foo);
     //~^ ERROR: this argument (4 byte) is passed by reference, but would be more efficient if
 }
 
 pub trait MyTrait2 {
-    fn trait_method2(&self, _color: &Color);
+    fn trait_method2(&self, color: &Color);
+}
+
+trait MyTrait3 {
+    #[expect(clippy::trivially_copy_pass_by_ref)]
+    fn trait_method(&self, foo: &Foo);
 }
 
-impl MyTrait for Foo {
-    fn trait_method(&self, _foo: &Foo) {
+// Trait impls should not warn
+impl MyTrait3 for Foo {
+    fn trait_method(&self, foo: &Foo) {
         unimplemented!()
     }
 }
 
-#[allow(unused_variables)]
 mod issue3992 {
     pub trait A {
         #[allow(clippy::trivially_copy_pass_by_ref)]
@@ -135,57 +141,39 @@ mod issue5876 {
     }
 }
 
-fn _ref_to_opt_ref_implicit(x: &u32) -> Option<&u32> {
+fn ref_to_opt_ref_implicit(x: &u32) -> Option<&u32> {
     Some(x)
 }
 
-#[allow(clippy::needless_lifetimes)]
-fn _ref_to_opt_ref_explicit<'a>(x: &'a u32) -> Option<&'a u32> {
+fn ref_to_opt_ref_explicit<'a>(x: &'a u32) -> Option<&'a u32> {
     Some(x)
 }
 
-fn _with_constraint<'a, 'b: 'a>(x: &'b u32, y: &'a u32) -> &'a u32 {
+fn with_constraint<'a, 'b: 'a>(x: &'b u32, y: &'a u32) -> &'a u32 {
     if true { x } else { y }
 }
 
-async fn _async_implicit(x: &u32) -> &u32 {
+async fn async_implicit(x: &u32) -> &u32 {
     x
 }
 
-#[allow(clippy::needless_lifetimes)]
-async fn _async_explicit<'a>(x: &'a u32) -> &'a u32 {
+async fn async_explicit<'a>(x: &'a u32) -> &'a u32 {
     x
 }
 
-fn _unrelated_lifetimes<'a, 'b>(_x: &'a u32, y: &'b u32) -> &'b u32 {
+fn unrelated_lifetimes<'a, 'b>(_x: &'a u32, y: &'b u32) -> &'b u32 {
     //~^ ERROR: this argument (4 byte) is passed by reference, but would be more efficient if passed by
     y
 }
 
-fn _return_ptr(x: &u32) -> *const u32 {
+fn return_ptr(x: &u32) -> *const u32 {
     x
 }
 
-fn _return_field_ptr(x: &(u32, u32)) -> *const u32 {
+fn return_field_ptr(x: &(u32, u32)) -> *const u32 {
     &x.0
 }
 
-fn _return_field_ptr_addr_of(x: &(u32, u32)) -> *const u32 {
+fn return_field_ptr_addr_of(x: &(u32, u32)) -> *const u32 {
     core::ptr::addr_of!(x.0)
 }
-
-fn main() {
-    let (mut foo, bar) = (Foo(0), Bar([0; 24]));
-    let (mut a, b, c, x, y, z) = (0, 0, Bar([0; 24]), 0, Foo(0), 0);
-    good(&mut a, b, &c);
-    good_return_implicit_lt_ref(&y);
-    good_return_explicit_lt_ref(&y);
-    bad(&x, &y, &z);
-    foo.good(&mut a, b, &c);
-    foo.good2();
-    foo.bad(&x, &y, &z);
-    Foo::bad2(&x, &y, &z);
-    bar.good(&mut a, b, &c);
-    Bar::bad2(&x, &y, &z);
-    foo.as_ref();
-}
diff --git a/src/tools/clippy/tests/ui/trivially_copy_pass_by_ref.stderr b/src/tools/clippy/tests/ui/trivially_copy_pass_by_ref.stderr
index e813fecf653..f101ac5ccd6 100644
--- a/src/tools/clippy/tests/ui/trivially_copy_pass_by_ref.stderr
+++ b/src/tools/clippy/tests/ui/trivially_copy_pass_by_ref.stderr
@@ -1,5 +1,5 @@
-error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: 8 byte)
-  --> tests/ui/trivially_copy_pass_by_ref.rs:52:11
+error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte)
+  --> tests/ui/trivially_copy_pass_by_ref.rs:53:11
    |
 LL | fn bad(x: &u32, y: &Foo, z: &Baz) {}
    |           ^^^^ help: consider passing by value instead: `u32`
@@ -10,107 +10,107 @@ note: the lint level is defined here
 LL | #![deny(clippy::trivially_copy_pass_by_ref)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: 8 byte)
-  --> tests/ui/trivially_copy_pass_by_ref.rs:52:20
+error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte)
+  --> tests/ui/trivially_copy_pass_by_ref.rs:53:20
    |
 LL | fn bad(x: &u32, y: &Foo, z: &Baz) {}
    |                    ^^^^ help: consider passing by value instead: `Foo`
 
-error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: 8 byte)
-  --> tests/ui/trivially_copy_pass_by_ref.rs:52:29
+error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte)
+  --> tests/ui/trivially_copy_pass_by_ref.rs:53:29
    |
 LL | fn bad(x: &u32, y: &Foo, z: &Baz) {}
    |                             ^^^^ help: consider passing by value instead: `Baz`
 
-error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: 8 byte)
-  --> tests/ui/trivially_copy_pass_by_ref.rs:62:12
+error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte)
+  --> tests/ui/trivially_copy_pass_by_ref.rs:63:12
    |
 LL |     fn bad(&self, x: &u32, y: &Foo, z: &Baz) {}
    |            ^^^^^ help: consider passing by value instead: `self`
 
-error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: 8 byte)
-  --> tests/ui/trivially_copy_pass_by_ref.rs:62:22
+error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte)
+  --> tests/ui/trivially_copy_pass_by_ref.rs:63:22
    |
 LL |     fn bad(&self, x: &u32, y: &Foo, z: &Baz) {}
    |                      ^^^^ help: consider passing by value instead: `u32`
 
-error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: 8 byte)
-  --> tests/ui/trivially_copy_pass_by_ref.rs:62:31
+error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte)
+  --> tests/ui/trivially_copy_pass_by_ref.rs:63:31
    |
 LL |     fn bad(&self, x: &u32, y: &Foo, z: &Baz) {}
    |                               ^^^^ help: consider passing by value instead: `Foo`
 
-error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: 8 byte)
-  --> tests/ui/trivially_copy_pass_by_ref.rs:62:40
+error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte)
+  --> tests/ui/trivially_copy_pass_by_ref.rs:63:40
    |
 LL |     fn bad(&self, x: &u32, y: &Foo, z: &Baz) {}
    |                                        ^^^^ help: consider passing by value instead: `Baz`
 
-error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: 8 byte)
-  --> tests/ui/trivially_copy_pass_by_ref.rs:68:16
+error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte)
+  --> tests/ui/trivially_copy_pass_by_ref.rs:69:16
    |
 LL |     fn bad2(x: &u32, y: &Foo, z: &Baz) {}
    |                ^^^^ help: consider passing by value instead: `u32`
 
-error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: 8 byte)
-  --> tests/ui/trivially_copy_pass_by_ref.rs:68:25
+error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte)
+  --> tests/ui/trivially_copy_pass_by_ref.rs:69:25
    |
 LL |     fn bad2(x: &u32, y: &Foo, z: &Baz) {}
    |                         ^^^^ help: consider passing by value instead: `Foo`
 
-error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: 8 byte)
-  --> tests/ui/trivially_copy_pass_by_ref.rs:68:34
+error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte)
+  --> tests/ui/trivially_copy_pass_by_ref.rs:69:34
    |
 LL |     fn bad2(x: &u32, y: &Foo, z: &Baz) {}
    |                                  ^^^^ help: consider passing by value instead: `Baz`
 
-error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: 8 byte)
-  --> tests/ui/trivially_copy_pass_by_ref.rs:73:35
+error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte)
+  --> tests/ui/trivially_copy_pass_by_ref.rs:74:35
    |
 LL |     fn bad_issue7518(self, other: &Self) {}
    |                                   ^^^^^ help: consider passing by value instead: `Self`
 
-error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: 8 byte)
-  --> tests/ui/trivially_copy_pass_by_ref.rs:86:16
+error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte)
+  --> tests/ui/trivially_copy_pass_by_ref.rs:87:16
    |
 LL |     fn bad2(x: &u32, y: &Foo, z: &Baz) {}
    |                ^^^^ help: consider passing by value instead: `u32`
 
-error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: 8 byte)
-  --> tests/ui/trivially_copy_pass_by_ref.rs:86:25
+error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte)
+  --> tests/ui/trivially_copy_pass_by_ref.rs:87:25
    |
 LL |     fn bad2(x: &u32, y: &Foo, z: &Baz) {}
    |                         ^^^^ help: consider passing by value instead: `Foo`
 
-error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: 8 byte)
-  --> tests/ui/trivially_copy_pass_by_ref.rs:86:34
+error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte)
+  --> tests/ui/trivially_copy_pass_by_ref.rs:87:34
    |
 LL |     fn bad2(x: &u32, y: &Foo, z: &Baz) {}
    |                                  ^^^^ help: consider passing by value instead: `Baz`
 
-error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: 8 byte)
-  --> tests/ui/trivially_copy_pass_by_ref.rs:93:34
+error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte)
+  --> tests/ui/trivially_copy_pass_by_ref.rs:94:33
    |
-LL |     fn trait_method(&self, _foo: &Foo);
-   |                                  ^^^^ help: consider passing by value instead: `Foo`
+LL |     fn trait_method(&self, foo: &Foo);
+   |                                 ^^^^ help: consider passing by value instead: `Foo`
 
-error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: 8 byte)
-  --> tests/ui/trivially_copy_pass_by_ref.rs:126:21
+error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte)
+  --> tests/ui/trivially_copy_pass_by_ref.rs:132:21
    |
 LL |     fn foo_never(x: &i32) {
    |                     ^^^^ help: consider passing by value instead: `i32`
 
-error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: 8 byte)
-  --> tests/ui/trivially_copy_pass_by_ref.rs:132:15
+error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte)
+  --> tests/ui/trivially_copy_pass_by_ref.rs:138:15
    |
 LL |     fn foo(x: &i32) {
    |               ^^^^ help: consider passing by value instead: `i32`
 
-error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: 8 byte)
-  --> tests/ui/trivially_copy_pass_by_ref.rs:160:37
+error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte)
+  --> tests/ui/trivially_copy_pass_by_ref.rs:164:36
    |
-LL | fn _unrelated_lifetimes<'a, 'b>(_x: &'a u32, y: &'b u32) -> &'b u32 {
-   |                                     ^^^^^^^ help: consider passing by value instead: `u32`
+LL | fn unrelated_lifetimes<'a, 'b>(_x: &'a u32, y: &'b u32) -> &'b u32 {
+   |                                    ^^^^^^^ help: consider passing by value instead: `u32`
 
 error: aborting due to 18 previous errors
 
diff --git a/src/tools/clippy/tests/ui/while_let_loop.rs b/src/tools/clippy/tests/ui/while_let_loop.rs
index d591ab984cf..95062c9f46c 100644
--- a/src/tools/clippy/tests/ui/while_let_loop.rs
+++ b/src/tools/clippy/tests/ui/while_let_loop.rs
@@ -154,3 +154,89 @@ fn issue_5715(mut m: core::cell::RefCell<Option<u32>>) {
         m = core::cell::RefCell::new(Some(x + 1));
     }
 }
+
+mod issue_362 {
+    pub fn merge_sorted<T>(xs: Vec<T>, ys: Vec<T>) -> Vec<T>
+    where
+        T: PartialOrd,
+    {
+        let total_len = xs.len() + ys.len();
+        let mut res = Vec::with_capacity(total_len);
+        let mut ix = xs.into_iter().peekable();
+        let mut iy = ys.into_iter().peekable();
+        loop {
+            //~^ while_let_loop
+            let lt = match (ix.peek(), iy.peek()) {
+                (Some(x), Some(y)) => x < y,
+                _ => break,
+            };
+            res.push(if lt { &mut ix } else { &mut iy }.next().unwrap());
+        }
+        res.extend(ix);
+        res.extend(iy);
+        res
+    }
+}
+
+fn let_assign() {
+    loop {
+        //~^ while_let_loop
+        let x = if let Some(y) = Some(3) {
+            y
+        } else {
+            break;
+        };
+        if x == 3 {
+            break;
+        }
+    }
+
+    loop {
+        //~^ while_let_loop
+        let x: u32 = if let Some(y) = Some(3) {
+            y
+        } else {
+            break;
+        };
+        if x == 3 {
+            break;
+        }
+    }
+
+    loop {
+        //~^ while_let_loop
+        let x = if let Some(x) = Some(3) {
+            x
+        } else {
+            break;
+        };
+        if x == 3 {
+            break;
+        }
+    }
+
+    loop {
+        //~^ while_let_loop
+        let x: u32 = if let Some(x) = Some(3) {
+            x
+        } else {
+            break;
+        };
+        if x == 3 {
+            break;
+        }
+    }
+
+    loop {
+        //~^ while_let_loop
+        let x = if let Some(x) = Some(2) {
+            let t = 1;
+            t + x
+        } else {
+            break;
+        };
+        if x == 3 {
+            break;
+        }
+    }
+}
diff --git a/src/tools/clippy/tests/ui/while_let_loop.stderr b/src/tools/clippy/tests/ui/while_let_loop.stderr
index bd482857e67..ed42628a53e 100644
--- a/src/tools/clippy/tests/ui/while_let_loop.stderr
+++ b/src/tools/clippy/tests/ui/while_let_loop.stderr
@@ -57,7 +57,125 @@ LL | |         let (e, l) = match "".split_whitespace().next() {
 ...  |
 LL | |         let _ = (e, l);
 LL | |     }
-   | |_____^ help: try: `while let Some(word) = "".split_whitespace().next() { .. }`
+   | |_____^
+   |
+help: try
+   |
+LL ~     while let Some(word) = "".split_whitespace().next() {
+LL +         let (e, l) = (word.is_empty(), word.len());
+LL +         ..
+LL +     }
+   |
+
+error: this loop could be written as a `while let` loop
+  --> tests/ui/while_let_loop.rs:167:9
+   |
+LL | /         loop {
+LL | |
+LL | |             let lt = match (ix.peek(), iy.peek()) {
+LL | |                 (Some(x), Some(y)) => x < y,
+...  |
+LL | |             res.push(if lt { &mut ix } else { &mut iy }.next().unwrap());
+LL | |         }
+   | |_________^
+   |
+help: try
+   |
+LL ~         while let (Some(x), Some(y)) = (ix.peek(), iy.peek()) {
+LL +             let lt = x < y;
+LL +             ..
+LL +         }
+   |
+
+error: this loop could be written as a `while let` loop
+  --> tests/ui/while_let_loop.rs:182:5
+   |
+LL | /     loop {
+LL | |
+LL | |         let x = if let Some(y) = Some(3) {
+LL | |             y
+...  |
+LL | |     }
+   | |_____^
+   |
+help: try
+   |
+LL ~     while let Some(y) = Some(3) {
+LL +         let x = y;
+LL +         ..
+LL +     }
+   |
+
+error: this loop could be written as a `while let` loop
+  --> tests/ui/while_let_loop.rs:194:5
+   |
+LL | /     loop {
+LL | |
+LL | |         let x: u32 = if let Some(y) = Some(3) {
+LL | |             y
+...  |
+LL | |     }
+   | |_____^
+   |
+help: try
+   |
+LL ~     while let Some(y) = Some(3) {
+LL +         let x: u32 = y;
+LL +         ..
+LL +     }
+   |
+
+error: this loop could be written as a `while let` loop
+  --> tests/ui/while_let_loop.rs:206:5
+   |
+LL | /     loop {
+LL | |
+LL | |         let x = if let Some(x) = Some(3) {
+LL | |             x
+...  |
+LL | |     }
+   | |_____^ help: try: `while let Some(x) = Some(3) { .. }`
+
+error: this loop could be written as a `while let` loop
+  --> tests/ui/while_let_loop.rs:218:5
+   |
+LL | /     loop {
+LL | |
+LL | |         let x: u32 = if let Some(x) = Some(3) {
+LL | |             x
+...  |
+LL | |     }
+   | |_____^
+   |
+help: try
+   |
+LL ~     while let Some(x) = Some(3) {
+LL +         let x: u32 = x;
+LL +         ..
+LL +     }
+   |
+
+error: this loop could be written as a `while let` loop
+  --> tests/ui/while_let_loop.rs:230:5
+   |
+LL | /     loop {
+LL | |
+LL | |         let x = if let Some(x) = Some(2) {
+LL | |             let t = 1;
+...  |
+LL | |     }
+   | |_____^
+   |
+help: try
+   |
+LL ~     while let Some(x) = Some(2) {
+LL +         let x = {
+LL +             let t = 1;
+LL +             t + x
+LL +         };
+LL +         ..
+LL +     }
+   |
 
-error: aborting due to 5 previous errors
+error: aborting due to 11 previous errors
 
diff --git a/src/tools/clippy/triagebot.toml b/src/tools/clippy/triagebot.toml
index 389f22c6a2c..16557a4bebb 100644
--- a/src/tools/clippy/triagebot.toml
+++ b/src/tools/clippy/triagebot.toml
@@ -45,6 +45,7 @@ contributing_url = "https://github.com/rust-lang/rust-clippy/blob/master/CONTRIB
 users_on_vacation = [
     "matthiaskrgr",
     "Manishearth",
+    "blyxyas",
 ]
 
 [assign.owners]
diff --git a/src/tools/clippy/util/gh-pages/index_template.html b/src/tools/clippy/util/gh-pages/index_template.html
index 19dc1ec0b0c..865b9523c39 100644
--- a/src/tools/clippy/util/gh-pages/index_template.html
+++ b/src/tools/clippy/util/gh-pages/index_template.html
@@ -50,7 +50,7 @@ Otherwise, have a great day =^.^=
 
     <div class="container"> {# #}
         <div class="page-header"> {# #}
-            <h1>Clippy Lints</h1> {# #}
+            <h1>Clippy Lints <span id="lint-count" class="badge"></span></h1> {# #}
         </div> {# #}
 
         <noscript> {# #}
diff --git a/src/tools/clippy/util/gh-pages/script.js b/src/tools/clippy/util/gh-pages/script.js
index c942a6a05a1..fec883938d6 100644
--- a/src/tools/clippy/util/gh-pages/script.js
+++ b/src/tools/clippy/util/gh-pages/script.js
@@ -71,6 +71,7 @@ window.searchState = {
         } else {
             window.location.hash = '';
         }
+        updateLintCount();
     },
 };
 
@@ -598,3 +599,14 @@ generateSearch();
 parseURLFilters();
 scrollToLintByURL();
 filters.filterLints();
+updateLintCount();
+
+function updateLintCount() {
+    const allLints = filters.getAllLints();
+    const totalLints = allLints.length;
+    
+    const countElement = document.getElementById("lint-count");
+    if (countElement) {
+        countElement.innerText = `Total number: ${totalLints}`;
+    }
+}
diff --git a/src/tools/generate-copyright/src/cargo_metadata.rs b/src/tools/generate-copyright/src/cargo_metadata.rs
index b717bd53eb1..3fae26bda47 100644
--- a/src/tools/generate-copyright/src/cargo_metadata.rs
+++ b/src/tools/generate-copyright/src/cargo_metadata.rs
@@ -46,11 +46,12 @@ pub struct PackageMetadata {
 /// covered it already.
 pub fn get_metadata_and_notices(
     cargo: &Path,
+    cargo_home_path: &Path,
     vendor_path: &Path,
     root_path: &Path,
     manifest_paths: &[PathBuf],
 ) -> Result<BTreeMap<Package, PackageMetadata>, Error> {
-    let mut output = get_metadata(cargo, root_path, manifest_paths)?;
+    let mut output = get_metadata(cargo, cargo_home_path, root_path, manifest_paths)?;
 
     // Now for each dependency we found, go and grab any important looking files
     for (package, metadata) in output.iter_mut() {
@@ -66,6 +67,7 @@ pub fn get_metadata_and_notices(
 /// assume `reuse` has covered it already.
 pub fn get_metadata(
     cargo: &Path,
+    cargo_home_path: &Path,
     root_path: &Path,
     manifest_paths: &[PathBuf],
 ) -> Result<BTreeMap<Package, PackageMetadata>, Error> {
@@ -81,8 +83,11 @@ pub fn get_metadata(
             .manifest_path(manifest_path)
             .exec()?;
         for package in metadata.packages {
-            let manifest_path = package.manifest_path.as_path();
-            if manifest_path.starts_with(root_path) {
+            let package_manifest_path = package.manifest_path.as_path();
+
+            if package_manifest_path.starts_with(root_path)
+                && !package_manifest_path.starts_with(cargo_home_path)
+            {
                 // it's an in-tree dependency and reuse covers it
                 continue;
             }
diff --git a/src/tools/generate-copyright/src/main.rs b/src/tools/generate-copyright/src/main.rs
index d6ed7261b7c..5497db1f5f3 100644
--- a/src/tools/generate-copyright/src/main.rs
+++ b/src/tools/generate-copyright/src/main.rs
@@ -15,6 +15,7 @@ mod cargo_metadata;
 ///
 /// Run `x.py run generate-copyright`
 fn main() -> Result<(), Error> {
+    let cargo_home = env_path("CARGO_HOME")?;
     let dest_file = env_path("DEST")?;
     let libstd_dest_file = env_path("DEST_LIBSTD")?;
     let src_dir = env_path("SRC_DIR")?;
@@ -39,11 +40,17 @@ fn main() -> Result<(), Error> {
         .collect::<Vec<_>>();
 
     // Scan Cargo dependencies
-    let mut collected_cargo_metadata =
-        cargo_metadata::get_metadata_and_notices(&cargo, &vendor_dir, &src_dir, &cargo_manifests)?;
+    let mut collected_cargo_metadata = cargo_metadata::get_metadata_and_notices(
+        &cargo,
+        &cargo_home,
+        &vendor_dir,
+        &src_dir,
+        &cargo_manifests,
+    )?;
 
     let library_collected_cargo_metadata = cargo_metadata::get_metadata_and_notices(
         &cargo,
+        &cargo_home,
         &vendor_dir,
         &src_dir,
         &library_manifests,
diff --git a/src/tools/lint-docs/Cargo.toml b/src/tools/lint-docs/Cargo.toml
index 3578bda8276..f1ffda75ac0 100644
--- a/src/tools/lint-docs/Cargo.toml
+++ b/src/tools/lint-docs/Cargo.toml
@@ -7,6 +7,7 @@ description = "A script to extract the lint documentation for the rustc book."
 # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
 
 [dependencies]
+rustc-literal-escaper = "0.0.2"
 serde_json = "1.0.57"
 tempfile = "3.1.0"
 walkdir = "2.3.1"
diff --git a/src/tools/lint-docs/src/lib.rs b/src/tools/lint-docs/src/lib.rs
index cacce01675f..6bb18c2bced 100644
--- a/src/tools/lint-docs/src/lib.rs
+++ b/src/tools/lint-docs/src/lib.rs
@@ -4,6 +4,7 @@ use std::fs;
 use std::path::{Path, PathBuf};
 use std::process::Command;
 
+use rustc_literal_escaper::{Mode, unescape_unicode};
 use walkdir::WalkDir;
 
 mod groups;
@@ -214,6 +215,16 @@ impl<'a> LintExtractor<'a> {
                         let line = line.trim();
                         if let Some(text) = line.strip_prefix("/// ") {
                             doc_lines.push(text.to_string());
+                        } else if let Some(text) = line.strip_prefix("#[doc = \"") {
+                            let escaped = text.strip_suffix("\"]").unwrap();
+                            let mut buf = String::new();
+                            unescape_unicode(escaped, Mode::Str, &mut |_, c| match c {
+                                Ok(c) => buf.push(c),
+                                Err(err) => {
+                                    assert!(!err.is_fatal(), "failed to unescape string literal")
+                                }
+                            });
+                            doc_lines.push(buf);
                         } else if line == "///" {
                             doc_lines.push("".to_string());
                         } else if line.starts_with("// ") {
diff --git a/src/tools/miri/cargo-miri/src/phases.rs b/src/tools/miri/cargo-miri/src/phases.rs
index 4857f62cd3a..a5e019a8ea9 100644
--- a/src/tools/miri/cargo-miri/src/phases.rs
+++ b/src/tools/miri/cargo-miri/src/phases.rs
@@ -90,7 +90,7 @@ pub fn phase_cargo_miri(mut args: impl Iterator<Item = String>) {
                 "`cargo miri` supports the following subcommands: `run`, `test`, `nextest`, `clean`, and `setup`."
             ),
     };
-    let verbose = num_arg_flag("-v");
+    let verbose = num_arg_flag("-v") + num_arg_flag("--verbose");
     let quiet = has_arg_flag("-q") || has_arg_flag("--quiet");
 
     // Determine the involved architectures.
diff --git a/src/tools/miri/ci/ci.sh b/src/tools/miri/ci/ci.sh
index 9ae15739dcb..8941af681a4 100755
--- a/src/tools/miri/ci/ci.sh
+++ b/src/tools/miri/ci/ci.sh
@@ -142,12 +142,12 @@ case $HOST_TARGET in
     # Host
     GC_STRESS=1 MIR_OPT=1 MANY_SEEDS=64 TEST_BENCH=1 CARGO_MIRI_ENV=1 run_tests
     # Extra tier 1
-    # With reduced many-seed count to avoid spending too much time on that.
-    # (All OSes and ABIs are run with 64 seeds at least once though via the macOS runner.)
-    MANY_SEEDS=16 TEST_TARGET=i686-unknown-linux-gnu run_tests
-    MANY_SEEDS=16 TEST_TARGET=aarch64-unknown-linux-gnu run_tests
-    MANY_SEEDS=16 TEST_TARGET=x86_64-apple-darwin run_tests
-    MANY_SEEDS=16 TEST_TARGET=x86_64-pc-windows-gnu run_tests
+    MANY_SEEDS=64 TEST_TARGET=i686-unknown-linux-gnu run_tests
+    MANY_SEEDS=64 TEST_TARGET=aarch64-unknown-linux-gnu run_tests
+    MANY_SEEDS=64 TEST_TARGET=x86_64-apple-darwin run_tests
+    MANY_SEEDS=64 TEST_TARGET=x86_64-pc-windows-gnu run_tests
+    # Extra tier 1 candidate
+    MANY_SEEDS=64 TEST_TARGET=aarch64-pc-windows-msvc run_tests
     ;;
   aarch64-apple-darwin)
     # Host
@@ -156,7 +156,8 @@ case $HOST_TARGET in
     MANY_SEEDS=64 TEST_TARGET=i686-pc-windows-gnu run_tests
     MANY_SEEDS=64 TEST_TARGET=x86_64-pc-windows-msvc CARGO_MIRI_ENV=1 run_tests
     # Extra tier 2
-    MANY_SEEDS=16 TEST_TARGET=arm-unknown-linux-gnueabi run_tests
+    MANY_SEEDS=16 TEST_TARGET=arm-unknown-linux-gnueabi run_tests # 32bit ARM
+    MANY_SEEDS=16 TEST_TARGET=aarch64-pc-windows-gnullvm run_tests # gnullvm ABI
     MANY_SEEDS=16 TEST_TARGET=s390x-unknown-linux-gnu run_tests # big-endian architecture of choice
     # Not officially supported tier 2
     MANY_SEEDS=16 TEST_TARGET=mips-unknown-linux-gnu run_tests # a 32bit big-endian target, and also a target without 64bit atomics
@@ -178,7 +179,7 @@ case $HOST_TARGET in
     # Host
     # Without GC_STRESS and with reduced many-seeds count as this is the slowest runner.
     # (The macOS runner checks windows-msvc with full many-seeds count.)
-    MIR_OPT=1 MANY_SEEDS=16 TEST_BENCH=1 run_tests
+    MIR_OPT=1 MANY_SEEDS=64 TEST_BENCH=1 run_tests
     # Extra tier 1
     # We really want to ensure a Linux target works on a Windows host,
     # and a 64bit target works on a 32bit host.
diff --git a/src/tools/miri/miri-script/src/commands.rs b/src/tools/miri/miri-script/src/commands.rs
index 3b7b159aeab..86362145d47 100644
--- a/src/tools/miri/miri-script/src/commands.rs
+++ b/src/tools/miri/miri-script/src/commands.rs
@@ -1,4 +1,4 @@
-use std::collections::HashMap;
+use std::collections::BTreeMap;
 use std::ffi::{OsStr, OsString};
 use std::fmt::Write as _;
 use std::fs::{self, File};
@@ -404,7 +404,28 @@ impl Command {
         // We want to forward the host stdin so apparently we cannot use `cmd!`.
         let mut cmd = process::Command::new("git");
         cmd.arg("rebase").arg(&base).arg("--interactive");
-        cmd.env("GIT_SEQUENCE_EDITOR", env::current_exe()?);
+        let current_exe = {
+            if cfg!(windows) {
+                // Apparently git-for-Windows gets confused by backslashes if we just use
+                // `current_exe()` here. So replace them by forward slashes if this is not a "magic"
+                // path starting with "\\". This is clearly a git bug but we work around it here.
+                // Also see <https://github.com/rust-lang/miri/issues/4340>.
+                let bin = env::current_exe()?;
+                match bin.into_os_string().into_string() {
+                    Err(not_utf8) => not_utf8.into(), // :shrug:
+                    Ok(str) => {
+                        if str.starts_with(r"\\") {
+                            str.into() // don't touch these magic paths, they must use backslashes
+                        } else {
+                            str.replace('\\', "/").into()
+                        }
+                    }
+                }
+            } else {
+                env::current_exe()?
+            }
+        };
+        cmd.env("GIT_SEQUENCE_EDITOR", current_exe);
         cmd.env("MIRI_SCRIPT_IS_GIT_SEQUENCE_EDITOR", "1");
         cmd.current_dir(sh.current_dir());
         let result = cmd.status()?;
@@ -489,7 +510,9 @@ impl Command {
             sh.read_dir(benches_dir)?
                 .into_iter()
                 .filter(|path| path.is_dir())
-                .map(|path| path.into_os_string().into_string().unwrap())
+                // Only keep the basename: that matches the usage with a manual bench list,
+                // and it ensure the path concatenations below work as intended.
+                .map(|path| path.file_name().unwrap().to_owned().into_string().unwrap())
                 .collect()
         } else {
             benches.into_iter().collect()
@@ -530,14 +553,16 @@ impl Command {
             stddev: f64,
         }
 
-        let gather_results = || -> Result<HashMap<&str, BenchResult>> {
+        let gather_results = || -> Result<BTreeMap<&str, BenchResult>> {
             let baseline_temp_dir = results_json_dir.unwrap();
-            let mut results = HashMap::new();
+            let mut results = BTreeMap::new();
             for bench in &benches {
-                let result = File::open(path!(baseline_temp_dir / format!("{bench}.bench.json")))?;
-                let mut result: serde_json::Value =
-                    serde_json::from_reader(BufReader::new(result))?;
-                let result: BenchResult = serde_json::from_value(result["results"][0].take())?;
+                let result = File::open(path!(baseline_temp_dir / format!("{bench}.bench.json")))
+                    .context("failed to read hyperfine JSON")?;
+                let mut result: serde_json::Value = serde_json::from_reader(BufReader::new(result))
+                    .context("failed to parse hyperfine JSON")?;
+                let result: BenchResult = serde_json::from_value(result["results"][0].take())
+                    .context("failed to interpret hyperfine JSON")?;
                 results.insert(bench as &str, result);
             }
             Ok(results)
@@ -549,15 +574,15 @@ impl Command {
             serde_json::to_writer_pretty(BufWriter::new(baseline), &results)?;
         } else if let Some(baseline_file) = load_baseline {
             let new_results = gather_results()?;
-            let baseline_results: HashMap<String, BenchResult> = {
+            let baseline_results: BTreeMap<String, BenchResult> = {
                 let f = File::open(baseline_file)?;
                 serde_json::from_reader(BufReader::new(f))?
             };
             println!(
                 "Comparison with baseline (relative speed, lower is better for the new results):"
             );
-            for (bench, new_result) in new_results.iter() {
-                let Some(baseline_result) = baseline_results.get(*bench) else { continue };
+            for (bench, new_result) in new_results {
+                let Some(baseline_result) = baseline_results.get(bench) else { continue };
 
                 // Compare results (inspired by hyperfine)
                 let ratio = new_result.mean / baseline_result.mean;
diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version
index 46989695302..553d410b2bc 100644
--- a/src/tools/miri/rust-version
+++ b/src/tools/miri/rust-version
@@ -1 +1 @@
-2b96ddca1272960623e41829439df8dae82d20af
+337c11e5932275e7d450c1f2e26f289f0ddfa717
diff --git a/src/tools/miri/src/alloc_bytes.rs b/src/tools/miri/src/alloc/alloc_bytes.rs
index 6788494c01c..2a253952b27 100644
--- a/src/tools/miri/src/alloc_bytes.rs
+++ b/src/tools/miri/src/alloc/alloc_bytes.rs
@@ -1,12 +1,23 @@
 use std::alloc::Layout;
 use std::borrow::Cow;
 use std::{alloc, slice};
+#[cfg(target_os = "linux")]
+use std::{cell::RefCell, rc::Rc};
 
 use rustc_abi::{Align, Size};
 use rustc_middle::mir::interpret::AllocBytes;
 
+#[cfg(target_os = "linux")]
+use crate::alloc::isolated_alloc::IsolatedAlloc;
 use crate::helpers::ToU64 as _;
 
+#[derive(Clone, Debug)]
+pub enum MiriAllocParams {
+    Global,
+    #[cfg(target_os = "linux")]
+    Isolated(Rc<RefCell<IsolatedAlloc>>),
+}
+
 /// Allocation bytes that explicitly handle the layout of the data they're storing.
 /// This is necessary to interface with native code that accesses the program store in Miri.
 #[derive(Debug)]
@@ -18,13 +29,16 @@ pub struct MiriAllocBytes {
     /// * If `self.layout.size() == 0`, then `self.ptr` was allocated with the equivalent layout with size 1.
     /// * Otherwise, `self.ptr` points to memory allocated with `self.layout`.
     ptr: *mut u8,
+    /// Whether this instance of `MiriAllocBytes` had its allocation created by calling `alloc::alloc()`
+    /// (`Global`) or the discrete allocator (`Isolated`)
+    params: MiriAllocParams,
 }
 
 impl Clone for MiriAllocBytes {
     fn clone(&self) -> Self {
         let bytes: Cow<'_, [u8]> = Cow::Borrowed(self);
         let align = Align::from_bytes(self.layout.align().to_u64()).unwrap();
-        MiriAllocBytes::from_bytes(bytes, align)
+        MiriAllocBytes::from_bytes(bytes, align, self.params.clone())
     }
 }
 
@@ -37,8 +51,16 @@ impl Drop for MiriAllocBytes {
         } else {
             self.layout
         };
+
         // SAFETY: Invariant, `self.ptr` points to memory allocated with `self.layout`.
-        unsafe { alloc::dealloc(self.ptr, alloc_layout) }
+        unsafe {
+            match self.params.clone() {
+                MiriAllocParams::Global => alloc::dealloc(self.ptr, alloc_layout),
+                #[cfg(target_os = "linux")]
+                MiriAllocParams::Isolated(alloc) =>
+                    alloc.borrow_mut().dealloc(self.ptr, alloc_layout),
+            }
+        }
     }
 }
 
@@ -67,7 +89,8 @@ impl MiriAllocBytes {
     fn alloc_with(
         size: u64,
         align: u64,
-        alloc_fn: impl FnOnce(Layout) -> *mut u8,
+        params: MiriAllocParams,
+        alloc_fn: impl FnOnce(Layout, &MiriAllocParams) -> *mut u8,
     ) -> Result<MiriAllocBytes, ()> {
         let size = usize::try_from(size).map_err(|_| ())?;
         let align = usize::try_from(align).map_err(|_| ())?;
@@ -75,24 +98,36 @@ impl MiriAllocBytes {
         // When size is 0 we allocate 1 byte anyway, to ensure each allocation has a unique address.
         let alloc_layout =
             if size == 0 { Layout::from_size_align(1, align).unwrap() } else { layout };
-        let ptr = alloc_fn(alloc_layout);
+        let ptr = alloc_fn(alloc_layout, &params);
         if ptr.is_null() {
             Err(())
         } else {
             // SAFETY: All `MiriAllocBytes` invariants are fulfilled.
-            Ok(Self { ptr, layout })
+            Ok(Self { ptr, layout, params })
         }
     }
 }
 
 impl AllocBytes for MiriAllocBytes {
-    fn from_bytes<'a>(slice: impl Into<Cow<'a, [u8]>>, align: Align) -> Self {
+    type AllocParams = MiriAllocParams;
+
+    fn from_bytes<'a>(
+        slice: impl Into<Cow<'a, [u8]>>,
+        align: Align,
+        params: MiriAllocParams,
+    ) -> Self {
         let slice = slice.into();
         let size = slice.len();
         let align = align.bytes();
         // SAFETY: `alloc_fn` will only be used with `size != 0`.
-        let alloc_fn = |layout| unsafe { alloc::alloc(layout) };
-        let alloc_bytes = MiriAllocBytes::alloc_with(size.to_u64(), align, alloc_fn)
+        let alloc_fn = |layout, params: &MiriAllocParams| unsafe {
+            match params {
+                MiriAllocParams::Global => alloc::alloc(layout),
+                #[cfg(target_os = "linux")]
+                MiriAllocParams::Isolated(alloc) => alloc.borrow_mut().alloc(layout),
+            }
+        };
+        let alloc_bytes = MiriAllocBytes::alloc_with(size.to_u64(), align, params, alloc_fn)
             .unwrap_or_else(|()| {
                 panic!("Miri ran out of memory: cannot create allocation of {size} bytes")
             });
@@ -102,12 +137,18 @@ impl AllocBytes for MiriAllocBytes {
         alloc_bytes
     }
 
-    fn zeroed(size: Size, align: Align) -> Option<Self> {
+    fn zeroed(size: Size, align: Align, params: MiriAllocParams) -> Option<Self> {
         let size = size.bytes();
         let align = align.bytes();
         // SAFETY: `alloc_fn` will only be used with `size != 0`.
-        let alloc_fn = |layout| unsafe { alloc::alloc_zeroed(layout) };
-        MiriAllocBytes::alloc_with(size, align, alloc_fn).ok()
+        let alloc_fn = |layout, params: &MiriAllocParams| unsafe {
+            match params {
+                MiriAllocParams::Global => alloc::alloc_zeroed(layout),
+                #[cfg(target_os = "linux")]
+                MiriAllocParams::Isolated(alloc) => alloc.borrow_mut().alloc_zeroed(layout),
+            }
+        };
+        MiriAllocBytes::alloc_with(size, align, params, alloc_fn).ok()
     }
 
     fn as_mut_ptr(&mut self) -> *mut u8 {
diff --git a/src/tools/miri/src/alloc/isolated_alloc.rs b/src/tools/miri/src/alloc/isolated_alloc.rs
new file mode 100644
index 00000000000..7b74d171373
--- /dev/null
+++ b/src/tools/miri/src/alloc/isolated_alloc.rs
@@ -0,0 +1,389 @@
+use std::alloc::{self, Layout};
+
+use rustc_index::bit_set::DenseBitSet;
+
+/// How many bytes of memory each bit in the bitset represents.
+const COMPRESSION_FACTOR: usize = 4;
+
+/// A dedicated allocator for interpreter memory contents, ensuring they are stored on dedicated
+/// pages (not mixed with Miri's own memory). This is used in native-lib mode.
+#[derive(Debug)]
+pub struct IsolatedAlloc {
+    /// Pointers to page-aligned memory that has been claimed by the allocator.
+    /// Every pointer here must point to a page-sized allocation claimed via
+    /// the global allocator. These pointers are used for "small" allocations.
+    page_ptrs: Vec<*mut u8>,
+    /// Metadata about which bytes have been allocated on each page. The length
+    /// of this vector must be the same as that of `page_ptrs`, and the domain
+    /// size of the bitset must be exactly `page_size / COMPRESSION_FACTOR`.
+    ///
+    /// Conceptually, each bit of the bitset represents the allocation status of
+    /// one n-byte chunk on the corresponding element of `page_ptrs`. Thus,
+    /// indexing into it should be done with a value one-nth of the corresponding
+    /// offset on the matching `page_ptrs` element (n = `COMPRESSION_FACTOR`).
+    page_infos: Vec<DenseBitSet<usize>>,
+    /// Pointers to multiple-page-sized allocations. These must also be page-aligned,
+    /// with their size stored as the second element of the vector.
+    huge_ptrs: Vec<(*mut u8, usize)>,
+    /// The host (not emulated) page size.
+    page_size: usize,
+}
+
+impl IsolatedAlloc {
+    /// Creates an empty allocator.
+    pub fn new() -> Self {
+        Self {
+            page_ptrs: Vec::new(),
+            huge_ptrs: Vec::new(),
+            page_infos: Vec::new(),
+            // SAFETY: `sysconf(_SC_PAGESIZE)` is always safe to call at runtime
+            // See https://www.man7.org/linux/man-pages/man3/sysconf.3.html
+            page_size: unsafe { libc::sysconf(libc::_SC_PAGESIZE).try_into().unwrap() },
+        }
+    }
+
+    /// For simplicity, we serve small allocations in multiples of COMPRESSION_FACTOR
+    /// bytes with at least that alignment.
+    #[inline]
+    fn normalized_layout(layout: Layout) -> Layout {
+        let align =
+            if layout.align() < COMPRESSION_FACTOR { COMPRESSION_FACTOR } else { layout.align() };
+        let size = layout.size().next_multiple_of(COMPRESSION_FACTOR);
+        Layout::from_size_align(size, align).unwrap()
+    }
+
+    /// Returns the layout used to allocate the pages that hold small allocations.
+    #[inline]
+    fn page_layout(&self) -> Layout {
+        Layout::from_size_align(self.page_size, self.page_size).unwrap()
+    }
+
+    /// If the allocation is greater than a page, then round to the nearest page #.
+    #[inline]
+    fn huge_normalized_layout(layout: Layout, page_size: usize) -> Layout {
+        // Allocate in page-sized chunks
+        let size = layout.size().next_multiple_of(page_size);
+        // And make sure the align is at least one page
+        let align = std::cmp::max(layout.align(), page_size);
+        Layout::from_size_align(size, align).unwrap()
+    }
+
+    /// Determined whether a given normalized (size, align) should be sent to
+    /// `alloc_huge` / `dealloc_huge`.
+    #[inline]
+    fn is_huge_alloc(&self, layout: &Layout) -> bool {
+        layout.align() > self.page_size / 2 || layout.size() >= self.page_size / 2
+    }
+
+    /// Allocates memory as described in `Layout`. This memory should be deallocated
+    /// by calling `dealloc` on this same allocator.
+    ///
+    /// SAFETY: See `alloc::alloc()`
+    pub unsafe fn alloc(&mut self, layout: Layout) -> *mut u8 {
+        // SAFETY: Upheld by caller
+        unsafe { self.allocate(layout, false) }
+    }
+
+    /// Same as `alloc`, but zeroes out the memory.
+    ///
+    /// SAFETY: See `alloc::alloc_zeroed()`
+    pub unsafe fn alloc_zeroed(&mut self, layout: Layout) -> *mut u8 {
+        // SAFETY: Upheld by caller
+        unsafe { self.allocate(layout, true) }
+    }
+
+    /// Abstracts over the logic of `alloc_zeroed` vs `alloc`, as determined by
+    /// the `zeroed` argument.
+    ///
+    /// SAFETY: See `alloc::alloc()`, with the added restriction that `page_size`
+    /// corresponds to the host pagesize.
+    unsafe fn allocate(&mut self, layout: Layout, zeroed: bool) -> *mut u8 {
+        let layout = IsolatedAlloc::normalized_layout(layout);
+        if self.is_huge_alloc(&layout) {
+            // SAFETY: Validity of `layout` upheld by caller; we checked that
+            // the size and alignment are appropriate for being a huge alloc
+            unsafe { self.alloc_huge(layout, zeroed) }
+        } else {
+            for (&mut page, pinfo) in std::iter::zip(&mut self.page_ptrs, &mut self.page_infos) {
+                // SAFETY: The value in `self.page_size` is used to allocate
+                // `page`, with page alignment
+                if let Some(ptr) =
+                    unsafe { Self::alloc_small(self.page_size, layout, page, pinfo, zeroed) }
+                {
+                    return ptr;
+                }
+            }
+
+            // We get here only if there's no space in our existing pages
+            let page_size = self.page_size;
+            // Add another page and allocate from it; this cannot fail since the
+            // new page is empty and we already asserted it fits into a page
+            let (page, pinfo) = self.add_page();
+
+            // SAFETY: See comment on `alloc_from_page` above
+            unsafe { Self::alloc_small(page_size, layout, page, pinfo, zeroed).unwrap() }
+        }
+    }
+
+    /// Used internally by `allocate` to abstract over some logic.
+    ///
+    /// SAFETY: `page` must be a page-aligned pointer to an allocated page,
+    /// where the allocation is (at least) `page_size` bytes.
+    unsafe fn alloc_small(
+        page_size: usize,
+        layout: Layout,
+        page: *mut u8,
+        pinfo: &mut DenseBitSet<usize>,
+        zeroed: bool,
+    ) -> Option<*mut u8> {
+        // Check every alignment-sized block and see if there exists a `size`
+        // chunk of empty space i.e. forall idx . !pinfo.contains(idx / n)
+        for offset in (0..page_size).step_by(layout.align()) {
+            let offset_pinfo = offset / COMPRESSION_FACTOR;
+            let size_pinfo = layout.size() / COMPRESSION_FACTOR;
+            // DenseBitSet::contains() panics if the index is out of bounds
+            if pinfo.domain_size() < offset_pinfo + size_pinfo {
+                break;
+            }
+            // FIXME: is there a more efficient way to check whether the entire range is unset
+            // in the bitset?
+            let range_avail = !(offset_pinfo..offset_pinfo + size_pinfo).any(|i| pinfo.contains(i));
+            if range_avail {
+                pinfo.insert_range(offset_pinfo..offset_pinfo + size_pinfo);
+                // SAFETY: We checked the available bytes after `idx` in the call
+                // to `domain_size` above and asserted there are at least `idx +
+                // layout.size()` bytes available and unallocated after it.
+                // `page` must point to the start of the page, so adding `idx`
+                // is safe per the above.
+                unsafe {
+                    let ptr = page.add(offset);
+                    if zeroed {
+                        // Only write the bytes we were specifically asked to
+                        // zero out, even if we allocated more
+                        ptr.write_bytes(0, layout.size());
+                    }
+                    return Some(ptr);
+                }
+            }
+        }
+        None
+    }
+
+    /// Expands the available memory pool by adding one page.
+    fn add_page(&mut self) -> (*mut u8, &mut DenseBitSet<usize>) {
+        // SAFETY: The system page size, which is the layout size, cannot be 0
+        let page_ptr = unsafe { alloc::alloc(self.page_layout()) };
+        // `page_infos` has to have one bit for each `COMPRESSION_FACTOR`-sized chunk of bytes in the page.
+        assert!(self.page_size % COMPRESSION_FACTOR == 0);
+        self.page_infos.push(DenseBitSet::new_empty(self.page_size / COMPRESSION_FACTOR));
+        self.page_ptrs.push(page_ptr);
+        (page_ptr, self.page_infos.last_mut().unwrap())
+    }
+
+    /// Allocates in multiples of one page on the host system.
+    ///
+    /// SAFETY: Same as `alloc()`.
+    unsafe fn alloc_huge(&mut self, layout: Layout, zeroed: bool) -> *mut u8 {
+        let layout = IsolatedAlloc::huge_normalized_layout(layout, self.page_size);
+        // SAFETY: Upheld by caller
+        let ret =
+            unsafe { if zeroed { alloc::alloc_zeroed(layout) } else { alloc::alloc(layout) } };
+        self.huge_ptrs.push((ret, layout.size()));
+        ret
+    }
+
+    /// Deallocates a pointer from this allocator.
+    ///
+    /// SAFETY: This pointer must have been allocated by calling `alloc()` (or
+    /// `alloc_zeroed()`) with the same layout as the one passed on this same
+    /// `IsolatedAlloc`.
+    pub unsafe fn dealloc(&mut self, ptr: *mut u8, layout: Layout) {
+        let layout = IsolatedAlloc::normalized_layout(layout);
+
+        if self.is_huge_alloc(&layout) {
+            // SAFETY: Partly upheld by caller, and we checked that the size
+            // and align, meaning this must have been allocated via `alloc_huge`
+            unsafe {
+                self.dealloc_huge(ptr, layout);
+            }
+        } else {
+            // SAFETY: It's not a huge allocation, therefore it is a small one.
+            let idx = unsafe { self.dealloc_small(ptr, layout) };
+
+            // This may have been the last allocation on this page. If so, free the entire page.
+            // FIXME: this can lead to threshold effects, we should probably add some form
+            // of hysteresis.
+            if self.page_infos[idx].is_empty() {
+                self.page_infos.remove(idx);
+                let page_ptr = self.page_ptrs.remove(idx);
+                // SAFETY: We checked that there are no outstanding allocations
+                // from us pointing to this page, and we know it was allocated
+                // with this layout
+                unsafe {
+                    alloc::dealloc(page_ptr, self.page_layout());
+                }
+            }
+        }
+    }
+
+    /// Returns the index of the page that this was deallocated from
+    ///
+    /// SAFETY: the pointer must have been allocated with `alloc_small`.
+    unsafe fn dealloc_small(&mut self, ptr: *mut u8, layout: Layout) -> usize {
+        // Offset of the pointer in the current page
+        let offset = ptr.addr() % self.page_size;
+        // And then the page's base address
+        let page_addr = ptr.addr() - offset;
+
+        // Find the page this allocation belongs to.
+        // This could be made faster if the list was sorted -- the allocator isn't fully optimized at the moment.
+        let pinfo = std::iter::zip(&mut self.page_ptrs, &mut self.page_infos)
+            .enumerate()
+            .find(|(_, (page, _))| page.addr() == page_addr);
+        let Some((idx_of_pinfo, (_, pinfo))) = pinfo else {
+            panic!("Freeing in an unallocated page: {ptr:?}\nHolding pages {:?}", self.page_ptrs)
+        };
+        // Mark this range as available in the page.
+        let ptr_idx_pinfo = offset / COMPRESSION_FACTOR;
+        let size_pinfo = layout.size() / COMPRESSION_FACTOR;
+        for idx in ptr_idx_pinfo..ptr_idx_pinfo + size_pinfo {
+            pinfo.remove(idx);
+        }
+        idx_of_pinfo
+    }
+
+    /// SAFETY: Same as `dealloc()` with the added requirement that `layout`
+    /// must ask for a size larger than the host pagesize.
+    unsafe fn dealloc_huge(&mut self, ptr: *mut u8, layout: Layout) {
+        let layout = IsolatedAlloc::huge_normalized_layout(layout, self.page_size);
+        // Find the pointer matching in address with the one we got
+        let idx = self
+            .huge_ptrs
+            .iter()
+            .position(|pg| ptr.addr() == pg.0.addr())
+            .expect("Freeing unallocated pages");
+        // And kick it from the list
+        self.huge_ptrs.remove(idx);
+        // SAFETY: Caller ensures validity of the layout
+        unsafe {
+            alloc::dealloc(ptr, layout);
+        }
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+
+    /// Helper function to assert that all bytes from `ptr` to `ptr.add(layout.size())`
+    /// are zeroes.
+    ///
+    /// SAFETY: `ptr` must have been allocated with `layout`.
+    unsafe fn assert_zeroes(ptr: *mut u8, layout: Layout) {
+        // SAFETY: Caller ensures this is valid
+        unsafe {
+            for ofs in 0..layout.size() {
+                assert_eq!(0, ptr.add(ofs).read());
+            }
+        }
+    }
+
+    /// Check that small (sub-pagesize) allocations are properly zeroed out.
+    #[test]
+    fn small_zeroes() {
+        let mut alloc = IsolatedAlloc::new();
+        // 256 should be less than the pagesize on *any* system
+        let layout = Layout::from_size_align(256, 32).unwrap();
+        // SAFETY: layout size is the constant above, not 0
+        let ptr = unsafe { alloc.alloc_zeroed(layout) };
+        // SAFETY: `ptr` was just allocated with `layout`
+        unsafe {
+            assert_zeroes(ptr, layout);
+            alloc.dealloc(ptr, layout);
+        }
+    }
+
+    /// Check that huge (> 1 page) allocations are properly zeroed out also.
+    #[test]
+    fn huge_zeroes() {
+        let mut alloc = IsolatedAlloc::new();
+        // 16k is about as big as pages get e.g. on macos aarch64
+        let layout = Layout::from_size_align(16 * 1024, 128).unwrap();
+        // SAFETY: layout size is the constant above, not 0
+        let ptr = unsafe { alloc.alloc_zeroed(layout) };
+        // SAFETY: `ptr` was just allocated with `layout`
+        unsafe {
+            assert_zeroes(ptr, layout);
+            alloc.dealloc(ptr, layout);
+        }
+    }
+
+    /// Check that repeatedly reallocating the same memory will still zero out
+    /// everything properly
+    #[test]
+    fn repeated_allocs() {
+        let mut alloc = IsolatedAlloc::new();
+        // Try both sub-pagesize allocs and those larger than / equal to a page
+        for sz in (1..=(16 * 1024)).step_by(128) {
+            let layout = Layout::from_size_align(sz, 1).unwrap();
+            // SAFETY: all sizes in the range above are nonzero as we start from 1
+            let ptr = unsafe { alloc.alloc_zeroed(layout) };
+            // SAFETY: `ptr` was just allocated with `layout`, which was used
+            // to bound the access size
+            unsafe {
+                assert_zeroes(ptr, layout);
+                ptr.write_bytes(255, sz);
+                alloc.dealloc(ptr, layout);
+            }
+        }
+    }
+
+    /// Checks that allocations of different sizes do not overlap, then for memory
+    /// leaks that might have occurred.
+    #[test]
+    fn check_leaks_and_overlaps() {
+        let mut alloc = IsolatedAlloc::new();
+
+        // Some random sizes and aligns
+        let mut sizes = vec![32; 10];
+        sizes.append(&mut vec![15; 4]);
+        sizes.append(&mut vec![256; 12]);
+        // Give it some multi-page ones too
+        sizes.append(&mut vec![32 * 1024; 4]);
+
+        // Matching aligns for the sizes
+        let mut aligns = vec![16; 12];
+        aligns.append(&mut vec![256; 2]);
+        aligns.append(&mut vec![64; 12]);
+        aligns.append(&mut vec![4096; 4]);
+
+        // Make sure we didn't mess up in the test itself!
+        assert_eq!(sizes.len(), aligns.len());
+
+        // Aggregate the sizes and aligns into a vec of layouts, then allocate them
+        let layouts: Vec<_> = std::iter::zip(sizes, aligns)
+            .map(|(sz, al)| Layout::from_size_align(sz, al).unwrap())
+            .collect();
+        // SAFETY: all sizes specified in `sizes` are nonzero
+        let ptrs: Vec<_> =
+            layouts.iter().map(|layout| unsafe { alloc.alloc_zeroed(*layout) }).collect();
+
+        for (&ptr, &layout) in std::iter::zip(&ptrs, &layouts) {
+            // We requested zeroed allocations, so check that that's true
+            // Then write to the end of the current size, so if the allocs
+            // overlap (or the zeroing is wrong) then `assert_zeroes` will panic.
+            // Also check that the alignment we asked for was respected
+            assert_eq!(ptr.addr().strict_rem(layout.align()), 0);
+            // SAFETY: each `ptr` was allocated with its corresponding `layout`,
+            // which is used to bound the access size
+            unsafe {
+                assert_zeroes(ptr, layout);
+                ptr.write_bytes(255, layout.size());
+                alloc.dealloc(ptr, layout);
+            }
+        }
+
+        // And then verify that no memory was leaked after all that
+        assert!(alloc.page_ptrs.is_empty() && alloc.huge_ptrs.is_empty());
+    }
+}
diff --git a/src/tools/miri/src/alloc/mod.rs b/src/tools/miri/src/alloc/mod.rs
new file mode 100644
index 00000000000..3be885920d2
--- /dev/null
+++ b/src/tools/miri/src/alloc/mod.rs
@@ -0,0 +1,5 @@
+mod alloc_bytes;
+#[cfg(target_os = "linux")]
+pub mod isolated_alloc;
+
+pub use self::alloc_bytes::{MiriAllocBytes, MiriAllocParams};
diff --git a/src/tools/miri/src/alloc_addresses/mod.rs b/src/tools/miri/src/alloc_addresses/mod.rs
index 21bd7fb54c6..12a320b9676 100644
--- a/src/tools/miri/src/alloc_addresses/mod.rs
+++ b/src/tools/miri/src/alloc_addresses/mod.rs
@@ -135,11 +135,12 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
         if this.machine.native_lib.is_some() {
             // In native lib mode, we use the "real" address of the bytes for this allocation.
             // This ensures the interpreted program and native code have the same view of memory.
+            let params = this.machine.get_default_alloc_params();
             let base_ptr = match info.kind {
                 AllocKind::LiveData => {
                     if memory_kind == MiriMemoryKind::Global.into() {
                         // For new global allocations, we always pre-allocate the memory to be able use the machine address directly.
-                        let prepared_bytes = MiriAllocBytes::zeroed(info.size, info.align)
+                        let prepared_bytes = MiriAllocBytes::zeroed(info.size, info.align, params)
                             .unwrap_or_else(|| {
                                 panic!("Miri ran out of memory: cannot create allocation of {size:?} bytes", size = info.size)
                             });
@@ -158,8 +159,11 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
                 }
                 AllocKind::Function | AllocKind::VTable => {
                     // Allocate some dummy memory to get a unique address for this function/vtable.
-                    let alloc_bytes =
-                        MiriAllocBytes::from_bytes(&[0u8; 1], Align::from_bytes(1).unwrap());
+                    let alloc_bytes = MiriAllocBytes::from_bytes(
+                        &[0u8; 1],
+                        Align::from_bytes(1).unwrap(),
+                        params,
+                    );
                     let ptr = alloc_bytes.as_ptr();
                     // Leak the underlying memory to ensure it remains unique.
                     std::mem::forget(alloc_bytes);
@@ -429,7 +433,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
             prepared_alloc_bytes.copy_from_slice(bytes);
             interp_ok(prepared_alloc_bytes)
         } else {
-            interp_ok(MiriAllocBytes::from_bytes(std::borrow::Cow::Borrowed(bytes), align))
+            let params = this.machine.get_default_alloc_params();
+            interp_ok(MiriAllocBytes::from_bytes(std::borrow::Cow::Borrowed(bytes), align, params))
         }
     }
 
diff --git a/src/tools/miri/src/bin/miri.rs b/src/tools/miri/src/bin/miri.rs
index 7098ef5130d..0121472d330 100644
--- a/src/tools/miri/src/bin/miri.rs
+++ b/src/tools/miri/src/bin/miri.rs
@@ -281,7 +281,9 @@ impl rustc_driver::Callbacks for MiriBeRustCompilerCalls {
                             }
                             let codegen_fn_attrs = tcx.codegen_fn_attrs(local_def_id);
                             if codegen_fn_attrs.contains_extern_indicator()
-                                || codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::USED_COMPILER)
+                                || codegen_fn_attrs
+                                    .flags
+                                    .contains(CodegenFnAttrFlags::USED_COMPILER)
                                 || codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::USED_LINKER)
                             {
                                 Some((
diff --git a/src/tools/miri/src/borrow_tracker/tree_borrows/diagnostics.rs b/src/tools/miri/src/borrow_tracker/tree_borrows/diagnostics.rs
index f5a0013047a..7b4c533cfae 100644
--- a/src/tools/miri/src/borrow_tracker/tree_borrows/diagnostics.rs
+++ b/src/tools/miri/src/borrow_tracker/tree_borrows/diagnostics.rs
@@ -504,7 +504,7 @@ impl DisplayFmt {
         if let Some(perm) = perm {
             format!(
                 "{ac}{st}",
-                ac = if perm.is_initialized() { self.accessed.yes } else { self.accessed.no },
+                ac = if perm.is_accessed() { self.accessed.yes } else { self.accessed.no },
                 st = perm.permission().short_name(),
             )
         } else {
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 f3e32e75f2f..411ae89da90 100644
--- a/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs
+++ b/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs
@@ -3,6 +3,8 @@ use rustc_middle::mir::{Mutability, RetagKind};
 use rustc_middle::ty::layout::HasTypingEnv;
 use rustc_middle::ty::{self, Ty};
 
+use self::foreign_access_skipping::IdempotentForeignAccess;
+use self::tree::LocationState;
 use crate::borrow_tracker::{GlobalState, GlobalStateInner, ProtectorKind};
 use crate::concurrency::data_race::NaReadType;
 use crate::*;
@@ -95,7 +97,7 @@ impl<'tcx> Tree {
     /// A tag just lost its protector.
     ///
     /// This emits a special kind of access that is only applied
-    /// to initialized locations, as a protection against other
+    /// to accessed locations, as a protection against other
     /// tags not having been made aware of the existence of this
     /// protector.
     pub fn release_protector(
@@ -113,16 +115,19 @@ impl<'tcx> Tree {
 
 /// Policy for a new borrow.
 #[derive(Debug, Clone, Copy)]
-struct NewPermission {
-    /// Which permission should the pointer start with.
-    initial_state: Permission,
+pub struct NewPermission {
+    /// Permission for the frozen part of the range.
+    freeze_perm: Permission,
+    /// Whether a read access should be performed on the frozen part on a retag.
+    freeze_access: bool,
+    /// Permission for the non-frozen part of the range.
+    nonfreeze_perm: Permission,
+    /// Whether a read access should be performed on the non-frozen
+    /// part on a retag.
+    nonfreeze_access: bool,
     /// Whether this pointer is part of the arguments of a function call.
     /// `protector` is `Some(_)` for all pointers marked `noalias`.
     protector: Option<ProtectorKind>,
-    /// Whether a read should be performed on a retag.  This should be `false`
-    /// for `Cell` because this could cause data races when using thread-safe
-    /// data types like `Mutex<T>`.
-    initial_read: bool,
 }
 
 impl<'tcx> NewPermission {
@@ -133,27 +138,42 @@ impl<'tcx> NewPermission {
         kind: RetagKind,
         cx: &crate::MiriInterpCx<'tcx>,
     ) -> Option<Self> {
-        let ty_is_freeze = pointee.is_freeze(*cx.tcx, cx.typing_env());
         let ty_is_unpin = pointee.is_unpin(*cx.tcx, cx.typing_env());
         let is_protected = kind == RetagKind::FnEntry;
-        // As demonstrated by `tests/fail/tree_borrows/reservedim_spurious_write.rs`,
-        // interior mutability and protectors interact poorly.
-        // To eliminate the case of Protected Reserved IM we override interior mutability
-        // in the case of a protected reference: protected references are always considered
-        // "freeze" in their reservation phase.
-        let (initial_state, initial_read) = match mutability {
+        let protector = is_protected.then_some(ProtectorKind::StrongProtector);
+
+        Some(match mutability {
             Mutability::Mut if ty_is_unpin =>
-                (Permission::new_reserved(ty_is_freeze, is_protected), true),
-            Mutability::Not if ty_is_freeze => (Permission::new_frozen(), true),
-            Mutability::Not if !ty_is_freeze => (Permission::new_cell(), false),
-            // Raw pointers never enter this function so they are not handled.
-            // However raw pointers are not the only pointers that take the parent
-            // tag, this also happens for `!Unpin` `&mut`s, which are excluded above.
+                NewPermission {
+                    freeze_perm: Permission::new_reserved(
+                        /* ty_is_freeze */ true,
+                        is_protected,
+                    ),
+                    freeze_access: true,
+                    nonfreeze_perm: Permission::new_reserved(
+                        /* ty_is_freeze */ false,
+                        is_protected,
+                    ),
+                    // If we have a mutable reference, then the non-frozen part will
+                    // have state `ReservedIM` or `Reserved`, which can have an initial read access
+                    // performed on it because you cannot have multiple mutable borrows.
+                    nonfreeze_access: true,
+                    protector,
+                },
+            Mutability::Not =>
+                NewPermission {
+                    freeze_perm: Permission::new_frozen(),
+                    freeze_access: true,
+                    nonfreeze_perm: Permission::new_cell(),
+                    // If it is a shared reference, then the non-frozen
+                    // part will have state `Cell`, which should not have an initial access,
+                    // as this can cause data races when using thread-safe data types like
+                    // `Mutex<T>`.
+                    nonfreeze_access: false,
+                    protector,
+                },
             _ => return None,
-        };
-
-        let protector = is_protected.then_some(ProtectorKind::StrongProtector);
-        Some(Self { initial_state, protector, initial_read })
+        })
     }
 
     /// Compute permission for `Box`-like type (`Box` always, and also `Unique` if enabled).
@@ -168,13 +188,17 @@ impl<'tcx> NewPermission {
         pointee.is_unpin(*cx.tcx, cx.typing_env()).then_some(()).map(|()| {
             // Regular `Unpin` box, give it `noalias` but only a weak protector
             // because it is valid to deallocate it within the function.
-            let ty_is_freeze = pointee.is_freeze(*cx.tcx, cx.typing_env());
-            let protected = kind == RetagKind::FnEntry;
-            let initial_state = Permission::new_reserved(ty_is_freeze, protected);
-            Self {
-                initial_state,
-                protector: protected.then_some(ProtectorKind::WeakProtector),
-                initial_read: true,
+            let is_protected = kind == RetagKind::FnEntry;
+            let protector = is_protected.then_some(ProtectorKind::WeakProtector);
+            NewPermission {
+                freeze_perm: Permission::new_reserved(/* ty_is_freeze */ true, is_protected),
+                freeze_access: true,
+                nonfreeze_perm: Permission::new_reserved(
+                    /* ty_is_freeze */ false,
+                    is_protected,
+                ),
+                nonfreeze_access: true,
+                protector,
             }
         })
     }
@@ -194,8 +218,6 @@ trait EvalContextPrivExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
         new_tag: BorTag,
     ) -> InterpResult<'tcx, Option<Provenance>> {
         let this = self.eval_context_mut();
-        // Make sure the new permission makes sense as the initial permission of a fresh tag.
-        assert!(new_perm.initial_state.is_initial());
         // Ensure we bail out if the pointer goes out-of-bounds (see miri#1050).
         this.check_ptr_access(place.ptr(), ptr_size, CheckInAllocMsg::Dereferenceable)?;
 
@@ -206,7 +228,13 @@ trait EvalContextPrivExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
             let global = this.machine.borrow_tracker.as_ref().unwrap().borrow();
             let ty = place.layout.ty;
             if global.tracked_pointer_tags.contains(&new_tag) {
-                let kind_str = format!("initial state {} (pointee type {ty})", new_perm.initial_state);
+                 let ty_is_freeze = ty.is_freeze(*this.tcx, this.typing_env());
+                 let kind_str =
+                     if ty_is_freeze {
+                         format!("initial state {} (pointee type {ty})", new_perm.freeze_perm)
+                     } else {
+                         format!("initial state {}/{} outside/inside UnsafeCell (pointee type {ty})", new_perm.freeze_perm, new_perm.nonfreeze_perm)
+                     };
                 this.emit_diagnostic(NonHaltingDiagnostic::CreatedPointerTag(
                     new_tag.inner(),
                     Some(kind_str),
@@ -285,43 +313,103 @@ trait EvalContextPrivExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
 
         let span = this.machine.current_span();
         let alloc_extra = this.get_alloc_extra(alloc_id)?;
-        let range = alloc_range(base_offset, ptr_size);
         let mut tree_borrows = alloc_extra.borrow_tracker_tb().borrow_mut();
 
-        // All reborrows incur a (possibly zero-sized) read access to the parent
-        if new_perm.initial_read {
-            tree_borrows.perform_access(
-                orig_tag,
-                Some((range, AccessKind::Read, diagnostics::AccessCause::Reborrow)),
-                this.machine.borrow_tracker.as_ref().unwrap(),
-                alloc_id,
-                this.machine.current_span(),
-            )?;
-        }
+        // Store initial permissions and their corresponding range.
+        let mut perms_map: RangeMap<LocationState> = RangeMap::new(
+            ptr_size,
+            LocationState::new_accessed(Permission::new_disabled(), IdempotentForeignAccess::None), // this will be overwritten
+        );
+        // Keep track of whether the node has any part that allows for interior mutability.
+        // FIXME: This misses `PhantomData<UnsafeCell<T>>` which could be considered a marker
+        // for requesting interior mutability.
+        let mut has_unsafe_cell = false;
+
+        // When adding a new node, the SIFA of its parents needs to be updated, potentially across
+        // the entire memory range. For the parts that are being accessed below, the access itself
+        // trivially takes care of that. However, we have to do some more work to also deal with
+        // the parts that are not being accessed. Specifically what we do is that we
+        // call `update_last_accessed_after_retag` on the SIFA of the permission set for the part of
+        // memory outside `perm_map` -- so that part is definitely taken care of. The remaining concern
+        // is the part of memory that is in the range of `perms_map`, but not accessed below.
+        // There we have two cases:
+        // * If we do have an `UnsafeCell` (`has_unsafe_cell` becomes true), then the non-accessed part
+        //   uses `nonfreeze_perm`, so the `nonfreeze_perm` initialized parts are also fine. We enforce
+        //   the `freeze_perm` parts to be accessed, and thus everything is taken care of.
+        // * If there is no `UnsafeCell`, then `freeze_perm` is used everywhere (both inside and outside the initial range),
+        //   and we update everything to have the `freeze_perm`'s SIFA, so there are no issues. (And this assert below is not
+        //   actually needed in this case).
+        assert!(new_perm.freeze_access);
+
+        let protected = new_perm.protector.is_some();
+        this.visit_freeze_sensitive(place, ptr_size, |range, frozen| {
+            has_unsafe_cell = has_unsafe_cell || !frozen;
+
+            // We are only ever `Frozen` inside the frozen bits.
+            let (perm, access) = if frozen {
+                (new_perm.freeze_perm, new_perm.freeze_access)
+            } else {
+                (new_perm.nonfreeze_perm, new_perm.nonfreeze_access)
+            };
+
+            // Store initial permissions.
+            for (_loc_range, loc) in perms_map.iter_mut(range.start, range.size) {
+                let sifa = perm.strongest_idempotent_foreign_access(protected);
+                // NOTE: Currently, `access` is false if and only if `perm` is Cell, so this `if`
+                // doesn't not change whether any code is UB or not. We could just always use
+                // `new_accessed` and everything would stay the same. But that seems conceptually
+                // odd, so we keep the initial "accessed" bit of the `LocationState` in sync with whether
+                // a read access is performed below.
+                if access {
+                    *loc = LocationState::new_accessed(perm, sifa);
+                } else {
+                    *loc = LocationState::new_non_accessed(perm, sifa);
+                }
+            }
+
+            // Some reborrows incur a read access to the parent.
+            if access {
+                // Adjust range to be relative to allocation start (rather than to `place`).
+                let mut range_in_alloc = range;
+                range_in_alloc.start += base_offset;
+
+                tree_borrows.perform_access(
+                    orig_tag,
+                    Some((range_in_alloc, AccessKind::Read, diagnostics::AccessCause::Reborrow)),
+                    this.machine.borrow_tracker.as_ref().unwrap(),
+                    alloc_id,
+                    this.machine.current_span(),
+                )?;
+
+                // Also inform the data race model (but only if any bytes are actually affected).
+                if range.size.bytes() > 0 {
+                    if let Some(data_race) = alloc_extra.data_race.as_vclocks_ref() {
+                        data_race.read(
+                            alloc_id,
+                            range_in_alloc,
+                            NaReadType::Retag,
+                            Some(place.layout.ty),
+                            &this.machine,
+                        )?
+                    }
+                }
+            }
+            interp_ok(())
+        })?;
+
         // Record the parent-child pair in the tree.
         tree_borrows.new_child(
+            base_offset,
             orig_tag,
             new_tag,
-            new_perm.initial_state,
-            range,
+            perms_map,
+            // Allow lazily writing to surrounding data if we found an `UnsafeCell`.
+            if has_unsafe_cell { new_perm.nonfreeze_perm } else { new_perm.freeze_perm },
+            protected,
             span,
-            new_perm.protector.is_some(),
         )?;
         drop(tree_borrows);
 
-        // Also inform the data race model (but only if any bytes are actually affected).
-        if range.size.bytes() > 0 && new_perm.initial_read {
-            if let Some(data_race) = alloc_extra.data_race.as_vclocks_ref() {
-                data_race.read(
-                    alloc_id,
-                    range,
-                    NaReadType::Retag,
-                    Some(place.layout.ty),
-                    &this.machine,
-                )?;
-            }
-        }
-
         interp_ok(Some(Provenance::Concrete { alloc_id, tag: new_tag }))
     }
 
@@ -508,15 +596,21 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     fn tb_protect_place(&mut self, place: &MPlaceTy<'tcx>) -> InterpResult<'tcx, MPlaceTy<'tcx>> {
         let this = self.eval_context_mut();
 
-        // Note: if we were to inline `new_reserved` below we would find out that
-        // `ty_is_freeze` is eventually unused because it appears in a `ty_is_freeze || true`.
-        // We are nevertheless including it here for clarity.
-        let ty_is_freeze = place.layout.ty.is_freeze(*this.tcx, this.typing_env());
         // Retag it. With protection! That is the entire point.
         let new_perm = NewPermission {
-            initial_state: Permission::new_reserved(ty_is_freeze, /* protected */ true),
+            // Note: If we are creating a protected Reserved, which can
+            // never be ReservedIM, the value of the `ty_is_freeze`
+            // argument doesn't matter
+            // (`ty_is_freeze || true` in `new_reserved` will always be `true`).
+            freeze_perm: Permission::new_reserved(
+                /* ty_is_freeze */ true, /* protected */ true,
+            ),
+            freeze_access: true,
+            nonfreeze_perm: Permission::new_reserved(
+                /* ty_is_freeze */ false, /* protected */ true,
+            ),
+            nonfreeze_access: true,
             protector: Some(ProtectorKind::StrongProtector),
-            initial_read: true,
         };
         this.tb_retag_place(place, new_perm)
     }
diff --git a/src/tools/miri/src/borrow_tracker/tree_borrows/perms.rs b/src/tools/miri/src/borrow_tracker/tree_borrows/perms.rs
index 087f6fc3f24..38863ca0734 100644
--- a/src/tools/miri/src/borrow_tracker/tree_borrows/perms.rs
+++ b/src/tools/miri/src/borrow_tracker/tree_borrows/perms.rs
@@ -94,6 +94,7 @@ impl PermissionPriv {
     }
 
     /// Reject `ReservedIM` that cannot exist in the presence of a protector.
+    #[cfg(test)]
     fn compatible_with_protector(&self) -> bool {
         // FIXME(TB-Cell): It is unclear what to do here.
         // `Cell` will occur with a protector but won't provide the guarantees
@@ -253,10 +254,6 @@ impl Permission {
     pub fn is_disabled(&self) -> bool {
         self.inner == Disabled
     }
-    /// Check if `self` is the post-child-write state of a pointer (is `Active`).
-    pub fn is_active(&self) -> bool {
-        self.inner == Active
-    }
     /// Check if `self` is the never-allow-writes-again state of a pointer (is `Frozen`).
     pub fn is_frozen(&self) -> bool {
         self.inner == Frozen
@@ -289,6 +286,11 @@ impl Permission {
     /// is a protector is relevant because being protected takes priority over being
     /// interior mutable)
     pub fn new_reserved(ty_is_freeze: bool, protected: bool) -> Self {
+        // As demonstrated by `tests/fail/tree_borrows/reservedim_spurious_write.rs`,
+        // interior mutability and protectors interact poorly.
+        // To eliminate the case of Protected Reserved IM we override interior mutability
+        // in the case of a protected reference: protected references are always considered
+        // "freeze" in their reservation phase.
         if ty_is_freeze || protected { Self::new_reserved_frz() } else { Self::new_reserved_im() }
     }
 
@@ -309,6 +311,7 @@ impl Permission {
     }
 
     /// Reject `ReservedIM` that cannot exist in the presence of a protector.
+    #[cfg(test)]
     pub fn compatible_with_protector(&self) -> bool {
         self.inner.compatible_with_protector()
     }
@@ -393,11 +396,6 @@ impl PermTransition {
         self.from <= self.to
     }
 
-    pub fn from(from: Permission, to: Permission) -> Option<Self> {
-        let t = Self { from: from.inner, to: to.inner };
-        t.is_possible().then_some(t)
-    }
-
     pub fn is_noop(self) -> bool {
         self.from == self.to
     }
@@ -407,11 +405,6 @@ impl PermTransition {
         (starting_point.inner == self.from).then_some(Permission { inner: self.to })
     }
 
-    /// Extract starting point of a transition
-    pub fn started(self) -> Permission {
-        Permission { inner: self.from }
-    }
-
     /// Determines if this transition would disable the permission.
     pub fn produces_disabled(self) -> bool {
         self.to == Disabled
diff --git a/src/tools/miri/src/borrow_tracker/tree_borrows/tree.rs b/src/tools/miri/src/borrow_tracker/tree_borrows/tree.rs
index 47ccaadbb9e..48e4a19e263 100644
--- a/src/tools/miri/src/borrow_tracker/tree_borrows/tree.rs
+++ b/src/tools/miri/src/borrow_tracker/tree_borrows/tree.rs
@@ -10,6 +10,7 @@
 //!   and the relative position of the access;
 //! - idempotency properties asserted in `perms.rs` (for optimizations)
 
+use std::ops::Range;
 use std::{fmt, mem};
 
 use rustc_abi::Size;
@@ -32,18 +33,18 @@ mod tests;
 /// Data for a single *location*.
 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
 pub(super) struct LocationState {
-    /// A location is initialized when it is child-accessed for the first time (and the initial
+    /// A location is "accessed" when it is child-accessed for the first time (and the initial
     /// retag initializes the location for the range covered by the type), and it then stays
-    /// initialized forever.
-    /// For initialized locations, "permission" is the current permission. However, for
-    /// uninitialized locations, we still need to track the "future initial permission": this will
+    /// accessed forever.
+    /// For accessed locations, "permission" is the current permission. However, for
+    /// non-accessed locations, we still need to track the "future initial permission": this will
     /// start out to be `default_initial_perm`, but foreign accesses need to be taken into account.
     /// Crucially however, while transitions to `Disabled` would usually be UB if this location is
-    /// protected, that is *not* the case for uninitialized locations. Instead we just have a latent
+    /// protected, that is *not* the case for non-accessed locations. Instead we just have a latent
     /// "future initial permission" of `Disabled`, causing UB only if an access is ever actually
     /// performed.
-    /// Note that the tree root is also always initialized, as if the allocation was a write access.
-    initialized: bool,
+    /// Note that the tree root is also always accessed, as if the allocation was a write access.
+    accessed: bool,
     /// This pointer's current permission / future initial permission.
     permission: Permission,
     /// See `foreign_access_skipping.rs`.
@@ -58,30 +59,30 @@ impl LocationState {
     /// to any foreign access yet.
     /// The permission is not allowed to be `Active`.
     /// `sifa` is the (strongest) idempotent foreign access, see `foreign_access_skipping.rs`
-    fn new_uninit(permission: Permission, sifa: IdempotentForeignAccess) -> Self {
+    pub fn new_non_accessed(permission: Permission, sifa: IdempotentForeignAccess) -> Self {
         assert!(permission.is_initial() || permission.is_disabled());
-        Self { permission, initialized: false, idempotent_foreign_access: sifa }
+        Self { permission, accessed: false, idempotent_foreign_access: sifa }
     }
 
     /// Constructs a new initial state. It has not yet been subjected
     /// to any foreign access. However, it is already marked as having been accessed.
     /// `sifa` is the (strongest) idempotent foreign access, see `foreign_access_skipping.rs`
-    fn new_init(permission: Permission, sifa: IdempotentForeignAccess) -> Self {
-        Self { permission, initialized: true, idempotent_foreign_access: sifa }
+    pub fn new_accessed(permission: Permission, sifa: IdempotentForeignAccess) -> Self {
+        Self { permission, accessed: true, idempotent_foreign_access: sifa }
     }
 
-    /// Check if the location has been initialized, i.e. if it has
+    /// Check if the location has been accessed, i.e. if it has
     /// ever been accessed through a child pointer.
-    pub fn is_initialized(&self) -> bool {
-        self.initialized
+    pub fn is_accessed(&self) -> bool {
+        self.accessed
     }
 
     /// Check if the state can exist as the initial permission of a pointer.
     ///
-    /// Do not confuse with `is_initialized`, the two are almost orthogonal
-    /// as apart from `Active` which is not initial and must be initialized,
+    /// Do not confuse with `is_accessed`, the two are almost orthogonal
+    /// as apart from `Active` which is not initial and must be accessed,
     /// any other permission can have an arbitrary combination of being
-    /// initial/initialized.
+    /// initial/accessed.
     /// FIXME: when the corresponding `assert` in `tree_borrows/mod.rs` finally
     /// passes and can be uncommented, remove this `#[allow(dead_code)]`.
     #[cfg_attr(not(test), allow(dead_code))]
@@ -95,8 +96,8 @@ impl LocationState {
 
     /// Apply the effect of an access to one location, including
     /// - applying `Permission::perform_access` to the inner `Permission`,
-    /// - emitting protector UB if the location is initialized,
-    /// - updating the initialized status (child accesses produce initialized locations).
+    /// - emitting protector UB if the location is accessed,
+    /// - updating the accessed status (child accesses produce accessed locations).
     fn perform_access(
         &mut self,
         access_kind: AccessKind,
@@ -106,14 +107,14 @@ impl LocationState {
         let old_perm = self.permission;
         let transition = Permission::perform_access(access_kind, rel_pos, old_perm, protected)
             .ok_or(TransitionError::ChildAccessForbidden(old_perm))?;
-        self.initialized |= !rel_pos.is_foreign();
+        self.accessed |= !rel_pos.is_foreign();
         self.permission = transition.applied(old_perm).unwrap();
-        // Why do only initialized locations cause protector errors?
+        // Why do only accessed locations cause protector errors?
         // Consider two mutable references `x`, `y` into disjoint parts of
         // the same allocation. A priori, these may actually both be used to
         // access the entire allocation, as long as only reads occur. However,
         // a write to `y` needs to somehow record that `x` can no longer be used
-        // on that location at all. For these uninitialized locations (i.e., locations
+        // on that location at all. For these non-accessed locations (i.e., locations
         // that haven't been accessed with `x` yet), we track the "future initial state":
         // it defaults to whatever the initial state of the tag is,
         // but the access to `y` moves that "future initial state" of `x` to `Disabled`.
@@ -121,8 +122,8 @@ impl LocationState {
         // So clearly protectors shouldn't fire for such "future initial state" transitions.
         //
         // See the test `two_mut_protected_same_alloc` in `tests/pass/tree_borrows/tree-borrows.rs`
-        // for an example of safe code that would be UB if we forgot to check `self.initialized`.
-        if protected && self.initialized && transition.produces_disabled() {
+        // for an example of safe code that would be UB if we forgot to check `self.accessed`.
+        if protected && self.accessed && transition.produces_disabled() {
             return Err(TransitionError::ProtectedDisabled(old_perm));
         }
         Ok(transition)
@@ -157,11 +158,11 @@ impl LocationState {
                 self.idempotent_foreign_access.can_skip_foreign_access(happening_now);
             if self.permission.is_disabled() {
                 // A foreign access to a `Disabled` tag will have almost no observable effect.
-                // It's a theorem that `Disabled` node have no protected initialized children,
+                // It's a theorem that `Disabled` node have no protected accessed children,
                 // and so this foreign access will never trigger any protector.
-                // (Intuition: You're either protected initialized, and thus can't become Disabled
-                // or you're already Disabled protected, but not initialized, and then can't
-                // become initialized since that requires a child access, which Disabled blocks.)
+                // (Intuition: You're either protected accessed, and thus can't become Disabled
+                // or you're already Disabled protected, but not accessed, and then can't
+                // become accessed since that requires a child access, which Disabled blocks.)
                 // Further, the children will never be able to read or write again, since they
                 // have a `Disabled` parent. So this only affects diagnostics, such that the
                 // blocking write will still be identified directly, just at a different tag.
@@ -217,7 +218,7 @@ impl LocationState {
 impl fmt::Display for LocationState {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         write!(f, "{}", self.permission)?;
-        if !self.initialized {
+        if !self.accessed {
             write!(f, "?")?;
         }
         Ok(())
@@ -598,12 +599,15 @@ impl Tree {
         let rperms = {
             let mut perms = UniValMap::default();
             // We manually set it to `Active` on all in-bounds positions.
-            // We also ensure that it is initialized, so that no `Active` but
-            // not yet initialized nodes exist. Essentially, we pretend there
+            // We also ensure that it is accessed, so that no `Active` but
+            // not yet accessed nodes exist. Essentially, we pretend there
             // was a write that initialized these to `Active`.
             perms.insert(
                 root_idx,
-                LocationState::new_init(Permission::new_active(), IdempotentForeignAccess::None),
+                LocationState::new_accessed(
+                    Permission::new_active(),
+                    IdempotentForeignAccess::None,
+                ),
             );
             RangeMap::new(size, perms)
         };
@@ -612,20 +616,32 @@ impl Tree {
 }
 
 impl<'tcx> Tree {
-    /// Insert a new tag in the tree
-    pub fn new_child(
+    /// Insert a new tag in the tree.
+    ///
+    /// `initial_perms` defines the initial permissions for the part of memory
+    /// that is already considered "initialized" immediately. The ranges in this
+    /// map are relative to `base_offset`.
+    /// `default_perm` defines the initial permission for the rest of the allocation.
+    ///
+    /// For all non-accessed locations in the RangeMap (those that haven't had an
+    /// implicit read), their SIFA must be weaker than or as weak as the SIFA of
+    /// `default_perm`.
+    pub(super) fn new_child(
         &mut self,
+        base_offset: Size,
         parent_tag: BorTag,
         new_tag: BorTag,
-        default_initial_perm: Permission,
-        reborrow_range: AllocRange,
+        initial_perms: RangeMap<LocationState>,
+        default_perm: Permission,
+        protected: bool,
         span: Span,
-        prot: bool,
     ) -> InterpResult<'tcx> {
-        assert!(!self.tag_mapping.contains_key(&new_tag));
         let idx = self.tag_mapping.insert(new_tag);
         let parent_idx = self.tag_mapping.get(&parent_tag).unwrap();
-        let strongest_idempotent = default_initial_perm.strongest_idempotent_foreign_access(prot);
+        assert!(default_perm.is_initial());
+
+        let default_strongest_idempotent =
+            default_perm.strongest_idempotent_foreign_access(protected);
         // Create the node
         self.nodes.insert(
             idx,
@@ -633,25 +649,36 @@ impl<'tcx> Tree {
                 tag: new_tag,
                 parent: Some(parent_idx),
                 children: SmallVec::default(),
-                default_initial_perm,
-                default_initial_idempotent_foreign_access: strongest_idempotent,
-                debug_info: NodeDebugInfo::new(new_tag, default_initial_perm, span),
+                default_initial_perm: default_perm,
+                default_initial_idempotent_foreign_access: default_strongest_idempotent,
+                debug_info: NodeDebugInfo::new(new_tag, default_perm, span),
             },
         );
         // Register new_tag as a child of parent_tag
         self.nodes.get_mut(parent_idx).unwrap().children.push(idx);
-        // Initialize perms
-        let perm = LocationState::new_init(default_initial_perm, strongest_idempotent);
-        for (_perms_range, perms) in self.rperms.iter_mut(reborrow_range.start, reborrow_range.size)
+
+        for (Range { start, end }, &perm) in
+            initial_perms.iter(Size::from_bytes(0), initial_perms.size())
         {
-            perms.insert(idx, perm);
+            assert!(perm.is_initial());
+            for (_perms_range, perms) in self
+                .rperms
+                .iter_mut(Size::from_bytes(start) + base_offset, Size::from_bytes(end - start))
+            {
+                assert!(
+                    default_strongest_idempotent
+                        >= perm.permission.strongest_idempotent_foreign_access(protected)
+                );
+                perms.insert(idx, perm);
+            }
         }
 
         // Inserting the new perms might have broken the SIFA invariant (see `foreign_access_skipping.rs`).
         // We now weaken the recorded SIFA for our parents, until the invariant is restored.
         // We could weaken them all to `LocalAccess`, but it is more efficient to compute the SIFA
         // for the new permission statically, and use that.
-        self.update_last_accessed_after_retag(parent_idx, strongest_idempotent);
+        // See the comment in `tb_reborrow` for why it is correct to use the SIFA of `default_uninit_perm`.
+        self.update_last_accessed_after_retag(parent_idx, default_strongest_idempotent);
 
         interp_ok(())
     }
@@ -758,14 +785,14 @@ impl<'tcx> Tree {
     ///
     /// If `access_range_and_kind` is `None`, this is interpreted as the special
     /// access that is applied on protector release:
-    /// - the access will be applied only to initialized locations of the allocation,
+    /// - the access will be applied only to accessed locations of the allocation,
     /// - it will not be visible to children,
     /// - it will be recorded as a `FnExit` diagnostic access
     /// - and it will be a read except if the location is `Active`, i.e. has been written to,
     ///   in which case it will be a write.
     ///
     /// `LocationState::perform_access` will take care of raising transition
-    /// errors and updating the `initialized` status of each location,
+    /// errors and updating the `accessed` status of each location,
     /// this traversal adds to that:
     /// - inserting into the map locations that do not exist yet,
     /// - trimming the traversal,
@@ -858,7 +885,7 @@ impl<'tcx> Tree {
             }
         } else {
             // This is a special access through the entire allocation.
-            // It actually only affects `initialized` locations, so we need
+            // It actually only affects `accessed` locations, so we need
             // to filter on those before initiating the traversal.
             //
             // In addition this implicit access should not be visible to children,
@@ -868,10 +895,10 @@ impl<'tcx> Tree {
             // why this is important.
             for (perms_range, perms) in self.rperms.iter_mut_all() {
                 let idx = self.tag_mapping.get(&tag).unwrap();
-                // Only visit initialized permissions
+                // Only visit accessed permissions
                 if let Some(p) = perms.get(idx)
                     && let Some(access_kind) = p.permission.protector_end_access()
-                    && p.initialized
+                    && p.accessed
                 {
                     let access_cause = diagnostics::AccessCause::FnExit(access_kind);
                     TreeVisitor { nodes: &mut self.nodes, tag_mapping: &self.tag_mapping, perms }
@@ -1035,7 +1062,7 @@ impl Tree {
 
 impl Node {
     pub fn default_location_state(&self) -> LocationState {
-        LocationState::new_uninit(
+        LocationState::new_non_accessed(
             self.default_initial_perm,
             self.default_initial_idempotent_foreign_access,
         )
@@ -1073,15 +1100,4 @@ impl AccessRelatedness {
     pub fn is_foreign(self) -> bool {
         matches!(self, AccessRelatedness::AncestorAccess | AccessRelatedness::CousinAccess)
     }
-
-    /// Given the AccessRelatedness for the parent node, compute the AccessRelatedness
-    /// for the child node. This function assumes that we propagate away from the initial
-    /// access.
-    pub fn for_child(self) -> Self {
-        use AccessRelatedness::*;
-        match self {
-            AncestorAccess | This => AncestorAccess,
-            StrictChildAccess | CousinAccess => CousinAccess,
-        }
-    }
 }
diff --git a/src/tools/miri/src/borrow_tracker/tree_borrows/tree/tests.rs b/src/tools/miri/src/borrow_tracker/tree_borrows/tree/tests.rs
index dbfa9807e3b..bb3fc2d80b3 100644
--- a/src/tools/miri/src/borrow_tracker/tree_borrows/tree/tests.rs
+++ b/src/tools/miri/src/borrow_tracker/tree_borrows/tree/tests.rs
@@ -9,10 +9,10 @@ use crate::borrow_tracker::tree_borrows::exhaustive::{Exhaustive, precondition};
 impl Exhaustive for LocationState {
     fn exhaustive() -> Box<dyn Iterator<Item = Self>> {
         // We keep `latest_foreign_access` at `None` as that's just a cache.
-        Box::new(<(Permission, bool)>::exhaustive().map(|(permission, initialized)| {
+        Box::new(<(Permission, bool)>::exhaustive().map(|(permission, accessed)| {
             Self {
                 permission,
-                initialized,
+                accessed,
                 idempotent_foreign_access: IdempotentForeignAccess::default(),
             }
         }))
@@ -76,8 +76,8 @@ fn as_protected(b: bool) -> &'static str {
     if b { " (protected)" } else { "" }
 }
 
-fn as_lazy_or_init(b: bool) -> &'static str {
-    if b { "initialized" } else { "lazy" }
+fn as_lazy_or_accessed(b: bool) -> &'static str {
+    if b { "accessed" } else { "lazy" }
 }
 
 /// Test that tree compacting (as performed by the GC) is sound.
@@ -106,7 +106,7 @@ fn tree_compacting_is_sound() {
                         as_foreign_or_child(rel),
                         kind,
                         parent.permission(),
-                        as_lazy_or_init(child.is_initialized()),
+                        as_lazy_or_accessed(child.is_accessed()),
                         child.permission(),
                         as_protected(child_protected),
                         np.permission(),
@@ -122,7 +122,7 @@ fn tree_compacting_is_sound() {
                         as_foreign_or_child(rel),
                         kind,
                         parent.permission(),
-                        as_lazy_or_init(child.is_initialized()),
+                        as_lazy_or_accessed(child.is_accessed()),
                         child.permission(),
                         as_protected(child_protected),
                         nc.permission()
@@ -435,19 +435,19 @@ mod spurious_read {
             Ok(Self { x, y, ..self })
         }
 
-        /// Perform a read on the given pointer if its state is `initialized`.
+        /// Perform a read on the given pointer if its state is `accessed`.
         /// Must be called just after reborrowing a pointer, and just after
         /// removing a protector.
-        fn read_if_initialized(self, ptr: PtrSelector) -> Result<Self, ()> {
-            let initialized = match ptr {
-                PtrSelector::X => self.x.state.initialized,
-                PtrSelector::Y => self.y.state.initialized,
+        fn read_if_accessed(self, ptr: PtrSelector) -> Result<Self, ()> {
+            let accessed = match ptr {
+                PtrSelector::X => self.x.state.accessed,
+                PtrSelector::Y => self.y.state.accessed,
                 PtrSelector::Other =>
                     panic!(
-                        "the `initialized` status of `PtrSelector::Other` is unknown, do not pass it to `read_if_initialized`"
+                        "the `accessed` status of `PtrSelector::Other` is unknown, do not pass it to `read_if_accessed`"
                     ),
             };
-            if initialized {
+            if accessed {
                 self.perform_test_access(&TestAccess { ptr, kind: AccessKind::Read })
             } else {
                 Ok(self)
@@ -457,13 +457,13 @@ mod spurious_read {
         /// Remove the protector of `x`, including the implicit read on function exit.
         fn end_protector_x(self) -> Result<Self, ()> {
             let x = self.x.end_protector();
-            Self { x, ..self }.read_if_initialized(PtrSelector::X)
+            Self { x, ..self }.read_if_accessed(PtrSelector::X)
         }
 
         /// Remove the protector of `y`, including the implicit read on function exit.
         fn end_protector_y(self) -> Result<Self, ()> {
             let y = self.y.end_protector();
-            Self { y, ..self }.read_if_initialized(PtrSelector::Y)
+            Self { y, ..self }.read_if_accessed(PtrSelector::Y)
         }
 
         fn retag_y(self, new_y: LocStateProt) -> Result<Self, ()> {
@@ -473,7 +473,7 @@ mod spurious_read {
             }
             // `xy_rel` changes to "mutually foreign" now: `y` can no longer be a parent of `x`.
             Self { y: new_y, xy_rel: RelPosXY::MutuallyForeign, ..self }
-                .read_if_initialized(PtrSelector::Y)
+                .read_if_accessed(PtrSelector::Y)
         }
 
         fn perform_test_event<RetX, RetY>(self, evt: &TestEvent<RetX, RetY>) -> Result<Self, ()> {
@@ -602,14 +602,14 @@ mod spurious_read {
             xy_rel: RelPosXY::MutuallyForeign,
             x: LocStateProt {
                 // For the tests, the strongest idempotent foreign access does not matter, so we use `Default::default`
-                state: LocationState::new_init(
+                state: LocationState::new_accessed(
                     Permission::new_frozen(),
                     IdempotentForeignAccess::default(),
                 ),
                 prot: true,
             },
             y: LocStateProt {
-                state: LocationState::new_uninit(
+                state: LocationState::new_non_accessed(
                     Permission::new_reserved(/* freeze */ true, /* protected */ true),
                     IdempotentForeignAccess::default(),
                 ),
@@ -650,8 +650,8 @@ mod spurious_read {
             for xy_rel in RelPosXY::exhaustive() {
                 for (x_retag_perm, y_current_perm) in <(LocationState, LocationState)>::exhaustive()
                 {
-                    // We can only do spurious reads for initialized locations anyway.
-                    precondition!(x_retag_perm.initialized);
+                    // We can only do spurious reads for accessed locations anyway.
+                    precondition!(x_retag_perm.accessed);
                     // And `x` just got retagged, so it must be initial.
                     precondition!(x_retag_perm.permission.is_initial());
                     // As stated earlier, `x` is always protected in the patterns we consider here.
@@ -696,7 +696,7 @@ mod spurious_read {
         fn initial_state(&self) -> Result<LocStateProtPair, ()> {
             let (x, y) = self.retag_permissions();
             let state = LocStateProtPair { xy_rel: self.xy_rel, x, y };
-            state.read_if_initialized(PtrSelector::X)
+            state.read_if_accessed(PtrSelector::X)
         }
     }
 
diff --git a/src/tools/miri/src/concurrency/mod.rs b/src/tools/miri/src/concurrency/mod.rs
index 17d0f3f5ff6..aaa3fc85a6c 100644
--- a/src/tools/miri/src/concurrency/mod.rs
+++ b/src/tools/miri/src/concurrency/mod.rs
@@ -8,8 +8,19 @@ pub mod thread;
 mod vector_clock;
 pub mod weak_memory;
 
+// cfg(bootstrap)
+macro_rules! cfg_select_dispatch {
+    ($($tokens:tt)*) => {
+        #[cfg(bootstrap)]
+        cfg_match! { $($tokens)* }
+
+        #[cfg(not(bootstrap))]
+        cfg_select! { $($tokens)* }
+    };
+}
+
 // Import either the real genmc adapter or a dummy module.
-cfg_select! {
+cfg_select_dispatch! {
     feature = "genmc" => {
         mod genmc;
         pub use self::genmc::{GenmcCtx, GenmcConfig};
diff --git a/src/tools/miri/src/concurrency/thread.rs b/src/tools/miri/src/concurrency/thread.rs
index 8aa65e6cb61..ba1436b77b8 100644
--- a/src/tools/miri/src/concurrency/thread.rs
+++ b/src/tools/miri/src/concurrency/thread.rs
@@ -218,34 +218,37 @@ impl<'tcx> Thread<'tcx> {
         }
     }
 
-    /// Return the top user-relevant frame, if there is one.
+    /// Return the top user-relevant frame, if there is one. `skip` indicates how many top frames
+    /// should be skipped.
     /// Note that the choice to return `None` here when there is no user-relevant frame is part of
     /// justifying the optimization that only pushes of user-relevant frames require updating the
     /// `top_user_relevant_frame` field.
-    fn compute_top_user_relevant_frame(&self) -> Option<usize> {
+    fn compute_top_user_relevant_frame(&self, skip: usize) -> Option<usize> {
         self.stack
             .iter()
             .enumerate()
             .rev()
+            .skip(skip)
             .find_map(|(idx, frame)| if frame.extra.is_user_relevant { Some(idx) } else { None })
     }
 
-    /// Re-compute the top user-relevant frame from scratch.
-    pub fn recompute_top_user_relevant_frame(&mut self) {
-        self.top_user_relevant_frame = self.compute_top_user_relevant_frame();
+    /// Re-compute the top user-relevant frame from scratch. `skip` indicates how many top frames
+    /// should be skipped.
+    pub fn recompute_top_user_relevant_frame(&mut self, skip: usize) {
+        self.top_user_relevant_frame = self.compute_top_user_relevant_frame(skip);
     }
 
     /// Set the top user-relevant frame to the given value. Must be equal to what
     /// `get_top_user_relevant_frame` would return!
     pub fn set_top_user_relevant_frame(&mut self, frame_idx: usize) {
-        debug_assert_eq!(Some(frame_idx), self.compute_top_user_relevant_frame());
+        debug_assert_eq!(Some(frame_idx), self.compute_top_user_relevant_frame(0));
         self.top_user_relevant_frame = Some(frame_idx);
     }
 
     /// Returns the topmost frame that is considered user-relevant, or the
     /// top of the stack if there is no such frame, or `None` if the stack is empty.
     pub fn top_user_relevant_frame(&self) -> Option<usize> {
-        debug_assert_eq!(self.top_user_relevant_frame, self.compute_top_user_relevant_frame());
+        debug_assert_eq!(self.top_user_relevant_frame, self.compute_top_user_relevant_frame(0));
         // This can be called upon creation of an allocation. We create allocations while setting up
         // parts of the Rust runtime when we do not have any stack frames yet, so we need to handle
         // empty stacks.
@@ -894,12 +897,17 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
             if tcx.is_foreign_item(def_id) {
                 throw_unsup_format!("foreign thread-local statics are not supported");
             }
+            let params = this.machine.get_default_alloc_params();
             let alloc = this.ctfe_query(|tcx| tcx.eval_static_initializer(def_id))?;
             // We make a full copy of this allocation.
             let mut alloc = alloc.inner().adjust_from_tcx(
                 &this.tcx,
                 |bytes, align| {
-                    interp_ok(MiriAllocBytes::from_bytes(std::borrow::Cow::Borrowed(bytes), align))
+                    interp_ok(MiriAllocBytes::from_bytes(
+                        std::borrow::Cow::Borrowed(bytes),
+                        align,
+                        params,
+                    ))
                 },
                 |ptr| this.global_root_pointer(ptr),
             )?;
diff --git a/src/tools/miri/src/diagnostics.rs b/src/tools/miri/src/diagnostics.rs
index 10570a37e5d..1728a9cfd6d 100644
--- a/src/tools/miri/src/diagnostics.rs
+++ b/src/tools/miri/src/diagnostics.rs
@@ -255,8 +255,7 @@ pub fn report_error<'tcx>(
                 ],
             UnsupportedForeignItem(_) => {
                 vec![
-                    note!("if this is a basic API commonly used on this target, please report an issue with Miri"),
-                    note!("however, note that Miri does not aim to support every FFI function out there; for instance, we will not support APIs for things such as GUIs, scripting languages, or databases"),
+                    note!("this means the program tried to do something Miri does not support; it does not indicate a bug in the program"),
                 ]
             }
             StackedBorrowsUb { help, history, .. } => {
diff --git a/src/tools/miri/src/eval.rs b/src/tools/miri/src/eval.rs
index a90c6ab9d40..8fe034d2582 100644
--- a/src/tools/miri/src/eval.rs
+++ b/src/tools/miri/src/eval.rs
@@ -354,11 +354,10 @@ pub fn create_ecx<'tcx>(
             argvs.push(arg_place.to_ref(&ecx));
         }
         // Make an array with all these pointers, in the Miri memory.
-        let argvs_layout = ecx.layout_of(Ty::new_array(
-            tcx,
-            Ty::new_imm_ptr(tcx, tcx.types.u8),
-            u64::try_from(argvs.len()).unwrap(),
-        ))?;
+        let u8_ptr_type = Ty::new_imm_ptr(tcx, tcx.types.u8);
+        let u8_ptr_ptr_type = Ty::new_imm_ptr(tcx, u8_ptr_type);
+        let argvs_layout =
+            ecx.layout_of(Ty::new_array(tcx, u8_ptr_type, u64::try_from(argvs.len()).unwrap()))?;
         let argvs_place = ecx.allocate(argvs_layout, MiriMemoryKind::Machine.into())?;
         for (idx, arg) in argvs.into_iter().enumerate() {
             let place = ecx.project_field(&argvs_place, idx)?;
@@ -373,10 +372,8 @@ pub fn create_ecx<'tcx>(
             ecx.mark_immutable(&argc_place);
             ecx.machine.argc = Some(argc_place.ptr());
 
-            let argv_place = ecx.allocate(
-                ecx.layout_of(Ty::new_imm_ptr(tcx, tcx.types.unit))?,
-                MiriMemoryKind::Machine.into(),
-            )?;
+            let argv_place =
+                ecx.allocate(ecx.layout_of(u8_ptr_ptr_type)?, MiriMemoryKind::Machine.into())?;
             ecx.write_pointer(argvs_place.ptr(), &argv_place)?;
             ecx.mark_immutable(&argv_place);
             ecx.machine.argv = Some(argv_place.ptr());
@@ -398,7 +395,9 @@ pub fn create_ecx<'tcx>(
             }
             ecx.mark_immutable(&cmd_place);
         }
-        ecx.mplace_to_ref(&argvs_place)?
+        let imm = argvs_place.to_ref(&ecx);
+        let layout = ecx.layout_of(u8_ptr_ptr_type)?;
+        ImmTy::from_immediate(imm, layout)
     };
 
     // Return place (in static memory so that it does not count as leak).
diff --git a/src/tools/miri/src/helpers.rs b/src/tools/miri/src/helpers.rs
index 2032a5a5aa3..20ea239b7e5 100644
--- a/src/tools/miri/src/helpers.rs
+++ b/src/tools/miri/src/helpers.rs
@@ -470,7 +470,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
             caller_fn_abi,
             &args.iter().map(|a| FnArg::Copy(a.clone().into())).collect::<Vec<_>>(),
             /*with_caller_location*/ false,
-            &dest,
+            &dest.into(),
             stack_pop,
         )
     }
diff --git a/src/tools/miri/src/intrinsics/atomic.rs b/src/tools/miri/src/intrinsics/atomic.rs
index 2eb8086f578..a61226eeed9 100644
--- a/src/tools/miri/src/intrinsics/atomic.rs
+++ b/src/tools/miri/src/intrinsics/atomic.rs
@@ -1,4 +1,5 @@
 use rustc_middle::mir::BinOp;
+use rustc_middle::ty::AtomicOrdering;
 use rustc_middle::{mir, ty};
 
 use self::helpers::check_intrinsic_arg_count;
@@ -19,6 +20,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     fn emulate_atomic_intrinsic(
         &mut self,
         intrinsic_name: &str,
+        generic_args: ty::GenericArgsRef<'tcx>,
         args: &[OpTy<'tcx>],
         dest: &MPlaceTy<'tcx>,
     ) -> InterpResult<'tcx, EmulateItemResult> {
@@ -35,6 +37,15 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
             }
         }
 
+        fn read_ord_const_generic(o: AtomicOrdering) -> AtomicReadOrd {
+            match o {
+                AtomicOrdering::SeqCst => AtomicReadOrd::SeqCst,
+                AtomicOrdering::Acquire => AtomicReadOrd::Acquire,
+                AtomicOrdering::Relaxed => AtomicReadOrd::Relaxed,
+                _ => panic!("invalid read ordering `{o:?}`"),
+            }
+        }
+
         fn write_ord(ord: &str) -> AtomicWriteOrd {
             match ord {
                 "seqcst" => AtomicWriteOrd::SeqCst,
@@ -66,7 +77,15 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
         }
 
         match &*intrinsic_structure {
-            ["load", ord] => this.atomic_load(args, dest, read_ord(ord))?,
+            // New-style intrinsics that use const generics
+            ["load"] => {
+                let ordering = generic_args.const_at(1).to_value();
+                let ordering =
+                    ordering.valtree.unwrap_branch()[0].unwrap_leaf().to_atomic_ordering();
+                this.atomic_load(args, dest, read_ord_const_generic(ordering))?;
+            }
+
+            // Old-style intrinsics that have the ordering in the intrinsic name
             ["store", ord] => this.atomic_store(args, write_ord(ord))?,
 
             ["fence", ord] => this.atomic_fence_intrinsic(args, fence_ord(ord))?,
diff --git a/src/tools/miri/src/intrinsics/mod.rs b/src/tools/miri/src/intrinsics/mod.rs
index 982fbc31811..a4882a20148 100644
--- a/src/tools/miri/src/intrinsics/mod.rs
+++ b/src/tools/miri/src/intrinsics/mod.rs
@@ -22,7 +22,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
         &mut self,
         instance: ty::Instance<'tcx>,
         args: &[OpTy<'tcx>],
-        dest: &MPlaceTy<'tcx>,
+        dest: &PlaceTy<'tcx>,
         ret: Option<mir::BasicBlock>,
         unwind: mir::UnwindAction,
     ) -> InterpResult<'tcx, Option<ty::Instance<'tcx>>> {
@@ -45,7 +45,10 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
         let intrinsic_name = this.tcx.item_name(instance.def_id());
         let intrinsic_name = intrinsic_name.as_str();
 
-        match this.emulate_intrinsic_by_name(intrinsic_name, instance.args, args, dest, ret)? {
+        // FIXME: avoid allocating memory
+        let dest = this.force_allocation(dest)?;
+
+        match this.emulate_intrinsic_by_name(intrinsic_name, instance.args, args, &dest, ret)? {
             EmulateItemResult::NotSupported => {
                 // We haven't handled the intrinsic, let's see if we can use a fallback body.
                 if this.tcx.intrinsic(instance.def_id()).unwrap().must_be_overridden {
@@ -94,7 +97,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
         let this = self.eval_context_mut();
 
         if let Some(name) = intrinsic_name.strip_prefix("atomic_") {
-            return this.emulate_atomic_intrinsic(name, args, dest);
+            return this.emulate_atomic_intrinsic(name, generic_args, args, dest);
         }
         if let Some(name) = intrinsic_name.strip_prefix("simd_") {
             return this.emulate_simd_intrinsic(name, generic_args, args, dest);
@@ -156,67 +159,6 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
                 this.write_scalar(Scalar::from_bool(branch), dest)?;
             }
 
-            "floorf16" | "ceilf16" | "truncf16" | "roundf16" | "round_ties_even_f16" => {
-                let [f] = check_intrinsic_arg_count(args)?;
-                let f = this.read_scalar(f)?.to_f16()?;
-                let mode = match intrinsic_name {
-                    "floorf16" => Round::TowardNegative,
-                    "ceilf16" => Round::TowardPositive,
-                    "truncf16" => Round::TowardZero,
-                    "roundf16" => Round::NearestTiesToAway,
-                    "round_ties_even_f16" => Round::NearestTiesToEven,
-                    _ => bug!(),
-                };
-                let res = f.round_to_integral(mode).value;
-                let res = this.adjust_nan(res, &[f]);
-                this.write_scalar(res, dest)?;
-            }
-            "floorf32" | "ceilf32" | "truncf32" | "roundf32" | "round_ties_even_f32" => {
-                let [f] = check_intrinsic_arg_count(args)?;
-                let f = this.read_scalar(f)?.to_f32()?;
-                let mode = match intrinsic_name {
-                    "floorf32" => Round::TowardNegative,
-                    "ceilf32" => Round::TowardPositive,
-                    "truncf32" => Round::TowardZero,
-                    "roundf32" => Round::NearestTiesToAway,
-                    "round_ties_even_f32" => Round::NearestTiesToEven,
-                    _ => bug!(),
-                };
-                let res = f.round_to_integral(mode).value;
-                let res = this.adjust_nan(res, &[f]);
-                this.write_scalar(res, dest)?;
-            }
-            "floorf64" | "ceilf64" | "truncf64" | "roundf64" | "round_ties_even_f64" => {
-                let [f] = check_intrinsic_arg_count(args)?;
-                let f = this.read_scalar(f)?.to_f64()?;
-                let mode = match intrinsic_name {
-                    "floorf64" => Round::TowardNegative,
-                    "ceilf64" => Round::TowardPositive,
-                    "truncf64" => Round::TowardZero,
-                    "roundf64" => Round::NearestTiesToAway,
-                    "round_ties_even_f64" => Round::NearestTiesToEven,
-                    _ => bug!(),
-                };
-                let res = f.round_to_integral(mode).value;
-                let res = this.adjust_nan(res, &[f]);
-                this.write_scalar(res, dest)?;
-            }
-            "floorf128" | "ceilf128" | "truncf128" | "roundf128" | "round_ties_even_f128" => {
-                let [f] = check_intrinsic_arg_count(args)?;
-                let f = this.read_scalar(f)?.to_f128()?;
-                let mode = match intrinsic_name {
-                    "floorf128" => Round::TowardNegative,
-                    "ceilf128" => Round::TowardPositive,
-                    "truncf128" => Round::TowardZero,
-                    "roundf128" => Round::NearestTiesToAway,
-                    "round_ties_even_f128" => Round::NearestTiesToEven,
-                    _ => bug!(),
-                };
-                let res = f.round_to_integral(mode).value;
-                let res = this.adjust_nan(res, &[f]);
-                this.write_scalar(res, dest)?;
-            }
-
             "sqrtf32" => {
                 let [f] = check_intrinsic_arg_count(args)?;
                 let f = this.read_scalar(f)?.to_f32()?;
diff --git a/src/tools/miri/src/lib.rs b/src/tools/miri/src/lib.rs
index 9d663ca9edf..51ec19af52a 100644
--- a/src/tools/miri/src/lib.rs
+++ b/src/tools/miri/src/lib.rs
@@ -1,5 +1,6 @@
+#![cfg_attr(bootstrap, feature(cfg_match))]
+#![cfg_attr(not(bootstrap), feature(cfg_select))]
 #![feature(rustc_private)]
-#![feature(cfg_select)]
 #![feature(float_gamma)]
 #![feature(float_erf)]
 #![feature(map_try_insert)]
@@ -11,6 +12,7 @@
 #![feature(nonzero_ops)]
 #![feature(strict_overflow_ops)]
 #![feature(pointer_is_aligned_to)]
+#![feature(ptr_metadata)]
 #![feature(unqualified_local_imports)]
 #![feature(derive_coerce_pointee)]
 #![feature(arbitrary_self_types)]
@@ -69,8 +71,8 @@ extern crate rustc_target;
 #[allow(unused_extern_crates)]
 extern crate rustc_driver;
 
+mod alloc;
 mod alloc_addresses;
-mod alloc_bytes;
 mod borrow_tracker;
 mod clock;
 mod concurrency;
@@ -105,8 +107,8 @@ pub type OpTy<'tcx> = interpret::OpTy<'tcx, machine::Provenance>;
 pub type PlaceTy<'tcx> = interpret::PlaceTy<'tcx, machine::Provenance>;
 pub type MPlaceTy<'tcx> = interpret::MPlaceTy<'tcx, machine::Provenance>;
 
+pub use crate::alloc::MiriAllocBytes;
 pub use crate::alloc_addresses::{EvalContextExt as _, ProvenanceMode};
-pub use crate::alloc_bytes::MiriAllocBytes;
 pub use crate::borrow_tracker::stacked_borrows::{
     EvalContextExt as _, Item, Permission, Stack, Stacks,
 };
diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs
index f75adffd950..15b3653d7ae 100644
--- a/src/tools/miri/src/machine.rs
+++ b/src/tools/miri/src/machine.rs
@@ -532,6 +532,10 @@ pub struct MiriMachine<'tcx> {
     /// Needs to be queried by ptr_to_int, hence needs interior mutability.
     pub(crate) rng: RefCell<StdRng>,
 
+    /// The allocator used for the machine's `AllocBytes` in native-libs mode.
+    #[cfg(target_os = "linux")]
+    pub(crate) allocator: Option<Rc<RefCell<crate::alloc::isolated_alloc::IsolatedAlloc>>>,
+
     /// The allocation IDs to report when they are being allocated
     /// (helps for debugging memory leaks and use after free bugs).
     tracked_alloc_ids: FxHashSet<AllocId>,
@@ -715,6 +719,10 @@ impl<'tcx> MiriMachine<'tcx> {
             local_crates,
             extern_statics: FxHashMap::default(),
             rng: RefCell::new(rng),
+            #[cfg(target_os = "linux")]
+            allocator: if config.native_lib.is_some() {
+                Some(Rc::new(RefCell::new(crate::alloc::isolated_alloc::IsolatedAlloc::new())))
+            } else { None },
             tracked_alloc_ids: config.tracked_alloc_ids.clone(),
             track_alloc_accesses: config.track_alloc_accesses,
             check_alignment: config.check_alignment,
@@ -917,6 +925,8 @@ impl VisitProvenance for MiriMachine<'_> {
             backtrace_style: _,
             local_crates: _,
             rng: _,
+            #[cfg(target_os = "linux")]
+            allocator: _,
             tracked_alloc_ids: _,
             track_alloc_accesses: _,
             check_alignment: _,
@@ -1115,7 +1125,7 @@ impl<'tcx> Machine<'tcx> for MiriMachine<'tcx> {
         instance: ty::Instance<'tcx>,
         abi: &FnAbi<'tcx, Ty<'tcx>>,
         args: &[FnArg<'tcx, Provenance>],
-        dest: &MPlaceTy<'tcx>,
+        dest: &PlaceTy<'tcx>,
         ret: Option<mir::BasicBlock>,
         unwind: mir::UnwindAction,
     ) -> InterpResult<'tcx, Option<(&'tcx mir::Body<'tcx>, ty::Instance<'tcx>)>> {
@@ -1142,7 +1152,7 @@ impl<'tcx> Machine<'tcx> for MiriMachine<'tcx> {
         fn_val: DynSym,
         abi: &FnAbi<'tcx, Ty<'tcx>>,
         args: &[FnArg<'tcx, Provenance>],
-        dest: &MPlaceTy<'tcx>,
+        dest: &PlaceTy<'tcx>,
         ret: Option<mir::BasicBlock>,
         unwind: mir::UnwindAction,
     ) -> InterpResult<'tcx> {
@@ -1155,7 +1165,7 @@ impl<'tcx> Machine<'tcx> for MiriMachine<'tcx> {
         ecx: &mut MiriInterpCx<'tcx>,
         instance: ty::Instance<'tcx>,
         args: &[OpTy<'tcx>],
-        dest: &MPlaceTy<'tcx>,
+        dest: &PlaceTy<'tcx>,
         ret: Option<mir::BasicBlock>,
         unwind: mir::UnwindAction,
     ) -> InterpResult<'tcx, Option<ty::Instance<'tcx>>> {
@@ -1634,15 +1644,21 @@ impl<'tcx> Machine<'tcx> for MiriMachine<'tcx> {
         interp_ok(())
     }
 
-    fn before_stack_pop(
-        ecx: &InterpCx<'tcx, Self>,
-        frame: &Frame<'tcx, Self::Provenance, Self::FrameExtra>,
-    ) -> InterpResult<'tcx> {
+    fn before_stack_pop(ecx: &mut InterpCx<'tcx, Self>) -> InterpResult<'tcx> {
+        let frame = ecx.frame();
         // We want this *before* the return value copy, because the return place itself is protected
-        // until we do `end_call` here.
+        // until we do `on_stack_pop` here, and we need to un-protect it to copy the return value.
         if ecx.machine.borrow_tracker.is_some() {
             ecx.on_stack_pop(frame)?;
         }
+        if frame.extra.is_user_relevant {
+            // All that we store is whether or not the frame we just removed is local, so now we
+            // have no idea where the next topmost local frame is. So we recompute it.
+            // (If this ever becomes a bottleneck, we could have `push` store the previous
+            // user-relevant frame and restore that here.)
+            // We have to skip the frame that is just being popped.
+            ecx.active_thread_mut().recompute_top_user_relevant_frame(/* skip */ 1);
+        }
         // tracing-tree can autoamtically annotate scope changes, but it gets very confused by our
         // concurrency and what it prints is just plain wrong. So we print our own information
         // instead. (Cc https://github.com/rust-lang/miri/issues/2266)
@@ -1656,15 +1672,8 @@ impl<'tcx> Machine<'tcx> for MiriMachine<'tcx> {
         frame: Frame<'tcx, Provenance, FrameExtra<'tcx>>,
         unwinding: bool,
     ) -> InterpResult<'tcx, ReturnAction> {
-        if frame.extra.is_user_relevant {
-            // All that we store is whether or not the frame we just removed is local, so now we
-            // have no idea where the next topmost local frame is. So we recompute it.
-            // (If this ever becomes a bottleneck, we could have `push` store the previous
-            // user-relevant frame and restore that here.)
-            ecx.active_thread_mut().recompute_top_user_relevant_frame();
-        }
         let res = {
-            // Move `frame`` into a sub-scope so we control when it will be dropped.
+            // Move `frame` into a sub-scope so we control when it will be dropped.
             let mut frame = frame;
             let timing = frame.extra.timing.take();
             let res = ecx.handle_stack_pop_unwind(frame.extra, unwinding);
@@ -1776,7 +1785,7 @@ impl<'tcx> Machine<'tcx> for MiriMachine<'tcx> {
             let is_generic = instance
                 .args
                 .into_iter()
-                .any(|kind| !matches!(kind.unpack(), ty::GenericArgKind::Lifetime(_)));
+                .any(|arg| !matches!(arg.kind(), ty::GenericArgKind::Lifetime(_)));
             let can_be_inlined = matches!(
                 ecx.tcx.sess.opts.unstable_opts.cross_crate_inline_threshold,
                 InliningThreshold::Always
@@ -1804,6 +1813,18 @@ impl<'tcx> Machine<'tcx> for MiriMachine<'tcx> {
     ) -> Cow<'e, RangeSet> {
         Cow::Borrowed(ecx.machine.union_data_ranges.entry(ty).or_insert_with(compute_range))
     }
+
+    fn get_default_alloc_params(&self) -> <Self::Bytes as AllocBytes>::AllocParams {
+        use crate::alloc::MiriAllocParams;
+
+        #[cfg(target_os = "linux")]
+        match &self.allocator {
+            Some(alloc) => MiriAllocParams::Isolated(alloc.clone()),
+            None => MiriAllocParams::Global,
+        }
+        #[cfg(not(target_os = "linux"))]
+        MiriAllocParams::Global
+    }
 }
 
 /// Trait for callbacks handling asynchronous machine operations.
diff --git a/src/tools/miri/src/range_map.rs b/src/tools/miri/src/range_map.rs
index 2c2484cd0bc..29a5a8537a4 100644
--- a/src/tools/miri/src/range_map.rs
+++ b/src/tools/miri/src/range_map.rs
@@ -31,6 +31,11 @@ impl<T> RangeMap<T> {
         RangeMap { v }
     }
 
+    pub fn size(&self) -> Size {
+        let size = self.v.last().map(|x| x.range.end).unwrap_or(0);
+        Size::from_bytes(size)
+    }
+
     /// Finds the index containing the given offset.
     fn find_offset(&self, offset: u64) -> usize {
         self.v
@@ -71,10 +76,7 @@ impl<T> RangeMap<T> {
         };
         // The first offset that is not included any more.
         let end = offset + len;
-        assert!(
-            end <= self.v.last().unwrap().range.end,
-            "iterating beyond the bounds of this RangeMap"
-        );
+        assert!(end <= self.size().bytes(), "iterating beyond the bounds of this RangeMap");
         slice
             .iter()
             .take_while(move |elem| elem.range.start < end)
@@ -327,4 +329,16 @@ mod tests {
         let map = RangeMap::<i32>::new(Size::from_bytes(20), -1);
         let _ = map.iter(Size::from_bytes(11), Size::from_bytes(11));
     }
+
+    #[test]
+    fn empty_map_iter() {
+        let map = RangeMap::<i32>::new(Size::from_bytes(0), -1);
+        let _ = map.iter(Size::from_bytes(0), Size::from_bytes(0));
+    }
+
+    #[test]
+    fn empty_map_iter_mut() {
+        let mut map = RangeMap::<i32>::new(Size::from_bytes(0), -1);
+        let _ = map.iter_mut(Size::from_bytes(0), Size::from_bytes(0));
+    }
 }
diff --git a/src/tools/miri/src/shims/files.rs b/src/tools/miri/src/shims/files.rs
index 31142431247..606d1ffbea6 100644
--- a/src/tools/miri/src/shims/files.rs
+++ b/src/tools/miri/src/shims/files.rs
@@ -202,6 +202,20 @@ pub trait FileDescription: std::fmt::Debug + FileDescriptionExt {
     fn as_unix<'tcx>(&self, _ecx: &MiriInterpCx<'tcx>) -> &dyn UnixFileDescription {
         panic!("Not a unix file descriptor: {}", self.name());
     }
+
+    /// Implementation of fcntl(F_GETFL) for this FD.
+    fn get_flags<'tcx>(&self, _ecx: &mut MiriInterpCx<'tcx>) -> InterpResult<'tcx, Scalar> {
+        throw_unsup_format!("fcntl: {} is not supported for F_GETFL", self.name());
+    }
+
+    /// Implementation of fcntl(F_SETFL) for this FD.
+    fn set_flags<'tcx>(
+        &self,
+        _flag: i32,
+        _ecx: &mut MiriInterpCx<'tcx>,
+    ) -> InterpResult<'tcx, Scalar> {
+        throw_unsup_format!("fcntl: {} is not supported for F_SETFL", self.name());
+    }
 }
 
 impl FileDescription for io::Stdin {
diff --git a/src/tools/miri/src/shims/foreign_items.rs b/src/tools/miri/src/shims/foreign_items.rs
index 17eb697eaf2..ae04ca018ab 100644
--- a/src/tools/miri/src/shims/foreign_items.rs
+++ b/src/tools/miri/src/shims/foreign_items.rs
@@ -43,7 +43,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
         link_name: Symbol,
         abi: &FnAbi<'tcx, Ty<'tcx>>,
         args: &[OpTy<'tcx>],
-        dest: &MPlaceTy<'tcx>,
+        dest: &PlaceTy<'tcx>,
         ret: Option<mir::BasicBlock>,
         unwind: mir::UnwindAction,
     ) -> InterpResult<'tcx, Option<(&'tcx mir::Body<'tcx>, ty::Instance<'tcx>)>> {
@@ -69,8 +69,11 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
             _ => {}
         }
 
+        // FIXME: avoid allocating memory
+        let dest = this.force_allocation(dest)?;
+
         // The rest either implements the logic, or falls back to `lookup_exported_symbol`.
-        match this.emulate_foreign_item_inner(link_name, abi, args, dest)? {
+        match this.emulate_foreign_item_inner(link_name, abi, args, &dest)? {
             EmulateItemResult::NeedsReturn => {
                 trace!("{:?}", this.dump_place(&dest.clone().into()));
                 this.return_to_block(ret)?;
@@ -111,7 +114,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
         sym: DynSym,
         abi: &FnAbi<'tcx, Ty<'tcx>>,
         args: &[OpTy<'tcx>],
-        dest: &MPlaceTy<'tcx>,
+        dest: &PlaceTy<'tcx>,
         ret: Option<mir::BasicBlock>,
         unwind: mir::UnwindAction,
     ) -> InterpResult<'tcx> {
diff --git a/src/tools/miri/src/shims/unix/fd.rs b/src/tools/miri/src/shims/unix/fd.rs
index 156814a26fa..71102d9f2f3 100644
--- a/src/tools/miri/src/shims/unix/fd.rs
+++ b/src/tools/miri/src/shims/unix/fd.rs
@@ -141,6 +141,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
         let f_getfd = this.eval_libc_i32("F_GETFD");
         let f_dupfd = this.eval_libc_i32("F_DUPFD");
         let f_dupfd_cloexec = this.eval_libc_i32("F_DUPFD_CLOEXEC");
+        let f_getfl = this.eval_libc_i32("F_GETFL");
+        let f_setfl = this.eval_libc_i32("F_SETFL");
 
         // We only support getting the flags for a descriptor.
         match cmd {
@@ -175,6 +177,25 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
                     this.set_last_error_and_return_i32(LibcError("EBADF"))
                 }
             }
+            cmd if cmd == f_getfl => {
+                // Check if this is a valid open file descriptor.
+                let Some(fd) = this.machine.fds.get(fd_num) else {
+                    return this.set_last_error_and_return_i32(LibcError("EBADF"));
+                };
+
+                fd.get_flags(this)
+            }
+            cmd if cmd == f_setfl => {
+                // Check if this is a valid open file descriptor.
+                let Some(fd) = this.machine.fds.get(fd_num) else {
+                    return this.set_last_error_and_return_i32(LibcError("EBADF"));
+                };
+
+                let [flag] = check_min_vararg_count("fcntl(fd, F_SETFL, ...)", varargs)?;
+                let flag = this.read_scalar(flag)?.to_i32()?;
+
+                fd.set_flags(flag, this)
+            }
             cmd if this.tcx.sess.target.os == "macos"
                 && cmd == this.eval_libc_i32("F_FULLFSYNC") =>
             {
diff --git a/src/tools/miri/src/shims/unix/fs.rs b/src/tools/miri/src/shims/unix/fs.rs
index 347930c52f2..31cb269059c 100644
--- a/src/tools/miri/src/shims/unix/fs.rs
+++ b/src/tools/miri/src/shims/unix/fs.rs
@@ -89,8 +89,19 @@ impl UnixFileDescription for FileHandle {
         communicate_allowed: bool,
         op: FlockOp,
     ) -> InterpResult<'tcx, io::Result<()>> {
+        // cfg(bootstrap)
+        macro_rules! cfg_select_dispatch {
+            ($($tokens:tt)*) => {
+                #[cfg(bootstrap)]
+                cfg_match! { $($tokens)* }
+
+                #[cfg(not(bootstrap))]
+                cfg_select! { $($tokens)* }
+            };
+        }
+
         assert!(communicate_allowed, "isolation should have prevented even opening a file");
-        cfg_select! {
+        cfg_select_dispatch! {
             all(target_family = "unix", not(target_os = "solaris")) => {
                 use std::os::fd::AsRawFd;
 
diff --git a/src/tools/miri/src/shims/unix/unnamed_socket.rs b/src/tools/miri/src/shims/unix/unnamed_socket.rs
index 135d8f6bee7..817ddd7954d 100644
--- a/src/tools/miri/src/shims/unix/unnamed_socket.rs
+++ b/src/tools/miri/src/shims/unix/unnamed_socket.rs
@@ -20,6 +20,16 @@ use crate::*;
 /// be configured in the real system.
 const MAX_SOCKETPAIR_BUFFER_CAPACITY: usize = 212992;
 
+#[derive(Debug, PartialEq)]
+enum AnonSocketType {
+    // Either end of the socketpair fd.
+    Socketpair,
+    // Read end of the pipe.
+    PipeRead,
+    // Write end of the pipe.
+    PipeWrite,
+}
+
 /// One end of a pair of connected unnamed sockets.
 #[derive(Debug)]
 struct AnonSocket {
@@ -40,7 +50,10 @@ struct AnonSocket {
     /// A list of thread ids blocked because the buffer was full.
     /// Once another thread reads some bytes, these threads will be unblocked.
     blocked_write_tid: RefCell<Vec<ThreadId>>,
-    is_nonblock: bool,
+    /// Whether this fd is non-blocking or not.
+    is_nonblock: Cell<bool>,
+    // Differentiate between different AnonSocket fd types.
+    fd_type: AnonSocketType,
 }
 
 #[derive(Debug)]
@@ -63,7 +76,10 @@ impl AnonSocket {
 
 impl FileDescription for AnonSocket {
     fn name(&self) -> &'static str {
-        "socketpair"
+        match self.fd_type {
+            AnonSocketType::Socketpair => "socketpair",
+            AnonSocketType::PipeRead | AnonSocketType::PipeWrite => "pipe",
+        }
     }
 
     fn close<'tcx>(
@@ -110,6 +126,66 @@ impl FileDescription for AnonSocket {
     fn as_unix<'tcx>(&self, _ecx: &MiriInterpCx<'tcx>) -> &dyn UnixFileDescription {
         self
     }
+
+    fn get_flags<'tcx>(&self, ecx: &mut MiriInterpCx<'tcx>) -> InterpResult<'tcx, Scalar> {
+        let mut flags = 0;
+
+        // Get flag for file access mode.
+        // The flag for both socketpair and pipe will remain the same even when the peer
+        // fd is closed, so we need to look at the original type of this socket, not at whether
+        // the peer socket still exists.
+        match self.fd_type {
+            AnonSocketType::Socketpair => {
+                flags |= ecx.eval_libc_i32("O_RDWR");
+            }
+            AnonSocketType::PipeRead => {
+                flags |= ecx.eval_libc_i32("O_RDONLY");
+            }
+            AnonSocketType::PipeWrite => {
+                flags |= ecx.eval_libc_i32("O_WRONLY");
+            }
+        }
+
+        // Get flag for blocking status.
+        if self.is_nonblock.get() {
+            flags |= ecx.eval_libc_i32("O_NONBLOCK");
+        }
+
+        interp_ok(Scalar::from_i32(flags))
+    }
+
+    fn set_flags<'tcx>(
+        &self,
+        mut flag: i32,
+        ecx: &mut MiriInterpCx<'tcx>,
+    ) -> InterpResult<'tcx, Scalar> {
+        // FIXME: File creation flags should be ignored.
+
+        let o_nonblock = ecx.eval_libc_i32("O_NONBLOCK");
+        let o_rdonly = ecx.eval_libc_i32("O_RDONLY");
+        let o_wronly = ecx.eval_libc_i32("O_WRONLY");
+        let o_rdwr = ecx.eval_libc_i32("O_RDWR");
+
+        // O_NONBLOCK flag can be set / unset by user.
+        if flag & o_nonblock == o_nonblock {
+            self.is_nonblock.set(true);
+            flag &= !o_nonblock;
+        } else {
+            self.is_nonblock.set(false);
+        }
+
+        // Ignore all file access mode flags.
+        flag &= !(o_rdonly | o_wronly | o_rdwr);
+
+        // Throw error if there is any unsupported flag.
+        if flag != 0 {
+            throw_unsup_format!(
+                "fcntl: only O_NONBLOCK is supported for F_SETFL on socketpairs and pipes"
+            )
+        }
+
+        interp_ok(Scalar::from_i32(0))
+    }
 }
 
 /// Write to AnonSocket based on the space available and return the written byte size.
@@ -141,7 +217,7 @@ fn anonsocket_write<'tcx>(
     // Let's see if we can write.
     let available_space = MAX_SOCKETPAIR_BUFFER_CAPACITY.strict_sub(writebuf.borrow().buf.len());
     if available_space == 0 {
-        if self_ref.is_nonblock {
+        if self_ref.is_nonblock.get() {
             // Non-blocking socketpair with a full buffer.
             return finish.call(ecx, Err(ErrorKind::WouldBlock.into()));
         } else {
@@ -223,7 +299,7 @@ fn anonsocket_read<'tcx>(
             // Socketpair with no peer and empty buffer.
             // 0 bytes successfully read indicates end-of-file.
             return finish.call(ecx, Ok(0));
-        } else if self_ref.is_nonblock {
+        } else if self_ref.is_nonblock.get() {
             // Non-blocking socketpair with writer and empty buffer.
             // https://linux.die.net/man/2/read
             // EAGAIN or EWOULDBLOCK can be returned for socket,
@@ -407,7 +483,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
             peer_lost_data: Cell::new(false),
             blocked_read_tid: RefCell::new(Vec::new()),
             blocked_write_tid: RefCell::new(Vec::new()),
-            is_nonblock: is_sock_nonblock,
+            is_nonblock: Cell::new(is_sock_nonblock),
+            fd_type: AnonSocketType::Socketpair,
         });
         let fd1 = fds.new_ref(AnonSocket {
             readbuf: Some(RefCell::new(Buffer::new())),
@@ -415,7 +492,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
             peer_lost_data: Cell::new(false),
             blocked_read_tid: RefCell::new(Vec::new()),
             blocked_write_tid: RefCell::new(Vec::new()),
-            is_nonblock: is_sock_nonblock,
+            is_nonblock: Cell::new(is_sock_nonblock),
+            fd_type: AnonSocketType::Socketpair,
         });
 
         // Make the file descriptions point to each other.
@@ -475,7 +553,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
             peer_lost_data: Cell::new(false),
             blocked_read_tid: RefCell::new(Vec::new()),
             blocked_write_tid: RefCell::new(Vec::new()),
-            is_nonblock,
+            is_nonblock: Cell::new(is_nonblock),
+            fd_type: AnonSocketType::PipeRead,
         });
         let fd1 = fds.new_ref(AnonSocket {
             readbuf: None,
@@ -483,7 +562,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
             peer_lost_data: Cell::new(false),
             blocked_read_tid: RefCell::new(Vec::new()),
             blocked_write_tid: RefCell::new(Vec::new()),
-            is_nonblock,
+            is_nonblock: Cell::new(is_nonblock),
+            fd_type: AnonSocketType::PipeWrite,
         });
 
         // Make the file descriptions point to each other.
diff --git a/src/tools/miri/src/shims/windows/foreign_items.rs b/src/tools/miri/src/shims/windows/foreign_items.rs
index 29671eb8149..10f6df67ad4 100644
--- a/src/tools/miri/src/shims/windows/foreign_items.rs
+++ b/src/tools/miri/src/shims/windows/foreign_items.rs
@@ -576,6 +576,14 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
                 let ret = this.WaitForSingleObject(handle, timeout)?;
                 this.write_scalar(ret, dest)?;
             }
+            "GetCurrentProcess" => {
+                let [] = this.check_shim(abi, sys_conv, link_name, args)?;
+
+                this.write_scalar(
+                    Handle::Pseudo(PseudoHandle::CurrentProcess).to_scalar(this),
+                    dest,
+                )?;
+            }
             "GetCurrentThread" => {
                 let [] = this.check_shim(abi, sys_conv, link_name, args)?;
 
@@ -697,6 +705,20 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
                 let res = this.GetStdHandle(which)?;
                 this.write_scalar(res, dest)?;
             }
+            "DuplicateHandle" => {
+                let [src_proc, src_handle, target_proc, target_handle, access, inherit, options] =
+                    this.check_shim(abi, sys_conv, link_name, args)?;
+                let res = this.DuplicateHandle(
+                    src_proc,
+                    src_handle,
+                    target_proc,
+                    target_handle,
+                    access,
+                    inherit,
+                    options,
+                )?;
+                this.write_scalar(res, dest)?;
+            }
             "CloseHandle" => {
                 let [handle] = this.check_shim(abi, sys_conv, link_name, args)?;
 
diff --git a/src/tools/miri/src/shims/windows/handle.rs b/src/tools/miri/src/shims/windows/handle.rs
index 5c04271fac5..1e30bf25ed9 100644
--- a/src/tools/miri/src/shims/windows/handle.rs
+++ b/src/tools/miri/src/shims/windows/handle.rs
@@ -9,6 +9,7 @@ use crate::*;
 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
 pub enum PseudoHandle {
     CurrentThread,
+    CurrentProcess,
 }
 
 /// Miri representation of a Windows `HANDLE`
@@ -23,16 +24,19 @@ pub enum Handle {
 
 impl PseudoHandle {
     const CURRENT_THREAD_VALUE: u32 = 0;
+    const CURRENT_PROCESS_VALUE: u32 = 1;
 
     fn value(self) -> u32 {
         match self {
             Self::CurrentThread => Self::CURRENT_THREAD_VALUE,
+            Self::CurrentProcess => Self::CURRENT_PROCESS_VALUE,
         }
     }
 
     fn from_value(value: u32) -> Option<Self> {
         match value {
             Self::CURRENT_THREAD_VALUE => Some(Self::CurrentThread),
+            Self::CURRENT_PROCESS_VALUE => Some(Self::CurrentProcess),
             _ => None,
         }
     }
@@ -244,6 +248,76 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
         interp_ok(handle.to_scalar(this))
     }
 
+    fn DuplicateHandle(
+        &mut self,
+        src_proc: &OpTy<'tcx>,       // HANDLE
+        src_handle: &OpTy<'tcx>,     // HANDLE
+        target_proc: &OpTy<'tcx>,    // HANDLE
+        target_handle: &OpTy<'tcx>,  // LPHANDLE
+        desired_access: &OpTy<'tcx>, // DWORD
+        inherit: &OpTy<'tcx>,        // BOOL
+        options: &OpTy<'tcx>,        // DWORD
+    ) -> InterpResult<'tcx, Scalar> {
+        // ^ Returns BOOL (i32 on Windows)
+        let this = self.eval_context_mut();
+
+        let src_proc = this.read_handle(src_proc, "DuplicateHandle")?;
+        let src_handle = this.read_handle(src_handle, "DuplicateHandle")?;
+        let target_proc = this.read_handle(target_proc, "DuplicateHandle")?;
+        let target_handle_ptr = this.read_pointer(target_handle)?;
+        // Since we only support DUPLICATE_SAME_ACCESS, this value is ignored, but should be valid
+        let _ = this.read_scalar(desired_access)?.to_u32()?;
+        // We don't support the CreateProcess API, so inheritable or not means nothing.
+        // If we ever add CreateProcess support, this will need to be implemented.
+        let _ = this.read_scalar(inherit)?;
+        let options = this.read_scalar(options)?;
+
+        if src_proc != Handle::Pseudo(PseudoHandle::CurrentProcess) {
+            throw_unsup_format!(
+                "`DuplicateHandle` `hSourceProcessHandle` parameter is not the current process, which is unsupported"
+            );
+        }
+
+        if target_proc != Handle::Pseudo(PseudoHandle::CurrentProcess) {
+            throw_unsup_format!(
+                "`DuplicateHandle` `hSourceProcessHandle` parameter is not the current process, which is unsupported"
+            );
+        }
+
+        if this.ptr_is_null(target_handle_ptr)? {
+            throw_unsup_format!(
+                "`DuplicateHandle` `lpTargetHandle` parameter is null, which is unsupported"
+            );
+        }
+
+        if options != this.eval_windows("c", "DUPLICATE_SAME_ACCESS") {
+            throw_unsup_format!(
+                "`DuplicateHandle` `dwOptions` parameter is not `DUPLICATE_SAME_ACCESS`, which is unsupported"
+            );
+        }
+
+        let new_handle = match src_handle {
+            Handle::File(old_fd_num) => {
+                let Some(fd) = this.machine.fds.get(old_fd_num) else {
+                    this.invalid_handle("DuplicateHandle")?
+                };
+                Handle::File(this.machine.fds.insert(fd))
+            }
+            Handle::Thread(_) => {
+                throw_unsup_format!(
+                    "`DuplicateHandle` called on a thread handle, which is unsupported"
+                );
+            }
+            Handle::Pseudo(pseudo) => Handle::Pseudo(pseudo),
+            Handle::Null | Handle::Invalid => this.invalid_handle("DuplicateHandle")?,
+        };
+
+        let target_place = this.deref_pointer_as(target_handle, this.machine.layouts.usize)?;
+        this.write_scalar(new_handle.to_scalar(this), &target_place)?;
+
+        interp_ok(this.eval_windows("c", "TRUE"))
+    }
+
     fn CloseHandle(&mut self, handle_op: &OpTy<'tcx>) -> InterpResult<'tcx, Scalar> {
         let this = self.eval_context_mut();
 
diff --git a/src/tools/miri/tests/fail-dep/libc/fcntl_fsetfl_while_blocking.rs b/src/tools/miri/tests/fail-dep/libc/fcntl_fsetfl_while_blocking.rs
new file mode 100644
index 00000000000..eef32136a0a
--- /dev/null
+++ b/src/tools/miri/tests/fail-dep/libc/fcntl_fsetfl_while_blocking.rs
@@ -0,0 +1,20 @@
+//@ignore-target: windows # Sockets/pipes are not implemented yet
+//~^ ERROR: deadlock: the evaluated program deadlocked
+//@compile-flags: -Zmiri-deterministic-concurrency
+use std::thread;
+
+/// If an O_NONBLOCK flag is set while the fd is blocking, that fd will not be woken up.
+fn main() {
+    let mut fds = [-1, -1];
+    let res = unsafe { libc::pipe(fds.as_mut_ptr()) };
+    assert_eq!(res, 0);
+    let mut buf: [u8; 5] = [0; 5];
+    let _thread1 = thread::spawn(move || {
+        // Add O_NONBLOCK flag while pipe is still block on read.
+        let res = unsafe { libc::fcntl(fds[0], libc::F_SETFL, libc::O_NONBLOCK) };
+        assert_eq!(res, 0);
+    });
+    // Main thread will block on read.
+    let _res = unsafe { libc::read(fds[0], buf.as_mut_ptr().cast(), buf.len() as libc::size_t) };
+    //~^ ERROR: deadlock: the evaluated program deadlocked
+}
diff --git a/src/tools/miri/tests/fail-dep/libc/fcntl_fsetfl_while_blocking.stderr b/src/tools/miri/tests/fail-dep/libc/fcntl_fsetfl_while_blocking.stderr
new file mode 100644
index 00000000000..9ca5598abae
--- /dev/null
+++ b/src/tools/miri/tests/fail-dep/libc/fcntl_fsetfl_while_blocking.stderr
@@ -0,0 +1,19 @@
+error: deadlock: the evaluated program deadlocked
+   |
+   = note: the evaluated program deadlocked
+   = note: (no span available)
+   = note: BACKTRACE on thread `unnamed-ID`:
+
+error: deadlock: the evaluated program deadlocked
+  --> tests/fail-dep/libc/fcntl_fsetfl_while_blocking.rs:LL:CC
+   |
+LL |     let _res = unsafe { libc::read(fds[0], buf.as_mut_ptr().cast(), buf.len() as libc::size_t) };
+   |                                                                                              ^ the evaluated program deadlocked
+   |
+   = note: BACKTRACE:
+   = note: inside `main` at tests/fail-dep/libc/fcntl_fsetfl_while_blocking.rs:LL:CC
+
+note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
+
+error: aborting due to 2 previous errors
+
diff --git a/src/tools/miri/tests/fail-dep/libc/unsupported_incomplete_function.stderr b/src/tools/miri/tests/fail-dep/libc/unsupported_incomplete_function.stderr
index a92a97cef3b..52a93ab263d 100644
--- a/src/tools/miri/tests/fail-dep/libc/unsupported_incomplete_function.stderr
+++ b/src/tools/miri/tests/fail-dep/libc/unsupported_incomplete_function.stderr
@@ -4,8 +4,7 @@ error: unsupported operation: can't call foreign function `signal` on $OS
 LL |         libc::signal(libc::SIGPIPE, libc::SIG_IGN);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't call foreign function `signal` on $OS
    |
-   = help: if this is a basic API commonly used on this target, please report an issue with Miri
-   = help: however, note that Miri does not aim to support every FFI function out there; for instance, we will not support APIs for things such as GUIs, scripting languages, or databases
+   = help: this means the program tried to do something Miri does not support; it does not indicate a bug in the program
    = note: BACKTRACE:
    = note: inside `main` at tests/fail-dep/libc/unsupported_incomplete_function.rs:LL:CC
 
diff --git a/src/tools/miri/tests/fail/alloc/no_global_allocator.stderr b/src/tools/miri/tests/fail/alloc/no_global_allocator.stderr
index 541af64b894..e80a3646714 100644
--- a/src/tools/miri/tests/fail/alloc/no_global_allocator.stderr
+++ b/src/tools/miri/tests/fail/alloc/no_global_allocator.stderr
@@ -4,8 +4,7 @@ error: unsupported operation: can't call foreign function `__rust_alloc` on $OS
 LL |         __rust_alloc(1, 1);
    |         ^^^^^^^^^^^^^^^^^^ can't call foreign function `__rust_alloc` on $OS
    |
-   = help: if this is a basic API commonly used on this target, please report an issue with Miri
-   = help: however, note that Miri does not aim to support every FFI function out there; for instance, we will not support APIs for things such as GUIs, scripting languages, or databases
+   = help: this means the program tried to do something Miri does not support; it does not indicate a bug in the program
    = note: BACKTRACE:
    = note: inside `miri_start` at tests/fail/alloc/no_global_allocator.rs:LL:CC
 
diff --git a/src/tools/miri/tests/fail/data_race/stack_pop_race.rs b/src/tools/miri/tests/fail/data_race/stack_pop_race.rs
index 5138bcbf8f7..e7632d43126 100644
--- a/src/tools/miri/tests/fail/data_race/stack_pop_race.rs
+++ b/src/tools/miri/tests/fail/data_race/stack_pop_race.rs
@@ -8,7 +8,7 @@ struct MakeSend(*const i32);
 unsafe impl Send for MakeSend {}
 
 fn main() {
-    race(0);
+    race(0); //~ERROR: Data race detected between (1) non-atomic read on thread `unnamed-1` and (2) deallocation on thread `main`
 }
 
 // Using an argument for the ptr to point to, since those do not get StorageDead.
@@ -22,5 +22,4 @@ fn race(local: i32) {
     thread::yield_now();
     // Deallocating the local (when `main` returns)
     // races with the read in the other thread.
-    // Make sure the error points at this function's end, not just the call site.
-} //~ERROR: Data race detected between (1) non-atomic read on thread `unnamed-1` and (2) deallocation on thread `main`
+}
diff --git a/src/tools/miri/tests/fail/data_race/stack_pop_race.stderr b/src/tools/miri/tests/fail/data_race/stack_pop_race.stderr
index 643426aba99..721b7563044 100644
--- a/src/tools/miri/tests/fail/data_race/stack_pop_race.stderr
+++ b/src/tools/miri/tests/fail/data_race/stack_pop_race.stderr
@@ -1,8 +1,8 @@
 error: Undefined Behavior: Data race detected between (1) non-atomic read on thread `unnamed-ID` and (2) deallocation on thread `main` at ALLOC. (2) just happened here
   --> tests/fail/data_race/stack_pop_race.rs:LL:CC
    |
-LL | }
-   |  ^ Data race detected between (1) non-atomic read on thread `unnamed-ID` and (2) deallocation on thread `main` at ALLOC. (2) just happened here
+LL |     race(0);
+   |     ^^^^^^^ Data race detected between (1) non-atomic read on thread `unnamed-ID` and (2) deallocation on thread `main` at ALLOC. (2) just happened here
    |
 help: and (1) occurred earlier here
   --> tests/fail/data_race/stack_pop_race.rs:LL:CC
@@ -12,12 +12,7 @@ LL |         let _val = unsafe { *ptr.0 };
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
    = note: BACKTRACE (of the first span):
-   = note: inside `race` at tests/fail/data_race/stack_pop_race.rs:LL:CC
-note: inside `main`
-  --> tests/fail/data_race/stack_pop_race.rs:LL:CC
-   |
-LL |     race(0);
-   |     ^^^^^^^
+   = note: inside `main` at tests/fail/data_race/stack_pop_race.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
 
diff --git a/src/tools/miri/tests/fail/ptr_swap_nonoverlapping.stderr b/src/tools/miri/tests/fail/ptr_swap_nonoverlapping.stderr
index f57487e3ffe..b4dadeecaa8 100644
--- a/src/tools/miri/tests/fail/ptr_swap_nonoverlapping.stderr
+++ b/src/tools/miri/tests/fail/ptr_swap_nonoverlapping.stderr
@@ -1,5 +1,5 @@
 
-thread 'main' panicked at RUSTLIB/core/src/panicking.rs:LL:CC:
+thread 'main' panicked at tests/fail/ptr_swap_nonoverlapping.rs:LL:CC:
 unsafe precondition(s) violated: ptr::swap_nonoverlapping requires that both pointer arguments are aligned and non-null and the specified memory ranges do not overlap
 
 This indicates a bug in the program. This Undefined Behavior check is optional, and cannot be relied on for safety.
@@ -18,9 +18,6 @@ LL | ABORT()
    = note: inside closure at RUSTLIB/std/src/panicking.rs:LL:CC
    = note: inside `std::sys::backtrace::__rust_end_short_backtrace::<{closure@std::panicking::begin_panic_handler::{closure#0}}, !>` at RUSTLIB/std/src/sys/backtrace.rs:LL:CC
    = note: inside `std::panicking::begin_panic_handler` at RUSTLIB/std/src/panicking.rs:LL:CC
-   = note: inside `core::panicking::panic_nounwind` at RUSTLIB/core/src/panicking.rs:LL:CC
-   = note: inside `std::ptr::swap_nonoverlapping::precondition_check` at RUSTLIB/core/src/ub_checks.rs:LL:CC
-   = note: inside `std::ptr::swap_nonoverlapping::<usize>` at RUSTLIB/core/src/ub_checks.rs:LL:CC
 note: inside `main`
   --> tests/fail/ptr_swap_nonoverlapping.rs:LL:CC
    |
diff --git a/src/tools/miri/tests/fail/tail_calls/dangling-local-var.stderr b/src/tools/miri/tests/fail/tail_calls/dangling-local-var.stderr
index 33e1e53ea06..15f73c8a9ae 100644
--- a/src/tools/miri/tests/fail/tail_calls/dangling-local-var.stderr
+++ b/src/tools/miri/tests/fail/tail_calls/dangling-local-var.stderr
@@ -14,8 +14,8 @@ LL |     let local = 0;
 help: ALLOC was deallocated here:
   --> tests/fail/tail_calls/dangling-local-var.rs:LL:CC
    |
-LL |     become g(ptr)
-   |     ^^^^^^^^^^^^^
+LL |     f(std::ptr::null());
+   |     ^^^^^^^^^^^^^^^^^^^
    = note: BACKTRACE (of the first span):
    = note: inside `g` at tests/fail/tail_calls/dangling-local-var.rs:LL:CC
 note: inside `main`
diff --git a/src/tools/miri/tests/fail/tree_borrows/cell-inside-struct.rs b/src/tools/miri/tests/fail/tree_borrows/cell-inside-struct.rs
new file mode 100644
index 00000000000..ff797877682
--- /dev/null
+++ b/src/tools/miri/tests/fail/tree_borrows/cell-inside-struct.rs
@@ -0,0 +1,33 @@
+//! A version of `cell_inside_struct` that dumps the tree so that we can see what is happening.
+//@compile-flags: -Zmiri-tree-borrows
+#[path = "../../utils/mod.rs"]
+#[macro_use]
+mod utils;
+
+use std::cell::Cell;
+
+struct Foo {
+    field1: u32,
+    field2: Cell<u32>,
+}
+
+pub fn main() {
+    let root = Foo { field1: 42, field2: Cell::new(88) };
+    unsafe {
+        let a = &root;
+
+        name!(a as *const Foo, "a");
+
+        let a: *const Foo = a as *const Foo;
+        let a: *mut Foo = a as *mut Foo;
+
+        let alloc_id = alloc_id!(a);
+        print_state!(alloc_id);
+
+        // Writing to `field2`, which is interior mutable, should be allowed.
+        (*a).field2.set(10);
+
+        // Writing to `field1`, which is frozen, should not be allowed.
+        (*a).field1 = 88; //~ ERROR: /write access through .* is forbidden/
+    }
+}
diff --git a/src/tools/miri/tests/fail/tree_borrows/cell-inside-struct.stderr b/src/tools/miri/tests/fail/tree_borrows/cell-inside-struct.stderr
new file mode 100644
index 00000000000..717f1419452
--- /dev/null
+++ b/src/tools/miri/tests/fail/tree_borrows/cell-inside-struct.stderr
@@ -0,0 +1,26 @@
+──────────────────────────────────────────────────
+Warning: this tree is indicative only. Some tags may have been hidden.
+0..   4..   8
+| Act | Act |    └─┬──<TAG=root of the allocation>
+| Frz |?Cel |      └────<TAG=a>
+──────────────────────────────────────────────────
+error: Undefined Behavior: write access through <TAG> (a) at ALLOC[0x0] is forbidden
+  --> tests/fail/tree_borrows/cell-inside-struct.rs:LL:CC
+   |
+LL |         (*a).field1 = 88;
+   |         ^^^^^^^^^^^^^^^^ write access through <TAG> (a) at ALLOC[0x0] is forbidden
+   |
+   = help: this indicates a potential bug in the program: it performed an invalid operation, but the Tree Borrows rules it violated are still experimental
+   = help: the accessed tag <TAG> (a) has state Frozen which forbids this child write access
+help: the accessed tag <TAG> was created here, in the initial state Cell
+  --> tests/fail/tree_borrows/cell-inside-struct.rs:LL:CC
+   |
+LL |         let a = &root;
+   |                 ^^^^^
+   = note: BACKTRACE (of the first span):
+   = note: inside `main` at tests/fail/tree_borrows/cell-inside-struct.rs:LL:CC
+
+note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
+
+error: aborting due to 1 previous error
+
diff --git a/src/tools/miri/tests/fail/unaligned_pointers/atomic_unaligned.rs b/src/tools/miri/tests/fail/unaligned_pointers/atomic_unaligned.rs
index 29976836b0b..37c64c81944 100644
--- a/src/tools/miri/tests/fail/unaligned_pointers/atomic_unaligned.rs
+++ b/src/tools/miri/tests/fail/unaligned_pointers/atomic_unaligned.rs
@@ -1,5 +1,6 @@
 //@compile-flags: -Zmiri-symbolic-alignment-check -Cdebug-assertions=no
 #![feature(core_intrinsics)]
+use std::intrinsics;
 
 fn main() {
     // Do a 4-aligned u64 atomic access. That should be UB on all platforms,
@@ -7,7 +8,7 @@ fn main() {
     let z = [0u32; 2];
     let zptr = &z as *const _ as *const u64;
     unsafe {
-        ::std::intrinsics::atomic_load_seqcst(zptr);
+        intrinsics::atomic_load::<_, { intrinsics::AtomicOrdering::SeqCst }>(zptr);
         //~^ERROR: accessing memory with alignment 4, but alignment 8 is required
     }
 }
diff --git a/src/tools/miri/tests/fail/unaligned_pointers/atomic_unaligned.stderr b/src/tools/miri/tests/fail/unaligned_pointers/atomic_unaligned.stderr
index a9da740be1d..e0f9d011ce4 100644
--- a/src/tools/miri/tests/fail/unaligned_pointers/atomic_unaligned.stderr
+++ b/src/tools/miri/tests/fail/unaligned_pointers/atomic_unaligned.stderr
@@ -1,8 +1,8 @@
 error: Undefined Behavior: accessing memory with alignment ALIGN, but alignment ALIGN is required
   --> tests/fail/unaligned_pointers/atomic_unaligned.rs:LL:CC
    |
-LL |         ::std::intrinsics::atomic_load_seqcst(zptr);
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ accessing memory with alignment ALIGN, but alignment ALIGN is required
+LL |         intrinsics::atomic_load::<_, { intrinsics::AtomicOrdering::SeqCst }>(zptr);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ accessing memory with alignment ALIGN, but alignment ALIGN is required
    |
    = help: this usually indicates that your program performed an invalid operation and caused Undefined Behavior
    = help: but due to `-Zmiri-symbolic-alignment-check`, alignment errors can also be false positives
diff --git a/src/tools/miri/tests/fail/unsupported_foreign_function.stderr b/src/tools/miri/tests/fail/unsupported_foreign_function.stderr
index 4fe45b0868a..bbfc5c31256 100644
--- a/src/tools/miri/tests/fail/unsupported_foreign_function.stderr
+++ b/src/tools/miri/tests/fail/unsupported_foreign_function.stderr
@@ -4,8 +4,7 @@ error: unsupported operation: can't call foreign function `foo` on $OS
 LL |         foo();
    |         ^^^^^ can't call foreign function `foo` on $OS
    |
-   = help: if this is a basic API commonly used on this target, please report an issue with Miri
-   = help: however, note that Miri does not aim to support every FFI function out there; for instance, we will not support APIs for things such as GUIs, scripting languages, or databases
+   = help: this means the program tried to do something Miri does not support; it does not indicate a bug in the program
    = note: BACKTRACE:
    = note: inside `main` at tests/fail/unsupported_foreign_function.rs:LL:CC
 
diff --git a/src/tools/miri/tests/many-seeds/reentrant-lock.rs b/src/tools/miri/tests/many-seeds/reentrant-lock.rs
index 8a363179a9c..4c2dc463f48 100644
--- a/src/tools/miri/tests/many-seeds/reentrant-lock.rs
+++ b/src/tools/miri/tests/many-seeds/reentrant-lock.rs
@@ -1,6 +1,6 @@
 #![feature(reentrant_lock)]
 //! This is a regression test for
-//! <https://rust-lang.zulipchat.com/#narrow/channel/269128-miri/topic/reentrant.20lock.20failure.20on.20musl>.
+//! <https://rust-lang.zulipchat.com/#narrow/channel/269128-miri/topic/reentrant.20lock.20failure.20on.20mips>.
 
 use std::cell::Cell;
 use std::sync::ReentrantLock;
diff --git a/src/tools/miri/tests/native-lib/fail/function_not_in_so.stderr b/src/tools/miri/tests/native-lib/fail/function_not_in_so.stderr
index bf1cfd573b8..b663fd41457 100644
--- a/src/tools/miri/tests/native-lib/fail/function_not_in_so.stderr
+++ b/src/tools/miri/tests/native-lib/fail/function_not_in_so.stderr
@@ -4,8 +4,7 @@ error: unsupported operation: can't call foreign function `foo` on $OS
 LL |         foo();
    |         ^^^^^ can't call foreign function `foo` on $OS
    |
-   = help: if this is a basic API commonly used on this target, please report an issue with Miri
-   = help: however, note that Miri does not aim to support every FFI function out there; for instance, we will not support APIs for things such as GUIs, scripting languages, or databases
+   = help: this means the program tried to do something Miri does not support; it does not indicate a bug in the program
    = note: BACKTRACE:
    = note: inside `main` at tests/native-lib/fail/function_not_in_so.rs:LL:CC
 
diff --git a/src/tools/miri/tests/native-lib/fail/private_function.stderr b/src/tools/miri/tests/native-lib/fail/private_function.stderr
index 2cfc062212b..03681240015 100644
--- a/src/tools/miri/tests/native-lib/fail/private_function.stderr
+++ b/src/tools/miri/tests/native-lib/fail/private_function.stderr
@@ -4,8 +4,7 @@ error: unsupported operation: can't call foreign function `not_exported` on $OS
 LL |         not_exported();
    |         ^^^^^^^^^^^^^^ can't call foreign function `not_exported` on $OS
    |
-   = help: if this is a basic API commonly used on this target, please report an issue with Miri
-   = help: however, note that Miri does not aim to support every FFI function out there; for instance, we will not support APIs for things such as GUIs, scripting languages, or databases
+   = help: this means the program tried to do something Miri does not support; it does not indicate a bug in the program
    = note: BACKTRACE:
    = note: inside `main` at tests/native-lib/fail/private_function.rs:LL:CC
 
diff --git a/src/tools/miri/tests/pass-dep/libc/libc-pipe.rs b/src/tools/miri/tests/pass-dep/libc/libc-pipe.rs
index 05f6c870c3d..bc755af864c 100644
--- a/src/tools/miri/tests/pass-dep/libc/libc-pipe.rs
+++ b/src/tools/miri/tests/pass-dep/libc/libc-pipe.rs
@@ -15,6 +15,8 @@ fn main() {
     ))]
     // `pipe2` only exists in some specific os.
     test_pipe2();
+    test_pipe_setfl_getfl();
+    test_pipe_fcntl_threaded();
 }
 
 fn test_pipe() {
@@ -127,3 +129,68 @@ fn test_pipe2() {
     let res = unsafe { libc::pipe2(fds.as_mut_ptr(), libc::O_NONBLOCK) };
     assert_eq!(res, 0);
 }
+
+/// Basic test for pipe fcntl's F_SETFL and F_GETFL flag.
+fn test_pipe_setfl_getfl() {
+    // Initialise pipe fds.
+    let mut fds = [-1, -1];
+    let res = unsafe { libc::pipe(fds.as_mut_ptr()) };
+    assert_eq!(res, 0);
+
+    // Both sides should either have O_RONLY or O_WRONLY.
+    let res = unsafe { libc::fcntl(fds[0], libc::F_GETFL) };
+    assert_eq!(res, libc::O_RDONLY);
+    let res = unsafe { libc::fcntl(fds[1], libc::F_GETFL) };
+    assert_eq!(res, libc::O_WRONLY);
+
+    // Add the O_NONBLOCK flag with F_SETFL.
+    let res = unsafe { libc::fcntl(fds[0], libc::F_SETFL, libc::O_NONBLOCK) };
+    assert_eq!(res, 0);
+
+    // Test if the O_NONBLOCK flag is successfully added.
+    let res = unsafe { libc::fcntl(fds[0], libc::F_GETFL) };
+    assert_eq!(res, libc::O_RDONLY | libc::O_NONBLOCK);
+
+    // The other side remains unchanged.
+    let res = unsafe { libc::fcntl(fds[1], libc::F_GETFL) };
+    assert_eq!(res, libc::O_WRONLY);
+
+    // Test if O_NONBLOCK flag can be unset.
+    let res = unsafe { libc::fcntl(fds[0], libc::F_SETFL, 0) };
+    assert_eq!(res, 0);
+    let res = unsafe { libc::fcntl(fds[0], libc::F_GETFL) };
+    assert_eq!(res, libc::O_RDONLY);
+}
+
+/// Test the behaviour of F_SETFL/F_GETFL when a fd is blocking.
+/// The expected execution is:
+/// 1. Main thread blocks on fds[0] `read`.
+/// 2. Thread 1 sets O_NONBLOCK flag on fds[0],
+///    checks the value of F_GETFL,
+///    then writes to fds[1] to unblock main thread's `read`.
+fn test_pipe_fcntl_threaded() {
+    let mut fds = [-1, -1];
+    let res = unsafe { libc::pipe(fds.as_mut_ptr()) };
+    assert_eq!(res, 0);
+    let mut buf: [u8; 5] = [0; 5];
+    let thread1 = thread::spawn(move || {
+        // Add O_NONBLOCK flag while pipe is still blocked on read.
+        let res = unsafe { libc::fcntl(fds[0], libc::F_SETFL, libc::O_NONBLOCK) };
+        assert_eq!(res, 0);
+
+        // Check the new flag value while the main thread is still blocked on fds[0].
+        let res = unsafe { libc::fcntl(fds[0], libc::F_GETFL) };
+        assert_eq!(res, libc::O_NONBLOCK);
+
+        // The write below will unblock the `read` in main thread: even though
+        // the socket is now "non-blocking", the shim needs to deal correctly
+        // with threads that were blocked before the socket was made non-blocking.
+        let data = "abcde".as_bytes().as_ptr();
+        let res = unsafe { libc::write(fds[1], data as *const libc::c_void, 5) };
+        assert_eq!(res, 5);
+    });
+    // The `read` below will block.
+    let res = unsafe { libc::read(fds[0], buf.as_mut_ptr().cast(), buf.len() as libc::size_t) };
+    thread1.join().unwrap();
+    assert_eq!(res, 5);
+}
diff --git a/src/tools/miri/tests/pass-dep/libc/libc-socketpair.rs b/src/tools/miri/tests/pass-dep/libc/libc-socketpair.rs
index 9e48410f704..c36f6b11224 100644
--- a/src/tools/miri/tests/pass-dep/libc/libc-socketpair.rs
+++ b/src/tools/miri/tests/pass-dep/libc/libc-socketpair.rs
@@ -12,6 +12,7 @@ fn main() {
     test_race();
     test_blocking_read();
     test_blocking_write();
+    test_socketpair_setfl_getfl();
 }
 
 fn test_socketpair() {
@@ -182,3 +183,35 @@ fn test_blocking_write() {
     thread1.join().unwrap();
     thread2.join().unwrap();
 }
+
+/// Basic test for socketpair fcntl's F_SETFL and F_GETFL flag.
+fn test_socketpair_setfl_getfl() {
+    // Initialise socketpair fds.
+    let mut fds = [-1, -1];
+    let res = unsafe { libc::socketpair(libc::AF_UNIX, libc::SOCK_STREAM, 0, fds.as_mut_ptr()) };
+    assert_eq!(res, 0);
+
+    // Test if both sides have O_RDWR.
+    let res = unsafe { libc::fcntl(fds[0], libc::F_GETFL) };
+    assert_eq!(res, libc::O_RDWR);
+    let res = unsafe { libc::fcntl(fds[1], libc::F_GETFL) };
+    assert_eq!(res, libc::O_RDWR);
+
+    // Add the O_NONBLOCK flag with F_SETFL.
+    let res = unsafe { libc::fcntl(fds[0], libc::F_SETFL, libc::O_NONBLOCK) };
+    assert_eq!(res, 0);
+
+    // Test if the O_NONBLOCK flag is successfully added.
+    let res = unsafe { libc::fcntl(fds[0], libc::F_GETFL) };
+    assert_eq!(res, libc::O_RDWR | libc::O_NONBLOCK);
+
+    // The other side remains unchanged.
+    let res = unsafe { libc::fcntl(fds[1], libc::F_GETFL) };
+    assert_eq!(res, libc::O_RDWR);
+
+    // Test if O_NONBLOCK flag can be unset.
+    let res = unsafe { libc::fcntl(fds[0], libc::F_SETFL, 0) };
+    assert_eq!(res, 0);
+    let res = unsafe { libc::fcntl(fds[0], libc::F_GETFL) };
+    assert_eq!(res, libc::O_RDWR);
+}
diff --git a/src/tools/miri/tests/pass-dep/tokio/file-io.rs b/src/tools/miri/tests/pass-dep/tokio/file-io.rs
index 6e88b907f5d..067753203bb 100644
--- a/src/tools/miri/tests/pass-dep/tokio/file-io.rs
+++ b/src/tools/miri/tests/pass-dep/tokio/file-io.rs
@@ -20,7 +20,11 @@ async fn test_create_and_write() -> io::Result<()> {
     let mut file = File::create(&path).await?;
 
     // Write 10 bytes to the file.
-    file.write(b"some bytes").await?;
+    file.write_all(b"some bytes").await?;
+    // For tokio's file I/O, `await` does not have its usual semantics of waiting until the
+    // operation is completed, so we have to wait some more to make sure the write is completed.
+    file.flush().await?;
+    // Check that 10 bytes have been written.
     assert_eq!(file.metadata().await.unwrap().len(), 10);
 
     remove_file(&path).unwrap();
@@ -31,10 +35,10 @@ async fn test_create_and_read() -> io::Result<()> {
     let bytes = b"more bytes";
     let path = utils::prepare_with_content("foo.txt", bytes);
     let mut file = OpenOptions::new().read(true).open(&path).await.unwrap();
-    let mut buffer = [0u8; 10];
+    let mut buffer = vec![];
 
     // Read the whole file.
-    file.read(&mut buffer[..]).await?;
+    file.read_to_end(&mut buffer).await?;
     assert_eq!(&buffer, b"more bytes");
 
     remove_file(&path).unwrap();
diff --git a/src/tools/miri/tests/pass/alloc-access-tracking.rs b/src/tools/miri/tests/pass/alloc-access-tracking.rs
index c47063bef03..0e88951dc43 100644
--- a/src/tools/miri/tests/pass/alloc-access-tracking.rs
+++ b/src/tools/miri/tests/pass/alloc-access-tracking.rs
@@ -1,7 +1,7 @@
 #![no_std]
 #![no_main]
-//@compile-flags: -Zmiri-track-alloc-id=21 -Zmiri-track-alloc-accesses -Cpanic=abort
-//@normalize-stderr-test: "id 21" -> "id $$ALLOC"
+//@compile-flags: -Zmiri-track-alloc-id=20 -Zmiri-track-alloc-accesses -Cpanic=abort
+//@normalize-stderr-test: "id 20" -> "id $$ALLOC"
 //@only-target: linux # alloc IDs differ between OSes (due to extern static allocations)
 
 extern "Rust" {
diff --git a/src/tools/miri/tests/pass/both_borrows/basic_aliasing_model.rs b/src/tools/miri/tests/pass/both_borrows/basic_aliasing_model.rs
index c76e7f2eebd..6a625e597df 100644
--- a/src/tools/miri/tests/pass/both_borrows/basic_aliasing_model.rs
+++ b/src/tools/miri/tests/pass/both_borrows/basic_aliasing_model.rs
@@ -1,6 +1,7 @@
 //@revisions: stack tree
 //@[tree]compile-flags: -Zmiri-tree-borrows
 #![feature(allocator_api)]
+use std::cell::Cell;
 use std::ptr;
 
 // Test various aliasing-model-related things.
@@ -22,6 +23,7 @@ fn main() {
     not_unpin_not_protected();
     write_does_not_invalidate_all_aliases();
     box_into_raw_allows_interior_mutable_alias();
+    cell_inside_struct()
 }
 
 // Make sure that reading from an `&mut` does, like reborrowing to `&`,
@@ -259,7 +261,7 @@ fn write_does_not_invalidate_all_aliases() {
 
 fn box_into_raw_allows_interior_mutable_alias() {
     unsafe {
-        let b = Box::new(std::cell::Cell::new(42));
+        let b = Box::new(Cell::new(42));
         let raw = Box::into_raw(b);
         let c = &*raw;
         let d = raw.cast::<i32>(); // bypassing `Cell` -- only okay in Miri tests
@@ -269,3 +271,19 @@ fn box_into_raw_allows_interior_mutable_alias() {
         drop(Box::from_raw(raw));
     }
 }
+
+fn cell_inside_struct() {
+    struct Foo {
+        field1: u32,
+        field2: Cell<u32>,
+    }
+
+    let mut root = Foo { field1: 42, field2: Cell::new(88) };
+    let a = &mut root;
+
+    // Writing to `field2`, which is interior mutable, should be allowed.
+    (*a).field2.set(10);
+
+    // Writing to `field1`, which is reserved, should also be allowed.
+    (*a).field1 = 88;
+}
diff --git a/src/tools/miri/tests/pass/btreemap.rs b/src/tools/miri/tests/pass/btreemap.rs
index 1213f81a6f1..1d65e69bf72 100644
--- a/src/tools/miri/tests/pass/btreemap.rs
+++ b/src/tools/miri/tests/pass/btreemap.rs
@@ -50,7 +50,7 @@ pub fn main() {
     test_all_refs(&mut 13, b.values_mut());
 
     // Test forgetting the extractor.
-    let mut d = b.extract_if(|_, i| *i < 30);
+    let mut d = b.extract_if(.., |_, i| *i < 30);
     d.next().unwrap();
     mem::forget(d);
 }
diff --git a/src/tools/miri/tests/pass/iter_macro.rs b/src/tools/miri/tests/pass/iter_macro.rs
new file mode 100644
index 00000000000..367c13f9969
--- /dev/null
+++ b/src/tools/miri/tests/pass/iter_macro.rs
@@ -0,0 +1,22 @@
+#![feature(iter_macro, yield_expr)]
+
+use std::iter::iter;
+
+fn main() {
+    let i = iter! { || {
+        yield 0;
+        for x in 5..10 {
+            yield x * 2;
+        }
+    } };
+    let mut i = i();
+    assert_eq!(i.next(), Some(0));
+    assert_eq!(i.next(), Some(10));
+    assert_eq!(i.next(), Some(12));
+    assert_eq!(i.next(), Some(14));
+    assert_eq!(i.next(), Some(16));
+    assert_eq!(i.next(), Some(18));
+    assert_eq!(i.next(), None);
+    assert_eq!(i.next(), None);
+    assert_eq!(i.next(), None);
+}
diff --git a/src/tools/miri/tests/pass/shims/fs.rs b/src/tools/miri/tests/pass/shims/fs.rs
index 315637ff7ec..87df43ca7e5 100644
--- a/src/tools/miri/tests/pass/shims/fs.rs
+++ b/src/tools/miri/tests/pass/shims/fs.rs
@@ -23,9 +23,9 @@ fn main() {
     test_seek();
     test_errors();
     test_from_raw_os_error();
+    test_file_clone();
     // Windows file handling is very incomplete.
     if cfg!(not(windows)) {
-        test_file_clone();
         test_file_set_len();
         test_file_sync();
         test_rename();
diff --git a/src/tools/miri/tests/pass/tree_borrows/cell-alternate-writes.stderr b/src/tools/miri/tests/pass/tree_borrows/cell-alternate-writes.stderr
index 75a30c9a083..e09aed2cf5d 100644
--- a/src/tools/miri/tests/pass/tree_borrows/cell-alternate-writes.stderr
+++ b/src/tools/miri/tests/pass/tree_borrows/cell-alternate-writes.stderr
@@ -3,8 +3,8 @@ Warning: this tree is indicative only. Some tags may have been hidden.
 0..   1
 | Act |    └─┬──<TAG=root of the allocation>
 | ReIM|      └─┬──<TAG=data>
-| Cel |        ├────<TAG=x>
-| Cel |        └────<TAG=y>
+|?Cel |        ├────<TAG=x>
+|?Cel |        └────<TAG=y>
 ──────────────────────────────────────────────────
 ──────────────────────────────────────────────────
 Warning: this tree is indicative only. Some tags may have been hidden.
diff --git a/src/tools/miri/tests/pass/tree_borrows/cell-lazy-write-to-surrounding.rs b/src/tools/miri/tests/pass/tree_borrows/cell-lazy-write-to-surrounding.rs
new file mode 100644
index 00000000000..abe08f2cd22
--- /dev/null
+++ b/src/tools/miri/tests/pass/tree_borrows/cell-lazy-write-to-surrounding.rs
@@ -0,0 +1,22 @@
+//@compile-flags: -Zmiri-tree-borrows
+
+use std::cell::Cell;
+
+fn foo(x: &Cell<i32>) {
+    unsafe {
+        let ptr = x as *const Cell<i32> as *mut Cell<i32> as *mut i32;
+        ptr.offset(1).write(0);
+    }
+}
+
+fn main() {
+    let arr = [Cell::new(1), Cell::new(1)];
+    foo(&arr[0]);
+
+    let pair = (Cell::new(1), 1);
+    // TODO: Ideally, this would result in UB since the second element
+    // in `pair` is Frozen.  We would need some way to express a
+    // "shared reference with permission to access surrounding
+    // interior mutable data".
+    foo(&pair.0);
+}
diff --git a/src/tools/opt-dist/src/training.rs b/src/tools/opt-dist/src/training.rs
index 47159a43140..36a7d6a7cba 100644
--- a/src/tools/opt-dist/src/training.rs
+++ b/src/tools/opt-dist/src/training.rs
@@ -36,7 +36,7 @@ fn init_compiler_benchmarks(
         profiles.join(",").as_str(),
         "--scenarios",
         scenarios.join(",").as_str(),
-        "--include",
+        "--exact-match",
         crates.join(",").as_str(),
     ])
     .env("RUST_LOG", "collector=debug")
diff --git a/src/tools/rust-analyzer/Cargo.lock b/src/tools/rust-analyzer/Cargo.lock
index bd8146defae..01de430925d 100644
--- a/src/tools/rust-analyzer/Cargo.lock
+++ b/src/tools/rust-analyzer/Cargo.lock
@@ -18,15 +18,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627"
 
 [[package]]
-name = "aho-corasick"
-version = "1.1.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916"
-dependencies = [
- "memchr",
-]
-
-[[package]]
 name = "allocator-api2"
 version = "0.2.21"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -124,12 +115,9 @@ dependencies = [
 
 [[package]]
 name = "boxcar"
-version = "0.2.11"
+version = "0.2.12"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6740c6e2fc6360fa57c35214c7493826aee95993926092606f27c983b40837be"
-dependencies = [
- "loom",
-]
+checksum = "66bb12751a83493ef4b8da1120451a262554e216a247f14b48cb5e8fe7ed8bdf"
 
 [[package]]
 name = "camino"
@@ -512,19 +500,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "7ab85b9b05e3978cc9a9cf8fea7f01b494e1a09ed3037e16ba39edc7a29eb61a"
 
 [[package]]
-name = "generator"
-version = "0.8.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cc6bd114ceda131d3b1d665eba35788690ad37f5916457286b32ab6fd3c438dd"
-dependencies = [
- "cfg-if",
- "libc",
- "log",
- "rustversion",
- "windows 0.58.0",
-]
-
-[[package]]
 name = "getrandom"
 version = "0.2.15"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1214,19 +1189,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "30bde2b3dc3671ae49d8e2e9f044c7c005836e7a023ee57cffa25ab82764bb9e"
 
 [[package]]
-name = "loom"
-version = "0.7.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "419e0dc8046cb947daa77eb95ae174acfbddb7673b4151f56d1eed8e93fbfaca"
-dependencies = [
- "cfg-if",
- "generator",
- "scoped-tls",
- "tracing",
- "tracing-subscriber",
-]
-
-[[package]]
 name = "lsp-server"
 version = "0.7.8"
 dependencies = [
@@ -1266,15 +1228,6 @@ dependencies = [
 ]
 
 [[package]]
-name = "matchers"
-version = "0.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558"
-dependencies = [
- "regex-automata 0.1.10",
-]
-
-[[package]]
 name = "mbe"
 version = "0.0.0"
 dependencies = [
@@ -1402,16 +1355,6 @@ checksum = "5e0826a989adedc2a244799e823aece04662b66609d96af8dff7ac6df9a8925d"
 
 [[package]]
 name = "nu-ansi-term"
-version = "0.46.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84"
-dependencies = [
- "overload",
- "winapi",
-]
-
-[[package]]
-name = "nu-ansi-term"
 version = "0.50.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "d4a28e057d01f97e61255210fcff094d74ed0466038633e95017f5beb68e4399"
@@ -1472,12 +1415,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d"
 
 [[package]]
-name = "overload"
-version = "0.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39"
-
-[[package]]
 name = "parking_lot"
 version = "0.12.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1648,7 +1585,7 @@ dependencies = [
  "indexmap",
  "nix",
  "tracing",
- "windows 0.61.1",
+ "windows",
 ]
 
 [[package]]
@@ -1865,50 +1802,6 @@ dependencies = [
 ]
 
 [[package]]
-name = "regex"
-version = "1.11.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191"
-dependencies = [
- "aho-corasick",
- "memchr",
- "regex-automata 0.4.9",
- "regex-syntax 0.8.5",
-]
-
-[[package]]
-name = "regex-automata"
-version = "0.1.10"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132"
-dependencies = [
- "regex-syntax 0.6.29",
-]
-
-[[package]]
-name = "regex-automata"
-version = "0.4.9"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908"
-dependencies = [
- "aho-corasick",
- "memchr",
- "regex-syntax 0.8.5",
-]
-
-[[package]]
-name = "regex-syntax"
-version = "0.6.29"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1"
-
-[[package]]
-name = "regex-syntax"
-version = "0.8.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
-
-[[package]]
 name = "rowan"
 version = "0.15.15"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2027,12 +1920,6 @@ dependencies = [
 ]
 
 [[package]]
-name = "rustversion"
-version = "1.0.20"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "eded382c5f5f786b989652c49544c4877d9f015cc22e145a5ea8ea66c2921cd2"
-
-[[package]]
 name = "ryu"
 version = "1.0.20"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2040,9 +1927,9 @@ checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f"
 
 [[package]]
 name = "salsa"
-version = "0.21.1"
+version = "0.22.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6f80d5cf3c3fcab2cef898012f242a670477a1baa609267376af9cb4409026c5"
+checksum = "c8fff508e3d6ef42a32607f7538e17171a877a12015e32036f46e99d00c95781"
 dependencies = [
  "boxcar",
  "crossbeam-queue",
@@ -2063,15 +1950,15 @@ dependencies = [
 
 [[package]]
 name = "salsa-macro-rules"
-version = "0.21.1"
+version = "0.22.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "05303d72606fbf2b9c9523cda2039bb8ecb00304027a3cd7e52b02a65c7d9185"
+checksum = "8ea72b3c06f2ce6350fe3a0eeb7aaaf842d1d8352b706973c19c4f02e298a87c"
 
 [[package]]
 name = "salsa-macros"
-version = "0.21.1"
+version = "0.22.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "eb2f0e2a30c65cb3cd63440c491dde68d9af7e1be2b77832ac7057141107db50"
+checksum = "0ce92025bc160b27814a207cb78d680973af17f863c7f4fc56cf3a535e22f378"
 dependencies = [
  "heck",
  "proc-macro2",
@@ -2556,15 +2443,9 @@ version = "0.3.19"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "e8189decb5ac0fa7bc8b96b7cb9b2701d60d48805aca84a238004d665fcc4008"
 dependencies = [
- "matchers",
- "nu-ansi-term 0.46.0",
- "once_cell",
- "regex",
  "sharded-slab",
- "smallvec",
  "thread_local",
  "time",
- "tracing",
  "tracing-core",
  "tracing-log",
 ]
@@ -2575,7 +2456,7 @@ version = "0.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "f459ca79f1b0d5f71c54ddfde6debfc59c8b6eeb46808ae492077f739dc7b49c"
 dependencies = [
- "nu-ansi-term 0.50.1",
+ "nu-ansi-term",
  "tracing-core",
  "tracing-log",
  "tracing-subscriber",
@@ -2710,22 +2591,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
 
 [[package]]
-name = "winapi"
-version = "0.3.9"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
-dependencies = [
- "winapi-i686-pc-windows-gnu",
- "winapi-x86_64-pc-windows-gnu",
-]
-
-[[package]]
-name = "winapi-i686-pc-windows-gnu"
-version = "0.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
-
-[[package]]
 name = "winapi-util"
 version = "0.1.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2735,29 +2600,13 @@ dependencies = [
 ]
 
 [[package]]
-name = "winapi-x86_64-pc-windows-gnu"
-version = "0.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
-
-[[package]]
-name = "windows"
-version = "0.58.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dd04d41d93c4992d421894c18c8b43496aa748dd4c081bac0dc93eb0489272b6"
-dependencies = [
- "windows-core 0.58.0",
- "windows-targets 0.52.6",
-]
-
-[[package]]
 name = "windows"
 version = "0.61.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "c5ee8f3d025738cb02bad7868bbb5f8a6327501e870bf51f1b455b0a2454a419"
 dependencies = [
  "windows-collections",
- "windows-core 0.61.0",
+ "windows-core",
  "windows-future",
  "windows-link",
  "windows-numerics",
@@ -2769,20 +2618,7 @@ version = "0.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "3beeceb5e5cfd9eb1d76b381630e82c4241ccd0d27f1a39ed41b2760b255c5e8"
 dependencies = [
- "windows-core 0.61.0",
-]
-
-[[package]]
-name = "windows-core"
-version = "0.58.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6ba6d44ec8c2591c134257ce647b7ea6b20335bf6379a27dac5f1641fcf59f99"
-dependencies = [
- "windows-implement 0.58.0",
- "windows-interface 0.58.0",
- "windows-result 0.2.0",
- "windows-strings 0.1.0",
- "windows-targets 0.52.6",
+ "windows-core",
 ]
 
 [[package]]
@@ -2791,11 +2627,11 @@ version = "0.61.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "4763c1de310c86d75a878046489e2e5ba02c649d185f21c67d4cf8a56d098980"
 dependencies = [
- "windows-implement 0.60.0",
- "windows-interface 0.59.1",
+ "windows-implement",
+ "windows-interface",
  "windows-link",
- "windows-result 0.3.2",
- "windows-strings 0.4.0",
+ "windows-result",
+ "windows-strings",
 ]
 
 [[package]]
@@ -2804,23 +2640,12 @@ version = "0.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "7a1d6bbefcb7b60acd19828e1bc965da6fcf18a7e39490c5f8be71e54a19ba32"
 dependencies = [
- "windows-core 0.61.0",
+ "windows-core",
  "windows-link",
 ]
 
 [[package]]
 name = "windows-implement"
-version = "0.58.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2bbd5b46c938e506ecbce286b6628a02171d56153ba733b6c741fc627ec9579b"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
-name = "windows-implement"
 version = "0.60.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "a47fddd13af08290e67f4acabf4b459f647552718f683a7b415d290ac744a836"
@@ -2832,17 +2657,6 @@ dependencies = [
 
 [[package]]
 name = "windows-interface"
-version = "0.58.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "053c4c462dc91d3b1504c6fe5a726dd15e216ba718e84a0e46a88fbe5ded3515"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
-name = "windows-interface"
 version = "0.59.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "bd9211b69f8dcdfa817bfd14bf1c97c9188afa36f4750130fcdf3f400eca9fa8"
@@ -2864,21 +2678,12 @@ version = "0.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "9150af68066c4c5c07ddc0ce30421554771e528bde427614c61038bc2c92c2b1"
 dependencies = [
- "windows-core 0.61.0",
+ "windows-core",
  "windows-link",
 ]
 
 [[package]]
 name = "windows-result"
-version = "0.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1d1043d8214f791817bab27572aaa8af63732e11bf84aa21a45a78d6c317ae0e"
-dependencies = [
- "windows-targets 0.52.6",
-]
-
-[[package]]
-name = "windows-result"
 version = "0.3.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "c64fd11a4fd95df68efcfee5f44a294fe71b8bc6a91993e2791938abcc712252"
@@ -2888,16 +2693,6 @@ dependencies = [
 
 [[package]]
 name = "windows-strings"
-version = "0.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10"
-dependencies = [
- "windows-result 0.2.0",
- "windows-targets 0.52.6",
-]
-
-[[package]]
-name = "windows-strings"
 version = "0.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "7a2ba9642430ee452d5a7aa78d72907ebe8cfda358e8cb7918a2050581322f97"
diff --git a/src/tools/rust-analyzer/Cargo.toml b/src/tools/rust-analyzer/Cargo.toml
index 07731bae3f3..8c507189846 100644
--- a/src/tools/rust-analyzer/Cargo.toml
+++ b/src/tools/rust-analyzer/Cargo.toml
@@ -132,11 +132,8 @@ pulldown-cmark-to-cmark = "10.0.4"
 pulldown-cmark = { version = "0.9.6", default-features = false }
 rayon = "1.10.0"
 rowan = "=0.15.15"
-salsa = { version = "0.21.1", default-features = false, features = [
-  "rayon",
-  "salsa_unstable",
-] }
-salsa-macros = "0.21.1"
+salsa = { version = "0.22.0", default-features = false, features = ["rayon","salsa_unstable"] }
+salsa-macros = "0.22.0"
 semver = "1.0.26"
 serde = { version = "1.0.219" }
 serde_derive = { version = "1.0.219" }
diff --git a/src/tools/rust-analyzer/crates/base-db/src/input.rs b/src/tools/rust-analyzer/crates/base-db/src/input.rs
index d42d7e5707d..745238167bc 100644
--- a/src/tools/rust-analyzer/crates/base-db/src/input.rs
+++ b/src/tools/rust-analyzer/crates/base-db/src/input.rs
@@ -395,21 +395,21 @@ impl BuiltDependency {
 pub type CratesIdMap = FxHashMap<CrateBuilderId, Crate>;
 
 #[salsa_macros::input]
-#[derive(Debug)]
+#[derive(Debug, PartialOrd, Ord)]
 pub struct Crate {
-    #[return_ref]
+    #[returns(ref)]
     pub data: BuiltCrateData,
     /// Crate data that is not needed for analysis.
     ///
     /// This is split into a separate field to increase incrementality.
-    #[return_ref]
+    #[returns(ref)]
     pub extra_data: ExtraCrateData,
     // This is in `Arc` because it is shared for all crates in a workspace.
-    #[return_ref]
+    #[returns(ref)]
     pub workspace_data: Arc<CrateWorkspaceData>,
-    #[return_ref]
+    #[returns(ref)]
     pub cfg_options: CfgOptions,
-    #[return_ref]
+    #[returns(ref)]
     pub env: Env,
 }
 
diff --git a/src/tools/rust-analyzer/crates/base-db/src/lib.rs b/src/tools/rust-analyzer/crates/base-db/src/lib.rs
index a67fbf75c02..4d4e6cae037 100644
--- a/src/tools/rust-analyzer/crates/base-db/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/base-db/src/lib.rs
@@ -32,6 +32,7 @@ pub use vfs::{AnchoredPath, AnchoredPathBuf, FileId, VfsPath, file_set::FileSet}
 macro_rules! impl_intern_key {
     ($id:ident, $loc:ident) => {
         #[salsa_macros::interned(no_lifetime)]
+        #[derive(PartialOrd, Ord)]
         pub struct $id {
             pub loc: $loc,
         }
@@ -165,6 +166,7 @@ impl Files {
 }
 
 #[salsa_macros::interned(no_lifetime, debug, constructor=from_span)]
+#[derive(PartialOrd, Ord)]
 pub struct EditionedFileId {
     pub editioned_file_id: span::EditionedFileId,
 }
@@ -356,7 +358,7 @@ fn parse(db: &dyn RootQueryDb, file_id: EditionedFileId) -> Parse<ast::SourceFil
 }
 
 fn parse_errors(db: &dyn RootQueryDb, file_id: EditionedFileId) -> Option<&[SyntaxError]> {
-    #[salsa_macros::tracked(return_ref)]
+    #[salsa_macros::tracked(returns(ref))]
     fn parse_errors(db: &dyn RootQueryDb, file_id: EditionedFileId) -> Option<Box<[SyntaxError]>> {
         let errors = db.parse(file_id).errors();
         match &*errors {
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/lang_item.rs b/src/tools/rust-analyzer/crates/hir-def/src/lang_item.rs
index 59344641f47..4ad44775ea1 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/lang_item.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/lang_item.rs
@@ -85,7 +85,7 @@ impl LangItemTarget {
 }
 
 /// Salsa query. This will look for lang items in a specific crate.
-#[salsa_macros::tracked(return_ref)]
+#[salsa_macros::tracked(returns(ref))]
 pub fn crate_lang_items(db: &dyn DefDatabase, krate: Crate) -> Option<Box<LangItems>> {
     let _p = tracing::info_span!("crate_lang_items_query").entered();
 
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/builtin_fn_macro.rs b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/builtin_fn_macro.rs
index 3027aff3163..293868df613 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/builtin_fn_macro.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/builtin_fn_macro.rs
@@ -510,24 +510,6 @@ fn main() { "s"; }
 }
 
 #[test]
-fn test_concat_idents_expand() {
-    check(
-        r##"
-#[rustc_builtin_macro]
-macro_rules! concat_idents {}
-
-fn main() { concat_idents!(foo, bar); }
-"##,
-        expect![[r##"
-#[rustc_builtin_macro]
-macro_rules! concat_idents {}
-
-fn main() { foobar; }
-"##]],
-    );
-}
-
-#[test]
 fn test_quote_string() {
     check(
         r##"
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres.rs
index d4b30a1d3e6..f337f83156a 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/nameres.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres.rs
@@ -381,15 +381,15 @@ mod __ {
     #[salsa_macros::tracked]
     pub(crate) struct DefMapPair<'db> {
         #[tracked]
-        #[return_ref]
+        #[returns(ref)]
         pub(crate) def_map: DefMap,
-        #[return_ref]
+        #[returns(ref)]
         pub(crate) local: LocalDefMap,
     }
 }
 pub(crate) use __::DefMapPair;
 
-#[salsa_macros::tracked(return_ref)]
+#[salsa_macros::tracked(returns(ref))]
 pub(crate) fn crate_local_def_map(db: &dyn DefDatabase, crate_id: Crate) -> DefMapPair<'_> {
     let krate = crate_id.data(db);
     let _p = tracing::info_span!(
@@ -420,7 +420,7 @@ pub(crate) fn crate_local_def_map(db: &dyn DefDatabase, crate_id: Crate) -> DefM
     DefMapPair::new(db, def_map, local_def_map)
 }
 
-#[salsa_macros::tracked(return_ref)]
+#[salsa_macros::tracked(returns(ref))]
 pub fn block_def_map(db: &dyn DefDatabase, block_id: BlockId) -> DefMap {
     let BlockLoc { ast_id, module } = block_id.lookup(db);
 
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres/assoc.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres/assoc.rs
index d45709b8b90..86225d33b4e 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/nameres/assoc.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres/assoc.rs
@@ -75,7 +75,7 @@ impl TraitItems {
         })
     }
 
-    pub fn attribute_calls(&self) -> impl Iterator<Item = (AstId<ast::Item>, MacroCallId)> + '_ {
+    pub fn macro_calls(&self) -> impl Iterator<Item = (AstId<ast::Item>, MacroCallId)> + '_ {
         self.macro_calls.iter().flat_map(|it| it.iter()).copied()
     }
 }
@@ -109,7 +109,7 @@ impl ImplItems {
         (Arc::new(ImplItems { items, macro_calls }), DefDiagnostics::new(diagnostics))
     }
 
-    pub fn attribute_calls(&self) -> impl Iterator<Item = (AstId<ast::Item>, MacroCallId)> + '_ {
+    pub fn macro_calls(&self) -> impl Iterator<Item = (AstId<ast::Item>, MacroCallId)> + '_ {
         self.macro_calls.iter().flat_map(|it| it.iter()).copied()
     }
 }
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/test_db.rs b/src/tools/rust-analyzer/crates/hir-def/src/test_db.rs
index 6c995ab6c23..e30a5b65a1f 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/test_db.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/test_db.rs
@@ -30,9 +30,18 @@ pub(crate) struct TestDB {
 
 impl Default for TestDB {
     fn default() -> Self {
+        let events = <Arc<Mutex<Option<Vec<salsa::Event>>>>>::default();
         let mut this = Self {
-            storage: Default::default(),
-            events: Default::default(),
+            storage: salsa::Storage::new(Some(Box::new({
+                let events = events.clone();
+                move |event| {
+                    let mut events = events.lock().unwrap();
+                    if let Some(events) = &mut *events {
+                        events.push(event);
+                    }
+                }
+            }))),
+            events,
             files: Default::default(),
             crates_map: Default::default(),
         };
@@ -45,15 +54,7 @@ impl Default for TestDB {
 }
 
 #[salsa_macros::db]
-impl salsa::Database for TestDB {
-    fn salsa_event(&self, event: &dyn std::ops::Fn() -> salsa::Event) {
-        let mut events = self.events.lock().unwrap();
-        if let Some(events) = &mut *events {
-            let event = event();
-            events.push(event);
-        }
-    }
-}
+impl salsa::Database for TestDB {}
 
 impl fmt::Debug for TestDB {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/builtin/fn_macro.rs b/src/tools/rust-analyzer/crates/hir-expand/src/builtin/fn_macro.rs
index 539c7277284..3180b8dae10 100644
--- a/src/tools/rust-analyzer/crates/hir-expand/src/builtin/fn_macro.rs
+++ b/src/tools/rust-analyzer/crates/hir-expand/src/builtin/fn_macro.rs
@@ -140,7 +140,6 @@ register_builtin! {
     EagerExpander:
     (compile_error, CompileError) => compile_error_expand,
     (concat, Concat) => concat_expand,
-    (concat_idents, ConcatIdents) => concat_idents_expand,
     (concat_bytes, ConcatBytes) => concat_bytes_expand,
     (include, Include) => include_expand,
     (include_bytes, IncludeBytes) => include_bytes_expand,
@@ -660,30 +659,6 @@ fn concat_bytes_expand_subtree(
     Ok(())
 }
 
-fn concat_idents_expand(
-    _db: &dyn ExpandDatabase,
-    _arg_id: MacroCallId,
-    tt: &tt::TopSubtree,
-    span: Span,
-) -> ExpandResult<tt::TopSubtree> {
-    let mut err = None;
-    let mut ident = String::new();
-    for (i, t) in tt.iter().enumerate() {
-        match t {
-            TtElement::Leaf(tt::Leaf::Ident(id)) => {
-                ident.push_str(id.sym.as_str());
-            }
-            TtElement::Leaf(tt::Leaf::Punct(punct)) if i % 2 == 1 && punct.char == ',' => (),
-            _ => {
-                err.get_or_insert(ExpandError::other(span, "unexpected token"));
-            }
-        }
-    }
-    // FIXME merge spans
-    let ident = tt::Ident { sym: Symbol::intern(&ident), span, is_raw: tt::IdentIsRaw::No };
-    ExpandResult { value: quote!(span =>#ident), err }
-}
-
 fn relative_file(
     db: &dyn ExpandDatabase,
     call_id: MacroCallId,
diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/files.rs b/src/tools/rust-analyzer/crates/hir-expand/src/files.rs
index 321ee8feb9a..8024823cbc5 100644
--- a/src/tools/rust-analyzer/crates/hir-expand/src/files.rs
+++ b/src/tools/rust-analyzer/crates/hir-expand/src/files.rs
@@ -42,6 +42,49 @@ impl FilePosition {
         FilePositionWrapper { file_id: self.file_id.file_id(db), offset: self.offset }
     }
 }
+
+impl From<FileRange> for HirFileRange {
+    fn from(value: FileRange) -> Self {
+        HirFileRange { file_id: value.file_id.into(), range: value.range }
+    }
+}
+
+impl From<FilePosition> for HirFilePosition {
+    fn from(value: FilePosition) -> Self {
+        HirFilePosition { file_id: value.file_id.into(), offset: value.offset }
+    }
+}
+
+impl FilePositionWrapper<span::FileId> {
+    pub fn with_edition(self, db: &dyn ExpandDatabase, edition: span::Edition) -> FilePosition {
+        FilePositionWrapper {
+            file_id: EditionedFileId::new(db, self.file_id, edition),
+            offset: self.offset,
+        }
+    }
+}
+
+impl FileRangeWrapper<span::FileId> {
+    pub fn with_edition(self, db: &dyn ExpandDatabase, edition: span::Edition) -> FileRange {
+        FileRangeWrapper {
+            file_id: EditionedFileId::new(db, self.file_id, edition),
+            range: self.range,
+        }
+    }
+}
+
+impl<T> InFileWrapper<span::FileId, T> {
+    pub fn with_edition(self, db: &dyn ExpandDatabase, edition: span::Edition) -> InRealFile<T> {
+        InRealFile { file_id: EditionedFileId::new(db, self.file_id, edition), value: self.value }
+    }
+}
+
+impl HirFileRange {
+    pub fn file_range(self) -> Option<FileRange> {
+        Some(FileRange { file_id: self.file_id.file_id()?, range: self.range })
+    }
+}
+
 #[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)]
 pub struct FileRangeWrapper<FileKind> {
     pub file_id: FileKind,
@@ -194,6 +237,9 @@ impl<FileId: Copy, N: AstNode> InFileWrapper<FileId, N> {
     pub fn syntax(&self) -> InFileWrapper<FileId, &SyntaxNode> {
         self.with_value(self.value.syntax())
     }
+    pub fn node_file_range(&self) -> FileRangeWrapper<FileId> {
+        FileRangeWrapper { file_id: self.file_id, range: self.value.syntax().text_range() }
+    }
 }
 
 impl<FileId: Copy, N: AstNode> InFileWrapper<FileId, &N> {
@@ -204,9 +250,9 @@ impl<FileId: Copy, N: AstNode> InFileWrapper<FileId, &N> {
 }
 
 // region:specific impls
-impl<SN: Borrow<SyntaxNode>> InRealFile<SN> {
-    pub fn file_range(&self) -> FileRange {
-        FileRange { file_id: self.file_id, range: self.value.borrow().text_range() }
+impl<FileId: Copy, SN: Borrow<SyntaxNode>> InFileWrapper<FileId, SN> {
+    pub fn file_range(&self) -> FileRangeWrapper<FileId> {
+        FileRangeWrapper { file_id: self.file_id, range: self.value.borrow().text_range() }
     }
 }
 
diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/lib.rs b/src/tools/rust-analyzer/crates/hir-expand/src/lib.rs
index d844d8f41ee..6ecac1463f5 100644
--- a/src/tools/rust-analyzer/crates/hir-expand/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/hir-expand/src/lib.rs
@@ -392,6 +392,10 @@ impl HirFileId {
         }
     }
 
+    pub fn call_node(self, db: &dyn ExpandDatabase) -> Option<InFile<SyntaxNode>> {
+        Some(db.lookup_intern_macro_call(self.macro_file()?).to_node(db))
+    }
+
     pub fn as_builtin_derive_attr_node(
         &self,
         db: &dyn ExpandDatabase,
@@ -848,7 +852,10 @@ impl ExpansionInfo {
         map_node_range_up(db, &self.exp_map, range)
     }
 
-    /// Maps up the text range out of the expansion into is macro call.
+    /// Maps up the text range out of the expansion into its macro call.
+    ///
+    /// Note that this may return multiple ranges as we lose the precise association between input to output
+    /// and as such we may consider inputs that are unrelated.
     pub fn map_range_up_once(
         &self,
         db: &dyn ExpandDatabase,
@@ -864,11 +871,10 @@ impl ExpansionInfo {
                 InFile { file_id, value: smallvec::smallvec![span.range + anchor_offset] }
             }
             SpanMap::ExpansionSpanMap(arg_map) => {
-                let arg_range = self
-                    .arg
-                    .value
-                    .as_ref()
-                    .map_or_else(|| TextRange::empty(TextSize::from(0)), |it| it.text_range());
+                let Some(arg_node) = &self.arg.value else {
+                    return InFile::new(self.arg.file_id, smallvec::smallvec![]);
+                };
+                let arg_range = arg_node.text_range();
                 InFile::new(
                     self.arg.file_id,
                     arg_map
diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/prettify_macro_expansion_.rs b/src/tools/rust-analyzer/crates/hir-expand/src/prettify_macro_expansion_.rs
index 11cc434c2d8..6134c3a36b9 100644
--- a/src/tools/rust-analyzer/crates/hir-expand/src/prettify_macro_expansion_.rs
+++ b/src/tools/rust-analyzer/crates/hir-expand/src/prettify_macro_expansion_.rs
@@ -20,42 +20,46 @@ pub fn prettify_macro_expansion(
     let span_offset = syn.text_range().start();
     let target_crate = target_crate_id.data(db);
     let mut syntax_ctx_id_to_dollar_crate_replacement = FxHashMap::default();
-    syntax_bridge::prettify_macro_expansion::prettify_macro_expansion(syn, &mut |dollar_crate| {
-        let ctx = span_map.span_at(dollar_crate.text_range().start() + span_offset).ctx;
-        let replacement =
-            syntax_ctx_id_to_dollar_crate_replacement.entry(ctx).or_insert_with(|| {
-                let macro_call_id =
-                    ctx.outer_expn(db).expect("`$crate` cannot come from `SyntaxContextId::ROOT`");
-                let macro_call = db.lookup_intern_macro_call(macro_call_id.into());
-                let macro_def_crate = macro_call.def.krate;
-                // First, if this is the same crate as the macro, nothing will work but `crate`.
-                // If not, if the target trait has the macro's crate as a dependency, using the dependency name
-                // will work in inserted code and match the user's expectation.
-                // If not, the crate's display name is what the dependency name is likely to be once such dependency
-                // is inserted, and also understandable to the user.
-                // Lastly, if nothing else found, resort to leaving `$crate`.
-                if target_crate_id == macro_def_crate {
-                    make::tokens::crate_kw()
-                } else if let Some(dep) =
-                    target_crate.dependencies.iter().find(|dep| dep.crate_id == macro_def_crate)
-                {
-                    make::tokens::ident(dep.name.as_str())
-                } else if let Some(crate_name) = &macro_def_crate.extra_data(db).display_name {
-                    make::tokens::ident(crate_name.crate_name().as_str())
-                } else {
-                    return dollar_crate.clone();
-                }
-            });
-        if replacement.text() == "$crate" {
-            // The parent may have many children, and looking for the token may yield incorrect results.
-            return dollar_crate.clone();
-        }
-        // We need to `clone_subtree()` but rowan doesn't provide such operation for tokens.
-        let parent = replacement.parent().unwrap().clone_subtree().clone_for_update();
-        parent
-            .children_with_tokens()
-            .filter_map(NodeOrToken::into_token)
-            .find(|it| it.kind() == replacement.kind())
-            .unwrap()
-    })
+    syntax_bridge::prettify_macro_expansion::prettify_macro_expansion(
+        syn,
+        &mut |dollar_crate| {
+            let ctx = span_map.span_at(dollar_crate.text_range().start() + span_offset).ctx;
+            let replacement =
+                syntax_ctx_id_to_dollar_crate_replacement.entry(ctx).or_insert_with(|| {
+                    let macro_call_id = ctx
+                        .outer_expn(db)
+                        .expect("`$crate` cannot come from `SyntaxContextId::ROOT`");
+                    let macro_call = db.lookup_intern_macro_call(macro_call_id.into());
+                    let macro_def_crate = macro_call.def.krate;
+                    // First, if this is the same crate as the macro, nothing will work but `crate`.
+                    // If not, if the target trait has the macro's crate as a dependency, using the dependency name
+                    // will work in inserted code and match the user's expectation.
+                    // If not, the crate's display name is what the dependency name is likely to be once such dependency
+                    // is inserted, and also understandable to the user.
+                    // Lastly, if nothing else found, resort to leaving `$crate`.
+                    if target_crate_id == macro_def_crate {
+                        make::tokens::crate_kw()
+                    } else if let Some(dep) =
+                        target_crate.dependencies.iter().find(|dep| dep.crate_id == macro_def_crate)
+                    {
+                        make::tokens::ident(dep.name.as_str())
+                    } else if let Some(crate_name) = &macro_def_crate.extra_data(db).display_name {
+                        make::tokens::ident(crate_name.crate_name().as_str())
+                    } else {
+                        return dollar_crate.clone();
+                    }
+                });
+            if replacement.text() == "$crate" {
+                // The parent may have many children, and looking for the token may yield incorrect results.
+                return None;
+            }
+            // We need to `clone_subtree()` but rowan doesn't provide such operation for tokens.
+            let parent = replacement.parent().unwrap().clone_subtree().clone_for_update();
+            parent
+                .children_with_tokens()
+                .filter_map(NodeOrToken::into_token)
+                .find(|it| it.kind() == replacement.kind())
+        },
+        |_| (),
+    )
 }
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs b/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs
index cd799c03ddf..22b96b55cbb 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs
@@ -259,7 +259,7 @@ impl chalk_solve::RustIrDatabase<Interner> for ChalkContext<'_> {
     }
     fn well_known_trait_id(
         &self,
-        well_known_trait: rust_ir::WellKnownTrait,
+        well_known_trait: WellKnownTrait,
     ) -> Option<chalk_ir::TraitId<Interner>> {
         let lang_attr = lang_item_from_well_known_trait(well_known_trait);
         let trait_ = lang_attr.resolve_trait(self.db, self.krate)?;
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/expr.rs b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/expr.rs
index e4a23cbbacf..9eb7ffe1c71 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/expr.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/expr.rs
@@ -25,7 +25,7 @@ use triomphe::Arc;
 use typed_arena::Arena;
 
 use crate::{
-    Adjust, InferenceResult, Interner, Ty, TyExt, TyKind,
+    Adjust, InferenceResult, Interner, TraitEnvironment, Ty, TyExt, TyKind,
     db::HirDatabase,
     diagnostics::match_check::{
         self,
@@ -74,8 +74,9 @@ impl BodyValidationDiagnostic {
         let _p = tracing::info_span!("BodyValidationDiagnostic::collect").entered();
         let infer = db.infer(owner);
         let body = db.body(owner);
+        let env = db.trait_environment_for_body(owner);
         let mut validator =
-            ExprValidator { owner, body, infer, diagnostics: Vec::new(), validate_lints };
+            ExprValidator { owner, body, infer, diagnostics: Vec::new(), validate_lints, env };
         validator.validate_body(db);
         validator.diagnostics
     }
@@ -85,6 +86,7 @@ struct ExprValidator {
     owner: DefWithBodyId,
     body: Arc<Body>,
     infer: Arc<InferenceResult>,
+    env: Arc<TraitEnvironment>,
     diagnostics: Vec<BodyValidationDiagnostic>,
     validate_lints: bool,
 }
@@ -190,7 +192,7 @@ impl ExprValidator {
             return;
         }
 
-        let cx = MatchCheckCtx::new(self.owner.module(db), self.owner, db);
+        let cx = MatchCheckCtx::new(self.owner.module(db), self.owner, db, self.env.clone());
 
         let pattern_arena = Arena::new();
         let mut m_arms = Vec::with_capacity(arms.len());
@@ -317,11 +319,14 @@ impl ExprValidator {
             return;
         };
         let pattern_arena = Arena::new();
-        let cx = MatchCheckCtx::new(self.owner.module(db), self.owner, db);
+        let cx = MatchCheckCtx::new(self.owner.module(db), self.owner, db, self.env.clone());
         for stmt in &**statements {
             let &Statement::Let { pat, initializer, else_branch: None, .. } = stmt else {
                 continue;
             };
+            if self.infer.type_mismatch_for_pat(pat).is_some() {
+                continue;
+            }
             let Some(initializer) = initializer else { continue };
             let ty = &self.infer[initializer];
             if ty.contains_unknown() {
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs
index 785277d70c6..dd82a0f45ca 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs
@@ -12,9 +12,10 @@ use rustc_pattern_analysis::{
 };
 use smallvec::{SmallVec, smallvec};
 use stdx::never;
+use triomphe::Arc;
 
 use crate::{
-    AdtId, Interner, Scalar, Ty, TyExt, TyKind,
+    AdtId, Interner, Scalar, TraitEnvironment, Ty, TyExt, TyKind,
     db::HirDatabase,
     infer::normalize,
     inhabitedness::{is_enum_variant_uninhabited_from, is_ty_uninhabited_from},
@@ -69,13 +70,19 @@ pub(crate) struct MatchCheckCtx<'db> {
     body: DefWithBodyId,
     pub(crate) db: &'db dyn HirDatabase,
     exhaustive_patterns: bool,
+    env: Arc<TraitEnvironment>,
 }
 
 impl<'db> MatchCheckCtx<'db> {
-    pub(crate) fn new(module: ModuleId, body: DefWithBodyId, db: &'db dyn HirDatabase) -> Self {
+    pub(crate) fn new(
+        module: ModuleId,
+        body: DefWithBodyId,
+        db: &'db dyn HirDatabase,
+        env: Arc<TraitEnvironment>,
+    ) -> Self {
         let def_map = module.crate_def_map(db);
         let exhaustive_patterns = def_map.is_unstable_feature_enabled(&sym::exhaustive_patterns);
-        Self { module, body, db, exhaustive_patterns }
+        Self { module, body, db, exhaustive_patterns, env }
     }
 
     pub(crate) fn compute_match_usefulness(
@@ -100,7 +107,7 @@ impl<'db> MatchCheckCtx<'db> {
     }
 
     fn is_uninhabited(&self, ty: &Ty) -> bool {
-        is_ty_uninhabited_from(self.db, ty, self.module)
+        is_ty_uninhabited_from(self.db, ty, self.module, self.env.clone())
     }
 
     /// Returns whether the given ADT is from another crate declared `#[non_exhaustive]`.
@@ -459,8 +466,13 @@ impl PatCx for MatchCheckCtx<'_> {
                 } else {
                     let mut variants = IndexVec::with_capacity(enum_data.variants.len());
                     for &(variant, _) in enum_data.variants.iter() {
-                        let is_uninhabited =
-                            is_enum_variant_uninhabited_from(cx.db, variant, subst, cx.module);
+                        let is_uninhabited = is_enum_variant_uninhabited_from(
+                            cx.db,
+                            variant,
+                            subst,
+                            cx.module,
+                            self.env.clone(),
+                        );
                         let visibility = if is_uninhabited {
                             VariantVisibility::Empty
                         } else {
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/display.rs b/src/tools/rust-analyzer/crates/hir-ty/src/display.rs
index f0989d9de91..f210dd8799f 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/display.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/display.rs
@@ -1463,6 +1463,8 @@ impl HirDisplay for Ty {
                     }
                     if f.closure_style == ClosureStyle::RANotation || !sig.ret().is_unit() {
                         write!(f, " -> ")?;
+                        // FIXME: We display `AsyncFn` as `-> impl Future`, but this is hard to fix because
+                        // we don't have a trait environment here, required to normalize `<Ret as Future>::Output`.
                         sig.ret().hir_fmt(f)?;
                     }
                 } else {
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/closure.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/closure.rs
index 800897c6fc3..bd57ca89162 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/closure.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/closure.rs
@@ -38,7 +38,7 @@ use crate::{
     infer::{BreakableKind, CoerceMany, Diverges, coerce::CoerceNever},
     make_binders,
     mir::{BorrowKind, MirSpan, MutBorrowKind, ProjectionElem},
-    to_chalk_trait_id,
+    to_assoc_type_id, to_chalk_trait_id,
     traits::FnTrait,
     utils::{self, elaborate_clause_supertraits},
 };
@@ -245,7 +245,7 @@ impl InferenceContext<'_> {
     }
 
     fn deduce_closure_kind_from_predicate_clauses(
-        &self,
+        &mut self,
         expected_ty: &Ty,
         clauses: impl DoubleEndedIterator<Item = WhereClause>,
         closure_kind: ClosureKind,
@@ -378,7 +378,7 @@ impl InferenceContext<'_> {
     }
 
     fn deduce_sig_from_projection(
-        &self,
+        &mut self,
         closure_kind: ClosureKind,
         projection_ty: &ProjectionTy,
         projected_ty: &Ty,
@@ -392,13 +392,16 @@ impl InferenceContext<'_> {
 
         // For now, we only do signature deduction based off of the `Fn` and `AsyncFn` traits,
         // for closures and async closures, respectively.
-        match closure_kind {
-            ClosureKind::Closure | ClosureKind::Async
-                if self.fn_trait_kind_from_trait_id(trait_).is_some() =>
-            {
-                self.extract_sig_from_projection(projection_ty, projected_ty)
-            }
-            _ => None,
+        let fn_trait_kind = self.fn_trait_kind_from_trait_id(trait_)?;
+        if !matches!(closure_kind, ClosureKind::Closure | ClosureKind::Async) {
+            return None;
+        }
+        if fn_trait_kind.is_async() {
+            // If the expected trait is `AsyncFn(...) -> X`, we don't know what the return type is,
+            // but we do know it must implement `Future<Output = X>`.
+            self.extract_async_fn_sig_from_projection(projection_ty, projected_ty)
+        } else {
+            self.extract_sig_from_projection(projection_ty, projected_ty)
         }
     }
 
@@ -424,6 +427,39 @@ impl InferenceContext<'_> {
         )))
     }
 
+    fn extract_async_fn_sig_from_projection(
+        &mut self,
+        projection_ty: &ProjectionTy,
+        projected_ty: &Ty,
+    ) -> Option<FnSubst<Interner>> {
+        let arg_param_ty = projection_ty.substitution.as_slice(Interner)[1].assert_ty_ref(Interner);
+
+        let TyKind::Tuple(_, input_tys) = arg_param_ty.kind(Interner) else {
+            return None;
+        };
+
+        let ret_param_future_output = projected_ty;
+        let ret_param_future = self.table.new_type_var();
+        let future_output =
+            LangItem::FutureOutput.resolve_type_alias(self.db, self.resolver.krate())?;
+        let future_projection = crate::AliasTy::Projection(crate::ProjectionTy {
+            associated_ty_id: to_assoc_type_id(future_output),
+            substitution: Substitution::from1(Interner, ret_param_future.clone()),
+        });
+        self.table.register_obligation(
+            crate::AliasEq { alias: future_projection, ty: ret_param_future_output.clone() }
+                .cast(Interner),
+        );
+
+        Some(FnSubst(Substitution::from_iter(
+            Interner,
+            input_tys.iter(Interner).map(|t| t.cast(Interner)).chain(Some(GenericArg::new(
+                Interner,
+                chalk_ir::GenericArgData::Ty(ret_param_future),
+            ))),
+        )))
+    }
+
     fn fn_trait_kind_from_trait_id(&self, trait_id: hir_def::TraitId) -> Option<FnTrait> {
         FnTrait::from_lang_item(self.db.lang_attr(trait_id.into())?)
     }
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/inhabitedness.rs b/src/tools/rust-analyzer/crates/hir-ty/src/inhabitedness.rs
index e0c3279d3fb..e81a5e3c311 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/inhabitedness.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/inhabitedness.rs
@@ -7,17 +7,24 @@ use chalk_ir::{
 };
 use hir_def::{AdtId, EnumVariantId, ModuleId, VariantId, visibility::Visibility};
 use rustc_hash::FxHashSet;
+use triomphe::Arc;
 
 use crate::{
-    Binders, Interner, Substitution, Ty, TyKind, consteval::try_const_usize, db::HirDatabase,
+    AliasTy, Binders, Interner, Substitution, TraitEnvironment, Ty, TyKind,
+    consteval::try_const_usize, db::HirDatabase,
 };
 
 // FIXME: Turn this into a query, it can be quite slow
 /// Checks whether a type is visibly uninhabited from a particular module.
-pub(crate) fn is_ty_uninhabited_from(db: &dyn HirDatabase, ty: &Ty, target_mod: ModuleId) -> bool {
+pub(crate) fn is_ty_uninhabited_from(
+    db: &dyn HirDatabase,
+    ty: &Ty,
+    target_mod: ModuleId,
+    env: Arc<TraitEnvironment>,
+) -> bool {
     let _p = tracing::info_span!("is_ty_uninhabited_from", ?ty).entered();
     let mut uninhabited_from =
-        UninhabitedFrom { target_mod, db, max_depth: 500, recursive_ty: FxHashSet::default() };
+        UninhabitedFrom { target_mod, db, max_depth: 500, recursive_ty: FxHashSet::default(), env };
     let inhabitedness = ty.visit_with(&mut uninhabited_from, DebruijnIndex::INNERMOST);
     inhabitedness == BREAK_VISIBLY_UNINHABITED
 }
@@ -29,11 +36,12 @@ pub(crate) fn is_enum_variant_uninhabited_from(
     variant: EnumVariantId,
     subst: &Substitution,
     target_mod: ModuleId,
+    env: Arc<TraitEnvironment>,
 ) -> bool {
     let _p = tracing::info_span!("is_enum_variant_uninhabited_from").entered();
 
     let mut uninhabited_from =
-        UninhabitedFrom { target_mod, db, max_depth: 500, recursive_ty: FxHashSet::default() };
+        UninhabitedFrom { target_mod, db, max_depth: 500, recursive_ty: FxHashSet::default(), env };
     let inhabitedness = uninhabited_from.visit_variant(variant.into(), subst);
     inhabitedness == BREAK_VISIBLY_UNINHABITED
 }
@@ -44,6 +52,7 @@ struct UninhabitedFrom<'a> {
     // guard for preventing stack overflow in non trivial non terminating types
     max_depth: usize,
     db: &'a dyn HirDatabase,
+    env: Arc<TraitEnvironment>,
 }
 
 const CONTINUE_OPAQUELY_INHABITED: ControlFlow<VisiblyUninhabited> = Continue(());
@@ -78,6 +87,12 @@ impl TypeVisitor<Interner> for UninhabitedFrom<'_> {
                 Some(0) | None => CONTINUE_OPAQUELY_INHABITED,
                 Some(1..) => item_ty.super_visit_with(self, outer_binder),
             },
+            TyKind::Alias(AliasTy::Projection(projection)) => {
+                // FIXME: I think this currently isn't used for monomorphized bodies, so there is no need to handle
+                // `TyKind::AssociatedType`, but perhaps in the future it will.
+                let normalized = self.db.normalize_projection(projection.clone(), self.env.clone());
+                self.visit_ty(&normalized, outer_binder)
+            }
             _ => CONTINUE_OPAQUELY_INHABITED,
         };
         self.recursive_ty.remove(ty);
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim.rs
index 7cf948b178e..90c52ee96f1 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim.rs
@@ -1121,7 +1121,7 @@ impl Evaluator<'_> {
                 // We don't call any drop glue yet, so there is nothing here
                 Ok(())
             }
-            "transmute" => {
+            "transmute" | "transmute_unchecked" => {
                 let [arg] = args else {
                     return Err(MirEvalError::InternalError(
                         "transmute arg is not provided".into(),
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs
index 7fcc89e5183..e6caf2d8d97 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs
@@ -25,7 +25,7 @@ use syntax::TextRange;
 use triomphe::Arc;
 
 use crate::{
-    Adjust, Adjustment, AutoBorrow, CallableDefId, TyBuilder, TyExt,
+    Adjust, Adjustment, AutoBorrow, CallableDefId, TraitEnvironment, TyBuilder, TyExt,
     consteval::ConstEvalError,
     db::{HirDatabase, InternedClosure, InternedClosureId},
     display::{DisplayTarget, HirDisplay, hir_display_with_store},
@@ -79,6 +79,7 @@ struct MirLowerCtx<'db> {
     infer: &'db InferenceResult,
     resolver: Resolver<'db>,
     drop_scopes: Vec<DropScope>,
+    env: Arc<TraitEnvironment>,
 }
 
 // FIXME: Make this smaller, its stored in database queries
@@ -288,6 +289,7 @@ impl<'ctx> MirLowerCtx<'ctx> {
             closures: vec![],
         };
         let resolver = owner.resolver(db);
+        let env = db.trait_environment_for_body(owner);
 
         MirLowerCtx {
             result: mir,
@@ -300,6 +302,7 @@ impl<'ctx> MirLowerCtx<'ctx> {
             labeled_loop_blocks: Default::default(),
             discr_temp: None,
             drop_scopes: vec![DropScope::default()],
+            env,
         }
     }
 
@@ -944,10 +947,7 @@ impl<'ctx> MirLowerCtx<'ctx> {
                     let cast_kind = if source_ty.as_reference().is_some() {
                         CastKind::PointerCoercion(PointerCast::ArrayToPointer)
                     } else {
-                        let mut table = InferenceTable::new(
-                            self.db,
-                            self.db.trait_environment_for_body(self.owner),
-                        );
+                        let mut table = InferenceTable::new(self.db, self.env.clone());
                         cast_kind(&mut table, &source_ty, &target_ty)?
                     };
 
@@ -1412,11 +1412,8 @@ impl<'ctx> MirLowerCtx<'ctx> {
     }
 
     fn lower_literal_to_operand(&mut self, ty: Ty, l: &Literal) -> Result<Operand> {
-        let size = || {
-            self.db
-                .layout_of_ty(ty.clone(), self.db.trait_environment_for_body(self.owner))
-                .map(|it| it.size.bytes_usize())
-        };
+        let size =
+            || self.db.layout_of_ty(ty.clone(), self.env.clone()).map(|it| it.size.bytes_usize());
         const USIZE_SIZE: usize = size_of::<usize>();
         let bytes: Box<[_]> = match l {
             hir_def::hir::Literal::String(b) => {
@@ -1723,7 +1720,12 @@ impl<'ctx> MirLowerCtx<'ctx> {
     }
 
     fn is_uninhabited(&self, expr_id: ExprId) -> bool {
-        is_ty_uninhabited_from(self.db, &self.infer[expr_id], self.owner.module(self.db))
+        is_ty_uninhabited_from(
+            self.db,
+            &self.infer[expr_id],
+            self.owner.module(self.db),
+            self.env.clone(),
+        )
     }
 
     /// This function push `StorageLive` statement for the binding, and applies changes to add `StorageDead` and
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/test_db.rs b/src/tools/rust-analyzer/crates/hir-ty/src/test_db.rs
index 8f0d17c9dc4..d049c678e2d 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/test_db.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/test_db.rs
@@ -27,9 +27,18 @@ pub(crate) struct TestDB {
 
 impl Default for TestDB {
     fn default() -> Self {
+        let events = <Arc<Mutex<Option<Vec<salsa::Event>>>>>::default();
         let mut this = Self {
-            storage: Default::default(),
-            events: Default::default(),
+            storage: salsa::Storage::new(Some(Box::new({
+                let events = events.clone();
+                move |event| {
+                    let mut events = events.lock().unwrap();
+                    if let Some(events) = &mut *events {
+                        events.push(event);
+                    }
+                }
+            }))),
+            events,
             files: Default::default(),
             crates_map: Default::default(),
         };
@@ -103,14 +112,7 @@ impl SourceDatabase for TestDB {
 }
 
 #[salsa_macros::db]
-impl salsa::Database for TestDB {
-    fn salsa_event(&self, event: &dyn std::ops::Fn() -> salsa::Event) {
-        let mut events = self.events.lock().unwrap();
-        if let Some(events) = &mut *events {
-            events.push(event());
-        }
-    }
-}
+impl salsa::Database for TestDB {}
 
 impl panic::RefUnwindSafe for TestDB {}
 
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tests/traits.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests/traits.rs
index 2b527a4ae12..e5d1fbe9def 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/tests/traits.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests/traits.rs
@@ -4903,3 +4903,30 @@ fn main() {
         "#]],
     );
 }
+
+#[test]
+fn async_fn_return_type() {
+    check_infer(
+        r#"
+//- minicore: async_fn
+fn foo<F: AsyncFn() -> R, R>(_: F) -> R {
+    loop {}
+}
+
+fn main() {
+    foo(async move || ());
+}
+    "#,
+        expect![[r#"
+            29..30 '_': F
+            40..55 '{     loop {} }': R
+            46..53 'loop {}': !
+            51..53 '{}': ()
+            67..97 '{     ...()); }': ()
+            73..76 'foo': fn foo<impl AsyncFn() -> impl Future<Output = ()>, ()>(impl AsyncFn() -> impl Future<Output = ()>)
+            73..94 'foo(as...|| ())': ()
+            77..93 'async ... || ()': impl AsyncFn() -> impl Future<Output = ()>
+            91..93 '()': ()
+        "#]],
+    );
+}
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/traits.rs b/src/tools/rust-analyzer/crates/hir-ty/src/traits.rs
index f9f8776cff7..7414b4fc607 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/traits.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/traits.rs
@@ -291,4 +291,9 @@ impl FnTrait {
     pub fn get_id(self, db: &dyn HirDatabase, krate: Crate) -> Option<TraitId> {
         self.lang_item().resolve_trait(db, krate)
     }
+
+    #[inline]
+    pub(crate) fn is_async(self) -> bool {
+        matches!(self, FnTrait::AsyncFn | FnTrait::AsyncFnMut | FnTrait::AsyncFnOnce)
+    }
 }
diff --git a/src/tools/rust-analyzer/crates/hir/src/lib.rs b/src/tools/rust-analyzer/crates/hir/src/lib.rs
index 3a91050d15f..e8218cf8611 100644
--- a/src/tools/rust-analyzer/crates/hir/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/hir/src/lib.rs
@@ -5972,6 +5972,59 @@ impl Layout {
         }
     }
 
+    pub fn tail_padding(&self, field_size: &mut impl FnMut(usize) -> Option<u64>) -> Option<u64> {
+        match self.0.fields {
+            layout::FieldsShape::Primitive => None,
+            layout::FieldsShape::Union(_) => None,
+            layout::FieldsShape::Array { stride, count } => count.checked_sub(1).and_then(|tail| {
+                let tail_field_size = field_size(tail as usize)?;
+                let offset = stride.bytes() * tail;
+                self.0.size.bytes().checked_sub(offset)?.checked_sub(tail_field_size)
+            }),
+            layout::FieldsShape::Arbitrary { ref offsets, ref memory_index } => {
+                let tail = memory_index.last_index()?;
+                let tail_field_size = field_size(tail.0.into_raw().into_u32() as usize)?;
+                let offset = offsets.get(tail)?.bytes();
+                self.0.size.bytes().checked_sub(offset)?.checked_sub(tail_field_size)
+            }
+        }
+    }
+
+    pub fn largest_padding(
+        &self,
+        field_size: &mut impl FnMut(usize) -> Option<u64>,
+    ) -> Option<u64> {
+        match self.0.fields {
+            layout::FieldsShape::Primitive => None,
+            layout::FieldsShape::Union(_) => None,
+            layout::FieldsShape::Array { stride: _, count: 0 } => None,
+            layout::FieldsShape::Array { stride, .. } => {
+                let size = field_size(0)?;
+                stride.bytes().checked_sub(size)
+            }
+            layout::FieldsShape::Arbitrary { ref offsets, ref memory_index } => {
+                let mut reverse_index = vec![None; memory_index.len()];
+                for (src, (mem, offset)) in memory_index.iter().zip(offsets.iter()).enumerate() {
+                    reverse_index[*mem as usize] = Some((src, offset.bytes()));
+                }
+                if reverse_index.iter().any(|it| it.is_none()) {
+                    stdx::never!();
+                    return None;
+                }
+                reverse_index
+                    .into_iter()
+                    .flatten()
+                    .chain(std::iter::once((0, self.0.size.bytes())))
+                    .tuple_windows()
+                    .filter_map(|((i, start), (_, end))| {
+                        let size = field_size(i)?;
+                        end.checked_sub(start)?.checked_sub(size)
+                    })
+                    .max()
+            }
+        }
+    }
+
     pub fn enum_tag_size(&self) -> Option<usize> {
         let tag_size =
             if let layout::Variants::Multiple { tag, tag_encoding, .. } = &self.0.variants {
diff --git a/src/tools/rust-analyzer/crates/hir/src/semantics.rs b/src/tools/rust-analyzer/crates/hir/src/semantics.rs
index caa6700de9f..e01774650b1 100644
--- a/src/tools/rust-analyzer/crates/hir/src/semantics.rs
+++ b/src/tools/rust-analyzer/crates/hir/src/semantics.rs
@@ -24,7 +24,7 @@ use hir_expand::{
     attrs::collect_attrs,
     builtin::{BuiltinFnLikeExpander, EagerExpander},
     db::ExpandDatabase,
-    files::{FileRangeWrapper, InRealFile},
+    files::{FileRangeWrapper, HirFileRange, InRealFile},
     inert_attr_macro::find_builtin_attr_idx,
     mod_path::{ModPath, PathKind},
     name::AsName,
@@ -147,7 +147,7 @@ impl TypeInfo {
 }
 
 /// Primary API to get semantic information, like types, from syntax trees.
-pub struct Semantics<'db, DB> {
+pub struct Semantics<'db, DB: ?Sized> {
     pub db: &'db DB,
     imp: SemanticsImpl<'db>,
 }
@@ -262,6 +262,17 @@ impl<DB: HirDatabase> Semantics<'_, DB> {
         self.imp.file_to_module_defs(file.into())
     }
 
+    pub fn hir_file_to_module_def(&self, file: impl Into<HirFileId>) -> Option<Module> {
+        self.imp.hir_file_to_module_defs(file.into()).next()
+    }
+
+    pub fn hir_file_to_module_defs(
+        &self,
+        file: impl Into<HirFileId>,
+    ) -> impl Iterator<Item = Module> {
+        self.imp.hir_file_to_module_defs(file.into())
+    }
+
     pub fn to_adt_def(&self, a: &ast::Adt) -> Option<Adt> {
         self.imp.to_def(a)
     }
@@ -357,6 +368,15 @@ impl<'db> SemanticsImpl<'db> {
         tree
     }
 
+    pub fn adjust_edition(&self, file_id: HirFileId) -> HirFileId {
+        if let Some(editioned_file_id) = file_id.file_id() {
+            self.attach_first_edition(editioned_file_id.file_id(self.db))
+                .map_or(file_id, Into::into)
+        } else {
+            file_id
+        }
+    }
+
     pub fn find_parent_file(&self, file_id: HirFileId) -> Option<InFile<SyntaxNode>> {
         match file_id {
             HirFileId::FileId(file_id) => {
@@ -407,14 +427,10 @@ impl<'db> SemanticsImpl<'db> {
         res
     }
 
-    pub fn expand_macro_call(&self, macro_call: &ast::MacroCall) -> Option<SyntaxNode> {
-        let sa = self.analyze_no_infer(macro_call.syntax())?;
-
-        let macro_call = InFile::new(sa.file_id, macro_call);
-        let file_id = sa.expand(self.db, macro_call)?;
-
+    pub fn expand_macro_call(&self, macro_call: &ast::MacroCall) -> Option<InFile<SyntaxNode>> {
+        let file_id = self.to_def(macro_call)?;
         let node = self.parse_or_expand(file_id.into());
-        Some(node)
+        Some(InFile::new(file_id.into(), node))
     }
 
     pub fn check_cfg_attr(&self, attr: &ast::TokenTree) -> Option<bool> {
@@ -434,10 +450,7 @@ impl<'db> SemanticsImpl<'db> {
         &self,
         macro_call: &ast::MacroCall,
     ) -> Option<ExpandResult<SyntaxNode>> {
-        let sa = self.analyze_no_infer(macro_call.syntax())?;
-
-        let macro_call = InFile::new(sa.file_id, macro_call);
-        let file_id = sa.expand(self.db, macro_call)?;
+        let file_id = self.to_def(macro_call)?;
         let macro_call = self.db.lookup_intern_macro_call(file_id);
 
         let skip = matches!(
@@ -468,10 +481,10 @@ impl<'db> SemanticsImpl<'db> {
     }
 
     /// If `item` has an attribute macro attached to it, expands it.
-    pub fn expand_attr_macro(&self, item: &ast::Item) -> Option<ExpandResult<SyntaxNode>> {
+    pub fn expand_attr_macro(&self, item: &ast::Item) -> Option<ExpandResult<InFile<SyntaxNode>>> {
         let src = self.wrap_node_infile(item.clone());
         let macro_call_id = self.with_ctx(|ctx| ctx.item_to_macro_call(src.as_ref()))?;
-        Some(self.expand(macro_call_id))
+        Some(self.expand(macro_call_id).map(|it| InFile::new(macro_call_id.into(), it)))
     }
 
     pub fn expand_derive_as_pseudo_attr_macro(&self, attr: &ast::Attr) -> Option<SyntaxNode> {
@@ -574,9 +587,7 @@ impl<'db> SemanticsImpl<'db> {
         speculative_args: &ast::TokenTree,
         token_to_map: SyntaxToken,
     ) -> Option<(SyntaxNode, Vec<(SyntaxToken, u8)>)> {
-        let analyzer = self.analyze_no_infer(actual_macro_call.syntax())?;
-        let macro_call = InFile::new(analyzer.file_id, actual_macro_call);
-        let macro_file = analyzer.expansion(macro_call)?;
+        let macro_file = self.to_def(actual_macro_call)?;
         hir_expand::db::expand_speculative(
             self.db,
             macro_file,
@@ -662,7 +673,7 @@ impl<'db> SemanticsImpl<'db> {
         string: &ast::String,
     ) -> Option<Vec<(TextRange, Option<Either<PathResolution, InlineAsmOperand>>)>> {
         let string_start = string.syntax().text_range().start();
-        let token = self.wrap_token_infile(string.syntax().clone()).into_real_file().ok()?;
+        let token = self.wrap_token_infile(string.syntax().clone());
         self.descend_into_macros_breakable(token, |token, _| {
             (|| {
                 let token = token.value;
@@ -702,50 +713,95 @@ impl<'db> SemanticsImpl<'db> {
     }
 
     /// Retrieves the formatting part of the format_args! template string at the given offset.
+    ///
+    // FIXME: Type the return type
+    /// Returns the range (pre-expansion) in the string literal corresponding to the resolution,
+    /// absolute file range (post-expansion)
+    /// of the part in the format string, the corresponding string token and the resolution if it
+    /// exists.
+    // FIXME: Remove this in favor of `check_for_format_args_template_with_file`
     pub fn check_for_format_args_template(
         &self,
         original_token: SyntaxToken,
         offset: TextSize,
-    ) -> Option<(TextRange, Option<Either<PathResolution, InlineAsmOperand>>)> {
-        let string_start = original_token.text_range().start();
-        let original_token = self.wrap_token_infile(original_token).into_real_file().ok()?;
-        self.descend_into_macros_breakable(original_token, |token, _| {
-            (|| {
-                let token = token.value;
-                self.resolve_offset_in_format_args(
-                    ast::String::cast(token)?,
-                    offset.checked_sub(string_start)?,
-                )
-                .map(|(range, res)| (range + string_start, res))
-            })()
-            .map_or(ControlFlow::Continue(()), ControlFlow::Break)
-        })
+    ) -> Option<(
+        TextRange,
+        HirFileRange,
+        ast::String,
+        Option<Either<PathResolution, InlineAsmOperand>>,
+    )> {
+        let original_token =
+            self.wrap_token_infile(original_token).map(ast::String::cast).transpose()?;
+        self.check_for_format_args_template_with_file(original_token, offset)
+    }
+
+    /// Retrieves the formatting part of the format_args! template string at the given offset.
+    ///
+    // FIXME: Type the return type
+    /// Returns the range (pre-expansion) in the string literal corresponding to the resolution,
+    /// absolute file range (post-expansion)
+    /// of the part in the format string, the corresponding string token and the resolution if it
+    /// exists.
+    pub fn check_for_format_args_template_with_file(
+        &self,
+        original_token: InFile<ast::String>,
+        offset: TextSize,
+    ) -> Option<(
+        TextRange,
+        HirFileRange,
+        ast::String,
+        Option<Either<PathResolution, InlineAsmOperand>>,
+    )> {
+        let relative_offset =
+            offset.checked_sub(original_token.value.syntax().text_range().start())?;
+        self.descend_into_macros_breakable(
+            original_token.as_ref().map(|it| it.syntax().clone()),
+            |token, _| {
+                (|| {
+                    let token = token.map(ast::String::cast).transpose()?;
+                    self.resolve_offset_in_format_args(token.as_ref(), relative_offset).map(
+                        |(range, res)| {
+                            (
+                                range + original_token.value.syntax().text_range().start(),
+                                HirFileRange {
+                                    file_id: token.file_id,
+                                    range: range + token.value.syntax().text_range().start(),
+                                },
+                                token.value,
+                                res,
+                            )
+                        },
+                    )
+                })()
+                .map_or(ControlFlow::Continue(()), ControlFlow::Break)
+            },
+        )
     }
 
     fn resolve_offset_in_format_args(
         &self,
-        string: ast::String,
+        InFile { value: string, file_id }: InFile<&ast::String>,
         offset: TextSize,
     ) -> Option<(TextRange, Option<Either<PathResolution, InlineAsmOperand>>)> {
         debug_assert!(offset <= string.syntax().text_range().len());
         let literal = string.syntax().parent().filter(|it| it.kind() == SyntaxKind::LITERAL)?;
         let parent = literal.parent()?;
         if let Some(format_args) = ast::FormatArgsExpr::cast(parent.clone()) {
-            let source_analyzer = &self.analyze_no_infer(format_args.syntax())?;
-            let format_args = self.wrap_node_infile(format_args);
+            let source_analyzer =
+                &self.analyze_impl(InFile::new(file_id, format_args.syntax()), None, false)?;
             source_analyzer
-                .resolve_offset_in_format_args(self.db, format_args.as_ref(), offset)
+                .resolve_offset_in_format_args(self.db, InFile::new(file_id, &format_args), offset)
                 .map(|(range, res)| (range, res.map(Either::Left)))
         } else {
             let asm = ast::AsmExpr::cast(parent)?;
-            let source_analyzer = &self.analyze_no_infer(asm.syntax())?;
+            let source_analyzer =
+                self.analyze_impl(InFile::new(file_id, asm.syntax()), None, false)?;
             let line = asm.template().position(|it| *it.syntax() == literal)?;
-            let asm = self.wrap_node_infile(asm);
-            source_analyzer.resolve_offset_in_asm_template(asm.as_ref(), line, offset).map(
-                |(owner, (expr, range, index))| {
+            source_analyzer
+                .resolve_offset_in_asm_template(InFile::new(file_id, &asm), line, offset)
+                .map(|(owner, (expr, range, index))| {
                     (range, Some(Either::Right(InlineAsmOperand { owner, expr, index })))
-                },
-            )
+                })
         }
     }
 
@@ -778,6 +834,31 @@ impl<'db> SemanticsImpl<'db> {
         })
     }
 
+    /// Descends the token into the include expansion, if its file is an included file.
+    pub fn descend_token_into_include_expansion(
+        &self,
+        tok: InRealFile<SyntaxToken>,
+    ) -> InFile<SyntaxToken> {
+        let Some(include) =
+            self.s2d_cache.borrow_mut().get_or_insert_include_for(self.db, tok.file_id)
+        else {
+            return tok.into();
+        };
+        let span = self.db.real_span_map(tok.file_id).span_for_range(tok.value.text_range());
+        let Some(InMacroFile { file_id, value: mut mapped_tokens }) = self.with_ctx(|ctx| {
+            Some(
+                ctx.cache
+                    .get_or_insert_expansion(ctx.db, include)
+                    .map_range_down(span)?
+                    .map(SmallVec::<[_; 2]>::from_iter),
+            )
+        }) else {
+            return tok.into();
+        };
+        // We should only get one result at most
+        mapped_tokens.pop().map_or_else(|| tok.into(), |(tok, _)| InFile::new(file_id.into(), tok))
+    }
+
     /// Maps a node down by mapping its first and last token down.
     pub fn descend_node_into_attributes<N: AstNode>(&self, node: N) -> SmallVec<[N; 1]> {
         // This might not be the correct way to do this, but it works for now
@@ -793,14 +874,11 @@ impl<'db> SemanticsImpl<'db> {
             None => return res,
         };
         let file = self.find_file(node.syntax());
-        let Some(file_id) = file.file_id.file_id() else {
-            return res;
-        };
 
         if first == last {
             // node is just the token, so descend the token
             self.descend_into_macros_impl(
-                InRealFile::new(file_id, first),
+                InFile::new(file.file_id, first),
                 &mut |InFile { value, .. }, _ctx| {
                     if let Some(node) = value
                         .parent_ancestors()
@@ -815,14 +893,14 @@ impl<'db> SemanticsImpl<'db> {
         } else {
             // Descend first and last token, then zip them to look for the node they belong to
             let mut scratch: SmallVec<[_; 1]> = smallvec![];
-            self.descend_into_macros_impl(InRealFile::new(file_id, first), &mut |token, _ctx| {
+            self.descend_into_macros_impl(InFile::new(file.file_id, first), &mut |token, _ctx| {
                 scratch.push(token);
                 CONTINUE_NO_BREAKS
             });
 
             let mut scratch = scratch.into_iter();
             self.descend_into_macros_impl(
-                InRealFile::new(file_id, last),
+                InFile::new(file.file_id, last),
                 &mut |InFile { value: last, file_id: last_fid }, _ctx| {
                     if let Some(InFile { value: first, file_id: first_fid }) = scratch.next() {
                         if first_fid == last_fid {
@@ -846,49 +924,35 @@ impl<'db> SemanticsImpl<'db> {
         res
     }
 
-    // FIXME: This isn't quite right wrt to inner attributes
-    /// Does a syntactic traversal to check whether this token might be inside a macro call
-    pub fn might_be_inside_macro_call(&self, token: &SyntaxToken) -> bool {
-        token.parent_ancestors().any(|ancestor| {
+    pub fn is_inside_macro_call(&self, token: InFile<&SyntaxToken>) -> bool {
+        // FIXME: Maybe `ancestors_with_macros()` is more suitable here? Currently
+        // this is only used on real (not macro) files so this is not a problem.
+        token.value.parent_ancestors().any(|ancestor| {
             if ast::MacroCall::can_cast(ancestor.kind()) {
                 return true;
             }
-            // Check if it is an item (only items can have macro attributes) that has a non-builtin attribute.
-            let Some(item) = ast::Item::cast(ancestor) else { return false };
-            item.attrs().any(|attr| {
-                let Some(meta) = attr.meta() else { return false };
-                let Some(path) = meta.path() else { return false };
-                if let Some(attr_name) = path.as_single_name_ref() {
-                    let attr_name = attr_name.text();
-                    let attr_name = Symbol::intern(attr_name.as_str());
-                    if attr_name == sym::derive {
-                        return true;
-                    }
-                    // We ignore `#[test]` and friends in the def map, so we cannot expand them.
-                    // FIXME: We match by text. This is both hacky and incorrect (people can, and do, create
-                    // other macros named `test`). We cannot fix that unfortunately because we use this method
-                    // for speculative expansion in completion, which we cannot analyze. Fortunately, most macros
-                    // named `test` are test-like, meaning their expansion is not terribly important for IDE.
-                    if attr_name == sym::test
-                        || attr_name == sym::bench
-                        || attr_name == sym::test_case
-                        || find_builtin_attr_idx(&attr_name).is_some()
-                    {
-                        return false;
-                    }
-                }
-                let mut segments = path.segments();
-                let mut next_segment_text = || segments.next().and_then(|it| it.name_ref());
-                // `#[core::prelude::rust_2024::test]` or `#[std::prelude::rust_2024::test]`.
-                if next_segment_text().is_some_and(|it| matches!(&*it.text(), "core" | "std"))
-                    && next_segment_text().is_some_and(|it| it.text() == "prelude")
-                    && next_segment_text().is_some()
-                    && next_segment_text()
-                        .is_some_and(|it| matches!(&*it.text(), "test" | "bench" | "test_case"))
-                {
-                    return false;
+
+            let Some(item) = ast::Item::cast(ancestor) else {
+                return false;
+            };
+            // Optimization to skip the semantic check.
+            if item.attrs().all(|attr| {
+                attr.simple_name()
+                    .is_some_and(|attr| find_builtin_attr_idx(&Symbol::intern(&attr)).is_some())
+            }) {
+                return false;
+            }
+            self.with_ctx(|ctx| {
+                if ctx.item_to_macro_call(token.with_value(&item)).is_some() {
+                    return true;
                 }
-                true
+                let adt = match item {
+                    ast::Item::Struct(it) => it.into(),
+                    ast::Item::Enum(it) => it.into(),
+                    ast::Item::Union(it) => it.into(),
+                    _ => return false,
+                };
+                ctx.has_derives(token.with_value(&adt))
             })
         })
     }
@@ -898,22 +962,18 @@ impl<'db> SemanticsImpl<'db> {
         token: SyntaxToken,
         mut cb: impl FnMut(InFile<SyntaxToken>, SyntaxContext),
     ) {
-        if let Ok(token) = self.wrap_token_infile(token).into_real_file() {
-            self.descend_into_macros_impl(token, &mut |t, ctx| {
-                cb(t, ctx);
-                CONTINUE_NO_BREAKS
-            });
-        }
+        self.descend_into_macros_impl(self.wrap_token_infile(token), &mut |t, ctx| {
+            cb(t, ctx);
+            CONTINUE_NO_BREAKS
+        });
     }
 
     pub fn descend_into_macros(&self, token: SyntaxToken) -> SmallVec<[SyntaxToken; 1]> {
         let mut res = smallvec![];
-        if let Ok(token) = self.wrap_token_infile(token.clone()).into_real_file() {
-            self.descend_into_macros_impl(token, &mut |t, _ctx| {
-                res.push(t.value);
-                CONTINUE_NO_BREAKS
-            });
-        }
+        self.descend_into_macros_impl(self.wrap_token_infile(token.clone()), &mut |t, _ctx| {
+            res.push(t.value);
+            CONTINUE_NO_BREAKS
+        });
         if res.is_empty() {
             res.push(token);
         }
@@ -926,15 +986,13 @@ impl<'db> SemanticsImpl<'db> {
     ) -> SmallVec<[InFile<SyntaxToken>; 1]> {
         let mut res = smallvec![];
         let token = self.wrap_token_infile(token);
-        if let Ok(token) = token.clone().into_real_file() {
-            self.descend_into_macros_impl(token, &mut |t, ctx| {
-                if !ctx.is_opaque(self.db) {
-                    // Don't descend into opaque contexts
-                    res.push(t);
-                }
-                CONTINUE_NO_BREAKS
-            });
-        }
+        self.descend_into_macros_impl(token.clone(), &mut |t, ctx| {
+            if !ctx.is_opaque(self.db) {
+                // Don't descend into opaque contexts
+                res.push(t);
+            }
+            CONTINUE_NO_BREAKS
+        });
         if res.is_empty() {
             res.push(token);
         }
@@ -943,7 +1001,7 @@ impl<'db> SemanticsImpl<'db> {
 
     pub fn descend_into_macros_breakable<T>(
         &self,
-        token: InRealFile<SyntaxToken>,
+        token: InFile<SyntaxToken>,
         mut cb: impl FnMut(InFile<SyntaxToken>, SyntaxContext) -> ControlFlow<T>,
     ) -> Option<T> {
         self.descend_into_macros_impl(token, &mut cb)
@@ -972,33 +1030,58 @@ impl<'db> SemanticsImpl<'db> {
         r
     }
 
+    /// Descends the token into expansions, returning the tokens that matches the input
+    /// token's [`SyntaxKind`] and text.
+    pub fn descend_into_macros_exact_with_file(
+        &self,
+        token: SyntaxToken,
+    ) -> SmallVec<[InFile<SyntaxToken>; 1]> {
+        let mut r = smallvec![];
+        let text = token.text();
+        let kind = token.kind();
+
+        self.descend_into_macros_cb(token.clone(), |InFile { value, file_id }, ctx| {
+            let mapped_kind = value.kind();
+            let any_ident_match = || kind.is_any_identifier() && value.kind().is_any_identifier();
+            let matches = (kind == mapped_kind || any_ident_match())
+                && text == value.text()
+                && !ctx.is_opaque(self.db);
+            if matches {
+                r.push(InFile { value, file_id });
+            }
+        });
+        if r.is_empty() {
+            r.push(self.wrap_token_infile(token));
+        }
+        r
+    }
+
     /// Descends the token into expansions, returning the first token that matches the input
     /// token's [`SyntaxKind`] and text.
     pub fn descend_into_macros_single_exact(&self, token: SyntaxToken) -> SyntaxToken {
         let text = token.text();
         let kind = token.kind();
-        if let Ok(token) = self.wrap_token_infile(token.clone()).into_real_file() {
-            self.descend_into_macros_breakable(token, |InFile { value, file_id: _ }, _ctx| {
+        self.descend_into_macros_breakable(
+            self.wrap_token_infile(token.clone()),
+            |InFile { value, file_id: _ }, _ctx| {
                 let mapped_kind = value.kind();
                 let any_ident_match =
                     || kind.is_any_identifier() && value.kind().is_any_identifier();
                 let matches = (kind == mapped_kind || any_ident_match()) && text == value.text();
                 if matches { ControlFlow::Break(value) } else { ControlFlow::Continue(()) }
-            })
-        } else {
-            None
-        }
+            },
+        )
         .unwrap_or(token)
     }
 
     fn descend_into_macros_impl<T>(
         &self,
-        InRealFile { value: token, file_id }: InRealFile<SyntaxToken>,
+        InFile { value: token, file_id }: InFile<SyntaxToken>,
         f: &mut dyn FnMut(InFile<SyntaxToken>, SyntaxContext) -> ControlFlow<T>,
     ) -> Option<T> {
         let _p = tracing::info_span!("descend_into_macros_impl").entered();
 
-        let span = self.db.real_span_map(file_id).span_for_range(token.text_range());
+        let span = self.db.span_map(file_id).span_for_range(token.text_range());
 
         // Process the expansion of a call, pushing all tokens with our span in the expansion back onto our stack
         let process_expansion_for_token = |stack: &mut Vec<_>, macro_file| {
@@ -1022,17 +1105,16 @@ impl<'db> SemanticsImpl<'db> {
         // the tokens themselves aren't that interesting as the span that is being used to map
         // things down never changes.
         let mut stack: Vec<(_, SmallVec<[_; 2]>)> = vec![];
-        let include = self.s2d_cache.borrow_mut().get_or_insert_include_for(self.db, file_id);
+        let include = file_id.file_id().and_then(|file_id| {
+            self.s2d_cache.borrow_mut().get_or_insert_include_for(self.db, file_id)
+        });
         match include {
             Some(include) => {
                 // include! inputs are always from real files, so they only need to be handled once upfront
                 process_expansion_for_token(&mut stack, include)?;
             }
             None => {
-                stack.push((
-                    file_id.into(),
-                    smallvec![(token, SyntaxContext::root(file_id.edition(self.db)))],
-                ));
+                stack.push((file_id, smallvec![(token, span.ctx)]));
             }
         }
 
@@ -1111,16 +1193,7 @@ impl<'db> SemanticsImpl<'db> {
                             let file_id = match m_cache.get(&mcall) {
                                 Some(&it) => it,
                                 None => {
-                                    let it = token
-                                        .parent()
-                                        .and_then(|parent| {
-                                            self.analyze_impl(
-                                                InFile::new(expansion, &parent),
-                                                None,
-                                                false,
-                                            )
-                                        })?
-                                        .expand(self.db, mcall.as_ref())?;
+                                    let it = ast::MacroCall::to_def(self, mcall.as_ref())?;
                                     m_cache.insert(mcall, it);
                                     it
                                 }
@@ -1560,14 +1633,9 @@ impl<'db> SemanticsImpl<'db> {
     }
 
     pub fn resolve_macro_call2(&self, macro_call: InFile<&ast::MacroCall>) -> Option<Macro> {
-        self.with_ctx(|ctx| {
-            ctx.macro_call_to_macro_call(macro_call)
-                .and_then(|call| macro_call_to_macro_id(ctx, call))
-                .map(Into::into)
-        })
-        .or_else(|| {
-            self.analyze(macro_call.value.syntax())?.resolve_macro_call(self.db, macro_call)
-        })
+        self.to_def2(macro_call)
+            .and_then(|call| self.with_ctx(|ctx| macro_call_to_macro_id(ctx, call)))
+            .map(Into::into)
     }
 
     pub fn is_proc_macro_call(&self, macro_call: InFile<&ast::MacroCall>) -> bool {
@@ -1576,14 +1644,8 @@ impl<'db> SemanticsImpl<'db> {
     }
 
     pub fn resolve_macro_call_arm(&self, macro_call: &ast::MacroCall) -> Option<u32> {
-        let sa = self.analyze(macro_call.syntax())?;
-        self.db
-            .parse_macro_expansion(
-                sa.expand(self.db, self.wrap_node_infile(macro_call.clone()).as_ref())?,
-            )
-            .value
-            .1
-            .matched_arm
+        let file_id = self.to_def(macro_call)?;
+        self.db.parse_macro_expansion(file_id).value.1.matched_arm
     }
 
     pub fn get_unsafe_ops(&self, def: DefWithBody) -> FxHashSet<ExprOrPatSource> {
@@ -1688,10 +1750,19 @@ impl<'db> SemanticsImpl<'db> {
         T::to_def(self, src)
     }
 
+    pub fn to_def2<T: ToDef>(&self, src: InFile<&T>) -> Option<T::Def> {
+        T::to_def(self, src)
+    }
+
     fn file_to_module_defs(&self, file: FileId) -> impl Iterator<Item = Module> {
         self.with_ctx(|ctx| ctx.file_to_def(file).to_owned()).into_iter().map(Module::from)
     }
 
+    fn hir_file_to_module_defs(&self, file: HirFileId) -> impl Iterator<Item = Module> {
+        // FIXME: Do we need to care about inline modules for macro expansions?
+        self.file_to_module_defs(file.original_file_respecting_includes(self.db).file_id(self.db))
+    }
+
     pub fn scope(&self, node: &SyntaxNode) -> Option<SemanticsScope<'db>> {
         self.analyze_no_infer(node).map(|SourceAnalyzer { file_id, resolver, .. }| SemanticsScope {
             db: self.db,
diff --git a/src/tools/rust-analyzer/crates/hir/src/semantics/child_by_source.rs b/src/tools/rust-analyzer/crates/hir/src/semantics/child_by_source.rs
index 9393d08ad3f..6accf9b2e9c 100644
--- a/src/tools/rust-analyzer/crates/hir/src/semantics/child_by_source.rs
+++ b/src/tools/rust-analyzer/crates/hir/src/semantics/child_by_source.rs
@@ -36,9 +36,14 @@ impl ChildBySource for TraitId {
     fn child_by_source_to(&self, db: &dyn DefDatabase, res: &mut DynMap, file_id: HirFileId) {
         let data = db.trait_items(*self);
 
-        data.attribute_calls().filter(|(ast_id, _)| ast_id.file_id == file_id).for_each(
+        data.macro_calls().filter(|(ast_id, _)| ast_id.file_id == file_id).for_each(
             |(ast_id, call_id)| {
-                res[keys::ATTR_MACRO_CALL].insert(ast_id.to_ptr(db), call_id);
+                let ptr = ast_id.to_ptr(db);
+                if let Some(ptr) = ptr.cast::<ast::MacroCall>() {
+                    res[keys::MACRO_CALL].insert(ptr, call_id);
+                } else {
+                    res[keys::ATTR_MACRO_CALL].insert(ptr, call_id);
+                }
             },
         );
         data.items.iter().for_each(|&(_, item)| {
@@ -50,10 +55,14 @@ impl ChildBySource for TraitId {
 impl ChildBySource for ImplId {
     fn child_by_source_to(&self, db: &dyn DefDatabase, res: &mut DynMap, file_id: HirFileId) {
         let data = db.impl_items(*self);
-        // FIXME: Macro calls
-        data.attribute_calls().filter(|(ast_id, _)| ast_id.file_id == file_id).for_each(
+        data.macro_calls().filter(|(ast_id, _)| ast_id.file_id == file_id).for_each(
             |(ast_id, call_id)| {
-                res[keys::ATTR_MACRO_CALL].insert(ast_id.to_ptr(db), call_id);
+                let ptr = ast_id.to_ptr(db);
+                if let Some(ptr) = ptr.cast::<ast::MacroCall>() {
+                    res[keys::MACRO_CALL].insert(ptr, call_id);
+                } else {
+                    res[keys::ATTR_MACRO_CALL].insert(ptr, call_id);
+                }
             },
         );
         data.items.iter().for_each(|&(_, item)| {
diff --git a/src/tools/rust-analyzer/crates/hir/src/semantics/source_to_def.rs b/src/tools/rust-analyzer/crates/hir/src/semantics/source_to_def.rs
index 172af456d92..7f6c9af4740 100644
--- a/src/tools/rust-analyzer/crates/hir/src/semantics/source_to_def.rs
+++ b/src/tools/rust-analyzer/crates/hir/src/semantics/source_to_def.rs
@@ -399,19 +399,6 @@ impl SourceToDefCtx<'_, '_> {
         Some((container, label?))
     }
 
-    pub(super) fn item_to_macro_call(&mut self, src: InFile<&ast::Item>) -> Option<MacroCallId> {
-        let map = self.dyn_map(src)?;
-        map[keys::ATTR_MACRO_CALL].get(&AstPtr::new(src.value)).copied()
-    }
-
-    pub(super) fn macro_call_to_macro_call(
-        &mut self,
-        src: InFile<&ast::MacroCall>,
-    ) -> Option<MacroCallId> {
-        let map = self.dyn_map(src)?;
-        map[keys::MACRO_CALL].get(&AstPtr::new(src.value)).copied()
-    }
-
     /// (AttrId, derive attribute call id, derive call ids)
     pub(super) fn attr_to_derive_macro_call(
         &mut self,
@@ -449,6 +436,17 @@ impl SourceToDefCtx<'_, '_> {
             .or_insert_with(|| container.child_by_source(db, file_id))
     }
 
+    pub(super) fn item_to_macro_call(&mut self, src: InFile<&ast::Item>) -> Option<MacroCallId> {
+        self.to_def(src, keys::ATTR_MACRO_CALL)
+    }
+
+    pub(super) fn macro_call_to_macro_call(
+        &mut self,
+        src: InFile<&ast::MacroCall>,
+    ) -> Option<MacroCallId> {
+        self.to_def(src, keys::MACRO_CALL)
+    }
+
     pub(super) fn type_param_to_def(
         &mut self,
         src: InFile<&ast::TypeParam>,
diff --git a/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs b/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs
index ea21546f9d7..ec2ccf8cba0 100644
--- a/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs
+++ b/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs
@@ -26,12 +26,12 @@ use hir_def::{
     },
     hir::{BindingId, Expr, ExprId, ExprOrPatId, Pat},
     lang_item::LangItem,
-    nameres::{MacroSubNs, crate_def_map},
+    nameres::MacroSubNs,
     resolver::{HasResolver, Resolver, TypeNs, ValueNs, resolver_for_scope},
     type_ref::{Mutability, TypeRefId},
 };
 use hir_expand::{
-    HirFileId, InFile, MacroCallId,
+    HirFileId, InFile,
     mod_path::{ModPath, PathKind, path},
     name::{AsName, Name},
 };
@@ -218,10 +218,6 @@ impl<'db> SourceAnalyzer<'db> {
         })
     }
 
-    pub(crate) fn expansion(&self, node: InFile<&ast::MacroCall>) -> Option<MacroCallId> {
-        self.store_sm()?.expansion(node)
-    }
-
     fn trait_environment(&self, db: &'db dyn HirDatabase) -> Arc<TraitEnvironment> {
         self.body_().map(|(def, ..)| def).map_or_else(
             || TraitEnvironment::empty(self.resolver.krate()),
@@ -745,22 +741,6 @@ impl<'db> SourceAnalyzer<'db> {
         ))
     }
 
-    pub(crate) fn resolve_macro_call(
-        &self,
-        db: &'db dyn HirDatabase,
-        macro_call: InFile<&ast::MacroCall>,
-    ) -> Option<Macro> {
-        let bs = self.store_sm()?;
-        bs.expansion(macro_call).and_then(|it| {
-            // FIXME: Block def maps
-            let def = it.lookup(db).def;
-            crate_def_map(db, def.krate)
-                .macro_def_to_macro_id
-                .get(&def.kind.erased_ast_id())
-                .map(|it| (*it).into())
-        })
-    }
-
     pub(crate) fn resolve_bind_pat_to_const(
         &self,
         db: &'db dyn HirDatabase,
@@ -1292,18 +1272,6 @@ impl<'db> SourceAnalyzer<'db> {
             .collect()
     }
 
-    pub(crate) fn expand(
-        &self,
-        db: &'db dyn HirDatabase,
-        macro_call: InFile<&ast::MacroCall>,
-    ) -> Option<MacroCallId> {
-        self.store_sm().and_then(|bs| bs.expansion(macro_call)).or_else(|| {
-            self.resolver.item_scope().macro_invoc(
-                macro_call.with_value(db.ast_id_map(macro_call.file_id).ast_id(macro_call.value)),
-            )
-        })
-    }
-
     pub(crate) fn resolve_variant(&self, record_lit: ast::RecordExpr) -> Option<VariantId> {
         let infer = self.infer()?;
         let expr_id = self.expr_id(record_lit.into())?;
@@ -1335,6 +1303,7 @@ impl<'db> SourceAnalyzer<'db> {
         false
     }
 
+    /// Returns the range of the implicit template argument and its resolution at the given `offset`
     pub(crate) fn resolve_offset_in_format_args(
         &self,
         db: &'db dyn HirDatabase,
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/auto_import.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/auto_import.rs
index d310e11011b..f3243d369a0 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/auto_import.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/auto_import.rs
@@ -128,11 +128,7 @@ pub(crate) fn auto_import(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<
             format!("Import `{import_name}`"),
             range,
             |builder| {
-                let scope = match scope.clone() {
-                    ImportScope::File(it) => ImportScope::File(builder.make_mut(it)),
-                    ImportScope::Module(it) => ImportScope::Module(builder.make_mut(it)),
-                    ImportScope::Block(it) => ImportScope::Block(builder.make_mut(it)),
-                };
+                let scope = builder.make_import_scope_mut(scope.clone());
                 insert_use(&scope, mod_path_to_ast(&import_path, edition), &ctx.config.insert_use);
             },
         );
@@ -153,11 +149,7 @@ pub(crate) fn auto_import(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<
                     format!("Import `{import_name} as _`"),
                     range,
                     |builder| {
-                        let scope = match scope.clone() {
-                            ImportScope::File(it) => ImportScope::File(builder.make_mut(it)),
-                            ImportScope::Module(it) => ImportScope::Module(builder.make_mut(it)),
-                            ImportScope::Block(it) => ImportScope::Block(builder.make_mut(it)),
-                        };
+                        let scope = builder.make_import_scope_mut(scope.clone());
                         insert_use_as_alias(
                             &scope,
                             mod_path_to_ast(&import_path, edition),
@@ -1877,4 +1869,30 @@ fn main() {
 ",
         );
     }
+
+    #[test]
+    fn carries_cfg_attr() {
+        check_assist(
+            auto_import,
+            r#"
+mod m {
+    pub struct S;
+}
+
+#[cfg(test)]
+fn foo(_: S$0) {}
+"#,
+            r#"
+#[cfg(test)]
+use m::S;
+
+mod m {
+    pub struct S;
+}
+
+#[cfg(test)]
+fn foo(_: S) {}
+"#,
+        );
+    }
 }
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_bool_to_enum.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_bool_to_enum.rs
index 00e9fdf124d..f73b8c4fd0f 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_bool_to_enum.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_bool_to_enum.rs
@@ -312,12 +312,8 @@ fn replace_usages(
                 }
 
                 // add imports across modules where needed
-                if let Some((import_scope, path)) = import_data {
-                    let scope = match import_scope {
-                        ImportScope::File(it) => ImportScope::File(edit.make_mut(it)),
-                        ImportScope::Module(it) => ImportScope::Module(edit.make_mut(it)),
-                        ImportScope::Block(it) => ImportScope::Block(edit.make_mut(it)),
-                    };
+                if let Some((scope, path)) = import_data {
+                    let scope = edit.make_import_scope_mut(scope);
                     delayed_mutations.push((scope, path));
                 }
             },
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_named_struct_to_tuple_struct.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_named_struct_to_tuple_struct.rs
index ed8aad7b2c6..5d75e445861 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_named_struct_to_tuple_struct.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_named_struct_to_tuple_struct.rs
@@ -996,7 +996,8 @@ pub struct $0Foo {
 }
 "#,
             r#"
-pub struct Foo(#[my_custom_attr] u32);
+pub struct Foo(#[my_custom_attr]
+u32);
 "#,
         );
     }
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_tuple_struct_to_named_struct.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_tuple_struct_to_named_struct.rs
index 777e366da95..0c0b93bcfbc 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_tuple_struct_to_named_struct.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_tuple_struct_to_named_struct.rs
@@ -923,7 +923,8 @@ where
 pub struct $0Foo(#[my_custom_attr] u32);
 "#,
             r#"
-pub struct Foo { #[my_custom_attr] field1: u32 }
+pub struct Foo { #[my_custom_attr]
+field1: u32 }
 "#,
         );
     }
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/desugar_try_expr.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/desugar_try_expr.rs
new file mode 100644
index 00000000000..efadde9e364
--- /dev/null
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/desugar_try_expr.rs
@@ -0,0 +1,281 @@
+use std::iter;
+
+use ide_db::{
+    assists::{AssistId, ExprFillDefaultMode},
+    ty_filter::TryEnum,
+};
+use syntax::{
+    AstNode, T,
+    ast::{
+        self,
+        edit::{AstNodeEdit, IndentLevel},
+        make,
+        syntax_factory::SyntaxFactory,
+    },
+};
+
+use crate::assist_context::{AssistContext, Assists};
+
+// Assist: desugar_try_expr_match
+//
+// Replaces a `try` expression with a `match` expression.
+//
+// ```
+// # //- minicore: try, option
+// fn handle() {
+//     let pat = Some(true)$0?;
+// }
+// ```
+// ->
+// ```
+// fn handle() {
+//     let pat = match Some(true) {
+//         Some(it) => it,
+//         None => return None,
+//     };
+// }
+// ```
+
+// Assist: desugar_try_expr_let_else
+//
+// Replaces a `try` expression with a `let else` statement.
+//
+// ```
+// # //- minicore: try, option
+// fn handle() {
+//     let pat = Some(true)$0?;
+// }
+// ```
+// ->
+// ```
+// fn handle() {
+//     let Some(pat) = Some(true) else {
+//         return None;
+//     };
+// }
+// ```
+pub(crate) fn desugar_try_expr(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> {
+    let question_tok = ctx.find_token_syntax_at_offset(T![?])?;
+    let try_expr = question_tok.parent().and_then(ast::TryExpr::cast)?;
+
+    let expr = try_expr.expr()?;
+    let expr_type_info = ctx.sema.type_of_expr(&expr)?;
+
+    let try_enum = TryEnum::from_ty(&ctx.sema, &expr_type_info.original)?;
+
+    let target = try_expr.syntax().text_range();
+    acc.add(
+        AssistId::refactor_rewrite("desugar_try_expr_match"),
+        "Replace try expression with match",
+        target,
+        |edit| {
+            let sad_pat = match try_enum {
+                TryEnum::Option => make::path_pat(make::ext::ident_path("None")),
+                TryEnum::Result => make::tuple_struct_pat(
+                    make::ext::ident_path("Err"),
+                    iter::once(make::path_pat(make::ext::ident_path("err"))),
+                )
+                .into(),
+            };
+            let sad_expr = match try_enum {
+                TryEnum::Option => {
+                    make::expr_return(Some(make::expr_path(make::ext::ident_path("None"))))
+                }
+                TryEnum::Result => make::expr_return(Some(
+                    make::expr_call(
+                        make::expr_path(make::ext::ident_path("Err")),
+                        make::arg_list(iter::once(make::expr_path(make::ext::ident_path("err")))),
+                    )
+                    .into(),
+                )),
+            };
+
+            let happy_arm = make::match_arm(
+                try_enum.happy_pattern(make::ident_pat(false, false, make::name("it")).into()),
+                None,
+                make::expr_path(make::ext::ident_path("it")),
+            );
+            let sad_arm = make::match_arm(sad_pat, None, sad_expr);
+
+            let match_arm_list = make::match_arm_list([happy_arm, sad_arm]);
+
+            let expr_match = make::expr_match(expr.clone(), match_arm_list)
+                .indent(IndentLevel::from_node(try_expr.syntax()));
+
+            edit.replace_ast::<ast::Expr>(try_expr.clone().into(), expr_match.into());
+        },
+    );
+
+    if let Some(let_stmt) = try_expr.syntax().parent().and_then(ast::LetStmt::cast) {
+        if let_stmt.let_else().is_none() {
+            let pat = let_stmt.pat()?;
+            acc.add(
+                AssistId::refactor_rewrite("desugar_try_expr_let_else"),
+                "Replace try expression with let else",
+                target,
+                |builder| {
+                    let make = SyntaxFactory::with_mappings();
+                    let mut editor = builder.make_editor(let_stmt.syntax());
+
+                    let indent_level = IndentLevel::from_node(let_stmt.syntax());
+                    let new_let_stmt = make.let_else_stmt(
+                        try_enum.happy_pattern(pat),
+                        let_stmt.ty(),
+                        expr,
+                        make.block_expr(
+                            iter::once(
+                                make.expr_stmt(
+                                    make.expr_return(Some(match try_enum {
+                                        TryEnum::Option => make.expr_path(make.ident_path("None")),
+                                        TryEnum::Result => make
+                                            .expr_call(
+                                                make.expr_path(make.ident_path("Err")),
+                                                make.arg_list(iter::once(
+                                                    match ctx.config.expr_fill_default {
+                                                        ExprFillDefaultMode::Todo => make
+                                                            .expr_macro(
+                                                                make.ident_path("todo"),
+                                                                make.token_tree(
+                                                                    syntax::SyntaxKind::L_PAREN,
+                                                                    [],
+                                                                ),
+                                                            )
+                                                            .into(),
+                                                        ExprFillDefaultMode::Underscore => {
+                                                            make.expr_underscore().into()
+                                                        }
+                                                        ExprFillDefaultMode::Default => make
+                                                            .expr_macro(
+                                                                make.ident_path("todo"),
+                                                                make.token_tree(
+                                                                    syntax::SyntaxKind::L_PAREN,
+                                                                    [],
+                                                                ),
+                                                            )
+                                                            .into(),
+                                                    },
+                                                )),
+                                            )
+                                            .into(),
+                                    }))
+                                    .indent(indent_level + 1)
+                                    .into(),
+                                )
+                                .into(),
+                            ),
+                            None,
+                        )
+                        .indent(indent_level),
+                    );
+                    editor.replace(let_stmt.syntax(), new_let_stmt.syntax());
+                    editor.add_mappings(make.finish_with_mappings());
+                    builder.add_file_edits(ctx.vfs_file_id(), editor);
+                },
+            );
+        }
+    }
+    Some(())
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+
+    use crate::tests::{check_assist, check_assist_by_label, check_assist_not_applicable};
+
+    #[test]
+    fn test_desugar_try_expr_not_applicable() {
+        check_assist_not_applicable(
+            desugar_try_expr,
+            r#"
+                fn test() {
+                    let pat: u32 = 25$0;
+                }
+            "#,
+        );
+    }
+
+    #[test]
+    fn test_desugar_try_expr_option() {
+        check_assist(
+            desugar_try_expr,
+            r#"
+//- minicore: try, option
+fn test() {
+    let pat = Some(true)$0?;
+}
+            "#,
+            r#"
+fn test() {
+    let pat = match Some(true) {
+        Some(it) => it,
+        None => return None,
+    };
+}
+            "#,
+        );
+    }
+
+    #[test]
+    fn test_desugar_try_expr_result() {
+        check_assist(
+            desugar_try_expr,
+            r#"
+//- minicore: try, from, result
+fn test() {
+    let pat = Ok(true)$0?;
+}
+            "#,
+            r#"
+fn test() {
+    let pat = match Ok(true) {
+        Ok(it) => it,
+        Err(err) => return Err(err),
+    };
+}
+            "#,
+        );
+    }
+
+    #[test]
+    fn test_desugar_try_expr_option_let_else() {
+        check_assist_by_label(
+            desugar_try_expr,
+            r#"
+//- minicore: try, option
+fn test() {
+    let pat = Some(true)$0?;
+}
+            "#,
+            r#"
+fn test() {
+    let Some(pat) = Some(true) else {
+        return None;
+    };
+}
+            "#,
+            "Replace try expression with let else",
+        );
+    }
+
+    #[test]
+    fn test_desugar_try_expr_result_let_else() {
+        check_assist_by_label(
+            desugar_try_expr,
+            r#"
+//- minicore: try, from, result
+fn test() {
+    let pat = Ok(true)$0?;
+}
+            "#,
+            r#"
+fn test() {
+    let Ok(pat) = Ok(true) else {
+        return Err(todo!());
+    };
+}
+            "#,
+            "Replace try expression with let else",
+        );
+    }
+}
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_function.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_function.rs
index e977798c4fd..cf45ea0a30d 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_function.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_function.rs
@@ -204,12 +204,7 @@ pub(crate) fn extract_function(acc: &mut Assists, ctx: &AssistContext<'_>) -> Op
                 .kind
                 .is_some_and(|kind| matches!(kind, FlowKind::Break(_, _) | FlowKind::Continue(_)))
             {
-                let scope = match scope {
-                    ImportScope::File(it) => ImportScope::File(builder.make_mut(it)),
-                    ImportScope::Module(it) => ImportScope::Module(builder.make_mut(it)),
-                    ImportScope::Block(it) => ImportScope::Block(builder.make_mut(it)),
-                };
-
+                let scope = builder.make_import_scope_mut(scope);
                 let control_flow_enum =
                     FamousDefs(&ctx.sema, module.krate()).core_ops_ControlFlow();
 
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_mut_trait_impl.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_mut_trait_impl.rs
index 2ac960ed7e1..bab2ccf3f33 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_mut_trait_impl.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_mut_trait_impl.rs
@@ -1,7 +1,7 @@
 use ide_db::famous_defs::FamousDefs;
 use syntax::{
     AstNode,
-    ast::{self, make},
+    ast::{self, edit_in_place::Indent, make},
     ted,
 };
 
@@ -46,6 +46,7 @@ use crate::{AssistContext, AssistId, Assists};
 // ```
 pub(crate) fn generate_mut_trait_impl(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> {
     let impl_def = ctx.find_node_at_offset::<ast::Impl>()?.clone_for_update();
+    let indent = impl_def.indent_level();
 
     let trait_ = impl_def.trait_()?;
     if let ast::Type::PathType(trait_path) = trait_ {
@@ -97,8 +98,8 @@ pub(crate) fn generate_mut_trait_impl(acc: &mut Assists, ctx: &AssistContext<'_>
     })?;
 
     let assoc_list = make::assoc_item_list().clone_for_update();
-    assoc_list.add_item(syntax::ast::AssocItem::Fn(fn_));
     ted::replace(impl_def.assoc_item_list()?.syntax(), assoc_list.syntax());
+    impl_def.get_or_create_assoc_item_list().add_item(syntax::ast::AssocItem::Fn(fn_));
 
     let target = impl_def.syntax().text_range();
     acc.add(
@@ -106,7 +107,7 @@ pub(crate) fn generate_mut_trait_impl(acc: &mut Assists, ctx: &AssistContext<'_>
         "Generate `IndexMut` impl from this `Index` trait",
         target,
         |edit| {
-            edit.insert(target.start(), format!("$0{impl_def}\n\n"));
+            edit.insert(target.start(), format!("$0{impl_def}\n\n{indent}"));
         },
     )
 }
@@ -190,6 +191,93 @@ impl<T> core::ops::Index<Axis> for [T; 3] where T: Copy {
     }
 
     #[test]
+    fn test_generate_mut_trait_impl_non_zero_indent() {
+        check_assist(
+            generate_mut_trait_impl,
+            r#"
+//- minicore: index
+mod foo {
+    pub enum Axis { X = 0, Y = 1, Z = 2 }
+
+    impl<T> core::ops::Index$0<Axis> for [T; 3] where T: Copy {
+        type Output = T;
+
+        fn index(&self, index: Axis) -> &Self::Output {
+            let var_name = &self[index as usize];
+            var_name
+        }
+    }
+}
+"#,
+            r#"
+mod foo {
+    pub enum Axis { X = 0, Y = 1, Z = 2 }
+
+    $0impl<T> core::ops::IndexMut<Axis> for [T; 3] where T: Copy {
+        fn index_mut(&mut self, index: Axis) -> &mut Self::Output {
+            let var_name = &self[index as usize];
+            var_name
+        }
+    }
+
+    impl<T> core::ops::Index<Axis> for [T; 3] where T: Copy {
+        type Output = T;
+
+        fn index(&self, index: Axis) -> &Self::Output {
+            let var_name = &self[index as usize];
+            var_name
+        }
+    }
+}
+"#,
+        );
+
+        check_assist(
+            generate_mut_trait_impl,
+            r#"
+//- minicore: index
+mod foo {
+    mod bar {
+        pub enum Axis { X = 0, Y = 1, Z = 2 }
+
+        impl<T> core::ops::Index$0<Axis> for [T; 3] where T: Copy {
+            type Output = T;
+
+            fn index(&self, index: Axis) -> &Self::Output {
+                let var_name = &self[index as usize];
+                var_name
+            }
+        }
+    }
+}
+"#,
+            r#"
+mod foo {
+    mod bar {
+        pub enum Axis { X = 0, Y = 1, Z = 2 }
+
+        $0impl<T> core::ops::IndexMut<Axis> for [T; 3] where T: Copy {
+            fn index_mut(&mut self, index: Axis) -> &mut Self::Output {
+                let var_name = &self[index as usize];
+                var_name
+            }
+        }
+
+        impl<T> core::ops::Index<Axis> for [T; 3] where T: Copy {
+            type Output = T;
+
+            fn index(&self, index: Axis) -> &Self::Output {
+                let var_name = &self[index as usize];
+                var_name
+            }
+        }
+    }
+}
+"#,
+        );
+    }
+
+    #[test]
     fn test_generate_mut_trait_impl_not_applicable() {
         check_assist_not_applicable(
             generate_mut_trait_impl,
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_new.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_new.rs
index f963f48d62a..4837f92f934 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_new.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_new.rs
@@ -129,17 +129,23 @@ pub(crate) fn generate_new(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option
 
         // Get the mutable version of the impl to modify
         let impl_def = if let Some(impl_def) = impl_def {
+            fn_.indent(impl_def.indent_level());
             builder.make_mut(impl_def)
         } else {
             // Generate a new impl to add the method to
             let impl_def = generate_impl(&ast::Adt::Struct(strukt.clone()));
+            let indent_level = strukt.indent_level();
+            fn_.indent(indent_level);
 
             // Insert it after the adt
             let strukt = builder.make_mut(strukt.clone());
 
             ted::insert_all_raw(
                 ted::Position::after(strukt.syntax()),
-                vec![make::tokens::blank_line().into(), impl_def.syntax().clone().into()],
+                vec![
+                    make::tokens::whitespace(&format!("\n\n{indent_level}")).into(),
+                    impl_def.syntax().clone().into(),
+                ],
             );
 
             impl_def
@@ -426,6 +432,135 @@ impl Foo {
     }
 
     #[test]
+    fn non_zero_indent() {
+        check_assist(
+            generate_new,
+            r#"
+mod foo {
+    struct $0Foo {}
+}
+"#,
+            r#"
+mod foo {
+    struct Foo {}
+
+    impl Foo {
+        fn $0new() -> Self {
+            Self {  }
+        }
+    }
+}
+"#,
+        );
+        check_assist(
+            generate_new,
+            r#"
+mod foo {
+    mod bar {
+        struct $0Foo {}
+    }
+}
+"#,
+            r#"
+mod foo {
+    mod bar {
+        struct Foo {}
+
+        impl Foo {
+            fn $0new() -> Self {
+                Self {  }
+            }
+        }
+    }
+}
+"#,
+        );
+        check_assist(
+            generate_new,
+            r#"
+mod foo {
+    struct $0Foo {}
+
+    impl Foo {
+        fn some() {}
+    }
+}
+"#,
+            r#"
+mod foo {
+    struct Foo {}
+
+    impl Foo {
+        fn $0new() -> Self {
+            Self {  }
+        }
+
+        fn some() {}
+    }
+}
+"#,
+        );
+        check_assist(
+            generate_new,
+            r#"
+mod foo {
+    mod bar {
+        struct $0Foo {}
+
+        impl Foo {
+            fn some() {}
+        }
+    }
+}
+"#,
+            r#"
+mod foo {
+    mod bar {
+        struct Foo {}
+
+        impl Foo {
+            fn $0new() -> Self {
+                Self {  }
+            }
+
+            fn some() {}
+        }
+    }
+}
+"#,
+        );
+        check_assist(
+            generate_new,
+            r#"
+mod foo {
+    mod bar {
+struct $0Foo {}
+
+        impl Foo {
+            fn some() {}
+        }
+    }
+}
+"#,
+            r#"
+mod foo {
+    mod bar {
+struct Foo {}
+
+        impl Foo {
+            fn $0new() -> Self {
+                Self {  }
+            }
+
+            fn some() {}
+        }
+    }
+}
+"#,
+        );
+    }
+
+    #[test]
     fn check_visibility_of_new_fn_based_on_struct() {
         check_assist(
             generate_new,
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_qualified_name_with_use.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_qualified_name_with_use.rs
index c067747bc1b..fa005a411d3 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_qualified_name_with_use.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_qualified_name_with_use.rs
@@ -81,11 +81,7 @@ pub(crate) fn replace_qualified_name_with_use(
         |builder| {
             // Now that we've brought the name into scope, re-qualify all paths that could be
             // affected (that is, all paths inside the node we added the `use` to).
-            let scope = match scope {
-                ImportScope::File(it) => ImportScope::File(builder.make_mut(it)),
-                ImportScope::Module(it) => ImportScope::Module(builder.make_mut(it)),
-                ImportScope::Block(it) => ImportScope::Block(builder.make_mut(it)),
-            };
+            let scope = builder.make_import_scope_mut(scope);
             shorten_paths(scope.as_syntax_node(), &original_path);
             let path = drop_generic_args(&original_path);
             let edition = ctx
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_try_expr_with_match.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_try_expr_with_match.rs
deleted file mode 100644
index c6e864fcfdb..00000000000
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_try_expr_with_match.rs
+++ /dev/null
@@ -1,148 +0,0 @@
-use std::iter;
-
-use ide_db::{assists::AssistId, ty_filter::TryEnum};
-use syntax::{
-    AstNode, T,
-    ast::{
-        self,
-        edit::{AstNodeEdit, IndentLevel},
-        make,
-    },
-};
-
-use crate::assist_context::{AssistContext, Assists};
-
-// Assist: replace_try_expr_with_match
-//
-// Replaces a `try` expression with a `match` expression.
-//
-// ```
-// # //- minicore: try, option
-// fn handle() {
-//     let pat = Some(true)$0?;
-// }
-// ```
-// ->
-// ```
-// fn handle() {
-//     let pat = match Some(true) {
-//         Some(it) => it,
-//         None => return None,
-//     };
-// }
-// ```
-pub(crate) fn replace_try_expr_with_match(
-    acc: &mut Assists,
-    ctx: &AssistContext<'_>,
-) -> Option<()> {
-    let qm_kw = ctx.find_token_syntax_at_offset(T![?])?;
-    let qm_kw_parent = qm_kw.parent().and_then(ast::TryExpr::cast)?;
-
-    let expr = qm_kw_parent.expr()?;
-    let expr_type_info = ctx.sema.type_of_expr(&expr)?;
-
-    let try_enum = TryEnum::from_ty(&ctx.sema, &expr_type_info.original)?;
-
-    let target = qm_kw_parent.syntax().text_range();
-    acc.add(
-        AssistId::refactor_rewrite("replace_try_expr_with_match"),
-        "Replace try expression with match",
-        target,
-        |edit| {
-            let sad_pat = match try_enum {
-                TryEnum::Option => make::path_pat(make::ext::ident_path("None")),
-                TryEnum::Result => make::tuple_struct_pat(
-                    make::ext::ident_path("Err"),
-                    iter::once(make::path_pat(make::ext::ident_path("err"))),
-                )
-                .into(),
-            };
-            let sad_expr = match try_enum {
-                TryEnum::Option => {
-                    make::expr_return(Some(make::expr_path(make::ext::ident_path("None"))))
-                }
-                TryEnum::Result => make::expr_return(Some(
-                    make::expr_call(
-                        make::expr_path(make::ext::ident_path("Err")),
-                        make::arg_list(iter::once(make::expr_path(make::ext::ident_path("err")))),
-                    )
-                    .into(),
-                )),
-            };
-
-            let happy_arm = make::match_arm(
-                try_enum.happy_pattern(make::ident_pat(false, false, make::name("it")).into()),
-                None,
-                make::expr_path(make::ext::ident_path("it")),
-            );
-            let sad_arm = make::match_arm(sad_pat, None, sad_expr);
-
-            let match_arm_list = make::match_arm_list([happy_arm, sad_arm]);
-
-            let expr_match = make::expr_match(expr, match_arm_list)
-                .indent(IndentLevel::from_node(qm_kw_parent.syntax()));
-            edit.replace_ast::<ast::Expr>(qm_kw_parent.into(), expr_match.into());
-        },
-    )
-}
-
-#[cfg(test)]
-mod tests {
-    use super::*;
-
-    use crate::tests::{check_assist, check_assist_not_applicable};
-
-    #[test]
-    fn test_replace_try_expr_with_match_not_applicable() {
-        check_assist_not_applicable(
-            replace_try_expr_with_match,
-            r#"
-                fn test() {
-                    let pat: u32 = 25$0;
-                }
-            "#,
-        );
-    }
-
-    #[test]
-    fn test_replace_try_expr_with_match_option() {
-        check_assist(
-            replace_try_expr_with_match,
-            r#"
-//- minicore: try, option
-fn test() {
-    let pat = Some(true)$0?;
-}
-            "#,
-            r#"
-fn test() {
-    let pat = match Some(true) {
-        Some(it) => it,
-        None => return None,
-    };
-}
-            "#,
-        );
-    }
-
-    #[test]
-    fn test_replace_try_expr_with_match_result() {
-        check_assist(
-            replace_try_expr_with_match,
-            r#"
-//- minicore: try, from, result
-fn test() {
-    let pat = Ok(true)$0?;
-}
-            "#,
-            r#"
-fn test() {
-    let pat = match Ok(true) {
-        Ok(it) => it,
-        Err(err) => return Err(err),
-    };
-}
-            "#,
-        );
-    }
-}
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unqualify_method_call.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unqualify_method_call.rs
index ebb8ef99100..1f89a3d5f17 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unqualify_method_call.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unqualify_method_call.rs
@@ -1,4 +1,3 @@
-use ide_db::imports::insert_use::ImportScope;
 use syntax::{
     TextRange,
     ast::{self, AstNode, HasArgList, prec::ExprPrecedence},
@@ -114,11 +113,7 @@ fn add_import(
         );
 
         if let Some(scope) = scope {
-            let scope = match scope {
-                ImportScope::File(it) => ImportScope::File(edit.make_mut(it)),
-                ImportScope::Module(it) => ImportScope::Module(edit.make_mut(it)),
-                ImportScope::Block(it) => ImportScope::Block(edit.make_mut(it)),
-            };
+            let scope = edit.make_import_scope_mut(scope);
             ide_db::imports::insert_use::insert_use(&scope, import, &ctx.config.insert_use);
         }
     }
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/lib.rs b/src/tools/rust-analyzer/crates/ide-assists/src/lib.rs
index 2395091b6f2..c2604432032 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/lib.rs
@@ -139,6 +139,7 @@ mod handlers {
     mod destructure_struct_binding;
     mod destructure_tuple_binding;
     mod desugar_doc_comment;
+    mod desugar_try_expr;
     mod expand_glob_import;
     mod expand_rest_pattern;
     mod extract_expressions_from_format_string;
@@ -214,7 +215,6 @@ mod handlers {
     mod replace_named_generic_with_impl;
     mod replace_qualified_name_with_use;
     mod replace_string_with_char;
-    mod replace_try_expr_with_match;
     mod replace_turbofish_with_explicit_type;
     mod sort_items;
     mod split_import;
@@ -273,6 +273,7 @@ mod handlers {
             destructure_struct_binding::destructure_struct_binding,
             destructure_tuple_binding::destructure_tuple_binding,
             desugar_doc_comment::desugar_doc_comment,
+            desugar_try_expr::desugar_try_expr,
             expand_glob_import::expand_glob_import,
             expand_glob_import::expand_glob_reexport,
             expand_rest_pattern::expand_rest_pattern,
@@ -354,7 +355,6 @@ mod handlers {
             replace_method_eager_lazy::replace_with_lazy_method,
             replace_named_generic_with_impl::replace_named_generic_with_impl,
             replace_qualified_name_with_use::replace_qualified_name_with_use,
-            replace_try_expr_with_match::replace_try_expr_with_match,
             replace_turbofish_with_explicit_type::replace_turbofish_with_explicit_type,
             sort_items::sort_items,
             split_import::split_import,
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/tests/generated.rs b/src/tools/rust-analyzer/crates/ide-assists/src/tests/generated.rs
index 76134acb36e..72f7195cbd7 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/tests/generated.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/tests/generated.rs
@@ -930,6 +930,47 @@ comment"]
 }
 
 #[test]
+fn doctest_desugar_try_expr_let_else() {
+    check_doc_test(
+        "desugar_try_expr_let_else",
+        r#####"
+//- minicore: try, option
+fn handle() {
+    let pat = Some(true)$0?;
+}
+"#####,
+        r#####"
+fn handle() {
+    let Some(pat) = Some(true) else {
+        return None;
+    };
+}
+"#####,
+    )
+}
+
+#[test]
+fn doctest_desugar_try_expr_match() {
+    check_doc_test(
+        "desugar_try_expr_match",
+        r#####"
+//- minicore: try, option
+fn handle() {
+    let pat = Some(true)$0?;
+}
+"#####,
+        r#####"
+fn handle() {
+    let pat = match Some(true) {
+        Some(it) => it,
+        None => return None,
+    };
+}
+"#####,
+    )
+}
+
+#[test]
 fn doctest_expand_glob_import() {
     check_doc_test(
         "expand_glob_import",
@@ -3097,27 +3138,6 @@ fn main() {
 }
 
 #[test]
-fn doctest_replace_try_expr_with_match() {
-    check_doc_test(
-        "replace_try_expr_with_match",
-        r#####"
-//- minicore: try, option
-fn handle() {
-    let pat = Some(true)$0?;
-}
-"#####,
-        r#####"
-fn handle() {
-    let pat = match Some(true) {
-        Some(it) => it,
-        None => return None,
-    };
-}
-"#####,
-    )
-}
-
-#[test]
 fn doctest_replace_turbofish_with_explicit_type() {
     check_doc_test(
         "replace_turbofish_with_explicit_type",
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/context.rs b/src/tools/rust-analyzer/crates/ide-completion/src/context.rs
index 3baf1f3de61..5287627790a 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/context.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/context.rs
@@ -8,8 +8,8 @@ use std::{iter, ops::ControlFlow};
 
 use base_db::RootQueryDb as _;
 use hir::{
-    DisplayTarget, HasAttrs, Local, ModuleDef, ModuleSource, Name, PathResolution, ScopeDef,
-    Semantics, SemanticsScope, Symbol, Type, TypeInfo,
+    DisplayTarget, HasAttrs, InFile, Local, ModuleDef, ModuleSource, Name, PathResolution,
+    ScopeDef, Semantics, SemanticsScope, Symbol, Type, TypeInfo,
 };
 use ide_db::{
     FilePosition, FxHashMap, FxHashSet, RootDatabase, famous_defs::FamousDefs,
@@ -751,7 +751,7 @@ impl<'a> CompletionContext<'a> {
             original_offset,
         } = expand_and_analyze(
             &sema,
-            original_file.syntax().clone(),
+            InFile::new(editioned_file_id.into(), original_file.syntax().clone()),
             file_with_fake_ident.syntax().clone(),
             offset,
             &original_token,
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/context/analysis.rs b/src/tools/rust-analyzer/crates/ide-completion/src/context/analysis.rs
index 284876ffc88..7a2230b3e36 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/context/analysis.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/context/analysis.rs
@@ -1,7 +1,7 @@
 //! Module responsible for analyzing the code surrounding the cursor for completion.
 use std::iter;
 
-use hir::{ExpandResult, Semantics, Type, TypeInfo, Variant};
+use hir::{ExpandResult, InFile, Semantics, Type, TypeInfo, Variant};
 use ide_db::{RootDatabase, active_parameter::ActiveParameter};
 use itertools::Either;
 use syntax::{
@@ -50,7 +50,7 @@ pub(super) struct AnalysisResult {
 
 pub(super) fn expand_and_analyze(
     sema: &Semantics<'_, RootDatabase>,
-    original_file: SyntaxNode,
+    original_file: InFile<SyntaxNode>,
     speculative_file: SyntaxNode,
     offset: TextSize,
     original_token: &SyntaxToken,
@@ -72,7 +72,7 @@ pub(super) fn expand_and_analyze(
         relative_offset,
     )
     .unwrap_or(ExpansionResult {
-        original_file,
+        original_file: original_file.value,
         speculative_file,
         original_offset: offset,
         speculative_offset: fake_ident_token.text_range().start(),
@@ -125,7 +125,7 @@ fn token_at_offset_ignore_whitespace(file: &SyntaxNode, offset: TextSize) -> Opt
 /// the best we can do.
 fn expand_maybe_stop(
     sema: &Semantics<'_, RootDatabase>,
-    original_file: SyntaxNode,
+    original_file: InFile<SyntaxNode>,
     speculative_file: SyntaxNode,
     original_offset: TextSize,
     fake_ident_token: SyntaxToken,
@@ -142,17 +142,16 @@ fn expand_maybe_stop(
         return result;
     }
 
-    // This needs to come after the recursive call, because our "inside macro" detection is subtly wrong
-    // with regard to attribute macros named `test` that are not std's test. So hopefully we will expand
-    // them successfully above and be able to analyze.
-    // Left biased since there may already be an identifier token there, and we appended to it.
-    if !sema.might_be_inside_macro_call(&fake_ident_token)
-        && token_at_offset_ignore_whitespace(&original_file, original_offset + relative_offset)
-            .is_some_and(|original_token| !sema.might_be_inside_macro_call(&original_token))
+    // We can't check whether the fake expansion is inside macro call, because that requires semantic info.
+    // But hopefully checking just the real one should be enough.
+    if token_at_offset_ignore_whitespace(&original_file.value, original_offset + relative_offset)
+        .is_some_and(|original_token| {
+            !sema.is_inside_macro_call(original_file.with_value(&original_token))
+        })
     {
         // Recursion base case.
         Some(ExpansionResult {
-            original_file,
+            original_file: original_file.value,
             speculative_file,
             original_offset,
             speculative_offset: fake_ident_token.text_range().start(),
@@ -166,7 +165,7 @@ fn expand_maybe_stop(
 
 fn expand(
     sema: &Semantics<'_, RootDatabase>,
-    original_file: SyntaxNode,
+    original_file: InFile<SyntaxNode>,
     speculative_file: SyntaxNode,
     original_offset: TextSize,
     fake_ident_token: SyntaxToken,
@@ -176,7 +175,7 @@ fn expand(
 
     let parent_item =
         |item: &ast::Item| item.syntax().ancestors().skip(1).find_map(ast::Item::cast);
-    let original_node = token_at_offset_ignore_whitespace(&original_file, original_offset)
+    let original_node = token_at_offset_ignore_whitespace(&original_file.value, original_offset)
         .and_then(|token| token.parent_ancestors().find_map(ast::Item::cast));
     let ancestor_items = iter::successors(
         Option::zip(
@@ -249,7 +248,7 @@ fn expand(
     }
 
     // No attributes have been expanded, so look for macro_call! token trees or derive token trees
-    let orig_tt = ancestors_at_offset(&original_file, original_offset)
+    let orig_tt = ancestors_at_offset(&original_file.value, original_offset)
         .map_while(Either::<ast::TokenTree, ast::Meta>::cast)
         .last()?;
     let spec_tt = ancestors_at_offset(&speculative_file, fake_ident_token.text_range().start())
@@ -292,7 +291,7 @@ fn expand(
                 fake_mapped_tokens.into_iter().min_by_key(|(_, rank)| *rank)
             {
                 return Some(ExpansionResult {
-                    original_file,
+                    original_file: original_file.value,
                     speculative_file,
                     original_offset,
                     speculative_offset: fake_ident_token.text_range().start(),
@@ -349,7 +348,7 @@ fn expand(
                                 }
                                 let result = expand_maybe_stop(
                                     sema,
-                                    actual_expansion.clone(),
+                                    InFile::new(file.into(), actual_expansion.clone()),
                                     fake_expansion.clone(),
                                     new_offset,
                                     fake_mapped_token,
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/tests/expression.rs b/src/tools/rust-analyzer/crates/ide-completion/src/tests/expression.rs
index e5467767d42..b46e4c32061 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/tests/expression.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/tests/expression.rs
@@ -2112,6 +2112,56 @@ fn foo() {
 }
 
 #[test]
+fn cfg_attr_attr_macro() {
+    check(
+        r#"
+//- proc_macros: identity
+#[cfg_attr(test, proc_macros::identity)]
+fn foo() {
+    $0
+}
+    "#,
+        expect![[r#"
+            fn foo()  fn()
+            md proc_macros
+            bt u32     u32
+            kw async
+            kw const
+            kw crate::
+            kw enum
+            kw extern
+            kw false
+            kw fn
+            kw for
+            kw if
+            kw if let
+            kw impl
+            kw impl for
+            kw let
+            kw letm
+            kw loop
+            kw match
+            kw mod
+            kw return
+            kw self::
+            kw static
+            kw struct
+            kw trait
+            kw true
+            kw type
+            kw union
+            kw unsafe
+            kw use
+            kw while
+            kw while let
+            sn macro_rules
+            sn pd
+            sn ppd
+        "#]],
+    );
+}
+
+#[test]
 fn escaped_label() {
     check(
         r#"
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/tests/item.rs b/src/tools/rust-analyzer/crates/ide-completion/src/tests/item.rs
index 55689034fb4..ed87b339fed 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/tests/item.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/tests/item.rs
@@ -4,7 +4,7 @@
 //! in [crate::completions::mod_].
 use expect_test::expect;
 
-use crate::tests::{check_edit, check_with_base_items};
+use crate::tests::{check, check_edit, check_with_base_items};
 
 #[test]
 fn target_type_or_trait_in_impl_block() {
@@ -308,3 +308,39 @@ fn bar() {
         "#]],
     );
 }
+
+#[test]
+fn expression_in_item_macro() {
+    check(
+        r#"
+fn foo() -> u8 { 0 }
+
+macro_rules! foo {
+    ($expr:expr) => {
+        const BAR: u8 = $expr;
+    };
+}
+
+foo!(f$0);
+    "#,
+        expect![[r#"
+            ct BAR                   u8
+            fn foo()         fn() -> u8
+            ma foo!(…) macro_rules! foo
+            bt u32                  u32
+            kw const
+            kw crate::
+            kw false
+            kw for
+            kw if
+            kw if let
+            kw loop
+            kw match
+            kw self::
+            kw true
+            kw unsafe
+            kw while
+            kw while let
+        "#]],
+    );
+}
diff --git a/src/tools/rust-analyzer/crates/ide-db/src/imports/insert_use.rs b/src/tools/rust-analyzer/crates/ide-db/src/imports/insert_use.rs
index d26e5d62ced..813f38380f6 100644
--- a/src/tools/rust-analyzer/crates/ide-db/src/imports/insert_use.rs
+++ b/src/tools/rust-analyzer/crates/ide-db/src/imports/insert_use.rs
@@ -60,107 +60,87 @@ pub struct InsertUseConfig {
 }
 
 #[derive(Debug, Clone)]
-pub enum ImportScope {
+pub struct ImportScope {
+    pub kind: ImportScopeKind,
+    pub required_cfgs: Vec<ast::Attr>,
+}
+
+#[derive(Debug, Clone)]
+pub enum ImportScopeKind {
     File(ast::SourceFile),
     Module(ast::ItemList),
     Block(ast::StmtList),
 }
 
 impl ImportScope {
-    // FIXME: Remove this?
-    #[cfg(test)]
-    fn from(syntax: SyntaxNode) -> Option<Self> {
-        use syntax::match_ast;
-        fn contains_cfg_attr(attrs: &dyn HasAttrs) -> bool {
-            attrs.attrs().any(|attr| attr.as_simple_call().is_some_and(|(ident, _)| ident == "cfg"))
-        }
-        match_ast! {
-            match syntax {
-                ast::Module(module) => module.item_list().map(ImportScope::Module),
-                ast::SourceFile(file) => Some(ImportScope::File(file)),
-                ast::Fn(func) => contains_cfg_attr(&func).then(|| func.body().and_then(|it| it.stmt_list().map(ImportScope::Block))).flatten(),
-                ast::Const(konst) => contains_cfg_attr(&konst).then(|| match konst.body()? {
-                    ast::Expr::BlockExpr(block) => Some(block),
-                    _ => None,
-                }).flatten().and_then(|it| it.stmt_list().map(ImportScope::Block)),
-                ast::Static(statik) => contains_cfg_attr(&statik).then(|| match statik.body()? {
-                    ast::Expr::BlockExpr(block) => Some(block),
-                    _ => None,
-                }).flatten().and_then(|it| it.stmt_list().map(ImportScope::Block)),
-                _ => None,
-
-            }
-        }
-    }
-
     /// Determines the containing syntax node in which to insert a `use` statement affecting `position`.
     /// Returns the original source node inside attributes.
     pub fn find_insert_use_container(
         position: &SyntaxNode,
         sema: &Semantics<'_, RootDatabase>,
     ) -> Option<Self> {
-        fn contains_cfg_attr(attrs: &dyn HasAttrs) -> bool {
-            attrs.attrs().any(|attr| attr.as_simple_call().is_some_and(|(ident, _)| ident == "cfg"))
-        }
-
+        // The closest block expression ancestor
+        let mut block = None;
+        let mut required_cfgs = Vec::new();
         // Walk up the ancestor tree searching for a suitable node to do insertions on
         // with special handling on cfg-gated items, in which case we want to insert imports locally
         // or FIXME: annotate inserted imports with the same cfg
         for syntax in sema.ancestors_with_macros(position.clone()) {
             if let Some(file) = ast::SourceFile::cast(syntax.clone()) {
-                return Some(ImportScope::File(file));
-            } else if let Some(item) = ast::Item::cast(syntax) {
-                return match item {
-                    ast::Item::Const(konst) if contains_cfg_attr(&konst) => {
-                        // FIXME: Instead of bailing out with None, we should note down that
-                        // this import needs an attribute added
-                        match sema.original_ast_node(konst)?.body()? {
-                            ast::Expr::BlockExpr(block) => block,
-                            _ => return None,
+                return Some(ImportScope { kind: ImportScopeKind::File(file), required_cfgs });
+            } else if let Some(module) = ast::Module::cast(syntax.clone()) {
+                // early return is important here, if we can't find the original module
+                // in the input there is no way for us to insert an import anywhere.
+                return sema
+                    .original_ast_node(module)?
+                    .item_list()
+                    .map(ImportScopeKind::Module)
+                    .map(|kind| ImportScope { kind, required_cfgs });
+            } else if let Some(has_attrs) = ast::AnyHasAttrs::cast(syntax) {
+                if block.is_none() {
+                    if let Some(b) = ast::BlockExpr::cast(has_attrs.syntax().clone()) {
+                        if let Some(b) = sema.original_ast_node(b) {
+                            block = b.stmt_list();
                         }
-                        .stmt_list()
-                        .map(ImportScope::Block)
                     }
-                    ast::Item::Fn(func) if contains_cfg_attr(&func) => {
-                        // FIXME: Instead of bailing out with None, we should note down that
-                        // this import needs an attribute added
-                        sema.original_ast_node(func)?.body()?.stmt_list().map(ImportScope::Block)
-                    }
-                    ast::Item::Static(statik) if contains_cfg_attr(&statik) => {
-                        // FIXME: Instead of bailing out with None, we should note down that
-                        // this import needs an attribute added
-                        match sema.original_ast_node(statik)?.body()? {
-                            ast::Expr::BlockExpr(block) => block,
-                            _ => return None,
-                        }
-                        .stmt_list()
-                        .map(ImportScope::Block)
-                    }
-                    ast::Item::Module(module) => {
-                        // early return is important here, if we can't find the original module
-                        // in the input there is no way for us to insert an import anywhere.
-                        sema.original_ast_node(module)?.item_list().map(ImportScope::Module)
+                }
+                if has_attrs
+                    .attrs()
+                    .any(|attr| attr.as_simple_call().is_some_and(|(ident, _)| ident == "cfg"))
+                {
+                    if let Some(b) = block {
+                        return Some(ImportScope {
+                            kind: ImportScopeKind::Block(b),
+                            required_cfgs,
+                        });
                     }
-                    _ => continue,
-                };
+                    required_cfgs.extend(has_attrs.attrs().filter(|attr| {
+                        attr.as_simple_call().is_some_and(|(ident, _)| ident == "cfg")
+                    }));
+                }
             }
         }
         None
     }
 
     pub fn as_syntax_node(&self) -> &SyntaxNode {
-        match self {
-            ImportScope::File(file) => file.syntax(),
-            ImportScope::Module(item_list) => item_list.syntax(),
-            ImportScope::Block(block) => block.syntax(),
+        match &self.kind {
+            ImportScopeKind::File(file) => file.syntax(),
+            ImportScopeKind::Module(item_list) => item_list.syntax(),
+            ImportScopeKind::Block(block) => block.syntax(),
         }
     }
 
     pub fn clone_for_update(&self) -> Self {
-        match self {
-            ImportScope::File(file) => ImportScope::File(file.clone_for_update()),
-            ImportScope::Module(item_list) => ImportScope::Module(item_list.clone_for_update()),
-            ImportScope::Block(block) => ImportScope::Block(block.clone_for_update()),
+        Self {
+            kind: match &self.kind {
+                ImportScopeKind::File(file) => ImportScopeKind::File(file.clone_for_update()),
+                ImportScopeKind::Module(item_list) => {
+                    ImportScopeKind::Module(item_list.clone_for_update())
+                }
+                ImportScopeKind::Block(block) => ImportScopeKind::Block(block.clone_for_update()),
+            },
+            required_cfgs: self.required_cfgs.iter().map(|attr| attr.clone_for_update()).collect(),
         }
     }
 }
@@ -216,6 +196,11 @@ fn insert_use_with_alias_option(
         use_tree.wrap_in_tree_list();
     }
     let use_item = make::use_(None, use_tree).clone_for_update();
+    for attr in
+        scope.required_cfgs.iter().map(|attr| attr.syntax().clone_subtree().clone_for_update())
+    {
+        ted::insert(ted::Position::first_child_of(use_item.syntax()), attr);
+    }
 
     // merge into existing imports if possible
     if let Some(mb) = mb {
@@ -229,7 +214,6 @@ fn insert_use_with_alias_option(
             }
         }
     }
-
     // either we weren't allowed to merge or there is no import that fits the merge conditions
     // so look for the place we have to insert to
     insert_use_(scope, use_item, cfg.group);
@@ -316,10 +300,10 @@ fn guess_granularity_from_scope(scope: &ImportScope) -> ImportGranularityGuess {
         }
         _ => None,
     };
-    let mut use_stmts = match scope {
-        ImportScope::File(f) => f.items(),
-        ImportScope::Module(m) => m.items(),
-        ImportScope::Block(b) => b.items(),
+    let mut use_stmts = match &scope.kind {
+        ImportScopeKind::File(f) => f.items(),
+        ImportScopeKind::Module(m) => m.items(),
+        ImportScopeKind::Block(b) => b.items(),
     }
     .filter_map(use_stmt);
     let mut res = ImportGranularityGuess::Unknown;
@@ -463,12 +447,12 @@ fn insert_use_(scope: &ImportScope, use_item: ast::Use, group_imports: bool) {
         }
     }
 
-    let l_curly = match scope {
-        ImportScope::File(_) => None,
+    let l_curly = match &scope.kind {
+        ImportScopeKind::File(_) => None,
         // don't insert the imports before the item list/block expr's opening curly brace
-        ImportScope::Module(item_list) => item_list.l_curly_token(),
+        ImportScopeKind::Module(item_list) => item_list.l_curly_token(),
         // don't insert the imports before the item list's opening curly brace
-        ImportScope::Block(block) => block.l_curly_token(),
+        ImportScopeKind::Block(block) => block.l_curly_token(),
     };
     // there are no imports in this file at all
     // so put the import after all inner module attributes and possible license header comments
diff --git a/src/tools/rust-analyzer/crates/ide-db/src/imports/insert_use/tests.rs b/src/tools/rust-analyzer/crates/ide-db/src/imports/insert_use/tests.rs
index 428ba1d5118..4a00854f01a 100644
--- a/src/tools/rust-analyzer/crates/ide-db/src/imports/insert_use/tests.rs
+++ b/src/tools/rust-analyzer/crates/ide-db/src/imports/insert_use/tests.rs
@@ -23,7 +23,7 @@ struct Struct;
 }
 
 #[test]
-fn respects_cfg_attr_fn() {
+fn respects_cfg_attr_fn_body() {
     check(
         r"bar::Bar",
         r#"
@@ -41,6 +41,25 @@ fn foo() {
 }
 
 #[test]
+fn respects_cfg_attr_fn_sig() {
+    check(
+        r"bar::Bar",
+        r#"
+#[cfg(test)]
+fn foo($0) {}
+"#,
+        r#"
+#[cfg(test)]
+use bar::Bar;
+
+#[cfg(test)]
+fn foo() {}
+"#,
+        ImportGranularity::Crate,
+    );
+}
+
+#[test]
 fn respects_cfg_attr_const() {
     check(
         r"bar::Bar",
@@ -59,6 +78,51 @@ const FOO: Bar = {
 }
 
 #[test]
+fn respects_cfg_attr_impl() {
+    check(
+        r"bar::Bar",
+        r#"
+#[cfg(test)]
+impl () {$0}
+"#,
+        r#"
+#[cfg(test)]
+use bar::Bar;
+
+#[cfg(test)]
+impl () {}
+"#,
+        ImportGranularity::Crate,
+    );
+}
+
+#[test]
+fn respects_cfg_attr_multiple_layers() {
+    check(
+        r"bar::Bar",
+        r#"
+#[cfg(test)]
+impl () {
+    #[cfg(test2)]
+    fn f($0) {}
+}
+"#,
+        r#"
+#[cfg(test)]
+#[cfg(test2)]
+use bar::Bar;
+
+#[cfg(test)]
+impl () {
+    #[cfg(test2)]
+    fn f() {}
+}
+"#,
+        ImportGranularity::Crate,
+    );
+}
+
+#[test]
 fn insert_skips_lone_glob_imports() {
     check(
         "use foo::baz::A",
@@ -813,7 +877,7 @@ use {std::io};",
 }
 
 #[test]
-fn merge_groups_skip_attributed() {
+fn merge_groups_cfg_vs_no_cfg() {
     check_crate(
         "std::io",
         r#"
@@ -837,6 +901,25 @@ use {std::io};
 }
 
 #[test]
+fn merge_groups_cfg_matching() {
+    check_crate(
+        "std::io",
+        r#"
+#[cfg(feature = "gated")] use std::fmt::{Result, Display};
+
+#[cfg(feature = "gated")]
+fn f($0) {}
+"#,
+        r#"
+#[cfg(feature = "gated")] use std::{fmt::{Display, Result}, io};
+
+#[cfg(feature = "gated")]
+fn f() {}
+"#,
+    );
+}
+
+#[test]
 fn split_out_merge() {
     // FIXME: This is suboptimal, we want to get `use std::fmt::{self, Result}`
     // instead.
@@ -1259,12 +1342,14 @@ fn check_with_config(
     };
     let sema = &Semantics::new(&db);
     let source_file = sema.parse(file_id);
-    let syntax = source_file.syntax().clone_for_update();
     let file = pos
-        .and_then(|pos| syntax.token_at_offset(pos.expect_offset()).next()?.parent())
+        .and_then(|pos| source_file.syntax().token_at_offset(pos.expect_offset()).next()?.parent())
         .and_then(|it| ImportScope::find_insert_use_container(&it, sema))
-        .or_else(|| ImportScope::from(syntax))
-        .unwrap();
+        .unwrap_or_else(|| ImportScope {
+            kind: ImportScopeKind::File(source_file),
+            required_cfgs: vec![],
+        })
+        .clone_for_update();
     let path = ast::SourceFile::parse(&format!("use {path};"), span::Edition::CURRENT)
         .tree()
         .syntax()
@@ -1349,7 +1434,7 @@ fn check_merge_only_fail(ra_fixture0: &str, ra_fixture1: &str, mb: MergeBehavior
 }
 
 fn check_guess(#[rust_analyzer::rust_fixture] ra_fixture: &str, expected: ImportGranularityGuess) {
-    let syntax = ast::SourceFile::parse(ra_fixture, span::Edition::CURRENT).tree().syntax().clone();
-    let file = ImportScope::from(syntax).unwrap();
+    let syntax = ast::SourceFile::parse(ra_fixture, span::Edition::CURRENT).tree();
+    let file = ImportScope { kind: ImportScopeKind::File(syntax), required_cfgs: vec![] };
     assert_eq!(super::guess_granularity_from_scope(&file), expected);
 }
diff --git a/src/tools/rust-analyzer/crates/ide-db/src/lib.rs b/src/tools/rust-analyzer/crates/ide-db/src/lib.rs
index 63cc7cde280..c94be7e164e 100644
--- a/src/tools/rust-analyzer/crates/ide-db/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/ide-db/src/lib.rs
@@ -92,9 +92,7 @@ pub struct RootDatabase {
 impl std::panic::RefUnwindSafe for RootDatabase {}
 
 #[salsa_macros::db]
-impl salsa::Database for RootDatabase {
-    fn salsa_event(&self, _event: &dyn Fn() -> salsa::Event) {}
-}
+impl salsa::Database for RootDatabase {}
 
 impl Drop for RootDatabase {
     fn drop(&mut self) {
diff --git a/src/tools/rust-analyzer/crates/ide-db/src/search.rs b/src/tools/rust-analyzer/crates/ide-db/src/search.rs
index 30be5bc21b4..c5ad64ed594 100644
--- a/src/tools/rust-analyzer/crates/ide-db/src/search.rs
+++ b/src/tools/rust-analyzer/crates/ide-db/src/search.rs
@@ -524,6 +524,7 @@ impl<'a> FindUsages<'a> {
     fn find_nodes<'b>(
         sema: &'b Semantics<'_, RootDatabase>,
         name: &str,
+        file_id: EditionedFileId,
         node: &syntax::SyntaxNode,
         offset: TextSize,
     ) -> impl Iterator<Item = SyntaxNode> + 'b {
@@ -534,7 +535,7 @@ impl<'a> FindUsages<'a> {
             })
             .into_iter()
             .flat_map(move |token| {
-                if sema.might_be_inside_macro_call(&token) {
+                if sema.is_inside_macro_call(InFile::new(file_id.into(), &token)) {
                     sema.descend_into_macros_exact(token)
                 } else {
                     <_>::from([token])
@@ -654,11 +655,14 @@ impl<'a> FindUsages<'a> {
                     let tree = LazyCell::new(move || sema.parse(file_id).syntax().clone());
 
                     for offset in FindUsages::match_indices(&file_text, &finder, search_range) {
-                        let usages =
-                            FindUsages::find_nodes(sema, &current_to_process, &tree, offset)
-                                .filter(|it| {
-                                    matches!(it.kind(), SyntaxKind::NAME | SyntaxKind::NAME_REF)
-                                });
+                        let usages = FindUsages::find_nodes(
+                            sema,
+                            &current_to_process,
+                            file_id,
+                            &tree,
+                            offset,
+                        )
+                        .filter(|it| matches!(it.kind(), SyntaxKind::NAME | SyntaxKind::NAME_REF));
                         for usage in usages {
                             if let Some(alias) = usage.parent().and_then(|it| {
                                 let path = ast::PathSegment::cast(it)?.parent_path();
@@ -813,7 +817,7 @@ impl<'a> FindUsages<'a> {
                 let tree = LazyCell::new(move || this.sema.parse(file_id).syntax().clone());
 
                 for offset in FindUsages::match_indices(&file_text, finder, search_range) {
-                    let usages = FindUsages::find_nodes(this.sema, name, &tree, offset)
+                    let usages = FindUsages::find_nodes(this.sema, name, file_id, &tree, offset)
                         .filter_map(ast::NameRef::cast);
                     for usage in usages {
                         let found_usage = usage
@@ -957,12 +961,16 @@ impl<'a> FindUsages<'a> {
             // Search for occurrences of the items name
             for offset in Self::match_indices(&text, finder, search_range) {
                 let ret = tree.token_at_offset(offset).any(|token| {
-                    let Some(str_token) = ast::String::cast(token.clone()) else { return false };
-                    if let Some((range, Some(nameres))) =
-                        sema.check_for_format_args_template(token, offset)
+                    if let Some((range, _frange, string_token, Some(nameres))) =
+                        sema.check_for_format_args_template(token.clone(), offset)
                     {
-                        return self
-                            .found_format_args_ref(file_id, range, str_token, nameres, sink);
+                        return self.found_format_args_ref(
+                            file_id,
+                            range,
+                            string_token,
+                            nameres,
+                            sink,
+                        );
                     }
                     false
                 });
@@ -970,8 +978,8 @@ impl<'a> FindUsages<'a> {
                     return;
                 }
 
-                for name in
-                    Self::find_nodes(sema, name, &tree, offset).filter_map(ast::NameLike::cast)
+                for name in Self::find_nodes(sema, name, file_id, &tree, offset)
+                    .filter_map(ast::NameLike::cast)
                 {
                     if match name {
                         ast::NameLike::NameRef(name_ref) => self.found_name_ref(&name_ref, sink),
@@ -985,8 +993,8 @@ impl<'a> FindUsages<'a> {
             // Search for occurrences of the `Self` referring to our type
             if let Some((self_ty, finder)) = &include_self_kw_refs {
                 for offset in Self::match_indices(&text, finder, search_range) {
-                    for name_ref in
-                        Self::find_nodes(sema, "Self", &tree, offset).filter_map(ast::NameRef::cast)
+                    for name_ref in Self::find_nodes(sema, "Self", file_id, &tree, offset)
+                        .filter_map(ast::NameRef::cast)
                     {
                         if self.found_self_ty_name_ref(self_ty, &name_ref, sink) {
                             return;
@@ -1010,7 +1018,7 @@ impl<'a> FindUsages<'a> {
                 let tree = LazyCell::new(move || sema.parse(file_id).syntax().clone());
 
                 for offset in Self::match_indices(&text, finder, search_range) {
-                    for name_ref in Self::find_nodes(sema, "super", &tree, offset)
+                    for name_ref in Self::find_nodes(sema, "super", file_id, &tree, offset)
                         .filter_map(ast::NameRef::cast)
                     {
                         if self.found_name_ref(&name_ref, sink) {
@@ -1020,7 +1028,7 @@ impl<'a> FindUsages<'a> {
                 }
                 if let Some(finder) = &is_crate_root {
                     for offset in Self::match_indices(&text, finder, search_range) {
-                        for name_ref in Self::find_nodes(sema, "crate", &tree, offset)
+                        for name_ref in Self::find_nodes(sema, "crate", file_id, &tree, offset)
                             .filter_map(ast::NameRef::cast)
                         {
                             if self.found_name_ref(&name_ref, sink) {
@@ -1064,8 +1072,8 @@ impl<'a> FindUsages<'a> {
                 let finder = &Finder::new("self");
 
                 for offset in Self::match_indices(&text, finder, search_range) {
-                    for name_ref in
-                        Self::find_nodes(sema, "self", &tree, offset).filter_map(ast::NameRef::cast)
+                    for name_ref in Self::find_nodes(sema, "self", file_id, &tree, offset)
+                        .filter_map(ast::NameRef::cast)
                     {
                         if self.found_self_module_name_ref(&name_ref, sink) {
                             return;
diff --git a/src/tools/rust-analyzer/crates/ide-db/src/source_change.rs b/src/tools/rust-analyzer/crates/ide-db/src/source_change.rs
index b1b58d6568c..16c0d8d97a7 100644
--- a/src/tools/rust-analyzer/crates/ide-db/src/source_change.rs
+++ b/src/tools/rust-analyzer/crates/ide-db/src/source_change.rs
@@ -5,6 +5,7 @@
 
 use std::{collections::hash_map::Entry, fmt, iter, mem};
 
+use crate::imports::insert_use::{ImportScope, ImportScopeKind};
 use crate::text_edit::{TextEdit, TextEditBuilder};
 use crate::{SnippetCap, assists::Command, syntax_helpers::tree_diff::diff};
 use base_db::AnchoredPathBuf;
@@ -367,6 +368,17 @@ impl SourceChangeBuilder {
     pub fn make_mut<N: AstNode>(&mut self, node: N) -> N {
         self.mutated_tree.get_or_insert_with(|| TreeMutator::new(node.syntax())).make_mut(&node)
     }
+
+    pub fn make_import_scope_mut(&mut self, scope: ImportScope) -> ImportScope {
+        ImportScope {
+            kind: match scope.kind.clone() {
+                ImportScopeKind::File(it) => ImportScopeKind::File(self.make_mut(it)),
+                ImportScopeKind::Module(it) => ImportScopeKind::Module(self.make_mut(it)),
+                ImportScopeKind::Block(it) => ImportScopeKind::Block(self.make_mut(it)),
+            },
+            required_cfgs: scope.required_cfgs.iter().map(|it| self.make_mut(it.clone())).collect(),
+        }
+    }
     /// Returns a copy of the `node`, suitable for mutation.
     ///
     /// Syntax trees in rust-analyzer are typically immutable, and mutating
diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/json_is_not_rust.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/json_is_not_rust.rs
index ac1b599c49e..87c9397fb77 100644
--- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/json_is_not_rust.rs
+++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/json_is_not_rust.rs
@@ -137,11 +137,7 @@ pub(crate) fn json_in_items(
                     )
                     .with_fixes(Some(vec![{
                         let mut scb = SourceChangeBuilder::new(vfs_file_id);
-                        let scope = match import_scope {
-                            ImportScope::File(it) => ImportScope::File(scb.make_mut(it)),
-                            ImportScope::Module(it) => ImportScope::Module(scb.make_mut(it)),
-                            ImportScope::Block(it) => ImportScope::Block(scb.make_mut(it)),
-                        };
+                        let scope = scb.make_import_scope_mut(import_scope);
                         let current_module = semantics_scope.module();
 
                         let cfg = ImportPathConfig {
diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_unsafe.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_unsafe.rs
index 364bead34ef..6bd5417b25d 100644
--- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_unsafe.rs
+++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_unsafe.rs
@@ -915,4 +915,47 @@ fn foo() {
             "#,
         );
     }
+
+    #[test]
+    fn regression_19823() {
+        check_diagnostics(
+            r#"
+pub trait FooTrait {
+    unsafe fn method1();
+    unsafe fn method2();
+}
+
+unsafe fn some_unsafe_fn() {}
+
+macro_rules! impl_foo {
+    () => {
+        unsafe fn method1() {
+            some_unsafe_fn();
+        }
+        unsafe fn method2() {
+            some_unsafe_fn();
+        }
+    };
+}
+
+pub struct S1;
+#[allow(unsafe_op_in_unsafe_fn)]
+impl FooTrait for S1 {
+    unsafe fn method1() {
+        some_unsafe_fn();
+    }
+
+    unsafe fn method2() {
+        some_unsafe_fn();
+    }
+}
+
+pub struct S2;
+#[allow(unsafe_op_in_unsafe_fn)]
+impl FooTrait for S2 {
+    impl_foo!();
+}
+        "#,
+        );
+    }
 }
diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/non_exhaustive_let.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/non_exhaustive_let.rs
index 35cefd23975..f20b6dea122 100644
--- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/non_exhaustive_let.rs
+++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/non_exhaustive_let.rs
@@ -106,4 +106,29 @@ fn test(x: Result<i32, &'static !>) {
 "#,
         );
     }
+
+    #[test]
+    fn empty_patterns_normalize() {
+        check_diagnostics(
+            r#"
+enum Infallible {}
+
+trait Foo {
+    type Assoc;
+}
+enum Enum<T: Foo> {
+    A,
+    B(T::Assoc),
+}
+
+impl Foo for () {
+    type Assoc = Infallible;
+}
+
+fn foo(v: Enum<()>) {
+    let Enum::A = v;
+}
+        "#,
+        );
+    }
 }
diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/type_mismatch.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/type_mismatch.rs
index 5253734867e..076df1ab0f8 100644
--- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/type_mismatch.rs
+++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/type_mismatch.rs
@@ -1243,4 +1243,18 @@ fn foo(v: &Enum) {
     "#,
         );
     }
+
+    #[test]
+    fn regression_19844() {
+        check_diagnostics(
+            r#"
+fn main() {
+    struct S {}
+    enum E { V() }
+    let E::V() = &S {};
+     // ^^^^^^ error: expected S, found E
+}
+"#,
+        );
+    }
 }
diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/lib.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/lib.rs
index 2af14ca949b..72bd66d1c8b 100644
--- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/lib.rs
@@ -83,12 +83,11 @@ mod handlers {
 #[cfg(test)]
 mod tests;
 
-use std::{collections::hash_map, iter, sync::LazyLock};
+use std::{iter, sync::LazyLock};
 
 use either::Either;
 use hir::{
-    Crate, DisplayTarget, HirFileId, InFile, Semantics, db::ExpandDatabase,
-    diagnostics::AnyDiagnostic,
+    Crate, DisplayTarget, InFile, Semantics, db::ExpandDatabase, diagnostics::AnyDiagnostic,
 };
 use ide_db::{
     EditionedFileId, FileId, FileRange, FxHashMap, FxHashSet, RootDatabase, Severity, SnippetCap,
@@ -513,13 +512,7 @@ pub fn semantic_diagnostics(
 
     // The edition isn't accurate (each diagnostics may have its own edition due to macros),
     // but it's okay as it's only being used for error recovery.
-    handle_lints(
-        &ctx.sema,
-        &mut FxHashMap::default(),
-        &mut lints,
-        &mut Vec::new(),
-        editioned_file_id.edition(db),
-    );
+    handle_lints(&ctx.sema, &mut lints, editioned_file_id.edition(db));
 
     res.retain(|d| d.severity != Severity::Allow);
 
@@ -584,8 +577,6 @@ fn handle_diag_from_macros(
     true
 }
 
-// `__RA_EVERY_LINT` is a fake lint group to allow every lint in proc macros
-
 struct BuiltLint {
     lint: &'static Lint,
     groups: Vec<&'static str>,
@@ -629,9 +620,7 @@ fn build_lints_map(
 
 fn handle_lints(
     sema: &Semantics<'_, RootDatabase>,
-    cache: &mut FxHashMap<HirFileId, FxHashMap<SmolStr, SeverityAttr>>,
     diagnostics: &mut [(InFile<SyntaxNode>, &mut Diagnostic)],
-    cache_stack: &mut Vec<HirFileId>,
     edition: Edition,
 ) {
     for (node, diag) in diagnostics {
@@ -645,7 +634,8 @@ fn handle_lints(
             diag.severity = default_severity;
         }
 
-        let mut diag_severity = fill_lint_attrs(sema, node, cache, cache_stack, diag, edition);
+        let mut diag_severity =
+            lint_severity_at(sema, node, &lint_groups(&diag.code, edition), edition);
 
         if let outline_diag_severity @ Some(_) =
             find_outline_mod_lint_severity(sema, node, diag, edition)
@@ -698,155 +688,22 @@ fn find_outline_mod_lint_severity(
     result
 }
 
-#[derive(Debug, Clone, Copy)]
-struct SeverityAttr {
-    severity: Severity,
-    /// This field counts how far we are from the main node. Bigger values mean more far.
-    ///
-    /// Note this isn't accurate: there can be gaps between values (created when merging severity maps).
-    /// The important thing is that if an attr is closer to the main node, it will have smaller value.
-    ///
-    /// This is necessary even though we take care to never overwrite a value from deeper nesting
-    /// because of lint groups. For example, in the following code:
-    /// ```
-    /// #[warn(non_snake_case)]
-    /// mod foo {
-    ///     #[allow(nonstandard_style)]
-    ///     mod bar {}
-    /// }
-    /// ```
-    /// We want to not warn on non snake case inside `bar`. If we are traversing this for the first
-    /// time, everything will be fine, because we will set `diag_severity` on the first matching group
-    /// and never overwrite it since then. But if `bar` is cached, the cache will contain both
-    /// `#[warn(non_snake_case)]` and `#[allow(nonstandard_style)]`, and without this field, we have
-    /// no way of differentiating between the two.
-    depth: u32,
-}
-
-fn fill_lint_attrs(
+fn lint_severity_at(
     sema: &Semantics<'_, RootDatabase>,
     node: &InFile<SyntaxNode>,
-    cache: &mut FxHashMap<HirFileId, FxHashMap<SmolStr, SeverityAttr>>,
-    cache_stack: &mut Vec<HirFileId>,
-    diag: &Diagnostic,
+    lint_groups: &LintGroups,
     edition: Edition,
 ) -> Option<Severity> {
-    let mut collected_lint_attrs = FxHashMap::<SmolStr, SeverityAttr>::default();
-    let mut diag_severity = None;
-
-    let mut ancestors = node.value.ancestors().peekable();
-    let mut depth = 0;
-    loop {
-        let ancestor = ancestors.next().expect("we always return from top-level nodes");
-        depth += 1;
-
-        if ancestors.peek().is_none() {
-            // We don't want to insert too many nodes into cache, but top level nodes (aka. outline modules
-            // or macro expansions) need to touch the database so they seem like a good fit to cache.
-
-            if let Some(cached) = cache.get_mut(&node.file_id) {
-                // This node (and everything above it) is already cached; the attribute is either here or nowhere.
-
-                // Workaround for the borrow checker.
-                let cached = std::mem::take(cached);
-
-                cached.iter().for_each(|(lint, severity)| {
-                    for item in &*cache_stack {
-                        let node_cache_entry = cache
-                            .get_mut(item)
-                            .expect("we always insert cached nodes into the cache map");
-                        let lint_cache_entry = node_cache_entry.entry(lint.clone());
-                        if let hash_map::Entry::Vacant(lint_cache_entry) = lint_cache_entry {
-                            // Do not overwrite existing lint attributes, as we go bottom to top and bottom attrs
-                            // overwrite top attrs.
-                            lint_cache_entry.insert(SeverityAttr {
-                                severity: severity.severity,
-                                depth: severity.depth + depth,
-                            });
-                        }
-                    }
-                });
-
-                let lints = lint_groups(&diag.code, edition);
-                let all_matching_groups =
-                    lints.iter().filter_map(|lint_group| cached.get(lint_group));
-                let cached_severity =
-                    all_matching_groups.min_by_key(|it| it.depth).map(|it| it.severity);
-
-                cache.insert(node.file_id, cached);
-
-                return diag_severity.or(cached_severity);
-            }
-
-            // Insert this node's descendants' attributes into any outline descendant, but not including this node.
-            // This must come before inserting this node's own attributes to preserve order.
-            collected_lint_attrs.drain().for_each(|(lint, severity)| {
-                if diag_severity.is_none() && lint_groups(&diag.code, edition).contains(&lint) {
-                    diag_severity = Some(severity.severity);
-                }
-
-                for item in &*cache_stack {
-                    let node_cache_entry = cache
-                        .get_mut(item)
-                        .expect("we always insert cached nodes into the cache map");
-                    let lint_cache_entry = node_cache_entry.entry(lint.clone());
-                    if let hash_map::Entry::Vacant(lint_cache_entry) = lint_cache_entry {
-                        // Do not overwrite existing lint attributes, as we go bottom to top and bottom attrs
-                        // overwrite top attrs.
-                        lint_cache_entry.insert(severity);
-                    }
-                }
-            });
-
-            cache_stack.push(node.file_id);
-            cache.insert(node.file_id, FxHashMap::default());
-
-            if let Some(ancestor) = ast::AnyHasAttrs::cast(ancestor) {
-                // Insert this node's attributes into any outline descendant, including this node.
-                lint_attrs(sema, ancestor, edition).for_each(|(lint, severity)| {
-                    if diag_severity.is_none() && lint_groups(&diag.code, edition).contains(&lint) {
-                        diag_severity = Some(severity);
-                    }
-
-                    for item in &*cache_stack {
-                        let node_cache_entry = cache
-                            .get_mut(item)
-                            .expect("we always insert cached nodes into the cache map");
-                        let lint_cache_entry = node_cache_entry.entry(lint.clone());
-                        if let hash_map::Entry::Vacant(lint_cache_entry) = lint_cache_entry {
-                            // Do not overwrite existing lint attributes, as we go bottom to top and bottom attrs
-                            // overwrite top attrs.
-                            lint_cache_entry.insert(SeverityAttr { severity, depth });
-                        }
-                    }
-                });
-            }
-
-            let parent_node = sema.find_parent_file(node.file_id);
-            if let Some(parent_node) = parent_node {
-                let parent_severity =
-                    fill_lint_attrs(sema, &parent_node, cache, cache_stack, diag, edition);
-                if diag_severity.is_none() {
-                    diag_severity = parent_severity;
-                }
-            }
-            cache_stack.pop();
-            return diag_severity;
-        } else if let Some(ancestor) = ast::AnyHasAttrs::cast(ancestor) {
-            lint_attrs(sema, ancestor, edition).for_each(|(lint, severity)| {
-                if diag_severity.is_none() && lint_groups(&diag.code, edition).contains(&lint) {
-                    diag_severity = Some(severity);
-                }
-
-                let lint_cache_entry = collected_lint_attrs.entry(lint);
-                if let hash_map::Entry::Vacant(lint_cache_entry) = lint_cache_entry {
-                    // Do not overwrite existing lint attributes, as we go bottom to top and bottom attrs
-                    // overwrite top attrs.
-                    lint_cache_entry.insert(SeverityAttr { severity, depth });
-                }
-            });
-        }
-    }
+    node.value
+        .ancestors()
+        .filter_map(ast::AnyHasAttrs::cast)
+        .find_map(|ancestor| {
+            lint_attrs(sema, ancestor, edition)
+                .find_map(|(lint, severity)| lint_groups.contains(&lint).then_some(severity))
+        })
+        .or_else(|| {
+            lint_severity_at(sema, &sema.find_parent_file(node.file_id)?, lint_groups, edition)
+        })
 }
 
 fn lint_attrs<'a>(
@@ -945,10 +802,6 @@ impl LintGroups {
     fn contains(&self, group: &str) -> bool {
         self.groups.contains(&group) || (self.inside_warnings && group == "warnings")
     }
-
-    fn iter(&self) -> impl Iterator<Item = &'static str> {
-        self.groups.iter().copied().chain(self.inside_warnings.then_some("warnings"))
-    }
 }
 
 fn lint_groups(lint: &DiagnosticCode, edition: Edition) -> LintGroups {
diff --git a/src/tools/rust-analyzer/crates/ide-ssr/src/lib.rs b/src/tools/rust-analyzer/crates/ide-ssr/src/lib.rs
index 339c199ec29..43c56ac8bec 100644
--- a/src/tools/rust-analyzer/crates/ide-ssr/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/ide-ssr/src/lib.rs
@@ -287,7 +287,7 @@ impl<'db> MatchFinder<'db> {
                 if let Some(expanded) = self.sema.expand_macro_call(&macro_call) {
                     if let Some(tt) = macro_call.token_tree() {
                         self.output_debug_for_nodes_at_range(
-                            &expanded,
+                            &expanded.value,
                             range,
                             &Some(self.sema.original_range(tt.syntax())),
                             out,
diff --git a/src/tools/rust-analyzer/crates/ide-ssr/src/search.rs b/src/tools/rust-analyzer/crates/ide-ssr/src/search.rs
index d89911fca40..9afbedbb1ab 100644
--- a/src/tools/rust-analyzer/crates/ide-ssr/src/search.rs
+++ b/src/tools/rust-analyzer/crates/ide-ssr/src/search.rs
@@ -194,7 +194,7 @@ impl MatchFinder<'_> {
                     // nodes that originated entirely from within the token tree of the macro call.
                     // i.e. we don't want to match something that came from the macro itself.
                     if let Some(range) = self.sema.original_range_opt(tt.syntax()) {
-                        self.slow_scan_node(&expanded, rule, &Some(range), matches_out);
+                        self.slow_scan_node(&expanded.value, rule, &Some(range), matches_out);
                     }
                 }
             }
diff --git a/src/tools/rust-analyzer/crates/ide/src/expand_macro.rs b/src/tools/rust-analyzer/crates/ide/src/expand_macro.rs
index 241a702038d..7c396339c14 100644
--- a/src/tools/rust-analyzer/crates/ide/src/expand_macro.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/expand_macro.rs
@@ -1,10 +1,10 @@
 use hir::db::ExpandDatabase;
-use hir::{ExpandResult, InFile, Semantics};
+use hir::{ExpandResult, InFile, InRealFile, Semantics};
 use ide_db::{
     FileId, RootDatabase, base_db::Crate, helpers::pick_best_token,
     syntax_helpers::prettify_macro_expansion,
 };
-use span::{Edition, SpanMap, SyntaxContext, TextRange, TextSize};
+use span::{SpanMap, SyntaxContext, TextRange, TextSize};
 use stdx::format_to;
 use syntax::{AstNode, NodeOrToken, SyntaxKind, SyntaxNode, T, ast, ted};
 
@@ -26,8 +26,9 @@ pub struct ExpandedMacro {
 // ![Expand Macro Recursively](https://user-images.githubusercontent.com/48062697/113020648-b3973180-917a-11eb-84a9-ecb921293dc5.gif)
 pub(crate) fn expand_macro(db: &RootDatabase, position: FilePosition) -> Option<ExpandedMacro> {
     let sema = Semantics::new(db);
-    let file = sema.parse_guess_edition(position.file_id);
-    let krate = sema.file_to_module_def(position.file_id)?.krate().into();
+    let file_id = sema.attach_first_edition(position.file_id)?;
+    let file = sema.parse(file_id);
+    let krate = sema.file_to_module_def(file_id.file_id(db))?.krate().into();
 
     let tok = pick_best_token(file.syntax().token_at_offset(position.offset), |kind| match kind {
         SyntaxKind::IDENT => 1,
@@ -86,7 +87,10 @@ pub(crate) fn expand_macro(db: &RootDatabase, position: FilePosition) -> Option<
         return derive;
     }
 
-    let mut anc = tok.parent_ancestors();
+    let mut anc = sema
+        .descend_token_into_include_expansion(InRealFile::new(file_id, tok))
+        .value
+        .parent_ancestors();
     let mut span_map = SpanMap::empty();
     let mut error = String::new();
     let (name, expanded, kind) = loop {
@@ -95,14 +99,7 @@ pub(crate) fn expand_macro(db: &RootDatabase, position: FilePosition) -> Option<
         if let Some(item) = ast::Item::cast(node.clone()) {
             if let Some(def) = sema.resolve_attr_macro_call(&item) {
                 break (
-                    def.name(db)
-                        .display(
-                            db,
-                            sema.attach_first_edition(position.file_id)
-                                .map(|it| it.edition(db))
-                                .unwrap_or(Edition::CURRENT),
-                        )
-                        .to_string(),
+                    def.name(db).display(db, file_id.edition(db)).to_string(),
                     expand_macro_recur(&sema, &item, &mut error, &mut span_map, TextSize::new(0))?,
                     SyntaxKind::MACRO_ITEMS,
                 );
@@ -146,10 +143,11 @@ fn expand_macro_recur(
     offset_in_original_node: TextSize,
 ) -> Option<SyntaxNode> {
     let ExpandResult { value: expanded, err } = match macro_call {
-        item @ ast::Item::MacroCall(macro_call) => {
-            sema.expand_attr_macro(item).or_else(|| sema.expand_allowed_builtins(macro_call))?
-        }
-        item => sema.expand_attr_macro(item)?,
+        item @ ast::Item::MacroCall(macro_call) => sema
+            .expand_attr_macro(item)
+            .map(|it| it.map(|it| it.value))
+            .or_else(|| sema.expand_allowed_builtins(macro_call))?,
+        item => sema.expand_attr_macro(item)?.map(|it| it.value),
     };
     let expanded = expanded.clone_for_update();
     if let Some(err) = err {
@@ -718,4 +716,88 @@ __log!(written:%; "Test"$0);
             "#]],
         );
     }
+
+    #[test]
+    fn assoc_call() {
+        check(
+            r#"
+macro_rules! mac {
+    () => { fn assoc() {} }
+}
+impl () {
+    mac$0!();
+}
+    "#,
+            expect![[r#"
+                mac!
+                fn assoc(){}"#]],
+        );
+    }
+
+    #[test]
+    fn eager() {
+        check(
+            r#"
+//- minicore: concat
+macro_rules! my_concat {
+    ($head:expr, $($tail:tt)*) => { concat!($head, $($tail)*) };
+}
+
+
+fn test() {
+    _ = my_concat!(
+        conc$0at!("<", ">"),
+        "hi",
+    );
+}
+    "#,
+            expect![[r#"
+                my_concat!
+                "<>hi""#]],
+        );
+    }
+
+    #[test]
+    fn in_included() {
+        check(
+            r#"
+//- minicore: include
+//- /main.rs crate:main
+include!("./included.rs");
+//- /included.rs
+macro_rules! foo {
+    () => { fn item() {} };
+}
+foo$0!();
+"#,
+            expect![[r#"
+                foo!
+                fn item(){}"#]],
+        );
+    }
+
+    #[test]
+    fn include() {
+        check(
+            r#"
+//- minicore: include
+//- /main.rs crate:main
+include$0!("./included.rs");
+//- /included.rs
+macro_rules! foo {
+    () => { fn item() {} };
+}
+foo();
+"#,
+            expect![[r#"
+                include!
+                macro_rules! foo {
+                    () => {
+                        fn item(){}
+
+                    };
+                }
+                foo();"#]],
+        );
+    }
 }
diff --git a/src/tools/rust-analyzer/crates/ide/src/goto_definition.rs b/src/tools/rust-analyzer/crates/ide/src/goto_definition.rs
index c60ca3562f6..7917aab8bf7 100644
--- a/src/tools/rust-analyzer/crates/ide/src/goto_definition.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/goto_definition.rs
@@ -67,7 +67,7 @@ pub(crate) fn goto_definition(
         });
     }
 
-    if let Some((range, resolution)) =
+    if let Some((range, _, _, resolution)) =
         sema.check_for_format_args_template(original_token.clone(), offset)
     {
         return Some(RangeInfo::new(
diff --git a/src/tools/rust-analyzer/crates/ide/src/goto_type_definition.rs b/src/tools/rust-analyzer/crates/ide/src/goto_type_definition.rs
index a78f5cdc9d0..a6c7ea29b09 100644
--- a/src/tools/rust-analyzer/crates/ide/src/goto_type_definition.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/goto_type_definition.rs
@@ -53,7 +53,9 @@ pub(crate) fn goto_type_definition(
             }
         });
     };
-    if let Some((range, resolution)) = sema.check_for_format_args_template(token.clone(), offset) {
+    if let Some((range, _, _, resolution)) =
+        sema.check_for_format_args_template(token.clone(), offset)
+    {
         if let Some(ty) = resolution.and_then(|res| match Definition::from(res) {
             Definition::Const(it) => Some(it.ty(db)),
             Definition::Static(it) => Some(it.ty(db)),
diff --git a/src/tools/rust-analyzer/crates/ide/src/highlight_related.rs b/src/tools/rust-analyzer/crates/ide/src/highlight_related.rs
index fb8dbcfc735..aa947921a9b 100644
--- a/src/tools/rust-analyzer/crates/ide/src/highlight_related.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/highlight_related.rs
@@ -11,7 +11,6 @@ use ide_db::{
         preorder_expr_with_ctx_checker,
     },
 };
-use span::FileId;
 use syntax::{
     AstNode,
     SyntaxKind::{self, IDENT, INT_NUMBER},
@@ -61,13 +60,12 @@ pub(crate) fn highlight_related(
     let file_id = sema
         .attach_first_edition(file_id)
         .unwrap_or_else(|| EditionedFileId::current_edition(sema.db, file_id));
-    let span_file_id = file_id.editioned_file_id(sema.db);
     let syntax = sema.parse(file_id).syntax().clone();
 
     let token = pick_best_token(syntax.token_at_offset(offset), |kind| match kind {
         T![?] => 4, // prefer `?` when the cursor is sandwiched like in `await$0?`
         T![->] => 4,
-        kind if kind.is_keyword(span_file_id.edition()) => 3,
+        kind if kind.is_keyword(file_id.edition(sema.db)) => 3,
         IDENT | INT_NUMBER => 2,
         T![|] => 1,
         _ => 0,
@@ -92,18 +90,11 @@ pub(crate) fn highlight_related(
         T![unsafe] if token.parent().and_then(ast::BlockExpr::cast).is_some() => {
             highlight_unsafe_points(sema, token).remove(&file_id)
         }
-        T![|] if config.closure_captures => {
-            highlight_closure_captures(sema, token, file_id, span_file_id.file_id())
+        T![|] if config.closure_captures => highlight_closure_captures(sema, token, file_id),
+        T![move] if config.closure_captures => highlight_closure_captures(sema, token, file_id),
+        _ if config.references => {
+            highlight_references(sema, token, FilePosition { file_id, offset })
         }
-        T![move] if config.closure_captures => {
-            highlight_closure_captures(sema, token, file_id, span_file_id.file_id())
-        }
-        _ if config.references => highlight_references(
-            sema,
-            token,
-            FilePosition { file_id, offset },
-            span_file_id.file_id(),
-        ),
         _ => None,
     }
 }
@@ -112,7 +103,6 @@ fn highlight_closure_captures(
     sema: &Semantics<'_, RootDatabase>,
     token: SyntaxToken,
     file_id: EditionedFileId,
-    vfs_file_id: FileId,
 ) -> Option<Vec<HighlightedRange>> {
     let closure = token.parent_ancestors().take(2).find_map(ast::ClosureExpr::cast)?;
     let search_range = closure.body()?.syntax().text_range();
@@ -145,7 +135,7 @@ fn highlight_closure_captures(
                     .sources(sema.db)
                     .into_iter()
                     .flat_map(|x| x.to_nav(sema.db))
-                    .filter(|decl| decl.file_id == vfs_file_id)
+                    .filter(|decl| decl.file_id == file_id.file_id(sema.db))
                     .filter_map(|decl| decl.focus_range)
                     .map(move |range| HighlightedRange { range, category })
                     .chain(usages)
@@ -158,9 +148,8 @@ fn highlight_references(
     sema: &Semantics<'_, RootDatabase>,
     token: SyntaxToken,
     FilePosition { file_id, offset }: FilePosition,
-    vfs_file_id: FileId,
 ) -> Option<Vec<HighlightedRange>> {
-    let defs = if let Some((range, resolution)) =
+    let defs = if let Some((range, _, _, resolution)) =
         sema.check_for_format_args_template(token.clone(), offset)
     {
         match resolution.map(Definition::from) {
@@ -270,7 +259,7 @@ fn highlight_references(
                     .sources(sema.db)
                     .into_iter()
                     .flat_map(|x| x.to_nav(sema.db))
-                    .filter(|decl| decl.file_id == vfs_file_id)
+                    .filter(|decl| decl.file_id == file_id.file_id(sema.db))
                     .filter_map(|decl| decl.focus_range)
                     .map(|range| HighlightedRange { range, category })
                     .for_each(|x| {
@@ -288,7 +277,7 @@ fn highlight_references(
                     },
                 };
                 for nav in navs {
-                    if nav.file_id != vfs_file_id {
+                    if nav.file_id != file_id.file_id(sema.db) {
                         continue;
                     }
                     let hl_range = nav.focus_range.map(|range| {
@@ -653,7 +642,7 @@ impl<'a> WalkExpandedExprCtx<'a> {
                             expr.macro_call().and_then(|call| self.sema.expand_macro_call(&call))
                         {
                             match_ast! {
-                                match expanded {
+                                match (expanded.value) {
                                     ast::MacroStmts(it) => {
                                         self.handle_expanded(it, cb);
                                     },
diff --git a/src/tools/rust-analyzer/crates/ide/src/hover.rs b/src/tools/rust-analyzer/crates/ide/src/hover.rs
index 873e31b4a33..5404a9dc2ce 100644
--- a/src/tools/rust-analyzer/crates/ide/src/hover.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/hover.rs
@@ -58,6 +58,7 @@ pub struct MemoryLayoutHoverConfig {
     pub size: Option<MemoryLayoutHoverRenderKind>,
     pub offset: Option<MemoryLayoutHoverRenderKind>,
     pub alignment: Option<MemoryLayoutHoverRenderKind>,
+    pub padding: Option<MemoryLayoutHoverRenderKind>,
     pub niches: bool,
 }
 
@@ -199,7 +200,7 @@ fn hover_offset(
         });
     }
 
-    if let Some((range, resolution)) =
+    if let Some((range, _, _, resolution)) =
         sema.check_for_format_args_template(original_token.clone(), offset)
     {
         let res = hover_for_definition(
diff --git a/src/tools/rust-analyzer/crates/ide/src/hover/render.rs b/src/tools/rust-analyzer/crates/ide/src/hover/render.rs
index ad720c8a627..c24864a18bd 100644
--- a/src/tools/rust-analyzer/crates/ide/src/hover/render.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/hover/render.rs
@@ -630,27 +630,57 @@ pub(super) fn definition(
                 }
             },
             |_| None,
+            |_| None,
+        ),
+        Definition::Adt(it @ Adt::Struct(strukt)) => render_memory_layout(
+            config.memory_layout,
+            || it.layout(db),
+            |_| None,
+            |layout| {
+                let mut field_size =
+                    |i: usize| Some(strukt.fields(db).get(i)?.layout(db).ok()?.size());
+                if strukt.repr(db).is_some_and(|it| it.inhibit_struct_field_reordering()) {
+                    Some(("tail padding", layout.tail_padding(&mut field_size)?))
+                } else {
+                    Some(("largest padding", layout.largest_padding(&mut field_size)?))
+                }
+            },
+            |_| None,
+        ),
+        Definition::Adt(it) => render_memory_layout(
+            config.memory_layout,
+            || it.layout(db),
+            |_| None,
+            |_| None,
+            |_| None,
         ),
-        Definition::Adt(it) => {
-            render_memory_layout(config.memory_layout, || it.layout(db), |_| None, |_| None)
-        }
         Definition::Variant(it) => render_memory_layout(
             config.memory_layout,
             || it.layout(db),
             |_| None,
+            |_| None,
             |layout| layout.enum_tag_size(),
         ),
-        Definition::TypeAlias(it) => {
-            render_memory_layout(config.memory_layout, || it.ty(db).layout(db), |_| None, |_| None)
-        }
-        Definition::Local(it) => {
-            render_memory_layout(config.memory_layout, || it.ty(db).layout(db), |_| None, |_| None)
-        }
+        Definition::TypeAlias(it) => render_memory_layout(
+            config.memory_layout,
+            || it.ty(db).layout(db),
+            |_| None,
+            |_| None,
+            |_| None,
+        ),
+        Definition::Local(it) => render_memory_layout(
+            config.memory_layout,
+            || it.ty(db).layout(db),
+            |_| None,
+            |_| None,
+            |_| None,
+        ),
         Definition::SelfType(it) => render_memory_layout(
             config.memory_layout,
             || it.self_ty(db).layout(db),
             |_| None,
             |_| None,
+            |_| None,
         ),
         _ => None,
     };
@@ -1055,9 +1085,13 @@ fn closure_ty(
     if let Some(trait_) = c.fn_trait(sema.db).get_id(sema.db, original.krate(sema.db).into()) {
         push_new_def(hir::Trait::from(trait_).into())
     }
-    if let Some(layout) =
-        render_memory_layout(config.memory_layout, || original.layout(sema.db), |_| None, |_| None)
-    {
+    if let Some(layout) = render_memory_layout(
+        config.memory_layout,
+        || original.layout(sema.db),
+        |_| None,
+        |_| None,
+        |_| None,
+    ) {
         format_to!(markup, "\n___\n{layout}");
     }
     format_to!(markup, "{adjusted}\n\n## Captures\n{}", captures_rendered,);
@@ -1142,6 +1176,7 @@ fn render_memory_layout(
     config: Option<MemoryLayoutHoverConfig>,
     layout: impl FnOnce() -> Result<Layout, LayoutError>,
     offset: impl FnOnce(&Layout) -> Option<u64>,
+    padding: impl FnOnce(&Layout) -> Option<(&str, u64)>,
     tag: impl FnOnce(&Layout) -> Option<usize>,
 ) -> Option<String> {
     let config = config?;
@@ -1199,6 +1234,23 @@ fn render_memory_layout(
         }
     }
 
+    if let Some(render) = config.padding {
+        if let Some((padding_name, padding)) = padding(&layout) {
+            format_to!(label, "{padding_name} = ");
+            match render {
+                MemoryLayoutHoverRenderKind::Decimal => format_to!(label, "{padding}"),
+                MemoryLayoutHoverRenderKind::Hexadecimal => format_to!(label, "{padding:#X}"),
+                MemoryLayoutHoverRenderKind::Both if padding >= 10 => {
+                    format_to!(label, "{padding} ({padding:#X})")
+                }
+                MemoryLayoutHoverRenderKind::Both => {
+                    format_to!(label, "{padding}")
+                }
+            }
+            format_to!(label, ", ");
+        }
+    }
+
     if config.niches {
         if let Some(niches) = layout.niches() {
             if niches > 1024 {
diff --git a/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs b/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs
index 06ca24c3ec3..a281a491525 100644
--- a/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs
@@ -12,6 +12,7 @@ const HOVER_BASE_CONFIG: HoverConfig = HoverConfig {
         size: Some(MemoryLayoutHoverRenderKind::Both),
         offset: Some(MemoryLayoutHoverRenderKind::Both),
         alignment: Some(MemoryLayoutHoverRenderKind::Both),
+        padding: Some(MemoryLayoutHoverRenderKind::Both),
         niches: true,
     }),
     documentation: true,
@@ -933,7 +934,7 @@ struct Foo$0(pub u32) where u32: Copy;
 
             ---
 
-            size = 4, align = 4, no Drop
+            size = 4, align = 4, largest padding = 0, no Drop
         "#]],
     );
 }
@@ -959,7 +960,7 @@ struct Foo$0 { field: u32 }
 
             ---
 
-            size = 4, align = 4, no Drop
+            size = 4, align = 4, largest padding = 0, no Drop
         "#]],
     );
     check(
@@ -984,7 +985,7 @@ struct Foo$0 where u32: Copy { field: u32 }
 
             ---
 
-            size = 4, align = 4, no Drop
+            size = 4, align = 4, largest padding = 0, no Drop
         "#]],
     );
 }
@@ -1013,7 +1014,7 @@ fn hover_record_struct_limit() {
 
             ---
 
-            size = 12 (0xC), align = 4, no Drop
+            size = 12 (0xC), align = 4, largest padding = 0, no Drop
         "#]],
     );
     check_hover_fields_limit(
@@ -1036,7 +1037,7 @@ fn hover_record_struct_limit() {
 
             ---
 
-            size = 4, align = 4, no Drop
+            size = 4, align = 4, largest padding = 0, no Drop
         "#]],
     );
     check_hover_fields_limit(
@@ -1062,7 +1063,7 @@ fn hover_record_struct_limit() {
 
             ---
 
-            size = 16 (0x10), align = 4, no Drop
+            size = 16 (0x10), align = 4, largest padding = 0, no Drop
         "#]],
     );
     check_hover_fields_limit(
@@ -1083,7 +1084,7 @@ fn hover_record_struct_limit() {
 
             ---
 
-            size = 12 (0xC), align = 4, no Drop
+            size = 12 (0xC), align = 4, largest padding = 0, no Drop
         "#]],
     );
     check_hover_fields_limit(
@@ -1104,7 +1105,7 @@ fn hover_record_struct_limit() {
 
             ---
 
-            size = 12 (0xC), align = 4, no Drop
+            size = 12 (0xC), align = 4, largest padding = 0, no Drop
         "#]],
     );
 
@@ -3114,7 +3115,7 @@ struct S$0<T>(core::marker::PhantomData<T>);
 
             ---
 
-            size = 0, align = 1, no Drop
+            size = 0, align = 1, largest padding = 0, no Drop
         "#]],
     );
 }
@@ -3148,6 +3149,111 @@ fn test_hover_layout_of_enum() {
 }
 
 #[test]
+fn test_hover_layout_padding_info() {
+    check(
+        r#"struct $0Foo {
+            x: bool,
+            y: i64,
+            z: u32,
+        }"#,
+        expect![[r#"
+            *Foo*
+
+            ```rust
+            ra_test_fixture
+            ```
+
+            ```rust
+            struct Foo {
+                x: bool,
+                y: i64,
+                z: u32,
+            }
+            ```
+
+            ---
+
+            size = 16 (0x10), align = 8, largest padding = 3, niches = 254, no Drop
+        "#]],
+    );
+
+    check(
+        r#"#[repr(align(32))]
+        struct $0Foo {
+            x: bool,
+            y: i64,
+            z: u32,
+        }"#,
+        expect![[r#"
+            *Foo*
+
+            ```rust
+            ra_test_fixture
+            ```
+
+            ```rust
+            struct Foo {
+                x: bool,
+                y: i64,
+                z: u32,
+            }
+            ```
+
+            ---
+
+            size = 32 (0x20), align = 32 (0x20), largest padding = 19 (0x13), niches = 254, no Drop
+        "#]],
+    );
+
+    check(
+        r#"#[repr(C)]
+        struct $0Foo {
+            x: bool,
+            y: i64,
+            z: u32,
+        }"#,
+        expect![[r#"
+            *Foo*
+
+            ```rust
+            ra_test_fixture
+            ```
+
+            ```rust
+            struct Foo {
+                x: bool,
+                y: i64,
+                z: u32,
+            }
+            ```
+
+            ---
+
+            size = 24 (0x18), align = 8, tail padding = 4, niches = 254, no Drop
+        "#]],
+    );
+
+    check(
+        r#"struct $0Foo(i16, u128, u64)"#,
+        expect![[r#"
+            *Foo*
+
+            ```rust
+            ra_test_fixture
+            ```
+
+            ```rust
+            struct Foo(i16, u128, u64)
+            ```
+
+            ---
+
+            size = 32 (0x20), align = 8, largest padding = 6, no Drop
+        "#]],
+    );
+}
+
+#[test]
 fn test_hover_no_memory_layout() {
     check_hover_no_memory_layout(
         r#"struct Foo { fiel$0d_a: u8, field_b: i32, field_c: i16 }"#,
@@ -9198,7 +9304,7 @@ struct Pedro$0<'a> {
 
             ---
 
-            size = 16 (0x10), align = 8, niches = 1, no Drop
+            size = 16 (0x10), align = 8, largest padding = 0, niches = 1, no Drop
         "#]],
     )
 }
@@ -10559,7 +10665,7 @@ struct DropField$0 {
 
             ---
 
-            size = 4, align = 4, needs Drop
+            size = 4, align = 4, largest padding = 0, needs Drop
         "#]],
     );
     check(
diff --git a/src/tools/rust-analyzer/crates/ide/src/lib.rs b/src/tools/rust-analyzer/crates/ide/src/lib.rs
index d649dffbd90..82dbcde4c06 100644
--- a/src/tools/rust-analyzer/crates/ide/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/lib.rs
@@ -514,7 +514,6 @@ impl Analysis {
         self.with_db(|db| goto_type_definition::goto_type_definition(db, position))
     }
 
-    /// Finds all usages of the reference at point.
     pub fn find_all_refs(
         &self,
         position: FilePosition,
diff --git a/src/tools/rust-analyzer/crates/ide/src/references.rs b/src/tools/rust-analyzer/crates/ide/src/references.rs
index 4fa116444b7..c6a323d4081 100644
--- a/src/tools/rust-analyzer/crates/ide/src/references.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/references.rs
@@ -8,6 +8,14 @@
 //! for text occurrences of the identifier. If there's an `ast::NameRef`
 //! at the index that the match starts at and its tree parent is
 //! resolved to the search element definition, we get a reference.
+//!
+//! Special handling for constructors/initializations:
+//! When searching for references to a struct/enum/variant, if the cursor is positioned on:
+//! - `{` after a struct/enum/variant definition
+//! - `(` for tuple structs/variants
+//! - `;` for unit structs
+//! - The type name in a struct/enum/variant definition
+//!   Then only constructor/initialization usages will be shown, filtering out other references.
 
 use hir::{PathResolution, Semantics};
 use ide_db::{
@@ -28,27 +36,76 @@ use syntax::{
 
 use crate::{FilePosition, HighlightedRange, NavigationTarget, TryToNav, highlight_related};
 
+/// Result of a reference search operation.
 #[derive(Debug, Clone)]
 pub struct ReferenceSearchResult {
+    /// Information about the declaration site of the searched item.
+    /// For ADTs (structs/enums), this points to the type definition.
+    /// May be None for primitives or items without clear declaration sites.
     pub declaration: Option<Declaration>,
+    /// All references found, grouped by file.
+    /// For ADTs when searching from a constructor position (e.g. on '{', '(', ';'),
+    /// this only includes constructor/initialization usages.
+    /// The map key is the file ID, and the value is a vector of (range, category) pairs.
+    /// - range: The text range of the reference in the file
+    /// - category: Metadata about how the reference is used (read/write/etc)
     pub references: IntMap<FileId, Vec<(TextRange, ReferenceCategory)>>,
 }
 
+/// Information about the declaration site of a searched item.
 #[derive(Debug, Clone)]
 pub struct Declaration {
+    /// Navigation information to jump to the declaration
     pub nav: NavigationTarget,
+    /// Whether the declared item is mutable (relevant for variables)
     pub is_mut: bool,
 }
 
 // Feature: Find All References
 //
-// Shows all references of the item at the cursor location
+// Shows all references of the item at the cursor location. This includes:
+// - Direct references to variables, functions, types, etc.
+// - Constructor/initialization references when cursor is on struct/enum definition tokens
+// - References in patterns and type contexts
+// - References through dereferencing and borrowing
+// - References in macro expansions
+//
+// Special handling for constructors:
+// - When the cursor is on `{`, `(`, or `;` in a struct/enum definition
+// - When the cursor is on the type name in a struct/enum definition
+// These cases will show only constructor/initialization usages of the type
 //
 // | Editor  | Shortcut |
 // |---------|----------|
 // | VS Code | <kbd>Shift+Alt+F12</kbd> |
 //
 // ![Find All References](https://user-images.githubusercontent.com/48062697/113020670-b7c34f00-917a-11eb-8003-370ac5f2b3cb.gif)
+
+/// Find all references to the item at the given position.
+///
+/// # Arguments
+/// * `sema` - Semantic analysis context
+/// * `position` - Position in the file where to look for the item
+/// * `search_scope` - Optional scope to limit the search (e.g. current crate only)
+///
+/// # Returns
+/// Returns `None` if no valid item is found at the position.
+/// Otherwise returns a vector of `ReferenceSearchResult`, usually with one element.
+/// Multiple results can occur in case of ambiguity or when searching for trait items.
+///
+/// # Special cases
+/// - Control flow keywords (break, continue, etc): Shows all related jump points
+/// - Constructor search: When on struct/enum definition tokens (`{`, `(`, `;`), shows only initialization sites
+/// - Format string arguments: Shows template parameter usages
+/// - Lifetime parameters: Shows lifetime constraint usages
+///
+/// # Constructor search
+/// When the cursor is on specific tokens in a struct/enum definition:
+/// - `{` after struct/enum/variant: Shows record literal initializations
+/// - `(` after tuple struct/variant: Shows tuple literal initializations
+/// - `;` after unit struct: Shows unit literal initializations
+/// - Type name in definition: Shows all initialization usages
+///   In these cases, other kinds of references (like type references) are filtered out.
 pub(crate) fn find_all_refs(
     sema: &Semantics<'_, RootDatabase>,
     position: FilePosition,
@@ -143,7 +200,7 @@ pub(crate) fn find_defs(
         )
     })?;
 
-    if let Some((_, resolution)) = sema.check_for_format_args_template(token.clone(), offset) {
+    if let Some((.., resolution)) = sema.check_for_format_args_template(token.clone(), offset) {
         return resolution.map(Definition::from).map(|it| vec![it]);
     }
 
@@ -219,7 +276,19 @@ fn retain_adt_literal_usages(
     }
 }
 
-/// Returns `Some` if the cursor is at a position for an item to search for all its constructor/literal usages
+/// Returns `Some` if the cursor is at a position where we should search for constructor/initialization usages.
+/// This is used to implement the special constructor search behavior when the cursor is on specific tokens
+/// in a struct/enum/variant definition.
+///
+/// # Returns
+/// - `Some(name)` if the cursor is on:
+///   - `{` after a struct/enum/variant definition
+///   - `(` for tuple structs/variants
+///   - `;` for unit structs
+///   - The type name in a struct/enum/variant definition
+/// - `None` otherwise
+///
+/// The returned name is the name of the type whose constructor usages should be searched for.
 fn name_for_constructor_search(syntax: &SyntaxNode, position: FilePosition) -> Option<ast::Name> {
     let token = syntax.token_at_offset(position.offset).right_biased()?;
     let token_parent = token.parent()?;
@@ -257,6 +326,16 @@ fn name_for_constructor_search(syntax: &SyntaxNode, position: FilePosition) -> O
     }
 }
 
+/// Checks if a name reference is part of an enum variant literal expression.
+/// Used to filter references when searching for enum variant constructors.
+///
+/// # Arguments
+/// * `sema` - Semantic analysis context
+/// * `enum_` - The enum type to check against
+/// * `name_ref` - The name reference to check
+///
+/// # Returns
+/// `true` if the name reference is used as part of constructing a variant of the given enum.
 fn is_enum_lit_name_ref(
     sema: &Semantics<'_, RootDatabase>,
     enum_: hir::Enum,
@@ -284,12 +363,19 @@ fn is_enum_lit_name_ref(
         .unwrap_or(false)
 }
 
+/// Checks if a path ends with the given name reference.
+/// Helper function for checking constructor usage patterns.
 fn path_ends_with(path: Option<ast::Path>, name_ref: &ast::NameRef) -> bool {
     path.and_then(|path| path.segment())
         .and_then(|segment| segment.name_ref())
         .map_or(false, |segment| segment == *name_ref)
 }
 
+/// Checks if a name reference is used in a literal (constructor) context.
+/// Used to filter references when searching for struct/variant constructors.
+///
+/// # Returns
+/// `true` if the name reference is used as part of a struct/variant literal expression.
 fn is_lit_name_ref(name_ref: &ast::NameRef) -> bool {
     name_ref.syntax().ancestors().find_map(|ancestor| {
         match_ast! {
diff --git a/src/tools/rust-analyzer/crates/ide/src/rename.rs b/src/tools/rust-analyzer/crates/ide/src/rename.rs
index e6cda60cd95..0423e3da2c8 100644
--- a/src/tools/rust-analyzer/crates/ide/src/rename.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/rename.rs
@@ -203,7 +203,7 @@ fn find_definitions(
 ) -> RenameResult<impl Iterator<Item = (FileRange, SyntaxKind, Definition)>> {
     let token = syntax.token_at_offset(offset).find(|t| matches!(t.kind(), SyntaxKind::STRING));
 
-    if let Some((range, Some(resolution))) =
+    if let Some((range, _, _, Some(resolution))) =
         token.and_then(|token| sema.check_for_format_args_template(token, offset))
     {
         return Ok(vec![(
diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting.rs b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting.rs
index e1bc76318f8..3ca172977cb 100644
--- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting.rs
@@ -542,7 +542,7 @@ fn descend_token(
 
     let mut t = None;
     let mut r = 0;
-    sema.descend_into_macros_breakable(token.clone(), |tok, _ctx| {
+    sema.descend_into_macros_breakable(token.clone().into(), |tok, _ctx| {
         // FIXME: Consider checking ctx transparency for being opaque?
         let my_rank = ranker.rank_token(&tok.value);
 
diff --git a/src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs b/src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs
index abde48d1512..fc922dd849f 100644
--- a/src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs
+++ b/src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs
@@ -164,7 +164,6 @@ define_symbols! {
     completion,
     compile_error,
     concat_bytes,
-    concat_idents,
     concat,
     const_format_args,
     const_panic_fmt,
diff --git a/src/tools/rust-analyzer/crates/mbe/src/tests.rs b/src/tools/rust-analyzer/crates/mbe/src/tests.rs
index 3369dfff281..769455faac0 100644
--- a/src/tools/rust-analyzer/crates/mbe/src/tests.rs
+++ b/src/tools/rust-analyzer/crates/mbe/src/tests.rs
@@ -74,7 +74,8 @@ fn check_(
         "{}",
         syntax_bridge::prettify_macro_expansion::prettify_macro_expansion(
             node.syntax_node(),
-            &mut |it| it.clone()
+            &mut |_| None,
+            |_| ()
         )
     );
     expect.assert_eq(&expect_res);
diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/rust_analyzer_span.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/rust_analyzer_span.rs
index 64b40e7b943..e0c6e68f803 100644
--- a/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/rust_analyzer_span.rs
+++ b/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/rust_analyzer_span.rs
@@ -258,7 +258,9 @@ impl server::TokenStream for RaSpanServer {
         &mut self,
         stream: Self::TokenStream,
     ) -> Vec<bridge::TokenTree<Self::TokenStream, Self::Span, Self::Symbol>> {
-        stream.into_bridge()
+        stream.into_bridge(&mut |first, second| {
+            server::Span::join(self, first, second).unwrap_or(first)
+        })
     }
 }
 
diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/token_id.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/token_id.rs
index 24a67bf45c8..d55b269f868 100644
--- a/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/token_id.rs
+++ b/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/token_id.rs
@@ -238,7 +238,8 @@ impl server::TokenStream for TokenIdServer {
         &mut self,
         stream: Self::TokenStream,
     ) -> Vec<bridge::TokenTree<Self::TokenStream, Self::Span, Self::Symbol>> {
-        stream.into_bridge()
+        // Can't join with `TokenId`.
+        stream.into_bridge(&mut |first, _second| first)
     }
 }
 
diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/token_stream.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/token_stream.rs
index 072557913c2..c5019a59172 100644
--- a/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/token_stream.rs
+++ b/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/token_stream.rs
@@ -56,7 +56,10 @@ impl<S: Copy> TokenStream<S> {
         self.token_trees.is_empty()
     }
 
-    pub(crate) fn into_bridge(self) -> Vec<bridge::TokenTree<Self, S, intern::Symbol>> {
+    pub(crate) fn into_bridge(
+        self,
+        join_spans: &mut dyn FnMut(S, S) -> S,
+    ) -> Vec<bridge::TokenTree<Self, S, intern::Symbol>> {
         let mut result = Vec::new();
         let mut iter = self.token_trees.into_iter();
         while let Some(tree) = iter.next() {
@@ -98,7 +101,11 @@ impl<S: Copy> TokenStream<S> {
                                 token_trees: iter.by_ref().take(subtree.usize_len()).collect(),
                             })
                         },
-                        span: bridge::DelimSpan::from_single(subtree.delimiter.open),
+                        span: bridge::DelimSpan {
+                            open: subtree.delimiter.open,
+                            close: subtree.delimiter.close,
+                            entire: join_spans(subtree.delimiter.open, subtree.delimiter.close),
+                        },
                     }))
                 }
             }
diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/src/tests/mod.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/src/tests/mod.rs
index 3868fee40fb..3a6ce639d13 100644
--- a/src/tools/rust-analyzer/crates/proc-macro-srv/src/tests/mod.rs
+++ b/src/tools/rust-analyzer/crates/proc-macro-srv/src/tests/mod.rs
@@ -144,7 +144,7 @@ fn test_fn_like_macro_clone_ident_subtree() {
             SUBTREE $$ 42:2@0..100#ROOT2024 42:2@0..100#ROOT2024
               IDENT   ident 42:2@0..5#ROOT2024
               PUNCH   , [alone] 42:2@5..6#ROOT2024
-              SUBTREE [] 42:2@7..8#ROOT2024 42:2@7..8#ROOT2024"#]],
+              SUBTREE [] 42:2@7..9#ROOT2024 42:2@7..9#ROOT2024"#]],
     );
 }
 
diff --git a/src/tools/rust-analyzer/crates/query-group-macro/tests/logger_db.rs b/src/tools/rust-analyzer/crates/query-group-macro/tests/logger_db.rs
index bade0c2cd6f..71af63a0d3b 100644
--- a/src/tools/rust-analyzer/crates/query-group-macro/tests/logger_db.rs
+++ b/src/tools/rust-analyzer/crates/query-group-macro/tests/logger_db.rs
@@ -1,33 +1,41 @@
 use std::sync::{Arc, Mutex};
 
 #[salsa_macros::db]
-#[derive(Default, Clone)]
+#[derive(Clone)]
 pub(crate) struct LoggerDb {
     storage: salsa::Storage<Self>,
     logger: Logger,
 }
 
+impl Default for LoggerDb {
+    fn default() -> Self {
+        let logger = Logger::default();
+        Self {
+            storage: salsa::Storage::new(Some(Box::new({
+                let logger = logger.clone();
+                move |event| match event.kind {
+                    salsa::EventKind::WillExecute { .. }
+                    | salsa::EventKind::WillCheckCancellation
+                    | salsa::EventKind::DidValidateMemoizedValue { .. }
+                    | salsa::EventKind::WillDiscardStaleOutput { .. }
+                    | salsa::EventKind::DidDiscard { .. } => {
+                        logger.logs.lock().unwrap().push(format!("salsa_event({:?})", event.kind));
+                    }
+                    _ => {}
+                }
+            }))),
+            logger,
+        }
+    }
+}
+
 #[derive(Default, Clone)]
 struct Logger {
     logs: Arc<Mutex<Vec<String>>>,
 }
 
 #[salsa_macros::db]
-impl salsa::Database for LoggerDb {
-    fn salsa_event(&self, event: &dyn Fn() -> salsa::Event) {
-        let event = event();
-        match event.kind {
-            salsa::EventKind::WillExecute { .. }
-            | salsa::EventKind::WillCheckCancellation
-            | salsa::EventKind::DidValidateMemoizedValue { .. }
-            | salsa::EventKind::WillDiscardStaleOutput { .. }
-            | salsa::EventKind::DidDiscard { .. } => {
-                self.push_log(format!("salsa_event({:?})", event.kind));
-            }
-            _ => {}
-        }
-    }
-}
+impl salsa::Database for LoggerDb {}
 
 impl LoggerDb {
     /// Log an event from inside a tracked function.
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs
index 671e838421f..12b393b80c0 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs
@@ -1023,7 +1023,7 @@ impl flags::AnalysisStats {
             percentage(num_pats_partially_unknown, num_pats),
             num_pat_type_mismatches
         );
-        eprintln!("  panics: {}", panics);
+        eprintln!("  panics: {panics}");
         eprintln!("{:<20} {}", "Inference:", inference_time);
         report_metric("unknown type", num_exprs_unknown, "#");
         report_metric("type mismatches", num_expr_type_mismatches, "#");
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs
index 03e5b1f6f4b..d1ca8c1a91a 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs
@@ -149,6 +149,8 @@ config_data! {
         hover_memoryLayout_niches: Option<bool> = Some(false),
         /// How to render the offset information in a memory layout hover.
         hover_memoryLayout_offset: Option<MemoryLayoutHoverRenderKindDef> = Some(MemoryLayoutHoverRenderKindDef::Hexadecimal),
+        /// How to render the padding information in a memory layout hover.
+        hover_memoryLayout_padding: Option<MemoryLayoutHoverRenderKindDef> = None,
         /// How to render the size information in a memory layout hover.
         hover_memoryLayout_size: Option<MemoryLayoutHoverRenderKindDef> = Some(MemoryLayoutHoverRenderKindDef::Both),
 
@@ -544,7 +546,7 @@ config_data! {
          /// Whether to prefer import paths containing a `prelude` module.
         imports_preferPrelude: bool                       = false,
         /// The path structure for newly inserted paths to use.
-        imports_prefix: ImportPrefixDef               = ImportPrefixDef::Plain,
+        imports_prefix: ImportPrefixDef               = ImportPrefixDef::ByCrate,
         /// Whether to prefix external (including std, core) crate imports with `::`. e.g. "use ::std::io::Read;".
         imports_prefixExternPrelude: bool = false,
     }
@@ -1635,6 +1637,7 @@ impl Config {
                 size: self.hover_memoryLayout_size().map(mem_kind),
                 offset: self.hover_memoryLayout_offset().map(mem_kind),
                 alignment: self.hover_memoryLayout_alignment().map(mem_kind),
+                padding: self.hover_memoryLayout_padding().map(mem_kind),
                 niches: self.hover_memoryLayout_niches().unwrap_or_default(),
             }),
             documentation: self.hover_documentation_enable().to_owned(),
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/dispatch.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/dispatch.rs
index f04ada38893..40d05567fcc 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/dispatch.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/dispatch.rs
@@ -6,7 +6,7 @@ use std::{
 
 use ide_db::base_db::{
     DbPanicContext,
-    salsa::{self, Cancelled},
+    salsa::{self, Cancelled, UnexpectedCycle},
 };
 use lsp_server::{ExtractError, Response, ResponseError};
 use serde::{Serialize, de::DeserializeOwned};
@@ -349,11 +349,14 @@ where
             let mut message = "request handler panicked".to_owned();
             if let Some(panic_message) = panic_message {
                 message.push_str(": ");
-                message.push_str(panic_message)
+                message.push_str(panic_message);
+            } else if let Some(cycle) = panic.downcast_ref::<UnexpectedCycle>() {
+                tracing::error!("{cycle}");
+                message.push_str(": unexpected cycle");
             } else if let Ok(cancelled) = panic.downcast::<Cancelled>() {
                 tracing::error!("Cancellation propagated out of salsa! This is a bug");
                 return Err(HandlerCancelledError::Inner(*cancelled));
-            }
+            };
 
             Ok(lsp_server::Response::new_err(
                 id,
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/integrated_benchmarks.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/integrated_benchmarks.rs
index 49ebffa909a..84b7888258f 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/integrated_benchmarks.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/integrated_benchmarks.rs
@@ -147,7 +147,7 @@ fn integrated_completion_benchmark() {
         let _it = stdx::timeit("change");
         let mut text = host.analysis().file_text(file_id).unwrap().to_string();
         let completion_offset =
-            patch(&mut text, "db.struct_data(self.id)", "sel;\ndb.struct_data(self.id)")
+            patch(&mut text, "db.struct_signature(self.id)", "sel;\ndb.struct_signature(self.id)")
                 + "sel".len();
         let mut change = ChangeWithProcMacros::default();
         change.change_file(file_id, Some(text));
@@ -197,9 +197,11 @@ fn integrated_completion_benchmark() {
     let completion_offset = {
         let _it = stdx::timeit("change");
         let mut text = host.analysis().file_text(file_id).unwrap().to_string();
-        let completion_offset =
-            patch(&mut text, "sel;\ndb.struct_data(self.id)", ";sel;\ndb.struct_data(self.id)")
-                + ";sel".len();
+        let completion_offset = patch(
+            &mut text,
+            "sel;\ndb.struct_signature(self.id)",
+            ";sel;\ndb.struct_signature(self.id)",
+        ) + ";sel".len();
         let mut change = ChangeWithProcMacros::default();
         change.change_file(file_id, Some(text));
         host.apply_change(change);
@@ -247,9 +249,11 @@ fn integrated_completion_benchmark() {
     let completion_offset = {
         let _it = stdx::timeit("change");
         let mut text = host.analysis().file_text(file_id).unwrap().to_string();
-        let completion_offset =
-            patch(&mut text, "sel;\ndb.struct_data(self.id)", "self.;\ndb.struct_data(self.id)")
-                + "self.".len();
+        let completion_offset = patch(
+            &mut text,
+            "sel;\ndb.struct_signature(self.id)",
+            "self.;\ndb.struct_signature(self.id)",
+        ) + "self.".len();
         let mut change = ChangeWithProcMacros::default();
         change.change_file(file_id, Some(text));
         host.apply_change(change);
@@ -366,7 +370,7 @@ fn integrated_diagnostics_benchmark() {
     {
         let _it = stdx::timeit("change");
         let mut text = host.analysis().file_text(file_id).unwrap().to_string();
-        patch(&mut text, "db.struct_data(self.id)", "();\ndb.struct_data(self.id)");
+        patch(&mut text, "db.struct_signature(self.id)", "();\ndb.struct_signature(self.id)");
         let mut change = ChangeWithProcMacros::default();
         change.change_file(file_id, Some(text));
         host.apply_change(change);
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/from_proto.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/from_proto.rs
index fb8a9838290..02757616d4f 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/from_proto.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/from_proto.rs
@@ -103,6 +103,7 @@ pub(crate) fn file_range_uri(
 
 pub(crate) fn assist_kind(kind: lsp_types::CodeActionKind) -> Option<AssistKind> {
     let assist_kind = match &kind {
+        k if k == &lsp_types::CodeActionKind::EMPTY => AssistKind::Generate,
         k if k == &lsp_types::CodeActionKind::QUICKFIX => AssistKind::QuickFix,
         k if k == &lsp_types::CodeActionKind::REFACTOR => AssistKind::Refactor,
         k if k == &lsp_types::CodeActionKind::REFACTOR_EXTRACT => AssistKind::RefactorExtract,
diff --git a/src/tools/rust-analyzer/crates/span/src/lib.rs b/src/tools/rust-analyzer/crates/span/src/lib.rs
index 54f90908f36..f81648ac42c 100644
--- a/src/tools/rust-analyzer/crates/span/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/span/src/lib.rs
@@ -112,7 +112,10 @@ pub struct EditionedFileId(u32);
 
 impl fmt::Debug for EditionedFileId {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        f.debug_tuple("EditionedFileId").field(&self.file_id()).field(&self.edition()).finish()
+        f.debug_tuple("EditionedFileId")
+            .field(&self.file_id().index())
+            .field(&self.edition())
+            .finish()
     }
 }
 
diff --git a/src/tools/rust-analyzer/crates/syntax-bridge/src/prettify_macro_expansion.rs b/src/tools/rust-analyzer/crates/syntax-bridge/src/prettify_macro_expansion.rs
index e815e07d80a..0a5c8df0d0a 100644
--- a/src/tools/rust-analyzer/crates/syntax-bridge/src/prettify_macro_expansion.rs
+++ b/src/tools/rust-analyzer/crates/syntax-bridge/src/prettify_macro_expansion.rs
@@ -7,6 +7,13 @@ use syntax::{
     ted::{self, Position},
 };
 
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+pub enum PrettifyWsKind {
+    Space,
+    Indent(usize),
+    Newline,
+}
+
 /// Renders a [`SyntaxNode`] with whitespace inserted between tokens that require them.
 ///
 /// This is an internal API that is only exported because `mbe` needs it for tests and cannot depend
@@ -15,7 +22,8 @@ use syntax::{
 #[deprecated = "use `hir_expand::prettify_macro_expansion()` instead"]
 pub fn prettify_macro_expansion(
     syn: SyntaxNode,
-    dollar_crate_replacement: &mut dyn FnMut(&SyntaxToken) -> SyntaxToken,
+    dollar_crate_replacement: &mut dyn FnMut(&SyntaxToken) -> Option<SyntaxToken>,
+    inspect_mods: impl FnOnce(&[(Position, PrettifyWsKind)]),
 ) -> SyntaxNode {
     let mut indent = 0;
     let mut last: Option<SyntaxKind> = None;
@@ -27,14 +35,12 @@ pub fn prettify_macro_expansion(
     let after = Position::after;
 
     let do_indent = |pos: fn(_) -> Position, token: &SyntaxToken, indent| {
-        (pos(token.clone()), make::tokens::whitespace(&" ".repeat(4 * indent)))
-    };
-    let do_ws = |pos: fn(_) -> Position, token: &SyntaxToken| {
-        (pos(token.clone()), make::tokens::single_space())
-    };
-    let do_nl = |pos: fn(_) -> Position, token: &SyntaxToken| {
-        (pos(token.clone()), make::tokens::single_newline())
+        (pos(token.clone()), PrettifyWsKind::Indent(indent))
     };
+    let do_ws =
+        |pos: fn(_) -> Position, token: &SyntaxToken| (pos(token.clone()), PrettifyWsKind::Space);
+    let do_nl =
+        |pos: fn(_) -> Position, token: &SyntaxToken| (pos(token.clone()), PrettifyWsKind::Newline);
 
     for event in syn.preorder_with_tokens() {
         let token = match event {
@@ -46,20 +52,19 @@ pub fn prettify_macro_expansion(
                 ) =>
             {
                 if indent > 0 {
-                    mods.push((
-                        Position::after(node.clone()),
-                        make::tokens::whitespace(&" ".repeat(4 * indent)),
-                    ));
+                    mods.push((Position::after(node.clone()), PrettifyWsKind::Indent(indent)));
                 }
                 if node.parent().is_some() {
-                    mods.push((Position::after(node), make::tokens::single_newline()));
+                    mods.push((Position::after(node), PrettifyWsKind::Newline));
                 }
                 continue;
             }
             _ => continue,
         };
         if token.kind() == SyntaxKind::IDENT && token.text() == "$crate" {
-            dollar_crate_replacements.push((token.clone(), dollar_crate_replacement(&token)));
+            if let Some(replacement) = dollar_crate_replacement(&token) {
+                dollar_crate_replacements.push((token.clone(), replacement));
+            }
         }
         let tok = &token;
 
@@ -129,8 +134,16 @@ pub fn prettify_macro_expansion(
         last = Some(tok.kind());
     }
 
+    inspect_mods(&mods);
     for (pos, insert) in mods {
-        ted::insert(pos, insert);
+        ted::insert_raw(
+            pos,
+            match insert {
+                PrettifyWsKind::Space => make::tokens::single_space(),
+                PrettifyWsKind::Indent(indent) => make::tokens::whitespace(&" ".repeat(4 * indent)),
+                PrettifyWsKind::Newline => make::tokens::single_newline(),
+            },
+        );
     }
     for (old, new) in dollar_crate_replacements {
         ted::replace(old, new);
diff --git a/src/tools/rust-analyzer/crates/syntax/src/ast/syntax_factory/constructors.rs b/src/tools/rust-analyzer/crates/syntax/src/ast/syntax_factory/constructors.rs
index 8dee3964d44..429e51ba362 100644
--- a/src/tools/rust-analyzer/crates/syntax/src/ast/syntax_factory/constructors.rs
+++ b/src/tools/rust-analyzer/crates/syntax/src/ast/syntax_factory/constructors.rs
@@ -585,6 +585,18 @@ impl SyntaxFactory {
         ast
     }
 
+    pub fn expr_underscore(&self) -> ast::UnderscoreExpr {
+        let ast::Expr::UnderscoreExpr(ast) = make::ext::expr_underscore().clone_for_update() else {
+            unreachable!()
+        };
+
+        if let Some(mut mapping) = self.mappings() {
+            SyntaxMappingBuilder::new(ast.syntax().clone()).finish(&mut mapping);
+        }
+
+        ast
+    }
+
     pub fn expr_if(
         &self,
         condition: ast::Expr,
diff --git a/src/tools/rust-analyzer/crates/syntax/src/ted.rs b/src/tools/rust-analyzer/crates/syntax/src/ted.rs
index 64d5ea084c1..6fcbdd006c2 100644
--- a/src/tools/rust-analyzer/crates/syntax/src/ted.rs
+++ b/src/tools/rust-analyzer/crates/syntax/src/ted.rs
@@ -5,6 +5,7 @@
 use std::{mem, ops::RangeInclusive};
 
 use parser::T;
+use rowan::TextSize;
 
 use crate::{
     SyntaxElement, SyntaxKind, SyntaxNode, SyntaxToken,
@@ -74,6 +75,12 @@ impl Position {
         };
         Position { repr }
     }
+    pub fn offset(&self) -> TextSize {
+        match &self.repr {
+            PositionRepr::FirstChild(node) => node.text_range().start(),
+            PositionRepr::After(elem) => elem.text_range().end(),
+        }
+    }
 }
 
 pub fn insert(position: Position, elem: impl Element) {
@@ -207,5 +214,12 @@ fn ws_between(left: &SyntaxElement, right: &SyntaxElement) -> Option<SyntaxToken
         }
         return Some(make::tokens::whitespace(&format!("\n{indent}")));
     }
+    if left.kind() == SyntaxKind::ATTR {
+        let mut indent = IndentLevel::from_element(right);
+        if right.kind() == SyntaxKind::ATTR {
+            indent.0 = IndentLevel::from_element(left).0.max(indent.0);
+        }
+        return Some(make::tokens::whitespace(&format!("\n{indent}")));
+    }
     Some(make::tokens::single_space())
 }
diff --git a/src/tools/rust-analyzer/crates/vfs/src/vfs_path.rs b/src/tools/rust-analyzer/crates/vfs/src/vfs_path.rs
index c35b7f229f6..7e2c787afc7 100644
--- a/src/tools/rust-analyzer/crates/vfs/src/vfs_path.rs
+++ b/src/tools/rust-analyzer/crates/vfs/src/vfs_path.rs
@@ -39,6 +39,13 @@ impl VfsPath {
         }
     }
 
+    pub fn into_abs_path(self) -> Option<AbsPathBuf> {
+        match self.0 {
+            VfsPathRepr::PathBuf(it) => Some(it),
+            VfsPathRepr::VirtualPath(_) => None,
+        }
+    }
+
     /// Creates a new `VfsPath` with `path` adjoined to `self`.
     pub fn join(&self, path: &str) -> Option<VfsPath> {
         match &self.0 {
diff --git a/src/tools/rust-analyzer/docs/book/src/configuration_generated.md b/src/tools/rust-analyzer/docs/book/src/configuration_generated.md
index 2ae73df61d0..0e07dadfb7c 100644
--- a/src/tools/rust-analyzer/docs/book/src/configuration_generated.md
+++ b/src/tools/rust-analyzer/docs/book/src/configuration_generated.md
@@ -763,6 +763,13 @@ Default: `"hexadecimal"`
 How to render the offset information in a memory layout hover.
 
 
+## rust-analyzer.hover.memoryLayout.padding {#hover.memoryLayout.padding}
+
+Default: `null`
+
+How to render the padding information in a memory layout hover.
+
+
 ## rust-analyzer.hover.memoryLayout.size {#hover.memoryLayout.size}
 
 Default: `"both"`
@@ -835,7 +842,7 @@ Whether to prefer import paths containing a `prelude` module.
 
 ## rust-analyzer.imports.prefix {#imports.prefix}
 
-Default: `"plain"`
+Default: `"crate"`
 
 The path structure for newly inserted paths to use.
 
diff --git a/src/tools/rust-analyzer/docs/book/src/other_editors.md b/src/tools/rust-analyzer/docs/book/src/other_editors.md
index 1eac7dd2c25..896df52af5f 100644
--- a/src/tools/rust-analyzer/docs/book/src/other_editors.md
+++ b/src/tools/rust-analyzer/docs/book/src/other_editors.md
@@ -364,30 +364,6 @@ binary](./rust_analyzer_binary.html).
 There are multiple rust-analyzer extensions for Visual Studio 2022 on
 Windows:
 
-### rust-analyzer.vs
-
-(License: Creative Commons Attribution-NonCommercial-ShareAlike 4.0
-International)
-
-[Visual Studio
-Marketplace](https://marketplace.visualstudio.com/items?itemName=kitamstudios.RustAnalyzer)
-
-[GitHub](https://github.com/kitamstudios/rust-analyzer/)
-
-Support for Rust development in the Visual Studio IDE is enabled by the
-[rust-analyzer](https://marketplace.visualstudio.com/items?itemName=kitamstudios.RustAnalyzer)
-package. Either click on the download link or install from IDE’s
-extension manager. For now [Visual Studio
-2022](https://visualstudio.microsoft.com/downloads/) is required. All
-editions are supported viz. Community, Professional & Enterprise. The
-package aims to provide 0-friction installation and therefore comes
-loaded with most things required including rust-analyzer binary. If
-anything it needs is missing, appropriate errors / warnings will guide
-the user. E.g. cargo.exe needs to be in path and the package will tell
-you as much. This package is under rapid active development. So if you
-encounter any issues please file it at
-[rust-analyzer.vs](https://github.com/kitamstudios/rust-analyzer/).
-
 ### VS RustAnalyzer
 
 (License: GPL)
diff --git a/src/tools/rust-analyzer/editors/code/package.json b/src/tools/rust-analyzer/editors/code/package.json
index a282eea9997..c8c36cd85c8 100644
--- a/src/tools/rust-analyzer/editors/code/package.json
+++ b/src/tools/rust-analyzer/editors/code/package.json
@@ -1782,6 +1782,33 @@
             {
                 "title": "hover",
                 "properties": {
+                    "rust-analyzer.hover.memoryLayout.padding": {
+                        "markdownDescription": "How to render the padding information in a memory layout hover.",
+                        "default": null,
+                        "anyOf": [
+                            {
+                                "type": "null"
+                            },
+                            {
+                                "type": "string",
+                                "enum": [
+                                    "both",
+                                    "decimal",
+                                    "hexadecimal"
+                                ],
+                                "enumDescriptions": [
+                                    "Render as 12 (0xC)",
+                                    "Render as 12",
+                                    "Render as 0xC"
+                                ]
+                            }
+                        ]
+                    }
+                }
+            },
+            {
+                "title": "hover",
+                "properties": {
                     "rust-analyzer.hover.memoryLayout.size": {
                         "markdownDescription": "How to render the size information in a memory layout hover.",
                         "default": "both",
@@ -1927,7 +1954,7 @@
                 "properties": {
                     "rust-analyzer.imports.prefix": {
                         "markdownDescription": "The path structure for newly inserted paths to use.",
-                        "default": "plain",
+                        "default": "crate",
                         "type": "string",
                         "enum": [
                             "plain",
diff --git a/src/tools/rust-analyzer/xtask/src/codegen.rs b/src/tools/rust-analyzer/xtask/src/codegen.rs
index bba7ad73f38..19ca62e8a32 100644
--- a/src/tools/rust-analyzer/xtask/src/codegen.rs
+++ b/src/tools/rust-analyzer/xtask/src/codegen.rs
@@ -24,8 +24,8 @@ impl flags::Codegen {
                 grammar::generate(self.check);
                 assists_doc_tests::generate(self.check);
                 parser_inline_tests::generate(self.check);
-                feature_docs::generate(self.check)
-                // diagnostics_docs::generate(self.check) doesn't generate any tests
+                feature_docs::generate(self.check);
+                diagnostics_docs::generate(self.check);
                 // lints::generate(self.check) Updating clones the rust repo, so don't run it unless
                 // explicitly asked for
             }
diff --git a/src/tools/rustbook/Cargo.lock b/src/tools/rustbook/Cargo.lock
index 5c862e95400..8893846b5fa 100644
--- a/src/tools/rustbook/Cargo.lock
+++ b/src/tools/rustbook/Cargo.lock
@@ -885,9 +885,9 @@ dependencies = [
 
 [[package]]
 name = "mdbook"
-version = "0.4.50"
+version = "0.4.51"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f72bc08f096e1fb15cfc382babe218317c2897d2040f967c4db40d156ca28e21"
+checksum = "a87e65420ab45ca9c1b8cdf698f95b710cc826d373fa550f0f7fad82beac9328"
 dependencies = [
  "ammonia",
  "anyhow",
@@ -1026,11 +1026,11 @@ checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
 
 [[package]]
 name = "onig"
-version = "6.4.0"
+version = "6.5.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8c4b31c8722ad9171c6d77d3557db078cab2bd50afcc9d09c8b315c59df8ca4f"
+checksum = "336b9c63443aceef14bea841b899035ae3abe89b7c486aaf4c5bd8aafedac3f0"
 dependencies = [
- "bitflags 1.3.2",
+ "bitflags 2.9.0",
  "libc",
  "once_cell",
  "onig_sys",
@@ -1038,9 +1038,9 @@ dependencies = [
 
 [[package]]
 name = "onig_sys"
-version = "69.8.1"
+version = "69.9.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7b829e3d7e9cc74c7e315ee8edb185bf4190da5acde74afd7fc59c35b1f086e7"
+checksum = "c7f86c6eef3d6df15f23bcfb6af487cbd2fed4e5581d58d5bf1f5f8b7f6727dc"
 dependencies = [
  "cc",
  "pkg-config",
diff --git a/src/tools/rustbook/Cargo.toml b/src/tools/rustbook/Cargo.toml
index ee2ada5aa2b..69c0cfaf5c9 100644
--- a/src/tools/rustbook/Cargo.toml
+++ b/src/tools/rustbook/Cargo.toml
@@ -15,6 +15,6 @@ mdbook-i18n-helpers = "0.3.3"
 mdbook-spec = { path = "../../doc/reference/mdbook-spec" }
 
 [dependencies.mdbook]
-version = "0.4.50"
+version = "0.4.51"
 default-features = false
 features = ["search"]
diff --git a/src/tools/rustc-perf b/src/tools/rustc-perf
-Subproject c0f3b53c8e5de87714d18a5f42998859302ae03
+Subproject 6a70166b92a1b1560cb3cf056427b011b2a1f2b
diff --git a/src/tools/rustfmt/src/items.rs b/src/tools/rustfmt/src/items.rs
index e79b7803c60..1a3897b51cb 100644
--- a/src/tools/rustfmt/src/items.rs
+++ b/src/tools/rustfmt/src/items.rs
@@ -1110,10 +1110,10 @@ impl<'a> StructParts<'a> {
 
     pub(crate) fn from_item(item: &'a ast::Item) -> Self {
         let (prefix, def, ident, generics) = match item.kind {
-            ast::ItemKind::Struct(ident, ref def, ref generics) => {
+            ast::ItemKind::Struct(ident, ref generics, ref def) => {
                 ("struct ", def, ident, generics)
             }
-            ast::ItemKind::Union(ident, ref def, ref generics) => ("union ", def, ident, generics),
+            ast::ItemKind::Union(ident, ref generics, ref def) => ("union ", def, ident, generics),
             _ => unreachable!(),
         };
         StructParts {
diff --git a/src/tools/rustfmt/src/lib.rs b/src/tools/rustfmt/src/lib.rs
index 08cda6913b9..942b42ec5f2 100644
--- a/src/tools/rustfmt/src/lib.rs
+++ b/src/tools/rustfmt/src/lib.rs
@@ -8,7 +8,6 @@
 // N.B. these crates are loaded from the sysroot, so they need extern crate.
 extern crate rustc_ast;
 extern crate rustc_ast_pretty;
-extern crate rustc_builtin_macros;
 extern crate rustc_data_structures;
 extern crate rustc_errors;
 extern crate rustc_expand;
diff --git a/src/tools/rustfmt/src/parse/macros/asm.rs b/src/tools/rustfmt/src/parse/macros/asm.rs
index 1a9614bacec..bfa9c6300c4 100644
--- a/src/tools/rustfmt/src/parse/macros/asm.rs
+++ b/src/tools/rustfmt/src/parse/macros/asm.rs
@@ -1,5 +1,5 @@
 use rustc_ast::ast;
-use rustc_builtin_macros::asm::{AsmArg, parse_asm_args};
+use rustc_parse::parser::asm::{AsmArg, parse_asm_args};
 
 use crate::rewrite::RewriteContext;
 
diff --git a/src/tools/rustfmt/src/visitor.rs b/src/tools/rustfmt/src/visitor.rs
index 16d1f5105d5..f6a9a3f2cd1 100644
--- a/src/tools/rustfmt/src/visitor.rs
+++ b/src/tools/rustfmt/src/visitor.rs
@@ -521,7 +521,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
                 ast::ItemKind::Struct(..) | ast::ItemKind::Union(..) => {
                     self.visit_struct(&StructParts::from_item(item));
                 }
-                ast::ItemKind::Enum(ident, ref def, ref generics) => {
+                ast::ItemKind::Enum(ident, ref generics, ref def) => {
                     self.format_missing_with_indent(source!(self, item.span).lo());
                     self.visit_enum(ident, &item.vis, def, generics, item.span);
                     self.last_pos = source!(self, item.span).hi();
diff --git a/src/etc/test-float-parse/Cargo.lock b/src/tools/test-float-parse/Cargo.lock
index 3f60423fed3..3f60423fed3 100644
--- a/src/etc/test-float-parse/Cargo.lock
+++ b/src/tools/test-float-parse/Cargo.lock
diff --git a/src/etc/test-float-parse/Cargo.toml b/src/tools/test-float-parse/Cargo.toml
index e407e322f9e..e407e322f9e 100644
--- a/src/etc/test-float-parse/Cargo.toml
+++ b/src/tools/test-float-parse/Cargo.toml
diff --git a/src/etc/test-float-parse/README.md b/src/tools/test-float-parse/README.md
index 5e2c43d1cad..5e2c43d1cad 100644
--- a/src/etc/test-float-parse/README.md
+++ b/src/tools/test-float-parse/README.md
diff --git a/src/etc/test-float-parse/src/gen_/exhaustive.rs b/src/tools/test-float-parse/src/gen_/exhaustive.rs
index 01458fb0b60..01458fb0b60 100644
--- a/src/etc/test-float-parse/src/gen_/exhaustive.rs
+++ b/src/tools/test-float-parse/src/gen_/exhaustive.rs
diff --git a/src/etc/test-float-parse/src/gen_/exponents.rs b/src/tools/test-float-parse/src/gen_/exponents.rs
index 3748e9d380c..3748e9d380c 100644
--- a/src/etc/test-float-parse/src/gen_/exponents.rs
+++ b/src/tools/test-float-parse/src/gen_/exponents.rs
diff --git a/src/etc/test-float-parse/src/gen_/fuzz.rs b/src/tools/test-float-parse/src/gen_/fuzz.rs
index 1d6c5562a14..1d6c5562a14 100644
--- a/src/etc/test-float-parse/src/gen_/fuzz.rs
+++ b/src/tools/test-float-parse/src/gen_/fuzz.rs
diff --git a/src/etc/test-float-parse/src/gen_/integers.rs b/src/tools/test-float-parse/src/gen_/integers.rs
index 070d188e88c..070d188e88c 100644
--- a/src/etc/test-float-parse/src/gen_/integers.rs
+++ b/src/tools/test-float-parse/src/gen_/integers.rs
diff --git a/src/etc/test-float-parse/src/gen_/long_fractions.rs b/src/tools/test-float-parse/src/gen_/long_fractions.rs
index b75148b779c..b75148b779c 100644
--- a/src/etc/test-float-parse/src/gen_/long_fractions.rs
+++ b/src/tools/test-float-parse/src/gen_/long_fractions.rs
diff --git a/src/etc/test-float-parse/src/gen_/many_digits.rs b/src/tools/test-float-parse/src/gen_/many_digits.rs
index 741e11437fe..741e11437fe 100644
--- a/src/etc/test-float-parse/src/gen_/many_digits.rs
+++ b/src/tools/test-float-parse/src/gen_/many_digits.rs
diff --git a/src/etc/test-float-parse/src/gen_/sparse.rs b/src/tools/test-float-parse/src/gen_/sparse.rs
index 72b65d4ce7f..72b65d4ce7f 100644
--- a/src/etc/test-float-parse/src/gen_/sparse.rs
+++ b/src/tools/test-float-parse/src/gen_/sparse.rs
diff --git a/src/etc/test-float-parse/src/gen_/spot_checks.rs b/src/tools/test-float-parse/src/gen_/spot_checks.rs
index 18691f9d6cf..18691f9d6cf 100644
--- a/src/etc/test-float-parse/src/gen_/spot_checks.rs
+++ b/src/tools/test-float-parse/src/gen_/spot_checks.rs
diff --git a/src/etc/test-float-parse/src/gen_/subnorm.rs b/src/tools/test-float-parse/src/gen_/subnorm.rs
index 654f324b9b0..654f324b9b0 100644
--- a/src/etc/test-float-parse/src/gen_/subnorm.rs
+++ b/src/tools/test-float-parse/src/gen_/subnorm.rs
diff --git a/src/etc/test-float-parse/src/lib.rs b/src/tools/test-float-parse/src/lib.rs
index 0bd4878f9a6..f590149523b 100644
--- a/src/etc/test-float-parse/src/lib.rs
+++ b/src/tools/test-float-parse/src/lib.rs
@@ -119,6 +119,7 @@ pub fn register_tests(cfg: &Config) -> Vec<TestInfo> {
 
     // Register normal generators for all floats.
 
+    #[cfg(not(bootstrap))]
     #[cfg(target_has_reliable_f16)]
     register_float::<f16>(&mut tests, cfg);
     register_float::<f32>(&mut tests, cfg);
diff --git a/src/etc/test-float-parse/src/main.rs b/src/tools/test-float-parse/src/main.rs
index 9c6cad7324f..9c6cad7324f 100644
--- a/src/etc/test-float-parse/src/main.rs
+++ b/src/tools/test-float-parse/src/main.rs
diff --git a/src/etc/test-float-parse/src/traits.rs b/src/tools/test-float-parse/src/traits.rs
index 65a8721bfa5..16484f8fe2c 100644
--- a/src/etc/test-float-parse/src/traits.rs
+++ b/src/tools/test-float-parse/src/traits.rs
@@ -170,6 +170,7 @@ macro_rules! impl_float {
 
 impl_float!(f32, u32; f64, u64);
 
+#[cfg(not(bootstrap))]
 #[cfg(target_has_reliable_f16)]
 impl_float!(f16, u16);
 
diff --git a/src/etc/test-float-parse/src/ui.rs b/src/tools/test-float-parse/src/ui.rs
index 73473eef0bf..73473eef0bf 100644
--- a/src/etc/test-float-parse/src/ui.rs
+++ b/src/tools/test-float-parse/src/ui.rs
diff --git a/src/etc/test-float-parse/src/validate.rs b/src/tools/test-float-parse/src/validate.rs
index 40dda274e3b..40dda274e3b 100644
--- a/src/etc/test-float-parse/src/validate.rs
+++ b/src/tools/test-float-parse/src/validate.rs
diff --git a/src/etc/test-float-parse/src/validate/tests.rs b/src/tools/test-float-parse/src/validate/tests.rs
index ab0e7d8a7ba..ab0e7d8a7ba 100644
--- a/src/etc/test-float-parse/src/validate/tests.rs
+++ b/src/tools/test-float-parse/src/validate/tests.rs
diff --git a/src/tools/tidy/Cargo.toml b/src/tools/tidy/Cargo.toml
index dfdbc0878f2..4835c220210 100644
--- a/src/tools/tidy/Cargo.toml
+++ b/src/tools/tidy/Cargo.toml
@@ -15,7 +15,7 @@ semver = "1.0"
 serde = { version = "1.0.125", features = ["derive"], optional = true }
 termcolor = "1.1.3"
 rustc-hash = "2.0.0"
-fluent-syntax = "0.11.1"
+fluent-syntax = "0.12"
 similar = "2.5.0"
 toml = "0.7.8"
 
diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs
index 9f333cc43cf..fdca7a7a40e 100644
--- a/src/tools/tidy/src/deps.rs
+++ b/src/tools/tidy/src/deps.rs
@@ -74,13 +74,13 @@ pub(crate) const WORKSPACES: &[(&str, ExceptionList, Option<(&[&str], &[&str])>,
     ("compiler/rustc_codegen_gcc", EXCEPTIONS_GCC, None, &[]),
     ("src/bootstrap", EXCEPTIONS_BOOTSTRAP, None, &[]),
     ("src/ci/docker/host-x86_64/test-various/uefi_qemu_test", EXCEPTIONS_UEFI_QEMU_TEST, None, &[]),
-    ("src/etc/test-float-parse", EXCEPTIONS, None, &[]),
     ("src/tools/cargo", EXCEPTIONS_CARGO, None, &["src/tools/cargo"]),
     //("src/tools/miri/test-cargo-miri", &[], None), // FIXME uncomment once all deps are vendored
     //("src/tools/miri/test_dependencies", &[], None), // FIXME uncomment once all deps are vendored
     ("src/tools/rust-analyzer", EXCEPTIONS_RUST_ANALYZER, None, &[]),
     ("src/tools/rustbook", EXCEPTIONS_RUSTBOOK, None, &["src/doc/book", "src/doc/reference"]),
     ("src/tools/rustc-perf", EXCEPTIONS_RUSTC_PERF, None, &["src/tools/rustc-perf"]),
+    ("src/tools/test-float-parse", EXCEPTIONS, None, &[]),
     // tidy-alphabetical-end
 ];
 
diff --git a/src/tools/tidy/src/issues.txt b/src/tools/tidy/src/issues.txt
index 1d0ddd56eec..3e9d79224fd 100644
--- a/src/tools/tidy/src/issues.txt
+++ b/src/tools/tidy/src/issues.txt
@@ -939,7 +939,6 @@ ui/enum-discriminant/auxiliary/issue-41394.rs
 ui/enum-discriminant/issue-104519.rs
 ui/enum-discriminant/issue-41394-rpass.rs
 ui/enum-discriminant/issue-41394.rs
-ui/enum-discriminant/issue-43398.rs
 ui/enum-discriminant/issue-46519.rs
 ui/enum-discriminant/issue-50689.rs
 ui/enum-discriminant/issue-51582.rs
diff --git a/src/tools/tidy/src/lib.rs b/src/tools/tidy/src/lib.rs
index ca45f8bb84b..e8a12d56335 100644
--- a/src/tools/tidy/src/lib.rs
+++ b/src/tools/tidy/src/lib.rs
@@ -82,6 +82,7 @@ pub mod mir_opt_tests;
 pub mod pal;
 pub mod rustdoc_css_themes;
 pub mod rustdoc_gui_tests;
+pub mod rustdoc_js;
 pub mod rustdoc_templates;
 pub mod style;
 pub mod target_policy;
diff --git a/src/tools/tidy/src/main.rs b/src/tools/tidy/src/main.rs
index 48122129b01..776f1bde2eb 100644
--- a/src/tools/tidy/src/main.rs
+++ b/src/tools/tidy/src/main.rs
@@ -35,6 +35,7 @@ fn main() {
     let library_path = root_path.join("library");
     let compiler_path = root_path.join("compiler");
     let librustdoc_path = src_path.join("librustdoc");
+    let tools_path = src_path.join("tools");
     let crashes_path = tests_path.join("crashes");
 
     let args: Vec<String> = env::args().skip(1).collect();
@@ -108,6 +109,7 @@ fn main() {
         check!(rustdoc_gui_tests, &tests_path);
         check!(rustdoc_css_themes, &librustdoc_path);
         check!(rustdoc_templates, &librustdoc_path);
+        check!(rustdoc_js, &librustdoc_path, &tools_path, &src_path);
         check!(known_bug, &crashes_path);
         check!(unknown_revision, &tests_path);
 
diff --git a/src/tools/tidy/src/rustdoc_js.rs b/src/tools/tidy/src/rustdoc_js.rs
new file mode 100644
index 00000000000..2517e2de12c
--- /dev/null
+++ b/src/tools/tidy/src/rustdoc_js.rs
@@ -0,0 +1,99 @@
+//! Tidy check to ensure that rustdoc templates didn't forget a `{# #}` to strip extra whitespace
+//! characters.
+
+use std::ffi::OsStr;
+use std::path::{Path, PathBuf};
+use std::process::Command;
+
+use ignore::DirEntry;
+
+use crate::walk::walk_no_read;
+
+fn run_eslint(args: &[PathBuf], config_folder: PathBuf, bad: &mut bool) {
+    let mut child = match Command::new("npx")
+        .arg("eslint")
+        .arg("-c")
+        .arg(config_folder.join(".eslintrc.js"))
+        .args(args)
+        .spawn()
+    {
+        Ok(child) => child,
+        Err(error) => {
+            *bad = true;
+            eprintln!("failed to run eslint: {error:?}");
+            return;
+        }
+    };
+    match child.wait() {
+        Ok(exit_status) => {
+            if exit_status.success() {
+                return;
+            }
+            eprintln!("eslint command failed");
+        }
+        Err(error) => eprintln!("eslint command failed: {error:?}"),
+    }
+    *bad = true;
+}
+
+fn get_eslint_version_inner(global: bool) -> Option<String> {
+    let mut command = Command::new("npm");
+    command.arg("list").arg("--parseable").arg("--long").arg("--depth=0");
+    if global {
+        command.arg("--global");
+    }
+    let output = command.output().ok()?;
+    let lines = String::from_utf8_lossy(&output.stdout);
+    lines.lines().find_map(|l| l.split(':').nth(1)?.strip_prefix("eslint@")).map(|v| v.to_owned())
+}
+
+fn get_eslint_version() -> Option<String> {
+    get_eslint_version_inner(false).or_else(|| get_eslint_version_inner(true))
+}
+
+pub fn check(librustdoc_path: &Path, tools_path: &Path, src_path: &Path, bad: &mut bool) {
+    let eslint_version_path =
+        src_path.join("ci/docker/host-x86_64/mingw-check-tidy/eslint.version");
+    let eslint_version = match std::fs::read_to_string(&eslint_version_path) {
+        Ok(version) => version.trim().to_string(),
+        Err(error) => {
+            *bad = true;
+            eprintln!("failed to read `{}`: {error:?}", eslint_version_path.display());
+            return;
+        }
+    };
+    match get_eslint_version() {
+        Some(version) => {
+            if version != eslint_version {
+                *bad = true;
+                eprintln!(
+                    "⚠️ Installed version of eslint (`{version}`) is different than the \
+                     one used in the CI (`{eslint_version}`)",
+                );
+                eprintln!(
+                    "You can install this version using `npm update eslint` or by using \
+                     `npm install eslint@{eslint_version}`",
+                );
+                return;
+            }
+        }
+        None => {
+            eprintln!("`eslint` doesn't seem to be installed. Skipping tidy check for JS files.");
+            eprintln!("You can install it using `npm install eslint@{eslint_version}`");
+            return;
+        }
+    }
+    let mut files_to_check = Vec::new();
+    walk_no_read(
+        &[&librustdoc_path.join("html/static/js")],
+        |path, is_dir| is_dir || !path.extension().is_some_and(|ext| ext == OsStr::new("js")),
+        &mut |path: &DirEntry| {
+            files_to_check.push(path.path().into());
+        },
+    );
+    println!("Running eslint on rustdoc JS files");
+    run_eslint(&files_to_check, librustdoc_path.join("html/static"), bad);
+
+    run_eslint(&[tools_path.join("rustdoc-js/tester.js")], tools_path.join("rustdoc-js"), bad);
+    run_eslint(&[tools_path.join("rustdoc-gui/tester.js")], tools_path.join("rustdoc-gui"), bad);
+}
diff --git a/src/tools/unstable-book-gen/src/SUMMARY.md b/src/tools/unstable-book-gen/src/SUMMARY.md
index 933c928e2f0..fd4ea1dada6 100644
--- a/src/tools/unstable-book-gen/src/SUMMARY.md
+++ b/src/tools/unstable-book-gen/src/SUMMARY.md
@@ -1,5 +1,7 @@
 [The Unstable Book](the-unstable-book.md)
 
+- [Compiler environment variables](compiler-environment-variables.md)
+{compiler_env_vars}
 - [Compiler flags](compiler-flags.md)
 {compiler_flags}
 - [Language features](language-features.md)
diff --git a/src/tools/unstable-book-gen/src/main.rs b/src/tools/unstable-book-gen/src/main.rs
index 33435772960..159a1d0fa17 100644
--- a/src/tools/unstable-book-gen/src/main.rs
+++ b/src/tools/unstable-book-gen/src/main.rs
@@ -35,8 +35,12 @@ fn set_to_summary_str(set: &BTreeSet<String>, dir: &str) -> String {
 
 fn generate_summary(path: &Path, lang_features: &Features, lib_features: &Features) {
     let compiler_flags = collect_unstable_book_section_file_names(&path.join("src/compiler-flags"));
+    let compiler_env_vars =
+        collect_unstable_book_section_file_names(&path.join("src/compiler-environment-variables"));
 
     let compiler_flags_str = set_to_summary_str(&compiler_flags, "compiler-flags");
+    let compiler_env_vars_str =
+        set_to_summary_str(&compiler_env_vars, "compiler-environment-variables");
 
     let unstable_lang_features = collect_unstable_feature_names(&lang_features);
     let unstable_lib_features = collect_unstable_feature_names(&lib_features);
@@ -47,6 +51,7 @@ fn generate_summary(path: &Path, lang_features: &Features, lib_features: &Featur
     let summary_path = path.join("src/SUMMARY.md");
     let content = format!(
         include_str!("SUMMARY.md"),
+        compiler_env_vars = compiler_env_vars_str,
         compiler_flags = compiler_flags_str,
         language_features = lang_features_str,
         library_features = lib_features_str
diff --git a/tests/assembly/aarch64-xray.rs b/tests/assembly/aarch64-xray.rs
new file mode 100644
index 00000000000..d5ee0111843
--- /dev/null
+++ b/tests/assembly/aarch64-xray.rs
@@ -0,0 +1,25 @@
+//@ assembly-output: emit-asm
+//@ compile-flags: -Zinstrument-xray=always
+
+//@ revisions: aarch64-linux
+//@[aarch64-linux] compile-flags: --target=aarch64-unknown-linux-gnu
+//@[aarch64-linux] needs-llvm-components: aarch64
+//@[aarch64-linux] only-aarch64-unknown-linux-gnu
+
+//@ revisions: aarch64-darwin
+//@[aarch64-darwin] compile-flags: --target=aarch64-apple-darwin
+//@[aarch64-darwin] needs-llvm-components: aarch64
+//@[aarch64-darwin] only-aarch64-apple-darwin
+
+#![crate_type = "lib"]
+
+// CHECK-LABEL: xray_func:
+#[no_mangle]
+pub fn xray_func() {
+    // CHECK: nop
+
+    std::hint::black_box(());
+
+    // CHECK: b #32
+    // CHECK-NEXT: nop
+}
diff --git a/tests/assembly/x86_64-xray.rs b/tests/assembly/x86_64-xray.rs
new file mode 100644
index 00000000000..4cf3e8cda13
--- /dev/null
+++ b/tests/assembly/x86_64-xray.rs
@@ -0,0 +1,25 @@
+//@ assembly-output: emit-asm
+//@ compile-flags: -Zinstrument-xray=always -Cllvm-args=-x86-asm-syntax=intel
+
+//@ revisions: x86_64-linux
+//@[x86_64-linux] compile-flags: --target=x86_64-unknown-linux-gnu
+//@[x86_64-linux] needs-llvm-components: x86
+//@[x86_64-linux] only-x86_64-unknown-linux-gnu
+
+//@ revisions: x86_64-darwin
+//@[x86_64-darwin] compile-flags: --target=x86_64-apple-darwin
+//@[x86_64-darwin] needs-llvm-components: x86
+//@[x86_64-darwin] only-x86_64-apple-darwin
+
+#![crate_type = "lib"]
+
+// CHECK-LABEL: xray_func:
+#[no_mangle]
+pub fn xray_func() {
+    // CHECK: nop word ptr [rax + rax + 512]
+
+    std::hint::black_box(());
+
+    // CHECK: ret
+    // CHECK-NEXT: nop word ptr cs:[rax + rax + 512]
+}
diff --git a/tests/codegen/align-byval-alignment-mismatch.rs b/tests/codegen/align-byval-alignment-mismatch.rs
index 46cfb2972df..c69fc2de9d2 100644
--- a/tests/codegen/align-byval-alignment-mismatch.rs
+++ b/tests/codegen/align-byval-alignment-mismatch.rs
@@ -2,9 +2,10 @@
 //@ add-core-stubs
 //@ revisions:i686-linux x86_64-linux
 
-//@[i686-linux] compile-flags: --target i686-unknown-linux-gnu -C panic=abort
+//@ compile-flags: -Cno-prepopulate-passes -Copt-level=1 -Cpanic=abort
+//@[i686-linux] compile-flags: --target i686-unknown-linux-gnu
 //@[i686-linux] needs-llvm-components: x86
-//@[x86_64-linux] compile-flags: --target x86_64-unknown-linux-gnu -C panic=abort
+//@[x86_64-linux] compile-flags: --target x86_64-unknown-linux-gnu
 //@[x86_64-linux] needs-llvm-components: x86
 
 // Tests that we correctly copy arguments into allocas when the alignment of the byval argument
@@ -54,8 +55,10 @@ extern "C" {
 pub unsafe fn rust_to_c_increases_alignment(x: Align1) {
     // i686-linux: start:
     // i686-linux-NEXT: [[ALLOCA:%[0-9a-z]+]] = alloca [48 x i8], align 4
+    // i686-linux-NEXT: call void @llvm.lifetime.start.p0(i64 48, ptr {{.*}}[[ALLOCA]])
     // i686-linux-NEXT: call void @llvm.memcpy.{{.+}}(ptr {{.*}}align 4 {{.*}}[[ALLOCA]], ptr {{.*}}align 1 {{.*}}%x
     // i686-linux-NEXT: call void @extern_c_align1({{.+}} [[ALLOCA]])
+    // i686-linux-NEXT: call void @llvm.lifetime.end.p0(i64 48, ptr {{.*}}[[ALLOCA]])
 
     // x86_64-linux: start:
     // x86_64-linux-NEXT: call void @extern_c_align1
diff --git a/tests/codegen/autodiff/batched.rs b/tests/codegen/autodiff/batched.rs
index e0047116405..d27aed50e6c 100644
--- a/tests/codegen/autodiff/batched.rs
+++ b/tests/codegen/autodiff/batched.rs
@@ -11,11 +11,11 @@
 
 #![feature(autodiff)]
 
-use std::autodiff::autodiff;
+use std::autodiff::autodiff_forward;
 
-#[autodiff(d_square3, Forward, Dual, DualOnly)]
-#[autodiff(d_square2, Forward, 4, Dual, DualOnly)]
-#[autodiff(d_square1, Forward, 4, Dual, Dual)]
+#[autodiff_forward(d_square3, Dual, DualOnly)]
+#[autodiff_forward(d_square2, 4, Dual, DualOnly)]
+#[autodiff_forward(d_square1, 4, Dual, Dual)]
 #[no_mangle]
 fn square(x: &f32) -> f32 {
     x * x
diff --git a/tests/codegen/autodiff/generic.rs b/tests/codegen/autodiff/generic.rs
index 15e7d8a4957..2f674079be0 100644
--- a/tests/codegen/autodiff/generic.rs
+++ b/tests/codegen/autodiff/generic.rs
@@ -3,9 +3,9 @@
 //@ needs-enzyme
 #![feature(autodiff)]
 
-use std::autodiff::autodiff;
+use std::autodiff::autodiff_reverse;
 
-#[autodiff(d_square, Reverse, Duplicated, Active)]
+#[autodiff_reverse(d_square, Duplicated, Active)]
 fn square<T: std::ops::Mul<Output = T> + Copy>(x: &T) -> T {
     *x * *x
 }
diff --git a/tests/codegen/autodiff/identical_fnc.rs b/tests/codegen/autodiff/identical_fnc.rs
index 1c3277f52b4..1c25b3d09ab 100644
--- a/tests/codegen/autodiff/identical_fnc.rs
+++ b/tests/codegen/autodiff/identical_fnc.rs
@@ -11,14 +11,14 @@
 // identical function calls in the LLVM-IR, while having two different calls in the Rust code.
 #![feature(autodiff)]
 
-use std::autodiff::autodiff;
+use std::autodiff::autodiff_reverse;
 
-#[autodiff(d_square, Reverse, Duplicated, Active)]
+#[autodiff_reverse(d_square, Duplicated, Active)]
 fn square(x: &f64) -> f64 {
     x * x
 }
 
-#[autodiff(d_square2, Reverse, Duplicated, Active)]
+#[autodiff_reverse(d_square2, Duplicated, Active)]
 fn square2(x: &f64) -> f64 {
     x * x
 }
diff --git a/tests/codegen/autodiff/inline.rs b/tests/codegen/autodiff/inline.rs
index e90faa4aa38..65bed170207 100644
--- a/tests/codegen/autodiff/inline.rs
+++ b/tests/codegen/autodiff/inline.rs
@@ -4,9 +4,9 @@
 
 #![feature(autodiff)]
 
-use std::autodiff::autodiff;
+use std::autodiff::autodiff_reverse;
 
-#[autodiff(d_square, Reverse, Duplicated, Active)]
+#[autodiff_reverse(d_square, Duplicated, Active)]
 fn square(x: &f64) -> f64 {
     x * x
 }
diff --git a/tests/codegen/autodiff/scalar.rs b/tests/codegen/autodiff/scalar.rs
index 85358f5fcb6..096b4209e84 100644
--- a/tests/codegen/autodiff/scalar.rs
+++ b/tests/codegen/autodiff/scalar.rs
@@ -3,9 +3,9 @@
 //@ needs-enzyme
 #![feature(autodiff)]
 
-use std::autodiff::autodiff;
+use std::autodiff::autodiff_reverse;
 
-#[autodiff(d_square, Reverse, Duplicated, Active)]
+#[autodiff_reverse(d_square, Duplicated, Active)]
 #[no_mangle]
 fn square(x: &f64) -> f64 {
     x * x
diff --git a/tests/codegen/autodiff/sret.rs b/tests/codegen/autodiff/sret.rs
index 5ead90041ed..d2fa85e3e37 100644
--- a/tests/codegen/autodiff/sret.rs
+++ b/tests/codegen/autodiff/sret.rs
@@ -9,10 +9,10 @@
 
 #![feature(autodiff)]
 
-use std::autodiff::autodiff;
+use std::autodiff::autodiff_reverse;
 
 #[no_mangle]
-#[autodiff(df, Reverse, Active, Active, Active)]
+#[autodiff_reverse(df, Active, Active, Active)]
 fn primal(x: f32, y: f32) -> f64 {
     (x * x * y) as f64
 }
diff --git a/tests/codegen/call-tmps-lifetime.rs b/tests/codegen/call-tmps-lifetime.rs
new file mode 100644
index 00000000000..7b7b6e17bdd
--- /dev/null
+++ b/tests/codegen/call-tmps-lifetime.rs
@@ -0,0 +1,68 @@
+// Test that temporary allocas used for call arguments have their lifetimes described by
+// intrinsics.
+//
+//@ add-core-stubs
+//@ compile-flags: -Copt-level=1 -Cno-prepopulate-passes --crate-type=lib --target i686-unknown-linux-gnu
+//@ needs-llvm-components: x86
+#![feature(no_core)]
+#![no_std]
+#![no_core]
+extern crate minicore;
+use minicore::*;
+
+// Const operand. Regression test for #98156.
+//
+// CHECK-LABEL: define void @const_indirect(
+// CHECK-NEXT: start:
+// CHECK-NEXT: [[B:%.*]] = alloca
+// CHECK-NEXT: [[A:%.*]] = alloca
+// CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 4096, ptr [[A]])
+// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[A]], ptr align 4 {{.*}}, i32 4096, i1 false)
+// CHECK-NEXT: call void %h(ptr {{.*}} [[A]])
+// CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 4096, ptr [[A]])
+// CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 4096, ptr [[B]])
+// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[B]], ptr align 4 {{.*}}, i32 4096, i1 false)
+// CHECK-NEXT: call void %h(ptr {{.*}} [[B]])
+// CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 4096, ptr [[B]])
+#[no_mangle]
+pub fn const_indirect(h: extern "C" fn([u32; 1024])) {
+    const C: [u32; 1024] = [0; 1024];
+    h(C);
+    h(C);
+}
+
+#[repr(C)]
+pub struct Str {
+    pub ptr: *const u8,
+    pub len: usize,
+}
+
+// Pair of immediates. Regression test for #132014.
+//
+// CHECK-LABEL: define void @immediate_indirect(ptr {{.*}}%s.0, i32 {{.*}}%s.1, ptr {{.*}}%g)
+// CHECK-NEXT: start:
+// CHECK-NEXT: [[A:%.*]] = alloca
+// CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 8, ptr [[A]])
+// CHECK-NEXT: store ptr %s.0, ptr [[A]]
+// CHECK-NEXT: [[B:%.]] = getelementptr inbounds i8, ptr [[A]], i32 4
+// CHECK-NEXT: store i32 %s.1, ptr [[B]]
+// CHECK-NEXT: call void %g(ptr {{.*}} [[A]])
+// CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 8, ptr [[A]])
+#[no_mangle]
+pub fn immediate_indirect(s: Str, g: extern "C" fn(Str)) {
+    g(s);
+}
+
+// Indirect argument with a higher alignment requirement than the type's.
+//
+// CHECK-LABEL: define void @align_indirect(ptr{{.*}} align 1{{.*}} %a, ptr{{.*}} %fun)
+// CHECK-NEXT: start:
+// CHECK-NEXT: [[A:%.*]] = alloca [1024 x i8], align 4
+// CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 1024, ptr [[A]])
+// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[A]], ptr align 1 %a, i32 1024, i1 false)
+// CHECK-NEXT: call void %fun(ptr {{.*}} [[A]])
+// CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 1024, ptr [[A]])
+#[no_mangle]
+pub fn align_indirect(a: [u8; 1024], fun: extern "C" fn([u8; 1024])) {
+    fun(a);
+}
diff --git a/tests/codegen/enum/enum-u128.rs b/tests/codegen/enum/enum-u128.rs
index ecdff3c5ce3..2676669f3e3 100644
--- a/tests/codegen/enum/enum-u128.rs
+++ b/tests/codegen/enum/enum-u128.rs
@@ -13,9 +13,6 @@
 // CHECK: {{.*}}DIEnumerator{{.*}}name: "Hi",{{.*}}value: 18446744073709551616,{{.*}}
 // CHECK: {{.*}}DIEnumerator{{.*}}name: "Bar",{{.*}}value: 18446745000000000123,{{.*}}
 
-#![allow(incomplete_features)]
-#![feature(repr128)]
-
 #[repr(u128)]
 pub enum Foo {
     Lo,
diff --git a/tests/codegen/issues/issue-98156-const-arg-temp-lifetime.rs b/tests/codegen/issues/issue-98156-const-arg-temp-lifetime.rs
deleted file mode 100644
index aecb81caf22..00000000000
--- a/tests/codegen/issues/issue-98156-const-arg-temp-lifetime.rs
+++ /dev/null
@@ -1,27 +0,0 @@
-// This test checks that temporaries for indirectly-passed arguments get lifetime markers.
-
-//@ compile-flags: -Copt-level=3 -C no-prepopulate-passes -Zmir-opt-level=0
-
-#![crate_type = "lib"]
-
-extern "Rust" {
-    fn f(x: [u8; 1024]);
-}
-
-const A: [u8; 1024] = [0; 1024];
-
-// CHECK-LABEL: @const_arg_indirect
-#[no_mangle]
-pub unsafe fn const_arg_indirect() {
-    // Ensure that the live ranges for the two argument temporaries don't overlap.
-
-    // CHECK: call void @llvm.lifetime.start
-    // CHECK: call void @f
-    // CHECK: call void @llvm.lifetime.end
-    // CHECK: call void @llvm.lifetime.start
-    // CHECK: call void @f
-    // CHECK: call void @llvm.lifetime.end
-
-    f(A);
-    f(A);
-}
diff --git a/tests/codegen/option-niche-eq.rs b/tests/codegen/option-niche-eq.rs
index a39e2870a0f..3900cb79aa2 100644
--- a/tests/codegen/option-niche-eq.rs
+++ b/tests/codegen/option-niche-eq.rs
@@ -1,5 +1,7 @@
+//@ revisions: REGULAR LLVM21
 //@ min-llvm-version: 20
 //@ compile-flags: -Copt-level=3 -Zmerge-functions=disabled
+//@ [LLVM21] min-llvm-version: 21
 #![crate_type = "lib"]
 
 extern crate core;
@@ -74,3 +76,12 @@ pub fn niche_eq(l: Option<EnumWithNiche>, r: Option<EnumWithNiche>) -> bool {
     // CHECK-NEXT: ret i1
     l == r
 }
+
+// LLVM21-LABEL: @bool_eq
+#[no_mangle]
+pub fn bool_eq(l: Option<bool>, r: Option<bool>) -> bool {
+    // LLVM21: start:
+    // LLVM21-NEXT: icmp eq i8
+    // LLVM21-NEXT: ret i1
+    l == r
+}
diff --git a/tests/codegen/option-niche-unfixed/option-bool-eq.rs b/tests/codegen/option-niche-unfixed/option-bool-eq.rs
deleted file mode 100644
index fa0e7836afb..00000000000
--- a/tests/codegen/option-niche-unfixed/option-bool-eq.rs
+++ /dev/null
@@ -1,15 +0,0 @@
-//@ should-fail
-//@ compile-flags: -Copt-level=3 -Zmerge-functions=disabled
-//! FIXME(#49892)
-//! Tests that LLVM does not fully optimize comparisons of `Option<bool>`.
-//! If this starts passing, it can be moved to `tests/codegen/option-niche-eq.rs`
-#![crate_type = "lib"]
-
-// CHECK-LABEL: @bool_eq
-#[no_mangle]
-pub fn bool_eq(l: Option<bool>, r: Option<bool>) -> bool {
-    // CHECK: start:
-    // CHECK-NEXT: icmp eq i8
-    // CHECK-NEXT: ret i1
-    l == r
-}
diff --git a/tests/codegen/thread-local.rs b/tests/codegen/thread-local.rs
index 9ce34473b91..41df8c9be1b 100644
--- a/tests/codegen/thread-local.rs
+++ b/tests/codegen/thread-local.rs
@@ -14,13 +14,14 @@ use std::cell::Cell;
 
 thread_local!(static A: Cell<u32> = const { Cell::new(1) });
 
-// CHECK: [[TLS_AUX:@.+]] = external thread_local local_unnamed_addr global i64
-// CHECK: [[TLS:@.+]] = internal thread_local unnamed_addr global
+// CHECK: [[TLS_AUX:@.+]] = external thread_local{{.*}} global i64
+// CHECK: [[TLS:@.+]] = internal thread_local{{.*}} global
 
 // CHECK-LABEL: @get
 #[no_mangle]
 fn get() -> u32 {
-    // CHECK: [[RET_0:%.+]] = load i32, {{.*}}[[TLS]]{{.*}}
+    // CHECK: [[PTR:%.+]] = tail call {{.*}} ptr @llvm.threadlocal.address.p0(ptr [[TLS]])
+    // CHECK-NEXT: [[RET_0:%.+]] = load i32, ptr [[PTR]]
     // CHECK-NEXT: ret i32 [[RET_0]]
     A.with(|a| a.get())
 }
@@ -28,7 +29,8 @@ fn get() -> u32 {
 // CHECK-LABEL: @set
 #[no_mangle]
 fn set(v: u32) {
-    // CHECK: store i32 %0, {{.*}}[[TLS]]{{.*}}
+    // CHECK: [[PTR:%.+]] = tail call {{.*}} ptr @llvm.threadlocal.address.p0(ptr [[TLS]])
+    // CHECK-NEXT: store i32 %0, ptr [[PTR]]
     // CHECK-NEXT: ret void
     A.with(|a| a.set(v))
 }
@@ -36,7 +38,8 @@ fn set(v: u32) {
 // CHECK-LABEL: @get_aux
 #[no_mangle]
 fn get_aux() -> u64 {
-    // CHECK: [[RET_1:%.+]] = load i64, {{.*}}[[TLS_AUX]]
+    // CHECK: [[PTR:%.+]] = tail call {{.*}} ptr @llvm.threadlocal.address.p0(ptr [[TLS_AUX]])
+    // CHECK-NEXT: [[RET_1:%.+]] = load i64, ptr [[PTR]]
     // CHECK-NEXT: ret i64 [[RET_1]]
     aux::A.with(|a| a.get())
 }
@@ -44,7 +47,8 @@ fn get_aux() -> u64 {
 // CHECK-LABEL: @set_aux
 #[no_mangle]
 fn set_aux(v: u64) {
-    // CHECK: store i64 %0, {{.*}}[[TLS_AUX]]
+    // CHECK: [[PTR:%.+]] = tail call {{.*}} ptr @llvm.threadlocal.address.p0(ptr [[TLS_AUX]])
+    // CHECK-NEXT: store i64 %0, ptr [[PTR]]
     // CHECK-NEXT: ret void
     aux::A.with(|a| a.set(v))
 }
diff --git a/tests/coverage/async_closure.cov-map b/tests/coverage/async_closure.cov-map
index 53128dd7a48..9f8dc8d6cbb 100644
--- a/tests/coverage/async_closure.cov-map
+++ b/tests/coverage/async_closure.cov-map
@@ -37,29 +37,32 @@ Number of file 0 mappings: 8
 Highest counter ID seen: c0
 
 Function name: async_closure::main::{closure#0}
-Raw bytes (9): 0x[01, 01, 00, 01, 01, 0b, 22, 00, 24]
+Raw bytes (14): 0x[01, 01, 00, 02, 01, 0b, 22, 00, 23, 01, 00, 23, 00, 24]
 Number of files: 1
 - file 0 => $DIR/async_closure.rs
 Number of expressions: 0
-Number of file 0 mappings: 1
-- Code(Counter(0)) at (prev + 11, 34) to (start + 0, 36)
+Number of file 0 mappings: 2
+- Code(Counter(0)) at (prev + 11, 34) to (start + 0, 35)
+- Code(Counter(0)) at (prev + 0, 35) to (start + 0, 36)
 Highest counter ID seen: c0
 
 Function name: async_closure::main::{closure#0}
-Raw bytes (9): 0x[01, 01, 00, 01, 01, 0b, 22, 00, 24]
+Raw bytes (14): 0x[01, 01, 00, 02, 01, 0b, 22, 00, 23, 01, 00, 23, 00, 24]
 Number of files: 1
 - file 0 => $DIR/async_closure.rs
 Number of expressions: 0
-Number of file 0 mappings: 1
-- Code(Counter(0)) at (prev + 11, 34) to (start + 0, 36)
+Number of file 0 mappings: 2
+- Code(Counter(0)) at (prev + 11, 34) to (start + 0, 35)
+- Code(Counter(0)) at (prev + 0, 35) to (start + 0, 36)
 Highest counter ID seen: c0
 
 Function name: async_closure::main::{closure#0}::{closure#0}::<i16>
-Raw bytes (9): 0x[01, 01, 00, 01, 01, 0b, 22, 00, 24]
+Raw bytes (14): 0x[01, 01, 00, 02, 01, 0b, 22, 00, 23, 01, 00, 23, 00, 24]
 Number of files: 1
 - file 0 => $DIR/async_closure.rs
 Number of expressions: 0
-Number of file 0 mappings: 1
-- Code(Counter(0)) at (prev + 11, 34) to (start + 0, 36)
+Number of file 0 mappings: 2
+- Code(Counter(0)) at (prev + 11, 34) to (start + 0, 35)
+- Code(Counter(0)) at (prev + 0, 35) to (start + 0, 36)
 Highest counter ID seen: c0
 
diff --git a/tests/coverage/unused-local-file.coverage b/tests/coverage/unused-local-file.coverage
deleted file mode 100644
index 8f5a32f6d70..00000000000
--- a/tests/coverage/unused-local-file.coverage
+++ /dev/null
@@ -1,7 +0,0 @@
-   LL|       |//@ edition: 2021
-   LL|       |
-   LL|       |// Force this function to be generated in its home crate, so that it ends up
-   LL|       |// with normal coverage metadata.
-   LL|       |#[inline(never)]
-   LL|      1|pub fn external_function() {}
-
diff --git a/tests/coverage/unused-local-file.rs b/tests/coverage/unused-local-file.rs
deleted file mode 100644
index cf43c62d703..00000000000
--- a/tests/coverage/unused-local-file.rs
+++ /dev/null
@@ -1,22 +0,0 @@
-//! If we give LLVM a local file table for a function, but some of the entries
-//! in that table have no associated mapping regions, then an assertion failure
-//! will occur in LLVM. We therefore need to detect and skip any function that
-//! would trigger that assertion.
-//!
-//! To test that this case is handled, even before adding code that could allow
-//! it to happen organically (for expansion region support), we use a special
-//! testing-only flag to force it to occur.
-
-//@ edition: 2024
-//@ compile-flags: -Zcoverage-options=inject-unused-local-file
-
-// The `llvm-cov` tool will complain if the test binary ends up having no
-// coverage metadata at all. To prevent that, we also link to instrumented
-// code in an auxiliary crate that doesn't have the special flag set.
-
-//@ aux-build: discard_all_helper.rs
-extern crate discard_all_helper;
-
-fn main() {
-    discard_all_helper::external_function();
-}
diff --git a/tests/crashes/140255.rs b/tests/crashes/140255.rs
deleted file mode 100644
index 6b0ec1718b0..00000000000
--- a/tests/crashes/140255.rs
+++ /dev/null
@@ -1,3 +0,0 @@
-//@ known-bug: #140255
-#[unsafe(macro_use::VAR2)]
-fn dead_code() {}
diff --git a/tests/crashes/140281.rs b/tests/crashes/140281.rs
deleted file mode 100644
index 76858cfc74a..00000000000
--- a/tests/crashes/140281.rs
+++ /dev/null
@@ -1,18 +0,0 @@
-//@ known-bug: #140281
-
-macro_rules! foo {
-    ($x:expr) => { $x }
-}
-
-fn main() {
-    let t = vec![
-        /// ‮test⁦ RTL in doc in vec!
-        //  ICE (Sadly)
-        1
-    ];
-
-        foo!(
-        /// ‮test⁦ RTL in doc in macro
-        1
-    );
-}
diff --git a/tests/crashes/140484.rs b/tests/crashes/140484.rs
deleted file mode 100644
index 92ec1984398..00000000000
--- a/tests/crashes/140484.rs
+++ /dev/null
@@ -1,14 +0,0 @@
-//@ known-bug: #140484
-//@edition:2024
-#![feature(async_drop)]
-use std::future::AsyncDrop;
-struct a;
-impl Drop for a {
-    fn b() {}
-}
-impl AsyncDrop for a {
-    type c;
-}
-async fn bar() {
-    a;
-}
diff --git a/tests/crashes/140500.rs b/tests/crashes/140500.rs
deleted file mode 100644
index ee5b93ab821..00000000000
--- a/tests/crashes/140500.rs
+++ /dev/null
@@ -1,14 +0,0 @@
-//@ known-bug: #140500
-
-#![feature(async_drop)]
-use std::future::AsyncDrop;
-struct a;
-impl Drop for a {
-    fn b() {}
-}
-impl AsyncDrop for a {
-    fn c(d: impl Sized) {}
-}
-async fn bar() {
-    a;
-}
diff --git a/tests/crashes/140683.rs b/tests/crashes/140683.rs
deleted file mode 100644
index 74ea5c2533b..00000000000
--- a/tests/crashes/140683.rs
+++ /dev/null
@@ -1,5 +0,0 @@
-//@ known-bug: #140683
-impl T {
-#[core::contracts::ensures]
-  fn b() { (loop) }
-}
diff --git a/tests/debuginfo/by-value-non-immediate-argument.rs b/tests/debuginfo/by-value-non-immediate-argument.rs
index 192f6efe7db..5233b95f1f4 100644
--- a/tests/debuginfo/by-value-non-immediate-argument.rs
+++ b/tests/debuginfo/by-value-non-immediate-argument.rs
@@ -2,6 +2,7 @@
 //@ min-gdb-version: 13.0
 //@ compile-flags:-g
 //@ ignore-windows-gnu: #128973
+//@ ignore-aarch64-unknown-linux-gnu (gdb tries to read from 0x0; FIXME: #128973)
 
 // === GDB TESTS ===================================================================================
 
diff --git a/tests/debuginfo/msvc-pretty-enums.rs b/tests/debuginfo/msvc-pretty-enums.rs
index 06bc25dc5d5..aa6629ef1e1 100644
--- a/tests/debuginfo/msvc-pretty-enums.rs
+++ b/tests/debuginfo/msvc-pretty-enums.rs
@@ -231,8 +231,6 @@
 // cdb-command: dx c_style_i128_d
 // cdb-check: c_style_i128_d   : D [Type: enum2$<msvc_pretty_enums::CStyleI128>]
 #![feature(rustc_attrs)]
-#![feature(repr128)]
-#![feature(arbitrary_enum_discriminant)]
 
 use std::num::NonZero;
 
diff --git a/tests/mir-opt/coverage/branch_match_arms.main.InstrumentCoverage.diff b/tests/mir-opt/coverage/branch_match_arms.main.InstrumentCoverage.diff
index fa88211383a..d465b8bded2 100644
--- a/tests/mir-opt/coverage/branch_match_arms.main.InstrumentCoverage.diff
+++ b/tests/mir-opt/coverage/branch_match_arms.main.InstrumentCoverage.diff
@@ -40,7 +40,7 @@
 +     coverage Code { bcb: bcb5 } => $DIR/branch_match_arms.rs:19:17: 19:18 (#0);
 +     coverage Code { bcb: bcb5 } => $DIR/branch_match_arms.rs:19:23: 19:30 (#0);
 +     coverage Code { bcb: bcb5 } => $DIR/branch_match_arms.rs:19:31: 19:32 (#0);
-+     coverage Code { bcb: bcb2 } => $DIR/branch_match_arms.rs:21:1: 21:2 (#0);
++     coverage Code { bcb: bcb2 } => $DIR/branch_match_arms.rs:21:2: 21:2 (#0);
 + 
       bb0: {
 +         Coverage::VirtualCounter(bcb0);
diff --git a/tests/mir-opt/coverage/instrument_coverage.bar.InstrumentCoverage.diff b/tests/mir-opt/coverage/instrument_coverage.bar.InstrumentCoverage.diff
index 9b6d2b22087..cf6d85abd80 100644
--- a/tests/mir-opt/coverage/instrument_coverage.bar.InstrumentCoverage.diff
+++ b/tests/mir-opt/coverage/instrument_coverage.bar.InstrumentCoverage.diff
@@ -6,7 +6,7 @@
   
 +     coverage Code { bcb: bcb0 } => $DIR/instrument_coverage.rs:27:1: 27:17 (#0);
 +     coverage Code { bcb: bcb0 } => $DIR/instrument_coverage.rs:28:5: 28:9 (#0);
-+     coverage Code { bcb: bcb0 } => $DIR/instrument_coverage.rs:29:1: 29:2 (#0);
++     coverage Code { bcb: bcb0 } => $DIR/instrument_coverage.rs:29:2: 29:2 (#0);
 + 
       bb0: {
 +         Coverage::VirtualCounter(bcb0);
diff --git a/tests/mir-opt/coverage/instrument_coverage.main.InstrumentCoverage.diff b/tests/mir-opt/coverage/instrument_coverage.main.InstrumentCoverage.diff
index b2bb2375aee..980c5e202ff 100644
--- a/tests/mir-opt/coverage/instrument_coverage.main.InstrumentCoverage.diff
+++ b/tests/mir-opt/coverage/instrument_coverage.main.InstrumentCoverage.diff
@@ -10,8 +10,8 @@
 +     coverage Code { bcb: bcb0 } => $DIR/instrument_coverage.rs:13:1: 13:10 (#0);
 +     coverage Code { bcb: bcb1 } => $DIR/instrument_coverage.rs:15:12: 15:15 (#0);
 +     coverage Code { bcb: bcb2 } => $DIR/instrument_coverage.rs:16:13: 16:18 (#0);
-+     coverage Code { bcb: bcb3 } => $DIR/instrument_coverage.rs:17:9: 17:10 (#0);
-+     coverage Code { bcb: bcb2 } => $DIR/instrument_coverage.rs:19:1: 19:2 (#0);
++     coverage Code { bcb: bcb3 } => $DIR/instrument_coverage.rs:17:10: 17:10 (#0);
++     coverage Code { bcb: bcb2 } => $DIR/instrument_coverage.rs:19:2: 19:2 (#0);
 + 
       bb0: {
 +         Coverage::VirtualCounter(bcb0);
diff --git a/tests/mir-opt/coverage/instrument_coverage_cleanup.main.CleanupPostBorrowck.diff b/tests/mir-opt/coverage/instrument_coverage_cleanup.main.CleanupPostBorrowck.diff
index 2eb78c08ee8..b707cd41788 100644
--- a/tests/mir-opt/coverage/instrument_coverage_cleanup.main.CleanupPostBorrowck.diff
+++ b/tests/mir-opt/coverage/instrument_coverage_cleanup.main.CleanupPostBorrowck.diff
@@ -10,8 +10,8 @@
       coverage Code { bcb: bcb0 } => $DIR/instrument_coverage_cleanup.rs:13:1: 13:10 (#0);
       coverage Code { bcb: bcb0 } => $DIR/instrument_coverage_cleanup.rs:14:8: 14:36 (#0);
       coverage Code { bcb: bcb3 } => $DIR/instrument_coverage_cleanup.rs:14:37: 14:39 (#0);
-      coverage Code { bcb: bcb1 } => $DIR/instrument_coverage_cleanup.rs:14:38: 14:39 (#0);
-      coverage Code { bcb: bcb2 } => $DIR/instrument_coverage_cleanup.rs:15:1: 15:2 (#0);
+      coverage Code { bcb: bcb1 } => $DIR/instrument_coverage_cleanup.rs:14:39: 14:39 (#0);
+      coverage Code { bcb: bcb2 } => $DIR/instrument_coverage_cleanup.rs:15:2: 15:2 (#0);
       coverage Branch { true_bcb: bcb3, false_bcb: bcb1 } => $DIR/instrument_coverage_cleanup.rs:14:8: 14:36 (#0);
   
       bb0: {
diff --git a/tests/mir-opt/coverage/instrument_coverage_cleanup.main.InstrumentCoverage.diff b/tests/mir-opt/coverage/instrument_coverage_cleanup.main.InstrumentCoverage.diff
index 0c1bc24b6dc..239b845c231 100644
--- a/tests/mir-opt/coverage/instrument_coverage_cleanup.main.InstrumentCoverage.diff
+++ b/tests/mir-opt/coverage/instrument_coverage_cleanup.main.InstrumentCoverage.diff
@@ -10,8 +10,8 @@
 +     coverage Code { bcb: bcb0 } => $DIR/instrument_coverage_cleanup.rs:13:1: 13:10 (#0);
 +     coverage Code { bcb: bcb0 } => $DIR/instrument_coverage_cleanup.rs:14:8: 14:36 (#0);
 +     coverage Code { bcb: bcb3 } => $DIR/instrument_coverage_cleanup.rs:14:37: 14:39 (#0);
-+     coverage Code { bcb: bcb1 } => $DIR/instrument_coverage_cleanup.rs:14:38: 14:39 (#0);
-+     coverage Code { bcb: bcb2 } => $DIR/instrument_coverage_cleanup.rs:15:1: 15:2 (#0);
++     coverage Code { bcb: bcb1 } => $DIR/instrument_coverage_cleanup.rs:14:39: 14:39 (#0);
++     coverage Code { bcb: bcb2 } => $DIR/instrument_coverage_cleanup.rs:15:2: 15:2 (#0);
 +     coverage Branch { true_bcb: bcb3, false_bcb: bcb1 } => $DIR/instrument_coverage_cleanup.rs:14:8: 14:36 (#0);
 + 
       bb0: {
diff --git a/tests/mir-opt/dataflow.main.maybe_init.borrowck.dot b/tests/mir-opt/dataflow.main.maybe_init.borrowck.dot
deleted file mode 100644
index 7c7d8921fb3..00000000000
--- a/tests/mir-opt/dataflow.main.maybe_init.borrowck.dot
+++ /dev/null
@@ -1,6 +0,0 @@
-digraph graph_for_def_id_0_3 {
-    graph[fontname="Courier, monospace"];
-    node[fontname="Courier, monospace"];
-    edge[fontname="Courier, monospace"];
-    bb_0[label=<<table border="1" cellborder="1" cellspacing="0" cellpadding="3" sides="rb"><tr><td colspan="3" sides="tl">bb0</td></tr><tr><td colspan="2" bgcolor="#a0a0a0" sides="tl">MIR</td><td bgcolor="#a0a0a0" sides="tl">STATE</td></tr><tr><td valign="bottom" sides="tl"  align="right"></td><td valign="bottom" sides="tl"  align="left">(on start)</td><td colspan="1" valign="bottom" sides="tl"  align="left">{}</td></tr><tr><td valign="top" sides="tl" bgcolor="#f0f0f0" align="right">0</td><td valign="top" sides="tl" bgcolor="#f0f0f0" align="left">_0 = const ()</td><td valign="top" sides="tl" bgcolor="#f0f0f0" align="left"><font color="darkgreen">+_0</font></td></tr><tr><td valign="top" sides="tl"  align="right">T</td><td valign="top" sides="tl"  align="left">return</td><td valign="top" sides="tl"  align="left"></td></tr><tr><td valign="bottom" sides="tl" bgcolor="#f0f0f0" align="right"></td><td valign="bottom" sides="tl" bgcolor="#f0f0f0" align="left">(on end)</td><td colspan="1" valign="bottom" sides="tl" bgcolor="#f0f0f0" align="left">{_0}</td></tr></table>>][shape="none"];
-}
diff --git a/tests/mir-opt/dataflow.main.maybe_uninit.borrowck.dot b/tests/mir-opt/dataflow.main.maybe_uninit.borrowck.dot
new file mode 100644
index 00000000000..258404b8da7
--- /dev/null
+++ b/tests/mir-opt/dataflow.main.maybe_uninit.borrowck.dot
@@ -0,0 +1,6 @@
+digraph graph_for_def_id_0_3 {
+    graph[fontname="Courier, monospace"];
+    node[fontname="Courier, monospace"];
+    edge[fontname="Courier, monospace"];
+    bb_0[label=<<table border="1" cellborder="1" cellspacing="0" cellpadding="3" sides="rb"><tr><td colspan="3" sides="tl">bb0</td></tr><tr><td colspan="2" bgcolor="#a0a0a0" sides="tl">MIR</td><td bgcolor="#a0a0a0" sides="tl">STATE</td></tr><tr><td valign="bottom" sides="tl"  align="right"></td><td valign="bottom" sides="tl"  align="left">(on start)</td><td colspan="1" valign="bottom" sides="tl"  align="left">{_0}</td></tr><tr><td valign="top" sides="tl" bgcolor="#f0f0f0" align="right">0</td><td valign="top" sides="tl" bgcolor="#f0f0f0" align="left">_0 = const ()</td><td valign="top" sides="tl" bgcolor="#f0f0f0" align="left"><font color="red">-_0</font></td></tr><tr><td valign="top" sides="tl"  align="right">T</td><td valign="top" sides="tl"  align="left">return</td><td valign="top" sides="tl"  align="left"></td></tr><tr><td valign="bottom" sides="tl" bgcolor="#f0f0f0" align="right"></td><td valign="bottom" sides="tl" bgcolor="#f0f0f0" align="left">(on end)</td><td colspan="1" valign="bottom" sides="tl" bgcolor="#f0f0f0" align="left">{}</td></tr></table>>][shape="none"];
+}
diff --git a/tests/mir-opt/dataflow.rs b/tests/mir-opt/dataflow.rs
index 3a28f5d47b9..5ed3da4c531 100644
--- a/tests/mir-opt/dataflow.rs
+++ b/tests/mir-opt/dataflow.rs
@@ -2,5 +2,5 @@
 // Test graphviz dataflow output
 //@ compile-flags: -Z dump-mir=main -Z dump-mir-dataflow
 
-// EMIT_MIR dataflow.main.maybe_init.borrowck.dot
+// EMIT_MIR dataflow.main.maybe_uninit.borrowck.dot
 fn main() {}
diff --git a/tests/mir-opt/dont_reset_cast_kind_without_updating_operand.test.GVN.32bit.panic-abort.diff b/tests/mir-opt/dont_reset_cast_kind_without_updating_operand.test.GVN.32bit.panic-abort.diff
index 35eb4fbd106..25ffff619e6 100644
--- a/tests/mir-opt/dont_reset_cast_kind_without_updating_operand.test.GVN.32bit.panic-abort.diff
+++ b/tests/mir-opt/dont_reset_cast_kind_without_updating_operand.test.GVN.32bit.panic-abort.diff
@@ -59,7 +59,7 @@
                   scope 10 (inlined <std::alloc::Global as Allocator>::allocate) {
                   }
               }
-              scope 9 (inlined Layout::from_size_align_unchecked) {
+              scope 9 (inlined #[track_caller] Layout::from_size_align_unchecked) {
                   let mut _19: bool;
                   let _20: ();
                   let mut _21: std::ptr::Alignment;
diff --git a/tests/mir-opt/dont_reset_cast_kind_without_updating_operand.test.GVN.64bit.panic-abort.diff b/tests/mir-opt/dont_reset_cast_kind_without_updating_operand.test.GVN.64bit.panic-abort.diff
index 4427a5fcc7d..839b53e3b0b 100644
--- a/tests/mir-opt/dont_reset_cast_kind_without_updating_operand.test.GVN.64bit.panic-abort.diff
+++ b/tests/mir-opt/dont_reset_cast_kind_without_updating_operand.test.GVN.64bit.panic-abort.diff
@@ -59,7 +59,7 @@
                   scope 10 (inlined <std::alloc::Global as Allocator>::allocate) {
                   }
               }
-              scope 9 (inlined Layout::from_size_align_unchecked) {
+              scope 9 (inlined #[track_caller] Layout::from_size_align_unchecked) {
                   let mut _19: bool;
                   let _20: ();
                   let mut _21: std::ptr::Alignment;
diff --git a/tests/mir-opt/enum_opt.rs b/tests/mir-opt/enum_opt.rs
index e42be8ac06d..81390567c2b 100644
--- a/tests/mir-opt/enum_opt.rs
+++ b/tests/mir-opt/enum_opt.rs
@@ -3,8 +3,6 @@
 // EMIT_MIR_FOR_EACH_BIT_WIDTH
 //@ compile-flags: -Zunsound-mir-opts -Zdump-mir-exclude-alloc-bytes
 
-#![feature(arbitrary_enum_discriminant, repr128)]
-
 // Tests that an enum with a variant with no data gets correctly transformed.
 pub enum NoData {
     Large([u8; 8196]),
diff --git a/tests/mir-opt/gvn_repeat.repeat_local.GVN.diff b/tests/mir-opt/gvn_repeat.repeat_local.GVN.diff
new file mode 100644
index 00000000000..fd047825281
--- /dev/null
+++ b/tests/mir-opt/gvn_repeat.repeat_local.GVN.diff
@@ -0,0 +1,18 @@
+- // MIR for `repeat_local` before GVN
++ // MIR for `repeat_local` after GVN
+  
+  fn repeat_local(_1: usize, _2: usize, _3: i32) -> i32 {
+      let mut _0: i32;
+      let mut _4: [i32; 5];
+      let mut _5: &i32;
+  
+      bb0: {
+          _4 = [copy _3; 5];
+          _5 = &_4[_1];
+          _1 = copy _2;
+-         _0 = copy (*_5);
++         _0 = copy _3;
+          return;
+      }
+  }
+  
diff --git a/tests/mir-opt/gvn_repeat.repeat_place.GVN.diff b/tests/mir-opt/gvn_repeat.repeat_place.GVN.diff
new file mode 100644
index 00000000000..e490925bc11
--- /dev/null
+++ b/tests/mir-opt/gvn_repeat.repeat_place.GVN.diff
@@ -0,0 +1,17 @@
+- // MIR for `repeat_place` before GVN
++ // MIR for `repeat_place` after GVN
+  
+  fn repeat_place(_1: usize, _2: usize, _3: &i32) -> i32 {
+      let mut _0: i32;
+      let mut _4: [i32; 5];
+      let mut _5: &i32;
+  
+      bb0: {
+          _4 = [copy (*_3); 5];
+          _5 = &_4[_1];
+          _1 = copy _2;
+          _0 = copy (*_5);
+          return;
+      }
+  }
+  
diff --git a/tests/mir-opt/gvn_repeat.rs b/tests/mir-opt/gvn_repeat.rs
new file mode 100644
index 00000000000..bbbb2a7ccba
--- /dev/null
+++ b/tests/mir-opt/gvn_repeat.rs
@@ -0,0 +1,49 @@
+//@ test-mir-pass: GVN
+
+#![feature(custom_mir, core_intrinsics)]
+
+// Check that we do not introduce out-of-bounds access.
+
+use std::intrinsics::mir::*;
+
+// EMIT_MIR gvn_repeat.repeat_place.GVN.diff
+#[custom_mir(dialect = "runtime")]
+pub fn repeat_place(mut idx1: usize, idx2: usize, val: &i32) -> i32 {
+    // CHECK-LABEL: fn repeat_place(
+    // CHECK: let mut [[ELEM:.*]]: &i32;
+    // CHECK: _0 = copy (*[[ELEM]])
+    mir! {
+        let array;
+        let elem;
+        {
+            array = [*val; 5];
+            elem = &array[idx1];
+            idx1 = idx2;
+            RET = *elem;
+            Return()
+        }
+    }
+}
+
+// EMIT_MIR gvn_repeat.repeat_local.GVN.diff
+#[custom_mir(dialect = "runtime")]
+pub fn repeat_local(mut idx1: usize, idx2: usize, val: i32) -> i32 {
+    // CHECK-LABEL: fn repeat_local(
+    // CHECK: _0 = copy _3
+    mir! {
+        let array;
+        let elem;
+        {
+            array = [val; 5];
+            elem = &array[idx1];
+            idx1 = idx2;
+            RET = *elem;
+            Return()
+        }
+    }
+}
+
+fn main() {
+    assert_eq!(repeat_place(0, 5, &0), 0);
+    assert_eq!(repeat_local(0, 5, 0), 0);
+}
diff --git a/tests/mir-opt/inline/unchecked_shifts.rs b/tests/mir-opt/inline/unchecked_shifts.rs
index 3c4e73bf7ea..122f099da4b 100644
--- a/tests/mir-opt/inline/unchecked_shifts.rs
+++ b/tests/mir-opt/inline/unchecked_shifts.rs
@@ -11,7 +11,7 @@
 // EMIT_MIR unchecked_shifts.unchecked_shl_unsigned_smaller.PreCodegen.after.mir
 pub unsafe fn unchecked_shl_unsigned_smaller(a: u16, b: u32) -> u16 {
     // CHECK-LABEL: fn unchecked_shl_unsigned_smaller(
-    // CHECK: (inlined core::num::<impl u16>::unchecked_shl)
+    // CHECK: (inlined #[track_caller] core::num::<impl u16>::unchecked_shl)
     a.unchecked_shl(b)
 }
 
@@ -19,6 +19,6 @@ pub unsafe fn unchecked_shl_unsigned_smaller(a: u16, b: u32) -> u16 {
 // EMIT_MIR unchecked_shifts.unchecked_shr_signed_bigger.PreCodegen.after.mir
 pub unsafe fn unchecked_shr_signed_bigger(a: i64, b: u32) -> i64 {
     // CHECK-LABEL: fn unchecked_shr_signed_bigger(
-    // CHECK: (inlined core::num::<impl i64>::unchecked_shr)
+    // CHECK: (inlined #[track_caller] core::num::<impl i64>::unchecked_shr)
     a.unchecked_shr(b)
 }
diff --git a/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.Inline.panic-abort.diff b/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.Inline.panic-abort.diff
index 39ba480d203..813796657b2 100644
--- a/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.Inline.panic-abort.diff
+++ b/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.Inline.panic-abort.diff
@@ -7,7 +7,7 @@
       let mut _0: u16;
       let mut _3: u16;
       let mut _4: u32;
-+     scope 1 (inlined core::num::<impl u16>::unchecked_shl) {
++     scope 1 (inlined #[track_caller] core::num::<impl u16>::unchecked_shl) {
 +         let _5: ();
 +         scope 2 (inlined core::ub_checks::check_language_ub) {
 +             let mut _6: bool;
diff --git a/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.Inline.panic-unwind.diff b/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.Inline.panic-unwind.diff
index 5a758d35740..61fdb69f74b 100644
--- a/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.Inline.panic-unwind.diff
+++ b/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.Inline.panic-unwind.diff
@@ -7,7 +7,7 @@
       let mut _0: u16;
       let mut _3: u16;
       let mut _4: u32;
-+     scope 1 (inlined core::num::<impl u16>::unchecked_shl) {
++     scope 1 (inlined #[track_caller] core::num::<impl u16>::unchecked_shl) {
 +         let _5: ();
 +         scope 2 (inlined core::ub_checks::check_language_ub) {
 +             let mut _6: bool;
diff --git a/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.PreCodegen.after.panic-abort.mir b/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.PreCodegen.after.panic-abort.mir
index 611273ab08d..0fc7c4b7947 100644
--- a/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.PreCodegen.after.panic-abort.mir
+++ b/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.PreCodegen.after.panic-abort.mir
@@ -4,7 +4,7 @@ fn unchecked_shl_unsigned_smaller(_1: u16, _2: u32) -> u16 {
     debug a => _1;
     debug b => _2;
     let mut _0: u16;
-    scope 1 (inlined core::num::<impl u16>::unchecked_shl) {
+    scope 1 (inlined #[track_caller] core::num::<impl u16>::unchecked_shl) {
         scope 2 (inlined core::ub_checks::check_language_ub) {
             scope 3 (inlined core::ub_checks::check_language_ub::runtime) {
             }
diff --git a/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.PreCodegen.after.panic-unwind.mir
index 611273ab08d..0fc7c4b7947 100644
--- a/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.PreCodegen.after.panic-unwind.mir
+++ b/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.PreCodegen.after.panic-unwind.mir
@@ -4,7 +4,7 @@ fn unchecked_shl_unsigned_smaller(_1: u16, _2: u32) -> u16 {
     debug a => _1;
     debug b => _2;
     let mut _0: u16;
-    scope 1 (inlined core::num::<impl u16>::unchecked_shl) {
+    scope 1 (inlined #[track_caller] core::num::<impl u16>::unchecked_shl) {
         scope 2 (inlined core::ub_checks::check_language_ub) {
             scope 3 (inlined core::ub_checks::check_language_ub::runtime) {
             }
diff --git a/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_bigger.Inline.panic-abort.diff b/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_bigger.Inline.panic-abort.diff
index a0caf141f2d..5ea99e8301b 100644
--- a/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_bigger.Inline.panic-abort.diff
+++ b/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_bigger.Inline.panic-abort.diff
@@ -7,7 +7,7 @@
       let mut _0: i64;
       let mut _3: i64;
       let mut _4: u32;
-+     scope 1 (inlined core::num::<impl i64>::unchecked_shr) {
++     scope 1 (inlined #[track_caller] core::num::<impl i64>::unchecked_shr) {
 +         let _5: ();
 +         scope 2 (inlined core::ub_checks::check_language_ub) {
 +             let mut _6: bool;
diff --git a/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_bigger.Inline.panic-unwind.diff b/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_bigger.Inline.panic-unwind.diff
index 633089e7b2a..b13531ab148 100644
--- a/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_bigger.Inline.panic-unwind.diff
+++ b/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_bigger.Inline.panic-unwind.diff
@@ -7,7 +7,7 @@
       let mut _0: i64;
       let mut _3: i64;
       let mut _4: u32;
-+     scope 1 (inlined core::num::<impl i64>::unchecked_shr) {
++     scope 1 (inlined #[track_caller] core::num::<impl i64>::unchecked_shr) {
 +         let _5: ();
 +         scope 2 (inlined core::ub_checks::check_language_ub) {
 +             let mut _6: bool;
diff --git a/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_bigger.PreCodegen.after.panic-abort.mir b/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_bigger.PreCodegen.after.panic-abort.mir
index f4ddd0bca04..bef7fa7b1df 100644
--- a/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_bigger.PreCodegen.after.panic-abort.mir
+++ b/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_bigger.PreCodegen.after.panic-abort.mir
@@ -4,7 +4,7 @@ fn unchecked_shr_signed_bigger(_1: i64, _2: u32) -> i64 {
     debug a => _1;
     debug b => _2;
     let mut _0: i64;
-    scope 1 (inlined core::num::<impl i64>::unchecked_shr) {
+    scope 1 (inlined #[track_caller] core::num::<impl i64>::unchecked_shr) {
         scope 2 (inlined core::ub_checks::check_language_ub) {
             scope 3 (inlined core::ub_checks::check_language_ub::runtime) {
             }
diff --git a/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_bigger.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_bigger.PreCodegen.after.panic-unwind.mir
index f4ddd0bca04..bef7fa7b1df 100644
--- a/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_bigger.PreCodegen.after.panic-unwind.mir
+++ b/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_bigger.PreCodegen.after.panic-unwind.mir
@@ -4,7 +4,7 @@ fn unchecked_shr_signed_bigger(_1: i64, _2: u32) -> i64 {
     debug a => _1;
     debug b => _2;
     let mut _0: i64;
-    scope 1 (inlined core::num::<impl i64>::unchecked_shr) {
+    scope 1 (inlined #[track_caller] core::num::<impl i64>::unchecked_shr) {
         scope 2 (inlined core::ub_checks::check_language_ub) {
             scope 3 (inlined core::ub_checks::check_language_ub::runtime) {
             }
diff --git a/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-abort.diff b/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-abort.diff
index a5986a4315a..0119dd79970 100644
--- a/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-abort.diff
+++ b/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-abort.diff
@@ -9,7 +9,7 @@
 +         let mut _3: isize;
 +         scope 2 {
 +         }
-+         scope 3 (inlined unreachable_unchecked) {
++         scope 3 (inlined #[track_caller] unreachable_unchecked) {
 +             let _4: ();
 +             scope 4 (inlined core::ub_checks::check_language_ub) {
 +                 let mut _5: bool;
diff --git a/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-unwind.diff b/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-unwind.diff
index 12b03a6b6d9..d6a5eab1d6e 100644
--- a/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-unwind.diff
+++ b/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-unwind.diff
@@ -9,7 +9,7 @@
 +         let mut _3: isize;
 +         scope 2 {
 +         }
-+         scope 3 (inlined unreachable_unchecked) {
++         scope 3 (inlined #[track_caller] unreachable_unchecked) {
 +             let _4: ();
 +             scope 4 (inlined core::ub_checks::check_language_ub) {
 +                 let mut _5: bool;
diff --git a/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.panic-abort.mir b/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.panic-abort.mir
index 66ab5e1b962..b7b892c177c 100644
--- a/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.panic-abort.mir
+++ b/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.panic-abort.mir
@@ -7,7 +7,7 @@ fn unwrap_unchecked(_1: Option<T>) -> T {
         let mut _2: isize;
         scope 2 {
         }
-        scope 3 (inlined unreachable_unchecked) {
+        scope 3 (inlined #[track_caller] unreachable_unchecked) {
             scope 4 (inlined core::ub_checks::check_language_ub) {
                 scope 5 (inlined core::ub_checks::check_language_ub::runtime) {
                 }
diff --git a/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.panic-unwind.mir
index 66ab5e1b962..b7b892c177c 100644
--- a/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.panic-unwind.mir
+++ b/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.panic-unwind.mir
@@ -7,7 +7,7 @@ fn unwrap_unchecked(_1: Option<T>) -> T {
         let mut _2: isize;
         scope 2 {
         }
-        scope 3 (inlined unreachable_unchecked) {
+        scope 3 (inlined #[track_caller] unreachable_unchecked) {
             scope 4 (inlined core::ub_checks::check_language_ub) {
                 scope 5 (inlined core::ub_checks::check_language_ub::runtime) {
                 }
diff --git a/tests/mir-opt/instsimplify/ub_check.unwrap_unchecked.InstSimplify-after-simplifycfg.diff b/tests/mir-opt/instsimplify/ub_check.unwrap_unchecked.InstSimplify-after-simplifycfg.diff
index 82353a2d540..2c9071e6e20 100644
--- a/tests/mir-opt/instsimplify/ub_check.unwrap_unchecked.InstSimplify-after-simplifycfg.diff
+++ b/tests/mir-opt/instsimplify/ub_check.unwrap_unchecked.InstSimplify-after-simplifycfg.diff
@@ -9,7 +9,7 @@
           let mut _3: isize;
           scope 2 {
           }
-          scope 3 (inlined unreachable_unchecked) {
+          scope 3 (inlined #[track_caller] unreachable_unchecked) {
               let _4: ();
               scope 4 (inlined core::ub_checks::check_language_ub) {
                   let mut _5: bool;
diff --git a/tests/mir-opt/lower_intrinsics.rs b/tests/mir-opt/lower_intrinsics.rs
index 4e000b05a4b..1e4f2024194 100644
--- a/tests/mir-opt/lower_intrinsics.rs
+++ b/tests/mir-opt/lower_intrinsics.rs
@@ -263,3 +263,24 @@ pub fn get_metadata(a: *const i32, b: *const [u8], c: *const dyn std::fmt::Debug
     let _usize = ptr_metadata(b);
     let _vtable = ptr_metadata(c);
 }
+
+// EMIT_MIR lower_intrinsics.slice_get.LowerIntrinsics.diff
+pub unsafe fn slice_get<'a, 'b>(
+    r: &'a [i8],
+    rm: &'b mut [i16],
+    p: *const [i32],
+    pm: *mut [i64],
+    i: usize,
+) -> (&'a i8, &'b mut i16, *const i32, *mut i64) {
+    use std::intrinsics::slice_get_unchecked;
+    // CHECK: = &(*_{{[0-9]+}})[_{{[0-9]+}}]
+    // CHECK: = &mut (*_{{[0-9]+}})[_{{[0-9]+}}]
+    // CHECK: = &raw const (*_{{[0-9]+}})[_{{[0-9]+}}]
+    // CHECK: = &raw mut (*_{{[0-9]+}})[_{{[0-9]+}}]
+    (
+        slice_get_unchecked(r, i),
+        slice_get_unchecked(rm, i),
+        slice_get_unchecked(p, i),
+        slice_get_unchecked(pm, i),
+    )
+}
diff --git a/tests/mir-opt/lower_intrinsics.slice_get.LowerIntrinsics.panic-abort.diff b/tests/mir-opt/lower_intrinsics.slice_get.LowerIntrinsics.panic-abort.diff
new file mode 100644
index 00000000000..d18bdc43168
--- /dev/null
+++ b/tests/mir-opt/lower_intrinsics.slice_get.LowerIntrinsics.panic-abort.diff
@@ -0,0 +1,85 @@
+- // MIR for `slice_get` before LowerIntrinsics
++ // MIR for `slice_get` after LowerIntrinsics
+  
+  fn slice_get(_1: &[i8], _2: &mut [i16], _3: *const [i32], _4: *mut [i64], _5: usize) -> (&i8, &mut i16, *const i32, *mut i64) {
+      debug r => _1;
+      debug rm => _2;
+      debug p => _3;
+      debug pm => _4;
+      debug i => _5;
+      let mut _0: (&i8, &mut i16, *const i32, *mut i64);
+      let mut _6: &i8;
+      let mut _7: &[i8];
+      let mut _8: usize;
+      let mut _9: &mut i16;
+      let mut _10: &mut [i16];
+      let mut _11: usize;
+      let mut _12: *const i32;
+      let mut _13: *const [i32];
+      let mut _14: usize;
+      let mut _15: *mut i64;
+      let mut _16: *mut [i64];
+      let mut _17: usize;
+  
+      bb0: {
+          StorageLive(_6);
+          StorageLive(_7);
+          _7 = copy _1;
+          StorageLive(_8);
+          _8 = copy _5;
+-         _6 = slice_get_unchecked::<&i8, &[i8], i8>(move _7, move _8) -> [return: bb1, unwind unreachable];
++         _6 = &(*_7)[_8];
++         goto -> bb1;
+      }
+  
+      bb1: {
+          StorageDead(_8);
+          StorageDead(_7);
+          StorageLive(_9);
+          StorageLive(_10);
+          _10 = move _2;
+          StorageLive(_11);
+          _11 = copy _5;
+-         _9 = slice_get_unchecked::<&mut i16, &mut [i16], i16>(move _10, move _11) -> [return: bb2, unwind unreachable];
++         _9 = &mut (*_10)[_11];
++         goto -> bb2;
+      }
+  
+      bb2: {
+          StorageDead(_11);
+          StorageDead(_10);
+          StorageLive(_12);
+          StorageLive(_13);
+          _13 = copy _3;
+          StorageLive(_14);
+          _14 = copy _5;
+-         _12 = slice_get_unchecked::<*const i32, *const [i32], i32>(move _13, move _14) -> [return: bb3, unwind unreachable];
++         _12 = &raw const (*_13)[_14];
++         goto -> bb3;
+      }
+  
+      bb3: {
+          StorageDead(_14);
+          StorageDead(_13);
+          StorageLive(_15);
+          StorageLive(_16);
+          _16 = copy _4;
+          StorageLive(_17);
+          _17 = copy _5;
+-         _15 = slice_get_unchecked::<*mut i64, *mut [i64], i64>(move _16, move _17) -> [return: bb4, unwind unreachable];
++         _15 = &raw mut (*_16)[_17];
++         goto -> bb4;
+      }
+  
+      bb4: {
+          StorageDead(_17);
+          StorageDead(_16);
+          _0 = (move _6, move _9, move _12, move _15);
+          StorageDead(_15);
+          StorageDead(_12);
+          StorageDead(_9);
+          StorageDead(_6);
+          return;
+      }
+  }
+  
diff --git a/tests/mir-opt/lower_intrinsics.slice_get.LowerIntrinsics.panic-unwind.diff b/tests/mir-opt/lower_intrinsics.slice_get.LowerIntrinsics.panic-unwind.diff
new file mode 100644
index 00000000000..d18bdc43168
--- /dev/null
+++ b/tests/mir-opt/lower_intrinsics.slice_get.LowerIntrinsics.panic-unwind.diff
@@ -0,0 +1,85 @@
+- // MIR for `slice_get` before LowerIntrinsics
++ // MIR for `slice_get` after LowerIntrinsics
+  
+  fn slice_get(_1: &[i8], _2: &mut [i16], _3: *const [i32], _4: *mut [i64], _5: usize) -> (&i8, &mut i16, *const i32, *mut i64) {
+      debug r => _1;
+      debug rm => _2;
+      debug p => _3;
+      debug pm => _4;
+      debug i => _5;
+      let mut _0: (&i8, &mut i16, *const i32, *mut i64);
+      let mut _6: &i8;
+      let mut _7: &[i8];
+      let mut _8: usize;
+      let mut _9: &mut i16;
+      let mut _10: &mut [i16];
+      let mut _11: usize;
+      let mut _12: *const i32;
+      let mut _13: *const [i32];
+      let mut _14: usize;
+      let mut _15: *mut i64;
+      let mut _16: *mut [i64];
+      let mut _17: usize;
+  
+      bb0: {
+          StorageLive(_6);
+          StorageLive(_7);
+          _7 = copy _1;
+          StorageLive(_8);
+          _8 = copy _5;
+-         _6 = slice_get_unchecked::<&i8, &[i8], i8>(move _7, move _8) -> [return: bb1, unwind unreachable];
++         _6 = &(*_7)[_8];
++         goto -> bb1;
+      }
+  
+      bb1: {
+          StorageDead(_8);
+          StorageDead(_7);
+          StorageLive(_9);
+          StorageLive(_10);
+          _10 = move _2;
+          StorageLive(_11);
+          _11 = copy _5;
+-         _9 = slice_get_unchecked::<&mut i16, &mut [i16], i16>(move _10, move _11) -> [return: bb2, unwind unreachable];
++         _9 = &mut (*_10)[_11];
++         goto -> bb2;
+      }
+  
+      bb2: {
+          StorageDead(_11);
+          StorageDead(_10);
+          StorageLive(_12);
+          StorageLive(_13);
+          _13 = copy _3;
+          StorageLive(_14);
+          _14 = copy _5;
+-         _12 = slice_get_unchecked::<*const i32, *const [i32], i32>(move _13, move _14) -> [return: bb3, unwind unreachable];
++         _12 = &raw const (*_13)[_14];
++         goto -> bb3;
+      }
+  
+      bb3: {
+          StorageDead(_14);
+          StorageDead(_13);
+          StorageLive(_15);
+          StorageLive(_16);
+          _16 = copy _4;
+          StorageLive(_17);
+          _17 = copy _5;
+-         _15 = slice_get_unchecked::<*mut i64, *mut [i64], i64>(move _16, move _17) -> [return: bb4, unwind unreachable];
++         _15 = &raw mut (*_16)[_17];
++         goto -> bb4;
+      }
+  
+      bb4: {
+          StorageDead(_17);
+          StorageDead(_16);
+          _0 = (move _6, move _9, move _12, move _15);
+          StorageDead(_15);
+          StorageDead(_12);
+          StorageDead(_9);
+          StorageDead(_6);
+          return;
+      }
+  }
+  
diff --git a/tests/mir-opt/matches_reduce_branches.match_non_int_failed.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.match_non_int_failed.MatchBranchSimplification.diff
new file mode 100644
index 00000000000..81e900a34c0
--- /dev/null
+++ b/tests/mir-opt/matches_reduce_branches.match_non_int_failed.MatchBranchSimplification.diff
@@ -0,0 +1,29 @@
+- // MIR for `match_non_int_failed` before MatchBranchSimplification
++ // MIR for `match_non_int_failed` after MatchBranchSimplification
+  
+  fn match_non_int_failed(_1: char) -> u8 {
+      let mut _0: u8;
+  
+      bb0: {
+          switchInt(copy _1) -> [97: bb1, 98: bb2, otherwise: bb3];
+      }
+  
+      bb1: {
+          _0 = const 97_u8;
+          goto -> bb4;
+      }
+  
+      bb2: {
+          _0 = const 98_u8;
+          goto -> bb4;
+      }
+  
+      bb3: {
+          unreachable;
+      }
+  
+      bb4: {
+          return;
+      }
+  }
+  
diff --git a/tests/mir-opt/matches_reduce_branches.rs b/tests/mir-opt/matches_reduce_branches.rs
index 3372ae2f2a6..89ef3bfb308 100644
--- a/tests/mir-opt/matches_reduce_branches.rs
+++ b/tests/mir-opt/matches_reduce_branches.rs
@@ -1,6 +1,5 @@
 //@ test-mir-pass: MatchBranchSimplification
 
-#![feature(repr128)]
 #![feature(core_intrinsics)]
 #![feature(custom_mir)]
 #![allow(non_camel_case_types)]
@@ -628,6 +627,37 @@ fn match_i128_u128(i: EnumAi128) -> u128 {
     }
 }
 
+// EMIT_MIR matches_reduce_branches.match_non_int_failed.MatchBranchSimplification.diff
+#[custom_mir(dialect = "runtime")]
+fn match_non_int_failed(i: char) -> u8 {
+    // CHECK-LABEL: fn match_non_int_failed(
+    // CHECK: switchInt
+    // CHECK: return
+    mir! {
+        {
+            match i {
+                'a' => bb1,
+                'b' => bb2,
+                _ => unreachable_bb,
+            }
+        }
+        bb1 = {
+            RET = 97;
+            Goto(ret)
+        }
+        bb2 = {
+            RET = 98;
+            Goto(ret)
+        }
+        unreachable_bb = {
+            Unreachable()
+        }
+        ret = {
+            Return()
+        }
+    }
+}
+
 fn main() {
     let _ = foo(None);
     let _ = foo(Some(()));
@@ -665,4 +695,5 @@ fn main() {
     let _ = match_i128_u128(EnumAi128::A);
 
     let _ = my_is_some(None);
+    let _ = match_non_int_failed('a');
 }
diff --git a/tests/mir-opt/pre-codegen/checked_ops.checked_shl.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/checked_ops.checked_shl.PreCodegen.after.panic-abort.mir
index a9dd8886577..18eeb8e4d3b 100644
--- a/tests/mir-opt/pre-codegen/checked_ops.checked_shl.PreCodegen.after.panic-abort.mir
+++ b/tests/mir-opt/pre-codegen/checked_ops.checked_shl.PreCodegen.after.panic-abort.mir
@@ -7,7 +7,7 @@ fn checked_shl(_1: u32, _2: u32) -> Option<u32> {
     scope 1 (inlined core::num::<impl u32>::checked_shl) {
         let mut _3: bool;
         let mut _4: u32;
-        scope 2 (inlined core::num::<impl u32>::unchecked_shl) {
+        scope 2 (inlined #[track_caller] core::num::<impl u32>::unchecked_shl) {
             scope 3 (inlined core::ub_checks::check_language_ub) {
                 scope 4 (inlined core::ub_checks::check_language_ub::runtime) {
                 }
diff --git a/tests/mir-opt/pre-codegen/checked_ops.checked_shl.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/checked_ops.checked_shl.PreCodegen.after.panic-unwind.mir
index a9dd8886577..18eeb8e4d3b 100644
--- a/tests/mir-opt/pre-codegen/checked_ops.checked_shl.PreCodegen.after.panic-unwind.mir
+++ b/tests/mir-opt/pre-codegen/checked_ops.checked_shl.PreCodegen.after.panic-unwind.mir
@@ -7,7 +7,7 @@ fn checked_shl(_1: u32, _2: u32) -> Option<u32> {
     scope 1 (inlined core::num::<impl u32>::checked_shl) {
         let mut _3: bool;
         let mut _4: u32;
-        scope 2 (inlined core::num::<impl u32>::unchecked_shl) {
+        scope 2 (inlined #[track_caller] core::num::<impl u32>::unchecked_shl) {
             scope 3 (inlined core::ub_checks::check_language_ub) {
                 scope 4 (inlined core::ub_checks::check_language_ub::runtime) {
                 }
diff --git a/tests/mir-opt/pre-codegen/duplicate_switch_targets.ub_if_b.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/duplicate_switch_targets.ub_if_b.PreCodegen.after.mir
index 518fedffc16..8a6732d5f74 100644
--- a/tests/mir-opt/pre-codegen/duplicate_switch_targets.ub_if_b.PreCodegen.after.mir
+++ b/tests/mir-opt/pre-codegen/duplicate_switch_targets.ub_if_b.PreCodegen.after.mir
@@ -4,7 +4,7 @@ fn ub_if_b(_1: Thing) -> Thing {
     debug t => _1;
     let mut _0: Thing;
     let mut _2: isize;
-    scope 1 (inlined unreachable_unchecked) {
+    scope 1 (inlined #[track_caller] unreachable_unchecked) {
         scope 2 (inlined core::ub_checks::check_language_ub) {
             scope 3 (inlined core::ub_checks::check_language_ub::runtime) {
             }
diff --git a/tests/mir-opt/pre-codegen/loops.int_range.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/loops.int_range.PreCodegen.after.mir
index 1f9c464d633..154cbd3791c 100644
--- a/tests/mir-opt/pre-codegen/loops.int_range.PreCodegen.after.mir
+++ b/tests/mir-opt/pre-codegen/loops.int_range.PreCodegen.after.mir
@@ -29,7 +29,7 @@ fn int_range(_1: usize, _2: usize) -> () {
                     scope 8 (inlined <usize as Step>::forward_unchecked) {
                         debug start => _11;
                         debug n => const 1_usize;
-                        scope 9 (inlined core::num::<impl usize>::unchecked_add) {
+                        scope 9 (inlined #[track_caller] core::num::<impl usize>::unchecked_add) {
                             debug self => _11;
                             debug rhs => const 1_usize;
                             scope 10 (inlined core::ub_checks::check_language_ub) {
diff --git a/tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_fat.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_fat.PreCodegen.after.panic-abort.mir
index 5faa1e210cf..a6dad00bbdb 100644
--- a/tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_fat.PreCodegen.after.panic-abort.mir
+++ b/tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_fat.PreCodegen.after.panic-abort.mir
@@ -4,12 +4,12 @@ fn demo_byte_add_fat(_1: *const [u32], _2: usize) -> *const [u32] {
     debug p => _1;
     debug n => _2;
     let mut _0: *const [u32];
-    scope 1 (inlined std::ptr::const_ptr::<impl *const [u32]>::byte_add) {
+    scope 1 (inlined #[track_caller] std::ptr::const_ptr::<impl *const [u32]>::byte_add) {
         let mut _3: *const u8;
         let mut _4: *const u8;
         scope 2 (inlined std::ptr::const_ptr::<impl *const [u32]>::cast::<u8>) {
         }
-        scope 3 (inlined std::ptr::const_ptr::<impl *const u8>::add) {
+        scope 3 (inlined #[track_caller] std::ptr::const_ptr::<impl *const u8>::add) {
         }
         scope 4 (inlined std::ptr::const_ptr::<impl *const u8>::with_metadata_of::<[u32]>) {
             let mut _5: usize;
diff --git a/tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_fat.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_fat.PreCodegen.after.panic-unwind.mir
index 5faa1e210cf..a6dad00bbdb 100644
--- a/tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_fat.PreCodegen.after.panic-unwind.mir
+++ b/tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_fat.PreCodegen.after.panic-unwind.mir
@@ -4,12 +4,12 @@ fn demo_byte_add_fat(_1: *const [u32], _2: usize) -> *const [u32] {
     debug p => _1;
     debug n => _2;
     let mut _0: *const [u32];
-    scope 1 (inlined std::ptr::const_ptr::<impl *const [u32]>::byte_add) {
+    scope 1 (inlined #[track_caller] std::ptr::const_ptr::<impl *const [u32]>::byte_add) {
         let mut _3: *const u8;
         let mut _4: *const u8;
         scope 2 (inlined std::ptr::const_ptr::<impl *const [u32]>::cast::<u8>) {
         }
-        scope 3 (inlined std::ptr::const_ptr::<impl *const u8>::add) {
+        scope 3 (inlined #[track_caller] std::ptr::const_ptr::<impl *const u8>::add) {
         }
         scope 4 (inlined std::ptr::const_ptr::<impl *const u8>::with_metadata_of::<[u32]>) {
             let mut _5: usize;
diff --git a/tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_thin.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_thin.PreCodegen.after.panic-abort.mir
index 9429785045a..cb7f1565746 100644
--- a/tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_thin.PreCodegen.after.panic-abort.mir
+++ b/tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_thin.PreCodegen.after.panic-abort.mir
@@ -4,12 +4,12 @@ fn demo_byte_add_thin(_1: *const u32, _2: usize) -> *const u32 {
     debug p => _1;
     debug n => _2;
     let mut _0: *const u32;
-    scope 1 (inlined std::ptr::const_ptr::<impl *const u32>::byte_add) {
+    scope 1 (inlined #[track_caller] std::ptr::const_ptr::<impl *const u32>::byte_add) {
         let mut _3: *const u8;
         let mut _4: *const u8;
         scope 2 (inlined std::ptr::const_ptr::<impl *const u32>::cast::<u8>) {
         }
-        scope 3 (inlined std::ptr::const_ptr::<impl *const u8>::add) {
+        scope 3 (inlined #[track_caller] std::ptr::const_ptr::<impl *const u8>::add) {
         }
         scope 4 (inlined std::ptr::const_ptr::<impl *const u8>::with_metadata_of::<u32>) {
             scope 5 (inlined std::ptr::metadata::<u32>) {
diff --git a/tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_thin.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_thin.PreCodegen.after.panic-unwind.mir
index 9429785045a..cb7f1565746 100644
--- a/tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_thin.PreCodegen.after.panic-unwind.mir
+++ b/tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_thin.PreCodegen.after.panic-unwind.mir
@@ -4,12 +4,12 @@ fn demo_byte_add_thin(_1: *const u32, _2: usize) -> *const u32 {
     debug p => _1;
     debug n => _2;
     let mut _0: *const u32;
-    scope 1 (inlined std::ptr::const_ptr::<impl *const u32>::byte_add) {
+    scope 1 (inlined #[track_caller] std::ptr::const_ptr::<impl *const u32>::byte_add) {
         let mut _3: *const u8;
         let mut _4: *const u8;
         scope 2 (inlined std::ptr::const_ptr::<impl *const u32>::cast::<u8>) {
         }
-        scope 3 (inlined std::ptr::const_ptr::<impl *const u8>::add) {
+        scope 3 (inlined #[track_caller] std::ptr::const_ptr::<impl *const u8>::add) {
         }
         scope 4 (inlined std::ptr::const_ptr::<impl *const u8>::with_metadata_of::<u32>) {
             scope 5 (inlined std::ptr::metadata::<u32>) {
diff --git a/tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-abort.mir
index 0aa37203c1b..dfe618612ab 100644
--- a/tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-abort.mir
+++ b/tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-abort.mir
@@ -24,7 +24,7 @@ fn forward_loop(_1: u32, _2: u32, _3: impl Fn(u32)) -> () {
                 let mut _8: u32;
                 scope 6 {
                     scope 8 (inlined <u32 as Step>::forward_unchecked) {
-                        scope 9 (inlined core::num::<impl u32>::unchecked_add) {
+                        scope 9 (inlined #[track_caller] core::num::<impl u32>::unchecked_add) {
                             scope 10 (inlined core::ub_checks::check_language_ub) {
                                 scope 11 (inlined core::ub_checks::check_language_ub::runtime) {
                                 }
diff --git a/tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-unwind.mir
index 699d8bc8fea..e0fcfcaffc5 100644
--- a/tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-unwind.mir
+++ b/tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-unwind.mir
@@ -24,7 +24,7 @@ fn forward_loop(_1: u32, _2: u32, _3: impl Fn(u32)) -> () {
                 let mut _8: u32;
                 scope 6 {
                     scope 8 (inlined <u32 as Step>::forward_unchecked) {
-                        scope 9 (inlined core::num::<impl u32>::unchecked_add) {
+                        scope 9 (inlined #[track_caller] core::num::<impl u32>::unchecked_add) {
                             scope 10 (inlined core::ub_checks::check_language_ub) {
                                 scope 11 (inlined core::ub_checks::check_language_ub::runtime) {
                                 }
diff --git a/tests/mir-opt/pre-codegen/range_iter.range_iter_next.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/range_iter.range_iter_next.PreCodegen.after.panic-abort.mir
index f3033d4a2fa..1f82fc59ac2 100644
--- a/tests/mir-opt/pre-codegen/range_iter.range_iter_next.PreCodegen.after.panic-abort.mir
+++ b/tests/mir-opt/pre-codegen/range_iter.range_iter_next.PreCodegen.after.panic-abort.mir
@@ -10,7 +10,7 @@ fn range_iter_next(_1: &mut std::ops::Range<u32>) -> Option<u32> {
             let mut _6: u32;
             scope 3 {
                 scope 5 (inlined <u32 as Step>::forward_unchecked) {
-                    scope 6 (inlined core::num::<impl u32>::unchecked_add) {
+                    scope 6 (inlined #[track_caller] core::num::<impl u32>::unchecked_add) {
                         scope 7 (inlined core::ub_checks::check_language_ub) {
                             scope 8 (inlined core::ub_checks::check_language_ub::runtime) {
                             }
diff --git a/tests/mir-opt/pre-codegen/range_iter.range_iter_next.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/range_iter.range_iter_next.PreCodegen.after.panic-unwind.mir
index f3033d4a2fa..1f82fc59ac2 100644
--- a/tests/mir-opt/pre-codegen/range_iter.range_iter_next.PreCodegen.after.panic-unwind.mir
+++ b/tests/mir-opt/pre-codegen/range_iter.range_iter_next.PreCodegen.after.panic-unwind.mir
@@ -10,7 +10,7 @@ fn range_iter_next(_1: &mut std::ops::Range<u32>) -> Option<u32> {
             let mut _6: u32;
             scope 3 {
                 scope 5 (inlined <u32 as Step>::forward_unchecked) {
-                    scope 6 (inlined core::num::<impl u32>::unchecked_add) {
+                    scope 6 (inlined #[track_caller] core::num::<impl u32>::unchecked_add) {
                         scope 7 (inlined core::ub_checks::check_language_ub) {
                             scope 8 (inlined core::ub_checks::check_language_ub::runtime) {
                             }
diff --git a/tests/mir-opt/pre-codegen/slice_index.slice_get_mut_usize.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_index.slice_get_mut_usize.PreCodegen.after.panic-abort.mir
index ec67193bc79..d1b1e3d7dd7 100644
--- a/tests/mir-opt/pre-codegen/slice_index.slice_get_mut_usize.PreCodegen.after.panic-abort.mir
+++ b/tests/mir-opt/pre-codegen/slice_index.slice_get_mut_usize.PreCodegen.after.panic-abort.mir
@@ -8,19 +8,11 @@ fn slice_get_mut_usize(_1: &mut [u32], _2: usize) -> Option<&mut u32> {
         scope 2 (inlined <usize as SliceIndex<[u32]>>::get_mut) {
             let mut _3: usize;
             let mut _4: bool;
-            let mut _5: *mut [u32];
-            let mut _7: *mut u32;
-            let mut _8: &mut u32;
-            scope 3 (inlined core::slice::index::get_mut_noubcheck::<u32>) {
-                let _6: *mut u32;
-                scope 4 {
-                }
-            }
+            let mut _5: &mut u32;
         }
     }
 
     bb0: {
-        StorageLive(_8);
         StorageLive(_4);
         StorageLive(_3);
         _3 = PtrMetadata(copy _1);
@@ -36,23 +28,15 @@ fn slice_get_mut_usize(_1: &mut [u32], _2: usize) -> Option<&mut u32> {
 
     bb2: {
         StorageDead(_3);
-        StorageLive(_7);
         StorageLive(_5);
-        _5 = &raw mut (*_1);
-        StorageLive(_6);
-        _6 = copy _5 as *mut u32 (PtrToPtr);
-        _7 = Offset(copy _6, copy _2);
-        StorageDead(_6);
+        _5 = &mut (*_1)[_2];
+        _0 = Option::<&mut u32>::Some(move _5);
         StorageDead(_5);
-        _8 = &mut (*_7);
-        _0 = Option::<&mut u32>::Some(copy _8);
-        StorageDead(_7);
         goto -> bb3;
     }
 
     bb3: {
         StorageDead(_4);
-        StorageDead(_8);
         return;
     }
 }
diff --git a/tests/mir-opt/pre-codegen/slice_index.slice_get_mut_usize.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_index.slice_get_mut_usize.PreCodegen.after.panic-unwind.mir
index ec67193bc79..d1b1e3d7dd7 100644
--- a/tests/mir-opt/pre-codegen/slice_index.slice_get_mut_usize.PreCodegen.after.panic-unwind.mir
+++ b/tests/mir-opt/pre-codegen/slice_index.slice_get_mut_usize.PreCodegen.after.panic-unwind.mir
@@ -8,19 +8,11 @@ fn slice_get_mut_usize(_1: &mut [u32], _2: usize) -> Option<&mut u32> {
         scope 2 (inlined <usize as SliceIndex<[u32]>>::get_mut) {
             let mut _3: usize;
             let mut _4: bool;
-            let mut _5: *mut [u32];
-            let mut _7: *mut u32;
-            let mut _8: &mut u32;
-            scope 3 (inlined core::slice::index::get_mut_noubcheck::<u32>) {
-                let _6: *mut u32;
-                scope 4 {
-                }
-            }
+            let mut _5: &mut u32;
         }
     }
 
     bb0: {
-        StorageLive(_8);
         StorageLive(_4);
         StorageLive(_3);
         _3 = PtrMetadata(copy _1);
@@ -36,23 +28,15 @@ fn slice_get_mut_usize(_1: &mut [u32], _2: usize) -> Option<&mut u32> {
 
     bb2: {
         StorageDead(_3);
-        StorageLive(_7);
         StorageLive(_5);
-        _5 = &raw mut (*_1);
-        StorageLive(_6);
-        _6 = copy _5 as *mut u32 (PtrToPtr);
-        _7 = Offset(copy _6, copy _2);
-        StorageDead(_6);
+        _5 = &mut (*_1)[_2];
+        _0 = Option::<&mut u32>::Some(move _5);
         StorageDead(_5);
-        _8 = &mut (*_7);
-        _0 = Option::<&mut u32>::Some(copy _8);
-        StorageDead(_7);
         goto -> bb3;
     }
 
     bb3: {
         StorageDead(_4);
-        StorageDead(_8);
         return;
     }
 }
diff --git a/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-abort.mir
index 220e881f866..6fb1637a6e0 100644
--- a/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-abort.mir
+++ b/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-abort.mir
@@ -6,21 +6,19 @@ fn slice_get_unchecked_mut_range(_1: &mut [u32], _2: std::ops::Range<usize>) ->
     let mut _0: &mut [u32];
     let mut _3: usize;
     let mut _4: usize;
-    scope 1 (inlined core::slice::<impl [u32]>::get_unchecked_mut::<std::ops::Range<usize>>) {
+    scope 1 (inlined #[track_caller] core::slice::<impl [u32]>::get_unchecked_mut::<std::ops::Range<usize>>) {
         let mut _5: *mut [u32];
         let mut _11: *mut [u32];
-        scope 2 (inlined <std::ops::Range<usize> as SliceIndex<[u32]>>::get_unchecked_mut) {
+        scope 2 (inlined #[track_caller] <std::ops::Range<usize> as SliceIndex<[u32]>>::get_unchecked_mut) {
             let mut _6: usize;
             let _7: ();
             let _8: usize;
             scope 3 {
                 scope 6 (inlined core::slice::index::get_offset_len_mut_noubcheck::<u32>) {
-                    let _10: *mut u32;
+                    let _9: *mut u32;
                     scope 7 {
-                    }
-                    scope 8 (inlined core::slice::index::get_mut_noubcheck::<u32>) {
-                        let _9: *mut u32;
-                        scope 9 {
+                        let _10: *mut u32;
+                        scope 8 {
                         }
                     }
                 }
@@ -47,13 +45,13 @@ fn slice_get_unchecked_mut_range(_1: &mut [u32], _2: std::ops::Range<usize>) ->
     bb1: {
         StorageDead(_6);
         _8 = SubUnchecked(copy _4, copy _3);
-        StorageLive(_10);
         StorageLive(_9);
+        StorageLive(_10);
         _9 = copy _5 as *mut u32 (PtrToPtr);
         _10 = Offset(copy _9, copy _3);
-        StorageDead(_9);
         _11 = *mut [u32] from (copy _10, copy _8);
         StorageDead(_10);
+        StorageDead(_9);
         StorageDead(_8);
         StorageDead(_5);
         _0 = &mut (*_11);
diff --git a/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-unwind.mir
index 220e881f866..6fb1637a6e0 100644
--- a/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-unwind.mir
+++ b/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-unwind.mir
@@ -6,21 +6,19 @@ fn slice_get_unchecked_mut_range(_1: &mut [u32], _2: std::ops::Range<usize>) ->
     let mut _0: &mut [u32];
     let mut _3: usize;
     let mut _4: usize;
-    scope 1 (inlined core::slice::<impl [u32]>::get_unchecked_mut::<std::ops::Range<usize>>) {
+    scope 1 (inlined #[track_caller] core::slice::<impl [u32]>::get_unchecked_mut::<std::ops::Range<usize>>) {
         let mut _5: *mut [u32];
         let mut _11: *mut [u32];
-        scope 2 (inlined <std::ops::Range<usize> as SliceIndex<[u32]>>::get_unchecked_mut) {
+        scope 2 (inlined #[track_caller] <std::ops::Range<usize> as SliceIndex<[u32]>>::get_unchecked_mut) {
             let mut _6: usize;
             let _7: ();
             let _8: usize;
             scope 3 {
                 scope 6 (inlined core::slice::index::get_offset_len_mut_noubcheck::<u32>) {
-                    let _10: *mut u32;
+                    let _9: *mut u32;
                     scope 7 {
-                    }
-                    scope 8 (inlined core::slice::index::get_mut_noubcheck::<u32>) {
-                        let _9: *mut u32;
-                        scope 9 {
+                        let _10: *mut u32;
+                        scope 8 {
                         }
                     }
                 }
@@ -47,13 +45,13 @@ fn slice_get_unchecked_mut_range(_1: &mut [u32], _2: std::ops::Range<usize>) ->
     bb1: {
         StorageDead(_6);
         _8 = SubUnchecked(copy _4, copy _3);
-        StorageLive(_10);
         StorageLive(_9);
+        StorageLive(_10);
         _9 = copy _5 as *mut u32 (PtrToPtr);
         _10 = Offset(copy _9, copy _3);
-        StorageDead(_9);
         _11 = *mut [u32] from (copy _10, copy _8);
         StorageDead(_10);
+        StorageDead(_9);
         StorageDead(_8);
         StorageDead(_5);
         _0 = &mut (*_11);
diff --git a/tests/mir-opt/pre-codegen/slice_index.slice_ptr_get_unchecked_range.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_index.slice_ptr_get_unchecked_range.PreCodegen.after.panic-abort.mir
index 1e0df94b67f..ad1ca5dff43 100644
--- a/tests/mir-opt/pre-codegen/slice_index.slice_ptr_get_unchecked_range.PreCodegen.after.panic-abort.mir
+++ b/tests/mir-opt/pre-codegen/slice_index.slice_ptr_get_unchecked_range.PreCodegen.after.panic-abort.mir
@@ -7,18 +7,16 @@ fn slice_ptr_get_unchecked_range(_1: *const [u32], _2: std::ops::Range<usize>) -
     let mut _3: usize;
     let mut _4: usize;
     scope 1 (inlined std::ptr::const_ptr::<impl *const [u32]>::get_unchecked::<std::ops::Range<usize>>) {
-        scope 2 (inlined <std::ops::Range<usize> as SliceIndex<[u32]>>::get_unchecked) {
+        scope 2 (inlined #[track_caller] <std::ops::Range<usize> as SliceIndex<[u32]>>::get_unchecked) {
             let mut _5: usize;
             let _6: ();
             let _7: usize;
             scope 3 {
                 scope 6 (inlined core::slice::index::get_offset_len_noubcheck::<u32>) {
-                    let _9: *const u32;
+                    let _8: *const u32;
                     scope 7 {
-                    }
-                    scope 8 (inlined core::slice::index::get_noubcheck::<u32>) {
-                        let _8: *const u32;
-                        scope 9 {
+                        let _9: *const u32;
+                        scope 8 {
                         }
                     }
                 }
@@ -42,13 +40,13 @@ fn slice_ptr_get_unchecked_range(_1: *const [u32], _2: std::ops::Range<usize>) -
     bb1: {
         StorageDead(_5);
         _7 = SubUnchecked(copy _4, copy _3);
-        StorageLive(_9);
         StorageLive(_8);
+        StorageLive(_9);
         _8 = copy _1 as *const u32 (PtrToPtr);
         _9 = Offset(copy _8, copy _3);
-        StorageDead(_8);
         _0 = *const [u32] from (copy _9, copy _7);
         StorageDead(_9);
+        StorageDead(_8);
         StorageDead(_7);
         return;
     }
diff --git a/tests/mir-opt/pre-codegen/slice_index.slice_ptr_get_unchecked_range.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_index.slice_ptr_get_unchecked_range.PreCodegen.after.panic-unwind.mir
index 1e0df94b67f..ad1ca5dff43 100644
--- a/tests/mir-opt/pre-codegen/slice_index.slice_ptr_get_unchecked_range.PreCodegen.after.panic-unwind.mir
+++ b/tests/mir-opt/pre-codegen/slice_index.slice_ptr_get_unchecked_range.PreCodegen.after.panic-unwind.mir
@@ -7,18 +7,16 @@ fn slice_ptr_get_unchecked_range(_1: *const [u32], _2: std::ops::Range<usize>) -
     let mut _3: usize;
     let mut _4: usize;
     scope 1 (inlined std::ptr::const_ptr::<impl *const [u32]>::get_unchecked::<std::ops::Range<usize>>) {
-        scope 2 (inlined <std::ops::Range<usize> as SliceIndex<[u32]>>::get_unchecked) {
+        scope 2 (inlined #[track_caller] <std::ops::Range<usize> as SliceIndex<[u32]>>::get_unchecked) {
             let mut _5: usize;
             let _6: ();
             let _7: usize;
             scope 3 {
                 scope 6 (inlined core::slice::index::get_offset_len_noubcheck::<u32>) {
-                    let _9: *const u32;
+                    let _8: *const u32;
                     scope 7 {
-                    }
-                    scope 8 (inlined core::slice::index::get_noubcheck::<u32>) {
-                        let _8: *const u32;
-                        scope 9 {
+                        let _9: *const u32;
+                        scope 8 {
                         }
                     }
                 }
@@ -42,13 +40,13 @@ fn slice_ptr_get_unchecked_range(_1: *const [u32], _2: std::ops::Range<usize>) -
     bb1: {
         StorageDead(_5);
         _7 = SubUnchecked(copy _4, copy _3);
-        StorageLive(_9);
         StorageLive(_8);
+        StorageLive(_9);
         _8 = copy _1 as *const u32 (PtrToPtr);
         _9 = Offset(copy _8, copy _3);
-        StorageDead(_8);
         _0 = *const [u32] from (copy _9, copy _7);
         StorageDead(_9);
+        StorageDead(_8);
         StorageDead(_7);
         return;
     }
diff --git a/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-abort.mir
index c75edde711e..d389e4069d0 100644
--- a/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-abort.mir
+++ b/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-abort.mir
@@ -58,7 +58,7 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () {
                     scope 30 {
                         let _23: usize;
                         scope 31 {
-                            scope 34 (inlined core::num::<impl usize>::unchecked_sub) {
+                            scope 34 (inlined #[track_caller] core::num::<impl usize>::unchecked_sub) {
                                 scope 35 (inlined core::ub_checks::check_language_ub) {
                                     scope 36 (inlined core::ub_checks::check_language_ub::runtime) {
                                     }
@@ -115,7 +115,7 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () {
                     }
                     scope 13 (inlined NonNull::<T>::as_ptr) {
                     }
-                    scope 14 (inlined std::ptr::mut_ptr::<impl *mut T>::add) {
+                    scope 14 (inlined #[track_caller] std::ptr::mut_ptr::<impl *mut T>::add) {
                     }
                 }
                 scope 8 (inlined NonNull::<[T]>::from_ref) {
diff --git a/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-unwind.mir
index bc72181b77c..3b58f1d61f4 100644
--- a/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-unwind.mir
+++ b/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-unwind.mir
@@ -40,7 +40,7 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () {
                     }
                     scope 13 (inlined NonNull::<T>::as_ptr) {
                     }
-                    scope 14 (inlined std::ptr::mut_ptr::<impl *mut T>::add) {
+                    scope 14 (inlined #[track_caller] std::ptr::mut_ptr::<impl *mut T>::add) {
                     }
                 }
                 scope 8 (inlined NonNull::<[T]>::from_ref) {
diff --git a/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-abort.mir
index 38c509d0b53..216e05ec5b7 100644
--- a/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-abort.mir
+++ b/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-abort.mir
@@ -30,7 +30,7 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () {
                 scope 18 {
                     let _22: usize;
                     scope 19 {
-                        scope 22 (inlined core::num::<impl usize>::unchecked_sub) {
+                        scope 22 (inlined #[track_caller] core::num::<impl usize>::unchecked_sub) {
                             scope 23 (inlined core::ub_checks::check_language_ub) {
                                 scope 24 (inlined core::ub_checks::check_language_ub::runtime) {
                                 }
@@ -86,7 +86,7 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () {
                     }
                     scope 13 (inlined NonNull::<T>::as_ptr) {
                     }
-                    scope 14 (inlined std::ptr::mut_ptr::<impl *mut T>::add) {
+                    scope 14 (inlined #[track_caller] std::ptr::mut_ptr::<impl *mut T>::add) {
                     }
                 }
                 scope 8 (inlined NonNull::<[T]>::from_ref) {
diff --git a/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-unwind.mir
index 158cc284b1a..00102391980 100644
--- a/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-unwind.mir
+++ b/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-unwind.mir
@@ -30,7 +30,7 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () {
                 scope 18 {
                     let _22: usize;
                     scope 19 {
-                        scope 22 (inlined core::num::<impl usize>::unchecked_sub) {
+                        scope 22 (inlined #[track_caller] core::num::<impl usize>::unchecked_sub) {
                             scope 23 (inlined core::ub_checks::check_language_ub) {
                                 scope 24 (inlined core::ub_checks::check_language_ub::runtime) {
                                 }
@@ -86,7 +86,7 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () {
                     }
                     scope 13 (inlined NonNull::<T>::as_ptr) {
                     }
-                    scope 14 (inlined std::ptr::mut_ptr::<impl *mut T>::add) {
+                    scope 14 (inlined #[track_caller] std::ptr::mut_ptr::<impl *mut T>::add) {
                     }
                 }
                 scope 8 (inlined NonNull::<[T]>::from_ref) {
diff --git a/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-abort.mir
index f8d11df5185..41e273151ec 100644
--- a/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-abort.mir
+++ b/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-abort.mir
@@ -29,7 +29,7 @@ fn range_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () {
                 let mut _8: usize;
                 scope 7 {
                     scope 9 (inlined <usize as Step>::forward_unchecked) {
-                        scope 10 (inlined core::num::<impl usize>::unchecked_add) {
+                        scope 10 (inlined #[track_caller] core::num::<impl usize>::unchecked_add) {
                             scope 11 (inlined core::ub_checks::check_language_ub) {
                                 scope 12 (inlined core::ub_checks::check_language_ub::runtime) {
                                 }
diff --git a/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-unwind.mir
index 2c249197894..ec781c1480c 100644
--- a/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-unwind.mir
+++ b/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-unwind.mir
@@ -29,7 +29,7 @@ fn range_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () {
                 let mut _8: usize;
                 scope 7 {
                     scope 9 (inlined <usize as Step>::forward_unchecked) {
-                        scope 10 (inlined core::num::<impl usize>::unchecked_add) {
+                        scope 10 (inlined #[track_caller] core::num::<impl usize>::unchecked_add) {
                             scope 11 (inlined core::ub_checks::check_language_ub) {
                                 scope 12 (inlined core::ub_checks::check_language_ub::runtime) {
                                 }
diff --git a/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-abort.mir
index 00366762108..b09e3622344 100644
--- a/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-abort.mir
+++ b/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-abort.mir
@@ -40,7 +40,7 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () {
                     }
                     scope 13 (inlined NonNull::<T>::as_ptr) {
                     }
-                    scope 14 (inlined std::ptr::mut_ptr::<impl *mut T>::add) {
+                    scope 14 (inlined #[track_caller] std::ptr::mut_ptr::<impl *mut T>::add) {
                     }
                 }
                 scope 8 (inlined NonNull::<[T]>::from_ref) {
diff --git a/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-unwind.mir
index e1d710fb689..12b54b57b84 100644
--- a/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-unwind.mir
+++ b/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-unwind.mir
@@ -40,7 +40,7 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () {
                     }
                     scope 13 (inlined NonNull::<T>::as_ptr) {
                     }
-                    scope 14 (inlined std::ptr::mut_ptr::<impl *mut T>::add) {
+                    scope 14 (inlined #[track_caller] std::ptr::mut_ptr::<impl *mut T>::add) {
                     }
                 }
                 scope 8 (inlined NonNull::<[T]>::from_ref) {
diff --git a/tests/mir-opt/pre-codegen/slice_iter.slice_iter_next.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_iter.slice_iter_next.PreCodegen.after.panic-abort.mir
index b6df2300efb..c0ed0aea1e2 100644
--- a/tests/mir-opt/pre-codegen/slice_iter.slice_iter_next.PreCodegen.after.panic-abort.mir
+++ b/tests/mir-opt/pre-codegen/slice_iter.slice_iter_next.PreCodegen.after.panic-abort.mir
@@ -15,7 +15,7 @@ fn slice_iter_next(_1: &mut std::slice::Iter<'_, T>) -> Option<&T> {
             scope 3 {
                 let _11: usize;
                 scope 4 {
-                    scope 7 (inlined core::num::<impl usize>::unchecked_sub) {
+                    scope 7 (inlined #[track_caller] core::num::<impl usize>::unchecked_sub) {
                         scope 8 (inlined core::ub_checks::check_language_ub) {
                             scope 9 (inlined core::ub_checks::check_language_ub::runtime) {
                             }
diff --git a/tests/mir-opt/pre-codegen/slice_iter.slice_iter_next.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_iter.slice_iter_next.PreCodegen.after.panic-unwind.mir
index b6df2300efb..c0ed0aea1e2 100644
--- a/tests/mir-opt/pre-codegen/slice_iter.slice_iter_next.PreCodegen.after.panic-unwind.mir
+++ b/tests/mir-opt/pre-codegen/slice_iter.slice_iter_next.PreCodegen.after.panic-unwind.mir
@@ -15,7 +15,7 @@ fn slice_iter_next(_1: &mut std::slice::Iter<'_, T>) -> Option<&T> {
             scope 3 {
                 let _11: usize;
                 scope 4 {
-                    scope 7 (inlined core::num::<impl usize>::unchecked_sub) {
+                    scope 7 (inlined #[track_caller] core::num::<impl usize>::unchecked_sub) {
                         scope 8 (inlined core::ub_checks::check_language_ub) {
                             scope 9 (inlined core::ub_checks::check_language_ub::runtime) {
                             }
diff --git a/tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-abort.mir
index 927deabd253..30eafe8594b 100644
--- a/tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-abort.mir
+++ b/tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-abort.mir
@@ -29,7 +29,7 @@ fn vec_deref_to_slice(_1: &Vec<u8>) -> &[u8] {
                     }
                 }
             }
-            scope 12 (inlined std::slice::from_raw_parts::<'_, u8>) {
+            scope 12 (inlined #[track_caller] std::slice::from_raw_parts::<'_, u8>) {
                 debug data => _3;
                 debug len => _4;
                 let _5: *const [u8];
diff --git a/tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-unwind.mir
index 927deabd253..30eafe8594b 100644
--- a/tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-unwind.mir
+++ b/tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-unwind.mir
@@ -29,7 +29,7 @@ fn vec_deref_to_slice(_1: &Vec<u8>) -> &[u8] {
                     }
                 }
             }
-            scope 12 (inlined std::slice::from_raw_parts::<'_, u8>) {
+            scope 12 (inlined #[track_caller] std::slice::from_raw_parts::<'_, u8>) {
                 debug data => _3;
                 debug len => _4;
                 let _5: *const [u8];
diff --git a/tests/pretty/autodiff/autodiff_forward.pp b/tests/pretty/autodiff/autodiff_forward.pp
index 8253603e807..a2525abc832 100644
--- a/tests/pretty/autodiff/autodiff_forward.pp
+++ b/tests/pretty/autodiff/autodiff_forward.pp
@@ -13,7 +13,7 @@ extern crate std;
 
 // Test that forward mode ad macros are expanded correctly.
 
-use std::autodiff::autodiff;
+use std::autodiff::{autodiff_forward, autodiff_reverse};
 
 #[rustc_autodiff]
 #[inline(never)]
diff --git a/tests/pretty/autodiff/autodiff_forward.rs b/tests/pretty/autodiff/autodiff_forward.rs
index ae974f9b4db..e23a1b3e241 100644
--- a/tests/pretty/autodiff/autodiff_forward.rs
+++ b/tests/pretty/autodiff/autodiff_forward.rs
@@ -7,48 +7,48 @@
 
 // Test that forward mode ad macros are expanded correctly.
 
-use std::autodiff::autodiff;
+use std::autodiff::{autodiff_forward, autodiff_reverse};
 
-#[autodiff(df1, Forward, Dual, Const, Dual)]
+#[autodiff_forward(df1, Dual, Const, Dual)]
 pub fn f1(x: &[f64], y: f64) -> f64 {
     unimplemented!()
 }
 
-#[autodiff(df2, Forward, Dual, Const, Const)]
+#[autodiff_forward(df2, Dual, Const, Const)]
 pub fn f2(x: &[f64], y: f64) -> f64 {
     unimplemented!()
 }
 
-#[autodiff(df3, Forward, Dual, Const, Const)]
+#[autodiff_forward(df3, Dual, Const, Const)]
 pub fn f3(x: &[f64], y: f64) -> f64 {
     unimplemented!()
 }
 
 // Not the most interesting derivative, but who are we to judge
-#[autodiff(df4, Forward)]
+#[autodiff_forward(df4)]
 pub fn f4() {}
 
 // We want to be sure that the same function can be differentiated in different ways
-#[autodiff(df5_rev, Reverse, Duplicated, Const, Active)]
-#[autodiff(df5_x, Forward, Dual, Const, Const)]
-#[autodiff(df5_y, Forward, Const, Dual, Const)]
+#[autodiff_reverse(df5_rev, Duplicated, Const, Active)]
+#[autodiff_forward(df5_x, Dual, Const, Const)]
+#[autodiff_forward(df5_y, Const, Dual, Const)]
 pub fn f5(x: &[f64], y: f64) -> f64 {
     unimplemented!()
 }
 
 struct DoesNotImplDefault;
-#[autodiff(df6, Forward, Const)]
+#[autodiff_forward(df6, Const)]
 pub fn f6() -> DoesNotImplDefault {
     unimplemented!()
 }
 
 // Make sure, that we add the None for the default return.
-#[autodiff(df7, Forward, Const)]
+#[autodiff_forward(df7, Const)]
 pub fn f7(x: f32) -> () {}
 
-#[autodiff(f8_1, Forward, Dual, DualOnly)]
-#[autodiff(f8_2, Forward, 4, Dual, DualOnly)]
-#[autodiff(f8_3, Forward, 4, Dual, Dual)]
+#[autodiff_forward(f8_1, Dual, DualOnly)]
+#[autodiff_forward(f8_2, 4, Dual, DualOnly)]
+#[autodiff_forward(f8_3, 4, Dual, Dual)]
 #[no_mangle]
 fn f8(x: &f32) -> f32 {
     unimplemented!()
@@ -56,15 +56,15 @@ fn f8(x: &f32) -> f32 {
 
 // We want to make sure that we can use the macro for functions defined inside of functions
 pub fn f9() {
-    #[autodiff(d_inner_1, Forward, Dual, DualOnly)]
-    #[autodiff(d_inner_2, Forward, Dual, Dual)]
+    #[autodiff_forward(d_inner_1, Dual, DualOnly)]
+    #[autodiff_forward(d_inner_2, Dual, Dual)]
     fn inner(x: f32) -> f32 {
         x * x
     }
 }
 
 // Make sure we can handle generics
-#[autodiff(d_square, Reverse, Duplicated, Active)]
+#[autodiff_reverse(d_square, Duplicated, Active)]
 pub fn f10<T: std::ops::Mul<Output = T> + Copy>(x: &T) -> T {
     *x * *x
 }
diff --git a/tests/pretty/autodiff/autodiff_reverse.pp b/tests/pretty/autodiff/autodiff_reverse.pp
index 31920694a3a..e67c3443dde 100644
--- a/tests/pretty/autodiff/autodiff_reverse.pp
+++ b/tests/pretty/autodiff/autodiff_reverse.pp
@@ -13,7 +13,7 @@ extern crate std;
 
 // Test that reverse mode ad macros are expanded correctly.
 
-use std::autodiff::autodiff;
+use std::autodiff::autodiff_reverse;
 
 #[rustc_autodiff]
 #[inline(never)]
diff --git a/tests/pretty/autodiff/autodiff_reverse.rs b/tests/pretty/autodiff/autodiff_reverse.rs
index 3c024272f40..d37e5e3eb4c 100644
--- a/tests/pretty/autodiff/autodiff_reverse.rs
+++ b/tests/pretty/autodiff/autodiff_reverse.rs
@@ -7,18 +7,18 @@
 
 // Test that reverse mode ad macros are expanded correctly.
 
-use std::autodiff::autodiff;
+use std::autodiff::autodiff_reverse;
 
-#[autodiff(df1, Reverse, Duplicated, Const, Active)]
+#[autodiff_reverse(df1, Duplicated, Const, Active)]
 pub fn f1(x: &[f64], y: f64) -> f64 {
     unimplemented!()
 }
 
 // Not the most interesting derivative, but who are we to judge
-#[autodiff(df2, Reverse)]
+#[autodiff_reverse(df2)]
 pub fn f2() {}
 
-#[autodiff(df3, Reverse, Duplicated, Const, Active)]
+#[autodiff_reverse(df3, Duplicated, Const, Active)]
 pub fn f3(x: &[f64], y: f64) -> f64 {
     unimplemented!()
 }
@@ -27,12 +27,12 @@ enum Foo { Reverse }
 use Foo::Reverse;
 // What happens if we already have Reverse in type (enum variant decl) and value (enum variant
 // constructor) namespace? > It's expected to work normally.
-#[autodiff(df4, Reverse, Const)]
+#[autodiff_reverse(df4, Const)]
 pub fn f4(x: f32) {
     unimplemented!()
 }
 
-#[autodiff(df5, Reverse, DuplicatedOnly, Duplicated)]
+#[autodiff_reverse(df5, DuplicatedOnly, Duplicated)]
 pub fn f5(x: *const f32, y: &f32) {
     unimplemented!()
 }
diff --git a/tests/pretty/autodiff/inherent_impl.pp b/tests/pretty/autodiff/inherent_impl.pp
index 97ac766b6b9..d18061b2dbd 100644
--- a/tests/pretty/autodiff/inherent_impl.pp
+++ b/tests/pretty/autodiff/inherent_impl.pp
@@ -11,7 +11,7 @@ extern crate std;
 //@ pretty-compare-only
 //@ pp-exact:inherent_impl.pp
 
-use std::autodiff::autodiff;
+use std::autodiff::autodiff_reverse;
 
 struct Foo {
     a: f64,
diff --git a/tests/pretty/autodiff/inherent_impl.rs b/tests/pretty/autodiff/inherent_impl.rs
index 59de93f7e0f..11ff209f9d8 100644
--- a/tests/pretty/autodiff/inherent_impl.rs
+++ b/tests/pretty/autodiff/inherent_impl.rs
@@ -5,7 +5,7 @@
 //@ pretty-compare-only
 //@ pp-exact:inherent_impl.pp
 
-use std::autodiff::autodiff;
+use std::autodiff::autodiff_reverse;
 
 struct Foo {
     a: f64,
@@ -17,7 +17,7 @@ trait MyTrait {
 }
 
 impl MyTrait for Foo {
-    #[autodiff(df, Reverse, Const, Active, Active)]
+    #[autodiff_reverse(df, Const, Active, Active)]
     fn f(&self, x: f64) -> f64 {
         self.a * 0.25 * (x * x - 1.0 - 2.0 * x.ln())
     }
diff --git a/tests/run-make/c-link-to-rust-va-list-fn/checkrust.rs b/tests/run-make/c-link-to-rust-va-list-fn/checkrust.rs
index 7e4344f1c69..36c9db106ec 100644
--- a/tests/run-make/c-link-to-rust-va-list-fn/checkrust.rs
+++ b/tests/run-make/c-link-to-rust-va-list-fn/checkrust.rs
@@ -112,6 +112,9 @@ pub unsafe extern "C" fn check_varargs_4(_: c_double, mut ap: ...) -> usize {
     continue_if!(ap.arg::<c_double>() == 8.0);
     continue_if!(ap.arg::<c_double>() == 9.0);
     continue_if!(ap.arg::<c_double>() == 10.0);
+    continue_if!(ap.arg::<c_double>() == 11.0);
+    continue_if!(ap.arg::<c_double>() == 12.0);
+    continue_if!(ap.arg::<c_double>() == 13.0);
     0
 }
 
@@ -137,5 +140,11 @@ pub unsafe extern "C" fn check_varargs_5(_: c_int, mut ap: ...) -> usize {
     continue_if!(ap.arg::<c_double>() == 9.0);
     continue_if!(ap.arg::<c_int>() == 10);
     continue_if!(ap.arg::<c_double>() == 10.0);
+    continue_if!(ap.arg::<c_int>() == 11);
+    continue_if!(ap.arg::<c_double>() == 11.0);
+    continue_if!(ap.arg::<c_int>() == 12);
+    continue_if!(ap.arg::<c_double>() == 12.0);
+    continue_if!(ap.arg::<c_int>() == 13);
+    continue_if!(ap.arg::<c_double>() == 13.0);
     0
 }
diff --git a/tests/run-make/c-link-to-rust-va-list-fn/test.c b/tests/run-make/c-link-to-rust-va-list-fn/test.c
index 5bdb51680a6..b47a9357880 100644
--- a/tests/run-make/c-link-to-rust-va-list-fn/test.c
+++ b/tests/run-make/c-link-to-rust-va-list-fn/test.c
@@ -41,10 +41,11 @@ int main(int argc, char* argv[]) {
 
     assert(check_varargs_3(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10) == 0);
 
-    assert(check_varargs_4(0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0) == 0);
+    assert(check_varargs_4(0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0,
+                           13.0) == 0);
 
     assert(check_varargs_5(0, 1.0, 1, 2.0, 2, 3.0, 3, 4.0, 4, 5, 5.0, 6, 6.0, 7, 7.0, 8, 8.0,
-                           9, 9.0, 10, 10.0) == 0);
+                           9, 9.0, 10, 10.0, 11, 11.0, 12, 12.0, 13, 13.0) == 0);
 
     return 0;
 }
diff --git a/tests/run-make/mte-ffi/bar.h b/tests/run-make/mte-ffi/bar.h
index a2292ae02a3..9b030c618d1 100644
--- a/tests/run-make/mte-ffi/bar.h
+++ b/tests/run-make/mte-ffi/bar.h
@@ -1,3 +1,5 @@
+// FIXME(#141600) the mte-ffi test doesn't fail in aarch64-gnu
+
 #ifndef __BAR_H
 #define __BAR_H
 
diff --git a/tests/run-make/mte-ffi/bar_float.c b/tests/run-make/mte-ffi/bar_float.c
index a1590f62765..acc2f5d9266 100644
--- a/tests/run-make/mte-ffi/bar_float.c
+++ b/tests/run-make/mte-ffi/bar_float.c
@@ -3,9 +3,9 @@
 #include <stdint.h>
 #include "bar.h"
 
-extern void foo(char*);
+extern void foo(float*);
 
-void bar(char *ptr) {
+void bar(float *ptr) {
     if (((uintptr_t)ptr >> 56) != 0x1f) {
         fprintf(stderr, "Top byte corrupted on Rust -> C FFI boundary!\n");
         exit(1);
diff --git a/tests/run-make/mte-ffi/bar_int.c b/tests/run-make/mte-ffi/bar_int.c
index d1c79e95dc9..c92e765302c 100644
--- a/tests/run-make/mte-ffi/bar_int.c
+++ b/tests/run-make/mte-ffi/bar_int.c
@@ -5,7 +5,7 @@
 
 extern void foo(unsigned int *);
 
-void bar(char *ptr) {
+void bar(unsigned int *ptr) {
     if (((uintptr_t)ptr >> 56) != 0x1f) {
         fprintf(stderr, "Top byte corrupted on Rust -> C FFI boundary!\n");
         exit(1);
diff --git a/tests/run-make/mte-ffi/bar_string.c b/tests/run-make/mte-ffi/bar_string.c
index 5669ffd6695..8e1202f6fd1 100644
--- a/tests/run-make/mte-ffi/bar_string.c
+++ b/tests/run-make/mte-ffi/bar_string.c
@@ -1,6 +1,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <stdint.h>
+#include <string.h>
 #include "bar.h"
 
 extern void foo(char*);
@@ -32,7 +33,7 @@ int main(void)
 
     // Store an arbitrary tag in bits 56-59 of the pointer (where an MTE tag may be),
     // and a different value in the ignored top 4 bits.
-    ptr = (unsigned int *)((uintptr_t)ptr | 0x1fl << 56);
+    ptr = (char *)((uintptr_t)ptr | 0x1fl << 56);
 
     if (mte_enabled()) {
         set_tag(ptr);
diff --git a/tests/run-make/repr128-dwarf/main.rs b/tests/run-make/repr128-dwarf/main.rs
index 9842ab4a342..a8a414fd72e 100644
--- a/tests/run-make/repr128-dwarf/main.rs
+++ b/tests/run-make/repr128-dwarf/main.rs
@@ -1,5 +1,3 @@
-#![feature(repr128)]
-
 // Use .to_le() to ensure that the bytes are in the same order on both little- and big-endian
 // platforms.
 
diff --git a/tests/run-make/version-check/rmake.rs b/tests/run-make/version-check/rmake.rs
new file mode 100644
index 00000000000..e6a14d2e95c
--- /dev/null
+++ b/tests/run-make/version-check/rmake.rs
@@ -0,0 +1,13 @@
+use run_make_support::bare_rustc;
+
+fn main() {
+    let signalled_version = "Ceci n'est pas une rustc";
+    let rustc_out = bare_rustc()
+        .env("RUSTC_OVERRIDE_VERSION_STRING", signalled_version)
+        .arg("--version")
+        .run()
+        .stdout_utf8();
+
+    let version = rustc_out.strip_prefix("rustc ").unwrap().trim_end();
+    assert_eq!(version, signalled_version);
+}
diff --git a/tests/rustdoc-json/enums/discriminant/limits.rs b/tests/rustdoc-json/enums/discriminant/limits.rs
index c84181334e3..e98271b7c80 100644
--- a/tests/rustdoc-json/enums/discriminant/limits.rs
+++ b/tests/rustdoc-json/enums/discriminant/limits.rs
@@ -1,6 +1,3 @@
-#![feature(repr128)]
-#![allow(incomplete_features)]
-
 #[repr(u64)]
 pub enum U64 {
     //@ is "$.index[?(@.name=='U64Min')].inner.variant.discriminant.value" '"0"'
diff --git a/tests/rustdoc-ui/doc-cfg-check-cfg.cfg_empty.stderr b/tests/rustdoc-ui/doc-cfg-check-cfg.cfg_empty.stderr
new file mode 100644
index 00000000000..0878f7edbf4
--- /dev/null
+++ b/tests/rustdoc-ui/doc-cfg-check-cfg.cfg_empty.stderr
@@ -0,0 +1,30 @@
+warning: unexpected `cfg` condition name: `foo`
+  --> $DIR/doc-cfg-check-cfg.rs:12:12
+   |
+LL | #![doc(cfg(foo))]
+   |            ^^^
+   |
+   = help: to expect this configuration use `--check-cfg=cfg(foo)`
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
+   = note: `#[warn(unexpected_cfgs)]` on by default
+
+warning: unexpected `cfg` condition name: `foo`
+  --> $DIR/doc-cfg-check-cfg.rs:19:11
+   |
+LL | #[doc(cfg(foo))]
+   |           ^^^
+   |
+   = help: to expect this configuration use `--check-cfg=cfg(foo)`
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
+
+warning: unexpected `cfg` condition name: `foo`
+  --> $DIR/doc-cfg-check-cfg.rs:15:11
+   |
+LL | #[doc(cfg(foo))]
+   |           ^^^
+   |
+   = help: to expect this configuration use `--check-cfg=cfg(foo)`
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
+
+warning: 3 warnings emitted
+
diff --git a/tests/rustdoc-ui/doc-cfg-check-cfg.rs b/tests/rustdoc-ui/doc-cfg-check-cfg.rs
index e3420dc0789..7d37077a32d 100644
--- a/tests/rustdoc-ui/doc-cfg-check-cfg.rs
+++ b/tests/rustdoc-ui/doc-cfg-check-cfg.rs
@@ -1,16 +1,25 @@
 // Ensure that `doc(cfg())` respects `check-cfg`
 // Currently not properly working
-#![feature(doc_cfg)]
-#![deny(unexpected_cfgs)]
 
-//@revisions: no_check cfg_empty cfg_foo
+//@ check-pass
+//@ no-auto-check-cfg
+
+//@ revisions: no_check cfg_empty cfg_foo
 //@[cfg_empty] compile-flags: --check-cfg cfg()
 //@[cfg_foo] compile-flags: --check-cfg cfg(foo)
 
-//@[no_check] check-pass
-//@[cfg_empty] check-pass
-//@[cfg_empty] known-bug: #138358
-//@[cfg_foo] check-pass
+#![feature(doc_cfg)]
+#![doc(cfg(foo))]
+//[cfg_empty]~^ WARN unexpected `cfg` condition name: `foo`
 
 #[doc(cfg(foo))]
+//[cfg_empty]~^ WARN unexpected `cfg` condition name: `foo`
 pub fn foo() {}
+
+#[doc(cfg(foo))]
+//[cfg_empty]~^ WARN unexpected `cfg` condition name: `foo`
+pub mod module {
+    #[allow(unexpected_cfgs)]
+    #[doc(cfg(bar))]
+    pub fn bar() {}
+}
diff --git a/tests/rustdoc-ui/doc-cfg.rs b/tests/rustdoc-ui/doc-cfg.rs
index 354d76bc3c4..14943bbc341 100644
--- a/tests/rustdoc-ui/doc-cfg.rs
+++ b/tests/rustdoc-ui/doc-cfg.rs
@@ -3,7 +3,9 @@
 #[doc(cfg(), cfg(foo, bar))]
 //~^ ERROR
 //~^^ ERROR
-#[doc(cfg(foo), cfg(bar))] // ok!
+#[doc(cfg(foo), cfg(bar))]
+//~^ WARN unexpected `cfg` condition name: `foo`
+//~^^ WARN unexpected `cfg` condition name: `bar`
 #[doc(cfg())] //~ ERROR
 #[doc(cfg(foo, bar))] //~ ERROR
 pub fn foo() {}
diff --git a/tests/rustdoc-ui/doc-cfg.stderr b/tests/rustdoc-ui/doc-cfg.stderr
index 14b7b17e04d..1233ee010de 100644
--- a/tests/rustdoc-ui/doc-cfg.stderr
+++ b/tests/rustdoc-ui/doc-cfg.stderr
@@ -11,16 +11,36 @@ LL | #[doc(cfg(), cfg(foo, bar))]
    |                       ^^^
 
 error: `cfg` predicate is not specified
-  --> $DIR/doc-cfg.rs:7:7
+  --> $DIR/doc-cfg.rs:9:7
    |
 LL | #[doc(cfg())]
    |       ^^^^^ help: expected syntax is: `cfg(/* predicate */)`
 
 error: multiple `cfg` predicates are specified
-  --> $DIR/doc-cfg.rs:8:16
+  --> $DIR/doc-cfg.rs:10:16
    |
 LL | #[doc(cfg(foo, bar))]
    |                ^^^
 
-error: aborting due to 4 previous errors
+warning: unexpected `cfg` condition name: `foo`
+  --> $DIR/doc-cfg.rs:6:11
+   |
+LL | #[doc(cfg(foo), cfg(bar))]
+   |           ^^^
+   |
+   = help: expected names are: `FALSE` and `test` and 31 more
+   = help: to expect this configuration use `--check-cfg=cfg(foo)`
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
+   = note: `#[warn(unexpected_cfgs)]` on by default
+
+warning: unexpected `cfg` condition name: `bar`
+  --> $DIR/doc-cfg.rs:6:21
+   |
+LL | #[doc(cfg(foo), cfg(bar))]
+   |                     ^^^
+   |
+   = help: to expect this configuration use `--check-cfg=cfg(bar)`
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
+
+error: aborting due to 4 previous errors; 2 warnings emitted
 
diff --git a/tests/rustdoc-ui/intra-doc/bad-link-to-proc-macro.rs b/tests/rustdoc-ui/intra-doc/bad-link-to-proc-macro.rs
new file mode 100644
index 00000000000..b449465768e
--- /dev/null
+++ b/tests/rustdoc-ui/intra-doc/bad-link-to-proc-macro.rs
@@ -0,0 +1,21 @@
+//@ compile-flags: --crate-type=proc-macro --document-private-items
+#![deny(rustdoc::broken_intra_doc_links)]
+
+//! Link to [`m`].
+//~^ ERROR `m` is both a module and a macro
+
+// test a further edge case related to https://github.com/rust-lang/rust/issues/91274
+
+// we need to make sure that when there is actually an ambiguity
+// in a proc-macro crate, we print out a sensible error.
+// because proc macro crates can't normally export modules,
+// this can only happen in --document-private-items mode.
+
+extern crate proc_macro;
+
+mod m {}
+
+#[proc_macro]
+pub fn m(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
+    input
+}
diff --git a/tests/rustdoc-ui/intra-doc/bad-link-to-proc-macro.stderr b/tests/rustdoc-ui/intra-doc/bad-link-to-proc-macro.stderr
new file mode 100644
index 00000000000..09a5d26eded
--- /dev/null
+++ b/tests/rustdoc-ui/intra-doc/bad-link-to-proc-macro.stderr
@@ -0,0 +1,22 @@
+error: `m` is both a module and a macro
+  --> $DIR/bad-link-to-proc-macro.rs:4:15
+   |
+LL | //! Link to [`m`].
+   |               ^ ambiguous link
+   |
+note: the lint level is defined here
+  --> $DIR/bad-link-to-proc-macro.rs:2:9
+   |
+LL | #![deny(rustdoc::broken_intra_doc_links)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+help: to link to the module, prefix with `mod@`
+   |
+LL | //! Link to [`mod@m`].
+   |               ++++
+help: to link to the macro, add an exclamation mark
+   |
+LL | //! Link to [`m!`].
+   |                +
+
+error: aborting due to 1 previous error
+
diff --git a/tests/rustdoc-ui/issues/issue-91713.stdout b/tests/rustdoc-ui/issues/issue-91713.stdout
index 790e58b0df9..30aadfe89f4 100644
--- a/tests/rustdoc-ui/issues/issue-91713.stdout
+++ b/tests/rustdoc-ui/issues/issue-91713.stdout
@@ -1,4 +1,5 @@
 Available passes for running rustdoc:
+       check-doc-cfg - checks `#[doc(cfg(...))]` for stability feature and unexpected cfgs
 check_doc_test_visibility - run various visibility-related lints on doctests
 strip-aliased-non-local - strips all non-local private aliased items from the output
         strip-hidden - strips all `#[doc(hidden)]` items from the output
@@ -14,6 +15,7 @@ calculate-doc-coverage - counts the number of items with and without documentati
 Default passes for rustdoc:
  collect-trait-impls
 check_doc_test_visibility
+       check-doc-cfg
 strip-aliased-non-local
         strip-hidden  (when not --document-hidden-items)
        strip-private  (when not --document-private-items)
diff --git a/tests/rustdoc/cfg-bool.rs b/tests/rustdoc/cfg-bool.rs
new file mode 100644
index 00000000000..34fdfbe930e
--- /dev/null
+++ b/tests/rustdoc/cfg-bool.rs
@@ -0,0 +1,13 @@
+#![feature(doc_cfg)]
+#![crate_name = "foo"]
+
+// regression test for https://github.com/rust-lang/rust/issues/138112
+
+//@ has 'foo/fn.foo.html' '//div[@class="stab portability"]' 'Available nowhere'
+#[doc(cfg(false))]
+pub fn foo() {}
+
+// a cfg(true) will simply be ommited, as it is the same as no cfg.
+//@ !has 'foo/fn.bar.html' '//div[@class="stab portability"]' ''
+#[doc(cfg(true))]
+pub fn bar() {}
diff --git a/tests/rustdoc/doctest/ignore-sometimes.rs b/tests/rustdoc/doctest/ignore-sometimes.rs
new file mode 100644
index 00000000000..0f8586d221c
--- /dev/null
+++ b/tests/rustdoc/doctest/ignore-sometimes.rs
@@ -0,0 +1,23 @@
+#![crate_name = "foo"]
+
+// test for https://github.com/rust-lang/rust/issues/141092
+
+//@ has 'foo/fn.f.html' '//a[@title="This example is not tested on wasm"]' 'ⓘ'
+/// Example
+///
+/// ```ignore-wasm
+/// let x = 1;
+/// ```
+pub fn f() {}
+
+//@ has 'foo/fn.g.html' '//a[@title="This example is not tested on wasm or windows"]' 'ⓘ'
+/// ```ignore-wasm,ignore-windows
+/// let x = 1;
+/// ```
+pub fn g() {}
+
+//@ has 'foo/fn.h.html' '//a[@title="This example is not tested on wasm, windows, or unix"]' 'ⓘ'
+/// ```ignore-wasm,ignore-windows,ignore-unix
+/// let x = 1;
+/// ```
+pub fn h() {}
diff --git a/tests/rustdoc/intra-doc/link-to-proc-macro.rs b/tests/rustdoc/intra-doc/link-to-proc-macro.rs
new file mode 100644
index 00000000000..6c289078db8
--- /dev/null
+++ b/tests/rustdoc/intra-doc/link-to-proc-macro.rs
@@ -0,0 +1,13 @@
+//@ compile-flags: --crate-type=proc-macro
+//@ has 'foo/index.html' '//a[@href="macro.my_macro.html"]' 'my_macro'
+//! Link to [`my_macro`].
+#![crate_name = "foo"]
+
+// regression test for https://github.com/rust-lang/rust/issues/91274
+
+extern crate proc_macro;
+
+#[proc_macro]
+pub fn my_macro(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
+    input
+}
diff --git a/tests/rustdoc/type-alias/repr.rs b/tests/rustdoc/type-alias/repr.rs
new file mode 100644
index 00000000000..cf907980360
--- /dev/null
+++ b/tests/rustdoc/type-alias/repr.rs
@@ -0,0 +1,42 @@
+// This test ensures that the `repr` attribute is displayed in type aliases.
+//
+// Regression test for <https://github.com/rust-lang/rust/issues/140739>.
+
+#![crate_name = "foo"]
+
+/// bla
+#[repr(C)]
+pub struct Foo1;
+
+//@ has 'foo/type.Bar1.html'
+//@ has - '//*[@class="rust item-decl"]/code' '#[repr(C)]pub struct Bar1;'
+// Ensures that we see the doc comment of the type alias and not of the aliased type.
+//@ has - '//*[@class="toggle top-doc"]/*[@class="docblock"]' 'bar'
+/// bar
+pub type Bar1 = Foo1;
+
+/// bla
+#[repr(C)]
+pub union Foo2 {
+    pub a: u8,
+}
+
+//@ has 'foo/type.Bar2.html'
+//@ matches - '//*[@class="rust item-decl"]' '#\[repr\(C\)\]\npub union Bar2 \{*'
+// Ensures that we see the doc comment of the type alias and not of the aliased type.
+//@ has - '//*[@class="toggle top-doc"]/*[@class="docblock"]' 'bar'
+/// bar
+pub type Bar2 = Foo2;
+
+/// bla
+#[repr(C)]
+pub enum Foo3 {
+    A,
+}
+
+//@ has 'foo/type.Bar3.html'
+//@ matches - '//*[@class="rust item-decl"]' '#\[repr\(C\)\]pub enum Bar3 \{*'
+// Ensures that we see the doc comment of the type alias and not of the aliased type.
+//@ has - '//*[@class="toggle top-doc"]/*[@class="docblock"]' 'bar'
+/// bar
+pub type Bar3 = Foo3;
diff --git a/tests/rustdoc/type-layout.rs b/tests/rustdoc/type-layout.rs
index 6de435dbcc1..482b8b597dd 100644
--- a/tests/rustdoc/type-layout.rs
+++ b/tests/rustdoc/type-layout.rs
@@ -61,7 +61,7 @@ pub type TypeAlias = X;
 pub type GenericTypeAlias = (Generic<(u32, ())>, Generic<u32>);
 
 // Regression test for the rustdoc equivalent of #85103.
-//@ hasraw type_layout/type.Edges.html 'Encountered an error during type layout; the type failed to be normalized.'
+//@ hasraw type_layout/type.Edges.html 'Unable to compute type layout, possibly due to this type having generic parameters. Layout can only be computed for concrete, fully-instantiated types.'
 pub type Edges<'a, E> = std::borrow::Cow<'a, [E]>;
 
 //@ !hasraw type_layout/trait.MyTrait.html 'Size: '
diff --git a/tests/ui-fulldeps/pprust-expr-roundtrip.rs b/tests/ui-fulldeps/pprust-expr-roundtrip.rs
index 4a866560e79..f5cfa9e0bcc 100644
--- a/tests/ui-fulldeps/pprust-expr-roundtrip.rs
+++ b/tests/ui-fulldeps/pprust-expr-roundtrip.rs
@@ -34,7 +34,7 @@ extern crate thin_vec;
 extern crate rustc_driver;
 
 use parser::parse_expr;
-use rustc_ast::mut_visit::{visit_clobber, MutVisitor};
+use rustc_ast::mut_visit::MutVisitor;
 use rustc_ast::ptr::P;
 use rustc_ast::*;
 use rustc_ast_pretty::pprust;
@@ -202,15 +202,9 @@ struct AddParens;
 impl MutVisitor for AddParens {
     fn visit_expr(&mut self, e: &mut P<Expr>) {
         mut_visit::walk_expr(self, e);
-        visit_clobber(e, |e| {
-            P(Expr {
-                id: DUMMY_NODE_ID,
-                kind: ExprKind::Paren(e),
-                span: DUMMY_SP,
-                attrs: AttrVec::new(),
-                tokens: None,
-            })
-        });
+        let expr = std::mem::replace(e, Expr::dummy());
+
+        e.kind = ExprKind::Paren(expr);
     }
 }
 
diff --git a/tests/ui-fulldeps/pprust-parenthesis-insertion.rs b/tests/ui-fulldeps/pprust-parenthesis-insertion.rs
index 2b41020d307..c566ac459e0 100644
--- a/tests/ui-fulldeps/pprust-parenthesis-insertion.rs
+++ b/tests/ui-fulldeps/pprust-parenthesis-insertion.rs
@@ -42,7 +42,7 @@ use std::process::ExitCode;
 
 use parser::parse_expr;
 use rustc_ast::ast::{Expr, ExprKind};
-use rustc_ast::mut_visit::{self, DummyAstNode as _, MutVisitor};
+use rustc_ast::mut_visit::{self, MutVisitor};
 use rustc_ast::ptr::P;
 use rustc_ast_pretty::pprust;
 use rustc_session::parse::ParseSess;
@@ -154,7 +154,7 @@ struct Unparenthesize;
 impl MutVisitor for Unparenthesize {
     fn visit_expr(&mut self, e: &mut P<Expr>) {
         while let ExprKind::Paren(paren) = &mut e.kind {
-            **e = mem::replace(&mut *paren, Expr::dummy());
+            *e = mem::replace(paren, Expr::dummy());
         }
         mut_visit::walk_expr(self, e);
     }
diff --git a/tests/ui/allocator/auxiliary/helper.rs b/tests/ui/allocator/auxiliary/helper.rs
index c638546a947..4267b901ca0 100644
--- a/tests/ui/allocator/auxiliary/helper.rs
+++ b/tests/ui/allocator/auxiliary/helper.rs
@@ -6,6 +6,6 @@
 extern crate alloc;
 use alloc::fmt;
 
-pub fn work_with(p: &fmt::Debug) {
+pub fn work_with(p: &dyn fmt::Debug) {
     drop(p);
 }
diff --git a/tests/ui/asm/cfg-parse-error.rs b/tests/ui/asm/cfg-parse-error.rs
new file mode 100644
index 00000000000..9b79d16a76d
--- /dev/null
+++ b/tests/ui/asm/cfg-parse-error.rs
@@ -0,0 +1,57 @@
+//@ needs-asm-support
+#![feature(asm_cfg)]
+
+use std::arch::asm;
+
+fn main() {
+    unsafe {
+        asm!(
+            "",
+            #[cfg(false)]
+            clobber_abi("C"),
+            #[cfg(false)]
+            options(att_syntax),
+            #[cfg(false)]
+            a = out(reg) x,
+            "",
+            //~^ ERROR expected one of `#`, `clobber_abi`, `const`, `in`, `inlateout`, `inout`, `label`, `lateout`, `options`, `out`, or `sym`, found `""`
+        );
+        asm!(
+            #[cfg(false)]
+            "",
+            #[cfg(false)]
+            const {
+                5
+            },
+            "",
+            //~^ ERROR expected one of `#`, `clobber_abi`, `const`, `in`, `inlateout`, `inout`, `label`, `lateout`, `options`, `out`, or `sym`, found `""`
+        );
+
+        asm!(
+            #[cfg_attr(true, cfg(false))]
+            const {
+                5
+            },
+            "",
+        );
+
+        // This is not accepted because `a = out(reg) x` is not a valid expression.
+        asm!(
+            #[cfg(false)]
+            a = out(reg) x, //~ ERROR expected token: `,`
+            "",
+        );
+
+        // For now, any non-cfg attributes are rejected
+        asm!(
+            #[rustfmt::skip] //~ ERROR this attribute is not supported on assembly
+            "",
+        );
+
+        // For now, any non-cfg attributes are rejected
+        asm!(
+            #![rustfmt::skip] //~ ERROR an inner attribute is not permitted in this context
+            "",
+        );
+    }
+}
diff --git a/tests/ui/asm/cfg-parse-error.stderr b/tests/ui/asm/cfg-parse-error.stderr
new file mode 100644
index 00000000000..8a70d39a43d
--- /dev/null
+++ b/tests/ui/asm/cfg-parse-error.stderr
@@ -0,0 +1,39 @@
+error: expected one of `#`, `clobber_abi`, `const`, `in`, `inlateout`, `inout`, `label`, `lateout`, `options`, `out`, or `sym`, found `""`
+  --> $DIR/cfg-parse-error.rs:16:13
+   |
+LL |             a = out(reg) x,
+   |                            - expected one of 11 possible tokens
+LL |             "",
+   |             ^^ unexpected token
+
+error: expected one of `#`, `clobber_abi`, `const`, `in`, `inlateout`, `inout`, `label`, `lateout`, `options`, `out`, or `sym`, found `""`
+  --> $DIR/cfg-parse-error.rs:26:13
+   |
+LL |             },
+   |               - expected one of 11 possible tokens
+LL |             "",
+   |             ^^ unexpected token
+
+error: expected token: `,`
+  --> $DIR/cfg-parse-error.rs:41:26
+   |
+LL |             a = out(reg) x,
+   |                          ^ expected `,`
+
+error: this attribute is not supported on assembly
+  --> $DIR/cfg-parse-error.rs:47:13
+   |
+LL |             #[rustfmt::skip]
+   |             ^^^^^^^^^^^^^^^^
+
+error: an inner attribute is not permitted in this context
+  --> $DIR/cfg-parse-error.rs:53:13
+   |
+LL |             #![rustfmt::skip]
+   |             ^^^^^^^^^^^^^^^^^
+   |
+   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files
+   = note: outer attributes, like `#[test]`, annotate the item following them
+
+error: aborting due to 5 previous errors
+
diff --git a/tests/ui/asm/cfg.rs b/tests/ui/asm/cfg.rs
new file mode 100644
index 00000000000..bcf86340b9d
--- /dev/null
+++ b/tests/ui/asm/cfg.rs
@@ -0,0 +1,125 @@
+// Check that `cfg` and `cfg_attr` work as expected.
+//
+//@ revisions: reva revb
+//@ only-x86_64
+//@ run-pass
+#![feature(asm_cfg, cfg_select)]
+
+use std::arch::{asm, naked_asm};
+
+#[unsafe(naked)]
+extern "C" fn ignore_const_operand() -> u64 {
+    naked_asm!(
+        "mov rax, 5",
+        #[cfg(revb)]
+        "mov rax, {a}",
+        "ret",
+        #[cfg(revb)]
+        a = const 10,
+    )
+}
+
+#[unsafe(naked)]
+extern "C" fn ignore_const_operand_cfg_attr() -> u64 {
+    naked_asm!(
+        "mov rax, 5",
+        #[cfg_attr(true, cfg(revb))]
+        "mov rax, {a}",
+        "ret",
+        #[cfg_attr(true, cfg(revb))]
+        a = const 10,
+    )
+}
+
+#[unsafe(naked)]
+extern "C" fn const_operand() -> u64 {
+    naked_asm!(
+        "mov rax, {a}",
+        "ret",
+        #[cfg(reva)]
+        a = const 5,
+        #[cfg(revb)]
+        a = const 10,
+    )
+}
+
+fn options() {
+    // Without the cfg, this throws an error that the `att_syntax` option is provided twice.
+    unsafe {
+        asm!(
+            "nop",
+            #[cfg(false)]
+            options(att_syntax),
+            options(att_syntax)
+        )
+    }
+}
+
+fn clobber_abi() {
+    // Without the cfg, this throws an error that the "C" abi is provided twice.
+    unsafe {
+        asm!(
+            "nop",
+            #[cfg(false)]
+            clobber_abi("C"),
+            clobber_abi("C"),
+        );
+    }
+}
+
+#[unsafe(naked)]
+extern "C" fn first_template() -> u64 {
+    naked_asm!(
+        #[cfg(reva)]
+        "mov rax, 5",
+        #[cfg(revb)]
+        "mov rax, 10",
+        "ret",
+    )
+}
+
+#[unsafe(naked)]
+extern "C" fn true_and_false() -> u64 {
+    naked_asm!(
+        "mov rax, 5",
+        #[cfg(true)]
+        #[cfg(false)]
+        "mov rax, 10",
+        "ret",
+    )
+}
+
+#[unsafe(naked)]
+extern "C" fn false_and_true() -> u64 {
+    naked_asm!(
+        "mov rax, 5",
+        #[cfg(false)]
+        #[cfg(true)]
+        "mov rax, 10",
+        "ret",
+    )
+}
+
+pub fn main() {
+    std::cfg_select! {
+        reva => {
+            assert_eq!(const_operand(), 5);
+            assert_eq!(ignore_const_operand_cfg_attr(), 5);
+            assert_eq!(ignore_const_operand(), 5);
+            assert_eq!(first_template(), 5);
+
+        }
+        revb => {
+            assert_eq!(const_operand(), 10);
+            assert_eq!(ignore_const_operand_cfg_attr(), 10);
+            assert_eq!(ignore_const_operand(), 10);
+            assert_eq!(first_template(), 10);
+
+        }
+    }
+    options();
+    clobber_abi();
+
+    assert_eq!(true_and_false(), 5);
+    assert_eq!(false_and_true(), 5);
+}
diff --git a/tests/ui/asm/parse-error.stderr b/tests/ui/asm/parse-error.stderr
index 0bba1fd8d9b..dff85a601b7 100644
--- a/tests/ui/asm/parse-error.stderr
+++ b/tests/ui/asm/parse-error.stderr
@@ -176,17 +176,17 @@ LL |         asm!("{a}", a = const foo, a = const bar);
    |
    = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {1} */"`
 
-error: expected one of `clobber_abi`, `const`, `in`, `inlateout`, `inout`, `label`, `lateout`, `options`, `out`, or `sym`, found `""`
+error: expected one of `#`, `clobber_abi`, `const`, `in`, `inlateout`, `inout`, `label`, `lateout`, `options`, `out`, or `sym`, found `""`
   --> $DIR/parse-error.rs:80:29
    |
 LL |         asm!("", options(), "");
-   |                             ^^ expected one of 10 possible tokens
+   |                             ^^ expected one of 11 possible tokens
 
-error: expected one of `clobber_abi`, `const`, `in`, `inlateout`, `inout`, `label`, `lateout`, `options`, `out`, or `sym`, found `"{}"`
+error: expected one of `#`, `clobber_abi`, `const`, `in`, `inlateout`, `inout`, `label`, `lateout`, `options`, `out`, or `sym`, found `"{}"`
   --> $DIR/parse-error.rs:82:33
    |
 LL |         asm!("{}", in(reg) foo, "{}", out(reg) foo);
-   |                                 ^^^^ expected one of 10 possible tokens
+   |                                 ^^^^ expected one of 11 possible tokens
 
 error: asm template must be a string literal
   --> $DIR/parse-error.rs:84:14
@@ -340,17 +340,17 @@ LL | global_asm!("{a}", a = const FOO, a = const BAR);
    |
    = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {1} */"`
 
-error: expected one of `clobber_abi`, `const`, `options`, or `sym`, found `""`
+error: expected one of `#`, `clobber_abi`, `const`, `options`, or `sym`, found `""`
   --> $DIR/parse-error.rs:137:28
    |
 LL | global_asm!("", options(), "");
-   |                            ^^ expected one of `clobber_abi`, `const`, `options`, or `sym`
+   |                            ^^ expected one of `#`, `clobber_abi`, `const`, `options`, or `sym`
 
-error: expected one of `clobber_abi`, `const`, `options`, or `sym`, found `"{}"`
+error: expected one of `#`, `clobber_abi`, `const`, `options`, or `sym`, found `"{}"`
   --> $DIR/parse-error.rs:139:30
    |
 LL | global_asm!("{}", const FOO, "{}", const FOO);
-   |                              ^^^^ expected one of `clobber_abi`, `const`, `options`, or `sym`
+   |                              ^^^^ expected one of `#`, `clobber_abi`, `const`, `options`, or `sym`
 
 error: asm template must be a string literal
   --> $DIR/parse-error.rs:141:13
diff --git a/tests/ui/associated-type-bounds/return-type-notation/path-missing.stderr b/tests/ui/associated-type-bounds/return-type-notation/path-missing.stderr
index edac09db89d..677fc0e10bb 100644
--- a/tests/ui/associated-type-bounds/return-type-notation/path-missing.stderr
+++ b/tests/ui/associated-type-bounds/return-type-notation/path-missing.stderr
@@ -8,9 +8,7 @@ error[E0575]: expected method or associated constant, found associated type `A::
   --> $DIR/path-missing.rs:12:5
    |
 LL |     <T as A>::bad(..): Send,
-   |     ^^^^^^^^^^^^^^^^^
-   |
-   = note: can't use a type alias as a constructor
+   |     ^^^^^^^^^^^^^^^^^ not a method or associated constant
 
 error[E0220]: associated function `method` not found for `T`
   --> $DIR/path-missing.rs:19:8
diff --git a/tests/ui/associated-types/associated-type-tuple-struct-construction.rs b/tests/ui/associated-types/associated-type-tuple-struct-construction.rs
deleted file mode 100644
index d5809ecd55d..00000000000
--- a/tests/ui/associated-types/associated-type-tuple-struct-construction.rs
+++ /dev/null
@@ -1,24 +0,0 @@
-// Users cannot yet construct structs through associated types
-// in both expressions and patterns
-
-#![feature(more_qualified_paths)]
-
-fn main() {
-    let <Foo as A>::Assoc(n) = <Foo as A>::Assoc(2);
-    //~^ ERROR expected method or associated constant, found associated type
-    //~| ERROR expected method or associated constant, found associated type
-    assert!(n == 2);
-}
-
-struct TupleStruct(i8);
-
-struct Foo;
-
-
-trait A {
-    type Assoc;
-}
-
-impl A for Foo {
-    type Assoc = TupleStruct;
-}
diff --git a/tests/ui/associated-types/associated-type-tuple-struct-construction.stderr b/tests/ui/associated-types/associated-type-tuple-struct-construction.stderr
deleted file mode 100644
index bca7deeb512..00000000000
--- a/tests/ui/associated-types/associated-type-tuple-struct-construction.stderr
+++ /dev/null
@@ -1,19 +0,0 @@
-error[E0575]: expected method or associated constant, found associated type `A::Assoc`
-  --> $DIR/associated-type-tuple-struct-construction.rs:7:32
-   |
-LL |     let <Foo as A>::Assoc(n) = <Foo as A>::Assoc(2);
-   |                                ^^^^^^^^^^^^^^^^^
-   |
-   = note: can't use a type alias as a constructor
-
-error[E0575]: expected method or associated constant, found associated type `A::Assoc`
-  --> $DIR/associated-type-tuple-struct-construction.rs:7:9
-   |
-LL |     let <Foo as A>::Assoc(n) = <Foo as A>::Assoc(2);
-   |         ^^^^^^^^^^^^^^^^^
-   |
-   = note: can't use a type alias as a constructor
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0575`.
diff --git a/tests/ui/associated-types/tuple-struct-expr-pat.fixed b/tests/ui/associated-types/tuple-struct-expr-pat.fixed
new file mode 100644
index 00000000000..d6e2385f821
--- /dev/null
+++ b/tests/ui/associated-types/tuple-struct-expr-pat.fixed
@@ -0,0 +1,48 @@
+// Check that fully qualified syntax can **not** be used in tuple struct expressions (calls) and
+// patterns. Both tuple struct expressions and patterns are resolved in value namespace and thus
+// can't be resolved through associated *types*.
+//
+//@ run-rustfix
+
+#![feature(more_qualified_paths)]
+
+fn main() {
+    let <T<0> as Trait>::Assoc {} = <T<0> as Trait>::Assoc {};
+    //~^ error: expected method or associated constant, found associated type
+    //~| error: expected tuple struct or tuple variant, found associated type
+    let <T<1> as Trait>::Assoc { 0: _a } = <T<1> as Trait>::Assoc { 0: 0 };
+    //~^ error: expected method or associated constant, found associated type
+    //~| error: expected tuple struct or tuple variant, found associated type
+    let <T<2> as Trait>::Assoc { 0: _a, 1: _b } = <T<2> as Trait>::Assoc { 0: 0, 1: 1 };
+    //~^ error: expected method or associated constant, found associated type
+    //~| error: expected tuple struct or tuple variant, found associated type
+    let <T<3> as Trait>::Assoc { 0: ref _a, 1: ref mut _b, 2: mut _c } = <T<3> as Trait>::Assoc { 0: 0, 1: 1, 2: 2 };
+    //~^ error: expected method or associated constant, found associated type
+    //~| error: expected tuple struct or tuple variant, found associated type
+}
+
+
+struct T<const N: usize>;
+
+struct T0();
+struct T1(u8);
+struct T2(u8, u8);
+struct T3(u8, u8, u8);
+
+trait Trait {
+    type Assoc;
+}
+
+impl Trait for T<0> {
+    type Assoc = T0;
+}
+
+impl Trait for T<1> {
+    type Assoc = T1;
+}
+impl Trait for T<2> {
+    type Assoc = T2;
+}
+impl Trait for T<3> {
+    type Assoc = T3;
+}
diff --git a/tests/ui/associated-types/tuple-struct-expr-pat.rs b/tests/ui/associated-types/tuple-struct-expr-pat.rs
new file mode 100644
index 00000000000..f27a5fe1753
--- /dev/null
+++ b/tests/ui/associated-types/tuple-struct-expr-pat.rs
@@ -0,0 +1,48 @@
+// Check that fully qualified syntax can **not** be used in tuple struct expressions (calls) and
+// patterns. Both tuple struct expressions and patterns are resolved in value namespace and thus
+// can't be resolved through associated *types*.
+//
+//@ run-rustfix
+
+#![feature(more_qualified_paths)]
+
+fn main() {
+    let <T<0> as Trait>::Assoc() = <T<0> as Trait>::Assoc();
+    //~^ error: expected method or associated constant, found associated type
+    //~| error: expected tuple struct or tuple variant, found associated type
+    let <T<1> as Trait>::Assoc(_a) = <T<1> as Trait>::Assoc(0);
+    //~^ error: expected method or associated constant, found associated type
+    //~| error: expected tuple struct or tuple variant, found associated type
+    let <T<2> as Trait>::Assoc(_a, _b) = <T<2> as Trait>::Assoc(0, 1);
+    //~^ error: expected method or associated constant, found associated type
+    //~| error: expected tuple struct or tuple variant, found associated type
+    let <T<3> as Trait>::Assoc(ref _a, ref mut _b, mut _c) = <T<3> as Trait>::Assoc(0, 1, 2);
+    //~^ error: expected method or associated constant, found associated type
+    //~| error: expected tuple struct or tuple variant, found associated type
+}
+
+
+struct T<const N: usize>;
+
+struct T0();
+struct T1(u8);
+struct T2(u8, u8);
+struct T3(u8, u8, u8);
+
+trait Trait {
+    type Assoc;
+}
+
+impl Trait for T<0> {
+    type Assoc = T0;
+}
+
+impl Trait for T<1> {
+    type Assoc = T1;
+}
+impl Trait for T<2> {
+    type Assoc = T2;
+}
+impl Trait for T<3> {
+    type Assoc = T3;
+}
diff --git a/tests/ui/associated-types/tuple-struct-expr-pat.stderr b/tests/ui/associated-types/tuple-struct-expr-pat.stderr
new file mode 100644
index 00000000000..135dfcb3447
--- /dev/null
+++ b/tests/ui/associated-types/tuple-struct-expr-pat.stderr
@@ -0,0 +1,97 @@
+error[E0575]: expected method or associated constant, found associated type `Trait::Assoc`
+  --> $DIR/tuple-struct-expr-pat.rs:10:36
+   |
+LL |     let <T<0> as Trait>::Assoc() = <T<0> as Trait>::Assoc();
+   |                                    ^^^^^^^^^^^^^^^^^^^^^^-- help: use struct expression instead: `{}`
+   |
+   = note: can't use a type alias as a constructor
+
+error[E0575]: expected tuple struct or tuple variant, found associated type `Trait::Assoc`
+  --> $DIR/tuple-struct-expr-pat.rs:10:9
+   |
+LL |     let <T<0> as Trait>::Assoc() = <T<0> as Trait>::Assoc();
+   |         ^^^^^^^^^^^^^^^^^^^^^^-- help: use struct pattern instead: `{}`
+   |
+   = note: can't use a type alias as tuple pattern
+
+error[E0575]: expected method or associated constant, found associated type `Trait::Assoc`
+  --> $DIR/tuple-struct-expr-pat.rs:13:38
+   |
+LL |     let <T<1> as Trait>::Assoc(_a) = <T<1> as Trait>::Assoc(0);
+   |                                      ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: can't use a type alias as a constructor
+help: use struct expression instead
+   |
+LL -     let <T<1> as Trait>::Assoc(_a) = <T<1> as Trait>::Assoc(0);
+LL +     let <T<1> as Trait>::Assoc(_a) = <T<1> as Trait>::Assoc { 0: 0 };
+   |
+
+error[E0575]: expected tuple struct or tuple variant, found associated type `Trait::Assoc`
+  --> $DIR/tuple-struct-expr-pat.rs:13:9
+   |
+LL |     let <T<1> as Trait>::Assoc(_a) = <T<1> as Trait>::Assoc(0);
+   |         ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: can't use a type alias as tuple pattern
+help: use struct pattern instead
+   |
+LL -     let <T<1> as Trait>::Assoc(_a) = <T<1> as Trait>::Assoc(0);
+LL +     let <T<1> as Trait>::Assoc { 0: _a } = <T<1> as Trait>::Assoc(0);
+   |
+
+error[E0575]: expected method or associated constant, found associated type `Trait::Assoc`
+  --> $DIR/tuple-struct-expr-pat.rs:16:42
+   |
+LL |     let <T<2> as Trait>::Assoc(_a, _b) = <T<2> as Trait>::Assoc(0, 1);
+   |                                          ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: can't use a type alias as a constructor
+help: use struct expression instead
+   |
+LL -     let <T<2> as Trait>::Assoc(_a, _b) = <T<2> as Trait>::Assoc(0, 1);
+LL +     let <T<2> as Trait>::Assoc(_a, _b) = <T<2> as Trait>::Assoc { 0: 0, 1: 1 };
+   |
+
+error[E0575]: expected tuple struct or tuple variant, found associated type `Trait::Assoc`
+  --> $DIR/tuple-struct-expr-pat.rs:16:9
+   |
+LL |     let <T<2> as Trait>::Assoc(_a, _b) = <T<2> as Trait>::Assoc(0, 1);
+   |         ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: can't use a type alias as tuple pattern
+help: use struct pattern instead
+   |
+LL -     let <T<2> as Trait>::Assoc(_a, _b) = <T<2> as Trait>::Assoc(0, 1);
+LL +     let <T<2> as Trait>::Assoc { 0: _a, 1: _b } = <T<2> as Trait>::Assoc(0, 1);
+   |
+
+error[E0575]: expected method or associated constant, found associated type `Trait::Assoc`
+  --> $DIR/tuple-struct-expr-pat.rs:19:62
+   |
+LL |     let <T<3> as Trait>::Assoc(ref _a, ref mut _b, mut _c) = <T<3> as Trait>::Assoc(0, 1, 2);
+   |                                                              ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: can't use a type alias as a constructor
+help: use struct expression instead
+   |
+LL -     let <T<3> as Trait>::Assoc(ref _a, ref mut _b, mut _c) = <T<3> as Trait>::Assoc(0, 1, 2);
+LL +     let <T<3> as Trait>::Assoc(ref _a, ref mut _b, mut _c) = <T<3> as Trait>::Assoc { 0: 0, 1: 1, 2: 2 };
+   |
+
+error[E0575]: expected tuple struct or tuple variant, found associated type `Trait::Assoc`
+  --> $DIR/tuple-struct-expr-pat.rs:19:9
+   |
+LL |     let <T<3> as Trait>::Assoc(ref _a, ref mut _b, mut _c) = <T<3> as Trait>::Assoc(0, 1, 2);
+   |         ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: can't use a type alias as tuple pattern
+help: use struct pattern instead
+   |
+LL -     let <T<3> as Trait>::Assoc(ref _a, ref mut _b, mut _c) = <T<3> as Trait>::Assoc(0, 1, 2);
+LL +     let <T<3> as Trait>::Assoc { 0: ref _a, 1: ref mut _b, 2: mut _c } = <T<3> as Trait>::Assoc(0, 1, 2);
+   |
+
+error: aborting due to 8 previous errors
+
+For more information about this error, try `rustc --explain E0575`.
diff --git a/tests/ui/async-await/async-closures/promote-in-body.rs b/tests/ui/async-await/async-closures/promote-in-body.rs
new file mode 100644
index 00000000000..ea95d680987
--- /dev/null
+++ b/tests/ui/async-await/async-closures/promote-in-body.rs
@@ -0,0 +1,13 @@
+//@ build-pass
+//@ compile-flags: --crate-type=lib
+//@ edition: 2024
+
+union U {
+    f: i32,
+}
+
+fn foo() {
+    async || {
+        &U { f: 1 }
+    };
+}
diff --git a/tests/ui/async-await/async-drop/type-parameter.rs b/tests/ui/async-await/async-drop/type-parameter.rs
new file mode 100644
index 00000000000..dde5f9f8e64
--- /dev/null
+++ b/tests/ui/async-await/async-drop/type-parameter.rs
@@ -0,0 +1,16 @@
+//@ edition: 2024
+// ex-ice: #140500
+#![crate_type = "lib"]
+#![feature(async_drop)]
+#![expect(incomplete_features)]
+use std::future::AsyncDrop;
+struct A;
+impl Drop for A {
+    fn drop(&mut self) {}
+}
+impl AsyncDrop for A {
+    fn drop(_wrong: impl Sized) {} //~ ERROR: method `drop` has a `self: Pin<&mut Self>` declaration in the trait, but not in the impl
+}
+async fn bar() {
+    A;
+}
diff --git a/tests/ui/async-await/async-drop/type-parameter.stderr b/tests/ui/async-await/async-drop/type-parameter.stderr
new file mode 100644
index 00000000000..841576b839e
--- /dev/null
+++ b/tests/ui/async-await/async-drop/type-parameter.stderr
@@ -0,0 +1,11 @@
+error[E0186]: method `drop` has a `self: Pin<&mut Self>` declaration in the trait, but not in the impl
+  --> $DIR/type-parameter.rs:12:5
+   |
+LL |     fn drop(_wrong: impl Sized) {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `self: Pin<&mut Self>` in impl
+   |
+   = note: `drop` from trait: `fn(Pin<&mut Self>) -> impl Future<Output = ()>`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0186`.
diff --git a/tests/ui/async-await/async-drop/unexpected-sort.rs b/tests/ui/async-await/async-drop/unexpected-sort.rs
new file mode 100644
index 00000000000..659e21eb241
--- /dev/null
+++ b/tests/ui/async-await/async-drop/unexpected-sort.rs
@@ -0,0 +1,18 @@
+// Ex-ice: #140484
+//@ edition: 2024
+#![crate_type = "lib"]
+#![allow(incomplete_features)]
+#![allow(non_camel_case_types)]
+#![feature(async_drop)]
+use std::future::AsyncDrop;
+struct a;
+impl Drop for a { //~ ERROR: not all trait items implemented, missing: `drop`
+    fn b() {} //~ ERROR: method `b` is not a member of trait `Drop`
+}
+impl AsyncDrop for a { //~ ERROR: not all trait items implemented, missing: `drop`
+    type c = ();
+    //~^ ERROR: type `c` is not a member of trait `AsyncDrop`
+}
+async fn bar() {
+    a;
+}
diff --git a/tests/ui/async-await/async-drop/unexpected-sort.stderr b/tests/ui/async-await/async-drop/unexpected-sort.stderr
new file mode 100644
index 00000000000..a6e4f9fd573
--- /dev/null
+++ b/tests/ui/async-await/async-drop/unexpected-sort.stderr
@@ -0,0 +1,32 @@
+error[E0407]: method `b` is not a member of trait `Drop`
+  --> $DIR/unexpected-sort.rs:10:5
+   |
+LL |     fn b() {}
+   |     ^^^^^^^^^ not a member of trait `Drop`
+
+error[E0437]: type `c` is not a member of trait `AsyncDrop`
+  --> $DIR/unexpected-sort.rs:13:5
+   |
+LL |     type c = ();
+   |     ^^^^^^^^^^^^ not a member of trait `AsyncDrop`
+
+error[E0046]: not all trait items implemented, missing: `drop`
+  --> $DIR/unexpected-sort.rs:9:1
+   |
+LL | impl Drop for a {
+   | ^^^^^^^^^^^^^^^ missing `drop` in implementation
+   |
+   = help: implement the missing item: `fn drop(&mut self) { todo!() }`
+
+error[E0046]: not all trait items implemented, missing: `drop`
+  --> $DIR/unexpected-sort.rs:12:1
+   |
+LL | impl AsyncDrop for a {
+   | ^^^^^^^^^^^^^^^^^^^^ missing `drop` in implementation
+   |
+   = help: implement the missing item: `async fn drop(self: Pin<&mut Self>) { todo!() }`
+
+error: aborting due to 4 previous errors
+
+Some errors have detailed explanations: E0046, E0407, E0437.
+For more information about an error, try `rustc --explain E0046`.
diff --git a/tests/ui/async-await/async-fn/edition-2015-not-async-bound.rs b/tests/ui/async-await/async-fn/edition-2015-not-async-bound.rs
index d222ddc081e..60a7dff7d49 100644
--- a/tests/ui/async-await/async-fn/edition-2015-not-async-bound.rs
+++ b/tests/ui/async-await/async-fn/edition-2015-not-async-bound.rs
@@ -1,3 +1,4 @@
+//@ edition:2015
 //@ check-pass
 // Make sure that we don't eagerly recover `async ::Bound` in edition 2015.
 
diff --git a/tests/ui/async-await/async-fn/edition-2015.rs b/tests/ui/async-await/async-fn/edition-2015.rs
index 341b9b10e67..5a81df3a4e4 100644
--- a/tests/ui/async-await/async-fn/edition-2015.rs
+++ b/tests/ui/async-await/async-fn/edition-2015.rs
@@ -1,3 +1,4 @@
+//@ edition:2015
 fn foo(x: impl async Fn()) -> impl async Fn() { x }
 //~^ ERROR `async` trait bounds are only allowed in Rust 2018 or later
 //~| ERROR `async` trait bounds are only allowed in Rust 2018 or later
diff --git a/tests/ui/async-await/async-fn/edition-2015.stderr b/tests/ui/async-await/async-fn/edition-2015.stderr
index ca9e64cd1bb..0bec00c162c 100644
--- a/tests/ui/async-await/async-fn/edition-2015.stderr
+++ b/tests/ui/async-await/async-fn/edition-2015.stderr
@@ -1,5 +1,5 @@
 error: `async` trait bounds are only allowed in Rust 2018 or later
-  --> $DIR/edition-2015.rs:1:16
+  --> $DIR/edition-2015.rs:2:16
    |
 LL | fn foo(x: impl async Fn()) -> impl async Fn() { x }
    |                ^^^^^
@@ -8,7 +8,7 @@ LL | fn foo(x: impl async Fn()) -> impl async Fn() { x }
    = note: for more on editions, read https://doc.rust-lang.org/edition-guide
 
 error: `async` trait bounds are only allowed in Rust 2018 or later
-  --> $DIR/edition-2015.rs:1:36
+  --> $DIR/edition-2015.rs:2:36
    |
 LL | fn foo(x: impl async Fn()) -> impl async Fn() { x }
    |                                    ^^^^^
@@ -17,7 +17,7 @@ LL | fn foo(x: impl async Fn()) -> impl async Fn() { x }
    = note: for more on editions, read https://doc.rust-lang.org/edition-guide
 
 error[E0658]: `async` trait bounds are unstable
-  --> $DIR/edition-2015.rs:1:16
+  --> $DIR/edition-2015.rs:2:16
    |
 LL | fn foo(x: impl async Fn()) -> impl async Fn() { x }
    |                ^^^^^
@@ -28,7 +28,7 @@ LL | fn foo(x: impl async Fn()) -> impl async Fn() { x }
    = help: use the desugared name of the async trait, such as `AsyncFn`
 
 error[E0658]: `async` trait bounds are unstable
-  --> $DIR/edition-2015.rs:1:36
+  --> $DIR/edition-2015.rs:2:36
    |
 LL | fn foo(x: impl async Fn()) -> impl async Fn() { x }
    |                                    ^^^^^
diff --git a/tests/ui/async-await/await-keyword/2015-edition-error-various-positions.rs b/tests/ui/async-await/await-keyword/2015-edition-error-various-positions.rs
index 50c1639996e..714a3328ecf 100644
--- a/tests/ui/async-await/await-keyword/2015-edition-error-various-positions.rs
+++ b/tests/ui/async-await/await-keyword/2015-edition-error-various-positions.rs
@@ -1,3 +1,4 @@
+//@ edition:2015
 #![allow(non_camel_case_types)]
 #![deny(keyword_idents)]
 
diff --git a/tests/ui/async-await/await-keyword/2015-edition-error-various-positions.stderr b/tests/ui/async-await/await-keyword/2015-edition-error-various-positions.stderr
index 8cea73f8651..70900e612f4 100644
--- a/tests/ui/async-await/await-keyword/2015-edition-error-various-positions.stderr
+++ b/tests/ui/async-await/await-keyword/2015-edition-error-various-positions.stderr
@@ -1,5 +1,5 @@
 error: `await` is a keyword in the 2018 edition
-  --> $DIR/2015-edition-error-various-positions.rs:5:13
+  --> $DIR/2015-edition-error-various-positions.rs:6:13
    |
 LL |     pub mod await {
    |             ^^^^^ help: you can use a raw identifier to stay compatible: `r#await`
@@ -7,14 +7,14 @@ LL |     pub mod await {
    = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
    = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
 note: the lint level is defined here
-  --> $DIR/2015-edition-error-various-positions.rs:2:9
+  --> $DIR/2015-edition-error-various-positions.rs:3:9
    |
 LL | #![deny(keyword_idents)]
    |         ^^^^^^^^^^^^^^
    = note: `#[deny(keyword_idents_2018)]` implied by `#[deny(keyword_idents)]`
 
 error: `await` is a keyword in the 2018 edition
-  --> $DIR/2015-edition-error-various-positions.rs:7:20
+  --> $DIR/2015-edition-error-various-positions.rs:8:20
    |
 LL |         pub struct await;
    |                    ^^^^^ help: you can use a raw identifier to stay compatible: `r#await`
@@ -23,7 +23,7 @@ LL |         pub struct await;
    = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
 
 error: `await` is a keyword in the 2018 edition
-  --> $DIR/2015-edition-error-various-positions.rs:11:16
+  --> $DIR/2015-edition-error-various-positions.rs:12:16
    |
 LL | use outer_mod::await::await;
    |                ^^^^^ help: you can use a raw identifier to stay compatible: `r#await`
@@ -32,7 +32,7 @@ LL | use outer_mod::await::await;
    = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
 
 error: `await` is a keyword in the 2018 edition
-  --> $DIR/2015-edition-error-various-positions.rs:11:23
+  --> $DIR/2015-edition-error-various-positions.rs:12:23
    |
 LL | use outer_mod::await::await;
    |                       ^^^^^ help: you can use a raw identifier to stay compatible: `r#await`
@@ -41,7 +41,7 @@ LL | use outer_mod::await::await;
    = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
 
 error: `await` is a keyword in the 2018 edition
-  --> $DIR/2015-edition-error-various-positions.rs:16:14
+  --> $DIR/2015-edition-error-various-positions.rs:17:14
    |
 LL | struct Foo { await: () }
    |              ^^^^^ help: you can use a raw identifier to stay compatible: `r#await`
@@ -50,7 +50,7 @@ LL | struct Foo { await: () }
    = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
 
 error: `await` is a keyword in the 2018 edition
-  --> $DIR/2015-edition-error-various-positions.rs:20:15
+  --> $DIR/2015-edition-error-various-positions.rs:21:15
    |
 LL | impl Foo { fn await() {} }
    |               ^^^^^ help: you can use a raw identifier to stay compatible: `r#await`
@@ -59,7 +59,7 @@ LL | impl Foo { fn await() {} }
    = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
 
 error: `await` is a keyword in the 2018 edition
-  --> $DIR/2015-edition-error-various-positions.rs:24:14
+  --> $DIR/2015-edition-error-various-positions.rs:25:14
    |
 LL | macro_rules! await {
    |              ^^^^^ help: you can use a raw identifier to stay compatible: `r#await`
@@ -68,7 +68,7 @@ LL | macro_rules! await {
    = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
 
 error: `await` is a keyword in the 2018 edition
-  --> $DIR/2015-edition-error-various-positions.rs:31:5
+  --> $DIR/2015-edition-error-various-positions.rs:32:5
    |
 LL |     await!();
    |     ^^^^^ help: you can use a raw identifier to stay compatible: `r#await`
@@ -77,7 +77,7 @@ LL |     await!();
    = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
 
 error: `await` is a keyword in the 2018 edition
-  --> $DIR/2015-edition-error-various-positions.rs:34:11
+  --> $DIR/2015-edition-error-various-positions.rs:35:11
    |
 LL |     match await { await => {} }
    |           ^^^^^ help: you can use a raw identifier to stay compatible: `r#await`
@@ -86,7 +86,7 @@ LL |     match await { await => {} }
    = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
 
 error: `await` is a keyword in the 2018 edition
-  --> $DIR/2015-edition-error-various-positions.rs:34:19
+  --> $DIR/2015-edition-error-various-positions.rs:35:19
    |
 LL |     match await { await => {} }
    |                   ^^^^^ help: you can use a raw identifier to stay compatible: `r#await`
diff --git a/tests/ui/async-await/await-keyword/2015-edition-warning.fixed b/tests/ui/async-await/await-keyword/2015-edition-warning.fixed
index 4cb8017c7ee..45758cb1039 100644
--- a/tests/ui/async-await/await-keyword/2015-edition-warning.fixed
+++ b/tests/ui/async-await/await-keyword/2015-edition-warning.fixed
@@ -1,3 +1,4 @@
+//@ edition:2015
 //@ run-rustfix
 
 #![allow(non_camel_case_types)]
diff --git a/tests/ui/async-await/await-keyword/2015-edition-warning.rs b/tests/ui/async-await/await-keyword/2015-edition-warning.rs
index d591a5af821..ea26abe072b 100644
--- a/tests/ui/async-await/await-keyword/2015-edition-warning.rs
+++ b/tests/ui/async-await/await-keyword/2015-edition-warning.rs
@@ -1,3 +1,4 @@
+//@ edition:2015
 //@ run-rustfix
 
 #![allow(non_camel_case_types)]
diff --git a/tests/ui/async-await/await-keyword/2015-edition-warning.stderr b/tests/ui/async-await/await-keyword/2015-edition-warning.stderr
index 70b7fa52a19..9d19a09092b 100644
--- a/tests/ui/async-await/await-keyword/2015-edition-warning.stderr
+++ b/tests/ui/async-await/await-keyword/2015-edition-warning.stderr
@@ -1,5 +1,5 @@
 error: `await` is a keyword in the 2018 edition
-  --> $DIR/2015-edition-warning.rs:7:13
+  --> $DIR/2015-edition-warning.rs:8:13
    |
 LL |     pub mod await {
    |             ^^^^^ help: you can use a raw identifier to stay compatible: `r#await`
@@ -7,14 +7,14 @@ LL |     pub mod await {
    = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
    = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
 note: the lint level is defined here
-  --> $DIR/2015-edition-warning.rs:4:9
+  --> $DIR/2015-edition-warning.rs:5:9
    |
 LL | #![deny(keyword_idents)]
    |         ^^^^^^^^^^^^^^
    = note: `#[deny(keyword_idents_2018)]` implied by `#[deny(keyword_idents)]`
 
 error: `await` is a keyword in the 2018 edition
-  --> $DIR/2015-edition-warning.rs:10:20
+  --> $DIR/2015-edition-warning.rs:11:20
    |
 LL |         pub struct await;
    |                    ^^^^^ help: you can use a raw identifier to stay compatible: `r#await`
@@ -23,7 +23,7 @@ LL |         pub struct await;
    = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
 
 error: `await` is a keyword in the 2018 edition
-  --> $DIR/2015-edition-warning.rs:15:16
+  --> $DIR/2015-edition-warning.rs:16:16
    |
 LL | use outer_mod::await::await;
    |                ^^^^^ help: you can use a raw identifier to stay compatible: `r#await`
@@ -32,7 +32,7 @@ LL | use outer_mod::await::await;
    = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
 
 error: `await` is a keyword in the 2018 edition
-  --> $DIR/2015-edition-warning.rs:15:23
+  --> $DIR/2015-edition-warning.rs:16:23
    |
 LL | use outer_mod::await::await;
    |                       ^^^^^ help: you can use a raw identifier to stay compatible: `r#await`
@@ -41,7 +41,7 @@ LL | use outer_mod::await::await;
    = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
 
 error: `await` is a keyword in the 2018 edition
-  --> $DIR/2015-edition-warning.rs:22:11
+  --> $DIR/2015-edition-warning.rs:23:11
    |
 LL |     match await { await => {} }
    |           ^^^^^ help: you can use a raw identifier to stay compatible: `r#await`
@@ -50,7 +50,7 @@ LL |     match await { await => {} }
    = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
 
 error: `await` is a keyword in the 2018 edition
-  --> $DIR/2015-edition-warning.rs:22:19
+  --> $DIR/2015-edition-warning.rs:23:19
    |
 LL |     match await { await => {} }
    |                   ^^^^^ help: you can use a raw identifier to stay compatible: `r#await`
diff --git a/tests/ui/async-await/dyn/mut-is-pointer-like.stderr b/tests/ui/async-await/dyn/mut-is-pointer-like.stderr
index 07c3fd3527f..6689539ff45 100644
--- a/tests/ui/async-await/dyn/mut-is-pointer-like.stderr
+++ b/tests/ui/async-await/dyn/mut-is-pointer-like.stderr
@@ -8,10 +8,10 @@ LL | #![feature(async_fn_in_dyn_trait)]
    = note: `#[warn(incomplete_features)]` on by default
 
 error[E0038]: the trait `AsyncTrait` is not dyn compatible
-  --> $DIR/mut-is-pointer-like.rs:35:16
+  --> $DIR/mut-is-pointer-like.rs:35:29
    |
 LL |         let x: Pin<&mut dyn AsyncTrait<Output = ()>> = f;
-   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `AsyncTrait` is not dyn compatible
+   |                             ^^^^^^^^^^^^^^^^^^^^^^^ `AsyncTrait` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
       for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
@@ -24,24 +24,6 @@ LL |     async fn async_dispatch(self: Pin<&mut Self>) -> Self::Output;
    |              ^^^^^^^^^^^^^^ ...because method `async_dispatch` is `async`
    = help: consider moving `async_dispatch` to another trait
 
-error[E0038]: the trait `AsyncTrait` is not dyn compatible
-  --> $DIR/mut-is-pointer-like.rs:35:56
-   |
-LL |         let x: Pin<&mut dyn AsyncTrait<Output = ()>> = f;
-   |                                                        ^ `AsyncTrait` is not dyn compatible
-   |
-note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
-  --> $DIR/mut-is-pointer-like.rs:16:14
-   |
-LL | trait AsyncTrait {
-   |       ---------- this trait is not dyn compatible...
-...
-LL |     async fn async_dispatch(self: Pin<&mut Self>) -> Self::Output;
-   |              ^^^^^^^^^^^^^^ ...because method `async_dispatch` is `async`
-   = help: consider moving `async_dispatch` to another trait
-   = note: required for the cast from `Pin<&mut {async block@$DIR/mut-is-pointer-like.rs:32:32: 32:37}>` to `Pin<&mut dyn AsyncTrait<Output = ()>>`
-
-error: aborting due to 2 previous errors; 1 warning emitted
+error: aborting due to 1 previous error; 1 warning emitted
 
 For more information about this error, try `rustc --explain E0038`.
diff --git a/tests/ui/async-await/dyn/works.stderr b/tests/ui/async-await/dyn/works.stderr
index 1fe2b28eca8..338479d8b70 100644
--- a/tests/ui/async-await/dyn/works.stderr
+++ b/tests/ui/async-await/dyn/works.stderr
@@ -8,10 +8,10 @@ LL | #![feature(async_fn_in_dyn_trait)]
    = note: `#[warn(incomplete_features)]` on by default
 
 error[E0038]: the trait `AsyncTrait` is not dyn compatible
-  --> $DIR/works.rs:27:34
+  --> $DIR/works.rs:27:21
    |
 LL |         let x: &dyn AsyncTrait = &"hello, world!";
-   |                                  ^^^^^^^^^^^^^^^^ `AsyncTrait` is not dyn compatible
+   |                     ^^^^^^^^^^ `AsyncTrait` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
       for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
@@ -23,25 +23,7 @@ LL |     async fn async_dispatch(&self);
    |              ^^^^^^^^^^^^^^ ...because method `async_dispatch` is `async`
    = help: consider moving `async_dispatch` to another trait
    = help: only type `&'static str` implements `AsyncTrait`; consider using it directly instead.
-   = note: required for the cast from `&&'static str` to `&dyn AsyncTrait`
 
-error[E0038]: the trait `AsyncTrait` is not dyn compatible
-  --> $DIR/works.rs:27:16
-   |
-LL |         let x: &dyn AsyncTrait = &"hello, world!";
-   |                ^^^^^^^^^^^^^^^ `AsyncTrait` is not dyn compatible
-   |
-note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
-  --> $DIR/works.rs:14:14
-   |
-LL | trait AsyncTrait {
-   |       ---------- this trait is not dyn compatible...
-LL |     async fn async_dispatch(&self);
-   |              ^^^^^^^^^^^^^^ ...because method `async_dispatch` is `async`
-   = help: consider moving `async_dispatch` to another trait
-   = help: only type `&'static str` implements `AsyncTrait`; consider using it directly instead.
-
-error: aborting due to 2 previous errors; 1 warning emitted
+error: aborting due to 1 previous error; 1 warning emitted
 
 For more information about this error, try `rustc --explain E0038`.
diff --git a/tests/ui/async-await/dyn/wrong-size.stderr b/tests/ui/async-await/dyn/wrong-size.stderr
index b4684f4fc17..a465f91f62a 100644
--- a/tests/ui/async-await/dyn/wrong-size.stderr
+++ b/tests/ui/async-await/dyn/wrong-size.stderr
@@ -8,10 +8,10 @@ LL | #![feature(async_fn_in_dyn_trait)]
    = note: `#[warn(incomplete_features)]` on by default
 
 error[E0038]: the trait `AsyncTrait` is not dyn compatible
-  --> $DIR/wrong-size.rs:21:30
+  --> $DIR/wrong-size.rs:21:17
    |
 LL |     let x: &dyn AsyncTrait = &"hello, world!";
-   |                              ^^^^^^^^^^^^^^^^ `AsyncTrait` is not dyn compatible
+   |                 ^^^^^^^^^^ `AsyncTrait` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
       for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
@@ -23,25 +23,7 @@ LL |     async fn async_dispatch(&self);
    |              ^^^^^^^^^^^^^^ ...because method `async_dispatch` is `async`
    = help: consider moving `async_dispatch` to another trait
    = help: only type `&'static str` implements `AsyncTrait`; consider using it directly instead.
-   = note: required for the cast from `&&'static str` to `&dyn AsyncTrait`
 
-error[E0038]: the trait `AsyncTrait` is not dyn compatible
-  --> $DIR/wrong-size.rs:21:12
-   |
-LL |     let x: &dyn AsyncTrait = &"hello, world!";
-   |            ^^^^^^^^^^^^^^^ `AsyncTrait` is not dyn compatible
-   |
-note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
-  --> $DIR/wrong-size.rs:9:14
-   |
-LL | trait AsyncTrait {
-   |       ---------- this trait is not dyn compatible...
-LL |     async fn async_dispatch(&self);
-   |              ^^^^^^^^^^^^^^ ...because method `async_dispatch` is `async`
-   = help: consider moving `async_dispatch` to another trait
-   = help: only type `&'static str` implements `AsyncTrait`; consider using it directly instead.
-
-error: aborting due to 2 previous errors; 1 warning emitted
+error: aborting due to 1 previous error; 1 warning emitted
 
 For more information about this error, try `rustc --explain E0038`.
diff --git a/tests/ui/async-await/for-await-2015.rs b/tests/ui/async-await/for-await-2015.rs
index 89ff256da1d..c2bd39c8446 100644
--- a/tests/ui/async-await/for-await-2015.rs
+++ b/tests/ui/async-await/for-await-2015.rs
@@ -1,3 +1,4 @@
+//@ edition:2015
 //@ check-pass
 
 #![feature(async_for_loop)]
diff --git a/tests/ui/async-await/in-trait/dyn-compatibility.stderr b/tests/ui/async-await/in-trait/dyn-compatibility.stderr
index 553bcbf89d5..f0c5dc53478 100644
--- a/tests/ui/async-await/in-trait/dyn-compatibility.stderr
+++ b/tests/ui/async-await/in-trait/dyn-compatibility.stderr
@@ -1,8 +1,8 @@
 error[E0038]: the trait `Foo` is not dyn compatible
-  --> $DIR/dyn-compatibility.rs:9:12
+  --> $DIR/dyn-compatibility.rs:9:17
    |
 LL |     let x: &dyn Foo = todo!();
-   |            ^^^^^^^^ `Foo` is not dyn compatible
+   |                 ^^^ `Foo` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
       for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
diff --git a/tests/ui/async-await/issue-65634-raw-ident-suggestion.edition2015.stderr b/tests/ui/async-await/issue-65634-raw-ident-suggestion.edition2015.stderr
index 2bdc1347c81..8ce4d4ea06a 100644
--- a/tests/ui/async-await/issue-65634-raw-ident-suggestion.edition2015.stderr
+++ b/tests/ui/async-await/issue-65634-raw-ident-suggestion.edition2015.stderr
@@ -1,16 +1,16 @@
 error[E0034]: multiple applicable items in scope
-  --> $DIR/issue-65634-raw-ident-suggestion.rs:24:13
+  --> $DIR/issue-65634-raw-ident-suggestion.rs:25:13
    |
 LL |     r#fn {}.r#struct();
    |             ^^^^^^^^ multiple `r#struct` found
    |
 note: candidate #1 is defined in an impl of the trait `async` for the type `r#fn`
-  --> $DIR/issue-65634-raw-ident-suggestion.rs:7:5
+  --> $DIR/issue-65634-raw-ident-suggestion.rs:8:5
    |
 LL |     fn r#struct(&self) {
    |     ^^^^^^^^^^^^^^^^^^
 note: candidate #2 is defined in an impl of the trait `await` for the type `r#fn`
-  --> $DIR/issue-65634-raw-ident-suggestion.rs:13:5
+  --> $DIR/issue-65634-raw-ident-suggestion.rs:14:5
    |
 LL |     fn r#struct(&self) {
    |     ^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/async-await/issue-65634-raw-ident-suggestion.edition2018.stderr b/tests/ui/async-await/issue-65634-raw-ident-suggestion.edition2018.stderr
index ab10ab749fe..d910ef9872c 100644
--- a/tests/ui/async-await/issue-65634-raw-ident-suggestion.edition2018.stderr
+++ b/tests/ui/async-await/issue-65634-raw-ident-suggestion.edition2018.stderr
@@ -1,16 +1,16 @@
 error[E0034]: multiple applicable items in scope
-  --> $DIR/issue-65634-raw-ident-suggestion.rs:24:13
+  --> $DIR/issue-65634-raw-ident-suggestion.rs:25:13
    |
 LL |     r#fn {}.r#struct();
    |             ^^^^^^^^ multiple `r#struct` found
    |
 note: candidate #1 is defined in an impl of the trait `r#async` for the type `r#fn`
-  --> $DIR/issue-65634-raw-ident-suggestion.rs:7:5
+  --> $DIR/issue-65634-raw-ident-suggestion.rs:8:5
    |
 LL |     fn r#struct(&self) {
    |     ^^^^^^^^^^^^^^^^^^
 note: candidate #2 is defined in an impl of the trait `r#await` for the type `r#fn`
-  --> $DIR/issue-65634-raw-ident-suggestion.rs:13:5
+  --> $DIR/issue-65634-raw-ident-suggestion.rs:14:5
    |
 LL |     fn r#struct(&self) {
    |     ^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/async-await/issue-65634-raw-ident-suggestion.rs b/tests/ui/async-await/issue-65634-raw-ident-suggestion.rs
index ef5760f4846..98f5b6dd9f9 100644
--- a/tests/ui/async-await/issue-65634-raw-ident-suggestion.rs
+++ b/tests/ui/async-await/issue-65634-raw-ident-suggestion.rs
@@ -1,4 +1,5 @@
 //@ revisions: edition2015 edition2018
+//@[edition2015]edition:2015
 //@[edition2018]edition:2018
 
 #![allow(non_camel_case_types)]
diff --git a/tests/ui/async-await/suggest-switching-edition-on-await-cargo.rs b/tests/ui/async-await/suggest-switching-edition-on-await-cargo.rs
index bcb5cb94b77..555b0110521 100644
--- a/tests/ui/async-await/suggest-switching-edition-on-await-cargo.rs
+++ b/tests/ui/async-await/suggest-switching-edition-on-await-cargo.rs
@@ -1,3 +1,4 @@
+//@ edition:2015
 //@ rustc-env:CARGO_CRATE_NAME=foo
 
 use std::pin::Pin;
diff --git a/tests/ui/async-await/suggest-switching-edition-on-await-cargo.stderr b/tests/ui/async-await/suggest-switching-edition-on-await-cargo.stderr
index 11f5825c232..c5f1793731e 100644
--- a/tests/ui/async-await/suggest-switching-edition-on-await-cargo.stderr
+++ b/tests/ui/async-await/suggest-switching-edition-on-await-cargo.stderr
@@ -1,5 +1,5 @@
 error[E0609]: no field `await` on type `await_on_struct_missing::S`
-  --> $DIR/suggest-switching-edition-on-await-cargo.rs:11:7
+  --> $DIR/suggest-switching-edition-on-await-cargo.rs:12:7
    |
 LL |     x.await;
    |       ^^^^^ unknown field
@@ -9,7 +9,7 @@ LL |     x.await;
    = note: for more on editions, read https://doc.rust-lang.org/edition-guide
 
 error[E0609]: no field `await` on type `await_on_struct_similar::S`
-  --> $DIR/suggest-switching-edition-on-await-cargo.rs:24:7
+  --> $DIR/suggest-switching-edition-on-await-cargo.rs:25:7
    |
 LL |     x.await;
    |       ^^^^^ unknown field
@@ -24,7 +24,7 @@ LL +     x.awai;
    |
 
 error[E0609]: no field `await` on type `Pin<&mut dyn Future<Output = ()>>`
-  --> $DIR/suggest-switching-edition-on-await-cargo.rs:34:7
+  --> $DIR/suggest-switching-edition-on-await-cargo.rs:35:7
    |
 LL |     x.await;
    |       ^^^^^ unknown field
@@ -34,7 +34,7 @@ LL |     x.await;
    = note: for more on editions, read https://doc.rust-lang.org/edition-guide
 
 error[E0609]: no field `await` on type `impl Future<Output = ()>`
-  --> $DIR/suggest-switching-edition-on-await-cargo.rs:43:7
+  --> $DIR/suggest-switching-edition-on-await-cargo.rs:44:7
    |
 LL |     x.await;
    |       ^^^^^ unknown field
diff --git a/tests/ui/async-await/suggest-switching-edition-on-await.rs b/tests/ui/async-await/suggest-switching-edition-on-await.rs
index 0907a87e02c..6b639fa0b4e 100644
--- a/tests/ui/async-await/suggest-switching-edition-on-await.rs
+++ b/tests/ui/async-await/suggest-switching-edition-on-await.rs
@@ -1,3 +1,4 @@
+//@ edition:2015
 use std::pin::Pin;
 use std::future::Future;
 
diff --git a/tests/ui/async-await/suggest-switching-edition-on-await.stderr b/tests/ui/async-await/suggest-switching-edition-on-await.stderr
index 2ede8d5b7f4..bf03016222e 100644
--- a/tests/ui/async-await/suggest-switching-edition-on-await.stderr
+++ b/tests/ui/async-await/suggest-switching-edition-on-await.stderr
@@ -1,5 +1,5 @@
 error[E0609]: no field `await` on type `await_on_struct_missing::S`
-  --> $DIR/suggest-switching-edition-on-await.rs:9:7
+  --> $DIR/suggest-switching-edition-on-await.rs:10:7
    |
 LL |     x.await;
    |       ^^^^^ unknown field
@@ -9,7 +9,7 @@ LL |     x.await;
    = note: for more on editions, read https://doc.rust-lang.org/edition-guide
 
 error[E0609]: no field `await` on type `await_on_struct_similar::S`
-  --> $DIR/suggest-switching-edition-on-await.rs:22:7
+  --> $DIR/suggest-switching-edition-on-await.rs:23:7
    |
 LL |     x.await;
    |       ^^^^^ unknown field
@@ -24,7 +24,7 @@ LL +     x.awai;
    |
 
 error[E0609]: no field `await` on type `Pin<&mut dyn Future<Output = ()>>`
-  --> $DIR/suggest-switching-edition-on-await.rs:32:7
+  --> $DIR/suggest-switching-edition-on-await.rs:33:7
    |
 LL |     x.await;
    |       ^^^^^ unknown field
@@ -34,7 +34,7 @@ LL |     x.await;
    = note: for more on editions, read https://doc.rust-lang.org/edition-guide
 
 error[E0609]: no field `await` on type `impl Future<Output = ()>`
-  --> $DIR/suggest-switching-edition-on-await.rs:41:7
+  --> $DIR/suggest-switching-edition-on-await.rs:42:7
    |
 LL |     x.await;
    |       ^^^^^ unknown field
diff --git a/tests/ui/attributes/auxiliary/external-macro-use.rs b/tests/ui/attributes/auxiliary/external-macro-use.rs
new file mode 100644
index 00000000000..beeb7fe689c
--- /dev/null
+++ b/tests/ui/attributes/auxiliary/external-macro-use.rs
@@ -0,0 +1,7 @@
+extern crate proc_macro;
+use proc_macro::*;
+
+#[proc_macro_attribute]
+pub fn a(_: TokenStream, input: TokenStream) -> TokenStream {
+   input
+}
diff --git a/tests/ui/attributes/illegal-macro-use.rs b/tests/ui/attributes/illegal-macro-use.rs
new file mode 100644
index 00000000000..5a567107a6e
--- /dev/null
+++ b/tests/ui/attributes/illegal-macro-use.rs
@@ -0,0 +1,15 @@
+// issue#140255
+
+#[macro_use::a]       //~ ERROR failed to resolve: use of unresolved module or unlinked crate `macro_use`
+fn f0() {}
+
+#[macro_use::a::b]    //~ ERROR failed to resolve: use of unresolved module or unlinked crate `macro_use`
+fn f1() {}
+
+#[macro_escape::a]    //~ ERROR failed to resolve: use of unresolved module or unlinked crate `macro_escape`
+fn f2() {}
+
+#[macro_escape::a::b] //~ ERROR failed to resolve: use of unresolved module or unlinked crate `macro_escape`
+fn f3() {}
+
+fn main() {}
diff --git a/tests/ui/attributes/illegal-macro-use.stderr b/tests/ui/attributes/illegal-macro-use.stderr
new file mode 100644
index 00000000000..fa6bb83d588
--- /dev/null
+++ b/tests/ui/attributes/illegal-macro-use.stderr
@@ -0,0 +1,27 @@
+error[E0433]: failed to resolve: use of unresolved module or unlinked crate `macro_escape`
+  --> $DIR/illegal-macro-use.rs:12:3
+   |
+LL | #[macro_escape::a::b]
+   |   ^^^^^^^^^^^^ use of unresolved module or unlinked crate `macro_escape`
+
+error[E0433]: failed to resolve: use of unresolved module or unlinked crate `macro_escape`
+  --> $DIR/illegal-macro-use.rs:9:3
+   |
+LL | #[macro_escape::a]
+   |   ^^^^^^^^^^^^ use of unresolved module or unlinked crate `macro_escape`
+
+error[E0433]: failed to resolve: use of unresolved module or unlinked crate `macro_use`
+  --> $DIR/illegal-macro-use.rs:6:3
+   |
+LL | #[macro_use::a::b]
+   |   ^^^^^^^^^ use of unresolved module or unlinked crate `macro_use`
+
+error[E0433]: failed to resolve: use of unresolved module or unlinked crate `macro_use`
+  --> $DIR/illegal-macro-use.rs:3:3
+   |
+LL | #[macro_use::a]
+   |   ^^^^^^^^^ use of unresolved module or unlinked crate `macro_use`
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0433`.
diff --git a/tests/ui/attributes/use-extern-crate-named-macro-use.rs b/tests/ui/attributes/use-extern-crate-named-macro-use.rs
new file mode 100644
index 00000000000..5b322ccfaf7
--- /dev/null
+++ b/tests/ui/attributes/use-extern-crate-named-macro-use.rs
@@ -0,0 +1,11 @@
+//@ check-pass
+//@ proc-macro: external-macro-use.rs
+
+// issue#140255
+
+extern crate external_macro_use as macro_use;
+
+#[macro_use::a]
+fn f() {}
+
+fn main() {}
diff --git a/tests/ui/autoderef-full-lval.rs b/tests/ui/autoderef-full-lval.rs
deleted file mode 100644
index 0fadc5c9827..00000000000
--- a/tests/ui/autoderef-full-lval.rs
+++ /dev/null
@@ -1,25 +0,0 @@
-struct Clam {
-    x: Box<isize>,
-    y: Box<isize>,
-}
-
-
-
-struct Fish {
-    a: Box<isize>,
-}
-
-fn main() {
-    let a: Clam = Clam{ x: Box::new(1), y: Box::new(2) };
-    let b: Clam = Clam{ x: Box::new(10), y: Box::new(20) };
-    let z: isize = a.x + b.y;
-    //~^ ERROR cannot add `Box<isize>` to `Box<isize>`
-    println!("{}", z);
-    assert_eq!(z, 21);
-    let forty: Fish = Fish{ a: Box::new(40) };
-    let two: Fish = Fish{ a: Box::new(2) };
-    let answer: isize = forty.a + two.a;
-    //~^ ERROR cannot add `Box<isize>` to `Box<isize>`
-    println!("{}", answer);
-    assert_eq!(answer, 42);
-}
diff --git a/tests/ui/autodiff/autodiff_illegal.rs b/tests/ui/autodiff/autodiff_illegal.rs
index a916bd8b857..a53b6d5e589 100644
--- a/tests/ui/autodiff/autodiff_illegal.rs
+++ b/tests/ui/autodiff/autodiff_illegal.rs
@@ -7,38 +7,38 @@
 
 // Test that invalid ad macros give nice errors and don't ICE.
 
-use std::autodiff::autodiff;
+use std::autodiff::{autodiff_forward, autodiff_reverse};
 
 // We can't use Duplicated on scalars
-#[autodiff(df1, Reverse, Duplicated)]
+#[autodiff_reverse(df1, Duplicated)]
 pub fn f1(x: f64) {
     //~^ ERROR     Duplicated can not be used for this type
     unimplemented!()
 }
 
 // Too many activities
-#[autodiff(df3, Reverse, Duplicated, Const)]
+#[autodiff_reverse(df3, Duplicated, Const)]
 pub fn f3(x: f64) {
     //~^^ ERROR     expected 1 activities, but found 2
     unimplemented!()
 }
 
 // To few activities
-#[autodiff(df4, Reverse)]
+#[autodiff_reverse(df4)]
 pub fn f4(x: f64) {
     //~^^ ERROR     expected 1 activities, but found 0
     unimplemented!()
 }
 
 // We can't use Dual in Reverse mode
-#[autodiff(df5, Reverse, Dual)]
+#[autodiff_reverse(df5, Dual)]
 pub fn f5(x: f64) {
     //~^^ ERROR     Dual can not be used in Reverse Mode
     unimplemented!()
 }
 
 // We can't use Duplicated in Forward mode
-#[autodiff(df6, Forward, Duplicated)]
+#[autodiff_forward(df6, Duplicated)]
 pub fn f6(x: f64) {
     //~^^ ERROR Duplicated can not be used in Forward Mode
     //~^^ ERROR Duplicated can not be used for this type
@@ -46,36 +46,36 @@ pub fn f6(x: f64) {
 }
 
 fn dummy() {
-    #[autodiff(df7, Forward, Dual)]
+    #[autodiff_forward(df7, Dual)]
     let mut x = 5;
     //~^ ERROR autodiff must be applied to function
 
-    #[autodiff(df7, Forward, Dual)]
+    #[autodiff_forward(df7, Dual)]
     x = x + 3;
     //~^^ ERROR attributes on expressions are experimental [E0658]
     //~^^ ERROR autodiff must be applied to function
 
-    #[autodiff(df7, Forward, Dual)]
+    #[autodiff_forward(df7, Dual)]
     let add_one_v2 = |x: u32| -> u32 { x + 1 };
     //~^ ERROR autodiff must be applied to function
 }
 
 // Malformed, where args?
-#[autodiff]
+#[autodiff_forward]
 pub fn f7(x: f64) {
     //~^ ERROR autodiff requires at least a name and mode
     unimplemented!()
 }
 
 // Malformed, where args?
-#[autodiff()]
+#[autodiff_forward()]
 pub fn f8(x: f64) {
     //~^ ERROR autodiff requires at least a name and mode
     unimplemented!()
 }
 
 // Invalid attribute syntax
-#[autodiff = ""]
+#[autodiff_forward = ""]
 pub fn f9(x: f64) {
     //~^ ERROR autodiff requires at least a name and mode
     unimplemented!()
@@ -84,29 +84,15 @@ pub fn f9(x: f64) {
 fn fn_exists() {}
 
 // We colide with an already existing function
-#[autodiff(fn_exists, Reverse, Active)]
+#[autodiff_reverse(fn_exists, Active)]
 pub fn f10(x: f64) {
     //~^^ ERROR the name `fn_exists` is defined multiple times [E0428]
     unimplemented!()
 }
 
-// Malformed, missing a mode
-#[autodiff(df11)]
-pub fn f11() {
-    //~^ ERROR autodiff requires at least a name and mode
-    unimplemented!()
-}
-
-// Invalid Mode
-#[autodiff(df12, Debug)]
-pub fn f12() {
-    //~^^ ERROR unknown Mode: `Debug`. Use `Forward` or `Reverse`
-    unimplemented!()
-}
-
 // Invalid, please pick one Mode
 // or use two autodiff macros.
-#[autodiff(df13, Forward, Reverse)]
+#[autodiff_reverse(df13, Reverse)]
 pub fn f13() {
     //~^^ ERROR did not recognize Activity: `Reverse`
     unimplemented!()
@@ -117,7 +103,7 @@ struct Foo {}
 // We can't handle Active structs, because that would mean (in the general case), that we would
 // need to allocate and initialize arbitrary user types. We have Duplicated/Dual input args for
 // that. FIXME: Give a nicer error and suggest to the user to have a `&mut Foo` input instead.
-#[autodiff(df14, Reverse, Active, Active)]
+#[autodiff_reverse(df14, Active, Active)]
 fn f14(x: f32) -> Foo {
     unimplemented!()
 }
@@ -127,14 +113,14 @@ type MyFloat = f32;
 // We would like to support type alias to f32/f64 in argument type in the future,
 // but that requires us to implement our checks at a later stage
 // like THIR which has type information available.
-#[autodiff(df15, Reverse, Active, Active)]
+#[autodiff_reverse(df15, Active, Active)]
 fn f15(x: MyFloat) -> f32 {
     //~^^ ERROR failed to resolve: use of undeclared type `MyFloat` [E0433]
     unimplemented!()
 }
 
 // We would like to support type alias to f32/f64 in return type in the future
-#[autodiff(df16, Reverse, Active, Active)]
+#[autodiff_reverse(df16, Active, Active)]
 fn f16(x: f32) -> MyFloat {
     unimplemented!()
 }
@@ -145,40 +131,40 @@ struct F64Trans {
 }
 
 // We would like to support `#[repr(transparent)]` f32/f64 wrapper in return type in the future
-#[autodiff(df17, Reverse, Active, Active)]
+#[autodiff_reverse(df17, Active, Active)]
 fn f17(x: f64) -> F64Trans {
     unimplemented!()
 }
 
 // We would like to support `#[repr(transparent)]` f32/f64 wrapper in argument type in the future
-#[autodiff(df18, Reverse, Active, Active)]
+#[autodiff_reverse(df18, Active, Active)]
 fn f18(x: F64Trans) -> f64 {
     //~^^ ERROR failed to resolve: use of undeclared type `F64Trans` [E0433]
     unimplemented!()
 }
 
 // Invalid return activity
-#[autodiff(df19, Forward, Dual, Active)]
+#[autodiff_forward(df19, Dual, Active)]
 fn f19(x: f32) -> f32 {
     //~^^ ERROR invalid return activity Active in Forward Mode
     unimplemented!()
 }
 
-#[autodiff(df20, Reverse, Active, Dual)]
+#[autodiff_reverse(df20, Active, Dual)]
 fn f20(x: f32) -> f32 {
     //~^^ ERROR invalid return activity Dual in Reverse Mode
     unimplemented!()
 }
 
 // Duplicated cannot be used as return activity
-#[autodiff(df21, Reverse, Active, Duplicated)]
+#[autodiff_reverse(df21, Active, Duplicated)]
 fn f21(x: f32) -> f32 {
     //~^^ ERROR invalid return activity Duplicated in Reverse Mode
     unimplemented!()
 }
 
 struct DoesNotImplDefault;
-#[autodiff(df22, Forward, Dual)]
+#[autodiff_forward(df22, Dual)]
 pub fn f22() -> DoesNotImplDefault {
     //~^^ ERROR the function or associated item `default` exists for tuple `(DoesNotImplDefault, DoesNotImplDefault)`, but its trait bounds were not satisfied
     unimplemented!()
diff --git a/tests/ui/autodiff/autodiff_illegal.stderr b/tests/ui/autodiff/autodiff_illegal.stderr
index b119f61b8ae..ad6f10af467 100644
--- a/tests/ui/autodiff/autodiff_illegal.stderr
+++ b/tests/ui/autodiff/autodiff_illegal.stderr
@@ -1,8 +1,8 @@
 error[E0658]: attributes on expressions are experimental
   --> $DIR/autodiff_illegal.rs:53:5
    |
-LL |     #[autodiff(df7, Forward, Dual)]
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     #[autodiff_forward(df7, Dual)]
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> for more information
    = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable
@@ -17,26 +17,26 @@ LL | pub fn f1(x: f64) {
 error: expected 1 activities, but found 2
   --> $DIR/autodiff_illegal.rs:20:1
    |
-LL | #[autodiff(df3, Reverse, Duplicated, Const)]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #[autodiff_reverse(df3, Duplicated, Const)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: expected 1 activities, but found 0
   --> $DIR/autodiff_illegal.rs:27:1
    |
-LL | #[autodiff(df4, Reverse)]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #[autodiff_reverse(df4)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: Dual can not be used in Reverse Mode
   --> $DIR/autodiff_illegal.rs:34:1
    |
-LL | #[autodiff(df5, Reverse, Dual)]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #[autodiff_reverse(df5, Dual)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: Duplicated can not be used in Forward Mode
   --> $DIR/autodiff_illegal.rs:41:1
    |
-LL | #[autodiff(df6, Forward, Duplicated)]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #[autodiff_forward(df6, Duplicated)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: Duplicated can not be used for this type
   --> $DIR/autodiff_illegal.rs:42:14
@@ -95,69 +95,54 @@ error[E0428]: the name `fn_exists` is defined multiple times
 LL | fn fn_exists() {}
    | -------------- previous definition of the value `fn_exists` here
 ...
-LL | #[autodiff(fn_exists, Reverse, Active)]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `fn_exists` redefined here
+LL | #[autodiff_reverse(fn_exists, Active)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `fn_exists` redefined here
    |
    = note: `fn_exists` must be defined only once in the value namespace of this module
 
-error: autodiff requires at least a name and mode
-  --> $DIR/autodiff_illegal.rs:95:1
-   |
-LL | / pub fn f11() {
-LL | |
-LL | |     unimplemented!()
-LL | | }
-   | |_^
-
-error: unknown Mode: `Debug`. Use `Forward` or `Reverse`
-  --> $DIR/autodiff_illegal.rs:101:18
-   |
-LL | #[autodiff(df12, Debug)]
-   |                  ^^^^^
-
 error: did not recognize Activity: `Reverse`
-  --> $DIR/autodiff_illegal.rs:109:27
+  --> $DIR/autodiff_illegal.rs:95:26
    |
-LL | #[autodiff(df13, Forward, Reverse)]
-   |                           ^^^^^^^
+LL | #[autodiff_reverse(df13, Reverse)]
+   |                          ^^^^^^^
 
 error: invalid return activity Active in Forward Mode
-  --> $DIR/autodiff_illegal.rs:161:1
+  --> $DIR/autodiff_illegal.rs:147:1
    |
-LL | #[autodiff(df19, Forward, Dual, Active)]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #[autodiff_forward(df19, Dual, Active)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: invalid return activity Dual in Reverse Mode
-  --> $DIR/autodiff_illegal.rs:167:1
+  --> $DIR/autodiff_illegal.rs:153:1
    |
-LL | #[autodiff(df20, Reverse, Active, Dual)]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #[autodiff_reverse(df20, Active, Dual)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: invalid return activity Duplicated in Reverse Mode
-  --> $DIR/autodiff_illegal.rs:174:1
+  --> $DIR/autodiff_illegal.rs:160:1
    |
-LL | #[autodiff(df21, Reverse, Active, Duplicated)]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #[autodiff_reverse(df21, Active, Duplicated)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0433]: failed to resolve: use of undeclared type `MyFloat`
-  --> $DIR/autodiff_illegal.rs:130:1
+  --> $DIR/autodiff_illegal.rs:116:1
    |
-LL | #[autodiff(df15, Reverse, Active, Active)]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ use of undeclared type `MyFloat`
+LL | #[autodiff_reverse(df15, Active, Active)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ use of undeclared type `MyFloat`
 
 error[E0433]: failed to resolve: use of undeclared type `F64Trans`
-  --> $DIR/autodiff_illegal.rs:154:1
+  --> $DIR/autodiff_illegal.rs:140:1
    |
-LL | #[autodiff(df18, Reverse, Active, Active)]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ use of undeclared type `F64Trans`
+LL | #[autodiff_reverse(df18, Active, Active)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ use of undeclared type `F64Trans`
 
 error[E0599]: the function or associated item `default` exists for tuple `(DoesNotImplDefault, DoesNotImplDefault)`, but its trait bounds were not satisfied
-  --> $DIR/autodiff_illegal.rs:181:1
+  --> $DIR/autodiff_illegal.rs:167:1
    |
 LL | struct DoesNotImplDefault;
    | ------------------------- doesn't satisfy `DoesNotImplDefault: Default`
-LL | #[autodiff(df22, Forward, Dual)]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function or associated item cannot be called on `(DoesNotImplDefault, DoesNotImplDefault)` due to unsatisfied trait bounds
+LL | #[autodiff_forward(df22, Dual)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function or associated item cannot be called on `(DoesNotImplDefault, DoesNotImplDefault)` due to unsatisfied trait bounds
    |
    = note: the following trait bounds were not satisfied:
            `DoesNotImplDefault: Default`
@@ -168,7 +153,7 @@ LL + #[derive(Default)]
 LL | struct DoesNotImplDefault;
    |
 
-error: aborting due to 23 previous errors
+error: aborting due to 21 previous errors
 
 Some errors have detailed explanations: E0428, E0433, E0599, E0658.
 For more information about an error, try `rustc --explain E0428`.
diff --git a/tests/ui/autodiff/auxiliary/my_macro.rs b/tests/ui/autodiff/auxiliary/my_macro.rs
index 217631a33c9..1d5a6de1454 100644
--- a/tests/ui/autodiff/auxiliary/my_macro.rs
+++ b/tests/ui/autodiff/auxiliary/my_macro.rs
@@ -3,6 +3,6 @@ use proc_macro::TokenStream;
 
 #[proc_macro_attribute]
 #[macro_use]
-pub fn autodiff(_attr: TokenStream, item: TokenStream) -> TokenStream {
+pub fn autodiff_forward(_attr: TokenStream, item: TokenStream) -> TokenStream {
     item // identity proc-macro
 }
diff --git a/tests/ui/autodiff/visibility.rs b/tests/ui/autodiff/visibility.rs
index dfaec03aef0..a84df75e799 100644
--- a/tests/ui/autodiff/visibility.rs
+++ b/tests/ui/autodiff/visibility.rs
@@ -6,12 +6,11 @@
 #![feature(autodiff)]
 
 #[cfg(std_autodiff)]
-use std::autodiff::autodiff;
-
+use std::autodiff::autodiff_forward;
 extern crate my_macro;
-use my_macro::autodiff; // bring `autodiff` in scope
+use my_macro::autodiff_forward; // bring `autodiff_forward` in scope
 
-#[autodiff]
-//[std_autodiff]~^^^ ERROR the name `autodiff` is defined multiple times
+#[autodiff_forward(dfoo)]
+//[std_autodiff]~^^^ ERROR the name `autodiff_forward` is defined multiple times
 //[std_autodiff]~^^ ERROR this rustc version does not support autodiff
 fn foo() {}
diff --git a/tests/ui/autodiff/visibility.std_autodiff.stderr b/tests/ui/autodiff/visibility.std_autodiff.stderr
index 720c9a00170..e45f1139012 100644
--- a/tests/ui/autodiff/visibility.std_autodiff.stderr
+++ b/tests/ui/autodiff/visibility.std_autodiff.stderr
@@ -1,23 +1,23 @@
-error[E0252]: the name `autodiff` is defined multiple times
-  --> $DIR/visibility.rs:12:5
+error[E0252]: the name `autodiff_forward` is defined multiple times
+  --> $DIR/visibility.rs:11:5
    |
-LL | use std::autodiff::autodiff;
-   |     ----------------------- previous import of the macro `autodiff` here
-...
-LL | use my_macro::autodiff; // bring `autodiff` in scope
-   |     ^^^^^^^^^^^^^^^^^^ `autodiff` reimported here
+LL | use std::autodiff::autodiff_forward;
+   |     ------------------------------- previous import of the macro `autodiff_forward` here
+LL | extern crate my_macro;
+LL | use my_macro::autodiff_forward; // bring `autodiff_forward` in scope
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^ `autodiff_forward` reimported here
    |
-   = note: `autodiff` must be defined only once in the macro namespace of this module
+   = note: `autodiff_forward` must be defined only once in the macro namespace of this module
 help: you can use `as` to change the binding name of the import
    |
-LL | use my_macro::autodiff as other_autodiff; // bring `autodiff` in scope
-   |                        +++++++++++++++++
+LL | use my_macro::autodiff_forward as other_autodiff_forward; // bring `autodiff_forward` in scope
+   |                                +++++++++++++++++++++++++
 
 error: this rustc version does not support autodiff
-  --> $DIR/visibility.rs:14:1
+  --> $DIR/visibility.rs:13:1
    |
-LL | #[autodiff]
-   | ^^^^^^^^^^^
+LL | #[autodiff_forward(dfoo)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/autoref-autoderef/autoderef-box-no-add.rs b/tests/ui/autoref-autoderef/autoderef-box-no-add.rs
new file mode 100644
index 00000000000..f8085c1ae96
--- /dev/null
+++ b/tests/ui/autoref-autoderef/autoderef-box-no-add.rs
@@ -0,0 +1,35 @@
+//! Tests that auto-dereferencing does not allow addition of `Box<isize>` values.
+//!
+//! This test ensures that `Box<isize>` fields in structs (`Clam` and `Fish`) are not
+//! automatically dereferenced to `isize` during addition operations, as `Box<isize>`
+//! does not implement the `Add` trait.
+
+struct Clam {
+    x: Box<isize>,
+    y: Box<isize>,
+}
+
+struct Fish {
+    a: Box<isize>,
+}
+
+fn main() {
+    let a: Clam = Clam {
+        x: Box::new(1),
+        y: Box::new(2),
+    };
+    let b: Clam = Clam {
+        x: Box::new(10),
+        y: Box::new(20),
+    };
+    let z: isize = a.x + b.y;
+    //~^ ERROR cannot add `Box<isize>` to `Box<isize>`
+    println!("{}", z);
+    assert_eq!(z, 21);
+    let forty: Fish = Fish { a: Box::new(40) };
+    let two: Fish = Fish { a: Box::new(2) };
+    let answer: isize = forty.a + two.a;
+    //~^ ERROR cannot add `Box<isize>` to `Box<isize>`
+    println!("{}", answer);
+    assert_eq!(answer, 42);
+}
diff --git a/tests/ui/autoderef-full-lval.stderr b/tests/ui/autoref-autoderef/autoderef-box-no-add.stderr
index d90238a7fb2..20ef3352831 100644
--- a/tests/ui/autoderef-full-lval.stderr
+++ b/tests/ui/autoref-autoderef/autoderef-box-no-add.stderr
@@ -1,5 +1,5 @@
 error[E0369]: cannot add `Box<isize>` to `Box<isize>`
-  --> $DIR/autoderef-full-lval.rs:15:24
+  --> $DIR/autoderef-box-no-add.rs:25:24
    |
 LL |     let z: isize = a.x + b.y;
    |                    --- ^ --- Box<isize>
@@ -13,7 +13,7 @@ note: the foreign item type `Box<isize>` doesn't implement `Add`
    = note: not implement `Add`
 
 error[E0369]: cannot add `Box<isize>` to `Box<isize>`
-  --> $DIR/autoderef-full-lval.rs:21:33
+  --> $DIR/autoderef-box-no-add.rs:31:33
    |
 LL |     let answer: isize = forty.a + two.a;
    |                         ------- ^ ----- Box<isize>
diff --git a/tests/ui/autoref-autoderef/autoderef-vec-to-slice-by-value.rs b/tests/ui/autoref-autoderef/autoderef-vec-to-slice-by-value.rs
new file mode 100644
index 00000000000..4d67c3a6733
--- /dev/null
+++ b/tests/ui/autoref-autoderef/autoderef-vec-to-slice-by-value.rs
@@ -0,0 +1,18 @@
+//! Tests that a `Vec<isize>` can call a method defined in a trait (`Foo`)
+//! implemented for `&[isize]` with a by-value receiver (`self`), relying on auto-dereferencing
+//! from `Vec` to `&[isize]` during method resolution.
+
+//@ run-pass
+
+trait Foo {
+    fn foo(self);
+}
+
+impl<'a> Foo for &'a [isize] {
+    fn foo(self) {}
+}
+
+pub fn main() {
+    let items = vec![ 3, 5, 1, 2, 4 ];
+    items.foo();
+}
diff --git a/tests/ui/auxiliary/delegate_macro.rs b/tests/ui/auxiliary/delegate_macro.rs
new file mode 100644
index 00000000000..0d752e12039
--- /dev/null
+++ b/tests/ui/auxiliary/delegate_macro.rs
@@ -0,0 +1,6 @@
+#[macro_export]
+macro_rules! delegate {
+    ($method:ident) => {
+        <Self>::$method(8)
+    };
+}
diff --git a/tests/ui/bogus-tag.rs b/tests/ui/bogus-tag.rs
deleted file mode 100644
index c594385eec2..00000000000
--- a/tests/ui/bogus-tag.rs
+++ /dev/null
@@ -1,10 +0,0 @@
-enum Color { Rgb(isize, isize, isize), Rgba(isize, isize, isize, isize), }
-
-fn main() {
-    let red: Color = Color::Rgb(255, 0, 0);
-    match red {
-        Color::Rgb(r, g, b) => { println!("rgb"); }
-        Color::Hsl(h, s, l) => { println!("hsl"); }
-        //~^ ERROR no variant
-    }
-}
diff --git a/tests/ui/borrow-by-val-method-receiver.rs b/tests/ui/borrow-by-val-method-receiver.rs
deleted file mode 100644
index aee1108d96d..00000000000
--- a/tests/ui/borrow-by-val-method-receiver.rs
+++ /dev/null
@@ -1,14 +0,0 @@
-//@ run-pass
-
-trait Foo {
-    fn foo(self);
-}
-
-impl<'a> Foo for &'a [isize] {
-    fn foo(self) {}
-}
-
-pub fn main() {
-    let items = vec![ 3, 5, 1, 2, 4 ];
-    items.foo();
-}
diff --git a/tests/ui/cast/func-pointer-issue-140491.rs b/tests/ui/cast/func-pointer-issue-140491.rs
new file mode 100644
index 00000000000..d5d86a66f5a
--- /dev/null
+++ b/tests/ui/cast/func-pointer-issue-140491.rs
@@ -0,0 +1,7 @@
+fn my_fn(event: &Event<'_>) {}
+
+struct Event<'a>(&'a ());
+
+fn main() {
+    const ptr: &fn(&Event<'_>) = &my_fn as _; //~ ERROR non-primitive cast: `&for<'a, 'b> fn(&'a Event<'b>) {my_fn}` as `&for<'a, 'b> fn(&'a Event<'b>)` [E0605]
+}
diff --git a/tests/ui/cast/func-pointer-issue-140491.stderr b/tests/ui/cast/func-pointer-issue-140491.stderr
new file mode 100644
index 00000000000..e1c07010e69
--- /dev/null
+++ b/tests/ui/cast/func-pointer-issue-140491.stderr
@@ -0,0 +1,11 @@
+error[E0605]: non-primitive cast: `&for<'a, 'b> fn(&'a Event<'b>) {my_fn}` as `&for<'a, 'b> fn(&'a Event<'b>)`
+  --> $DIR/func-pointer-issue-140491.rs:6:34
+   |
+LL | ..._>) = &my_fn as _;
+   |          ^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
+   |
+   = note: casting reference expression `&my_fn` because `&` binds tighter than `as`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0605`.
diff --git a/tests/ui/cfg/cfg-version/syntax.rs b/tests/ui/cfg/cfg-version/syntax.rs
new file mode 100644
index 00000000000..22aab47e1ec
--- /dev/null
+++ b/tests/ui/cfg/cfg-version/syntax.rs
@@ -0,0 +1,152 @@
+//! Check `#[cfg(version(..))]` parsing.
+
+#![feature(cfg_version)]
+
+// Overall grammar
+// ===============
+//
+// `#[cfg(version(..))]` accepts only the `version(VERSION_STRING_LITERAL)` predicate form, where
+// only a single string literal is permitted.
+
+#[cfg(version(42))]
+//~^ ERROR expected a version literal
+fn not_a_string_literal_simple() {}
+
+#[cfg(version(1.20))]
+//~^ ERROR expected a version literal
+fn not_a_string_literal_semver_like() {}
+
+#[cfg(version(false))]
+//~^ ERROR expected a version literal
+fn not_a_string_literal_other() {}
+
+#[cfg(version("1.43", "1.44", "1.45"))]
+//~^ ERROR expected single version literal
+fn multiple_version_literals() {}
+
+// The key-value form `cfg(version = "..")` is not considered a valid `cfg(version(..))` usage, but
+// it will only trigger the `unexpected_cfgs` lint and not a hard error.
+
+#[cfg(version = "1.43")]
+//~^ WARN unexpected `cfg` condition name: `version`
+fn key_value_form() {}
+
+// Additional version string literal constraints
+// =============================================
+//
+// The `VERSION_STRING_LITERAL` ("version literal") has additional constraints on its syntactical
+// well-formedness.
+
+// 1. A valid version literal can only constitute of numbers and periods (a "simple" semver version
+// string). Non-semver strings or "complex" semver strings (such as build metadata) are not
+// considered valid version literals, and will emit a non-lint warning "unknown version literal
+// format".
+
+#[cfg(version("1.43.0"))]
+fn valid_major_minor_patch() {}
+
+#[cfg(version("0.0.0"))]
+fn valid_zero_zero_zero_major_minor_patch() {}
+
+#[cfg(version("foo"))]
+//~^ WARN unknown version literal format, assuming it refers to a future version
+fn not_numbers_or_periods() {}
+
+#[cfg(version("1.20.0-stable"))]
+//~^ WARN unknown version literal format, assuming it refers to a future version
+fn complex_semver_with_metadata() {}
+
+// 2. "Shortened" version strings are permitted but *only* for the omission of the patch number.
+
+#[cfg(version("1.0"))]
+fn valid_major_minor_1() {}
+
+#[cfg(version("1.43"))]
+fn valid_major_minor_2() {}
+
+#[cfg(not(version("1.44")))]
+fn valid_major_minor_negated_smoke_test() {}
+
+#[cfg(version("0.0"))]
+fn valid_zero_zero_major_minor() {}
+
+#[cfg(version("0.7"))]
+fn valid_zero_major_minor() {}
+
+// 3. Major-only, or other non-Semver-like strings are not permitted.
+
+#[cfg(version("1"))]
+//~^ WARN unknown version literal format, assuming it refers to a future version
+fn invalid_major_only() {}
+
+#[cfg(version("0"))]
+//~^ WARN unknown version literal format, assuming it refers to a future version
+fn invalid_major_only_zero() {}
+
+#[cfg(version(".7"))]
+//~^ WARN unknown version literal format, assuming it refers to a future version
+fn invalid_decimal_like() {}
+
+// Misc parsing overflow/underflow edge cases
+// ==========================================
+//
+// Check that we report "unknown version literal format" user-facing warnings and not ICEs.
+
+#[cfg(version("-1"))]
+//~^ WARN unknown version literal format, assuming it refers to a future version
+fn invalid_major_only_negative() {}
+
+// Implementation detail: we store rustc version as `{ major: u16, minor: u16, patch: u16 }`.
+
+#[cfg(version("65536"))]
+//~^ WARN unknown version literal format, assuming it refers to a future version
+fn exceed_u16_major() {}
+
+#[cfg(version("1.65536.0"))]
+//~^ WARN unknown version literal format, assuming it refers to a future version
+fn exceed_u16_minor() {}
+
+#[cfg(version("1.0.65536"))]
+//~^ WARN unknown version literal format, assuming it refers to a future version
+fn exceed_u16_patch() {}
+
+#[cfg(version("65536.0.65536"))]
+//~^ WARN unknown version literal format, assuming it refers to a future version
+fn exceed_u16_mixed() {}
+
+// Usage as `cfg!()`
+// =================
+
+fn cfg_usage() {
+    assert!(cfg!(version("1.0")));
+    assert!(cfg!(version("1.43")));
+    assert!(cfg!(version("1.43.0")));
+
+    assert!(cfg!(version("foo")));
+    //~^ WARN unknown version literal format, assuming it refers to a future version
+    assert!(cfg!(version("1.20.0-stable")));
+    //~^ WARN unknown version literal format, assuming it refers to a future version
+
+    assert!(cfg!(version = "1.43"));
+    //~^ WARN unexpected `cfg` condition name: `version`
+}
+
+fn main() {
+    cfg_usage();
+
+    // `cfg(version = "..")` is not a valid `cfg_version` form, but it only triggers
+    // `unexpected_cfgs` lint, and `cfg(version = "..")` eval to `false`.
+    key_value_form(); //~ ERROR cannot find function
+
+    // Invalid version literal formats within valid `cfg(version(..))` form should also cause
+    // `cfg(version(..))` eval to `false`.
+    not_numbers_or_periods(); //~ ERROR cannot find function
+    complex_semver_with_metadata(); //~ ERROR cannot find function
+    invalid_major_only(); //~ ERROR cannot find function
+    invalid_major_only_zero(); //~ ERROR cannot find function
+    invalid_major_only_negative(); //~ ERROR cannot find function
+    exceed_u16_major(); //~ ERROR cannot find function
+    exceed_u16_minor(); //~ ERROR cannot find function
+    exceed_u16_patch(); //~ ERROR cannot find function
+    exceed_u16_mixed(); //~ ERROR cannot find function
+}
diff --git a/tests/ui/cfg/cfg-version/syntax.stderr b/tests/ui/cfg/cfg-version/syntax.stderr
new file mode 100644
index 00000000000..2facd960763
--- /dev/null
+++ b/tests/ui/cfg/cfg-version/syntax.stderr
@@ -0,0 +1,188 @@
+error: expected a version literal
+  --> $DIR/syntax.rs:11:15
+   |
+LL | #[cfg(version(42))]
+   |               ^^
+
+error: expected a version literal
+  --> $DIR/syntax.rs:15:15
+   |
+LL | #[cfg(version(1.20))]
+   |               ^^^^
+
+error: expected a version literal
+  --> $DIR/syntax.rs:19:15
+   |
+LL | #[cfg(version(false))]
+   |               ^^^^^
+
+error: expected single version literal
+  --> $DIR/syntax.rs:23:7
+   |
+LL | #[cfg(version("1.43", "1.44", "1.45"))]
+   |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: unknown version literal format, assuming it refers to a future version
+  --> $DIR/syntax.rs:51:15
+   |
+LL | #[cfg(version("foo"))]
+   |               ^^^^^
+
+warning: unknown version literal format, assuming it refers to a future version
+  --> $DIR/syntax.rs:55:15
+   |
+LL | #[cfg(version("1.20.0-stable"))]
+   |               ^^^^^^^^^^^^^^^
+
+warning: unknown version literal format, assuming it refers to a future version
+  --> $DIR/syntax.rs:78:15
+   |
+LL | #[cfg(version("1"))]
+   |               ^^^
+
+warning: unknown version literal format, assuming it refers to a future version
+  --> $DIR/syntax.rs:82:15
+   |
+LL | #[cfg(version("0"))]
+   |               ^^^
+
+warning: unknown version literal format, assuming it refers to a future version
+  --> $DIR/syntax.rs:86:15
+   |
+LL | #[cfg(version(".7"))]
+   |               ^^^^
+
+warning: unknown version literal format, assuming it refers to a future version
+  --> $DIR/syntax.rs:95:15
+   |
+LL | #[cfg(version("-1"))]
+   |               ^^^^
+
+warning: unknown version literal format, assuming it refers to a future version
+  --> $DIR/syntax.rs:101:15
+   |
+LL | #[cfg(version("65536"))]
+   |               ^^^^^^^
+
+warning: unknown version literal format, assuming it refers to a future version
+  --> $DIR/syntax.rs:105:15
+   |
+LL | #[cfg(version("1.65536.0"))]
+   |               ^^^^^^^^^^^
+
+warning: unknown version literal format, assuming it refers to a future version
+  --> $DIR/syntax.rs:109:15
+   |
+LL | #[cfg(version("1.0.65536"))]
+   |               ^^^^^^^^^^^
+
+warning: unknown version literal format, assuming it refers to a future version
+  --> $DIR/syntax.rs:113:15
+   |
+LL | #[cfg(version("65536.0.65536"))]
+   |               ^^^^^^^^^^^^^^^
+
+warning: unknown version literal format, assuming it refers to a future version
+  --> $DIR/syntax.rs:125:26
+   |
+LL |     assert!(cfg!(version("foo")));
+   |                          ^^^^^
+
+warning: unknown version literal format, assuming it refers to a future version
+  --> $DIR/syntax.rs:127:26
+   |
+LL |     assert!(cfg!(version("1.20.0-stable")));
+   |                          ^^^^^^^^^^^^^^^
+
+warning: unexpected `cfg` condition name: `version`
+  --> $DIR/syntax.rs:30:7
+   |
+LL | #[cfg(version = "1.43")]
+   |       ^^^^^^^^^^^^^^^^
+   |
+   = help: to expect this configuration use `--check-cfg=cfg(version, values("1.43"))`
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
+   = note: `#[warn(unexpected_cfgs)]` on by default
+help: there is a similar config predicate: `version("..")`
+   |
+LL - #[cfg(version = "1.43")]
+LL + #[cfg(version("1.43"))]
+   |
+
+warning: unexpected `cfg` condition name: `version`
+  --> $DIR/syntax.rs:130:18
+   |
+LL |     assert!(cfg!(version = "1.43"));
+   |                  ^^^^^^^^^^^^^^^^
+   |
+   = help: to expect this configuration use `--check-cfg=cfg(version, values("1.43"))`
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
+help: there is a similar config predicate: `version("..")`
+   |
+LL -     assert!(cfg!(version = "1.43"));
+LL +     assert!(cfg!(version("1.43")));
+   |
+
+error[E0425]: cannot find function `key_value_form` in this scope
+  --> $DIR/syntax.rs:139:5
+   |
+LL |     key_value_form();
+   |     ^^^^^^^^^^^^^^ not found in this scope
+
+error[E0425]: cannot find function `not_numbers_or_periods` in this scope
+  --> $DIR/syntax.rs:143:5
+   |
+LL |     not_numbers_or_periods();
+   |     ^^^^^^^^^^^^^^^^^^^^^^ not found in this scope
+
+error[E0425]: cannot find function `complex_semver_with_metadata` in this scope
+  --> $DIR/syntax.rs:144:5
+   |
+LL |     complex_semver_with_metadata();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not found in this scope
+
+error[E0425]: cannot find function `invalid_major_only` in this scope
+  --> $DIR/syntax.rs:145:5
+   |
+LL |     invalid_major_only();
+   |     ^^^^^^^^^^^^^^^^^^ not found in this scope
+
+error[E0425]: cannot find function `invalid_major_only_zero` in this scope
+  --> $DIR/syntax.rs:146:5
+   |
+LL |     invalid_major_only_zero();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^ not found in this scope
+
+error[E0425]: cannot find function `invalid_major_only_negative` in this scope
+  --> $DIR/syntax.rs:147:5
+   |
+LL |     invalid_major_only_negative();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^ not found in this scope
+
+error[E0425]: cannot find function `exceed_u16_major` in this scope
+  --> $DIR/syntax.rs:148:5
+   |
+LL |     exceed_u16_major();
+   |     ^^^^^^^^^^^^^^^^ not found in this scope
+
+error[E0425]: cannot find function `exceed_u16_minor` in this scope
+  --> $DIR/syntax.rs:149:5
+   |
+LL |     exceed_u16_minor();
+   |     ^^^^^^^^^^^^^^^^ not found in this scope
+
+error[E0425]: cannot find function `exceed_u16_patch` in this scope
+  --> $DIR/syntax.rs:150:5
+   |
+LL |     exceed_u16_patch();
+   |     ^^^^^^^^^^^^^^^^ not found in this scope
+
+error[E0425]: cannot find function `exceed_u16_mixed` in this scope
+  --> $DIR/syntax.rs:151:5
+   |
+LL |     exceed_u16_mixed();
+   |     ^^^^^^^^^^^^^^^^ not found in this scope
+
+error: aborting due to 14 previous errors; 14 warnings emitted
+
+For more information about this error, try `rustc --explain E0425`.
diff --git a/tests/ui/cfg/diagnostics-reexport-2.rs b/tests/ui/cfg/diagnostics-reexport-2.rs
new file mode 100644
index 00000000000..f66b9ed99ee
--- /dev/null
+++ b/tests/ui/cfg/diagnostics-reexport-2.rs
@@ -0,0 +1,61 @@
+// issue#141256
+
+mod original {
+    #[cfg(false)]
+    //~^ NOTE the item is gated here
+    //~| NOTE the item is gated here
+    //~| NOTE the item is gated here
+    //~| NOTE the item is gated here
+    //~| NOTE the item is gated here
+    pub mod gated {
+    //~^ NOTE found an item that was configured out
+    //~| NOTE found an item that was configured out
+    //~| NOTE found an item that was configured out
+    //~| NOTE found an item that was configured out
+    //~| NOTE found an item that was configured out
+        pub fn foo() {}
+    }
+}
+
+mod reexport {
+    pub use super::original::*;
+}
+
+mod reexport2 {
+    pub use super::reexport::*;
+}
+
+mod reexport30 {
+    pub use super::original::*;
+    pub use super::reexport31::*;
+}
+
+mod reexport31 {
+    pub use super::reexport30::*;
+}
+
+mod reexport32 {
+    pub use super::reexport30::*;
+}
+
+fn main() {
+    reexport::gated::foo();
+    //~^ ERROR failed to resolve: could not find `gated` in `reexport`
+    //~| NOTE  could not find `gated` in `reexport`
+
+    reexport2::gated::foo();
+    //~^ ERROR failed to resolve: could not find `gated` in `reexport2`
+    //~| NOTE  could not find `gated` in `reexport2`
+
+    reexport30::gated::foo();
+    //~^ ERROR failed to resolve: could not find `gated` in `reexport30`
+    //~| NOTE  could not find `gated` in `reexport30`
+
+    reexport31::gated::foo();
+    //~^ ERROR failed to resolve: could not find `gated` in `reexport31`
+    //~| NOTE  could not find `gated` in `reexport31`
+
+    reexport32::gated::foo();
+    //~^ ERROR failed to resolve: could not find `gated` in `reexport32`
+    //~| NOTE  could not find `gated` in `reexport32`
+}
diff --git a/tests/ui/cfg/diagnostics-reexport-2.stderr b/tests/ui/cfg/diagnostics-reexport-2.stderr
new file mode 100644
index 00000000000..95ac5a19b0b
--- /dev/null
+++ b/tests/ui/cfg/diagnostics-reexport-2.stderr
@@ -0,0 +1,88 @@
+error[E0433]: failed to resolve: could not find `gated` in `reexport`
+  --> $DIR/diagnostics-reexport-2.rs:42:15
+   |
+LL |     reexport::gated::foo();
+   |               ^^^^^ could not find `gated` in `reexport`
+   |
+note: found an item that was configured out
+  --> $DIR/diagnostics-reexport-2.rs:10:13
+   |
+LL |     pub mod gated {
+   |             ^^^^^
+note: the item is gated here
+  --> $DIR/diagnostics-reexport-2.rs:4:5
+   |
+LL |     #[cfg(false)]
+   |     ^^^^^^^^^^^^^
+
+error[E0433]: failed to resolve: could not find `gated` in `reexport2`
+  --> $DIR/diagnostics-reexport-2.rs:46:16
+   |
+LL |     reexport2::gated::foo();
+   |                ^^^^^ could not find `gated` in `reexport2`
+   |
+note: found an item that was configured out
+  --> $DIR/diagnostics-reexport-2.rs:10:13
+   |
+LL |     pub mod gated {
+   |             ^^^^^
+note: the item is gated here
+  --> $DIR/diagnostics-reexport-2.rs:4:5
+   |
+LL |     #[cfg(false)]
+   |     ^^^^^^^^^^^^^
+
+error[E0433]: failed to resolve: could not find `gated` in `reexport30`
+  --> $DIR/diagnostics-reexport-2.rs:50:17
+   |
+LL |     reexport30::gated::foo();
+   |                 ^^^^^ could not find `gated` in `reexport30`
+   |
+note: found an item that was configured out
+  --> $DIR/diagnostics-reexport-2.rs:10:13
+   |
+LL |     pub mod gated {
+   |             ^^^^^
+note: the item is gated here
+  --> $DIR/diagnostics-reexport-2.rs:4:5
+   |
+LL |     #[cfg(false)]
+   |     ^^^^^^^^^^^^^
+
+error[E0433]: failed to resolve: could not find `gated` in `reexport31`
+  --> $DIR/diagnostics-reexport-2.rs:54:17
+   |
+LL |     reexport31::gated::foo();
+   |                 ^^^^^ could not find `gated` in `reexport31`
+   |
+note: found an item that was configured out
+  --> $DIR/diagnostics-reexport-2.rs:10:13
+   |
+LL |     pub mod gated {
+   |             ^^^^^
+note: the item is gated here
+  --> $DIR/diagnostics-reexport-2.rs:4:5
+   |
+LL |     #[cfg(false)]
+   |     ^^^^^^^^^^^^^
+
+error[E0433]: failed to resolve: could not find `gated` in `reexport32`
+  --> $DIR/diagnostics-reexport-2.rs:58:17
+   |
+LL |     reexport32::gated::foo();
+   |                 ^^^^^ could not find `gated` in `reexport32`
+   |
+note: found an item that was configured out
+  --> $DIR/diagnostics-reexport-2.rs:10:13
+   |
+LL |     pub mod gated {
+   |             ^^^^^
+note: the item is gated here
+  --> $DIR/diagnostics-reexport-2.rs:4:5
+   |
+LL |     #[cfg(false)]
+   |     ^^^^^^^^^^^^^
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0433`.
diff --git a/tests/ui/closures/2229_closure_analysis/run_pass/lit-pattern-matching-with-methods.rs b/tests/ui/closures/2229_closure_analysis/run_pass/lit-pattern-matching-with-methods.rs
index 7a4d7d9a81e..afb16cf58e8 100644
--- a/tests/ui/closures/2229_closure_analysis/run_pass/lit-pattern-matching-with-methods.rs
+++ b/tests/ui/closures/2229_closure_analysis/run_pass/lit-pattern-matching-with-methods.rs
@@ -14,14 +14,14 @@ fn main() {
     map.insert("c", ());
 
     {
-        let mut it = map.extract_if(|_, _| true);
+        let mut it = map.extract_if(.., |_, _| true);
         catch_unwind(AssertUnwindSafe(|| while it.next().is_some() {})).unwrap_err();
         let result = catch_unwind(AssertUnwindSafe(|| it.next()));
         assert!(matches!(result, Ok(None)));
     }
 
     {
-        let mut it = map.extract_if(|_, _| true);
+        let mut it = map.extract_if(.., |_, _| true);
         catch_unwind(AssertUnwindSafe(|| while let Some(_) = it.next() {})).unwrap_err();
         let result = catch_unwind(AssertUnwindSafe(|| it.next()));
         assert!(matches!(result, Ok(None)));
diff --git a/tests/ui/coercion/issue-73886.stderr b/tests/ui/coercion/issue-73886.stderr
index 0d4c90017cf..a287aa29e11 100644
--- a/tests/ui/coercion/issue-73886.stderr
+++ b/tests/ui/coercion/issue-73886.stderr
@@ -3,6 +3,8 @@ error[E0605]: non-primitive cast: `&&[i32; 1]` as `&[_]`
    |
 LL |     let _ = &&[0] as &[_];
    |             ^^^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
+   |
+   = note: casting reference expression `&&[0]` because `&` binds tighter than `as`
 
 error[E0605]: non-primitive cast: `u32` as `Option<_>`
   --> $DIR/issue-73886.rs:4:13
diff --git a/tests/ui/coercion/retslot-cast.rs b/tests/ui/coercion/retslot-cast.rs
index ae500cb15df..a87ac35a8e1 100644
--- a/tests/ui/coercion/retslot-cast.rs
+++ b/tests/ui/coercion/retslot-cast.rs
@@ -1,7 +1,7 @@
 #![allow(warnings)]
 
-pub fn fail(x: Option<&(Iterator<Item=()>+Send)>)
-            -> Option<&Iterator<Item=()>> {
+pub fn fail(x: Option<&(dyn Iterator<Item=()>+Send)>)
+            -> Option<&dyn Iterator<Item=()>> {
     // This call used to trigger an LLVM assertion because the return
     // slot had type "Option<&Iterator>"* instead of
     // "Option<&(Iterator+Send)>"* -- but this now yields a
@@ -13,8 +13,8 @@ pub fn fail(x: Option<&(Iterator<Item=()>+Send)>)
     inner(x) //~ ERROR mismatched types
 }
 
-pub fn inner(x: Option<&(Iterator<Item=()>+Send)>)
-             -> Option<&(Iterator<Item=()>+Send)> {
+pub fn inner(x: Option<&(dyn Iterator<Item=()>+Send)>)
+             -> Option<&(dyn Iterator<Item=()>+Send)> {
     x
 }
 
diff --git a/tests/ui/coercion/retslot-cast.stderr b/tests/ui/coercion/retslot-cast.stderr
index dac21a7f25b..a5242c13edd 100644
--- a/tests/ui/coercion/retslot-cast.stderr
+++ b/tests/ui/coercion/retslot-cast.stderr
@@ -1,8 +1,8 @@
 error[E0308]: mismatched types
   --> $DIR/retslot-cast.rs:13:5
    |
-LL |             -> Option<&Iterator<Item=()>> {
-   |                -------------------------- expected `Option<&dyn Iterator<Item = ()>>` because of return type
+LL |             -> Option<&dyn Iterator<Item=()>> {
+   |                ------------------------------ expected `Option<&dyn Iterator<Item = ()>>` because of return type
 ...
 LL |     inner(x)
    |     ^^^^^^^^ expected trait `Iterator<Item = ()>`, found trait `Iterator<Item = ()> + Send`
diff --git a/tests/ui/const-ptr/allowed_slices.rs b/tests/ui/const-ptr/allowed_slices.rs
index e5b9966c609..23f63ff5feb 100644
--- a/tests/ui/const-ptr/allowed_slices.rs
+++ b/tests/ui/const-ptr/allowed_slices.rs
@@ -26,7 +26,7 @@ pub static S5: &[MaybeUninit<u8>] = unsafe { from_raw_parts((&D1) as *const _ as
 // is valid as [bool; 4], so this is not UB (it's basically a transmute)
 pub static S6: &[bool] = unsafe { from_raw_parts((&D0) as *const _ as _, 4) };
 
-// Structs are considered single allocated objects,
+// Structs are considered single allocations,
 // as long as you don't reinterpret padding as initialized
 // data everything is ok.
 pub static S7: &[u16] = unsafe {
diff --git a/tests/ui/const-ptr/forbidden_slices.stderr b/tests/ui/const-ptr/forbidden_slices.stderr
index c73d2ca938c..e618fbf7e0f 100644
--- a/tests/ui/const-ptr/forbidden_slices.stderr
+++ b/tests/ui/const-ptr/forbidden_slices.stderr
@@ -104,20 +104,12 @@ error[E0080]: could not evaluate static initializer
    |
 LL | pub static R1: &[()] = unsafe { from_ptr_range(ptr::null()..ptr::null()) }; // errors inside libcore
    |                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ evaluation panicked: assertion failed: 0 < pointee_size && pointee_size <= isize::MAX as usize
-   |
-note: inside `from_ptr_range::<'_, ()>`
-  --> $SRC_DIR/core/src/slice/raw.rs:LL:COL
-note: inside `std::ptr::const_ptr::<impl *const ()>::offset_from_unsigned`
-  --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
 
 error[E0080]: could not evaluate static initializer
   --> $DIR/forbidden_slices.rs:54:25
    |
 LL |     from_ptr_range(ptr..ptr.add(2)) // errors inside libcore
    |                         ^^^^^^^^^^ in-bounds pointer arithmetic failed: attempting to offset pointer by 8 bytes, but got ALLOC10 which is only 4 bytes from the end of the allocation
-   |
-note: inside `std::ptr::const_ptr::<impl *const u32>::add`
-  --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
 
 error[E0080]: it is undefined behavior to use this value
   --> $DIR/forbidden_slices.rs:57:1
@@ -170,31 +162,18 @@ error[E0080]: could not evaluate static initializer
    |
 LL |     from_ptr_range(ptr..ptr.add(1))
    |                         ^^^^^^^^^^ in-bounds pointer arithmetic failed: attempting to offset pointer by 8 bytes, but got ALLOC11+0x1 which is only 7 bytes from the end of the allocation
-   |
-note: inside `std::ptr::const_ptr::<impl *const u64>::add`
-  --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
 
 error[E0080]: could not evaluate static initializer
   --> $DIR/forbidden_slices.rs:85:34
    |
 LL | pub static R9: &[u32] = unsafe { from_ptr_range(&D0..(&D0 as *const u32).add(1)) };
    |                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `ptr_offset_from_unsigned` called on two different pointers that are not both derived from the same allocation
-   |
-note: inside `from_ptr_range::<'_, u32>`
-  --> $SRC_DIR/core/src/slice/raw.rs:LL:COL
-note: inside `std::ptr::const_ptr::<impl *const u32>::offset_from_unsigned`
-  --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
 
 error[E0080]: could not evaluate static initializer
   --> $DIR/forbidden_slices.rs:87:35
    |
 LL | pub static R10: &[u32] = unsafe { from_ptr_range(&D0..&D0) };
    |                                   ^^^^^^^^^^^^^^^^^^^^^^^^ `ptr_offset_from_unsigned` called on two different pointers that are not both derived from the same allocation
-   |
-note: inside `from_ptr_range::<'_, u32>`
-  --> $SRC_DIR/core/src/slice/raw.rs:LL:COL
-note: inside `std::ptr::const_ptr::<impl *const u32>::offset_from_unsigned`
-  --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
 
 error: aborting due to 18 previous errors
 
diff --git a/tests/ui/const-ptr/out_of_bounds_read.stderr b/tests/ui/const-ptr/out_of_bounds_read.stderr
index 1d625a26b78..8f93793802b 100644
--- a/tests/ui/const-ptr/out_of_bounds_read.stderr
+++ b/tests/ui/const-ptr/out_of_bounds_read.stderr
@@ -3,31 +3,18 @@ error[E0080]: evaluation of constant value failed
    |
 LL |     const _READ: u32 = unsafe { ptr::read(PAST_END_PTR) };
    |                                 ^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: attempting to access 4 bytes, but got ALLOC0+0x4 which is at or beyond the end of the allocation of size 4 bytes
-   |
-note: inside `std::ptr::read::<u32>`
-  --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
 
 error[E0080]: evaluation of constant value failed
   --> $DIR/out_of_bounds_read.rs:10:39
    |
 LL |     const _CONST_READ: u32 = unsafe { PAST_END_PTR.read() };
    |                                       ^^^^^^^^^^^^^^^^^^^ memory access failed: attempting to access 4 bytes, but got ALLOC0+0x4 which is at or beyond the end of the allocation of size 4 bytes
-   |
-note: inside `std::ptr::const_ptr::<impl *const u32>::read`
-  --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
-note: inside `std::ptr::read::<u32>`
-  --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
 
 error[E0080]: evaluation of constant value failed
   --> $DIR/out_of_bounds_read.rs:12:37
    |
 LL |     const _MUT_READ: u32 = unsafe { (PAST_END_PTR as *mut u32).read() };
    |                                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: attempting to access 4 bytes, but got ALLOC0+0x4 which is at or beyond the end of the allocation of size 4 bytes
-   |
-note: inside `std::ptr::mut_ptr::<impl *mut u32>::read`
-  --> $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
-note: inside `std::ptr::read::<u32>`
-  --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
 
 error: aborting due to 3 previous errors
 
diff --git a/tests/ui/consts/const-eval/dont_promote_unstable_const_fn.stderr b/tests/ui/consts/const-eval/dont_promote_unstable_const_fn.stderr
index a506f2a282b..b505b76a6ab 100644
--- a/tests/ui/consts/const-eval/dont_promote_unstable_const_fn.stderr
+++ b/tests/ui/consts/const-eval/dont_promote_unstable_const_fn.stderr
@@ -5,16 +5,11 @@ LL | const fn bar() -> u32 { foo() }
    |                         ^^^^^
    |
    = help: mark the callee as `#[rustc_const_stable_indirect]` if it does not itself require any unstable features
-help: if the caller is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do)
+help: if the caller is not (yet) meant to be exposed to stable const contexts, add `#[rustc_const_unstable]`
    |
 LL + #[rustc_const_unstable(feature = "...", issue = "...")]
 LL | const fn bar() -> u32 { foo() }
    |
-help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval)
-   |
-LL + #[rustc_allow_const_fn_unstable(foo)]
-LL | const fn bar() -> u32 { foo() }
-   |
 
 error[E0716]: temporary value dropped while borrowed
   --> $DIR/dont_promote_unstable_const_fn.rs:17:28
diff --git a/tests/ui/consts/const-eval/float_methods.rs b/tests/ui/consts/const-eval/float_methods.rs
deleted file mode 100644
index 853f75825ac..00000000000
--- a/tests/ui/consts/const-eval/float_methods.rs
+++ /dev/null
@@ -1,46 +0,0 @@
-//@ run-pass
-//! Tests the float intrinsics: min, max, abs, copysign
-
-#![feature(f16, f128)]
-
-const F16_MIN: f16 = 1.0_f16.min(0.5_f16);
-const F16_MAX: f16 = 1.0_f16.max(0.5_f16);
-const F16_ABS: f16 = (-1.0_f16).abs();
-const F16_COPYSIGN: f16 = 1.0_f16.copysign(-2.0_f16);
-
-const F32_MIN: f32 = 1.0_f32.min(0.5_f32);
-const F32_MAX: f32 = 1.0_f32.max(0.5_f32);
-const F32_ABS: f32 = (-1.0_f32).abs();
-const F32_COPYSIGN: f32 = 1.0_f32.copysign(-2.0_f32);
-
-const F64_MIN: f64 = 1.0_f64.min(0.5_f64);
-const F64_MAX: f64 = 1.0_f64.max(0.5_f64);
-const F64_ABS: f64 = (-1.0_f64).abs();
-const F64_COPYSIGN: f64 = 1.0_f64.copysign(-2.0_f64);
-
-const F128_MIN: f128 = 1.0_f128.min(0.5_f128);
-const F128_MAX: f128 = 1.0_f128.max(0.5_f128);
-const F128_ABS: f128 = (-1.0_f128).abs();
-const F128_COPYSIGN: f128 = 1.0_f128.copysign(-2.0_f128);
-
-fn main() {
-    assert_eq!(F16_MIN, 0.5);
-    assert_eq!(F16_MAX, 1.0);
-    assert_eq!(F16_ABS, 1.0);
-    assert_eq!(F16_COPYSIGN, -1.0);
-
-    assert_eq!(F32_MIN, 0.5);
-    assert_eq!(F32_MAX, 1.0);
-    assert_eq!(F32_ABS, 1.0);
-    assert_eq!(F32_COPYSIGN, -1.0);
-
-    assert_eq!(F64_MIN, 0.5);
-    assert_eq!(F64_MAX, 1.0);
-    assert_eq!(F64_ABS, 1.0);
-    assert_eq!(F64_COPYSIGN, -1.0);
-
-    assert_eq!(F128_MIN, 0.5);
-    assert_eq!(F128_MAX, 1.0);
-    assert_eq!(F128_ABS, 1.0);
-    assert_eq!(F128_COPYSIGN, -1.0);
-}
diff --git a/tests/ui/consts/const-eval/ptr-to-int-transmute-in-consts-issue-87525.rs b/tests/ui/consts/const-eval/ptr-to-int-transmute-in-consts-issue-87525.rs
index 19c78f019aa..5fab075785a 100644
--- a/tests/ui/consts/const-eval/ptr-to-int-transmute-in-consts-issue-87525.rs
+++ b/tests/ui/consts/const-eval/ptr-to-int-transmute-in-consts-issue-87525.rs
@@ -1,7 +1,9 @@
+#![deny(ptr_to_integer_transmute_in_consts)]
+
 const fn foo(ptr: *const u8) -> usize {
     unsafe {
         std::mem::transmute(ptr)
-        //~^ WARN pointers cannot be transmuted to integers
+        //~^ ERROR pointers cannot be transmuted to integers
     }
 }
 
@@ -11,7 +13,7 @@ trait Human {
         let ptr: *const usize = &value;
         unsafe {
             std::mem::transmute(ptr)
-            //~^ WARN pointers cannot be transmuted to integers
+            //~^ ERROR pointers cannot be transmuted to integers
         }
     };
 
@@ -28,7 +30,7 @@ impl<T> Type<T> {
         let ptr: *const usize = &value;
         unsafe {
             std::mem::transmute(ptr)
-            //~^ WARN pointers cannot be transmuted to integers
+            //~^ ERROR pointers cannot be transmuted to integers
         }
     };
 
@@ -38,9 +40,7 @@ impl<T> Type<T> {
 }
 
 fn control(ptr: *const u8) -> usize {
-    unsafe {
-        std::mem::transmute(ptr)
-    }
+    unsafe { std::mem::transmute(ptr) }
 }
 
 struct ControlStruct;
@@ -49,22 +49,15 @@ impl ControlStruct {
     fn new() -> usize {
         let value = 10;
         let ptr: *const i32 = &value;
-        unsafe {
-            std::mem::transmute(ptr)
-        }
+        unsafe { std::mem::transmute(ptr) }
     }
 }
 
-
 const fn zoom(ptr: *const u8) -> usize {
     unsafe {
         std::mem::transmute(ptr)
-        //~^ WARN pointers cannot be transmuted to integers
+        //~^ ERROR pointers cannot be transmuted to integers
     }
 }
 
-fn main() {
-    const a: u8 = 10;
-    const value: usize = zoom(&a);
-    //~^ ERROR evaluation of constant value failed
-}
+fn main() {}
diff --git a/tests/ui/consts/const-eval/ptr-to-int-transmute-in-consts-issue-87525.stderr b/tests/ui/consts/const-eval/ptr-to-int-transmute-in-consts-issue-87525.stderr
index ca6ad9408ab..2a9d9b5cb96 100644
--- a/tests/ui/consts/const-eval/ptr-to-int-transmute-in-consts-issue-87525.stderr
+++ b/tests/ui/consts/const-eval/ptr-to-int-transmute-in-consts-issue-87525.stderr
@@ -1,5 +1,5 @@
-warning: pointers cannot be transmuted to integers during const eval
-  --> $DIR/ptr-to-int-transmute-in-consts-issue-87525.rs:61:9
+error: pointers cannot be transmuted to integers during const eval
+  --> $DIR/ptr-to-int-transmute-in-consts-issue-87525.rs:5:9
    |
 LL |         std::mem::transmute(ptr)
    |         ^^^^^^^^^^^^^^^^^^^^^^^^
@@ -7,29 +7,24 @@ LL |         std::mem::transmute(ptr)
    = note: at compile-time, pointers do not have an integer value
    = note: avoiding this restriction via `union` or raw pointers leads to compile-time undefined behavior
    = help: for more information, see https://doc.rust-lang.org/std/mem/fn.transmute.html
-   = note: `#[warn(ptr_to_integer_transmute_in_consts)]` on by default
-
-error[E0080]: evaluation of constant value failed
-  --> $DIR/ptr-to-int-transmute-in-consts-issue-87525.rs:68:26
-   |
-LL |     const value: usize = zoom(&a);
-   |                          ^^^^^^^^ unable to turn pointer into integer
+note: the lint level is defined here
+  --> $DIR/ptr-to-int-transmute-in-consts-issue-87525.rs:1:9
    |
-   = help: this code performed an operation that depends on the underlying bytes representing a pointer
-   = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
+LL | #![deny(ptr_to_integer_transmute_in_consts)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-warning: pointers cannot be transmuted to integers during const eval
-  --> $DIR/ptr-to-int-transmute-in-consts-issue-87525.rs:3:9
+error: pointers cannot be transmuted to integers during const eval
+  --> $DIR/ptr-to-int-transmute-in-consts-issue-87525.rs:15:13
    |
-LL |         std::mem::transmute(ptr)
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^
+LL |             std::mem::transmute(ptr)
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: at compile-time, pointers do not have an integer value
    = note: avoiding this restriction via `union` or raw pointers leads to compile-time undefined behavior
    = help: for more information, see https://doc.rust-lang.org/std/mem/fn.transmute.html
 
-warning: pointers cannot be transmuted to integers during const eval
-  --> $DIR/ptr-to-int-transmute-in-consts-issue-87525.rs:13:13
+error: pointers cannot be transmuted to integers during const eval
+  --> $DIR/ptr-to-int-transmute-in-consts-issue-87525.rs:32:13
    |
 LL |             std::mem::transmute(ptr)
    |             ^^^^^^^^^^^^^^^^^^^^^^^^
@@ -38,16 +33,15 @@ LL |             std::mem::transmute(ptr)
    = note: avoiding this restriction via `union` or raw pointers leads to compile-time undefined behavior
    = help: for more information, see https://doc.rust-lang.org/std/mem/fn.transmute.html
 
-warning: pointers cannot be transmuted to integers during const eval
-  --> $DIR/ptr-to-int-transmute-in-consts-issue-87525.rs:30:13
+error: pointers cannot be transmuted to integers during const eval
+  --> $DIR/ptr-to-int-transmute-in-consts-issue-87525.rs:58:9
    |
-LL |             std::mem::transmute(ptr)
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^
+LL |         std::mem::transmute(ptr)
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: at compile-time, pointers do not have an integer value
    = note: avoiding this restriction via `union` or raw pointers leads to compile-time undefined behavior
    = help: for more information, see https://doc.rust-lang.org/std/mem/fn.transmute.html
 
-error: aborting due to 1 previous error; 4 warnings emitted
+error: aborting due to 4 previous errors
 
-For more information about this error, try `rustc --explain E0080`.
diff --git a/tests/ui/consts/const-eval/raw-pointer-ub.rs b/tests/ui/consts/const-eval/raw-pointer-ub.rs
index 1383de63109..1e76104d515 100644
--- a/tests/ui/consts/const-eval/raw-pointer-ub.rs
+++ b/tests/ui/consts/const-eval/raw-pointer-ub.rs
@@ -18,7 +18,6 @@ const MISALIGNED_COPY: () = unsafe {
     let mut z = 123;
     y.copy_to_nonoverlapping(&mut z, 1);
     //~^ ERROR evaluation of constant value failed
-    //~| NOTE inside `std::ptr::const_ptr
     //~| NOTE inside `std::ptr::copy_nonoverlapping::<u32>`
     //~| NOTE accessing memory with alignment 1, but alignment 4 is required
     // The actual error points into the implementation of `copy_to_nonoverlapping`.
diff --git a/tests/ui/consts/const-eval/raw-pointer-ub.stderr b/tests/ui/consts/const-eval/raw-pointer-ub.stderr
index 0f3dc33f3a3..01a8decc93b 100644
--- a/tests/ui/consts/const-eval/raw-pointer-ub.stderr
+++ b/tests/ui/consts/const-eval/raw-pointer-ub.stderr
@@ -16,19 +16,17 @@ error[E0080]: evaluation of constant value failed
 LL |     y.copy_to_nonoverlapping(&mut z, 1);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ accessing memory with alignment 1, but alignment 4 is required
    |
-note: inside `std::ptr::const_ptr::<impl *const u32>::copy_to_nonoverlapping`
-  --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
 note: inside `std::ptr::copy_nonoverlapping::<u32>`
   --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/raw-pointer-ub.rs:34:16
+  --> $DIR/raw-pointer-ub.rs:33:16
    |
 LL |     let _val = (*ptr).0;
    |                ^^^^^^^^ accessing memory based on pointer with alignment 4, but alignment 16 is required
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/raw-pointer-ub.rs:41:16
+  --> $DIR/raw-pointer-ub.rs:40:16
    |
 LL |     let _val = *ptr;
    |                ^^^^ memory access failed: attempting to access 8 bytes, but got ALLOC0 which is only 4 bytes from the end of the allocation
diff --git a/tests/ui/consts/const-eval/ub-ref-ptr.stderr b/tests/ui/consts/const-eval/ub-ref-ptr.stderr
index de5e721c3f7..cfec1a42f28 100644
--- a/tests/ui/consts/const-eval/ub-ref-ptr.stderr
+++ b/tests/ui/consts/const-eval/ub-ref-ptr.stderr
@@ -153,11 +153,6 @@ error[E0080]: evaluation of constant value failed
    |
 LL |     ptr.read();
    |     ^^^^^^^^^^ accessing memory based on pointer with alignment 1, but alignment 4 is required
-   |
-note: inside `std::ptr::const_ptr::<impl *const u32>::read`
-  --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
-note: inside `std::ptr::read::<u32>`
-  --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
 
 error: aborting due to 15 previous errors
 
diff --git a/tests/ui/consts/const-unstable-intrinsic.stderr b/tests/ui/consts/const-unstable-intrinsic.stderr
index 308b02386f5..7e7ba966cee 100644
--- a/tests/ui/consts/const-unstable-intrinsic.stderr
+++ b/tests/ui/consts/const-unstable-intrinsic.stderr
@@ -46,16 +46,11 @@ error: const function that might be (indirectly) exposed to stable cannot use `#
 LL |         size_of_val(&x);
    |         ^^^^^^^^^^^^^^^
    |
-help: if the function is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do)
+help: if the function is not (yet) meant to be exposed to stable const contexts, add `#[rustc_const_unstable]`
    |
 LL + #[rustc_const_unstable(feature = "...", issue = "...")]
 LL | const fn const_main() {
    |
-help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval)
-   |
-LL + #[rustc_allow_const_fn_unstable(local)]
-LL | const fn const_main() {
-   |
 
 error: const function that might be (indirectly) exposed to stable cannot use `#[feature(local)]`
   --> $DIR/const-unstable-intrinsic.rs:26:9
@@ -63,16 +58,11 @@ error: const function that might be (indirectly) exposed to stable cannot use `#
 LL |         min_align_of_val(&x);
    |         ^^^^^^^^^^^^^^^^^^^^
    |
-help: if the function is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do)
+help: if the function is not (yet) meant to be exposed to stable const contexts, add `#[rustc_const_unstable]`
    |
 LL + #[rustc_const_unstable(feature = "...", issue = "...")]
 LL | const fn const_main() {
    |
-help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval)
-   |
-LL + #[rustc_allow_const_fn_unstable(local)]
-LL | const fn const_main() {
-   |
 
 error: intrinsic `copy::copy` cannot be (indirectly) exposed to stable
   --> $DIR/const-unstable-intrinsic.rs:48:14
@@ -88,16 +78,11 @@ error: const function that might be (indirectly) exposed to stable cannot use `#
 LL |         super::size_of_val(src);
    |         ^^^^^^^^^^^^^^^^^^^^^^^
    |
-help: if the function is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do)
+help: if the function is not (yet) meant to be exposed to stable const contexts, add `#[rustc_const_unstable]`
    |
 LL +     #[rustc_const_unstable(feature = "...", issue = "...")]
 LL |     const unsafe fn copy<T>(src: *const T, _dst: *mut T, _count: usize) {
    |
-help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval)
-   |
-LL +     #[rustc_allow_const_fn_unstable(local)]
-LL |     const unsafe fn copy<T>(src: *const T, _dst: *mut T, _count: usize) {
-   |
 
 error: aborting due to 8 previous errors
 
diff --git a/tests/ui/consts/const_unsafe_unreachable_ub.rs b/tests/ui/consts/const_unsafe_unreachable_ub.rs
index a3f7fd46a75..76c6c56d7c5 100644
--- a/tests/ui/consts/const_unsafe_unreachable_ub.rs
+++ b/tests/ui/consts/const_unsafe_unreachable_ub.rs
@@ -1,14 +1,15 @@
 const unsafe fn foo(x: bool) -> bool {
     match x {
         true => true,
-        false => std::hint::unreachable_unchecked(), //~ NOTE inside `foo`
+        false => std::hint::unreachable_unchecked(),
+        //~^ NOTE inside `foo`
+        //~| NOTE the failure occurred here
     }
 }
 
 const BAR: bool = unsafe { foo(false) };
 //~^ ERROR evaluation of constant value failed
 //~| NOTE entering unreachable code
-//~| NOTE inside `unreachable_unchecked`
 
 fn main() {
     assert_eq!(BAR, true);
diff --git a/tests/ui/consts/const_unsafe_unreachable_ub.stderr b/tests/ui/consts/const_unsafe_unreachable_ub.stderr
index 079ed77b219..42bf69aded0 100644
--- a/tests/ui/consts/const_unsafe_unreachable_ub.stderr
+++ b/tests/ui/consts/const_unsafe_unreachable_ub.stderr
@@ -1,5 +1,5 @@
 error[E0080]: evaluation of constant value failed
-  --> $DIR/const_unsafe_unreachable_ub.rs:8:28
+  --> $DIR/const_unsafe_unreachable_ub.rs:10:28
    |
 LL | const BAR: bool = unsafe { foo(false) };
    |                            ^^^^^^^^^^ entering unreachable code
@@ -8,9 +8,7 @@ note: inside `foo`
   --> $DIR/const_unsafe_unreachable_ub.rs:4:18
    |
 LL |         false => std::hint::unreachable_unchecked(),
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-note: inside `unreachable_unchecked`
-  --> $SRC_DIR/core/src/hint.rs:LL:COL
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the failure occurred here
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/consts/issue-miri-1910.stderr b/tests/ui/consts/issue-miri-1910.stderr
index 59cbccc13a7..52edad0c389 100644
--- a/tests/ui/consts/issue-miri-1910.stderr
+++ b/tests/ui/consts/issue-miri-1910.stderr
@@ -4,10 +4,6 @@ error[E0080]: evaluation of constant value failed
 LL |     (&foo as *const _ as *const u8).add(one_and_a_half_pointers).read();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into integer
    |
-note: inside `std::ptr::const_ptr::<impl *const u8>::read`
-  --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
-note: inside `std::ptr::read::<u8>`
-  --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
    = help: this code performed an operation that depends on the underlying bytes representing a pointer
    = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
 
diff --git a/tests/ui/consts/min_const_fn/min_const_fn_libstd_stability.stderr b/tests/ui/consts/min_const_fn/min_const_fn_libstd_stability.stderr
index 26dedc49a39..9efc252ce6b 100644
--- a/tests/ui/consts/min_const_fn/min_const_fn_libstd_stability.stderr
+++ b/tests/ui/consts/min_const_fn/min_const_fn_libstd_stability.stderr
@@ -5,16 +5,11 @@ LL | const fn bar() -> u32 { foo() }
    |                         ^^^^^
    |
    = help: mark the callee as `#[rustc_const_stable_indirect]` if it does not itself require any unstable features
-help: if the caller is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do)
+help: if the caller is not (yet) meant to be exposed to stable const contexts, add `#[rustc_const_unstable]`
    |
 LL + #[rustc_const_unstable(feature = "...", issue = "...")]
 LL | const fn bar() -> u32 { foo() }
    |
-help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval)
-   |
-LL + #[rustc_allow_const_fn_unstable(foo)]
-LL | const fn bar() -> u32 { foo() }
-   |
 
 error: const function that might be (indirectly) exposed to stable cannot use `#[feature(foo2)]`
   --> $DIR/min_const_fn_libstd_stability.rs:26:26
@@ -23,16 +18,11 @@ LL | const fn bar2() -> u32 { foo2() }
    |                          ^^^^^^
    |
    = help: mark the callee as `#[rustc_const_stable_indirect]` if it does not itself require any unstable features
-help: if the caller is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do)
+help: if the caller is not (yet) meant to be exposed to stable const contexts, add `#[rustc_const_unstable]`
    |
 LL + #[rustc_const_unstable(feature = "...", issue = "...")]
 LL | const fn bar2() -> u32 { foo2() }
    |
-help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval)
-   |
-LL + #[rustc_allow_const_fn_unstable(foo2)]
-LL | const fn bar2() -> u32 { foo2() }
-   |
 
 error: const function that might be (indirectly) exposed to stable cannot use `#[feature(const_async_blocks)]`
   --> $DIR/min_const_fn_libstd_stability.rs:32:13
@@ -40,16 +30,11 @@ error: const function that might be (indirectly) exposed to stable cannot use `#
 LL |     let x = async { 13 };
    |             ^^^^^^^^^^^^
    |
-help: if the function is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do)
+help: if the function is not (yet) meant to be exposed to stable const contexts, add `#[rustc_const_unstable]`
    |
 LL + #[rustc_const_unstable(feature = "...", issue = "...")]
 LL | const fn bar3() -> u32 {
    |
-help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval)
-   |
-LL + #[rustc_allow_const_fn_unstable(const_async_blocks)]
-LL | const fn bar3() -> u32 {
-   |
 
 error: const function that might be (indirectly) exposed to stable cannot use `#[feature(foo)]`
   --> $DIR/min_const_fn_libstd_stability.rs:34:5
@@ -58,16 +43,11 @@ LL |     foo()
    |     ^^^^^
    |
    = help: mark the callee as `#[rustc_const_stable_indirect]` if it does not itself require any unstable features
-help: if the caller is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do)
+help: if the caller is not (yet) meant to be exposed to stable const contexts, add `#[rustc_const_unstable]`
    |
 LL + #[rustc_const_unstable(feature = "...", issue = "...")]
 LL | const fn bar3() -> u32 {
    |
-help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval)
-   |
-LL + #[rustc_allow_const_fn_unstable(foo)]
-LL | const fn bar3() -> u32 {
-   |
 
 error: const function that might be (indirectly) exposed to stable cannot use `#[feature(foo2)]`
   --> $DIR/min_const_fn_libstd_stability.rs:46:32
@@ -76,16 +56,11 @@ LL | const fn bar2_gated() -> u32 { foo2_gated() }
    |                                ^^^^^^^^^^^^
    |
    = help: mark the callee as `#[rustc_const_stable_indirect]` if it does not itself require any unstable features
-help: if the caller is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do)
+help: if the caller is not (yet) meant to be exposed to stable const contexts, add `#[rustc_const_unstable]`
    |
 LL + #[rustc_const_unstable(feature = "...", issue = "...")]
 LL | const fn bar2_gated() -> u32 { foo2_gated() }
    |
-help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval)
-   |
-LL + #[rustc_allow_const_fn_unstable(foo2)]
-LL | const fn bar2_gated() -> u32 { foo2_gated() }
-   |
 
 error: const function that might be (indirectly) exposed to stable cannot use `#[feature(foo2)]`
   --> $DIR/min_const_fn_libstd_stability.rs:53:63
@@ -94,16 +69,11 @@ LL |     pub(crate) const fn bar2_gated_stable_indirect() -> u32 { super::foo2_g
    |                                                               ^^^^^^^^^^^^^^^^^^^
    |
    = help: mark the callee as `#[rustc_const_stable_indirect]` if it does not itself require any unstable features
-help: if the caller is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do)
+help: if the caller is not (yet) meant to be exposed to stable const contexts, add `#[rustc_const_unstable]`
    |
 LL +     #[rustc_const_unstable(feature = "...", issue = "...")]
 LL |     pub(crate) const fn bar2_gated_stable_indirect() -> u32 { super::foo2_gated() }
    |
-help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval)
-   |
-LL +     #[rustc_allow_const_fn_unstable(foo2)]
-LL |     pub(crate) const fn bar2_gated_stable_indirect() -> u32 { super::foo2_gated() }
-   |
 
 error: const function that might be (indirectly) exposed to stable cannot use `#[feature(foo2)]`
   --> $DIR/min_const_fn_libstd_stability.rs:59:37
@@ -112,16 +82,11 @@ LL | const fn stable_indirect() -> u32 { foo2_gated() }
    |                                     ^^^^^^^^^^^^
    |
    = help: mark the callee as `#[rustc_const_stable_indirect]` if it does not itself require any unstable features
-help: if the caller is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do)
+help: if the caller is not (yet) meant to be exposed to stable const contexts, add `#[rustc_const_unstable]`
    |
 LL + #[rustc_const_unstable(feature = "...", issue = "...")]
 LL | const fn stable_indirect() -> u32 { foo2_gated() }
    |
-help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval)
-   |
-LL + #[rustc_allow_const_fn_unstable(foo2)]
-LL | const fn stable_indirect() -> u32 { foo2_gated() }
-   |
 
 error: aborting due to 7 previous errors
 
diff --git a/tests/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability.stderr b/tests/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability.stderr
index b61f7db6f43..0712a790955 100644
--- a/tests/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability.stderr
+++ b/tests/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability.stderr
@@ -5,16 +5,11 @@ LL | const unsafe fn bar() -> u32 { unsafe { foo() } }
    |                                         ^^^^^
    |
    = help: mark the callee as `#[rustc_const_stable_indirect]` if it does not itself require any unstable features
-help: if the caller is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do)
+help: if the caller is not (yet) meant to be exposed to stable const contexts, add `#[rustc_const_unstable]`
    |
 LL + #[rustc_const_unstable(feature = "...", issue = "...")]
 LL | const unsafe fn bar() -> u32 { unsafe { foo() } }
    |
-help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval)
-   |
-LL + #[rustc_allow_const_fn_unstable(foo)]
-LL | const unsafe fn bar() -> u32 { unsafe { foo() } }
-   |
 
 error: const function that might be (indirectly) exposed to stable cannot use `#[feature(foo2)]`
   --> $DIR/min_const_unsafe_fn_libstd_stability.rs:25:42
@@ -23,16 +18,11 @@ LL | const unsafe fn bar2() -> u32 { unsafe { foo2() } }
    |                                          ^^^^^^
    |
    = help: mark the callee as `#[rustc_const_stable_indirect]` if it does not itself require any unstable features
-help: if the caller is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do)
+help: if the caller is not (yet) meant to be exposed to stable const contexts, add `#[rustc_const_unstable]`
    |
 LL + #[rustc_const_unstable(feature = "...", issue = "...")]
 LL | const unsafe fn bar2() -> u32 { unsafe { foo2() } }
    |
-help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval)
-   |
-LL + #[rustc_allow_const_fn_unstable(foo2)]
-LL | const unsafe fn bar2() -> u32 { unsafe { foo2() } }
-   |
 
 error: const function that might be (indirectly) exposed to stable cannot use `#[feature(foo2)]`
   --> $DIR/min_const_unsafe_fn_libstd_stability.rs:35:48
@@ -41,16 +31,11 @@ LL | const unsafe fn bar2_gated() -> u32 { unsafe { foo2_gated() } }
    |                                                ^^^^^^^^^^^^
    |
    = help: mark the callee as `#[rustc_const_stable_indirect]` if it does not itself require any unstable features
-help: if the caller is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do)
+help: if the caller is not (yet) meant to be exposed to stable const contexts, add `#[rustc_const_unstable]`
    |
 LL + #[rustc_const_unstable(feature = "...", issue = "...")]
 LL | const unsafe fn bar2_gated() -> u32 { unsafe { foo2_gated() } }
    |
-help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval)
-   |
-LL + #[rustc_allow_const_fn_unstable(foo2)]
-LL | const unsafe fn bar2_gated() -> u32 { unsafe { foo2_gated() } }
-   |
 
 error: aborting due to 3 previous errors
 
diff --git a/tests/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability2.stderr b/tests/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability2.stderr
index fad8e396e9a..618b9a16dd4 100644
--- a/tests/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability2.stderr
+++ b/tests/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability2.stderr
@@ -5,16 +5,11 @@ LL | const unsafe fn bar() -> u32 { foo() }
    |                                ^^^^^
    |
    = help: mark the callee as `#[rustc_const_stable_indirect]` if it does not itself require any unstable features
-help: if the caller is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do)
+help: if the caller is not (yet) meant to be exposed to stable const contexts, add `#[rustc_const_unstable]`
    |
 LL + #[rustc_const_unstable(feature = "...", issue = "...")]
 LL | const unsafe fn bar() -> u32 { foo() }
    |
-help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval)
-   |
-LL + #[rustc_allow_const_fn_unstable(foo)]
-LL | const unsafe fn bar() -> u32 { foo() }
-   |
 
 error: const function that might be (indirectly) exposed to stable cannot use `#[feature(foo2)]`
   --> $DIR/min_const_unsafe_fn_libstd_stability2.rs:25:33
@@ -23,16 +18,11 @@ LL | const unsafe fn bar2() -> u32 { foo2() }
    |                                 ^^^^^^
    |
    = help: mark the callee as `#[rustc_const_stable_indirect]` if it does not itself require any unstable features
-help: if the caller is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do)
+help: if the caller is not (yet) meant to be exposed to stable const contexts, add `#[rustc_const_unstable]`
    |
 LL + #[rustc_const_unstable(feature = "...", issue = "...")]
 LL | const unsafe fn bar2() -> u32 { foo2() }
    |
-help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval)
-   |
-LL + #[rustc_allow_const_fn_unstable(foo2)]
-LL | const unsafe fn bar2() -> u32 { foo2() }
-   |
 
 error: const function that might be (indirectly) exposed to stable cannot use `#[feature(foo2)]`
   --> $DIR/min_const_unsafe_fn_libstd_stability2.rs:35:39
@@ -41,16 +31,11 @@ LL | const unsafe fn bar2_gated() -> u32 { foo2_gated() }
    |                                       ^^^^^^^^^^^^
    |
    = help: mark the callee as `#[rustc_const_stable_indirect]` if it does not itself require any unstable features
-help: if the caller is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do)
+help: if the caller is not (yet) meant to be exposed to stable const contexts, add `#[rustc_const_unstable]`
    |
 LL + #[rustc_const_unstable(feature = "...", issue = "...")]
 LL | const unsafe fn bar2_gated() -> u32 { foo2_gated() }
    |
-help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval)
-   |
-LL + #[rustc_allow_const_fn_unstable(foo2)]
-LL | const unsafe fn bar2_gated() -> u32 { foo2_gated() }
-   |
 
 error: aborting due to 3 previous errors
 
diff --git a/tests/ui/consts/min_const_fn/recursive_const_stab_unmarked_crate_imports.stderr b/tests/ui/consts/min_const_fn/recursive_const_stab_unmarked_crate_imports.stderr
index bbe749f5958..04804cb6d33 100644
--- a/tests/ui/consts/min_const_fn/recursive_const_stab_unmarked_crate_imports.stderr
+++ b/tests/ui/consts/min_const_fn/recursive_const_stab_unmarked_crate_imports.stderr
@@ -5,16 +5,11 @@ LL |     unstable_if_unmarked_const_fn_crate::not_stably_const();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = help: mark the callee as `#[rustc_const_stable_indirect]` if it does not itself require any unstable features
-help: if the caller is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do)
+help: if the caller is not (yet) meant to be exposed to stable const contexts, add `#[rustc_const_unstable]`
    |
 LL + #[rustc_const_unstable(feature = "...", issue = "...")]
 LL | const fn stable_fn() {
    |
-help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval)
-   |
-LL + #[rustc_allow_const_fn_unstable(rustc_private)]
-LL | const fn stable_fn() {
-   |
 
 error: `just_a_fn` cannot be (indirectly) exposed to stable
   --> $DIR/recursive_const_stab_unmarked_crate_imports.rs:17:5
diff --git a/tests/ui/consts/min_const_fn/recursive_const_stab_unstable_if_unmarked.stderr b/tests/ui/consts/min_const_fn/recursive_const_stab_unstable_if_unmarked.stderr
index 9d7b81c822b..14940ae93f8 100644
--- a/tests/ui/consts/min_const_fn/recursive_const_stab_unstable_if_unmarked.stderr
+++ b/tests/ui/consts/min_const_fn/recursive_const_stab_unstable_if_unmarked.stderr
@@ -5,16 +5,11 @@ LL |     not_stably_const();
    |     ^^^^^^^^^^^^^^^^^^
    |
    = help: mark the callee as `#[rustc_const_stable_indirect]` if it does not itself require any unstable features
-help: if the caller is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do)
+help: if the caller is not (yet) meant to be exposed to stable const contexts, add `#[rustc_const_unstable]`
    |
 LL + #[rustc_const_unstable(feature = "...", issue = "...")]
 LL | pub const fn expose_on_stable() {
    |
-help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval)
-   |
-LL + #[rustc_allow_const_fn_unstable(rustc_private)]
-LL | pub const fn expose_on_stable() {
-   |
 
 error: const function that might be (indirectly) exposed to stable cannot use `#[feature(const_async_blocks)]`
   --> $DIR/recursive_const_stab_unstable_if_unmarked.rs:18:14
@@ -22,16 +17,11 @@ error: const function that might be (indirectly) exposed to stable cannot use `#
 LL |     let _x = async { 15 };
    |              ^^^^^^^^^^^^
    |
-help: if the function is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do)
+help: if the function is not (yet) meant to be exposed to stable const contexts, add `#[rustc_const_unstable]`
    |
 LL + #[rustc_const_unstable(feature = "...", issue = "...")]
 LL | pub const fn expose_on_stable() {
    |
-help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval)
-   |
-LL + #[rustc_allow_const_fn_unstable(const_async_blocks)]
-LL | pub const fn expose_on_stable() {
-   |
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/consts/missing_span_in_backtrace.stderr b/tests/ui/consts/missing_span_in_backtrace.stderr
index 7c07710332b..f802138c613 100644
--- a/tests/ui/consts/missing_span_in_backtrace.stderr
+++ b/tests/ui/consts/missing_span_in_backtrace.stderr
@@ -8,8 +8,6 @@ error[E0080]: evaluation of constant value failed
 18 | |         );
    | |_________^ unable to copy parts of a pointer from memory at ALLOC0
    |
-note: inside `swap_nonoverlapping::<MaybeUninit<u8>>`
-  --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
 note: inside `swap_nonoverlapping::compiletime::<MaybeUninit<u8>>`
   --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
 note: inside `std::ptr::swap_nonoverlapping_const::<MaybeUninit<u8>>`
@@ -18,7 +16,6 @@ note: inside `std::ptr::copy_nonoverlapping::<MaybeUninit<u8>>`
   --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
    = help: this code performed an operation that depends on the underlying bytes representing a pointer
    = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
-   = note: this error originates in the macro `$crate::intrinsics::const_eval_select` which comes from the expansion of the macro `const_eval_select` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/consts/offset_ub.stderr b/tests/ui/consts/offset_ub.stderr
index 699b63dfd66..31a2a36a669 100644
--- a/tests/ui/consts/offset_ub.stderr
+++ b/tests/ui/consts/offset_ub.stderr
@@ -3,99 +3,66 @@ error[E0080]: evaluation of constant value failed
    |
 LL | pub const BEFORE_START: *const u8 = unsafe { (&0u8 as *const u8).offset(-1) };
    |                                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ in-bounds pointer arithmetic failed: attempting to offset pointer by -$BYTES bytes, but got ALLOC0 which is at the beginning of the allocation
-   |
-note: inside `std::ptr::const_ptr::<impl *const u8>::offset`
-  --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
 
 error[E0080]: evaluation of constant value failed
   --> $DIR/offset_ub.rs:9:43
    |
 LL | pub const AFTER_END: *const u8 = unsafe { (&0u8 as *const u8).offset(2) };
    |                                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ in-bounds pointer arithmetic failed: attempting to offset pointer by $BYTES bytes, but got ALLOC1 which is only 1 byte from the end of the allocation
-   |
-note: inside `std::ptr::const_ptr::<impl *const u8>::offset`
-  --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
 
 error[E0080]: evaluation of constant value failed
   --> $DIR/offset_ub.rs:10:45
    |
 LL | pub const AFTER_ARRAY: *const u8 = unsafe { [0u8; 100].as_ptr().offset(101) };
    |                                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ in-bounds pointer arithmetic failed: attempting to offset pointer by $BYTES bytes, but got ALLOC2 which is only $BYTES bytes from the end of the allocation
-   |
-note: inside `std::ptr::const_ptr::<impl *const u8>::offset`
-  --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
 
 error[E0080]: evaluation of constant value failed
   --> $DIR/offset_ub.rs:12:43
    |
 LL | pub const OVERFLOW: *const u16 = unsafe { [0u16; 1].as_ptr().offset(isize::MAX) };
    |                                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing pointer arithmetic: the total offset in bytes does not fit in an `isize`
-   |
-note: inside `std::ptr::const_ptr::<impl *const u16>::offset`
-  --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
 
 error[E0080]: evaluation of constant value failed
   --> $DIR/offset_ub.rs:13:44
    |
 LL | pub const UNDERFLOW: *const u16 = unsafe { [0u16; 1].as_ptr().offset(isize::MIN) };
    |                                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing pointer arithmetic: the total offset in bytes does not fit in an `isize`
-   |
-note: inside `std::ptr::const_ptr::<impl *const u16>::offset`
-  --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
 
 error[E0080]: evaluation of constant value failed
   --> $DIR/offset_ub.rs:14:56
    |
 LL | pub const OVERFLOW_ADDRESS_SPACE: *const u8 = unsafe { (usize::MAX as *const u8).offset(2) };
    |                                                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ in-bounds pointer arithmetic failed: attempting to offset pointer by $BYTES bytes, but got 0xf..f[noalloc] which is a dangling pointer (it has no provenance)
-   |
-note: inside `std::ptr::const_ptr::<impl *const u8>::offset`
-  --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
 
 error[E0080]: evaluation of constant value failed
   --> $DIR/offset_ub.rs:15:57
    |
 LL | pub const UNDERFLOW_ADDRESS_SPACE: *const u8 = unsafe { (1 as *const u8).offset(-2) };
    |                                                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^ in-bounds pointer arithmetic failed: attempting to offset pointer by -$BYTES bytes, but got 0x1[noalloc] which is a dangling pointer (it has no provenance)
-   |
-note: inside `std::ptr::const_ptr::<impl *const u8>::offset`
-  --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
 
 error[E0080]: evaluation of constant value failed
   --> $DIR/offset_ub.rs:16:49
    |
 LL | pub const NEGATIVE_OFFSET: *const u8 = unsafe { [0u8; 1].as_ptr().wrapping_offset(-2).offset(-2) };
    |                                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ in-bounds pointer arithmetic failed: attempting to offset pointer by -$BYTES bytes, but got ALLOC3-0x2 which is only $BYTES bytes from the beginning of the allocation
-   |
-note: inside `std::ptr::const_ptr::<impl *const u8>::offset`
-  --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
 
 error[E0080]: evaluation of constant value failed
   --> $DIR/offset_ub.rs:18:50
    |
 LL | pub const ZERO_SIZED_ALLOC: *const u8 = unsafe { [0u8; 0].as_ptr().offset(1) };
    |                                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^ in-bounds pointer arithmetic failed: attempting to offset pointer by 1 byte, but got ALLOC4 which is at or beyond the end of the allocation of size $BYTES bytes
-   |
-note: inside `std::ptr::const_ptr::<impl *const u8>::offset`
-  --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
 
 error[E0080]: evaluation of constant value failed
   --> $DIR/offset_ub.rs:19:42
    |
 LL | pub const DANGLING: *const u8 = unsafe { ptr::NonNull::<u8>::dangling().as_ptr().offset(4) };
    |                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ in-bounds pointer arithmetic failed: attempting to offset pointer by $BYTES bytes, but got 0x1[noalloc] which is a dangling pointer (it has no provenance)
-   |
-note: inside `std::ptr::mut_ptr::<impl *mut u8>::offset`
-  --> $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
 
 error[E0080]: evaluation of constant value failed
   --> $DIR/offset_ub.rs:22:47
    |
 LL | pub const UNDERFLOW_ABS: *const u8 = unsafe { (usize::MAX as *const u8).offset(isize::MIN) };
    |                                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ in-bounds pointer arithmetic failed: attempting to offset pointer by -$BYTES bytes, but got 0xf..f[noalloc] which is a dangling pointer (it has no provenance)
-   |
-note: inside `std::ptr::const_ptr::<impl *const u8>::offset`
-  --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
 
 error: aborting due to 11 previous errors
 
diff --git a/tests/ui/consts/required-consts/interpret-in-promoted.noopt.stderr b/tests/ui/consts/required-consts/interpret-in-promoted.noopt.stderr
index f70e262ac4c..1375ac751f2 100644
--- a/tests/ui/consts/required-consts/interpret-in-promoted.noopt.stderr
+++ b/tests/ui/consts/required-consts/interpret-in-promoted.noopt.stderr
@@ -8,9 +8,7 @@ note: inside `ub`
   --> $DIR/interpret-in-promoted.rs:9:5
    |
 LL |     std::hint::unreachable_unchecked();
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-note: inside `unreachable_unchecked`
-  --> $SRC_DIR/core/src/hint.rs:LL:COL
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the failure occurred here
 
 note: erroneous constant encountered
   --> $DIR/interpret-in-promoted.rs:15:27
diff --git a/tests/ui/consts/required-consts/interpret-in-promoted.opt.stderr b/tests/ui/consts/required-consts/interpret-in-promoted.opt.stderr
index f70e262ac4c..1375ac751f2 100644
--- a/tests/ui/consts/required-consts/interpret-in-promoted.opt.stderr
+++ b/tests/ui/consts/required-consts/interpret-in-promoted.opt.stderr
@@ -8,9 +8,7 @@ note: inside `ub`
   --> $DIR/interpret-in-promoted.rs:9:5
    |
 LL |     std::hint::unreachable_unchecked();
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-note: inside `unreachable_unchecked`
-  --> $SRC_DIR/core/src/hint.rs:LL:COL
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the failure occurred here
 
 note: erroneous constant encountered
   --> $DIR/interpret-in-promoted.rs:15:27
diff --git a/tests/ui/coroutine/auxiliary/xcrate.rs b/tests/ui/coroutine/auxiliary/xcrate.rs
index 52f188135bd..524eaafc752 100644
--- a/tests/ui/coroutine/auxiliary/xcrate.rs
+++ b/tests/ui/coroutine/auxiliary/xcrate.rs
@@ -12,7 +12,7 @@ pub fn foo() -> impl Coroutine<(), Yield = (), Return = ()> {
     }
 }
 
-pub fn bar<T: 'static>(t: T) -> Box<Coroutine<(), Yield = T, Return = ()> + Unpin> {
+pub fn bar<T: 'static>(t: T) -> Box<dyn Coroutine<(), Yield = T, Return = ()> + Unpin> {
     Box::new(
         #[coroutine]
         || {
diff --git a/tests/ui/coroutine/const_gen_fn.rs b/tests/ui/coroutine/const_gen_fn.rs
index 2701139ffed..b044c185e0f 100644
--- a/tests/ui/coroutine/const_gen_fn.rs
+++ b/tests/ui/coroutine/const_gen_fn.rs
@@ -4,8 +4,10 @@
 
 const gen fn a() {}
 //~^ ERROR functions cannot be both `const` and `gen`
+//~^^ ERROR `gen` fn bodies are not allowed in constant functions
 
 const async gen fn b() {}
 //~^ ERROR functions cannot be both `const` and `async gen`
+//~^^ ERROR `async gen` fn bodies are not allowed in constant functions
 
 fn main() {}
diff --git a/tests/ui/coroutine/const_gen_fn.stderr b/tests/ui/coroutine/const_gen_fn.stderr
index 4f3c73d1678..400ee216d06 100644
--- a/tests/ui/coroutine/const_gen_fn.stderr
+++ b/tests/ui/coroutine/const_gen_fn.stderr
@@ -8,7 +8,7 @@ LL | const gen fn a() {}
    | `const` because of this
 
 error: functions cannot be both `const` and `async gen`
-  --> $DIR/const_gen_fn.rs:8:1
+  --> $DIR/const_gen_fn.rs:9:1
    |
 LL | const async gen fn b() {}
    | ^^^^^-^^^^^^^^^----------
@@ -16,5 +16,17 @@ LL | const async gen fn b() {}
    | |     `async gen` because of this
    | `const` because of this
 
-error: aborting due to 2 previous errors
+error: `gen` fn bodies are not allowed in constant functions
+  --> $DIR/const_gen_fn.rs:5:18
+   |
+LL | const gen fn a() {}
+   |                  ^^
+
+error: `async gen` fn bodies are not allowed in constant functions
+  --> $DIR/const_gen_fn.rs:9:24
+   |
+LL | const async gen fn b() {}
+   |                        ^^
+
+error: aborting due to 4 previous errors
 
diff --git a/tests/ui/coroutine/gen_block.none.stderr b/tests/ui/coroutine/gen_block.none.stderr
index ed744f2957a..b793033b521 100644
--- a/tests/ui/coroutine/gen_block.none.stderr
+++ b/tests/ui/coroutine/gen_block.none.stderr
@@ -31,7 +31,7 @@ LL |     let _ = || yield true;
    |                ^^^^^^^^^^
    |
    = note: see issue #43122 <https://github.com/rust-lang/rust/issues/43122> for more information
-   = help: add `#![feature(coroutines)]` to the crate attributes to enable
+   = help: add `#![feature(yield_expr)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
 error[E0658]: yield syntax is experimental
@@ -41,7 +41,7 @@ LL |     let _ = #[coroutine] || yield true;
    |                             ^^^^^^^^^^
    |
    = note: see issue #43122 <https://github.com/rust-lang/rust/issues/43122> for more information
-   = help: add `#![feature(coroutines)]` to the crate attributes to enable
+   = help: add `#![feature(yield_expr)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
 error[E0658]: the `#[coroutine]` attribute is an experimental feature
diff --git a/tests/ui/delegation/bad-resolve.stderr b/tests/ui/delegation/bad-resolve.stderr
index 966387e1d61..fc6811292a6 100644
--- a/tests/ui/delegation/bad-resolve.stderr
+++ b/tests/ui/delegation/bad-resolve.stderr
@@ -44,9 +44,7 @@ error[E0575]: expected method or associated constant, found associated type `Tra
   --> $DIR/bad-resolve.rs:27:11
    |
 LL |     reuse <F as Trait>::Type;
-   |           ^^^^^^^^^^^^^^^^^^
-   |
-   = note: can't use a type alias as a constructor
+   |           ^^^^^^^^^^^^^^^^^^ not a method or associated constant
 
 error[E0576]: cannot find method or associated constant `baz` in trait `Trait`
   --> $DIR/bad-resolve.rs:30:25
diff --git a/tests/ui/delegation/glob-non-fn.stderr b/tests/ui/delegation/glob-non-fn.stderr
index 4b918c53b84..f63c8e88c6f 100644
--- a/tests/ui/delegation/glob-non-fn.stderr
+++ b/tests/ui/delegation/glob-non-fn.stderr
@@ -38,9 +38,7 @@ error[E0423]: expected function, found associated type `Trait::Type`
   --> $DIR/glob-non-fn.rs:30:11
    |
 LL |     reuse Trait::* { &self.0 }
-   |           ^^^^^
-   |
-   = note: can't use a type alias as a constructor
+   |           ^^^^^ not a function
 
 error[E0046]: not all trait items implemented, missing: `CONST`, `Type`, `method`
   --> $DIR/glob-non-fn.rs:29:1
diff --git a/tests/ui/deprecation/deprecation-lint.rs b/tests/ui/deprecation/deprecation-lint.rs
index dc11a4d56a2..5eda38732c8 100644
--- a/tests/ui/deprecation/deprecation-lint.rs
+++ b/tests/ui/deprecation/deprecation-lint.rs
@@ -71,7 +71,7 @@ mod cross_crate {
         <Foo as Trait>::trait_deprecated_text(&foo); //~ ERROR use of deprecated method `deprecation_lint::Trait::trait_deprecated_text`: text
     }
 
-    fn test_method_object(foo: &Trait) {
+    fn test_method_object(foo: &dyn Trait) {
         foo.trait_deprecated(); //~ ERROR use of deprecated method `deprecation_lint::Trait::trait_deprecated`
         foo.trait_deprecated_text(); //~ ERROR use of deprecated method `deprecation_lint::Trait::trait_deprecated_text`: text
     }
@@ -299,7 +299,7 @@ mod this_crate {
         <Foo as Trait>::trait_deprecated_text(&foo); //~ ERROR use of deprecated method `this_crate::Trait::trait_deprecated_text`: text
     }
 
-    fn test_method_object(foo: &Trait) {
+    fn test_method_object(foo: &dyn Trait) {
         foo.trait_deprecated(); //~ ERROR use of deprecated method `this_crate::Trait::trait_deprecated`
         foo.trait_deprecated_text(); //~ ERROR use of deprecated method `this_crate::Trait::trait_deprecated_text`: text
     }
diff --git a/tests/ui/derives/clone-debug-dead-code.stderr b/tests/ui/derives/clone-debug-dead-code.stderr
index 38be486e332..34b7f929ec5 100644
--- a/tests/ui/derives/clone-debug-dead-code.stderr
+++ b/tests/ui/derives/clone-debug-dead-code.stderr
@@ -40,7 +40,7 @@ LL | struct D { f: () }
    |        |
    |        field in this struct
    |
-   = note: `D` has derived impls for the traits `Clone` and `Debug`, but these are intentionally ignored during dead code analysis
+   = note: `D` has derived impls for the traits `Debug` and `Clone`, but these are intentionally ignored during dead code analysis
 
 error: field `f` is never read
   --> $DIR/clone-debug-dead-code.rs:21:12
diff --git a/tests/ui/deriving/deriving-all-codegen.rs b/tests/ui/deriving/deriving-all-codegen.rs
index eab2b4f1f53..e2b6804fbd1 100644
--- a/tests/ui/deriving/deriving-all-codegen.rs
+++ b/tests/ui/deriving/deriving-all-codegen.rs
@@ -45,6 +45,22 @@ struct Big {
     b1: u32, b2: u32, b3: u32, b4: u32, b5: u32, b6: u32, b7: u32, b8: u32,
 }
 
+// It is more efficient to compare scalar types before non-scalar types.
+#[derive(PartialEq, PartialOrd)]
+struct Reorder {
+    b1: Option<f32>,
+    b2: u16,
+    b3: &'static str,
+    b4: i8,
+    b5: u128,
+    _b: *mut &'static dyn FnMut() -> (),
+    b6: f64,
+    b7: &'static mut (),
+    b8: char,
+    b9: &'static [i64],
+    b10: &'static *const bool,
+}
+
 // A struct that doesn't impl `Copy`, which means it gets the non-simple
 // `clone` implemention that clones the fields individually.
 #[derive(Clone)]
@@ -130,6 +146,20 @@ enum Mixed {
     S { d1: Option<u32>, d2: Option<i32> },
 }
 
+// When comparing enum variant it is more efficient to compare scalar types before non-scalar types.
+#[derive(PartialEq, PartialOrd)]
+enum ReorderEnum {
+    A(i32),
+    B,
+    C(i8),
+    D,
+    E,
+    F,
+    G(&'static mut str, *const u8, *const dyn Fn() -> ()),
+    H,
+    I,
+}
+
 // An enum with no fieldless variants. Note that `Default` cannot be derived
 // for this enum.
 #[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
diff --git a/tests/ui/deriving/deriving-all-codegen.stdout b/tests/ui/deriving/deriving-all-codegen.stdout
index 6503c870990..fa8f249373d 100644
--- a/tests/ui/deriving/deriving-all-codegen.stdout
+++ b/tests/ui/deriving/deriving-all-codegen.stdout
@@ -419,6 +419,100 @@ impl ::core::cmp::Ord for Big {
     }
 }
 
+// It is more efficient to compare scalar types before non-scalar types.
+struct Reorder {
+    b1: Option<f32>,
+    b2: u16,
+    b3: &'static str,
+    b4: i8,
+    b5: u128,
+    _b: *mut &'static dyn FnMut() -> (),
+    b6: f64,
+    b7: &'static mut (),
+    b8: char,
+    b9: &'static [i64],
+    b10: &'static *const bool,
+}
+#[automatically_derived]
+impl ::core::marker::StructuralPartialEq for Reorder { }
+#[automatically_derived]
+impl ::core::cmp::PartialEq for Reorder {
+    #[inline]
+    fn eq(&self, other: &Reorder) -> bool {
+        self.b2 == other.b2 && self.b4 == other.b4 && self.b5 == other.b5 &&
+                                        self.b6 == other.b6 && self.b7 == other.b7 &&
+                                self.b8 == other.b8 && self.b10 == other.b10 &&
+                        self.b1 == other.b1 && self.b3 == other.b3 &&
+                self._b == other._b && self.b9 == other.b9
+    }
+}
+#[automatically_derived]
+impl ::core::cmp::PartialOrd for Reorder {
+    #[inline]
+    fn partial_cmp(&self, other: &Reorder)
+        -> ::core::option::Option<::core::cmp::Ordering> {
+        match ::core::cmp::PartialOrd::partial_cmp(&self.b1, &other.b1) {
+            ::core::option::Option::Some(::core::cmp::Ordering::Equal) =>
+                match ::core::cmp::PartialOrd::partial_cmp(&self.b2,
+                        &other.b2) {
+                    ::core::option::Option::Some(::core::cmp::Ordering::Equal)
+                        =>
+                        match ::core::cmp::PartialOrd::partial_cmp(&self.b3,
+                                &other.b3) {
+                            ::core::option::Option::Some(::core::cmp::Ordering::Equal)
+                                =>
+                                match ::core::cmp::PartialOrd::partial_cmp(&self.b4,
+                                        &other.b4) {
+                                    ::core::option::Option::Some(::core::cmp::Ordering::Equal)
+                                        =>
+                                        match ::core::cmp::PartialOrd::partial_cmp(&self.b5,
+                                                &other.b5) {
+                                            ::core::option::Option::Some(::core::cmp::Ordering::Equal)
+                                                =>
+                                                match ::core::cmp::PartialOrd::partial_cmp(&self._b,
+                                                        &other._b) {
+                                                    ::core::option::Option::Some(::core::cmp::Ordering::Equal)
+                                                        =>
+                                                        match ::core::cmp::PartialOrd::partial_cmp(&self.b6,
+                                                                &other.b6) {
+                                                            ::core::option::Option::Some(::core::cmp::Ordering::Equal)
+                                                                =>
+                                                                match ::core::cmp::PartialOrd::partial_cmp(&self.b7,
+                                                                        &other.b7) {
+                                                                    ::core::option::Option::Some(::core::cmp::Ordering::Equal)
+                                                                        =>
+                                                                        match ::core::cmp::PartialOrd::partial_cmp(&self.b8,
+                                                                                &other.b8) {
+                                                                            ::core::option::Option::Some(::core::cmp::Ordering::Equal)
+                                                                                =>
+                                                                                match ::core::cmp::PartialOrd::partial_cmp(&self.b9,
+                                                                                        &other.b9) {
+                                                                                    ::core::option::Option::Some(::core::cmp::Ordering::Equal)
+                                                                                        =>
+                                                                                        ::core::cmp::PartialOrd::partial_cmp(&self.b10, &other.b10),
+                                                                                    cmp => cmp,
+                                                                                },
+                                                                            cmp => cmp,
+                                                                        },
+                                                                    cmp => cmp,
+                                                                },
+                                                            cmp => cmp,
+                                                        },
+                                                    cmp => cmp,
+                                                },
+                                            cmp => cmp,
+                                        },
+                                    cmp => cmp,
+                                },
+                            cmp => cmp,
+                        },
+                    cmp => cmp,
+                },
+            cmp => cmp,
+        }
+    }
+}
+
 // A struct that doesn't impl `Copy`, which means it gets the non-simple
 // `clone` implemention that clones the fields individually.
 struct NonCopy(u32);
@@ -1167,6 +1261,77 @@ impl ::core::cmp::Ord for Mixed {
     }
 }
 
+// When comparing enum variant it is more efficient to compare scalar types before non-scalar types.
+enum ReorderEnum {
+    A(i32),
+    B,
+    C(i8),
+    D,
+    E,
+    F,
+    G(&'static mut str, *const u8, *const dyn Fn() -> ()),
+    H,
+    I,
+}
+#[automatically_derived]
+impl ::core::marker::StructuralPartialEq for ReorderEnum { }
+#[automatically_derived]
+impl ::core::cmp::PartialEq for ReorderEnum {
+    #[inline]
+    fn eq(&self, other: &ReorderEnum) -> bool {
+        let __self_discr = ::core::intrinsics::discriminant_value(self);
+        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
+        __self_discr == __arg1_discr &&
+            match (self, other) {
+                (ReorderEnum::A(__self_0), ReorderEnum::A(__arg1_0)) =>
+                    __self_0 == __arg1_0,
+                (ReorderEnum::C(__self_0), ReorderEnum::C(__arg1_0)) =>
+                    __self_0 == __arg1_0,
+                (ReorderEnum::G(__self_0, __self_1, __self_2),
+                    ReorderEnum::G(__arg1_0, __arg1_1, __arg1_2)) =>
+                    __self_1 == __arg1_1 && __self_0 == __arg1_0 &&
+                        __self_2 == __arg1_2,
+                _ => true,
+            }
+    }
+}
+#[automatically_derived]
+impl ::core::cmp::PartialOrd for ReorderEnum {
+    #[inline]
+    fn partial_cmp(&self, other: &ReorderEnum)
+        -> ::core::option::Option<::core::cmp::Ordering> {
+        let __self_discr = ::core::intrinsics::discriminant_value(self);
+        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
+        match ::core::cmp::PartialOrd::partial_cmp(&__self_discr,
+                &__arg1_discr) {
+            ::core::option::Option::Some(::core::cmp::Ordering::Equal) =>
+                match (self, other) {
+                    (ReorderEnum::A(__self_0), ReorderEnum::A(__arg1_0)) =>
+                        ::core::cmp::PartialOrd::partial_cmp(__self_0, __arg1_0),
+                    (ReorderEnum::C(__self_0), ReorderEnum::C(__arg1_0)) =>
+                        ::core::cmp::PartialOrd::partial_cmp(__self_0, __arg1_0),
+                    (ReorderEnum::G(__self_0, __self_1, __self_2),
+                        ReorderEnum::G(__arg1_0, __arg1_1, __arg1_2)) =>
+                        match ::core::cmp::PartialOrd::partial_cmp(__self_0,
+                                __arg1_0) {
+                            ::core::option::Option::Some(::core::cmp::Ordering::Equal)
+                                =>
+                                match ::core::cmp::PartialOrd::partial_cmp(__self_1,
+                                        __arg1_1) {
+                                    ::core::option::Option::Some(::core::cmp::Ordering::Equal)
+                                        => ::core::cmp::PartialOrd::partial_cmp(__self_2, __arg1_2),
+                                    cmp => cmp,
+                                },
+                            cmp => cmp,
+                        },
+                    _ =>
+                        ::core::option::Option::Some(::core::cmp::Ordering::Equal),
+                },
+            cmp => cmp,
+        }
+    }
+}
+
 // An enum with no fieldless variants. Note that `Default` cannot be derived
 // for this enum.
 enum Fielded { X(u32), Y(bool), Z(Option<i32>), }
diff --git a/tests/ui/deriving/deriving-in-macro.rs b/tests/ui/deriving/deriving-in-macro.rs
index 493c1415c7f..739d9b30682 100644
--- a/tests/ui/deriving/deriving-in-macro.rs
+++ b/tests/ui/deriving/deriving-in-macro.rs
@@ -1,5 +1,6 @@
-//@ run-pass
+//@ check-pass
 #![allow(non_camel_case_types)]
+#![allow(dead_code)]
 
 macro_rules! define_vec {
     () => (
diff --git a/tests/ui/destructuring-assignment/bad-let-in-destructure.rs b/tests/ui/destructuring-assignment/bad-let-in-destructure.rs
new file mode 100644
index 00000000000..70a0403fc38
--- /dev/null
+++ b/tests/ui/destructuring-assignment/bad-let-in-destructure.rs
@@ -0,0 +1,13 @@
+// Regression test for <https://github.com/rust-lang/rust/issues/141844>.
+
+fn main() {
+  // The following expression gets desugared into something like:
+  // ```
+  // let (lhs,) = x; (let x = 1) = lhs;
+  // ```
+  // This used to ICE since we haven't yet declared the type for `x` when
+  // checking the first desugared statement, whose RHS resolved to `x` since
+  // in the AST, the `let` expression was visited first.
+  (let x = 1,) = x;
+  //~^ ERROR expected expression, found `let` statement
+}
diff --git a/tests/ui/destructuring-assignment/bad-let-in-destructure.stderr b/tests/ui/destructuring-assignment/bad-let-in-destructure.stderr
new file mode 100644
index 00000000000..622d714ba2f
--- /dev/null
+++ b/tests/ui/destructuring-assignment/bad-let-in-destructure.stderr
@@ -0,0 +1,10 @@
+error: expected expression, found `let` statement
+  --> $DIR/bad-let-in-destructure.rs:11:4
+   |
+LL |   (let x = 1,) = x;
+   |    ^^^
+   |
+   = note: only supported directly in conditions of `if` and `while` expressions
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/did_you_mean/E0178.rs b/tests/ui/did_you_mean/E0178.rs
index 095df640c38..cdaddac35a3 100644
--- a/tests/ui/did_you_mean/E0178.rs
+++ b/tests/ui/did_you_mean/E0178.rs
@@ -1,3 +1,4 @@
+//@ edition:2015
 #![allow(bare_trait_objects)]
 
 trait Foo {}
diff --git a/tests/ui/did_you_mean/E0178.stderr b/tests/ui/did_you_mean/E0178.stderr
index 36e4dbdf7c4..7b69f860381 100644
--- a/tests/ui/did_you_mean/E0178.stderr
+++ b/tests/ui/did_you_mean/E0178.stderr
@@ -1,5 +1,5 @@
 error[E0178]: expected a path on the left-hand side of `+`
-  --> $DIR/E0178.rs:6:8
+  --> $DIR/E0178.rs:7:8
    |
 LL |     w: &'a Foo + Copy,
    |        ^^^^^^^
@@ -10,7 +10,7 @@ LL |     w: &'a (Foo + Copy),
    |            +          +
 
 error[E0178]: expected a path on the left-hand side of `+`
-  --> $DIR/E0178.rs:7:8
+  --> $DIR/E0178.rs:8:8
    |
 LL |     x: &'a Foo + 'a,
    |        ^^^^^^^
@@ -21,7 +21,7 @@ LL |     x: &'a (Foo + 'a),
    |            +        +
 
 error[E0178]: expected a path on the left-hand side of `+`
-  --> $DIR/E0178.rs:8:8
+  --> $DIR/E0178.rs:9:8
    |
 LL |     y: &'a mut Foo + 'a,
    |        ^^^^^^^^^^^
@@ -32,7 +32,7 @@ LL |     y: &'a mut (Foo + 'a),
    |                +        +
 
 error[E0178]: expected a path on the left-hand side of `+`
-  --> $DIR/E0178.rs:9:8
+  --> $DIR/E0178.rs:10:8
    |
 LL |     z: fn() -> Foo + 'a,
    |        ^^^^^^^^^^^-----
diff --git a/tests/ui/did_you_mean/trait-object-reference-without-parens-suggestion.rs b/tests/ui/did_you_mean/trait-object-reference-without-parens-suggestion.rs
index 9cd32ffeb6d..eff431f4665 100644
--- a/tests/ui/did_you_mean/trait-object-reference-without-parens-suggestion.rs
+++ b/tests/ui/did_you_mean/trait-object-reference-without-parens-suggestion.rs
@@ -1,7 +1,9 @@
+//@ edition: 2015
 #![allow(bare_trait_objects)]
 
 fn main() {
     let _: &Copy + 'static; //~ ERROR expected a path
     //~^ ERROR is not dyn compatible
     let _: &'static Copy + 'static; //~ ERROR expected a path
+    //~^ ERROR is not dyn compatible
 }
diff --git a/tests/ui/did_you_mean/trait-object-reference-without-parens-suggestion.stderr b/tests/ui/did_you_mean/trait-object-reference-without-parens-suggestion.stderr
index 762b37b9e9d..b051d181ad8 100644
--- a/tests/ui/did_you_mean/trait-object-reference-without-parens-suggestion.stderr
+++ b/tests/ui/did_you_mean/trait-object-reference-without-parens-suggestion.stderr
@@ -1,5 +1,5 @@
 error[E0178]: expected a path on the left-hand side of `+`
-  --> $DIR/trait-object-reference-without-parens-suggestion.rs:4:12
+  --> $DIR/trait-object-reference-without-parens-suggestion.rs:5:12
    |
 LL |     let _: &Copy + 'static;
    |            ^^^^^
@@ -10,7 +10,7 @@ LL |     let _: &(Copy + 'static);
    |             +              +
 
 error[E0178]: expected a path on the left-hand side of `+`
-  --> $DIR/trait-object-reference-without-parens-suggestion.rs:6:12
+  --> $DIR/trait-object-reference-without-parens-suggestion.rs:7:12
    |
 LL |     let _: &'static Copy + 'static;
    |            ^^^^^^^^^^^^^
@@ -21,16 +21,26 @@ LL |     let _: &'static (Copy + 'static);
    |                     +              +
 
 error[E0038]: the trait `Copy` is not dyn compatible
-  --> $DIR/trait-object-reference-without-parens-suggestion.rs:4:12
+  --> $DIR/trait-object-reference-without-parens-suggestion.rs:5:13
    |
 LL |     let _: &Copy + 'static;
-   |            ^^^^^ `Copy` is not dyn compatible
+   |             ^^^^ `Copy` is not dyn compatible
    |
    = note: the trait is not dyn compatible because it requires `Self: Sized`
    = note: for a trait to be dyn compatible it needs to allow building a vtable
            for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
 
-error: aborting due to 3 previous errors
+error[E0038]: the trait `Copy` is not dyn compatible
+  --> $DIR/trait-object-reference-without-parens-suggestion.rs:7:21
+   |
+LL |     let _: &'static Copy + 'static;
+   |                     ^^^^ `Copy` is not dyn compatible
+   |
+   = note: the trait is not dyn compatible because it requires `Self: Sized`
+   = note: for a trait to be dyn compatible it needs to allow building a vtable
+           for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
+
+error: aborting due to 4 previous errors
 
 Some errors have detailed explanations: E0038, E0178.
 For more information about an error, try `rustc --explain E0038`.
diff --git a/tests/ui/dyn-compatibility/almost-supertrait-associated-type.rs b/tests/ui/dyn-compatibility/almost-supertrait-associated-type.rs
index 1b1b8bcf03d..d73b67dc080 100644
--- a/tests/ui/dyn-compatibility/almost-supertrait-associated-type.rs
+++ b/tests/ui/dyn-compatibility/almost-supertrait-associated-type.rs
@@ -6,7 +6,6 @@ use std::marker::PhantomData;
 fn transmute<T, U>(t: T) -> U {
     (&PhantomData::<T> as &dyn Foo<T, U>).transmute(t)
     //~^ ERROR the trait `Foo` is not dyn compatible
-    //~| ERROR the trait `Foo` is not dyn compatible
 }
 
 struct ActuallySuper;
diff --git a/tests/ui/dyn-compatibility/almost-supertrait-associated-type.stderr b/tests/ui/dyn-compatibility/almost-supertrait-associated-type.stderr
index a384697ee08..acd6dbe7b2c 100644
--- a/tests/ui/dyn-compatibility/almost-supertrait-associated-type.stderr
+++ b/tests/ui/dyn-compatibility/almost-supertrait-associated-type.stderr
@@ -1,12 +1,12 @@
 error[E0038]: the trait `Foo` is not dyn compatible
-  --> $DIR/almost-supertrait-associated-type.rs:21:20
+  --> $DIR/almost-supertrait-associated-type.rs:20:20
    |
 LL | impl<T, U> Dyn for dyn Foo<T, U> + '_ {
    |                    ^^^^^^^^^^^^^^^^^^ `Foo` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
       for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
-  --> $DIR/almost-supertrait-associated-type.rs:33:34
+  --> $DIR/almost-supertrait-associated-type.rs:32:34
    |
 LL | trait Foo<T, U>: Super<ActuallySuper, Assoc = T>
    |       --- this trait is not dyn compatible...
@@ -16,14 +16,14 @@ LL |     fn transmute(&self, t: T) -> <Self as Super<NotActuallySuper>>::Assoc;
    = help: consider moving `transmute` to another trait
 
 error[E0038]: the trait `Foo` is not dyn compatible
-  --> $DIR/almost-supertrait-associated-type.rs:7:27
+  --> $DIR/almost-supertrait-associated-type.rs:7:32
    |
 LL |     (&PhantomData::<T> as &dyn Foo<T, U>).transmute(t)
-   |                           ^^^^^^^^^^^^^^ `Foo` is not dyn compatible
+   |                                ^^^^^^^^^ `Foo` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
       for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
-  --> $DIR/almost-supertrait-associated-type.rs:33:34
+  --> $DIR/almost-supertrait-associated-type.rs:32:34
    |
 LL | trait Foo<T, U>: Super<ActuallySuper, Assoc = T>
    |       --- this trait is not dyn compatible...
@@ -32,24 +32,6 @@ LL |     fn transmute(&self, t: T) -> <Self as Super<NotActuallySuper>>::Assoc;
    |                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ...because method `transmute` references the `Self` type in its return type
    = help: consider moving `transmute` to another trait
 
-error[E0038]: the trait `Foo` is not dyn compatible
-  --> $DIR/almost-supertrait-associated-type.rs:7:6
-   |
-LL |     (&PhantomData::<T> as &dyn Foo<T, U>).transmute(t)
-   |      ^^^^^^^^^^^^^^^^^ `Foo` is not dyn compatible
-   |
-note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
-  --> $DIR/almost-supertrait-associated-type.rs:33:34
-   |
-LL | trait Foo<T, U>: Super<ActuallySuper, Assoc = T>
-   |       --- this trait is not dyn compatible...
-...
-LL |     fn transmute(&self, t: T) -> <Self as Super<NotActuallySuper>>::Assoc;
-   |                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ...because method `transmute` references the `Self` type in its return type
-   = help: consider moving `transmute` to another trait
-   = note: required for the cast from `&PhantomData<T>` to `&dyn Foo<T, U>`
-
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0038`.
diff --git a/tests/ui/dyn-compatibility/associated-consts.rs b/tests/ui/dyn-compatibility/associated-consts.rs
index 10d151d9a8b..69fff81b281 100644
--- a/tests/ui/dyn-compatibility/associated-consts.rs
+++ b/tests/ui/dyn-compatibility/associated-consts.rs
@@ -8,7 +8,6 @@ trait Bar {
 fn make_bar<T:Bar>(t: &T) -> &dyn Bar {
     //~^ ERROR E0038
     t
-    //~^ ERROR E0038
 }
 
 fn main() {
diff --git a/tests/ui/dyn-compatibility/associated-consts.stderr b/tests/ui/dyn-compatibility/associated-consts.stderr
index beaf263af07..dc64c93a577 100644
--- a/tests/ui/dyn-compatibility/associated-consts.stderr
+++ b/tests/ui/dyn-compatibility/associated-consts.stderr
@@ -14,23 +14,6 @@ LL |     const X: usize;
    |           ^ ...because it contains this associated `const`
    = help: consider moving `X` to another trait
 
-error[E0038]: the trait `Bar` is not dyn compatible
-  --> $DIR/associated-consts.rs:10:5
-   |
-LL |     t
-   |     ^ `Bar` is not dyn compatible
-   |
-note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
-  --> $DIR/associated-consts.rs:5:11
-   |
-LL | trait Bar {
-   |       --- this trait is not dyn compatible...
-LL |     const X: usize;
-   |           ^ ...because it contains this associated `const`
-   = help: consider moving `X` to another trait
-   = note: required for the cast from `&T` to `&dyn Bar`
-
-error: aborting due to 2 previous errors
+error: aborting due to 1 previous error
 
 For more information about this error, try `rustc --explain E0038`.
diff --git a/tests/ui/dyn-compatibility/generics.rs b/tests/ui/dyn-compatibility/generics.rs
index dcce17f925b..c25bdab361b 100644
--- a/tests/ui/dyn-compatibility/generics.rs
+++ b/tests/ui/dyn-compatibility/generics.rs
@@ -15,14 +15,12 @@ trait Quux {
 fn make_bar<T:Bar>(t: &T) -> &dyn Bar {
     //~^ ERROR E0038
     t
-    //~^ ERROR E0038
 }
 
 fn make_bar_explicit<T:Bar>(t: &T) -> &dyn Bar {
     //~^ ERROR E0038
     t as &dyn Bar
     //~^ ERROR E0038
-    //~| ERROR E0038
 }
 
 fn make_quux<T:Quux>(t: &T) -> &dyn Quux {
diff --git a/tests/ui/dyn-compatibility/generics.stderr b/tests/ui/dyn-compatibility/generics.stderr
index c0193010541..79dccc42244 100644
--- a/tests/ui/dyn-compatibility/generics.stderr
+++ b/tests/ui/dyn-compatibility/generics.stderr
@@ -15,7 +15,7 @@ LL |     fn bar<T>(&self, t: T);
    = help: consider moving `bar` to another trait
 
 error[E0038]: the trait `Bar` is not dyn compatible
-  --> $DIR/generics.rs:21:40
+  --> $DIR/generics.rs:20:40
    |
 LL | fn make_bar_explicit<T:Bar>(t: &T) -> &dyn Bar {
    |                                        ^^^^^^^ `Bar` is not dyn compatible
@@ -31,43 +31,10 @@ LL |     fn bar<T>(&self, t: T);
    = help: consider moving `bar` to another trait
 
 error[E0038]: the trait `Bar` is not dyn compatible
-  --> $DIR/generics.rs:17:5
-   |
-LL |     t
-   |     ^ `Bar` is not dyn compatible
-   |
-note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
-  --> $DIR/generics.rs:7:8
-   |
-LL | trait Bar {
-   |       --- this trait is not dyn compatible...
-LL |     fn bar<T>(&self, t: T);
-   |        ^^^ ...because method `bar` has generic type parameters
-   = help: consider moving `bar` to another trait
-   = note: required for the cast from `&T` to `&dyn Bar`
-
-error[E0038]: the trait `Bar` is not dyn compatible
-  --> $DIR/generics.rs:23:10
-   |
-LL |     t as &dyn Bar
-   |          ^^^^^^^^ `Bar` is not dyn compatible
-   |
-note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
-  --> $DIR/generics.rs:7:8
-   |
-LL | trait Bar {
-   |       --- this trait is not dyn compatible...
-LL |     fn bar<T>(&self, t: T);
-   |        ^^^ ...because method `bar` has generic type parameters
-   = help: consider moving `bar` to another trait
-
-error[E0038]: the trait `Bar` is not dyn compatible
-  --> $DIR/generics.rs:23:5
+  --> $DIR/generics.rs:22:15
    |
 LL |     t as &dyn Bar
-   |     ^ `Bar` is not dyn compatible
+   |               ^^^ `Bar` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
       for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
@@ -78,8 +45,7 @@ LL | trait Bar {
 LL |     fn bar<T>(&self, t: T);
    |        ^^^ ...because method `bar` has generic type parameters
    = help: consider moving `bar` to another trait
-   = note: required for the cast from `&T` to `&dyn Bar`
 
-error: aborting due to 5 previous errors
+error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0038`.
diff --git a/tests/ui/dyn-compatibility/mention-correct-dyn-incompatible-trait.rs b/tests/ui/dyn-compatibility/mention-correct-dyn-incompatible-trait.rs
index 1289d2d7874..d8b1bc5b717 100644
--- a/tests/ui/dyn-compatibility/mention-correct-dyn-incompatible-trait.rs
+++ b/tests/ui/dyn-compatibility/mention-correct-dyn-incompatible-trait.rs
@@ -18,5 +18,4 @@ fn main() {
     let mut thing = Thing;
     let test: &mut dyn Bar = &mut thing;
     //~^ ERROR E0038
-    //~| ERROR E0038
 }
diff --git a/tests/ui/dyn-compatibility/mention-correct-dyn-incompatible-trait.stderr b/tests/ui/dyn-compatibility/mention-correct-dyn-incompatible-trait.stderr
index c1e93ccb83c..dd7b31a70c5 100644
--- a/tests/ui/dyn-compatibility/mention-correct-dyn-incompatible-trait.stderr
+++ b/tests/ui/dyn-compatibility/mention-correct-dyn-incompatible-trait.stderr
@@ -1,8 +1,8 @@
 error[E0038]: the trait `Bar` is not dyn compatible
-  --> $DIR/mention-correct-dyn-incompatible-trait.rs:19:30
+  --> $DIR/mention-correct-dyn-incompatible-trait.rs:19:24
    |
 LL |     let test: &mut dyn Bar = &mut thing;
-   |                              ^^^^^^^^^^ `Bar` is not dyn compatible
+   |                        ^^^ `Bar` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
       for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
@@ -15,26 +15,7 @@ LL | trait Bar: Foo { }
    |       --- this trait is not dyn compatible...
    = help: consider moving `foo` to another trait
    = help: only type `Thing` implements `Bar`; consider using it directly instead.
-   = note: required for the cast from `&mut Thing` to `&mut dyn Bar`
 
-error[E0038]: the trait `Bar` is not dyn compatible
-  --> $DIR/mention-correct-dyn-incompatible-trait.rs:19:15
-   |
-LL |     let test: &mut dyn Bar = &mut thing;
-   |               ^^^^^^^^^^^^ `Bar` is not dyn compatible
-   |
-note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
-  --> $DIR/mention-correct-dyn-incompatible-trait.rs:4:8
-   |
-LL |     fn foo<T>(&self, val: T);
-   |        ^^^ ...because method `foo` has generic type parameters
-...
-LL | trait Bar: Foo { }
-   |       --- this trait is not dyn compatible...
-   = help: consider moving `foo` to another trait
-   = help: only type `Thing` implements `Bar`; consider using it directly instead.
-
-error: aborting due to 2 previous errors
+error: aborting due to 1 previous error
 
 For more information about this error, try `rustc --explain E0038`.
diff --git a/tests/ui/dyn-compatibility/mentions-Self.rs b/tests/ui/dyn-compatibility/mentions-Self.rs
index ce210f4776f..8b0d5ec6604 100644
--- a/tests/ui/dyn-compatibility/mentions-Self.rs
+++ b/tests/ui/dyn-compatibility/mentions-Self.rs
@@ -18,13 +18,11 @@ trait Quux {
 fn make_bar<T:Bar>(t: &T) -> &dyn Bar {
     //~^ ERROR E0038
     t
-    //~^ ERROR E0038
 }
 
 fn make_baz<T:Baz>(t: &T) -> &dyn Baz {
     //~^ ERROR E0038
     t
-    //~^ ERROR E0038
 }
 
 fn make_quux<T:Quux>(t: &T) -> &dyn Quux {
diff --git a/tests/ui/dyn-compatibility/mentions-Self.stderr b/tests/ui/dyn-compatibility/mentions-Self.stderr
index 6d1ae90152e..9d41e1d92dd 100644
--- a/tests/ui/dyn-compatibility/mentions-Self.stderr
+++ b/tests/ui/dyn-compatibility/mentions-Self.stderr
@@ -15,7 +15,7 @@ LL |     fn bar(&self, x: &Self);
    = help: consider moving `bar` to another trait
 
 error[E0038]: the trait `Baz` is not dyn compatible
-  --> $DIR/mentions-Self.rs:24:31
+  --> $DIR/mentions-Self.rs:23:31
    |
 LL | fn make_baz<T:Baz>(t: &T) -> &dyn Baz {
    |                               ^^^^^^^ `Baz` is not dyn compatible
@@ -30,40 +30,6 @@ LL |     fn baz(&self) -> Self;
    |                      ^^^^ ...because method `baz` references the `Self` type in its return type
    = help: consider moving `baz` to another trait
 
-error[E0038]: the trait `Bar` is not dyn compatible
-  --> $DIR/mentions-Self.rs:20:5
-   |
-LL |     t
-   |     ^ `Bar` is not dyn compatible
-   |
-note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
-  --> $DIR/mentions-Self.rs:7:22
-   |
-LL | trait Bar {
-   |       --- this trait is not dyn compatible...
-LL |     fn bar(&self, x: &Self);
-   |                      ^^^^^ ...because method `bar` references the `Self` type in this parameter
-   = help: consider moving `bar` to another trait
-   = note: required for the cast from `&T` to `&dyn Bar`
-
-error[E0038]: the trait `Baz` is not dyn compatible
-  --> $DIR/mentions-Self.rs:26:5
-   |
-LL |     t
-   |     ^ `Baz` is not dyn compatible
-   |
-note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
-  --> $DIR/mentions-Self.rs:11:22
-   |
-LL | trait Baz {
-   |       --- this trait is not dyn compatible...
-LL |     fn baz(&self) -> Self;
-   |                      ^^^^ ...because method `baz` references the `Self` type in its return type
-   = help: consider moving `baz` to another trait
-   = note: required for the cast from `&T` to `&dyn Baz`
-
-error: aborting due to 4 previous errors
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0038`.
diff --git a/tests/ui/dyn-compatibility/no-static.rs b/tests/ui/dyn-compatibility/no-static.rs
index 9bd87161972..2d5954afffd 100644
--- a/tests/ui/dyn-compatibility/no-static.rs
+++ b/tests/ui/dyn-compatibility/no-static.rs
@@ -17,5 +17,4 @@ impl Foo for Bar {}
 fn main() {
     let b: Box<dyn Foo> = Box::new(Bar);
     //~^ ERROR E0038
-    //~| ERROR E0038
 }
diff --git a/tests/ui/dyn-compatibility/no-static.stderr b/tests/ui/dyn-compatibility/no-static.stderr
index 814ab0d53c3..c1d5dd6f562 100644
--- a/tests/ui/dyn-compatibility/no-static.stderr
+++ b/tests/ui/dyn-compatibility/no-static.stderr
@@ -23,10 +23,10 @@ LL |     fn foo() where Self: Sized {}
    |              +++++++++++++++++
 
 error[E0038]: the trait `Foo` is not dyn compatible
-  --> $DIR/no-static.rs:18:12
+  --> $DIR/no-static.rs:18:20
    |
 LL |     let b: Box<dyn Foo> = Box::new(Bar);
-   |            ^^^^^^^^^^^^ `Foo` is not dyn compatible
+   |                    ^^^ `Foo` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
       for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
@@ -46,31 +46,6 @@ help: alternatively, consider constraining `foo` so it does not apply to trait o
 LL |     fn foo() where Self: Sized {}
    |              +++++++++++++++++
 
-error[E0038]: the trait `Foo` is not dyn compatible
-  --> $DIR/no-static.rs:18:27
-   |
-LL |     let b: Box<dyn Foo> = Box::new(Bar);
-   |                           ^^^^^^^^^^^^^ `Foo` is not dyn compatible
-   |
-note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
-  --> $DIR/no-static.rs:5:8
-   |
-LL | trait Foo {
-   |       --- this trait is not dyn compatible...
-LL |     fn foo() {}
-   |        ^^^ ...because associated function `foo` has no `self` parameter
-   = help: only type `Bar` implements `Foo`; consider using it directly instead.
-   = note: required for the cast from `Box<Bar>` to `Box<dyn Foo>`
-help: consider turning `foo` into a method by giving it a `&self` argument
-   |
-LL |     fn foo(&self) {}
-   |            +++++
-help: alternatively, consider constraining `foo` so it does not apply to trait objects
-   |
-LL |     fn foo() where Self: Sized {}
-   |              +++++++++++++++++
-
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0038`.
diff --git a/tests/ui/dyn-compatibility/sized-2.rs b/tests/ui/dyn-compatibility/sized-2.rs
index f61d49ee8df..c99dcce46b2 100644
--- a/tests/ui/dyn-compatibility/sized-2.rs
+++ b/tests/ui/dyn-compatibility/sized-2.rs
@@ -10,7 +10,6 @@ trait Bar
 fn make_bar<T:Bar>(t: &T) -> &dyn Bar {
     //~^ ERROR E0038
     t
-    //~^ ERROR E0038
 }
 
 fn main() {
diff --git a/tests/ui/dyn-compatibility/sized-2.stderr b/tests/ui/dyn-compatibility/sized-2.stderr
index 1834d906bb8..70bd5f6dd36 100644
--- a/tests/ui/dyn-compatibility/sized-2.stderr
+++ b/tests/ui/dyn-compatibility/sized-2.stderr
@@ -13,22 +13,6 @@ LL | trait Bar
 LL |     where Self : Sized
    |                  ^^^^^ ...because it requires `Self: Sized`
 
-error[E0038]: the trait `Bar` is not dyn compatible
-  --> $DIR/sized-2.rs:12:5
-   |
-LL |     t
-   |     ^ `Bar` is not dyn compatible
-   |
-note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
-  --> $DIR/sized-2.rs:5:18
-   |
-LL | trait Bar
-   |       --- this trait is not dyn compatible...
-LL |     where Self : Sized
-   |                  ^^^^^ ...because it requires `Self: Sized`
-   = note: required for the cast from `&T` to `&dyn Bar`
-
-error: aborting due to 2 previous errors
+error: aborting due to 1 previous error
 
 For more information about this error, try `rustc --explain E0038`.
diff --git a/tests/ui/dyn-compatibility/sized.rs b/tests/ui/dyn-compatibility/sized.rs
index eb5279c17e6..b5a8a4be766 100644
--- a/tests/ui/dyn-compatibility/sized.rs
+++ b/tests/ui/dyn-compatibility/sized.rs
@@ -8,7 +8,6 @@ trait Bar: Sized {
 fn make_bar<T: Bar>(t: &T) -> &dyn Bar {
     //~^ ERROR E0038
     t
-    //~^ ERROR E0038
 }
 
 fn main() {}
diff --git a/tests/ui/dyn-compatibility/sized.stderr b/tests/ui/dyn-compatibility/sized.stderr
index c66e299cf6f..0cc41179d9a 100644
--- a/tests/ui/dyn-compatibility/sized.stderr
+++ b/tests/ui/dyn-compatibility/sized.stderr
@@ -13,22 +13,6 @@ LL | trait Bar: Sized {
    |       |
    |       this trait is not dyn compatible...
 
-error[E0038]: the trait `Bar` is not dyn compatible
-  --> $DIR/sized.rs:10:5
-   |
-LL |     t
-   |     ^ `Bar` is not dyn compatible
-   |
-note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
-  --> $DIR/sized.rs:4:12
-   |
-LL | trait Bar: Sized {
-   |       ---  ^^^^^ ...because it requires `Self: Sized`
-   |       |
-   |       this trait is not dyn compatible...
-   = note: required for the cast from `&T` to `&dyn Bar`
-
-error: aborting due to 2 previous errors
+error: aborting due to 1 previous error
 
 For more information about this error, try `rustc --explain E0038`.
diff --git a/tests/ui/dyn-compatibility/taint-const-eval.rs b/tests/ui/dyn-compatibility/taint-const-eval.rs
index 64c4df611e6..a5c01e1791e 100644
--- a/tests/ui/dyn-compatibility/taint-const-eval.rs
+++ b/tests/ui/dyn-compatibility/taint-const-eval.rs
@@ -7,6 +7,5 @@ trait Qux {
 static FOO: &(dyn Qux + Sync) = "desc";
 //~^ ERROR the trait `Qux` is not dyn compatible
 //~| ERROR the trait `Qux` is not dyn compatible
-//~| ERROR the trait `Qux` is not dyn compatible
 
 fn main() {}
diff --git a/tests/ui/dyn-compatibility/taint-const-eval.stderr b/tests/ui/dyn-compatibility/taint-const-eval.stderr
index 942c20db6ce..585c1f012c7 100644
--- a/tests/ui/dyn-compatibility/taint-const-eval.stderr
+++ b/tests/ui/dyn-compatibility/taint-const-eval.stderr
@@ -22,30 +22,6 @@ LL |     fn bar() where Self: Sized;
    |              +++++++++++++++++
 
 error[E0038]: the trait `Qux` is not dyn compatible
-  --> $DIR/taint-const-eval.rs:7:33
-   |
-LL | static FOO: &(dyn Qux + Sync) = "desc";
-   |                                 ^^^^^^ `Qux` is not dyn compatible
-   |
-note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
-  --> $DIR/taint-const-eval.rs:4:8
-   |
-LL | trait Qux {
-   |       --- this trait is not dyn compatible...
-LL |     fn bar();
-   |        ^^^ ...because associated function `bar` has no `self` parameter
-   = note: required for the cast from `&'static str` to `&'static (dyn Qux + Sync + 'static)`
-help: consider turning `bar` into a method by giving it a `&self` argument
-   |
-LL |     fn bar(&self);
-   |            +++++
-help: alternatively, consider constraining `bar` so it does not apply to trait objects
-   |
-LL |     fn bar() where Self: Sized;
-   |              +++++++++++++++++
-
-error[E0038]: the trait `Qux` is not dyn compatible
   --> $DIR/taint-const-eval.rs:7:15
    |
 LL | static FOO: &(dyn Qux + Sync) = "desc";
@@ -69,6 +45,6 @@ help: alternatively, consider constraining `bar` so it does not apply to trait o
 LL |     fn bar() where Self: Sized;
    |              +++++++++++++++++
 
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0038`.
diff --git a/tests/ui/dyn-drop/dyn-drop.rs b/tests/ui/dyn-drop/dyn-drop.rs
index e1668a3f188..f336949d2cb 100644
--- a/tests/ui/dyn-drop/dyn-drop.rs
+++ b/tests/ui/dyn-drop/dyn-drop.rs
@@ -1,8 +1,7 @@
 #![deny(dyn_drop)]
-#![allow(bare_trait_objects)]
 fn foo(_: Box<dyn Drop>) {} //~ ERROR
 fn bar(_: &dyn Drop) {} //~ERROR
-fn baz(_: *mut Drop) {} //~ ERROR
+fn baz(_: *mut dyn Drop) {} //~ ERROR
 struct Foo {
   _x: Box<dyn Drop> //~ ERROR
 }
diff --git a/tests/ui/dyn-drop/dyn-drop.stderr b/tests/ui/dyn-drop/dyn-drop.stderr
index 1b1dbc4d12d..8210d8a4c48 100644
--- a/tests/ui/dyn-drop/dyn-drop.stderr
+++ b/tests/ui/dyn-drop/dyn-drop.stderr
@@ -1,5 +1,5 @@
 error: types that do not implement `Drop` can still have drop glue, consider instead using `std::mem::needs_drop` to detect whether a type is trivially dropped
-  --> $DIR/dyn-drop.rs:3:19
+  --> $DIR/dyn-drop.rs:2:19
    |
 LL | fn foo(_: Box<dyn Drop>) {}
    |                   ^^^^
@@ -11,25 +11,25 @@ LL | #![deny(dyn_drop)]
    |         ^^^^^^^^
 
 error: types that do not implement `Drop` can still have drop glue, consider instead using `std::mem::needs_drop` to detect whether a type is trivially dropped
-  --> $DIR/dyn-drop.rs:4:16
+  --> $DIR/dyn-drop.rs:3:16
    |
 LL | fn bar(_: &dyn Drop) {}
    |                ^^^^
 
 error: types that do not implement `Drop` can still have drop glue, consider instead using `std::mem::needs_drop` to detect whether a type is trivially dropped
-  --> $DIR/dyn-drop.rs:5:16
+  --> $DIR/dyn-drop.rs:4:20
    |
-LL | fn baz(_: *mut Drop) {}
-   |                ^^^^
+LL | fn baz(_: *mut dyn Drop) {}
+   |                    ^^^^
 
 error: types that do not implement `Drop` can still have drop glue, consider instead using `std::mem::needs_drop` to detect whether a type is trivially dropped
-  --> $DIR/dyn-drop.rs:7:15
+  --> $DIR/dyn-drop.rs:6:15
    |
 LL |   _x: Box<dyn Drop>
    |               ^^^^
 
 error: types that do not implement `Drop` can still have drop glue, consider instead using `std::mem::needs_drop` to detect whether a type is trivially dropped
-  --> $DIR/dyn-drop.rs:14:16
+  --> $DIR/dyn-drop.rs:13:16
    |
 LL |   type T = dyn Drop;
    |                ^^^^
diff --git a/tests/ui/editions/async-block-2015.rs b/tests/ui/editions/async-block-2015.rs
index a079b4aad91..21549f059de 100644
--- a/tests/ui/editions/async-block-2015.rs
+++ b/tests/ui/editions/async-block-2015.rs
@@ -1,3 +1,4 @@
+//@ edition:2015
 async fn foo() {
 //~^ ERROR `async fn` is not permitted in Rust 2015
 //~| NOTE to use `async fn`, switch to Rust 2018 or later
diff --git a/tests/ui/editions/async-block-2015.stderr b/tests/ui/editions/async-block-2015.stderr
index 574bcacc1cf..139df1758cc 100644
--- a/tests/ui/editions/async-block-2015.stderr
+++ b/tests/ui/editions/async-block-2015.stderr
@@ -1,5 +1,5 @@
 error[E0670]: `async fn` is not permitted in Rust 2015
-  --> $DIR/async-block-2015.rs:1:1
+  --> $DIR/async-block-2015.rs:2:1
    |
 LL | async fn foo() {
    | ^^^^^ to use `async fn`, switch to Rust 2018 or later
@@ -8,7 +8,7 @@ LL | async fn foo() {
    = note: for more on editions, read https://doc.rust-lang.org/edition-guide
 
 error: expected identifier, found keyword `let`
-  --> $DIR/async-block-2015.rs:11:9
+  --> $DIR/async-block-2015.rs:12:9
    |
 LL |     let y = async {
    |             ----- `async` blocks are only allowed in Rust 2018 or later
@@ -19,7 +19,7 @@ LL |         let x = 42;
    = note: for more on editions, read https://doc.rust-lang.org/edition-guide
 
 error: expected identifier, found `42`
-  --> $DIR/async-block-2015.rs:19:9
+  --> $DIR/async-block-2015.rs:20:9
    |
 LL |     let z = async {
    |             ----- `async` blocks are only allowed in Rust 2018 or later
@@ -30,7 +30,7 @@ LL |         42
    = note: for more on editions, read https://doc.rust-lang.org/edition-guide
 
 error[E0422]: cannot find struct, variant or union type `async` in this scope
-  --> $DIR/async-block-2015.rs:7:13
+  --> $DIR/async-block-2015.rs:8:13
    |
 LL |     let x = async {};
    |             ^^^^^ `async` blocks are only allowed in Rust 2018 or later
diff --git a/tests/ui/editions/edition-extern-crate-allowed.stderr b/tests/ui/editions/edition-extern-crate-allowed.stderr
index dde774c520d..4444ab79b38 100644
--- a/tests/ui/editions/edition-extern-crate-allowed.stderr
+++ b/tests/ui/editions/edition-extern-crate-allowed.stderr
@@ -2,7 +2,7 @@ warning: unused extern crate
   --> $DIR/edition-extern-crate-allowed.rs:7:1
    |
 LL | extern crate edition_extern_crate_allowed;
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove it
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unused
    |
 note: the lint level is defined here
   --> $DIR/edition-extern-crate-allowed.rs:5:9
@@ -10,6 +10,10 @@ note: the lint level is defined here
 LL | #![warn(rust_2018_idioms)]
    |         ^^^^^^^^^^^^^^^^
    = note: `#[warn(unused_extern_crates)]` implied by `#[warn(rust_2018_idioms)]`
+help: remove the unused `extern crate`
+   |
+LL - extern crate edition_extern_crate_allowed;
+   |
 
 warning: 1 warning emitted
 
diff --git a/tests/ui/enum-discriminant/discriminant_size.rs b/tests/ui/enum-discriminant/discriminant_size.rs
index a3ec1b28e5c..b1feff3c59e 100644
--- a/tests/ui/enum-discriminant/discriminant_size.rs
+++ b/tests/ui/enum-discriminant/discriminant_size.rs
@@ -1,6 +1,5 @@
 //@ run-pass
-#![feature(core_intrinsics, repr128)]
-//~^ WARN the feature `repr128` is incomplete
+#![feature(core_intrinsics)]
 
 use std::intrinsics::discriminant_value;
 
diff --git a/tests/ui/enum-discriminant/discriminant_size.stderr b/tests/ui/enum-discriminant/discriminant_size.stderr
deleted file mode 100644
index 9b1505b5c46..00000000000
--- a/tests/ui/enum-discriminant/discriminant_size.stderr
+++ /dev/null
@@ -1,11 +0,0 @@
-warning: the feature `repr128` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/discriminant_size.rs:2:29
-   |
-LL | #![feature(core_intrinsics, repr128)]
-   |                             ^^^^^^^
-   |
-   = note: see issue #56071 <https://github.com/rust-lang/rust/issues/56071> for more information
-   = note: `#[warn(incomplete_features)]` on by default
-
-warning: 1 warning emitted
-
diff --git a/tests/ui/enum-discriminant/issue-43398.stderr b/tests/ui/enum-discriminant/issue-43398.stderr
deleted file mode 100644
index fc7bbd06284..00000000000
--- a/tests/ui/enum-discriminant/issue-43398.stderr
+++ /dev/null
@@ -1,11 +0,0 @@
-warning: the feature `repr128` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/issue-43398.rs:4:12
-   |
-LL | #![feature(repr128)]
-   |            ^^^^^^^
-   |
-   = note: see issue #56071 <https://github.com/rust-lang/rust/issues/56071> for more information
-   = note: `#[warn(incomplete_features)]` on by default
-
-warning: 1 warning emitted
-
diff --git a/tests/ui/enum-discriminant/issue-70509-partial_eq.rs b/tests/ui/enum-discriminant/issue-70509-partial_eq.rs
index e98532c1207..5e71972c280 100644
--- a/tests/ui/enum-discriminant/issue-70509-partial_eq.rs
+++ b/tests/ui/enum-discriminant/issue-70509-partial_eq.rs
@@ -1,6 +1,4 @@
 //@ run-pass
-#![feature(repr128)]
-//~^ WARN the feature `repr128` is incomplete
 
 #[derive(PartialEq, Debug)]
 #[repr(i128)]
diff --git a/tests/ui/enum-discriminant/issue-70509-partial_eq.stderr b/tests/ui/enum-discriminant/issue-70509-partial_eq.stderr
deleted file mode 100644
index 2eef930c394..00000000000
--- a/tests/ui/enum-discriminant/issue-70509-partial_eq.stderr
+++ /dev/null
@@ -1,11 +0,0 @@
-warning: the feature `repr128` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/issue-70509-partial_eq.rs:2:12
-   |
-LL | #![feature(repr128)]
-   |            ^^^^^^^
-   |
-   = note: see issue #56071 <https://github.com/rust-lang/rust/issues/56071> for more information
-   = note: `#[warn(incomplete_features)]` on by default
-
-warning: 1 warning emitted
-
diff --git a/tests/ui/enum-discriminant/issue-43398.rs b/tests/ui/enum-discriminant/repr128-get-discriminant-issue-43398.rs
index 574a4b3ad5a..2bb9725fb77 100644
--- a/tests/ui/enum-discriminant/issue-43398.rs
+++ b/tests/ui/enum-discriminant/repr128-get-discriminant-issue-43398.rs
@@ -1,8 +1,6 @@
 //@ run-pass
 
 #![feature(core_intrinsics)]
-#![feature(repr128)]
-//~^ WARN the feature `repr128` is incomplete
 
 #[repr(i128)]
 enum Big { A, B }
diff --git a/tests/ui/enum-discriminant/repr128.rs b/tests/ui/enum-discriminant/repr128.rs
index 075ff7a7676..d59a5b3e256 100644
--- a/tests/ui/enum-discriminant/repr128.rs
+++ b/tests/ui/enum-discriminant/repr128.rs
@@ -1,6 +1,5 @@
 //@ run-pass
-#![feature(repr128, core_intrinsics, discriminant_kind)]
-//~^ WARN the feature `repr128` is incomplete
+#![feature(core_intrinsics, discriminant_kind)]
 
 use std::intrinsics::discriminant_value;
 use std::marker::DiscriminantKind;
diff --git a/tests/ui/enum-discriminant/repr128.stderr b/tests/ui/enum-discriminant/repr128.stderr
deleted file mode 100644
index da8d75c11af..00000000000
--- a/tests/ui/enum-discriminant/repr128.stderr
+++ /dev/null
@@ -1,11 +0,0 @@
-warning: the feature `repr128` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/repr128.rs:2:12
-   |
-LL | #![feature(repr128, core_intrinsics, discriminant_kind)]
-   |            ^^^^^^^
-   |
-   = note: see issue #56071 <https://github.com/rust-lang/rust/issues/56071> for more information
-   = note: `#[warn(incomplete_features)]` on by default
-
-warning: 1 warning emitted
-
diff --git a/tests/ui/ergonomic-clones/async/edition-2015.rs b/tests/ui/ergonomic-clones/async/edition-2015.rs
index d3b2071b9f9..78831249429 100644
--- a/tests/ui/ergonomic-clones/async/edition-2015.rs
+++ b/tests/ui/ergonomic-clones/async/edition-2015.rs
@@ -1,3 +1,4 @@
+//@ edition:2015
 #![feature(ergonomic_clones)]
 #![allow(incomplete_features)]
 
diff --git a/tests/ui/ergonomic-clones/async/edition-2015.stderr b/tests/ui/ergonomic-clones/async/edition-2015.stderr
index b218e6b242e..8de90f4bfd3 100644
--- a/tests/ui/ergonomic-clones/async/edition-2015.stderr
+++ b/tests/ui/ergonomic-clones/async/edition-2015.stderr
@@ -1,5 +1,5 @@
 error: `async use` blocks are only allowed in Rust 2018 or later
-  --> $DIR/edition-2015.rs:5:5
+  --> $DIR/edition-2015.rs:6:5
    |
 LL |     async use {};
    |     ^^^^^^^^^
diff --git a/tests/ui/error-codes/E0657.rs b/tests/ui/error-codes/E0657.rs
index 212c1d9e581..f046788153d 100644
--- a/tests/ui/error-codes/E0657.rs
+++ b/tests/ui/error-codes/E0657.rs
@@ -7,7 +7,7 @@ impl<'a> Lt<'a> for () {}
 impl<T> Id<T> for T {}
 
 fn free_fn_capture_hrtb_in_impl_trait()
-    -> Box<for<'a> Id<impl Lt<'a>>>
+    -> Box<dyn for<'a> Id<impl Lt<'a>>>
         //~^ ERROR `impl Trait` cannot capture higher-ranked lifetime from `dyn` type
 {
     Box::new(())
@@ -16,7 +16,7 @@ fn free_fn_capture_hrtb_in_impl_trait()
 struct Foo;
 impl Foo {
     fn impl_fn_capture_hrtb_in_impl_trait()
-        -> Box<for<'a> Id<impl Lt<'a>>>
+        -> Box<dyn for<'a> Id<impl Lt<'a>>>
             //~^ ERROR `impl Trait` cannot capture higher-ranked lifetime from `dyn` type
     {
         Box::new(())
diff --git a/tests/ui/error-codes/E0657.stderr b/tests/ui/error-codes/E0657.stderr
index c539007cdcf..c9dfc9eb906 100644
--- a/tests/ui/error-codes/E0657.stderr
+++ b/tests/ui/error-codes/E0657.stderr
@@ -1,26 +1,26 @@
 error[E0657]: `impl Trait` cannot capture higher-ranked lifetime from `dyn` type
-  --> $DIR/E0657.rs:10:31
+  --> $DIR/E0657.rs:10:35
    |
-LL |     -> Box<for<'a> Id<impl Lt<'a>>>
-   |                               ^^
+LL |     -> Box<dyn for<'a> Id<impl Lt<'a>>>
+   |                                   ^^
    |
 note: lifetime declared here
-  --> $DIR/E0657.rs:10:16
+  --> $DIR/E0657.rs:10:20
    |
-LL |     -> Box<for<'a> Id<impl Lt<'a>>>
-   |                ^^
+LL |     -> Box<dyn for<'a> Id<impl Lt<'a>>>
+   |                    ^^
 
 error[E0657]: `impl Trait` cannot capture higher-ranked lifetime from `dyn` type
-  --> $DIR/E0657.rs:19:35
+  --> $DIR/E0657.rs:19:39
    |
-LL |         -> Box<for<'a> Id<impl Lt<'a>>>
-   |                                   ^^
+LL |         -> Box<dyn for<'a> Id<impl Lt<'a>>>
+   |                                       ^^
    |
 note: lifetime declared here
-  --> $DIR/E0657.rs:19:20
+  --> $DIR/E0657.rs:19:24
    |
-LL |         -> Box<for<'a> Id<impl Lt<'a>>>
-   |                    ^^
+LL |         -> Box<dyn for<'a> Id<impl Lt<'a>>>
+   |                        ^^
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/error-codes/E0658.rs b/tests/ui/error-codes/E0658.rs
index 9c9b95d70a7..e51674cdf92 100644
--- a/tests/ui/error-codes/E0658.rs
+++ b/tests/ui/error-codes/E0658.rs
@@ -1,6 +1,3 @@
-#[repr(u128)]
-enum Foo { //~ ERROR E0658
-    Bar(u64),
-}
+use std::intrinsics; //~ ERROR E0658
 
 fn main() {}
diff --git a/tests/ui/error-codes/E0658.stderr b/tests/ui/error-codes/E0658.stderr
index e1e812940ec..ae7ecbbc5cb 100644
--- a/tests/ui/error-codes/E0658.stderr
+++ b/tests/ui/error-codes/E0658.stderr
@@ -1,11 +1,10 @@
-error[E0658]: repr with 128-bit type is unstable
-  --> $DIR/E0658.rs:2:1
+error[E0658]: use of unstable library feature `core_intrinsics`: intrinsics are unlikely to ever be stabilized, instead they should be used through stabilized interfaces in the rest of the standard library
+  --> $DIR/E0658.rs:1:5
    |
-LL | enum Foo {
-   | ^^^^^^^^
+LL | use std::intrinsics;
+   |     ^^^^^^^^^^^^^^^
    |
-   = note: see issue #56071 <https://github.com/rust-lang/rust/issues/56071> for more information
-   = help: add `#![feature(repr128)]` to the crate attributes to enable
+   = help: add `#![feature(core_intrinsics)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
 error: aborting due to 1 previous error
diff --git a/tests/ui/errors/dynless-turbofish-e0191-issue-91997.rs b/tests/ui/errors/dynless-turbofish-e0191-issue-91997.rs
index 69a4c13530b..d6bb6466227 100644
--- a/tests/ui/errors/dynless-turbofish-e0191-issue-91997.rs
+++ b/tests/ui/errors/dynless-turbofish-e0191-issue-91997.rs
@@ -1,3 +1,4 @@
+//@ edition:2015
 trait MyIterator : Iterator {}
 
 fn main() {
diff --git a/tests/ui/errors/dynless-turbofish-e0191-issue-91997.stderr b/tests/ui/errors/dynless-turbofish-e0191-issue-91997.stderr
index 24f00cfa6be..7f3022c2923 100644
--- a/tests/ui/errors/dynless-turbofish-e0191-issue-91997.stderr
+++ b/tests/ui/errors/dynless-turbofish-e0191-issue-91997.stderr
@@ -1,5 +1,5 @@
 warning: trait objects without an explicit `dyn` are deprecated
-  --> $DIR/dynless-turbofish-e0191-issue-91997.rs:4:13
+  --> $DIR/dynless-turbofish-e0191-issue-91997.rs:5:13
    |
 LL |     let _ = MyIterator::next;
    |             ^^^^^^^^^^
@@ -13,7 +13,7 @@ LL |     let _ = <dyn MyIterator>::next;
    |             ++++           +
 
 error[E0191]: the value of the associated type `Item` in `Iterator` must be specified
-  --> $DIR/dynless-turbofish-e0191-issue-91997.rs:4:13
+  --> $DIR/dynless-turbofish-e0191-issue-91997.rs:5:13
    |
 LL |     let _ = MyIterator::next;
    |             ^^^^^^^^^^ help: specify the associated type: `MyIterator::<Item = Type>`
diff --git a/tests/ui/expr/scope.rs b/tests/ui/expr/scope.rs
index 3a1c8b87da8..b059e43de9e 100644
--- a/tests/ui/expr/scope.rs
+++ b/tests/ui/expr/scope.rs
@@ -1,3 +1,4 @@
+//@ edition:2015
 //@ run-pass
 // Regression test for issue #762
 
diff --git a/tests/ui/feature-gates/feature-gate-asm_cfg.rs b/tests/ui/feature-gates/feature-gate-asm_cfg.rs
new file mode 100644
index 00000000000..ef8bf75b692
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-asm_cfg.rs
@@ -0,0 +1,48 @@
+//@ only-x86_64
+#![crate_type = "lib"]
+
+use std::arch::{asm, global_asm, naked_asm};
+
+global_asm!(
+    "nop",
+    #[cfg(false)]
+    //~^ ERROR the `#[cfg(/* ... */)]` and `#[cfg_attr(/* ... */)]` attributes on assembly are unstable
+    "nop"
+);
+
+#[unsafe(naked)]
+#[no_mangle]
+extern "C" fn naked() {
+    naked_asm!(
+        "mov rax, 5",
+        #[cfg(false)]
+        //~^ ERROR the `#[cfg(/* ... */)]` and `#[cfg_attr(/* ... */)]` attributes on assembly are unstable
+        "mov rax, {a}",
+        "ret",
+        #[cfg(false)]
+        //~^ ERROR the `#[cfg(/* ... */)]` and `#[cfg_attr(/* ... */)]` attributes on assembly are unstable
+        a = const 10,
+    )
+}
+
+fn asm() {
+    unsafe {
+        asm!(
+            "nop",
+            #[cfg(false)]
+            //~^ ERROR the `#[cfg(/* ... */)]` and `#[cfg_attr(/* ... */)]` attributes on assembly are unstable
+            clobber_abi("C"),
+            clobber_abi("C"), //~ ERROR `C` ABI specified multiple times
+        );
+    }
+}
+
+fn bad_attribute() {
+    unsafe {
+        asm!(
+            #[inline]
+            //~^ ERROR this attribute is not supported on assembly
+            "nop"
+        )
+    };
+}
diff --git a/tests/ui/feature-gates/feature-gate-asm_cfg.stderr b/tests/ui/feature-gates/feature-gate-asm_cfg.stderr
new file mode 100644
index 00000000000..e92d1e8c487
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-asm_cfg.stderr
@@ -0,0 +1,57 @@
+error[E0658]: the `#[cfg(/* ... */)]` and `#[cfg_attr(/* ... */)]` attributes on assembly are unstable
+  --> $DIR/feature-gate-asm_cfg.rs:8:5
+   |
+LL |     #[cfg(false)]
+   |     ^^^^^^^^^^^^^
+   |
+   = note: see issue #140364 <https://github.com/rust-lang/rust/issues/140364> for more information
+   = help: add `#![feature(asm_cfg)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: the `#[cfg(/* ... */)]` and `#[cfg_attr(/* ... */)]` attributes on assembly are unstable
+  --> $DIR/feature-gate-asm_cfg.rs:18:9
+   |
+LL |         #[cfg(false)]
+   |         ^^^^^^^^^^^^^
+   |
+   = note: see issue #140364 <https://github.com/rust-lang/rust/issues/140364> for more information
+   = help: add `#![feature(asm_cfg)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: the `#[cfg(/* ... */)]` and `#[cfg_attr(/* ... */)]` attributes on assembly are unstable
+  --> $DIR/feature-gate-asm_cfg.rs:22:9
+   |
+LL |         #[cfg(false)]
+   |         ^^^^^^^^^^^^^
+   |
+   = note: see issue #140364 <https://github.com/rust-lang/rust/issues/140364> for more information
+   = help: add `#![feature(asm_cfg)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: the `#[cfg(/* ... */)]` and `#[cfg_attr(/* ... */)]` attributes on assembly are unstable
+  --> $DIR/feature-gate-asm_cfg.rs:32:13
+   |
+LL |             #[cfg(false)]
+   |             ^^^^^^^^^^^^^
+   |
+   = note: see issue #140364 <https://github.com/rust-lang/rust/issues/140364> for more information
+   = help: add `#![feature(asm_cfg)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error: this attribute is not supported on assembly
+  --> $DIR/feature-gate-asm_cfg.rs:43:13
+   |
+LL |             #[inline]
+   |             ^^^^^^^^^
+
+error: `C` ABI specified multiple times
+  --> $DIR/feature-gate-asm_cfg.rs:35:13
+   |
+LL |             clobber_abi("C"),
+   |             ---------------- previously specified here
+LL |             clobber_abi("C"),
+   |             ^^^^^^^^^^^^^^^^
+
+error: aborting due to 6 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/feature-gates/feature-gate-autodiff-use.has_support.stderr b/tests/ui/feature-gates/feature-gate-autodiff-use.has_support.stderr
index 15ef257fbd8..e5edd8e45e6 100644
--- a/tests/ui/feature-gates/feature-gate-autodiff-use.has_support.stderr
+++ b/tests/ui/feature-gates/feature-gate-autodiff-use.has_support.stderr
@@ -1,8 +1,8 @@
 error[E0658]: use of unstable library feature `autodiff`
   --> $DIR/feature-gate-autodiff-use.rs:13:3
    |
-LL | #[autodiff(dfoo, Reverse)]
-   |   ^^^^^^^^
+LL | #[autodiff_reverse(dfoo)]
+   |   ^^^^^^^^^^^^^^^^
    |
    = note: see issue #124509 <https://github.com/rust-lang/rust/issues/124509> for more information
    = help: add `#![feature(autodiff)]` to the crate attributes to enable
@@ -11,8 +11,8 @@ LL | #[autodiff(dfoo, Reverse)]
 error[E0658]: use of unstable library feature `autodiff`
   --> $DIR/feature-gate-autodiff-use.rs:9:5
    |
-LL | use std::autodiff::autodiff;
-   |     ^^^^^^^^^^^^^^^^^^^^^^^
+LL | use std::autodiff::autodiff_reverse;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: see issue #124509 <https://github.com/rust-lang/rust/issues/124509> for more information
    = help: add `#![feature(autodiff)]` to the crate attributes to enable
diff --git a/tests/ui/feature-gates/feature-gate-autodiff-use.no_support.stderr b/tests/ui/feature-gates/feature-gate-autodiff-use.no_support.stderr
index f59e4955452..65ba033b358 100644
--- a/tests/ui/feature-gates/feature-gate-autodiff-use.no_support.stderr
+++ b/tests/ui/feature-gates/feature-gate-autodiff-use.no_support.stderr
@@ -1,8 +1,8 @@
 error[E0658]: use of unstable library feature `autodiff`
   --> $DIR/feature-gate-autodiff-use.rs:13:3
    |
-LL | #[autodiff(dfoo, Reverse)]
-   |   ^^^^^^^^
+LL | #[autodiff_reverse(dfoo)]
+   |   ^^^^^^^^^^^^^^^^
    |
    = note: see issue #124509 <https://github.com/rust-lang/rust/issues/124509> for more information
    = help: add `#![feature(autodiff)]` to the crate attributes to enable
@@ -11,14 +11,14 @@ LL | #[autodiff(dfoo, Reverse)]
 error: this rustc version does not support autodiff
   --> $DIR/feature-gate-autodiff-use.rs:13:1
    |
-LL | #[autodiff(dfoo, Reverse)]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #[autodiff_reverse(dfoo)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0658]: use of unstable library feature `autodiff`
   --> $DIR/feature-gate-autodiff-use.rs:9:5
    |
-LL | use std::autodiff::autodiff;
-   |     ^^^^^^^^^^^^^^^^^^^^^^^
+LL | use std::autodiff::autodiff_reverse;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: see issue #124509 <https://github.com/rust-lang/rust/issues/124509> for more information
    = help: add `#![feature(autodiff)]` to the crate attributes to enable
diff --git a/tests/ui/feature-gates/feature-gate-autodiff-use.rs b/tests/ui/feature-gates/feature-gate-autodiff-use.rs
index 602e830b0b2..2864b786c12 100644
--- a/tests/ui/feature-gates/feature-gate-autodiff-use.rs
+++ b/tests/ui/feature-gates/feature-gate-autodiff-use.rs
@@ -6,11 +6,11 @@
 
 #![crate_type = "lib"]
 
-use std::autodiff::autodiff;
+use std::autodiff::autodiff_reverse;
 //[has_support]~^ ERROR use of unstable library feature `autodiff`
 //[no_support]~^^ ERROR use of unstable library feature `autodiff`
 
-#[autodiff(dfoo, Reverse)]
+#[autodiff_reverse(dfoo)]
 //[has_support]~^ ERROR use of unstable library feature `autodiff` [E0658]
 //[no_support]~^^ ERROR use of unstable library feature `autodiff` [E0658]
 //[no_support]~| ERROR this rustc version does not support autodiff
diff --git a/tests/ui/feature-gates/feature-gate-autodiff.has_support.stderr b/tests/ui/feature-gates/feature-gate-autodiff.has_support.stderr
index c25cf7d3373..dcbaba71645 100644
--- a/tests/ui/feature-gates/feature-gate-autodiff.has_support.stderr
+++ b/tests/ui/feature-gates/feature-gate-autodiff.has_support.stderr
@@ -1,12 +1,12 @@
-error: cannot find attribute `autodiff` in this scope
+error: cannot find attribute `autodiff_reverse` in this scope
   --> $DIR/feature-gate-autodiff.rs:9:3
    |
-LL | #[autodiff(dfoo, Reverse)]
-   |   ^^^^^^^^
+LL | #[autodiff_reverse(dfoo)]
+   |   ^^^^^^^^^^^^^^^^
    |
 help: consider importing this attribute macro
    |
-LL + use std::autodiff::autodiff;
+LL + use std::autodiff::autodiff_reverse;
    |
 
 error: aborting due to 1 previous error
diff --git a/tests/ui/feature-gates/feature-gate-autodiff.no_support.stderr b/tests/ui/feature-gates/feature-gate-autodiff.no_support.stderr
index c25cf7d3373..dcbaba71645 100644
--- a/tests/ui/feature-gates/feature-gate-autodiff.no_support.stderr
+++ b/tests/ui/feature-gates/feature-gate-autodiff.no_support.stderr
@@ -1,12 +1,12 @@
-error: cannot find attribute `autodiff` in this scope
+error: cannot find attribute `autodiff_reverse` in this scope
   --> $DIR/feature-gate-autodiff.rs:9:3
    |
-LL | #[autodiff(dfoo, Reverse)]
-   |   ^^^^^^^^
+LL | #[autodiff_reverse(dfoo)]
+   |   ^^^^^^^^^^^^^^^^
    |
 help: consider importing this attribute macro
    |
-LL + use std::autodiff::autodiff;
+LL + use std::autodiff::autodiff_reverse;
    |
 
 error: aborting due to 1 previous error
diff --git a/tests/ui/feature-gates/feature-gate-autodiff.rs b/tests/ui/feature-gates/feature-gate-autodiff.rs
index 4249b229a69..adb35cb8e33 100644
--- a/tests/ui/feature-gates/feature-gate-autodiff.rs
+++ b/tests/ui/feature-gates/feature-gate-autodiff.rs
@@ -6,7 +6,7 @@
 
 // This checks that without the autodiff feature enabled, we can't use it.
 
-#[autodiff(dfoo, Reverse)]
-//[has_support]~^ ERROR cannot find attribute `autodiff` in this scope
-//[no_support]~^^ ERROR cannot find attribute `autodiff` in this scope
+#[autodiff_reverse(dfoo)]
+//[has_support]~^ ERROR cannot find attribute `autodiff_reverse` in this scope
+//[no_support]~^^ ERROR cannot find attribute `autodiff_reverse` in this scope
 fn foo() {}
diff --git a/tests/ui/feature-gates/feature-gate-cfg-version.rs b/tests/ui/feature-gates/feature-gate-cfg-version.rs
index e35784a68d1..ec2446cc146 100644
--- a/tests/ui/feature-gates/feature-gate-cfg-version.rs
+++ b/tests/ui/feature-gates/feature-gate-cfg-version.rs
@@ -1,49 +1,12 @@
-#[cfg(version(42))] //~ ERROR: expected a version literal
-//~^ ERROR `cfg(version)` is experimental and subject to change
-fn foo() {}
-#[cfg(version(1.20))] //~ ERROR: expected a version literal
-//~^ ERROR `cfg(version)` is experimental and subject to change
-fn foo() -> bool { true }
-#[cfg(version("1.44"))]
-//~^ ERROR `cfg(version)` is experimental and subject to change
-fn foo() -> bool { true }
-#[cfg(not(version("1.44")))]
-//~^ ERROR `cfg(version)` is experimental and subject to change
-fn foo() -> bool { false }
+//! Feature gate test for `cfg_version`.
+//!
+//! Tracking issue: #64796.
 
-#[cfg(version("1.43", "1.44", "1.45"))] //~ ERROR: expected single version literal
-//~^ ERROR `cfg(version)` is experimental and subject to change
-fn bar() -> bool  { false }
-#[cfg(version(false))] //~ ERROR: expected a version literal
-//~^ ERROR `cfg(version)` is experimental and subject to change
-fn bar() -> bool  { false }
-#[cfg(version("foo"))] //~ WARNING: unknown version literal format
-//~^ ERROR `cfg(version)` is experimental and subject to change
-fn bar() -> bool  { false }
-#[cfg(version("999"))] //~ WARNING: unknown version literal format
-//~^ ERROR `cfg(version)` is experimental and subject to change
-fn bar() -> bool  { false }
-#[cfg(version("-1"))] //~ WARNING: unknown version literal format
-//~^ ERROR `cfg(version)` is experimental and subject to change
-fn bar() -> bool  { false }
-#[cfg(version("65536"))] //~ WARNING: unknown version literal format
-//~^ ERROR `cfg(version)` is experimental and subject to change
-fn bar() -> bool  { false }
-#[cfg(version("0"))] //~ WARNING: unknown version literal format
-//~^ ERROR `cfg(version)` is experimental and subject to change
-fn bar() -> bool { true }
-#[cfg(version("1.0"))]
-//~^ ERROR `cfg(version)` is experimental and subject to change
-fn bar() -> bool { true }
-#[cfg(version("1.65536.2"))] //~ WARNING: unknown version literal format
-//~^ ERROR `cfg(version)` is experimental and subject to change
-fn bar() -> bool  { false }
-#[cfg(version("1.20.0-stable"))] //~ WARNING: unknown version literal format
+#[cfg(version("1.42"))]
 //~^ ERROR `cfg(version)` is experimental and subject to change
 fn bar() {}
 
 fn main() {
-    assert!(foo());
-    assert!(bar());
-    assert!(cfg!(version("1.42"))); //~ ERROR `cfg(version)` is experimental and subject to change
+    assert!(cfg!(version("1.42")));
+    //~^ ERROR `cfg(version)` is experimental and subject to change
 }
diff --git a/tests/ui/feature-gates/feature-gate-cfg-version.stderr b/tests/ui/feature-gates/feature-gate-cfg-version.stderr
index c1c3e8e5897..7cb2f1e07af 100644
--- a/tests/ui/feature-gates/feature-gate-cfg-version.stderr
+++ b/tests/ui/feature-gates/feature-gate-cfg-version.stderr
@@ -1,39 +1,7 @@
 error[E0658]: `cfg(version)` is experimental and subject to change
-  --> $DIR/feature-gate-cfg-version.rs:1:7
+  --> $DIR/feature-gate-cfg-version.rs:5:7
    |
-LL | #[cfg(version(42))]
-   |       ^^^^^^^^^^^
-   |
-   = note: see issue #64796 <https://github.com/rust-lang/rust/issues/64796> for more information
-   = help: add `#![feature(cfg_version)]` to the crate attributes to enable
-   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
-
-error: expected a version literal
-  --> $DIR/feature-gate-cfg-version.rs:1:15
-   |
-LL | #[cfg(version(42))]
-   |               ^^
-
-error[E0658]: `cfg(version)` is experimental and subject to change
-  --> $DIR/feature-gate-cfg-version.rs:4:7
-   |
-LL | #[cfg(version(1.20))]
-   |       ^^^^^^^^^^^^^
-   |
-   = note: see issue #64796 <https://github.com/rust-lang/rust/issues/64796> for more information
-   = help: add `#![feature(cfg_version)]` to the crate attributes to enable
-   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
-
-error: expected a version literal
-  --> $DIR/feature-gate-cfg-version.rs:4:15
-   |
-LL | #[cfg(version(1.20))]
-   |               ^^^^
-
-error[E0658]: `cfg(version)` is experimental and subject to change
-  --> $DIR/feature-gate-cfg-version.rs:7:7
-   |
-LL | #[cfg(version("1.44"))]
+LL | #[cfg(version("1.42"))]
    |       ^^^^^^^^^^^^^^^
    |
    = note: see issue #64796 <https://github.com/rust-lang/rust/issues/64796> for more information
@@ -41,171 +9,7 @@ LL | #[cfg(version("1.44"))]
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
 error[E0658]: `cfg(version)` is experimental and subject to change
-  --> $DIR/feature-gate-cfg-version.rs:10:11
-   |
-LL | #[cfg(not(version("1.44")))]
-   |           ^^^^^^^^^^^^^^^
-   |
-   = note: see issue #64796 <https://github.com/rust-lang/rust/issues/64796> for more information
-   = help: add `#![feature(cfg_version)]` to the crate attributes to enable
-   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
-
-error[E0658]: `cfg(version)` is experimental and subject to change
-  --> $DIR/feature-gate-cfg-version.rs:14:7
-   |
-LL | #[cfg(version("1.43", "1.44", "1.45"))]
-   |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #64796 <https://github.com/rust-lang/rust/issues/64796> for more information
-   = help: add `#![feature(cfg_version)]` to the crate attributes to enable
-   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
-
-error: expected single version literal
-  --> $DIR/feature-gate-cfg-version.rs:14:7
-   |
-LL | #[cfg(version("1.43", "1.44", "1.45"))]
-   |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error[E0658]: `cfg(version)` is experimental and subject to change
-  --> $DIR/feature-gate-cfg-version.rs:17:7
-   |
-LL | #[cfg(version(false))]
-   |       ^^^^^^^^^^^^^^
-   |
-   = note: see issue #64796 <https://github.com/rust-lang/rust/issues/64796> for more information
-   = help: add `#![feature(cfg_version)]` to the crate attributes to enable
-   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
-
-error: expected a version literal
-  --> $DIR/feature-gate-cfg-version.rs:17:15
-   |
-LL | #[cfg(version(false))]
-   |               ^^^^^
-
-error[E0658]: `cfg(version)` is experimental and subject to change
-  --> $DIR/feature-gate-cfg-version.rs:20:7
-   |
-LL | #[cfg(version("foo"))]
-   |       ^^^^^^^^^^^^^^
-   |
-   = note: see issue #64796 <https://github.com/rust-lang/rust/issues/64796> for more information
-   = help: add `#![feature(cfg_version)]` to the crate attributes to enable
-   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
-
-warning: unknown version literal format, assuming it refers to a future version
-  --> $DIR/feature-gate-cfg-version.rs:20:15
-   |
-LL | #[cfg(version("foo"))]
-   |               ^^^^^
-
-error[E0658]: `cfg(version)` is experimental and subject to change
-  --> $DIR/feature-gate-cfg-version.rs:23:7
-   |
-LL | #[cfg(version("999"))]
-   |       ^^^^^^^^^^^^^^
-   |
-   = note: see issue #64796 <https://github.com/rust-lang/rust/issues/64796> for more information
-   = help: add `#![feature(cfg_version)]` to the crate attributes to enable
-   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
-
-warning: unknown version literal format, assuming it refers to a future version
-  --> $DIR/feature-gate-cfg-version.rs:23:15
-   |
-LL | #[cfg(version("999"))]
-   |               ^^^^^
-
-error[E0658]: `cfg(version)` is experimental and subject to change
-  --> $DIR/feature-gate-cfg-version.rs:26:7
-   |
-LL | #[cfg(version("-1"))]
-   |       ^^^^^^^^^^^^^
-   |
-   = note: see issue #64796 <https://github.com/rust-lang/rust/issues/64796> for more information
-   = help: add `#![feature(cfg_version)]` to the crate attributes to enable
-   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
-
-warning: unknown version literal format, assuming it refers to a future version
-  --> $DIR/feature-gate-cfg-version.rs:26:15
-   |
-LL | #[cfg(version("-1"))]
-   |               ^^^^
-
-error[E0658]: `cfg(version)` is experimental and subject to change
-  --> $DIR/feature-gate-cfg-version.rs:29:7
-   |
-LL | #[cfg(version("65536"))]
-   |       ^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #64796 <https://github.com/rust-lang/rust/issues/64796> for more information
-   = help: add `#![feature(cfg_version)]` to the crate attributes to enable
-   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
-
-warning: unknown version literal format, assuming it refers to a future version
-  --> $DIR/feature-gate-cfg-version.rs:29:15
-   |
-LL | #[cfg(version("65536"))]
-   |               ^^^^^^^
-
-error[E0658]: `cfg(version)` is experimental and subject to change
-  --> $DIR/feature-gate-cfg-version.rs:32:7
-   |
-LL | #[cfg(version("0"))]
-   |       ^^^^^^^^^^^^
-   |
-   = note: see issue #64796 <https://github.com/rust-lang/rust/issues/64796> for more information
-   = help: add `#![feature(cfg_version)]` to the crate attributes to enable
-   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
-
-warning: unknown version literal format, assuming it refers to a future version
-  --> $DIR/feature-gate-cfg-version.rs:32:15
-   |
-LL | #[cfg(version("0"))]
-   |               ^^^
-
-error[E0658]: `cfg(version)` is experimental and subject to change
-  --> $DIR/feature-gate-cfg-version.rs:35:7
-   |
-LL | #[cfg(version("1.0"))]
-   |       ^^^^^^^^^^^^^^
-   |
-   = note: see issue #64796 <https://github.com/rust-lang/rust/issues/64796> for more information
-   = help: add `#![feature(cfg_version)]` to the crate attributes to enable
-   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
-
-error[E0658]: `cfg(version)` is experimental and subject to change
-  --> $DIR/feature-gate-cfg-version.rs:38:7
-   |
-LL | #[cfg(version("1.65536.2"))]
-   |       ^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #64796 <https://github.com/rust-lang/rust/issues/64796> for more information
-   = help: add `#![feature(cfg_version)]` to the crate attributes to enable
-   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
-
-warning: unknown version literal format, assuming it refers to a future version
-  --> $DIR/feature-gate-cfg-version.rs:38:15
-   |
-LL | #[cfg(version("1.65536.2"))]
-   |               ^^^^^^^^^^^
-
-error[E0658]: `cfg(version)` is experimental and subject to change
-  --> $DIR/feature-gate-cfg-version.rs:41:7
-   |
-LL | #[cfg(version("1.20.0-stable"))]
-   |       ^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #64796 <https://github.com/rust-lang/rust/issues/64796> for more information
-   = help: add `#![feature(cfg_version)]` to the crate attributes to enable
-   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
-
-warning: unknown version literal format, assuming it refers to a future version
-  --> $DIR/feature-gate-cfg-version.rs:41:15
-   |
-LL | #[cfg(version("1.20.0-stable"))]
-   |               ^^^^^^^^^^^^^^^
-
-error[E0658]: `cfg(version)` is experimental and subject to change
-  --> $DIR/feature-gate-cfg-version.rs:48:18
+  --> $DIR/feature-gate-cfg-version.rs:10:18
    |
 LL |     assert!(cfg!(version("1.42")));
    |                  ^^^^^^^^^^^^^^^
@@ -214,6 +18,6 @@ LL |     assert!(cfg!(version("1.42")));
    = help: add `#![feature(cfg_version)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error: aborting due to 19 previous errors; 7 warnings emitted
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/feature-gates/feature-gate-coroutines.e2024.stderr b/tests/ui/feature-gates/feature-gate-coroutines.e2024.stderr
index 381e7a210be..c29c328ac14 100644
--- a/tests/ui/feature-gates/feature-gate-coroutines.e2024.stderr
+++ b/tests/ui/feature-gates/feature-gate-coroutines.e2024.stderr
@@ -5,7 +5,7 @@ LL |     yield true;
    |     ^^^^^^^^^^
    |
    = note: see issue #43122 <https://github.com/rust-lang/rust/issues/43122> for more information
-   = help: add `#![feature(coroutines)]` to the crate attributes to enable
+   = help: add `#![feature(yield_expr)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
 error[E0658]: yield syntax is experimental
@@ -15,7 +15,7 @@ LL |     let _ = || yield true;
    |                ^^^^^^^^^^
    |
    = note: see issue #43122 <https://github.com/rust-lang/rust/issues/43122> for more information
-   = help: add `#![feature(coroutines)]` to the crate attributes to enable
+   = help: add `#![feature(yield_expr)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
 error[E0658]: yield syntax is experimental
@@ -25,7 +25,7 @@ LL |     yield;
    |     ^^^^^
    |
    = note: see issue #43122 <https://github.com/rust-lang/rust/issues/43122> for more information
-   = help: add `#![feature(coroutines)]` to the crate attributes to enable
+   = help: add `#![feature(yield_expr)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
 error[E0658]: yield syntax is experimental
@@ -35,7 +35,7 @@ LL |     yield 0;
    |     ^^^^^^^
    |
    = note: see issue #43122 <https://github.com/rust-lang/rust/issues/43122> for more information
-   = help: add `#![feature(coroutines)]` to the crate attributes to enable
+   = help: add `#![feature(yield_expr)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
 error[E0658]: yield syntax is experimental
diff --git a/tests/ui/feature-gates/feature-gate-coroutines.none.stderr b/tests/ui/feature-gates/feature-gate-coroutines.none.stderr
index 381e7a210be..c29c328ac14 100644
--- a/tests/ui/feature-gates/feature-gate-coroutines.none.stderr
+++ b/tests/ui/feature-gates/feature-gate-coroutines.none.stderr
@@ -5,7 +5,7 @@ LL |     yield true;
    |     ^^^^^^^^^^
    |
    = note: see issue #43122 <https://github.com/rust-lang/rust/issues/43122> for more information
-   = help: add `#![feature(coroutines)]` to the crate attributes to enable
+   = help: add `#![feature(yield_expr)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
 error[E0658]: yield syntax is experimental
@@ -15,7 +15,7 @@ LL |     let _ = || yield true;
    |                ^^^^^^^^^^
    |
    = note: see issue #43122 <https://github.com/rust-lang/rust/issues/43122> for more information
-   = help: add `#![feature(coroutines)]` to the crate attributes to enable
+   = help: add `#![feature(yield_expr)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
 error[E0658]: yield syntax is experimental
@@ -25,7 +25,7 @@ LL |     yield;
    |     ^^^^^
    |
    = note: see issue #43122 <https://github.com/rust-lang/rust/issues/43122> for more information
-   = help: add `#![feature(coroutines)]` to the crate attributes to enable
+   = help: add `#![feature(yield_expr)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
 error[E0658]: yield syntax is experimental
@@ -35,7 +35,7 @@ LL |     yield 0;
    |     ^^^^^^^
    |
    = note: see issue #43122 <https://github.com/rust-lang/rust/issues/43122> for more information
-   = help: add `#![feature(coroutines)]` to the crate attributes to enable
+   = help: add `#![feature(yield_expr)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
 error[E0658]: yield syntax is experimental
diff --git a/tests/ui/feature-gates/feature-gate-dispatch-from-dyn-missing-impl.rs b/tests/ui/feature-gates/feature-gate-dispatch-from-dyn-missing-impl.rs
index 37eabbf1602..8d7ccea9e64 100644
--- a/tests/ui/feature-gates/feature-gate-dispatch-from-dyn-missing-impl.rs
+++ b/tests/ui/feature-gates/feature-gate-dispatch-from-dyn-missing-impl.rs
@@ -31,5 +31,4 @@ impl Trait for i32 {
 fn main() {
     Ptr(Box::new(4)) as Ptr<dyn Trait>;
     //~^ ERROR the trait `Trait` is not dyn compatible
-    //~^^ ERROR the trait `Trait` is not dyn compatible
 }
diff --git a/tests/ui/feature-gates/feature-gate-dispatch-from-dyn-missing-impl.stderr b/tests/ui/feature-gates/feature-gate-dispatch-from-dyn-missing-impl.stderr
index 6634ce12118..c70ab65aa90 100644
--- a/tests/ui/feature-gates/feature-gate-dispatch-from-dyn-missing-impl.stderr
+++ b/tests/ui/feature-gates/feature-gate-dispatch-from-dyn-missing-impl.stderr
@@ -1,11 +1,11 @@
 error[E0038]: the trait `Trait` is not dyn compatible
-  --> $DIR/feature-gate-dispatch-from-dyn-missing-impl.rs:32:25
+  --> $DIR/feature-gate-dispatch-from-dyn-missing-impl.rs:32:33
    |
 LL |     fn ptr(self: Ptr<Self>);
    |                  --------- help: consider changing method `ptr`'s `self` parameter to be `&self`: `&Self`
 ...
 LL |     Ptr(Box::new(4)) as Ptr<dyn Trait>;
-   |                         ^^^^^^^^^^^^^^ `Trait` is not dyn compatible
+   |                                 ^^^^^ `Trait` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
       for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
@@ -17,26 +17,6 @@ LL |     fn ptr(self: Ptr<Self>);
    |                  ^^^^^^^^^ ...because method `ptr`'s `self` parameter cannot be dispatched on
    = help: only type `i32` implements `Trait`; consider using it directly instead.
 
-error[E0038]: the trait `Trait` is not dyn compatible
-  --> $DIR/feature-gate-dispatch-from-dyn-missing-impl.rs:32:5
-   |
-LL |     fn ptr(self: Ptr<Self>);
-   |                  --------- help: consider changing method `ptr`'s `self` parameter to be `&self`: `&Self`
-...
-LL |     Ptr(Box::new(4)) as Ptr<dyn Trait>;
-   |     ^^^^^^^^^^^^^^^^ `Trait` is not dyn compatible
-   |
-note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
-  --> $DIR/feature-gate-dispatch-from-dyn-missing-impl.rs:25:18
-   |
-LL | trait Trait {
-   |       ----- this trait is not dyn compatible...
-LL |     fn ptr(self: Ptr<Self>);
-   |                  ^^^^^^^^^ ...because method `ptr`'s `self` parameter cannot be dispatched on
-   = help: only type `i32` implements `Trait`; consider using it directly instead.
-   = note: required for the cast from `Ptr<{integer}>` to `Ptr<dyn Trait>`
-
-error: aborting due to 2 previous errors
+error: aborting due to 1 previous error
 
 For more information about this error, try `rustc --explain E0038`.
diff --git a/tests/ui/feature-gates/feature-gate-repr128.rs b/tests/ui/feature-gates/feature-gate-repr128.rs
deleted file mode 100644
index 0290874dd27..00000000000
--- a/tests/ui/feature-gates/feature-gate-repr128.rs
+++ /dev/null
@@ -1,6 +0,0 @@
-#[repr(u128)]
-enum A { //~ ERROR repr with 128-bit type is unstable
-    A(u64)
-}
-
-fn main() {}
diff --git a/tests/ui/feature-gates/feature-gate-repr128.stderr b/tests/ui/feature-gates/feature-gate-repr128.stderr
deleted file mode 100644
index 2607032447b..00000000000
--- a/tests/ui/feature-gates/feature-gate-repr128.stderr
+++ /dev/null
@@ -1,13 +0,0 @@
-error[E0658]: repr with 128-bit type is unstable
-  --> $DIR/feature-gate-repr128.rs:2:1
-   |
-LL | enum A {
-   | ^^^^^^
-   |
-   = note: see issue #56071 <https://github.com/rust-lang/rust/issues/56071> for more information
-   = help: add `#![feature(repr128)]` to the crate attributes to enable
-   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
-
-error: aborting due to 1 previous error
-
-For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/feature-gates/feature-gate-yield-expr.stderr b/tests/ui/feature-gates/feature-gate-yield-expr.stderr
index ad8a15a0f36..bfac9e49803 100644
--- a/tests/ui/feature-gates/feature-gate-yield-expr.stderr
+++ b/tests/ui/feature-gates/feature-gate-yield-expr.stderr
@@ -5,7 +5,7 @@ LL |     yield ();
    |     ^^^^^^^^
    |
    = note: see issue #43122 <https://github.com/rust-lang/rust/issues/43122> for more information
-   = help: add `#![feature(coroutines)]` to the crate attributes to enable
+   = help: add `#![feature(yield_expr)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
 error[E0658]: yield syntax is experimental
diff --git a/tests/ui/feature-gates/version_check.rs b/tests/ui/feature-gates/version_check.rs
deleted file mode 100644
index e212dc74fd1..00000000000
--- a/tests/ui/feature-gates/version_check.rs
+++ /dev/null
@@ -1,17 +0,0 @@
-//@ run-pass
-//@ only-linux
-//@ only-x86
-// FIXME: this should be more like //@ needs-subprocesses
-use std::process::Command;
-
-fn main() {
-    let signalled_version = "Ceci n'est pas une rustc";
-    let version = Command::new(std::env::var_os("RUSTC").unwrap())
-        .env("RUSTC_OVERRIDE_VERSION_STRING", signalled_version)
-        .arg("--version")
-        .output()
-        .unwrap()
-        .stdout;
-    let version = std::str::from_utf8(&version).unwrap().strip_prefix("rustc ").unwrap().trim_end();
-    assert_eq!(version, signalled_version);
-}
diff --git a/tests/ui/bare-fn-implements-fn-mut.rs b/tests/ui/functions-closures/bare-fn-implements-fn-mut.rs
index 49b31f28f8a..52d5ad3d0f7 100644
--- a/tests/ui/bare-fn-implements-fn-mut.rs
+++ b/tests/ui/functions-closures/bare-fn-implements-fn-mut.rs
@@ -1,3 +1,7 @@
+//! Tests that bare functions implement the `FnMut` trait.
+//!
+//! See <https://github.com/rust-lang/rust/issues/15448>.
+
 //@ run-pass
 
 fn call_f<F:FnMut()>(mut f: F) {
diff --git a/tests/ui/generic-associated-types/gat-in-trait-path.rs b/tests/ui/generic-associated-types/gat-in-trait-path.rs
index 7523803eacf..774e16d84c5 100644
--- a/tests/ui/generic-associated-types/gat-in-trait-path.rs
+++ b/tests/ui/generic-associated-types/gat-in-trait-path.rs
@@ -26,5 +26,4 @@ fn main() {
   let foo = Fooer(5);
   f(Box::new(foo));
   //~^ ERROR the trait `Foo` is not dyn compatible
-  //~| ERROR the trait `Foo` is not dyn compatible
 }
diff --git a/tests/ui/generic-associated-types/gat-in-trait-path.stderr b/tests/ui/generic-associated-types/gat-in-trait-path.stderr
index e57f6b48401..d4ccd80f146 100644
--- a/tests/ui/generic-associated-types/gat-in-trait-path.stderr
+++ b/tests/ui/generic-associated-types/gat-in-trait-path.stderr
@@ -30,23 +30,6 @@ LL |     type A<'a> where Self: 'a;
    |          ^ ...because it contains the generic associated type `A`
    = help: consider moving `A` to another trait
 
-error[E0038]: the trait `Foo` is not dyn compatible
-  --> $DIR/gat-in-trait-path.rs:27:5
-   |
-LL |   f(Box::new(foo));
-   |     ^^^^^^^^^^^^^ `Foo` is not dyn compatible
-   |
-note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
-  --> $DIR/gat-in-trait-path.rs:6:10
-   |
-LL | trait Foo {
-   |       --- this trait is not dyn compatible...
-LL |     type A<'a> where Self: 'a;
-   |          ^ ...because it contains the generic associated type `A`
-   = help: consider moving `A` to another trait
-   = note: required for the cast from `Box<Fooer<{integer}>>` to `Box<(dyn Foo<A<'a> = &'a ()> + 'static)>`
-
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0038`.
diff --git a/tests/ui/generic-associated-types/issue-71176.rs b/tests/ui/generic-associated-types/issue-71176.rs
index d3a0caffec1..8ecfa93750d 100644
--- a/tests/ui/generic-associated-types/issue-71176.rs
+++ b/tests/ui/generic-associated-types/issue-71176.rs
@@ -18,6 +18,5 @@ fn main() {
     Holder {
         inner: Box::new(()),
         //~^ ERROR: the trait `Provider` is not dyn compatible
-        //~| ERROR: the trait `Provider` is not dyn compatible
     };
 }
diff --git a/tests/ui/generic-associated-types/issue-71176.stderr b/tests/ui/generic-associated-types/issue-71176.stderr
index 56439f6dfea..f231056a2ee 100644
--- a/tests/ui/generic-associated-types/issue-71176.stderr
+++ b/tests/ui/generic-associated-types/issue-71176.stderr
@@ -82,25 +82,7 @@ LL |     type A<'a>;
    = help: consider moving `A` to another trait
    = help: only type `()` implements `Provider`; consider using it directly instead.
 
-error[E0038]: the trait `Provider` is not dyn compatible
-  --> $DIR/issue-71176.rs:19:16
-   |
-LL |         inner: Box::new(()),
-   |                ^^^^^^^^^^^^ `Provider` is not dyn compatible
-   |
-note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
-  --> $DIR/issue-71176.rs:2:10
-   |
-LL | trait Provider {
-   |       -------- this trait is not dyn compatible...
-LL |     type A<'a>;
-   |          ^ ...because it contains the generic associated type `A`
-   = help: consider moving `A` to another trait
-   = help: only type `()` implements `Provider`; consider using it directly instead.
-   = note: required for the cast from `Box<()>` to `Box<(dyn Provider<A<'_> = _> + 'static), {type error}>`
-
-error: aborting due to 6 previous errors
+error: aborting due to 5 previous errors
 
 Some errors have detailed explanations: E0038, E0107.
 For more information about an error, try `rustc --explain E0038`.
diff --git a/tests/ui/generic-associated-types/issue-76535.rs b/tests/ui/generic-associated-types/issue-76535.rs
index 9e18c82c7f1..dc697401a58 100644
--- a/tests/ui/generic-associated-types/issue-76535.rs
+++ b/tests/ui/generic-associated-types/issue-76535.rs
@@ -33,6 +33,5 @@ impl SuperTrait for SuperStruct {
 fn main() {
     let sub: Box<dyn SuperTrait<SubType = SubStruct>> = Box::new(SuperStruct::new(0));
       //~^ ERROR missing generics for associated type
-      //~^^ ERROR the trait
       //~| ERROR the trait
 }
diff --git a/tests/ui/generic-associated-types/issue-76535.stderr b/tests/ui/generic-associated-types/issue-76535.stderr
index b828234afa1..2daf9d817bb 100644
--- a/tests/ui/generic-associated-types/issue-76535.stderr
+++ b/tests/ui/generic-associated-types/issue-76535.stderr
@@ -15,10 +15,10 @@ LL |     let sub: Box<dyn SuperTrait<SubType<'a> = SubStruct>> = Box::new(SuperS
    |                                        ++++
 
 error[E0038]: the trait `SuperTrait` is not dyn compatible
-  --> $DIR/issue-76535.rs:34:14
+  --> $DIR/issue-76535.rs:34:22
    |
 LL |     let sub: Box<dyn SuperTrait<SubType = SubStruct>> = Box::new(SuperStruct::new(0));
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `SuperTrait` is not dyn compatible
+   |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `SuperTrait` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
       for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
@@ -32,26 +32,7 @@ LL |     type SubType<'a>: SubTrait where Self: 'a;
    = help: only type `SuperStruct` implements `SuperTrait` within this crate; consider using it directly instead.
    = note: `SuperTrait` may be implemented in other crates; if you want to support your users passing their own types here, you can't refer to a specific type
 
-error[E0038]: the trait `SuperTrait` is not dyn compatible
-  --> $DIR/issue-76535.rs:34:57
-   |
-LL |     let sub: Box<dyn SuperTrait<SubType = SubStruct>> = Box::new(SuperStruct::new(0));
-   |                                                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `SuperTrait` is not dyn compatible
-   |
-note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
-  --> $DIR/issue-76535.rs:4:10
-   |
-LL | pub trait SuperTrait {
-   |           ---------- this trait is not dyn compatible...
-LL |     type SubType<'a>: SubTrait where Self: 'a;
-   |          ^^^^^^^ ...because it contains the generic associated type `SubType`
-   = help: consider moving `SubType` to another trait
-   = help: only type `SuperStruct` implements `SuperTrait` within this crate; consider using it directly instead.
-   = note: `SuperTrait` may be implemented in other crates; if you want to support your users passing their own types here, you can't refer to a specific type
-   = note: required for the cast from `Box<SuperStruct>` to `Box<dyn SuperTrait<SubType<'_> = SubStruct<'_>>>`
-
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
 
 Some errors have detailed explanations: E0038, E0107.
 For more information about an error, try `rustc --explain E0038`.
diff --git a/tests/ui/generic-associated-types/issue-78671.stderr b/tests/ui/generic-associated-types/issue-78671.stderr
index c6da137672d..fff061a8ada 100644
--- a/tests/ui/generic-associated-types/issue-78671.stderr
+++ b/tests/ui/generic-associated-types/issue-78671.stderr
@@ -15,10 +15,10 @@ LL |     Box::new(Family) as &dyn CollectionFamily<Member<T>=usize>
    |                                                     +++
 
 error[E0038]: the trait `CollectionFamily` is not dyn compatible
-  --> $DIR/issue-78671.rs:5:25
+  --> $DIR/issue-78671.rs:5:30
    |
 LL |     Box::new(Family) as &dyn CollectionFamily<Member=usize>
-   |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `CollectionFamily` is not dyn compatible
+   |                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `CollectionFamily` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
       for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
diff --git a/tests/ui/generic-associated-types/issue-79422.rs b/tests/ui/generic-associated-types/issue-79422.rs
index fba7a86990e..462614b3612 100644
--- a/tests/ui/generic-associated-types/issue-79422.rs
+++ b/tests/ui/generic-associated-types/issue-79422.rs
@@ -15,12 +15,17 @@ impl<'a, T> RefCont<'a, T> for Box<T> {
 }
 
 trait MapLike<K, V> {
-    type VRefCont<'a>: RefCont<'a, V> where Self: 'a;
+    type VRefCont<'a>: RefCont<'a, V>
+    where
+        Self: 'a;
     fn get<'a>(&'a self, key: &K) -> Option<Self::VRefCont<'a>>;
 }
 
 impl<K: Ord, V: 'static> MapLike<K, V> for std::collections::BTreeMap<K, V> {
-    type VRefCont<'a> = &'a V where Self: 'a;
+    type VRefCont<'a>
+        = &'a V
+    where
+        Self: 'a;
     fn get<'a>(&'a self, key: &K) -> Option<&'a V> {
         std::collections::BTreeMap::get(self, key)
     }
@@ -37,8 +42,7 @@ impl<K, V: Default> MapLike<K, V> for Source {
 
 fn main() {
     let m = Box::new(std::collections::BTreeMap::<u8, u8>::new())
-    //~^ ERROR the trait
         as Box<dyn MapLike<u8, u8, VRefCont = dyn RefCont<'_, u8>>>;
-      //~^ ERROR missing generics for associated type
-      //~| ERROR the trait
+    //~^ ERROR the trait
+    //~| ERROR missing generics for associated type
 }
diff --git a/tests/ui/generic-associated-types/issue-79422.stderr b/tests/ui/generic-associated-types/issue-79422.stderr
index 6311e4de272..dcf3a9008de 100644
--- a/tests/ui/generic-associated-types/issue-79422.stderr
+++ b/tests/ui/generic-associated-types/issue-79422.stderr
@@ -1,5 +1,5 @@
 error[E0107]: missing generics for associated type `MapLike::VRefCont`
-  --> $DIR/issue-79422.rs:41:36
+  --> $DIR/issue-79422.rs:45:36
    |
 LL |         as Box<dyn MapLike<u8, u8, VRefCont = dyn RefCont<'_, u8>>>;
    |                                    ^^^^^^^^ expected 1 lifetime argument
@@ -7,7 +7,7 @@ LL |         as Box<dyn MapLike<u8, u8, VRefCont = dyn RefCont<'_, u8>>>;
 note: associated type defined here, with 1 lifetime parameter: `'a`
   --> $DIR/issue-79422.rs:18:10
    |
-LL |     type VRefCont<'a>: RefCont<'a, V> where Self: 'a;
+LL |     type VRefCont<'a>: RefCont<'a, V>
    |          ^^^^^^^^ --
 help: add missing lifetime argument
    |
@@ -15,10 +15,10 @@ LL |         as Box<dyn MapLike<u8, u8, VRefCont<'a> = dyn RefCont<'_, u8>>>;
    |                                            ++++
 
 error[E0038]: the trait `MapLike` is not dyn compatible
-  --> $DIR/issue-79422.rs:41:12
+  --> $DIR/issue-79422.rs:45:20
    |
 LL |         as Box<dyn MapLike<u8, u8, VRefCont = dyn RefCont<'_, u8>>>;
-   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `MapLike` is not dyn compatible
+   |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `MapLike` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
       for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
@@ -26,28 +26,11 @@ note: for a trait to be dyn compatible it needs to allow building a vtable
    |
 LL | trait MapLike<K, V> {
    |       ------- this trait is not dyn compatible...
-LL |     type VRefCont<'a>: RefCont<'a, V> where Self: 'a;
+LL |     type VRefCont<'a>: RefCont<'a, V>
    |          ^^^^^^^^ ...because it contains the generic associated type `VRefCont`
    = help: consider moving `VRefCont` to another trait
 
-error[E0038]: the trait `MapLike` is not dyn compatible
-  --> $DIR/issue-79422.rs:39:13
-   |
-LL |     let m = Box::new(std::collections::BTreeMap::<u8, u8>::new())
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `MapLike` is not dyn compatible
-   |
-note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
-  --> $DIR/issue-79422.rs:18:10
-   |
-LL | trait MapLike<K, V> {
-   |       ------- this trait is not dyn compatible...
-LL |     type VRefCont<'a>: RefCont<'a, V> where Self: 'a;
-   |          ^^^^^^^^ ...because it contains the generic associated type `VRefCont`
-   = help: consider moving `VRefCont` to another trait
-   = note: required for the cast from `Box<BTreeMap<u8, u8>>` to `Box<dyn MapLike<u8, u8, VRefCont<'_> = (dyn RefCont<'_, u8> + 'static)>>`
-
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
 
 Some errors have detailed explanations: E0038, E0107.
 For more information about an error, try `rustc --explain E0038`.
diff --git a/tests/ui/generic-const-items/def-site-eval.fail.stderr b/tests/ui/generic-const-items/def-site-eval.fail.stderr
index fa07f385522..4e7d9d8154a 100644
--- a/tests/ui/generic-const-items/def-site-eval.fail.stderr
+++ b/tests/ui/generic-const-items/def-site-eval.fail.stderr
@@ -1,5 +1,5 @@
-error[E0080]: evaluation of `_::<'_>` failed
-  --> $DIR/def-site-eval.rs:14:20
+error[E0080]: evaluation of constant value failed
+  --> $DIR/def-site-eval.rs:13:20
    |
 LL | const _<'_a>: () = panic!();
    |                    ^^^^^^^^ evaluation panicked: explicit panic
diff --git a/tests/ui/generic-const-items/def-site-eval.rs b/tests/ui/generic-const-items/def-site-eval.rs
index 3ed7f96aed0..b95e40c05d4 100644
--- a/tests/ui/generic-const-items/def-site-eval.rs
+++ b/tests/ui/generic-const-items/def-site-eval.rs
@@ -1,16 +1,15 @@
 //! Test that we only evaluate free const items (their def site to be clear)
 //! whose generics don't require monomorphization.
 #![feature(generic_const_items)]
-#![allow(incomplete_features)]
+#![expect(incomplete_features)]
 
 //@ revisions: fail pass
-//@[fail] build-fail (we require monomorphization)
-//@[pass] build-pass (we require monomorphization)
+//@[pass] check-pass
 
 const _<_T>: () = panic!();
 const _<const _N: usize>: () = panic!();
 
 #[cfg(fail)]
-const _<'_a>: () = panic!(); //[fail]~ ERROR evaluation of `_::<'_>` failed
+const _<'_a>: () = panic!(); //[fail]~ ERROR evaluation of constant value failed
 
 fn main() {}
diff --git a/tests/ui/generic-const-items/def-site-predicates-wf.rs b/tests/ui/generic-const-items/def-site-predicates-wf.rs
new file mode 100644
index 00000000000..39cdcc304f3
--- /dev/null
+++ b/tests/ui/generic-const-items/def-site-predicates-wf.rs
@@ -0,0 +1,9 @@
+//! Ensure that we check the predicates for well-formedness at the definition site.
+#![feature(generic_const_items)]
+#![expect(incomplete_features)]
+
+const _: () = ()
+where
+    Vec<str>: Sized; //~ ERROR the size for values of type `str` cannot be known at compilation time
+
+fn main() {}
diff --git a/tests/ui/generic-const-items/def-site-predicates-wf.stderr b/tests/ui/generic-const-items/def-site-predicates-wf.stderr
new file mode 100644
index 00000000000..62db089fd55
--- /dev/null
+++ b/tests/ui/generic-const-items/def-site-predicates-wf.stderr
@@ -0,0 +1,13 @@
+error[E0277]: the size for values of type `str` cannot be known at compilation time
+  --> $DIR/def-site-predicates-wf.rs:7:15
+   |
+LL |     Vec<str>: Sized;
+   |               ^^^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `Sized` is not implemented for `str`
+note: required by an implicit `Sized` bound in `Vec`
+  --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/bounds-lifetime.rs b/tests/ui/higher-ranked/higher-ranked-invalid-bounds.rs
index f26976066ac..be161aeb53d 100644
--- a/tests/ui/bounds-lifetime.rs
+++ b/tests/ui/higher-ranked/higher-ranked-invalid-bounds.rs
@@ -1,3 +1,5 @@
+//! Tests invalid lifetime bounds and generic parameters in higher-ranked types.
+
 type A = for<'b, 'a: 'b> fn(); //~ ERROR bounds cannot be used in this context
 type B = for<'b, 'a: 'b,> fn(); //~ ERROR bounds cannot be used in this context
 type C = for<'b, 'a: 'b +> fn(); //~ ERROR bounds cannot be used in this context
diff --git a/tests/ui/bounds-lifetime.stderr b/tests/ui/higher-ranked/higher-ranked-invalid-bounds.stderr
index 01b314f3d1b..60ee7a7cf76 100644
--- a/tests/ui/bounds-lifetime.stderr
+++ b/tests/ui/higher-ranked/higher-ranked-invalid-bounds.stderr
@@ -1,23 +1,23 @@
 error: bounds cannot be used in this context
-  --> $DIR/bounds-lifetime.rs:1:22
+  --> $DIR/higher-ranked-invalid-bounds.rs:3:22
    |
 LL | type A = for<'b, 'a: 'b> fn();
    |                      ^^
 
 error: bounds cannot be used in this context
-  --> $DIR/bounds-lifetime.rs:2:22
+  --> $DIR/higher-ranked-invalid-bounds.rs:4:22
    |
 LL | type B = for<'b, 'a: 'b,> fn();
    |                      ^^
 
 error: bounds cannot be used in this context
-  --> $DIR/bounds-lifetime.rs:3:22
+  --> $DIR/higher-ranked-invalid-bounds.rs:5:22
    |
 LL | type C = for<'b, 'a: 'b +> fn();
    |                      ^^
 
 error[E0658]: only lifetime parameters can be used in this context
-  --> $DIR/bounds-lifetime.rs:4:18
+  --> $DIR/higher-ranked-invalid-bounds.rs:6:18
    |
 LL | type D = for<'a, T> fn();
    |                  ^
@@ -27,7 +27,7 @@ LL | type D = for<'a, T> fn();
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
 error[E0658]: only lifetime parameters can be used in this context
-  --> $DIR/bounds-lifetime.rs:5:18
+  --> $DIR/higher-ranked-invalid-bounds.rs:7:18
    |
 LL | type E = dyn for<T, U> Fn();
    |                  ^  ^
diff --git a/tests/ui/higher-ranked/trait-bounds/span-bug-issue-121597.rs b/tests/ui/higher-ranked/trait-bounds/span-bug-issue-121597.rs
index 5d039cd5dc6..cc813430468 100644
--- a/tests/ui/higher-ranked/trait-bounds/span-bug-issue-121597.rs
+++ b/tests/ui/higher-ranked/trait-bounds/span-bug-issue-121597.rs
@@ -13,8 +13,6 @@ fn needs_bar(_: *mut Type2) {}
 fn main() {
     let x: &dyn Foo = &();
     //~^ ERROR the trait `Foo` is not dyn compatible
-    //~| ERROR the trait `Foo` is not dyn compatible
 
     needs_bar(x);
-    //~^ ERROR mismatched types
 }
diff --git a/tests/ui/higher-ranked/trait-bounds/span-bug-issue-121597.stderr b/tests/ui/higher-ranked/trait-bounds/span-bug-issue-121597.stderr
index 183ee678d7a..d35394a4f66 100644
--- a/tests/ui/higher-ranked/trait-bounds/span-bug-issue-121597.stderr
+++ b/tests/ui/higher-ranked/trait-bounds/span-bug-issue-121597.stderr
@@ -1,8 +1,8 @@
 error[E0038]: the trait `Foo` is not dyn compatible
-  --> $DIR/span-bug-issue-121597.rs:14:23
+  --> $DIR/span-bug-issue-121597.rs:14:17
    |
 LL |     let x: &dyn Foo = &();
-   |                       ^^^ `Foo` is not dyn compatible
+   |                 ^^^ `Foo` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
       for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
@@ -12,40 +12,7 @@ LL | trait Foo: for<T> Bar<T> {}
    |       ---  ^^^^^^^^^^^^^ ...because where clause cannot reference non-lifetime `for<...>` variables
    |       |
    |       this trait is not dyn compatible...
-   = note: required for the cast from `&()` to `&dyn Foo`
 
-error[E0038]: the trait `Foo` is not dyn compatible
-  --> $DIR/span-bug-issue-121597.rs:14:12
-   |
-LL |     let x: &dyn Foo = &();
-   |            ^^^^^^^^ `Foo` is not dyn compatible
-   |
-note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
-  --> $DIR/span-bug-issue-121597.rs:4:12
-   |
-LL | trait Foo: for<T> Bar<T> {}
-   |       ---  ^^^^^^^^^^^^^ ...because where clause cannot reference non-lifetime `for<...>` variables
-   |       |
-   |       this trait is not dyn compatible...
-
-error[E0308]: mismatched types
-  --> $DIR/span-bug-issue-121597.rs:18:15
-   |
-LL |     needs_bar(x);
-   |     --------- ^ types differ in mutability
-   |     |
-   |     arguments to this function are incorrect
-   |
-   = note: expected raw pointer `*mut Type2`
-                found reference `&dyn Foo`
-note: function defined here
-  --> $DIR/span-bug-issue-121597.rs:11:4
-   |
-LL | fn needs_bar(_: *mut Type2) {}
-   |    ^^^^^^^^^ -------------
-
-error: aborting due to 3 previous errors
+error: aborting due to 1 previous error
 
-Some errors have detailed explanations: E0038, E0308.
-For more information about an error, try `rustc --explain E0038`.
+For more information about this error, try `rustc --explain E0038`.
diff --git a/tests/ui/impl-trait/dyn-incompatible-trait-in-return-position-dyn-trait.rs b/tests/ui/impl-trait/dyn-incompatible-trait-in-return-position-dyn-trait.rs
index 901d4b39cf3..accd173ce23 100644
--- a/tests/ui/impl-trait/dyn-incompatible-trait-in-return-position-dyn-trait.rs
+++ b/tests/ui/impl-trait/dyn-incompatible-trait-in-return-position-dyn-trait.rs
@@ -21,6 +21,8 @@ impl DynIncompatible for B {
 
 fn car() -> dyn DynIncompatible { //~ ERROR the trait `DynIncompatible` is not dyn compatible
 //~^ ERROR return type cannot be a trait object without pointer indirection
+//~| ERROR the trait `DynIncompatible` is not dyn compatible
+//~| ERROR the trait `DynIncompatible` is not dyn compatible
     if true {
         return A;
     }
@@ -29,9 +31,9 @@ fn car() -> dyn DynIncompatible { //~ ERROR the trait `DynIncompatible` is not d
 
 fn cat() -> Box<dyn DynIncompatible> { //~ ERROR the trait `DynIncompatible` is not dyn compatible
     if true {
-        return Box::new(A); //~ ERROR is not dyn compatible
+        return Box::new(A);
     }
-    Box::new(B) //~ ERROR is not dyn compatible
+    Box::new(B)
 }
 
 fn main() {}
diff --git a/tests/ui/impl-trait/dyn-incompatible-trait-in-return-position-dyn-trait.stderr b/tests/ui/impl-trait/dyn-incompatible-trait-in-return-position-dyn-trait.stderr
index 2c314b07bce..a8787a01a6f 100644
--- a/tests/ui/impl-trait/dyn-incompatible-trait-in-return-position-dyn-trait.stderr
+++ b/tests/ui/impl-trait/dyn-incompatible-trait-in-return-position-dyn-trait.stderr
@@ -41,6 +41,7 @@ help: alternatively, box the return type, and wrap all of the returned values in
    |
 LL ~ fn car() -> Box<dyn DynIncompatible> {
 LL |
+...
 LL |     if true {
 LL ~         return Box::new(A);
 LL |     }
@@ -48,7 +49,7 @@ LL ~     Box::new(B)
    |
 
 error[E0038]: the trait `DynIncompatible` is not dyn compatible
-  --> $DIR/dyn-incompatible-trait-in-return-position-dyn-trait.rs:30:17
+  --> $DIR/dyn-incompatible-trait-in-return-position-dyn-trait.rs:32:17
    |
 LL | fn cat() -> Box<dyn DynIncompatible> {
    |                 ^^^^^^^^^^^^^^^^^^^ `DynIncompatible` is not dyn compatible
@@ -76,10 +77,10 @@ LL |     fn foo() -> Self where Self: Sized;
    |                      +++++++++++++++++
 
 error[E0038]: the trait `DynIncompatible` is not dyn compatible
-  --> $DIR/dyn-incompatible-trait-in-return-position-dyn-trait.rs:32:16
+  --> $DIR/dyn-incompatible-trait-in-return-position-dyn-trait.rs:22:17
    |
-LL |         return Box::new(A);
-   |                ^^^^^^^^^^^ `DynIncompatible` is not dyn compatible
+LL | fn car() -> dyn DynIncompatible {
+   |                 ^^^^^^^^^^^^^^^ `DynIncompatible` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
       for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
@@ -94,7 +95,11 @@ LL |     fn foo() -> Self;
              B
            consider defining an enum where each variant holds one of these types,
            implementing `DynIncompatible` for this new enum and using it instead
-   = note: required for the cast from `Box<A>` to `Box<(dyn DynIncompatible + 'static)>`
+help: consider using an opaque type instead
+   |
+LL - fn car() -> dyn DynIncompatible {
+LL + fn car() -> impl DynIncompatible {
+   |
 help: consider turning `foo` into a method by giving it a `&self` argument
    |
 LL |     fn foo(&self) -> Self;
@@ -105,10 +110,10 @@ LL |     fn foo() -> Self where Self: Sized;
    |                      +++++++++++++++++
 
 error[E0038]: the trait `DynIncompatible` is not dyn compatible
-  --> $DIR/dyn-incompatible-trait-in-return-position-dyn-trait.rs:34:5
+  --> $DIR/dyn-incompatible-trait-in-return-position-dyn-trait.rs:22:17
    |
-LL |     Box::new(B)
-   |     ^^^^^^^^^^^ `DynIncompatible` is not dyn compatible
+LL | fn car() -> dyn DynIncompatible {
+   |                 ^^^^^^^^^^^^^^^ `DynIncompatible` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
       for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
@@ -123,7 +128,12 @@ LL |     fn foo() -> Self;
              B
            consider defining an enum where each variant holds one of these types,
            implementing `DynIncompatible` for this new enum and using it instead
-   = note: required for the cast from `Box<B>` to `Box<(dyn DynIncompatible + 'static)>`
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+help: consider using an opaque type instead
+   |
+LL - fn car() -> dyn DynIncompatible {
+LL + fn car() -> impl DynIncompatible {
+   |
 help: consider turning `foo` into a method by giving it a `&self` argument
    |
 LL |     fn foo(&self) -> Self;
diff --git a/tests/ui/impl-trait/in-trait/dyn-compatibility.rs b/tests/ui/impl-trait/in-trait/dyn-compatibility.rs
index 92203c470bb..45b431f6d30 100644
--- a/tests/ui/impl-trait/in-trait/dyn-compatibility.rs
+++ b/tests/ui/impl-trait/in-trait/dyn-compatibility.rs
@@ -13,6 +13,5 @@ impl Foo for u32 {
 fn main() {
     let i = Box::new(42_u32) as Box<dyn Foo>;
     //~^ ERROR the trait `Foo` is not dyn compatible
-    //~| ERROR the trait `Foo` is not dyn compatible
     let s = i.baz();
 }
diff --git a/tests/ui/impl-trait/in-trait/dyn-compatibility.stderr b/tests/ui/impl-trait/in-trait/dyn-compatibility.stderr
index 5c498548aff..8cdb3808533 100644
--- a/tests/ui/impl-trait/in-trait/dyn-compatibility.stderr
+++ b/tests/ui/impl-trait/in-trait/dyn-compatibility.stderr
@@ -1,8 +1,8 @@
 error[E0038]: the trait `Foo` is not dyn compatible
-  --> $DIR/dyn-compatibility.rs:14:33
+  --> $DIR/dyn-compatibility.rs:14:41
    |
 LL |     let i = Box::new(42_u32) as Box<dyn Foo>;
-   |                                 ^^^^^^^^^^^^ `Foo` is not dyn compatible
+   |                                         ^^^ `Foo` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
       for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
@@ -15,24 +15,6 @@ LL |     fn baz(&self) -> impl Debug;
    = help: consider moving `baz` to another trait
    = help: only type `u32` implements `Foo`; consider using it directly instead.
 
-error[E0038]: the trait `Foo` is not dyn compatible
-  --> $DIR/dyn-compatibility.rs:14:13
-   |
-LL |     let i = Box::new(42_u32) as Box<dyn Foo>;
-   |             ^^^^^^^^^^^^^^^^ `Foo` is not dyn compatible
-   |
-note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
-  --> $DIR/dyn-compatibility.rs:4:22
-   |
-LL | trait Foo {
-   |       --- this trait is not dyn compatible...
-LL |     fn baz(&self) -> impl Debug;
-   |                      ^^^^^^^^^^ ...because method `baz` references an `impl Trait` type in its return type
-   = help: consider moving `baz` to another trait
-   = help: only type `u32` implements `Foo`; consider using it directly instead.
-   = note: required for the cast from `Box<u32>` to `Box<dyn Foo>`
-
-error: aborting due to 2 previous errors
+error: aborting due to 1 previous error
 
 For more information about this error, try `rustc --explain E0038`.
diff --git a/tests/ui/impl-trait/in-trait/foreign-dyn-error.stderr b/tests/ui/impl-trait/in-trait/foreign-dyn-error.stderr
index 29235ca78a5..68ac765a3c1 100644
--- a/tests/ui/impl-trait/in-trait/foreign-dyn-error.stderr
+++ b/tests/ui/impl-trait/in-trait/foreign-dyn-error.stderr
@@ -1,8 +1,8 @@
 error[E0038]: the trait `Foo` is not dyn compatible
-  --> $DIR/foreign-dyn-error.rs:6:12
+  --> $DIR/foreign-dyn-error.rs:6:17
    |
 LL |     let _: &dyn rpitit::Foo = todo!();
-   |            ^^^^^^^^^^^^^^^^ `Foo` is not dyn compatible
+   |                 ^^^^^^^^^^^ `Foo` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
       for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
diff --git a/tests/ui/imports/extern-crate-used.stderr b/tests/ui/imports/extern-crate-used.stderr
index 982da0c913e..08bee391414 100644
--- a/tests/ui/imports/extern-crate-used.stderr
+++ b/tests/ui/imports/extern-crate-used.stderr
@@ -2,13 +2,18 @@ error: unused extern crate
   --> $DIR/extern-crate-used.rs:18:1
    |
 LL | extern crate core;
-   | ^^^^^^^^^^^^^^^^^^ help: remove it
+   | ^^^^^^^^^^^^^^^^^^ unused
    |
 note: the lint level is defined here
   --> $DIR/extern-crate-used.rs:6:9
    |
 LL | #![deny(unused_extern_crates)]
    |         ^^^^^^^^^^^^^^^^^^^^
+help: remove the unused `extern crate`
+   |
+LL - extern crate core;
+LL +
+   |
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/imports/import-glob-crate.rs b/tests/ui/imports/import-glob-crate.rs
index 0a2ca6ef2c3..ee067931876 100644
--- a/tests/ui/imports/import-glob-crate.rs
+++ b/tests/ui/imports/import-glob-crate.rs
@@ -1,3 +1,4 @@
+//@ edition: 2015
 //@ run-pass
 use std::mem::*;
 
diff --git a/tests/ui/instrument-xray/platform-support.rs b/tests/ui/instrument-xray/platform-support.rs
new file mode 100644
index 00000000000..238018b348d
--- /dev/null
+++ b/tests/ui/instrument-xray/platform-support.rs
@@ -0,0 +1,27 @@
+//@ only-nightly (flag is still unstable)
+//@ needs-xray
+
+//@ revisions: unsupported
+//@[unsupported] needs-llvm-components: x86
+//@[unsupported] compile-flags: -Z instrument-xray --target=x86_64-pc-windows-msvc
+
+//@ revisions: x86_64-linux
+//@[x86_64-linux] needs-llvm-components: x86
+//@[x86_64-linux] compile-flags: -Z instrument-xray --target=x86_64-unknown-linux-gnu
+//@[x86_64-linux] check-pass
+
+//@ revisions: x86_64-darwin
+//@[x86_64-darwin] needs-llvm-components: x86
+//@[x86_64-darwin] compile-flags: -Z instrument-xray --target=x86_64-apple-darwin
+//@[x86_64-darwin] check-pass
+
+//@ revisions: aarch64-darwin
+//@[aarch64-darwin] needs-llvm-components: aarch64
+//@[aarch64-darwin] compile-flags: -Z instrument-xray --target=aarch64-apple-darwin
+//@[aarch64-darwin] check-pass
+
+#![feature(no_core)]
+#![no_core]
+#![no_main]
+
+//[unsupported]~? ERROR XRay instrumentation is not supported for this target
diff --git a/tests/ui/instrument-xray/target-not-supported.stderr b/tests/ui/instrument-xray/platform-support.unsupported.stderr
index 119094bfc4c..119094bfc4c 100644
--- a/tests/ui/instrument-xray/target-not-supported.stderr
+++ b/tests/ui/instrument-xray/platform-support.unsupported.stderr
diff --git a/tests/ui/instrument-xray/target-not-supported.rs b/tests/ui/instrument-xray/target-not-supported.rs
deleted file mode 100644
index 2045913b186..00000000000
--- a/tests/ui/instrument-xray/target-not-supported.rs
+++ /dev/null
@@ -1,10 +0,0 @@
-// Verifies that `-Z instrument-xray` cannot be used with unsupported targets,
-//
-//@ needs-llvm-components: x86
-//@ compile-flags: -Z instrument-xray --target x86_64-apple-darwin
-
-#![feature(no_core)]
-#![no_core]
-#![no_main]
-
-//~? ERROR XRay instrumentation is not supported for this target
diff --git a/tests/ui/intrinsics/const-eval-select-stability.stderr b/tests/ui/intrinsics/const-eval-select-stability.stderr
index 5f443b1d4ff..513c19cbb5b 100644
--- a/tests/ui/intrinsics/const-eval-select-stability.stderr
+++ b/tests/ui/intrinsics/const-eval-select-stability.stderr
@@ -4,16 +4,11 @@ error: const function that might be (indirectly) exposed to stable cannot use `#
 LL |     const_eval_select((), nothing, log);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-help: if the function is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do)
+help: if the function is not (yet) meant to be exposed to stable const contexts, add `#[rustc_const_unstable]`
    |
 LL + #[rustc_const_unstable(feature = "...", issue = "...")]
 LL | pub const fn hey() {
    |
-help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval)
-   |
-LL + #[rustc_allow_const_fn_unstable(const_eval_select)]
-LL | pub const fn hey() {
-   |
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/intrinsics/intrinsic-atomics.rs b/tests/ui/intrinsics/intrinsic-atomics.rs
index 9127cc649e6..f96c6dc832e 100644
--- a/tests/ui/intrinsics/intrinsic-atomics.rs
+++ b/tests/ui/intrinsics/intrinsic-atomics.rs
@@ -1,14 +1,14 @@
 //@ run-pass
 #![feature(core_intrinsics)]
-use std::intrinsics as rusti;
+use std::intrinsics::{self as rusti, AtomicOrdering};
 
 pub fn main() {
     unsafe {
         let mut x: Box<_> = Box::new(1);
 
-        assert_eq!(rusti::atomic_load_seqcst(&*x), 1);
+        assert_eq!(rusti::atomic_load::<_, { AtomicOrdering::SeqCst }>(&*x), 1);
         *x = 5;
-        assert_eq!(rusti::atomic_load_acquire(&*x), 5);
+        assert_eq!(rusti::atomic_load::<_, { AtomicOrdering::Acquire }>(&*x), 5);
 
         rusti::atomic_store_seqcst(&mut *x, 3);
         assert_eq!(*x, 3);
diff --git a/tests/ui/intrinsics/non-integer-atomic.rs b/tests/ui/intrinsics/non-integer-atomic.rs
index 2d1d0882084..5464bf747fa 100644
--- a/tests/ui/intrinsics/non-integer-atomic.rs
+++ b/tests/ui/intrinsics/non-integer-atomic.rs
@@ -4,16 +4,16 @@
 #![allow(warnings)]
 #![crate_type = "rlib"]
 
-use std::intrinsics;
+use std::intrinsics::{self, AtomicOrdering};
 
 #[derive(Copy, Clone)]
 pub struct Foo(i64);
-pub type Bar = &'static Fn();
+pub type Bar = &'static dyn Fn();
 pub type Quux = [u8; 100];
 
 pub unsafe fn test_bool_load(p: &mut bool, v: bool) {
-    intrinsics::atomic_load_seqcst(p);
-    //~^ ERROR `atomic_load_seqcst` intrinsic: expected basic integer type, found `bool`
+    intrinsics::atomic_load::<_, { AtomicOrdering::SeqCst }>(p);
+    //~^ ERROR `atomic_load` intrinsic: expected basic integer type, found `bool`
 }
 
 pub unsafe fn test_bool_store(p: &mut bool, v: bool) {
@@ -32,8 +32,8 @@ pub unsafe fn test_bool_cxchg(p: &mut bool, v: bool) {
 }
 
 pub unsafe fn test_Foo_load(p: &mut Foo, v: Foo) {
-    intrinsics::atomic_load_seqcst(p);
-    //~^ ERROR `atomic_load_seqcst` intrinsic: expected basic integer type, found `Foo`
+    intrinsics::atomic_load::<_, { AtomicOrdering::SeqCst }>(p);
+    //~^ ERROR `atomic_load` intrinsic: expected basic integer type, found `Foo`
 }
 
 pub unsafe fn test_Foo_store(p: &mut Foo, v: Foo) {
@@ -52,7 +52,7 @@ pub unsafe fn test_Foo_cxchg(p: &mut Foo, v: Foo) {
 }
 
 pub unsafe fn test_Bar_load(p: &mut Bar, v: Bar) {
-    intrinsics::atomic_load_seqcst(p);
+    intrinsics::atomic_load::<_, { AtomicOrdering::SeqCst }>(p);
     //~^ ERROR expected basic integer type, found `&dyn Fn()`
 }
 
@@ -72,8 +72,8 @@ pub unsafe fn test_Bar_cxchg(p: &mut Bar, v: Bar) {
 }
 
 pub unsafe fn test_Quux_load(p: &mut Quux, v: Quux) {
-    intrinsics::atomic_load_seqcst(p);
-    //~^ ERROR `atomic_load_seqcst` intrinsic: expected basic integer type, found `[u8; 100]`
+    intrinsics::atomic_load::<_, { AtomicOrdering::SeqCst }>(p);
+    //~^ ERROR `atomic_load` intrinsic: expected basic integer type, found `[u8; 100]`
 }
 
 pub unsafe fn test_Quux_store(p: &mut Quux, v: Quux) {
diff --git a/tests/ui/intrinsics/non-integer-atomic.stderr b/tests/ui/intrinsics/non-integer-atomic.stderr
index 32791a8e8b7..58c2dc00c66 100644
--- a/tests/ui/intrinsics/non-integer-atomic.stderr
+++ b/tests/ui/intrinsics/non-integer-atomic.stderr
@@ -1,8 +1,8 @@
-error[E0511]: invalid monomorphization of `atomic_load_seqcst` intrinsic: expected basic integer type, found `bool`
+error[E0511]: invalid monomorphization of `atomic_load` intrinsic: expected basic integer type, found `bool`
   --> $DIR/non-integer-atomic.rs:15:5
    |
-LL |     intrinsics::atomic_load_seqcst(p);
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     intrinsics::atomic_load::<_, { AtomicOrdering::SeqCst }>(p);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0511]: invalid monomorphization of `atomic_store_seqcst` intrinsic: expected basic integer type, found `bool`
   --> $DIR/non-integer-atomic.rs:20:5
@@ -22,11 +22,11 @@ error[E0511]: invalid monomorphization of `atomic_cxchg_seqcst_seqcst` intrinsic
 LL |     intrinsics::atomic_cxchg_seqcst_seqcst(p, v, v);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error[E0511]: invalid monomorphization of `atomic_load_seqcst` intrinsic: expected basic integer type, found `Foo`
+error[E0511]: invalid monomorphization of `atomic_load` intrinsic: expected basic integer type, found `Foo`
   --> $DIR/non-integer-atomic.rs:35:5
    |
-LL |     intrinsics::atomic_load_seqcst(p);
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     intrinsics::atomic_load::<_, { AtomicOrdering::SeqCst }>(p);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0511]: invalid monomorphization of `atomic_store_seqcst` intrinsic: expected basic integer type, found `Foo`
   --> $DIR/non-integer-atomic.rs:40:5
@@ -46,11 +46,11 @@ error[E0511]: invalid monomorphization of `atomic_cxchg_seqcst_seqcst` intrinsic
 LL |     intrinsics::atomic_cxchg_seqcst_seqcst(p, v, v);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error[E0511]: invalid monomorphization of `atomic_load_seqcst` intrinsic: expected basic integer type, found `&dyn Fn()`
+error[E0511]: invalid monomorphization of `atomic_load` intrinsic: expected basic integer type, found `&dyn Fn()`
   --> $DIR/non-integer-atomic.rs:55:5
    |
-LL |     intrinsics::atomic_load_seqcst(p);
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     intrinsics::atomic_load::<_, { AtomicOrdering::SeqCst }>(p);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0511]: invalid monomorphization of `atomic_store_seqcst` intrinsic: expected basic integer type, found `&dyn Fn()`
   --> $DIR/non-integer-atomic.rs:60:5
@@ -70,11 +70,11 @@ error[E0511]: invalid monomorphization of `atomic_cxchg_seqcst_seqcst` intrinsic
 LL |     intrinsics::atomic_cxchg_seqcst_seqcst(p, v, v);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error[E0511]: invalid monomorphization of `atomic_load_seqcst` intrinsic: expected basic integer type, found `[u8; 100]`
+error[E0511]: invalid monomorphization of `atomic_load` intrinsic: expected basic integer type, found `[u8; 100]`
   --> $DIR/non-integer-atomic.rs:75:5
    |
-LL |     intrinsics::atomic_load_seqcst(p);
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     intrinsics::atomic_load::<_, { AtomicOrdering::SeqCst }>(p);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0511]: invalid monomorphization of `atomic_store_seqcst` intrinsic: expected basic integer type, found `[u8; 100]`
   --> $DIR/non-integer-atomic.rs:80:5
diff --git a/tests/ui/issues/issue-18959.rs b/tests/ui/issues/issue-18959.rs
index dbc73bafce9..415fe818f53 100644
--- a/tests/ui/issues/issue-18959.rs
+++ b/tests/ui/issues/issue-18959.rs
@@ -17,6 +17,6 @@ fn main() {
     let mut thing = Thing;
     let test: &dyn Bar = &mut thing;
     //~^ ERROR E0038
-    //~| ERROR E0038
     foo(test);
+    //~^ ERROR E0038
 }
diff --git a/tests/ui/issues/issue-18959.stderr b/tests/ui/issues/issue-18959.stderr
index 7ddfdb49d95..df47d50a019 100644
--- a/tests/ui/issues/issue-18959.stderr
+++ b/tests/ui/issues/issue-18959.stderr
@@ -15,10 +15,10 @@ LL | pub trait Bar: Foo { }
    = help: consider moving `foo` to another trait
 
 error[E0038]: the trait `Bar` is not dyn compatible
-  --> $DIR/issue-18959.rs:18:26
+  --> $DIR/issue-18959.rs:18:20
    |
 LL |     let test: &dyn Bar = &mut thing;
-   |                          ^^^^^^^^^^ `Bar` is not dyn compatible
+   |                    ^^^ `Bar` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
       for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
@@ -29,13 +29,12 @@ LL | pub trait Foo { fn foo<T>(&self, ext_thing: &T); }
 LL | pub trait Bar: Foo { }
    |           --- this trait is not dyn compatible...
    = help: consider moving `foo` to another trait
-   = note: required for the cast from `&mut Thing` to `&dyn Bar`
 
 error[E0038]: the trait `Bar` is not dyn compatible
-  --> $DIR/issue-18959.rs:18:15
+  --> $DIR/issue-18959.rs:20:9
    |
-LL |     let test: &dyn Bar = &mut thing;
-   |               ^^^^^^^^ `Bar` is not dyn compatible
+LL |     foo(test);
+   |         ^^^^ `Bar` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
       for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
diff --git a/tests/ui/issues/issue-19380.rs b/tests/ui/issues/issue-19380.rs
index 8b3fe4d2b09..fce737cba18 100644
--- a/tests/ui/issues/issue-19380.rs
+++ b/tests/ui/issues/issue-19380.rs
@@ -15,6 +15,5 @@ struct Bar {
 const FOO : Foo = Foo;
 const BAR : Bar = Bar { foos: &[&FOO]};
 //~^ ERROR E0038
-//~| ERROR E0038
 
 fn main() { }
diff --git a/tests/ui/issues/issue-19380.stderr b/tests/ui/issues/issue-19380.stderr
index f8509891d3a..4c41d41ae37 100644
--- a/tests/ui/issues/issue-19380.stderr
+++ b/tests/ui/issues/issue-19380.stderr
@@ -23,31 +23,6 @@ LL |   fn qiz() where Self: Sized;
    |            +++++++++++++++++
 
 error[E0038]: the trait `Qiz` is not dyn compatible
-  --> $DIR/issue-19380.rs:16:33
-   |
-LL | const BAR : Bar = Bar { foos: &[&FOO]};
-   |                                 ^^^^ `Qiz` is not dyn compatible
-   |
-note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
-  --> $DIR/issue-19380.rs:2:6
-   |
-LL | trait Qiz {
-   |       --- this trait is not dyn compatible...
-LL |   fn qiz();
-   |      ^^^ ...because associated function `qiz` has no `self` parameter
-   = help: only type `Foo` implements `Qiz`; consider using it directly instead.
-   = note: required for the cast from `&Foo` to `&'static (dyn Qiz + 'static)`
-help: consider turning `qiz` into a method by giving it a `&self` argument
-   |
-LL |   fn qiz(&self);
-   |          +++++
-help: alternatively, consider constraining `qiz` so it does not apply to trait objects
-   |
-LL |   fn qiz() where Self: Sized;
-   |            +++++++++++++++++
-
-error[E0038]: the trait `Qiz` is not dyn compatible
   --> $DIR/issue-19380.rs:16:31
    |
 LL | const BAR : Bar = Bar { foos: &[&FOO]};
@@ -71,6 +46,6 @@ help: alternatively, consider constraining `qiz` so it does not apply to trait o
 LL |   fn qiz() where Self: Sized;
    |            +++++++++++++++++
 
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0038`.
diff --git a/tests/ui/issues/issue-50781.rs b/tests/ui/issues/issue-50781.rs
index ab90db1cadc..d837b848591 100644
--- a/tests/ui/issues/issue-50781.rs
+++ b/tests/ui/issues/issue-50781.rs
@@ -15,5 +15,4 @@ pub fn main() {
     // Check that this does not segfault.
     <dyn X as X>::foo(&());
     //~^ ERROR the trait `X` is not dyn compatible
-    //~| ERROR the trait `X` is not dyn compatible
 }
diff --git a/tests/ui/issues/issue-50781.stderr b/tests/ui/issues/issue-50781.stderr
index 88b83a83e0c..4ba3166b6c5 100644
--- a/tests/ui/issues/issue-50781.stderr
+++ b/tests/ui/issues/issue-50781.stderr
@@ -16,10 +16,10 @@ LL |     fn foo(&self) where Self: Trait;
    = help: only type `()` implements `X`; consider using it directly instead.
 
 error[E0038]: the trait `X` is not dyn compatible
-  --> $DIR/issue-50781.rs:16:23
+  --> $DIR/issue-50781.rs:16:10
    |
 LL |     <dyn X as X>::foo(&());
-   |                       ^^^ `X` is not dyn compatible
+   |          ^ `X` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
       for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
@@ -31,25 +31,7 @@ LL |     fn foo(&self) where Self: Trait;
    |        ^^^ ...because method `foo` references the `Self` type in its `where` clause
    = help: consider moving `foo` to another trait
    = help: only type `()` implements `X`; consider using it directly instead.
-   = note: required for the cast from `&()` to `&dyn X`
 
-error[E0038]: the trait `X` is not dyn compatible
-  --> $DIR/issue-50781.rs:16:6
-   |
-LL |     <dyn X as X>::foo(&());
-   |      ^^^^^ `X` is not dyn compatible
-   |
-note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
-  --> $DIR/issue-50781.rs:4:8
-   |
-LL | trait X {
-   |       - this trait is not dyn compatible...
-LL |     fn foo(&self) where Self: Trait;
-   |        ^^^ ...because method `foo` references the `Self` type in its `where` clause
-   = help: consider moving `foo` to another trait
-   = help: only type `()` implements `X`; consider using it directly instead.
-
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0038`.
diff --git a/tests/ui/issues/issue-58734.rs b/tests/ui/issues/issue-58734.rs
index ee23be87b6b..e5b371f5530 100644
--- a/tests/ui/issues/issue-58734.rs
+++ b/tests/ui/issues/issue-58734.rs
@@ -18,8 +18,7 @@ fn main() {
     Trait::exists(());
     // no dyn-compatibility error
     Trait::nonexistent(());
-    //~^ ERROR no function or associated item named `nonexistent` found
-    //~| WARN trait objects without an explicit `dyn` are deprecated
+    //~^ WARN trait objects without an explicit `dyn` are deprecated
     //~| WARN this is accepted in the current edition
     //~| ERROR the trait `Trait` is not dyn compatible
 }
diff --git a/tests/ui/issues/issue-58734.stderr b/tests/ui/issues/issue-58734.stderr
index c4624cecc62..e5dad000b51 100644
--- a/tests/ui/issues/issue-58734.stderr
+++ b/tests/ui/issues/issue-58734.stderr
@@ -37,13 +37,6 @@ help: alternatively, consider constraining `dyn_incompatible` so it does not app
 LL |     fn dyn_incompatible() -> Self where Self: Sized;
    |                                   +++++++++++++++++
 
-error[E0599]: no function or associated item named `nonexistent` found for trait object `dyn Trait` in the current scope
-  --> $DIR/issue-58734.rs:20:12
-   |
-LL |     Trait::nonexistent(());
-   |            ^^^^^^^^^^^ function or associated item not found in `dyn Trait`
-
-error: aborting due to 2 previous errors; 1 warning emitted
+error: aborting due to 1 previous error; 1 warning emitted
 
-Some errors have detailed explanations: E0038, E0599.
-For more information about an error, try `rustc --explain E0038`.
+For more information about this error, try `rustc --explain E0038`.
diff --git a/tests/ui/iterators/generator.rs b/tests/ui/iterators/generator.rs
new file mode 100644
index 00000000000..e633efb11c1
--- /dev/null
+++ b/tests/ui/iterators/generator.rs
@@ -0,0 +1,24 @@
+//@ run-pass
+
+#![feature(iter_macro, yield_expr)]
+
+use std::iter::iter;
+
+fn main() {
+    let i = iter! { || {
+        yield 0;
+        for x in 5..10 {
+            yield x * 2;
+        }
+    } };
+    let mut i = i();
+    assert_eq!(i.next(), Some(0));
+    assert_eq!(i.next(), Some(10));
+    assert_eq!(i.next(), Some(12));
+    assert_eq!(i.next(), Some(14));
+    assert_eq!(i.next(), Some(16));
+    assert_eq!(i.next(), Some(18));
+    assert_eq!(i.next(), None);
+    assert_eq!(i.next(), None);
+    assert_eq!(i.next(), None);
+}
diff --git a/tests/ui/iterators/generator_args.rs b/tests/ui/iterators/generator_args.rs
new file mode 100644
index 00000000000..c9da9e5fba6
--- /dev/null
+++ b/tests/ui/iterators/generator_args.rs
@@ -0,0 +1,24 @@
+//@ run-pass
+
+#![feature(iter_macro, yield_expr)]
+
+use std::iter::iter;
+
+fn main() {
+    let i = iter! {|foo| {
+        yield foo;
+        for x in 5..10 {
+            yield x * 2;
+        }
+    }};
+    let mut i = i(3);
+    assert_eq!(i.next(), Some(3));
+    assert_eq!(i.next(), Some(10));
+    assert_eq!(i.next(), Some(12));
+    assert_eq!(i.next(), Some(14));
+    assert_eq!(i.next(), Some(16));
+    assert_eq!(i.next(), Some(18));
+    assert_eq!(i.next(), None);
+    assert_eq!(i.next(), None);
+    assert_eq!(i.next(), None);
+}
diff --git a/tests/ui/iterators/generator_capture.rs b/tests/ui/iterators/generator_capture.rs
new file mode 100644
index 00000000000..c790b7a4b96
--- /dev/null
+++ b/tests/ui/iterators/generator_capture.rs
@@ -0,0 +1,27 @@
+//@ run-pass
+
+#![feature(iter_macro, yield_expr)]
+
+use std::iter::iter;
+
+fn main() {
+    let i = {
+        let s = String::new();
+        iter! { move || {
+            yield s.len();
+            for x in 5..10 {
+                yield x * 2;
+            }
+        }}
+    };
+    let mut i = i();
+    assert_eq!(i.next(), Some(0));
+    assert_eq!(i.next(), Some(10));
+    assert_eq!(i.next(), Some(12));
+    assert_eq!(i.next(), Some(14));
+    assert_eq!(i.next(), Some(16));
+    assert_eq!(i.next(), Some(18));
+    assert_eq!(i.next(), None);
+    assert_eq!(i.next(), None);
+    assert_eq!(i.next(), None);
+}
diff --git a/tests/ui/iterators/generator_capture_.rs b/tests/ui/iterators/generator_capture_.rs
new file mode 100644
index 00000000000..f630bc64b97
--- /dev/null
+++ b/tests/ui/iterators/generator_capture_.rs
@@ -0,0 +1,26 @@
+// This test exercises lending behavior for iterator closures which is not yet supported.
+
+#![feature(iter_macro, yield_expr)]
+
+use std::iter::iter;
+
+fn main() {
+    let f = {
+        let s = "foo".to_string();
+        iter! { move || {
+            for c in s.chars() {
+                yield c;
+            }
+        }}
+    };
+    let mut i = f();
+    assert_eq!(i.next(), Some('f'));
+    assert_eq!(i.next(), Some('o'));
+    assert_eq!(i.next(), Some('o'));
+    assert_eq!(i.next(), None);
+    let mut i = f(); //~ ERROR use of moved value: `f`
+    assert_eq!(i.next(), Some('f'));
+    assert_eq!(i.next(), Some('o'));
+    assert_eq!(i.next(), Some('o'));
+    assert_eq!(i.next(), None);
+}
diff --git a/tests/ui/iterators/generator_capture_.stderr b/tests/ui/iterators/generator_capture_.stderr
new file mode 100644
index 00000000000..3d9647ae16f
--- /dev/null
+++ b/tests/ui/iterators/generator_capture_.stderr
@@ -0,0 +1,25 @@
+error[E0382]: use of moved value: `f`
+  --> $DIR/generator_capture_.rs:21:17
+   |
+LL |     let f = {
+   |         - move occurs because `f` has type `{gen closure@$DIR/generator_capture_.rs:10:17: 10:24}`, which does not implement the `Copy` trait
+...
+LL |     let mut i = f();
+   |                 --- `f` moved due to this call
+...
+LL |     let mut i = f();
+   |                 ^ value used here after move
+   |
+note: this value implements `FnOnce`, which causes it to be moved when called
+  --> $DIR/generator_capture_.rs:16:17
+   |
+LL |     let mut i = f();
+   |                 ^
+help: consider cloning the value if the performance cost is acceptable
+   |
+LL |     let mut i = f.clone()();
+   |                  ++++++++
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/tests/ui/iterators/generator_capture_fail.rs b/tests/ui/iterators/generator_capture_fail.rs
new file mode 100644
index 00000000000..d987b2df011
--- /dev/null
+++ b/tests/ui/iterators/generator_capture_fail.rs
@@ -0,0 +1,25 @@
+#![feature(iter_macro, yield_expr)]
+
+use std::iter::iter;
+
+fn main() {
+    let i = {
+        let s = String::new();
+        iter! { || { //~ ERROR `s` does not live long enough
+            yield s.len();
+            for x in 5..10 {
+                yield x * 2;
+            }
+        } }
+    };
+    let mut i = i();
+    assert_eq!(i.next(), Some(0));
+    assert_eq!(i.next(), Some(10));
+    assert_eq!(i.next(), Some(12));
+    assert_eq!(i.next(), Some(14));
+    assert_eq!(i.next(), Some(16));
+    assert_eq!(i.next(), Some(18));
+    assert_eq!(i.next(), None);
+    assert_eq!(i.next(), None);
+    assert_eq!(i.next(), None);
+}
diff --git a/tests/ui/iterators/generator_capture_fail.stderr b/tests/ui/iterators/generator_capture_fail.stderr
new file mode 100644
index 00000000000..225a385d6a0
--- /dev/null
+++ b/tests/ui/iterators/generator_capture_fail.stderr
@@ -0,0 +1,20 @@
+error[E0597]: `s` does not live long enough
+  --> $DIR/generator_capture_fail.rs:8:17
+   |
+LL |       let i = {
+   |           - borrow later stored here
+LL |           let s = String::new();
+LL |           iter! { || {
+   |  _________________^
+LL | |             yield s.len();
+LL | |             for x in 5..10 {
+LL | |                 yield x * 2;
+LL | |             }
+LL | |         } }
+   | |_________^ borrowed value does not live long enough
+LL |       };
+   |       - `s` dropped here while still borrowed
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/tests/ui/iterators/generator_capture_fnonce.rs b/tests/ui/iterators/generator_capture_fnonce.rs
new file mode 100644
index 00000000000..090727eb9b7
--- /dev/null
+++ b/tests/ui/iterators/generator_capture_fnonce.rs
@@ -0,0 +1,32 @@
+//@ run-pass
+
+#![feature(iter_macro, yield_expr)]
+
+use std::iter::iter;
+
+fn main() {
+    let i = {
+        let s = String::new();
+        iter! { move || {
+            yield s.len();
+            for x in 5..10 {
+                yield x * 2;
+            }
+        }}
+    };
+    test_iterator(i);
+}
+
+/// Exercise the iterator in a separate function to ensure it's not capturing anything it shoudln't.
+fn test_iterator<I: Iterator<Item = usize>>(i: impl FnOnce() -> I) {
+    let mut i = i();
+    assert_eq!(i.next(), Some(0));
+    assert_eq!(i.next(), Some(10));
+    assert_eq!(i.next(), Some(12));
+    assert_eq!(i.next(), Some(14));
+    assert_eq!(i.next(), Some(16));
+    assert_eq!(i.next(), Some(18));
+    assert_eq!(i.next(), None);
+    assert_eq!(i.next(), None);
+    assert_eq!(i.next(), None);
+}
diff --git a/tests/ui/iterators/generator_capture_no_lend.rs b/tests/ui/iterators/generator_capture_no_lend.rs
new file mode 100644
index 00000000000..822db58d48d
--- /dev/null
+++ b/tests/ui/iterators/generator_capture_no_lend.rs
@@ -0,0 +1,30 @@
+//@ run-pass
+
+#![feature(iter_macro, yield_expr)]
+
+// This test creates an iterator that captures a reference and ensure that doesn't force the
+// iterator to become lending.
+
+use std::iter::iter;
+
+fn main() {
+    let s = "foo".to_string();
+    let f = iter! { || {
+        for c in s.chars() {
+            yield c;
+        }
+    }};
+
+    let mut i = f();
+    let mut j = f();
+
+    assert_eq!(i.next(), Some('f'));
+    assert_eq!(i.next(), Some('o'));
+    assert_eq!(i.next(), Some('o'));
+    assert_eq!(i.next(), None);
+
+    assert_eq!(j.next(), Some('f'));
+    assert_eq!(j.next(), Some('o'));
+    assert_eq!(j.next(), Some('o'));
+    assert_eq!(j.next(), None);
+}
diff --git a/tests/ui/iterators/generator_returned_from_fn.rs b/tests/ui/iterators/generator_returned_from_fn.rs
new file mode 100644
index 00000000000..bd0317b1ffb
--- /dev/null
+++ b/tests/ui/iterators/generator_returned_from_fn.rs
@@ -0,0 +1,63 @@
+#![feature(iter_macro, impl_trait_in_fn_trait_return, yield_expr)]
+
+use std::iter::iter;
+
+fn plain() -> impl Fn() -> impl Iterator<Item = u32> {
+    iter! { || {
+        yield 0;
+        for x in 5..10 {
+            yield x * 2;
+        }
+    } }
+}
+
+fn arg() -> impl Fn(u32) -> impl Iterator<Item = u32> {
+    iter! { |arg| {
+        yield arg;
+        for x in 5..10 {
+            yield x * 2;
+        }
+    } }
+}
+
+fn capture<'a>(a: &'a u32) -> impl Fn() -> (impl Iterator<Item = u32> + 'a) {
+    iter! { || { //~ ERROR cannot return reference to function parameter `a`
+        yield *a;
+        for x in 5..10 {
+            yield x * 2;
+        }
+    } }
+}
+
+fn capture_move(a: &u32) -> impl Fn() -> impl Iterator<Item = u32> {
+    iter! { move || { //~ ERROR does not implement `Fn` because it captures
+        yield *a;
+        for x in 5..10 {
+            yield x * 2;
+        }
+    } }
+}
+
+fn capture_move_once(a: &u32) -> impl FnOnce() -> impl Iterator<Item = u32> {
+    iter! { move || {
+        //~^ ERROR captures lifetime
+        //~| ERROR: captures lifetime
+        yield *a;
+        for x in 5..10 {
+            yield x * 2;
+        }
+    } }
+}
+
+fn capture_move_once_lifetimes<'a>(
+    a: &'a u32,
+) -> impl FnOnce() -> (impl Iterator<Item = u32> + 'a) {
+    iter! { move || {
+        yield *a;
+        for x in 5..10 {
+            yield x * 2;
+        }
+    } }
+}
+
+fn main() {}
diff --git a/tests/ui/iterators/generator_returned_from_fn.stderr b/tests/ui/iterators/generator_returned_from_fn.stderr
new file mode 100644
index 00000000000..b2324af6d5e
--- /dev/null
+++ b/tests/ui/iterators/generator_returned_from_fn.stderr
@@ -0,0 +1,70 @@
+error[E0515]: cannot return reference to function parameter `a`
+  --> $DIR/generator_returned_from_fn.rs:24:13
+   |
+LL |       iter! { || {
+   |  _____________^
+LL | |         yield *a;
+LL | |         for x in 5..10 {
+LL | |             yield x * 2;
+LL | |         }
+LL | |     } }
+   | |_____^ returns a reference to data owned by the current function
+
+error: gen closure does not implement `Fn` because it captures state from its environment
+  --> $DIR/generator_returned_from_fn.rs:33:13
+   |
+LL |       iter! { move || {
+   |  _____________-^^^^^^
+LL | |         yield *a;
+LL | |         for x in 5..10 {
+LL | |             yield x * 2;
+LL | |         }
+LL | |     } }
+   | |_____- return type was inferred to be `{gen closure@$DIR/generator_returned_from_fn.rs:33:13: 33:20}` here
+
+error[E0700]: hidden type for `impl FnOnce() -> impl Iterator<Item = u32>` captures lifetime that does not appear in bounds
+  --> $DIR/generator_returned_from_fn.rs:42:13
+   |
+LL |   fn capture_move_once(a: &u32) -> impl FnOnce() -> impl Iterator<Item = u32> {
+   |                           ----     ------------------------------------------ opaque type defined here
+   |                           |
+   |                           hidden type `{gen closure@$DIR/generator_returned_from_fn.rs:42:13: 42:20}` captures the anonymous lifetime defined here
+LL |       iter! { move || {
+   |  _____________^
+LL | |
+LL | |
+LL | |         yield *a;
+...  |
+LL | |     } }
+   | |_____^
+   |
+help: add a `use<...>` bound to explicitly capture `'_`
+   |
+LL | fn capture_move_once(a: &u32) -> impl FnOnce() -> impl Iterator<Item = u32> + use<'_> {
+   |                                                                             +++++++++
+
+error[E0700]: hidden type for `impl Iterator<Item = u32>` captures lifetime that does not appear in bounds
+  --> $DIR/generator_returned_from_fn.rs:42:13
+   |
+LL |   fn capture_move_once(a: &u32) -> impl FnOnce() -> impl Iterator<Item = u32> {
+   |                           ----                      ------------------------- opaque type defined here
+   |                           |
+   |                           hidden type `{gen closure body@$DIR/generator_returned_from_fn.rs:42:21: 49:6}` captures the anonymous lifetime defined here
+LL |       iter! { move || {
+   |  _____________^
+LL | |
+LL | |
+LL | |         yield *a;
+...  |
+LL | |     } }
+   | |_____^
+   |
+help: add a `use<...>` bound to explicitly capture `'_`
+   |
+LL | fn capture_move_once(a: &u32) -> impl FnOnce() -> impl Iterator<Item = u32> + use<'_> {
+   |                                                                             +++++++++
+
+error: aborting due to 4 previous errors
+
+Some errors have detailed explanations: E0515, E0700.
+For more information about an error, try `rustc --explain E0515`.
diff --git a/tests/ui/iterators/iter-macro-not-async-closure-simplified.narrow.stderr b/tests/ui/iterators/iter-macro-not-async-closure-simplified.narrow.stderr
new file mode 100644
index 00000000000..4e0dabade2d
--- /dev/null
+++ b/tests/ui/iterators/iter-macro-not-async-closure-simplified.narrow.stderr
@@ -0,0 +1,18 @@
+error[E0277]: the trait bound `{gen closure@$DIR/iter-macro-not-async-closure-simplified.rs:21:21: 21:28}: AsyncFnOnce()` is not satisfied
+  --> $DIR/iter-macro-not-async-closure-simplified.rs:27:21
+   |
+LL |     call_async_once(f);
+   |     --------------- ^ unsatisfied trait bound
+   |     |
+   |     required by a bound introduced by this call
+   |
+   = help: the trait `AsyncFnOnce()` is not implemented for `{gen closure@$DIR/iter-macro-not-async-closure-simplified.rs:21:21: 21:28}`
+note: required by a bound in `call_async_once`
+  --> $DIR/iter-macro-not-async-closure-simplified.rs:18:28
+   |
+LL | ...pl AsyncFnOnce()) {}
+   |       ^^^^^^^^^^^^^ required by this bound in `call_async_once`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/iterators/iter-macro-not-async-closure-simplified.rs b/tests/ui/iterators/iter-macro-not-async-closure-simplified.rs
new file mode 100644
index 00000000000..4fa14fda661
--- /dev/null
+++ b/tests/ui/iterators/iter-macro-not-async-closure-simplified.rs
@@ -0,0 +1,29 @@
+// This test ensures iterators created with the `iter!` macro are not
+// accidentally async closures.
+//
+// We test this both in a `narrow` and `wide` configuration because
+// the way that the diagnostic is emitted varies depending on the
+// diagnostic width.  If it's too narrow to fit the explanation, that
+// explanation is moved to the `help` instead of the span label.
+//
+//@ edition: 2024
+//@ revisions: narrow wide
+//@[narrow] compile-flags: --diagnostic-width=20
+//@[wide] compile-flags: --diagnostic-width=300
+
+#![feature(yield_expr, iter_macro)]
+
+use std::iter::iter;
+
+fn call_async_once(_: impl AsyncFnOnce()) {}
+
+fn main() {
+    let f = iter! { move || {
+        for i in 0..10 {
+            yield i;
+        }
+    }};
+
+    call_async_once(f);
+    //~^ ERROR AsyncFnOnce()` is not satisfied
+}
diff --git a/tests/ui/iterators/iter-macro-not-async-closure-simplified.wide.stderr b/tests/ui/iterators/iter-macro-not-async-closure-simplified.wide.stderr
new file mode 100644
index 00000000000..a6c239c181b
--- /dev/null
+++ b/tests/ui/iterators/iter-macro-not-async-closure-simplified.wide.stderr
@@ -0,0 +1,17 @@
+error[E0277]: the trait bound `{gen closure@$DIR/iter-macro-not-async-closure-simplified.rs:21:21: 21:28}: AsyncFnOnce()` is not satisfied
+  --> $DIR/iter-macro-not-async-closure-simplified.rs:27:21
+   |
+LL |     call_async_once(f);
+   |     --------------- ^ the trait `AsyncFnOnce()` is not implemented for `{gen closure@$DIR/iter-macro-not-async-closure-simplified.rs:21:21: 21:28}`
+   |     |
+   |     required by a bound introduced by this call
+   |
+note: required by a bound in `call_async_once`
+  --> $DIR/iter-macro-not-async-closure-simplified.rs:18:28
+   |
+LL | fn call_async_once(_: impl AsyncFnOnce()) {}
+   |                            ^^^^^^^^^^^^^ required by this bound in `call_async_once`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/iterators/iter-macro-not-async-closure.narrow.stderr b/tests/ui/iterators/iter-macro-not-async-closure.narrow.stderr
new file mode 100644
index 00000000000..af3289c3d4e
--- /dev/null
+++ b/tests/ui/iterators/iter-macro-not-async-closure.narrow.stderr
@@ -0,0 +1,72 @@
+error[E0277]: the trait bound `{gen closure@$DIR/iter-macro-not-async-closure.rs:26:21: 26:28}: AsyncFnOnce()` is not satisfied
+  --> $DIR/iter-macro-not-async-closure.rs:32:34
+   |
+LL | ...n!(call_async_once(f));
+   |       --------------- ^ unsatisfied trait bound
+   |       |
+   |       required by a bound introduced by this call
+   |
+   = help: the trait `AsyncFnOnce()` is not implemented for `{gen closure@$DIR/iter-macro-not-async-closure.rs:26:21: 26:28}`
+note: required by a bound in `call_async_once`
+  --> $DIR/iter-macro-not-async-closure.rs:21:34
+   |
+LL | ...pl AsyncFnOnce()) {
+   |       ^^^^^^^^^^^^^ required by this bound in `call_async_once`
+
+error[E0277]: the trait bound `{gen closure@$DIR/iter-macro-not-async-closure.rs:26:21: 26:28}: AsyncFnOnce()` is not satisfied
+  --> $DIR/iter-macro-not-async-closure.rs:32:18
+   |
+LL | ...n!(call_async_once(f));
+   |       ^^^^^^^^^^^^^^^^^^ unsatisfied trait bound
+   |
+   = help: the trait `AsyncFnOnce()` is not implemented for `{gen closure@$DIR/iter-macro-not-async-closure.rs:26:21: 26:28}`
+note: required by a bound in `call_async_once`
+  --> $DIR/iter-macro-not-async-closure.rs:21:34
+   |
+LL | ...pl AsyncFnOnce()) {
+   |       ^^^^^^^^^^^^^ required by this bound in `call_async_once`
+
+error[E0277]: the trait bound `{gen closure@$DIR/iter-macro-not-async-closure.rs:26:21: 26:28}: AsyncFnOnce()` is not satisfied
+  --> $DIR/iter-macro-not-async-closure.rs:32:13
+   |
+LL | ... = pin!(call_async_once(f));
+   |       ^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied trait bound
+   |
+   = help: the trait `AsyncFnOnce()` is not implemented for `{gen closure@$DIR/iter-macro-not-async-closure.rs:26:21: 26:28}`
+note: required by a bound in `call_async_once`
+  --> $DIR/iter-macro-not-async-closure.rs:21:34
+   |
+LL | ...pl AsyncFnOnce()) {
+   |       ^^^^^^^^^^^^^ required by this bound in `call_async_once`
+   = note: this error originates in the macro `pin` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the trait bound `{gen closure@$DIR/iter-macro-not-async-closure.rs:26:21: 26:28}: AsyncFnOnce()` is not satisfied
+  --> $DIR/iter-macro-not-async-closure.rs:32:13
+   |
+LL | ... = pin!(call_async_once(f));
+   |       ^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied trait bound
+   |
+   = help: the trait `AsyncFnOnce()` is not implemented for `{gen closure@$DIR/iter-macro-not-async-closure.rs:26:21: 26:28}`
+note: required by a bound in `call_async_once`
+  --> $DIR/iter-macro-not-async-closure.rs:21:34
+   |
+LL | ...pl AsyncFnOnce()) {
+   |       ^^^^^^^^^^^^^ required by this bound in `call_async_once`
+   = note: this error originates in the macro `pin` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the trait bound `{gen closure@$DIR/iter-macro-not-async-closure.rs:26:21: 26:28}: AsyncFnOnce()` is not satisfied
+  --> $DIR/iter-macro-not-async-closure.rs:37:5
+   |
+LL |     ...::noop()));
+   |     ...^^^^^^^^^^ unsatisfied trait bound
+   |
+   = help: the trait `AsyncFnOnce()` is not implemented for `{gen closure@$DIR/iter-macro-not-async-closure.rs:26:21: 26:28}`
+note: required by a bound in `call_async_once`
+  --> $DIR/iter-macro-not-async-closure.rs:21:34
+   |
+LL | ...pl AsyncFnOnce()) {
+   |       ^^^^^^^^^^^^^ required by this bound in `call_async_once`
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/iterators/iter-macro-not-async-closure.rs b/tests/ui/iterators/iter-macro-not-async-closure.rs
new file mode 100644
index 00000000000..634391883ea
--- /dev/null
+++ b/tests/ui/iterators/iter-macro-not-async-closure.rs
@@ -0,0 +1,32 @@
+// This test ensures iterators created with the `iter!` macro are not
+// accidentally async closures.
+//
+//@ edition: 2024
+//@ remap-src-base
+
+#![feature(yield_expr, iter_macro)]
+
+use std::task::{Waker, Context};
+use std::iter::iter;
+use std::pin::pin;
+use std::future::Future;
+
+async fn call_async_once(f: impl AsyncFnOnce()) {
+    f().await
+}
+
+fn main() {
+    let f = iter! { move || {
+        for i in 0..10 {
+            yield i;
+        }
+    }};
+
+    let x = pin!(call_async_once(f));
+    //~^ ERROR AsyncFnOnce()` is not satisfied
+    //~^^ ERROR AsyncFnOnce()` is not satisfied
+    //~^^^ ERROR AsyncFnOnce()` is not satisfied
+    //~^^^^ ERROR AsyncFnOnce()` is not satisfied
+    x.poll(&mut Context::from_waker(Waker::noop()));
+    //~^ ERROR AsyncFnOnce()` is not satisfied
+}
diff --git a/tests/ui/iterators/iter-macro-not-async-closure.stderr b/tests/ui/iterators/iter-macro-not-async-closure.stderr
new file mode 100644
index 00000000000..2f0343a2d0d
--- /dev/null
+++ b/tests/ui/iterators/iter-macro-not-async-closure.stderr
@@ -0,0 +1,67 @@
+error[E0277]: the trait bound `{gen closure@$DIR/iter-macro-not-async-closure.rs:19:21: 19:28}: AsyncFnOnce()` is not satisfied
+  --> $DIR/iter-macro-not-async-closure.rs:25:34
+   |
+LL |     let x = pin!(call_async_once(f));
+   |                  --------------- ^ the trait `AsyncFnOnce()` is not implemented for `{gen closure@$DIR/iter-macro-not-async-closure.rs:19:21: 19:28}`
+   |                  |
+   |                  required by a bound introduced by this call
+   |
+note: required by a bound in `call_async_once`
+  --> $DIR/iter-macro-not-async-closure.rs:14:34
+   |
+LL | async fn call_async_once(f: impl AsyncFnOnce()) {
+   |                                  ^^^^^^^^^^^^^ required by this bound in `call_async_once`
+
+error[E0277]: the trait bound `{gen closure@$DIR/iter-macro-not-async-closure.rs:19:21: 19:28}: AsyncFnOnce()` is not satisfied
+  --> $DIR/iter-macro-not-async-closure.rs:25:18
+   |
+LL |     let x = pin!(call_async_once(f));
+   |                  ^^^^^^^^^^^^^^^^^^ the trait `AsyncFnOnce()` is not implemented for `{gen closure@$DIR/iter-macro-not-async-closure.rs:19:21: 19:28}`
+   |
+note: required by a bound in `call_async_once`
+  --> $DIR/iter-macro-not-async-closure.rs:14:34
+   |
+LL | async fn call_async_once(f: impl AsyncFnOnce()) {
+   |                                  ^^^^^^^^^^^^^ required by this bound in `call_async_once`
+
+error[E0277]: the trait bound `{gen closure@$DIR/iter-macro-not-async-closure.rs:19:21: 19:28}: AsyncFnOnce()` is not satisfied
+  --> $DIR/iter-macro-not-async-closure.rs:25:13
+   |
+LL |     let x = pin!(call_async_once(f));
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `AsyncFnOnce()` is not implemented for `{gen closure@$DIR/iter-macro-not-async-closure.rs:19:21: 19:28}`
+   |
+note: required by a bound in `call_async_once`
+  --> $DIR/iter-macro-not-async-closure.rs:14:34
+   |
+LL | async fn call_async_once(f: impl AsyncFnOnce()) {
+   |                                  ^^^^^^^^^^^^^ required by this bound in `call_async_once`
+   = note: this error originates in the macro `pin` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the trait bound `{gen closure@$DIR/iter-macro-not-async-closure.rs:19:21: 19:28}: AsyncFnOnce()` is not satisfied
+  --> $DIR/iter-macro-not-async-closure.rs:25:13
+   |
+LL |     let x = pin!(call_async_once(f));
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `AsyncFnOnce()` is not implemented for `{gen closure@$DIR/iter-macro-not-async-closure.rs:19:21: 19:28}`
+   |
+note: required by a bound in `call_async_once`
+  --> $DIR/iter-macro-not-async-closure.rs:14:34
+   |
+LL | async fn call_async_once(f: impl AsyncFnOnce()) {
+   |                                  ^^^^^^^^^^^^^ required by this bound in `call_async_once`
+   = note: this error originates in the macro `pin` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the trait bound `{gen closure@$DIR/iter-macro-not-async-closure.rs:19:21: 19:28}: AsyncFnOnce()` is not satisfied
+  --> $DIR/iter-macro-not-async-closure.rs:30:5
+   |
+LL |     x.poll(&mut Context::from_waker(Waker::noop()));
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `AsyncFnOnce()` is not implemented for `{gen closure@$DIR/iter-macro-not-async-closure.rs:19:21: 19:28}`
+   |
+note: required by a bound in `call_async_once`
+  --> $DIR/iter-macro-not-async-closure.rs:14:34
+   |
+LL | async fn call_async_once(f: impl AsyncFnOnce()) {
+   |                                  ^^^^^^^^^^^^^ required by this bound in `call_async_once`
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/kindck/kindck-inherited-copy-bound.rs b/tests/ui/kindck/kindck-inherited-copy-bound.rs
index 20d54a3fb10..92c2b273c2c 100644
--- a/tests/ui/kindck/kindck-inherited-copy-bound.rs
+++ b/tests/ui/kindck/kindck-inherited-copy-bound.rs
@@ -22,7 +22,6 @@ fn b() {
     let y = &x;
     let z = &x as &dyn Foo;
     //~^ ERROR E0038
-    //~| ERROR E0038
 }
 
 fn main() { }
diff --git a/tests/ui/kindck/kindck-inherited-copy-bound.stderr b/tests/ui/kindck/kindck-inherited-copy-bound.stderr
index edfa7ae7769..c15aabacddd 100644
--- a/tests/ui/kindck/kindck-inherited-copy-bound.stderr
+++ b/tests/ui/kindck/kindck-inherited-copy-bound.stderr
@@ -20,10 +20,10 @@ LL | fn take_param<T:Foo>(foo: &T) { }
    |                 ^^^ required by this bound in `take_param`
 
 error[E0038]: the trait `Foo` is not dyn compatible
-  --> $DIR/kindck-inherited-copy-bound.rs:23:19
+  --> $DIR/kindck-inherited-copy-bound.rs:23:24
    |
 LL |     let z = &x as &dyn Foo;
-   |                   ^^^^^^^^ `Foo` is not dyn compatible
+   |                        ^^^ `Foo` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
       for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
@@ -34,23 +34,7 @@ LL | trait Foo : Copy {
    |       |
    |       this trait is not dyn compatible...
 
-error[E0038]: the trait `Foo` is not dyn compatible
-  --> $DIR/kindck-inherited-copy-bound.rs:23:13
-   |
-LL |     let z = &x as &dyn Foo;
-   |             ^^ `Foo` is not dyn compatible
-   |
-note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
-  --> $DIR/kindck-inherited-copy-bound.rs:6:13
-   |
-LL | trait Foo : Copy {
-   |       ---   ^^^^ ...because it requires `Self: Sized`
-   |       |
-   |       this trait is not dyn compatible...
-   = note: required for the cast from `&Box<{integer}>` to `&dyn Foo`
-
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
 
 Some errors have detailed explanations: E0038, E0277.
 For more information about an error, try `rustc --explain E0038`.
diff --git a/tests/ui/lint/dead-code/alias-type-used-as-generic-arg-in-impl.rs b/tests/ui/lint/dead-code/alias-type-used-as-generic-arg-in-impl.rs
new file mode 100644
index 00000000000..4857ef6a9b8
--- /dev/null
+++ b/tests/ui/lint/dead-code/alias-type-used-as-generic-arg-in-impl.rs
@@ -0,0 +1,19 @@
+//@ check-pass
+
+#![deny(dead_code)]
+
+struct T<X>(X);
+
+type A<X> = T<X>;
+
+trait Tr {
+    fn foo();
+}
+
+impl<X> Tr for T<A<X>> {
+    fn foo() {}
+}
+
+fn main() {
+   T::<T<()>>::foo();
+}
diff --git a/tests/ui/lint/dead-code/issue-41883.stderr b/tests/ui/lint/dead-code/issue-41883.stderr
index 47ccef9a530..cf079e4dda3 100644
--- a/tests/ui/lint/dead-code/issue-41883.stderr
+++ b/tests/ui/lint/dead-code/issue-41883.stderr
@@ -29,6 +29,8 @@ error: struct `UnusedStruct` is never constructed
    |
 LL |     struct UnusedStruct;
    |            ^^^^^^^^^^^^
+   |
+   = note: `UnusedStruct` has a derived impl for the trait `Debug`, but this is intentionally ignored during dead code analysis
 
 error: aborting due to 4 previous errors
 
diff --git a/tests/ui/lint/dead-code/multiple-dead-codes-in-the-same-struct.stderr b/tests/ui/lint/dead-code/multiple-dead-codes-in-the-same-struct.stderr
index 25a7d96cb89..b992005318f 100644
--- a/tests/ui/lint/dead-code/multiple-dead-codes-in-the-same-struct.stderr
+++ b/tests/ui/lint/dead-code/multiple-dead-codes-in-the-same-struct.stderr
@@ -56,6 +56,8 @@ warning: struct `Foo` is never constructed
    |
 LL | struct Foo(usize, #[allow(unused)] usize);
    |        ^^^
+   |
+   = note: `Foo` has a derived impl for the trait `Debug`, but this is intentionally ignored during dead code analysis
 
 error: aborting due to 2 previous errors; 2 warnings emitted
 
diff --git a/tests/ui/lint/dead-code/trait-only-used-as-type-bound.rs b/tests/ui/lint/dead-code/trait-only-used-as-type-bound.rs
new file mode 100644
index 00000000000..fb994653e1b
--- /dev/null
+++ b/tests/ui/lint/dead-code/trait-only-used-as-type-bound.rs
@@ -0,0 +1,31 @@
+//@ check-pass
+
+#![deny(dead_code)]
+
+trait UInt: Copy + From<u8> {}
+
+impl UInt for u16 {}
+
+trait Int: Copy {
+    type Unsigned: UInt;
+
+    fn as_unsigned(self) -> Self::Unsigned;
+}
+
+impl Int for i16 {
+    type Unsigned = u16;
+
+    fn as_unsigned(self) -> u16 {
+        self as _
+    }
+}
+
+fn priv_func<T: Int>(x: u8, y: T) -> (T::Unsigned, T::Unsigned) {
+    (T::Unsigned::from(x), y.as_unsigned())
+}
+
+pub fn pub_func(x: u8, y: i16) -> (u16, u16) {
+    priv_func(x, y)
+}
+
+fn main() {}
diff --git a/tests/ui/lint/lint-ctypes-enum.rs b/tests/ui/lint/lint-ctypes-enum.rs
index b2ef27b833b..612da86c956 100644
--- a/tests/ui/lint/lint-ctypes-enum.rs
+++ b/tests/ui/lint/lint-ctypes-enum.rs
@@ -2,8 +2,6 @@
 #![deny(improper_ctypes)]
 #![feature(ptr_internals)]
 #![feature(transparent_unions)]
-#![feature(repr128)]
-#![allow(incomplete_features)]
 
 use std::num;
 
diff --git a/tests/ui/lint/lint-ctypes-enum.stderr b/tests/ui/lint/lint-ctypes-enum.stderr
index d5fc844f756..50a6f526f26 100644
--- a/tests/ui/lint/lint-ctypes-enum.stderr
+++ b/tests/ui/lint/lint-ctypes-enum.stderr
@@ -1,5 +1,5 @@
 error: `extern` block uses type `U`, which is not FFI-safe
-  --> $DIR/lint-ctypes-enum.rs:84:14
+  --> $DIR/lint-ctypes-enum.rs:82:14
    |
 LL |     fn uf(x: U);
    |              ^ not FFI-safe
@@ -7,7 +7,7 @@ LL |     fn uf(x: U);
    = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
    = note: enum has no representation hint
 note: the type is defined here
-  --> $DIR/lint-ctypes-enum.rs:11:1
+  --> $DIR/lint-ctypes-enum.rs:9:1
    |
 LL | enum U {
    | ^^^^^^
@@ -18,7 +18,7 @@ LL | #![deny(improper_ctypes)]
    |         ^^^^^^^^^^^^^^^
 
 error: `extern` block uses type `B`, which is not FFI-safe
-  --> $DIR/lint-ctypes-enum.rs:85:14
+  --> $DIR/lint-ctypes-enum.rs:83:14
    |
 LL |     fn bf(x: B);
    |              ^ not FFI-safe
@@ -26,13 +26,13 @@ LL |     fn bf(x: B);
    = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
    = note: enum has no representation hint
 note: the type is defined here
-  --> $DIR/lint-ctypes-enum.rs:14:1
+  --> $DIR/lint-ctypes-enum.rs:12:1
    |
 LL | enum B {
    | ^^^^^^
 
 error: `extern` block uses type `T`, which is not FFI-safe
-  --> $DIR/lint-ctypes-enum.rs:86:14
+  --> $DIR/lint-ctypes-enum.rs:84:14
    |
 LL |     fn tf(x: T);
    |              ^ not FFI-safe
@@ -40,39 +40,39 @@ LL |     fn tf(x: T);
    = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
    = note: enum has no representation hint
 note: the type is defined here
-  --> $DIR/lint-ctypes-enum.rs:18:1
+  --> $DIR/lint-ctypes-enum.rs:16:1
    |
 LL | enum T {
    | ^^^^^^
 
 error: `extern` block uses type `U128`, which is not FFI-safe
-  --> $DIR/lint-ctypes-enum.rs:90:21
+  --> $DIR/lint-ctypes-enum.rs:88:21
    |
 LL |     fn repr_u128(x: U128);
    |                     ^^^^ not FFI-safe
    |
    = note: 128-bit integers don't currently have a known stable ABI
 note: the type is defined here
-  --> $DIR/lint-ctypes-enum.rs:46:1
+  --> $DIR/lint-ctypes-enum.rs:44:1
    |
 LL | enum U128 {
    | ^^^^^^^^^
 
 error: `extern` block uses type `I128`, which is not FFI-safe
-  --> $DIR/lint-ctypes-enum.rs:91:21
+  --> $DIR/lint-ctypes-enum.rs:89:21
    |
 LL |     fn repr_i128(x: I128);
    |                     ^^^^ not FFI-safe
    |
    = note: 128-bit integers don't currently have a known stable ABI
 note: the type is defined here
-  --> $DIR/lint-ctypes-enum.rs:53:1
+  --> $DIR/lint-ctypes-enum.rs:51:1
    |
 LL | enum I128 {
    | ^^^^^^^^^
 
 error: `extern` block uses type `u128`, which is not FFI-safe
-  --> $DIR/lint-ctypes-enum.rs:100:31
+  --> $DIR/lint-ctypes-enum.rs:98:31
    |
 LL |     fn option_nonzero_u128(x: Option<num::NonZero<u128>>);
    |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
@@ -80,7 +80,7 @@ LL |     fn option_nonzero_u128(x: Option<num::NonZero<u128>>);
    = note: 128-bit integers don't currently have a known stable ABI
 
 error: `extern` block uses type `i128`, which is not FFI-safe
-  --> $DIR/lint-ctypes-enum.rs:107:31
+  --> $DIR/lint-ctypes-enum.rs:105:31
    |
 LL |     fn option_nonzero_i128(x: Option<num::NonZero<i128>>);
    |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
@@ -88,7 +88,7 @@ LL |     fn option_nonzero_i128(x: Option<num::NonZero<i128>>);
    = note: 128-bit integers don't currently have a known stable ABI
 
 error: `extern` block uses type `Option<TransparentUnion<NonZero<u8>>>`, which is not FFI-safe
-  --> $DIR/lint-ctypes-enum.rs:112:36
+  --> $DIR/lint-ctypes-enum.rs:110:36
    |
 LL |     fn option_transparent_union(x: Option<TransparentUnion<num::NonZero<u8>>>);
    |                                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
@@ -97,7 +97,7 @@ LL |     fn option_transparent_union(x: Option<TransparentUnion<num::NonZero<u8>
    = note: enum has no representation hint
 
 error: `extern` block uses type `Option<Rust<NonZero<u8>>>`, which is not FFI-safe
-  --> $DIR/lint-ctypes-enum.rs:114:28
+  --> $DIR/lint-ctypes-enum.rs:112:28
    |
 LL |     fn option_repr_rust(x: Option<Rust<num::NonZero<u8>>>);
    |                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
@@ -106,7 +106,7 @@ LL |     fn option_repr_rust(x: Option<Rust<num::NonZero<u8>>>);
    = note: enum has no representation hint
 
 error: `extern` block uses type `Option<u8>`, which is not FFI-safe
-  --> $DIR/lint-ctypes-enum.rs:115:21
+  --> $DIR/lint-ctypes-enum.rs:113:21
    |
 LL |     fn option_u8(x: Option<u8>);
    |                     ^^^^^^^^^^ not FFI-safe
@@ -115,7 +115,7 @@ LL |     fn option_u8(x: Option<u8>);
    = note: enum has no representation hint
 
 error: `extern` block uses type `u128`, which is not FFI-safe
-  --> $DIR/lint-ctypes-enum.rs:125:33
+  --> $DIR/lint-ctypes-enum.rs:123:33
    |
 LL |     fn result_nonzero_u128_t(x: Result<num::NonZero<u128>, ()>);
    |                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
@@ -123,7 +123,7 @@ LL |     fn result_nonzero_u128_t(x: Result<num::NonZero<u128>, ()>);
    = note: 128-bit integers don't currently have a known stable ABI
 
 error: `extern` block uses type `i128`, which is not FFI-safe
-  --> $DIR/lint-ctypes-enum.rs:132:33
+  --> $DIR/lint-ctypes-enum.rs:130:33
    |
 LL |     fn result_nonzero_i128_t(x: Result<num::NonZero<i128>, ()>);
    |                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
@@ -131,7 +131,7 @@ LL |     fn result_nonzero_i128_t(x: Result<num::NonZero<i128>, ()>);
    = note: 128-bit integers don't currently have a known stable ABI
 
 error: `extern` block uses type `Result<TransparentUnion<NonZero<u8>>, ()>`, which is not FFI-safe
-  --> $DIR/lint-ctypes-enum.rs:137:38
+  --> $DIR/lint-ctypes-enum.rs:135:38
    |
 LL |     fn result_transparent_union_t(x: Result<TransparentUnion<num::NonZero<u8>>, ()>);
    |                                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
@@ -140,7 +140,7 @@ LL |     fn result_transparent_union_t(x: Result<TransparentUnion<num::NonZero<u
    = note: enum has no representation hint
 
 error: `extern` block uses type `Result<Rust<NonZero<u8>>, ()>`, which is not FFI-safe
-  --> $DIR/lint-ctypes-enum.rs:139:30
+  --> $DIR/lint-ctypes-enum.rs:137:30
    |
 LL |     fn result_repr_rust_t(x: Result<Rust<num::NonZero<u8>>, ()>);
    |                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
@@ -149,7 +149,7 @@ LL |     fn result_repr_rust_t(x: Result<Rust<num::NonZero<u8>>, ()>);
    = note: enum has no representation hint
 
 error: `extern` block uses type `Result<NonZero<u8>, U>`, which is not FFI-safe
-  --> $DIR/lint-ctypes-enum.rs:143:51
+  --> $DIR/lint-ctypes-enum.rs:141:51
    |
 LL |     fn result_1zst_exhaustive_single_variant_t(x: Result<num::NonZero<u8>, U>);
    |                                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
@@ -158,7 +158,7 @@ LL |     fn result_1zst_exhaustive_single_variant_t(x: Result<num::NonZero<u8>,
    = note: enum has no representation hint
 
 error: `extern` block uses type `Result<NonZero<u8>, B>`, which is not FFI-safe
-  --> $DIR/lint-ctypes-enum.rs:145:53
+  --> $DIR/lint-ctypes-enum.rs:143:53
    |
 LL |     fn result_1zst_exhaustive_multiple_variant_t(x: Result<num::NonZero<u8>, B>);
    |                                                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
@@ -167,7 +167,7 @@ LL |     fn result_1zst_exhaustive_multiple_variant_t(x: Result<num::NonZero<u8>
    = note: enum has no representation hint
 
 error: `extern` block uses type `Result<NonZero<u8>, NonExhaustive>`, which is not FFI-safe
-  --> $DIR/lint-ctypes-enum.rs:147:51
+  --> $DIR/lint-ctypes-enum.rs:145:51
    |
 LL |     fn result_1zst_non_exhaustive_no_variant_t(x: Result<num::NonZero<u8>, NonExhaustive>);
    |                                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
@@ -176,7 +176,7 @@ LL |     fn result_1zst_non_exhaustive_no_variant_t(x: Result<num::NonZero<u8>,
    = note: enum has no representation hint
 
 error: `extern` block uses type `Result<NonZero<u8>, Field>`, which is not FFI-safe
-  --> $DIR/lint-ctypes-enum.rs:150:49
+  --> $DIR/lint-ctypes-enum.rs:148:49
    |
 LL |     fn result_1zst_exhaustive_single_field_t(x: Result<num::NonZero<u8>, Field>);
    |                                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
@@ -185,7 +185,7 @@ LL |     fn result_1zst_exhaustive_single_field_t(x: Result<num::NonZero<u8>, Fi
    = note: enum has no representation hint
 
 error: `extern` block uses type `Result<Result<(), NonZero<u8>>, ()>`, which is not FFI-safe
-  --> $DIR/lint-ctypes-enum.rs:152:30
+  --> $DIR/lint-ctypes-enum.rs:150:30
    |
 LL |     fn result_cascading_t(x: Result<Result<(), num::NonZero<u8>>, ()>);
    |                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
@@ -194,7 +194,7 @@ LL |     fn result_cascading_t(x: Result<Result<(), num::NonZero<u8>>, ()>);
    = note: enum has no representation hint
 
 error: `extern` block uses type `u128`, which is not FFI-safe
-  --> $DIR/lint-ctypes-enum.rs:163:33
+  --> $DIR/lint-ctypes-enum.rs:161:33
    |
 LL |     fn result_nonzero_u128_e(x: Result<(), num::NonZero<u128>>);
    |                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
@@ -202,7 +202,7 @@ LL |     fn result_nonzero_u128_e(x: Result<(), num::NonZero<u128>>);
    = note: 128-bit integers don't currently have a known stable ABI
 
 error: `extern` block uses type `i128`, which is not FFI-safe
-  --> $DIR/lint-ctypes-enum.rs:170:33
+  --> $DIR/lint-ctypes-enum.rs:168:33
    |
 LL |     fn result_nonzero_i128_e(x: Result<(), num::NonZero<i128>>);
    |                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
@@ -210,7 +210,7 @@ LL |     fn result_nonzero_i128_e(x: Result<(), num::NonZero<i128>>);
    = note: 128-bit integers don't currently have a known stable ABI
 
 error: `extern` block uses type `Result<(), TransparentUnion<NonZero<u8>>>`, which is not FFI-safe
-  --> $DIR/lint-ctypes-enum.rs:175:38
+  --> $DIR/lint-ctypes-enum.rs:173:38
    |
 LL |     fn result_transparent_union_e(x: Result<(), TransparentUnion<num::NonZero<u8>>>);
    |                                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
@@ -219,7 +219,7 @@ LL |     fn result_transparent_union_e(x: Result<(), TransparentUnion<num::NonZe
    = note: enum has no representation hint
 
 error: `extern` block uses type `Result<(), Rust<NonZero<u8>>>`, which is not FFI-safe
-  --> $DIR/lint-ctypes-enum.rs:177:30
+  --> $DIR/lint-ctypes-enum.rs:175:30
    |
 LL |     fn result_repr_rust_e(x: Result<(), Rust<num::NonZero<u8>>>);
    |                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
@@ -228,7 +228,7 @@ LL |     fn result_repr_rust_e(x: Result<(), Rust<num::NonZero<u8>>>);
    = note: enum has no representation hint
 
 error: `extern` block uses type `Result<U, NonZero<u8>>`, which is not FFI-safe
-  --> $DIR/lint-ctypes-enum.rs:181:51
+  --> $DIR/lint-ctypes-enum.rs:179:51
    |
 LL |     fn result_1zst_exhaustive_single_variant_e(x: Result<U, num::NonZero<u8>>);
    |                                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
@@ -237,7 +237,7 @@ LL |     fn result_1zst_exhaustive_single_variant_e(x: Result<U, num::NonZero<u8
    = note: enum has no representation hint
 
 error: `extern` block uses type `Result<B, NonZero<u8>>`, which is not FFI-safe
-  --> $DIR/lint-ctypes-enum.rs:183:53
+  --> $DIR/lint-ctypes-enum.rs:181:53
    |
 LL |     fn result_1zst_exhaustive_multiple_variant_e(x: Result<B, num::NonZero<u8>>);
    |                                                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
@@ -246,7 +246,7 @@ LL |     fn result_1zst_exhaustive_multiple_variant_e(x: Result<B, num::NonZero<
    = note: enum has no representation hint
 
 error: `extern` block uses type `Result<NonExhaustive, NonZero<u8>>`, which is not FFI-safe
-  --> $DIR/lint-ctypes-enum.rs:185:51
+  --> $DIR/lint-ctypes-enum.rs:183:51
    |
 LL |     fn result_1zst_non_exhaustive_no_variant_e(x: Result<NonExhaustive, num::NonZero<u8>>);
    |                                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
@@ -255,7 +255,7 @@ LL |     fn result_1zst_non_exhaustive_no_variant_e(x: Result<NonExhaustive, num
    = note: enum has no representation hint
 
 error: `extern` block uses type `Result<Field, NonZero<u8>>`, which is not FFI-safe
-  --> $DIR/lint-ctypes-enum.rs:188:49
+  --> $DIR/lint-ctypes-enum.rs:186:49
    |
 LL |     fn result_1zst_exhaustive_single_field_e(x: Result<Field, num::NonZero<u8>>);
    |                                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
@@ -264,7 +264,7 @@ LL |     fn result_1zst_exhaustive_single_field_e(x: Result<Field, num::NonZero<
    = note: enum has no representation hint
 
 error: `extern` block uses type `Result<(), Result<(), NonZero<u8>>>`, which is not FFI-safe
-  --> $DIR/lint-ctypes-enum.rs:190:30
+  --> $DIR/lint-ctypes-enum.rs:188:30
    |
 LL |     fn result_cascading_e(x: Result<(), Result<(), num::NonZero<u8>>>);
    |                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
@@ -273,7 +273,7 @@ LL |     fn result_cascading_e(x: Result<(), Result<(), num::NonZero<u8>>>);
    = note: enum has no representation hint
 
 error: `extern` block uses type `Result<(), ()>`, which is not FFI-safe
-  --> $DIR/lint-ctypes-enum.rs:192:27
+  --> $DIR/lint-ctypes-enum.rs:190:27
    |
 LL |     fn result_unit_t_e(x: Result<(), ()>);
    |                           ^^^^^^^^^^^^^^ not FFI-safe
diff --git a/tests/ui/big-literals.rs b/tests/ui/lint/overflowing-literals-valid.rs
index d2f447a595c..08aa092ee71 100644
--- a/tests/ui/big-literals.rs
+++ b/tests/ui/lint/overflowing-literals-valid.rs
@@ -1,5 +1,7 @@
+//! Test that valid large numeric literals do not trigger the `overflowing_literals` lint.
+
 //@ run-pass
-// Catch mistakes in the overflowing literals lint.
+
 #![deny(overflowing_literals)]
 
 pub fn main() {
diff --git a/tests/ui/lint/unnecessary-extern-crate.stderr b/tests/ui/lint/unnecessary-extern-crate.stderr
index 1fa4aa9c9a9..db5406bc567 100644
--- a/tests/ui/lint/unnecessary-extern-crate.stderr
+++ b/tests/ui/lint/unnecessary-extern-crate.stderr
@@ -2,43 +2,72 @@ error: unused extern crate
   --> $DIR/unnecessary-extern-crate.rs:6:1
    |
 LL | extern crate core;
-   | ^^^^^^^^^^^^^^^^^^ help: remove it
+   | ^^^^^^^^^^^^^^^^^^ unused
    |
 note: the lint level is defined here
   --> $DIR/unnecessary-extern-crate.rs:3:9
    |
 LL | #![deny(unused_extern_crates)]
    |         ^^^^^^^^^^^^^^^^^^^^
+help: remove the unused `extern crate`
+   |
+LL - extern crate core;
+   |
 
 error: unused extern crate
   --> $DIR/unnecessary-extern-crate.rs:9:1
    |
 LL | extern crate core as x;
-   | ^^^^^^^^^^^^^^^^^^^^^^^ help: remove it
+   | ^^^^^^^^^^^^^^^^^^^^^^^ unused
+   |
+help: remove the unused `extern crate`
+   |
+LL - extern crate core as x;
+   |
 
 error: unused extern crate
   --> $DIR/unnecessary-extern-crate.rs:31:5
    |
 LL |     extern crate core;
-   |     ^^^^^^^^^^^^^^^^^^ help: remove it
+   |     ^^^^^^^^^^^^^^^^^^ unused
+   |
+help: remove the unused `extern crate`
+   |
+LL -     extern crate core;
+   |
 
 error: unused extern crate
   --> $DIR/unnecessary-extern-crate.rs:35:5
    |
 LL |     extern crate core as x;
-   |     ^^^^^^^^^^^^^^^^^^^^^^^ help: remove it
+   |     ^^^^^^^^^^^^^^^^^^^^^^^ unused
+   |
+help: remove the unused `extern crate`
+   |
+LL -     extern crate core as x;
+   |
 
 error: unused extern crate
   --> $DIR/unnecessary-extern-crate.rs:44:9
    |
 LL |         extern crate core;
-   |         ^^^^^^^^^^^^^^^^^^ help: remove it
+   |         ^^^^^^^^^^^^^^^^^^ unused
+   |
+help: remove the unused `extern crate`
+   |
+LL -         extern crate core;
+   |
 
 error: unused extern crate
   --> $DIR/unnecessary-extern-crate.rs:48:9
    |
 LL |         extern crate core as x;
-   |         ^^^^^^^^^^^^^^^^^^^^^^^ help: remove it
+   |         ^^^^^^^^^^^^^^^^^^^^^^^ unused
+   |
+help: remove the unused `extern crate`
+   |
+LL -         extern crate core as x;
+   |
 
 error: aborting due to 6 previous errors
 
diff --git a/tests/ui/lint/unused/lint-unused-extern-crate.stderr b/tests/ui/lint/unused/lint-unused-extern-crate.stderr
index 46d8f3beeab..7fcbdd813ce 100644
--- a/tests/ui/lint/unused/lint-unused-extern-crate.stderr
+++ b/tests/ui/lint/unused/lint-unused-extern-crate.stderr
@@ -2,19 +2,30 @@ error: unused extern crate
   --> $DIR/lint-unused-extern-crate.rs:11:1
    |
 LL | extern crate lint_unused_extern_crate5;
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove it
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unused
    |
 note: the lint level is defined here
   --> $DIR/lint-unused-extern-crate.rs:7:9
    |
 LL | #![deny(unused_extern_crates)]
    |         ^^^^^^^^^^^^^^^^^^^^
+help: remove the unused `extern crate`
+   |
+LL - extern crate lint_unused_extern_crate5;
+LL +
+   |
 
 error: unused extern crate
   --> $DIR/lint-unused-extern-crate.rs:29:5
    |
 LL |     extern crate lint_unused_extern_crate2;
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove it
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unused
+   |
+help: remove the unused `extern crate`
+   |
+LL -     extern crate lint_unused_extern_crate2;
+LL +
+   |
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/lint/unused/unused-braces-attrs-issue-141549.fixed b/tests/ui/lint/unused/unused-braces-attrs-issue-141549.fixed
new file mode 100644
index 00000000000..6129da30676
--- /dev/null
+++ b/tests/ui/lint/unused/unused-braces-attrs-issue-141549.fixed
@@ -0,0 +1,15 @@
+//@ check-pass
+//@ run-rustfix
+
+#![allow(dead_code)]
+#![warn(unused_braces)]
+
+use std::cmp::Ordering;
+
+#[rustfmt::skip]
+fn ptr_cmp<T: ?Sized>(p1: *const T, p2: *const T) -> Ordering {
+    #[expect(ambiguous_wide_pointer_comparisons)] p1.cmp(&p2)
+    //~^ WARN unnecessary braces around block return value
+}
+
+fn main() {}
diff --git a/tests/ui/lint/unused/unused-braces-attrs-issue-141549.rs b/tests/ui/lint/unused/unused-braces-attrs-issue-141549.rs
new file mode 100644
index 00000000000..a550ebc4973
--- /dev/null
+++ b/tests/ui/lint/unused/unused-braces-attrs-issue-141549.rs
@@ -0,0 +1,15 @@
+//@ check-pass
+//@ run-rustfix
+
+#![allow(dead_code)]
+#![warn(unused_braces)]
+
+use std::cmp::Ordering;
+
+#[rustfmt::skip]
+fn ptr_cmp<T: ?Sized>(p1: *const T, p2: *const T) -> Ordering {
+    { #[expect(ambiguous_wide_pointer_comparisons)] p1.cmp(&p2) }
+    //~^ WARN unnecessary braces around block return value
+}
+
+fn main() {}
diff --git a/tests/ui/lint/unused/unused-braces-attrs-issue-141549.stderr b/tests/ui/lint/unused/unused-braces-attrs-issue-141549.stderr
new file mode 100644
index 00000000000..0b2b6211ab9
--- /dev/null
+++ b/tests/ui/lint/unused/unused-braces-attrs-issue-141549.stderr
@@ -0,0 +1,19 @@
+warning: unnecessary braces around block return value
+  --> $DIR/unused-braces-attrs-issue-141549.rs:11:5
+   |
+LL |     { #[expect(ambiguous_wide_pointer_comparisons)] p1.cmp(&p2) }
+   |     ^^                                                         ^^
+   |
+note: the lint level is defined here
+  --> $DIR/unused-braces-attrs-issue-141549.rs:5:9
+   |
+LL | #![warn(unused_braces)]
+   |         ^^^^^^^^^^^^^
+help: remove these braces
+   |
+LL -     { #[expect(ambiguous_wide_pointer_comparisons)] p1.cmp(&p2) }
+LL +     #[expect(ambiguous_wide_pointer_comparisons)] p1.cmp(&p2)
+   |
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/lint/wide_pointer_comparisons.stderr b/tests/ui/lint/wide_pointer_comparisons.stderr
index 5a0b914d832..4f5238e8252 100644
--- a/tests/ui/lint/wide_pointer_comparisons.stderr
+++ b/tests/ui/lint/wide_pointer_comparisons.stderr
@@ -29,10 +29,14 @@ warning: ambiguous wide pointer comparison, the comparison includes metadata whi
 LL |     let _ = a < b;
    |             ^^^^^
    |
-help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses
+help: use untyped pointers to only compare their addresses
    |
 LL |     let _ = a.cast::<()>() < b.cast::<()>();
    |              +++++++++++++    +++++++++++++
+help: or expect the lint to compare the pointers metadata and addresses
+   |
+LL |     let _ = { #[expect(ambiguous_wide_pointer_comparisons, reason = "...")] (a < b) };
+   |             +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++     +++
 
 warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected
   --> $DIR/wide_pointer_comparisons.rs:26:13
@@ -40,10 +44,14 @@ warning: ambiguous wide pointer comparison, the comparison includes metadata whi
 LL |     let _ = a <= b;
    |             ^^^^^^
    |
-help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses
+help: use untyped pointers to only compare their addresses
    |
 LL |     let _ = a.cast::<()>() <= b.cast::<()>();
    |              +++++++++++++     +++++++++++++
+help: or expect the lint to compare the pointers metadata and addresses
+   |
+LL |     let _ = { #[expect(ambiguous_wide_pointer_comparisons, reason = "...")] (a <= b) };
+   |             +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++      +++
 
 warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected
   --> $DIR/wide_pointer_comparisons.rs:28:13
@@ -51,10 +59,14 @@ warning: ambiguous wide pointer comparison, the comparison includes metadata whi
 LL |     let _ = a > b;
    |             ^^^^^
    |
-help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses
+help: use untyped pointers to only compare their addresses
    |
 LL |     let _ = a.cast::<()>() > b.cast::<()>();
    |              +++++++++++++    +++++++++++++
+help: or expect the lint to compare the pointers metadata and addresses
+   |
+LL |     let _ = { #[expect(ambiguous_wide_pointer_comparisons, reason = "...")] (a > b) };
+   |             +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++     +++
 
 warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected
   --> $DIR/wide_pointer_comparisons.rs:30:13
@@ -62,10 +74,14 @@ warning: ambiguous wide pointer comparison, the comparison includes metadata whi
 LL |     let _ = a >= b;
    |             ^^^^^^
    |
-help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses
+help: use untyped pointers to only compare their addresses
    |
 LL |     let _ = a.cast::<()>() >= b.cast::<()>();
    |              +++++++++++++     +++++++++++++
+help: or expect the lint to compare the pointers metadata and addresses
+   |
+LL |     let _ = { #[expect(ambiguous_wide_pointer_comparisons, reason = "...")] (a >= b) };
+   |             +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++      +++
 
 warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected
   --> $DIR/wide_pointer_comparisons.rs:33:13
@@ -121,10 +137,14 @@ warning: ambiguous wide pointer comparison, the comparison includes metadata whi
 LL |     let _ = a.cmp(&b);
    |             ^^^^^^^^^
    |
-help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses
+help: use untyped pointers to only compare their addresses
    |
 LL |     let _ = a.cast::<()>().cmp(&b.cast::<()>());
    |              +++++++++++++       +++++++++++++
+help: or expect the lint to compare the pointers metadata and addresses
+   |
+LL |     let _ = { #[expect(ambiguous_wide_pointer_comparisons, reason = "...")] a.cmp(&b) };
+   |             +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++           +
 
 warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected
   --> $DIR/wide_pointer_comparisons.rs:43:13
@@ -132,10 +152,14 @@ warning: ambiguous wide pointer comparison, the comparison includes metadata whi
 LL |     let _ = a.partial_cmp(&b);
    |             ^^^^^^^^^^^^^^^^^
    |
-help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses
+help: use untyped pointers to only compare their addresses
    |
 LL |     let _ = a.cast::<()>().partial_cmp(&b.cast::<()>());
    |              +++++++++++++               +++++++++++++
+help: or expect the lint to compare the pointers metadata and addresses
+   |
+LL |     let _ = { #[expect(ambiguous_wide_pointer_comparisons, reason = "...")] a.partial_cmp(&b) };
+   |             +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++                   +
 
 warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected
   --> $DIR/wide_pointer_comparisons.rs:45:13
@@ -143,10 +167,14 @@ warning: ambiguous wide pointer comparison, the comparison includes metadata whi
 LL |     let _ = a.le(&b);
    |             ^^^^^^^^
    |
-help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses
+help: use untyped pointers to only compare their addresses
    |
 LL |     let _ = a.cast::<()>().le(&b.cast::<()>());
    |              +++++++++++++      +++++++++++++
+help: or expect the lint to compare the pointers metadata and addresses
+   |
+LL |     let _ = { #[expect(ambiguous_wide_pointer_comparisons, reason = "...")] a.le(&b) };
+   |             +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++          +
 
 warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected
   --> $DIR/wide_pointer_comparisons.rs:47:13
@@ -154,10 +182,14 @@ warning: ambiguous wide pointer comparison, the comparison includes metadata whi
 LL |     let _ = a.lt(&b);
    |             ^^^^^^^^
    |
-help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses
+help: use untyped pointers to only compare their addresses
    |
 LL |     let _ = a.cast::<()>().lt(&b.cast::<()>());
    |              +++++++++++++      +++++++++++++
+help: or expect the lint to compare the pointers metadata and addresses
+   |
+LL |     let _ = { #[expect(ambiguous_wide_pointer_comparisons, reason = "...")] a.lt(&b) };
+   |             +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++          +
 
 warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected
   --> $DIR/wide_pointer_comparisons.rs:49:13
@@ -165,10 +197,14 @@ warning: ambiguous wide pointer comparison, the comparison includes metadata whi
 LL |     let _ = a.ge(&b);
    |             ^^^^^^^^
    |
-help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses
+help: use untyped pointers to only compare their addresses
    |
 LL |     let _ = a.cast::<()>().ge(&b.cast::<()>());
    |              +++++++++++++      +++++++++++++
+help: or expect the lint to compare the pointers metadata and addresses
+   |
+LL |     let _ = { #[expect(ambiguous_wide_pointer_comparisons, reason = "...")] a.ge(&b) };
+   |             +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++          +
 
 warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected
   --> $DIR/wide_pointer_comparisons.rs:51:13
@@ -176,10 +212,14 @@ warning: ambiguous wide pointer comparison, the comparison includes metadata whi
 LL |     let _ = a.gt(&b);
    |             ^^^^^^^^
    |
-help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses
+help: use untyped pointers to only compare their addresses
    |
 LL |     let _ = a.cast::<()>().gt(&b.cast::<()>());
    |              +++++++++++++      +++++++++++++
+help: or expect the lint to compare the pointers metadata and addresses
+   |
+LL |     let _ = { #[expect(ambiguous_wide_pointer_comparisons, reason = "...")] a.gt(&b) };
+   |             +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++          +
 
 warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected
   --> $DIR/wide_pointer_comparisons.rs:57:17
@@ -199,10 +239,14 @@ warning: ambiguous wide pointer comparison, the comparison includes metadata whi
 LL |         let _ = a >= b;
    |                 ^^^^^^
    |
-help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses
+help: use untyped pointers to only compare their addresses
    |
 LL |         let _ = a.as_ptr().cast::<()>() >= b.as_ptr().cast::<()>();
    |                  ++++++++++++++++++++++     ++++++++++++++++++++++
+help: or expect the lint to compare the pointers metadata and addresses
+   |
+LL |         let _ = { #[expect(ambiguous_wide_pointer_comparisons, reason = "...")] (a >= b) };
+   |                 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++      +++
 
 warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected
   --> $DIR/wide_pointer_comparisons.rs:61:17
@@ -246,10 +290,14 @@ warning: ambiguous wide pointer comparison, the comparison includes metadata whi
 LL |         let _ = a < b;
    |                 ^^^^^
    |
-help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses
+help: use untyped pointers to only compare their addresses
    |
 LL |         let _ = (*a).cast::<()>() < (*b).cast::<()>();
    |                 ++ ++++++++++++++   ++ ++++++++++++++
+help: or expect the lint to compare the pointers metadata and addresses
+   |
+LL |         let _ = { #[expect(ambiguous_wide_pointer_comparisons, reason = "...")] (a < b) };
+   |                 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++     +++
 
 warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected
   --> $DIR/wide_pointer_comparisons.rs:76:17
@@ -257,10 +305,14 @@ warning: ambiguous wide pointer comparison, the comparison includes metadata whi
 LL |         let _ = a <= b;
    |                 ^^^^^^
    |
-help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses
+help: use untyped pointers to only compare their addresses
    |
 LL |         let _ = (*a).cast::<()>() <= (*b).cast::<()>();
    |                 ++ ++++++++++++++    ++ ++++++++++++++
+help: or expect the lint to compare the pointers metadata and addresses
+   |
+LL |         let _ = { #[expect(ambiguous_wide_pointer_comparisons, reason = "...")] (a <= b) };
+   |                 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++      +++
 
 warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected
   --> $DIR/wide_pointer_comparisons.rs:78:17
@@ -268,10 +320,14 @@ warning: ambiguous wide pointer comparison, the comparison includes metadata whi
 LL |         let _ = a > b;
    |                 ^^^^^
    |
-help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses
+help: use untyped pointers to only compare their addresses
    |
 LL |         let _ = (*a).cast::<()>() > (*b).cast::<()>();
    |                 ++ ++++++++++++++   ++ ++++++++++++++
+help: or expect the lint to compare the pointers metadata and addresses
+   |
+LL |         let _ = { #[expect(ambiguous_wide_pointer_comparisons, reason = "...")] (a > b) };
+   |                 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++     +++
 
 warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected
   --> $DIR/wide_pointer_comparisons.rs:80:17
@@ -279,10 +335,14 @@ warning: ambiguous wide pointer comparison, the comparison includes metadata whi
 LL |         let _ = a >= b;
    |                 ^^^^^^
    |
-help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses
+help: use untyped pointers to only compare their addresses
    |
 LL |         let _ = (*a).cast::<()>() >= (*b).cast::<()>();
    |                 ++ ++++++++++++++    ++ ++++++++++++++
+help: or expect the lint to compare the pointers metadata and addresses
+   |
+LL |         let _ = { #[expect(ambiguous_wide_pointer_comparisons, reason = "...")] (a >= b) };
+   |                 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++      +++
 
 warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected
   --> $DIR/wide_pointer_comparisons.rs:83:17
@@ -362,10 +422,14 @@ warning: ambiguous wide pointer comparison, the comparison includes metadata whi
 LL |         let _ = a.cmp(&b);
    |                 ^^^^^^^^^
    |
-help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses
+help: use untyped pointers to only compare their addresses
    |
 LL |         let _ = (*a).cast::<()>().cmp(&(*b).cast::<()>());
    |                 ++ ++++++++++++++      ++ ++++++++++++++
+help: or expect the lint to compare the pointers metadata and addresses
+   |
+LL |         let _ = { #[expect(ambiguous_wide_pointer_comparisons, reason = "...")] a.cmp(&b) };
+   |                 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++           +
 
 warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected
   --> $DIR/wide_pointer_comparisons.rs:97:17
@@ -373,10 +437,14 @@ warning: ambiguous wide pointer comparison, the comparison includes metadata whi
 LL |         let _ = a.partial_cmp(&b);
    |                 ^^^^^^^^^^^^^^^^^
    |
-help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses
+help: use untyped pointers to only compare their addresses
    |
 LL |         let _ = (*a).cast::<()>().partial_cmp(&(*b).cast::<()>());
    |                 ++ ++++++++++++++              ++ ++++++++++++++
+help: or expect the lint to compare the pointers metadata and addresses
+   |
+LL |         let _ = { #[expect(ambiguous_wide_pointer_comparisons, reason = "...")] a.partial_cmp(&b) };
+   |                 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++                   +
 
 warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected
   --> $DIR/wide_pointer_comparisons.rs:99:17
@@ -384,10 +452,14 @@ warning: ambiguous wide pointer comparison, the comparison includes metadata whi
 LL |         let _ = a.le(&b);
    |                 ^^^^^^^^
    |
-help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses
+help: use untyped pointers to only compare their addresses
    |
 LL |         let _ = (*a).cast::<()>().le(&(*b).cast::<()>());
    |                 ++ ++++++++++++++     ++ ++++++++++++++
+help: or expect the lint to compare the pointers metadata and addresses
+   |
+LL |         let _ = { #[expect(ambiguous_wide_pointer_comparisons, reason = "...")] a.le(&b) };
+   |                 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++          +
 
 warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected
   --> $DIR/wide_pointer_comparisons.rs:101:17
@@ -395,10 +467,14 @@ warning: ambiguous wide pointer comparison, the comparison includes metadata whi
 LL |         let _ = a.lt(&b);
    |                 ^^^^^^^^
    |
-help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses
+help: use untyped pointers to only compare their addresses
    |
 LL |         let _ = (*a).cast::<()>().lt(&(*b).cast::<()>());
    |                 ++ ++++++++++++++     ++ ++++++++++++++
+help: or expect the lint to compare the pointers metadata and addresses
+   |
+LL |         let _ = { #[expect(ambiguous_wide_pointer_comparisons, reason = "...")] a.lt(&b) };
+   |                 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++          +
 
 warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected
   --> $DIR/wide_pointer_comparisons.rs:103:17
@@ -406,10 +482,14 @@ warning: ambiguous wide pointer comparison, the comparison includes metadata whi
 LL |         let _ = a.ge(&b);
    |                 ^^^^^^^^
    |
-help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses
+help: use untyped pointers to only compare their addresses
    |
 LL |         let _ = (*a).cast::<()>().ge(&(*b).cast::<()>());
    |                 ++ ++++++++++++++     ++ ++++++++++++++
+help: or expect the lint to compare the pointers metadata and addresses
+   |
+LL |         let _ = { #[expect(ambiguous_wide_pointer_comparisons, reason = "...")] a.ge(&b) };
+   |                 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++          +
 
 warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected
   --> $DIR/wide_pointer_comparisons.rs:105:17
@@ -417,10 +497,14 @@ warning: ambiguous wide pointer comparison, the comparison includes metadata whi
 LL |         let _ = a.gt(&b);
    |                 ^^^^^^^^
    |
-help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses
+help: use untyped pointers to only compare their addresses
    |
 LL |         let _ = (*a).cast::<()>().gt(&(*b).cast::<()>());
    |                 ++ ++++++++++++++     ++ ++++++++++++++
+help: or expect the lint to compare the pointers metadata and addresses
+   |
+LL |         let _ = { #[expect(ambiguous_wide_pointer_comparisons, reason = "...")] a.gt(&b) };
+   |                 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++          +
 
 warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected
   --> $DIR/wide_pointer_comparisons.rs:110:13
@@ -496,10 +580,14 @@ warning: ambiguous wide pointer comparison, the comparison includes metadata whi
 LL |         let _ = a < b;
    |                 ^^^^^
    |
-help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses
+help: use untyped pointers to only compare their addresses
    |
 LL |         let _ = a.cast::<()>() < b.cast::<()>();
    |                  +++++++++++++    +++++++++++++
+help: or expect the lint to compare the pointers metadata and addresses
+   |
+LL |         let _ = { #[expect(ambiguous_wide_pointer_comparisons, reason = "...")] (a < b) };
+   |                 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++     +++
 
 warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected
   --> $DIR/wide_pointer_comparisons.rs:124:17
@@ -507,10 +595,14 @@ warning: ambiguous wide pointer comparison, the comparison includes metadata whi
 LL |         let _ = a <= b;
    |                 ^^^^^^
    |
-help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses
+help: use untyped pointers to only compare their addresses
    |
 LL |         let _ = a.cast::<()>() <= b.cast::<()>();
    |                  +++++++++++++     +++++++++++++
+help: or expect the lint to compare the pointers metadata and addresses
+   |
+LL |         let _ = { #[expect(ambiguous_wide_pointer_comparisons, reason = "...")] (a <= b) };
+   |                 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++      +++
 
 warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected
   --> $DIR/wide_pointer_comparisons.rs:126:17
@@ -518,10 +610,14 @@ warning: ambiguous wide pointer comparison, the comparison includes metadata whi
 LL |         let _ = a > b;
    |                 ^^^^^
    |
-help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses
+help: use untyped pointers to only compare their addresses
    |
 LL |         let _ = a.cast::<()>() > b.cast::<()>();
    |                  +++++++++++++    +++++++++++++
+help: or expect the lint to compare the pointers metadata and addresses
+   |
+LL |         let _ = { #[expect(ambiguous_wide_pointer_comparisons, reason = "...")] (a > b) };
+   |                 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++     +++
 
 warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected
   --> $DIR/wide_pointer_comparisons.rs:128:17
@@ -529,10 +625,14 @@ warning: ambiguous wide pointer comparison, the comparison includes metadata whi
 LL |         let _ = a >= b;
    |                 ^^^^^^
    |
-help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses
+help: use untyped pointers to only compare their addresses
    |
 LL |         let _ = a.cast::<()>() >= b.cast::<()>();
    |                  +++++++++++++     +++++++++++++
+help: or expect the lint to compare the pointers metadata and addresses
+   |
+LL |         let _ = { #[expect(ambiguous_wide_pointer_comparisons, reason = "...")] (a >= b) };
+   |                 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++      +++
 
 warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected
   --> $DIR/wide_pointer_comparisons.rs:131:17
diff --git a/tests/ui/macros/auxiliary/borrowck-error-in-macro.rs b/tests/ui/macros/auxiliary/borrowck-error-in-macro.rs
new file mode 100644
index 00000000000..2d5f2bda2ed
--- /dev/null
+++ b/tests/ui/macros/auxiliary/borrowck-error-in-macro.rs
@@ -0,0 +1,10 @@
+#[macro_export]
+macro_rules! ice {
+    () => {
+        fn main() {
+            let d = &mut 0;
+            let c = || *d += 1;
+            c();
+        }
+    };
+}
diff --git a/tests/ui/macros/borrowck-error-in-macro.rs b/tests/ui/macros/borrowck-error-in-macro.rs
new file mode 100644
index 00000000000..fe75188efd2
--- /dev/null
+++ b/tests/ui/macros/borrowck-error-in-macro.rs
@@ -0,0 +1,8 @@
+//@ aux-build: borrowck-error-in-macro.rs
+//@ error-pattern: a call in this macro requires a mutable binding due to mutable borrow of `d`
+//FIXME: remove error-pattern (see #141896)
+
+extern crate borrowck_error_in_macro as a;
+
+a::ice! {}
+//~^ ERROR cannot borrow value as mutable, as it is not declared as mutable
diff --git a/tests/ui/macros/borrowck-error-in-macro.stderr b/tests/ui/macros/borrowck-error-in-macro.stderr
new file mode 100644
index 00000000000..ec0302ee287
--- /dev/null
+++ b/tests/ui/macros/borrowck-error-in-macro.stderr
@@ -0,0 +1,19 @@
+error[E0596]: cannot borrow value as mutable, as it is not declared as mutable
+  --> $DIR/borrowck-error-in-macro.rs:7:1
+   |
+LL | a::ice! {}
+   | ^^^^^^^^^^
+   | |
+   | cannot borrow as mutable
+   | a call in this macro requires a mutable binding due to mutable borrow of `d`
+   |
+   = note: this error originates in the macro `a::ice` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: consider changing this to be mutable
+  --> $DIR/auxiliary/borrowck-error-in-macro.rs:6:17
+   |
+LL |             let mut c = || *d += 1;
+   |                 +++
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0596`.
diff --git a/tests/ui/macros/ice-in-tokenstream-for-contracts-issue-140683.rs b/tests/ui/macros/ice-in-tokenstream-for-contracts-issue-140683.rs
new file mode 100644
index 00000000000..68346a00ae1
--- /dev/null
+++ b/tests/ui/macros/ice-in-tokenstream-for-contracts-issue-140683.rs
@@ -0,0 +1,13 @@
+#![feature(contracts)]
+#![allow(incomplete_features)]
+
+struct T;
+
+impl T {
+    #[core::contracts::ensures] //~ ERROR expected a `Fn(&_)` closure, found `()`
+    fn b() {(loop)}
+    //~^ ERROR expected `{`, found `)`
+    //~| ERROR expected `{`, found `)`
+}
+
+fn main() {}
diff --git a/tests/ui/macros/ice-in-tokenstream-for-contracts-issue-140683.stderr b/tests/ui/macros/ice-in-tokenstream-for-contracts-issue-140683.stderr
new file mode 100644
index 00000000000..f1ffda2a9be
--- /dev/null
+++ b/tests/ui/macros/ice-in-tokenstream-for-contracts-issue-140683.stderr
@@ -0,0 +1,34 @@
+error: expected `{`, found `)`
+  --> $DIR/ice-in-tokenstream-for-contracts-issue-140683.rs:8:18
+   |
+LL |     fn b() {(loop)}
+   |              ----^ expected `{`
+   |              |
+   |              while parsing this `loop` expression
+
+error: expected `{`, found `)`
+  --> $DIR/ice-in-tokenstream-for-contracts-issue-140683.rs:8:18
+   |
+LL |     fn b() {(loop)}
+   |              ----^ expected `{`
+   |              |
+   |              while parsing this `loop` expression
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+error[E0277]: expected a `Fn(&_)` closure, found `()`
+  --> $DIR/ice-in-tokenstream-for-contracts-issue-140683.rs:7:5
+   |
+LL |     #[core::contracts::ensures]
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |     |
+   |     expected an `Fn(&_)` closure, found `()`
+   |     required by a bound introduced by this call
+   |
+   = help: the trait `for<'a> Fn(&'a _)` is not implemented for `()`
+note: required by a bound in `build_check_ensures`
+  --> $SRC_DIR/core/src/contracts.rs:LL:COL
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/macros/no-close-delim-issue-139248.rs b/tests/ui/macros/no-close-delim-issue-139248.rs
index 86583b2724e..f15234eaff1 100644
--- a/tests/ui/macros/no-close-delim-issue-139248.rs
+++ b/tests/ui/macros/no-close-delim-issue-139248.rs
@@ -2,9 +2,8 @@
 
 macro_rules! m {
     (static a : () = $e:expr) => {
-        static a : () = $e;
-        //~^ ERROR macro expansion ends with an incomplete expression: expected expression
-    }
+        static a: () = $e;
+    };
 }
 
 m! { static a : () = (if b) }
diff --git a/tests/ui/macros/no-close-delim-issue-139248.stderr b/tests/ui/macros/no-close-delim-issue-139248.stderr
index 6ed41ae9b46..8aa39851b4b 100644
--- a/tests/ui/macros/no-close-delim-issue-139248.stderr
+++ b/tests/ui/macros/no-close-delim-issue-139248.stderr
@@ -1,33 +1,27 @@
 error: expected `{`, found `)`
-  --> $DIR/no-close-delim-issue-139248.rs:10:27
+  --> $DIR/no-close-delim-issue-139248.rs:9:27
    |
 LL | m! { static a : () = (if b) }
    |                           ^ expected `{`
    |
 note: the `if` expression is missing a block after this condition
-  --> $DIR/no-close-delim-issue-139248.rs:10:26
+  --> $DIR/no-close-delim-issue-139248.rs:9:26
    |
 LL | m! { static a : () = (if b) }
    |                          ^
 
 error: expected `{`, found `)`
-  --> $DIR/no-close-delim-issue-139248.rs:10:27
+  --> $DIR/no-close-delim-issue-139248.rs:9:27
    |
 LL | m! { static a : () = (if b) }
    |                           ^ expected `{`
    |
 note: the `if` expression is missing a block after this condition
-  --> $DIR/no-close-delim-issue-139248.rs:10:26
+  --> $DIR/no-close-delim-issue-139248.rs:9:26
    |
 LL | m! { static a : () = (if b) }
    |                          ^
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
-error: macro expansion ends with an incomplete expression: expected expression
-  --> $DIR/no-close-delim-issue-139248.rs:5:28
-   |
-LL |         static a : () = $e;
-   |                            ^ expected expression
-
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
 
diff --git a/tests/ui/auto-ref-slice-plus-ref.rs b/tests/ui/methods/vec-autoderef-autoref.rs
index 00b279d3226..38c0ba8574b 100644
--- a/tests/ui/auto-ref-slice-plus-ref.rs
+++ b/tests/ui/methods/vec-autoderef-autoref.rs
@@ -1,8 +1,7 @@
-fn main() {
-
-    // Testing that method lookup does not automatically borrow
-    // vectors to slices then automatically create a self reference.
+//! Test that method resolution does not autoderef `Vec`
+//! into a slice or perform additional autorefs.
 
+fn main() {
     let mut a = vec![0];
     a.test_mut(); //~ ERROR no method named `test_mut` found
     a.test(); //~ ERROR no method named `test` found
diff --git a/tests/ui/auto-ref-slice-plus-ref.stderr b/tests/ui/methods/vec-autoderef-autoref.stderr
index 806c1ee064f..61c3bcc5b3b 100644
--- a/tests/ui/auto-ref-slice-plus-ref.stderr
+++ b/tests/ui/methods/vec-autoderef-autoref.stderr
@@ -1,12 +1,12 @@
 error[E0599]: no method named `test_mut` found for struct `Vec<{integer}>` in the current scope
-  --> $DIR/auto-ref-slice-plus-ref.rs:7:7
+  --> $DIR/vec-autoderef-autoref.rs:6:7
    |
 LL |     a.test_mut();
    |       ^^^^^^^^
    |
    = help: items from traits can only be used if the trait is implemented and in scope
 note: `MyIter` defines an item `test_mut`, perhaps you need to implement it
-  --> $DIR/auto-ref-slice-plus-ref.rs:14:1
+  --> $DIR/vec-autoderef-autoref.rs:13:1
    |
 LL | trait MyIter {
    | ^^^^^^^^^^^^
@@ -14,40 +14,40 @@ help: there is a method `get_mut` with a similar name, but with different argume
   --> $SRC_DIR/core/src/slice/mod.rs:LL:COL
 
 error[E0599]: no method named `test` found for struct `Vec<{integer}>` in the current scope
-  --> $DIR/auto-ref-slice-plus-ref.rs:8:7
+  --> $DIR/vec-autoderef-autoref.rs:7:7
    |
 LL |     a.test();
    |       ^^^^ method not found in `Vec<{integer}>`
    |
    = help: items from traits can only be used if the trait is implemented and in scope
 note: `MyIter` defines an item `test`, perhaps you need to implement it
-  --> $DIR/auto-ref-slice-plus-ref.rs:14:1
+  --> $DIR/vec-autoderef-autoref.rs:13:1
    |
 LL | trait MyIter {
    | ^^^^^^^^^^^^
 
 error[E0599]: no method named `test` found for array `[{integer}; 1]` in the current scope
-  --> $DIR/auto-ref-slice-plus-ref.rs:10:11
+  --> $DIR/vec-autoderef-autoref.rs:9:11
    |
 LL |     ([1]).test();
    |           ^^^^ method not found in `[{integer}; 1]`
    |
    = help: items from traits can only be used if the trait is implemented and in scope
 note: `MyIter` defines an item `test`, perhaps you need to implement it
-  --> $DIR/auto-ref-slice-plus-ref.rs:14:1
+  --> $DIR/vec-autoderef-autoref.rs:13:1
    |
 LL | trait MyIter {
    | ^^^^^^^^^^^^
 
 error[E0599]: no method named `test` found for reference `&[{integer}; 1]` in the current scope
-  --> $DIR/auto-ref-slice-plus-ref.rs:11:12
+  --> $DIR/vec-autoderef-autoref.rs:10:12
    |
 LL |     (&[1]).test();
    |            ^^^^ method not found in `&[{integer}; 1]`
    |
    = help: items from traits can only be used if the trait is implemented and in scope
 note: `MyIter` defines an item `test`, perhaps you need to implement it
-  --> $DIR/auto-ref-slice-plus-ref.rs:14:1
+  --> $DIR/vec-autoderef-autoref.rs:13:1
    |
 LL | trait MyIter {
    | ^^^^^^^^^^^^
diff --git a/tests/ui/namespace/namespace-mix.stderr b/tests/ui/namespace/namespace-mix.stderr
index 412ea4aba30..200d31cc710 100644
--- a/tests/ui/namespace/namespace-mix.stderr
+++ b/tests/ui/namespace/namespace-mix.stderr
@@ -7,7 +7,6 @@ LL |     pub struct TS();
 LL |     check(m1::S);
    |           ^^^^^
    |
-   = note: can't use a type alias as a constructor
 help: a tuple struct with a similar name exists
    |
 LL |     check(m1::TS);
@@ -35,7 +34,6 @@ LL |     check(xm1::S);
 LL |     pub struct TS();
    |     ------------- similarly named tuple struct `TS` defined here
    |
-   = note: can't use a type alias as a constructor
 help: a tuple struct with a similar name exists
    |
 LL |     check(xm1::TS);
@@ -61,7 +59,6 @@ LL |         TV(),
 LL |     check(m7::V);
    |           ^^^^^
    |
-   = note: can't use a type alias as a constructor
 help: a tuple variant with a similar name exists
    |
 LL |     check(m7::TV);
@@ -89,7 +86,6 @@ LL |     check(xm7::V);
 LL |         TV(),
    |         -- similarly named tuple variant `TV` defined here
    |
-   = note: can't use a type alias as a constructor
 help: a tuple variant with a similar name exists
    |
 LL |     check(xm7::TV);
diff --git a/tests/ui/nll/user-annotations/normalizing-user-annotation.rs b/tests/ui/nll/user-annotations/normalizing-user-annotation.rs
new file mode 100644
index 00000000000..fa8b3bfd577
--- /dev/null
+++ b/tests/ui/nll/user-annotations/normalizing-user-annotation.rs
@@ -0,0 +1,31 @@
+//@ check-pass
+//@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
+//@[next] compile-flags: -Znext-solver
+
+// Regression test for <https://github.com/rust-lang/rust/issues/141708>.
+
+// See description in there; this has to do with fundamental limitations
+// to the old trait solver surrounding higher-ranked aliases with infer
+// vars. This always worked in the new trait solver, but I added a revision
+// just for good measure.
+
+trait Foo<'a> {
+    type Assoc;
+}
+
+impl Foo<'_> for i32 {
+    type Assoc = u32;
+}
+
+impl Foo<'_> for u32 {
+    type Assoc = u32;
+}
+
+fn foo<'b: 'b, T: for<'a> Foo<'a>, F: for<'a> Fn(<T as Foo<'a>>::Assoc)>(_: F) -> (T, F) {
+    todo!()
+}
+
+fn main() {
+    let (x, c): (i32, _) = foo::<'static, _, _>(|_| {});
+}
diff --git a/tests/ui/not-enough-arguments.rs b/tests/ui/not-enough-arguments.rs
index 4a2ea5e44c7..ec660a1de81 100644
--- a/tests/ui/not-enough-arguments.rs
+++ b/tests/ui/not-enough-arguments.rs
@@ -1,20 +1,16 @@
+//@ aux-build: delegate_macro.rs
+extern crate delegate_macro;
+use delegate_macro::delegate;
+
 // Check that the only error msg we report is the
 // mismatch between the # of params, and not other
 // unrelated errors.
-
-fn foo(a: isize, b: isize, c: isize, d:isize) {
-  panic!();
+fn foo(a: isize, b: isize, c: isize, d: isize) {
+    panic!();
 }
 
 // Check that all arguments are shown in the error message, even if they're across multiple lines.
-fn bar(
-    a: i32,
-    b: i32,
-    c: i32,
-    d: i32,
-    e: i32,
-    f: i32,
-) {
+fn bar(a: i32, b: i32, c: i32, d: i32, e: i32, f: i32) {
     println!("{}", a);
     println!("{}", b);
     println!("{}", c);
@@ -23,9 +19,35 @@ fn bar(
     println!("{}", f);
 }
 
+macro_rules! delegate_local {
+    ($method:ident) => {
+        <Self>::$method(8)
+        //~^ ERROR function takes 2 arguments but 1
+    };
+}
+
+macro_rules! delegate_from {
+    ($from:ident, $method:ident) => {
+        <$from>::$method(8)
+        //~^ ERROR function takes 2 arguments but 1
+    };
+}
+
+struct Bar;
+
+impl Bar {
+    fn foo(a: u8, b: u8) {}
+    fn bar() {
+        delegate_local!(foo);
+        delegate!(foo);
+        //~^ ERROR function takes 2 arguments but 1
+        delegate_from!(Bar, foo);
+    }
+}
+
 fn main() {
-  foo(1, 2, 3);
-  //~^ ERROR function takes 4 arguments but 3
-  bar(1, 2, 3);
-  //~^ ERROR function takes 6 arguments but 3
+    foo(1, 2, 3);
+    //~^ ERROR function takes 4 arguments but 3
+    bar(1, 2, 3);
+    //~^ ERROR function takes 6 arguments but 3
 }
diff --git a/tests/ui/not-enough-arguments.stderr b/tests/ui/not-enough-arguments.stderr
index 099d82eb935..908d0273bbe 100644
--- a/tests/ui/not-enough-arguments.stderr
+++ b/tests/ui/not-enough-arguments.stderr
@@ -1,42 +1,88 @@
+error[E0061]: this function takes 2 arguments but 1 argument was supplied
+  --> $DIR/not-enough-arguments.rs:24:9
+   |
+LL |         <Self>::$method(8)
+   |         ^^^^^^^^^^^^^^^--- argument #2 of type `u8` is missing
+...
+LL |         delegate_local!(foo);
+   |         -------------------- in this macro invocation
+   |
+note: associated function defined here
+  --> $DIR/not-enough-arguments.rs:39:8
+   |
+LL |     fn foo(a: u8, b: u8) {}
+   |        ^^^        -----
+   = note: this error originates in the macro `delegate_local` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: provide the argument
+   |
+LL |         <Self>::$method(8, /* u8 */)
+   |                          ++++++++++
+
+error[E0061]: this function takes 2 arguments but 1 argument was supplied
+  --> $DIR/not-enough-arguments.rs:42:9
+   |
+LL |         delegate!(foo);
+   |         ^^^^^^^^^^^^^^ argument #2 of type `u8` is missing
+   |
+note: associated function defined here
+  --> $DIR/not-enough-arguments.rs:39:8
+   |
+LL |     fn foo(a: u8, b: u8) {}
+   |        ^^^        -----
+   = note: this error originates in the macro `delegate` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0061]: this function takes 2 arguments but 1 argument was supplied
+  --> $DIR/not-enough-arguments.rs:31:9
+   |
+LL |         <$from>::$method(8)
+   |         ^^^^^^^^^^^^^^^^--- argument #2 of type `u8` is missing
+...
+LL |         delegate_from!(Bar, foo);
+   |         ------------------------ in this macro invocation
+   |
+note: associated function defined here
+  --> $DIR/not-enough-arguments.rs:39:8
+   |
+LL |     fn foo(a: u8, b: u8) {}
+   |        ^^^        -----
+   = note: this error originates in the macro `delegate_from` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: provide the argument
+   |
+LL |         <$from>::$method(8, /* u8 */)
+   |                           ++++++++++
+
 error[E0061]: this function takes 4 arguments but 3 arguments were supplied
-  --> $DIR/not-enough-arguments.rs:27:3
+  --> $DIR/not-enough-arguments.rs:49:5
    |
-LL |   foo(1, 2, 3);
-   |   ^^^--------- argument #4 of type `isize` is missing
+LL |     foo(1, 2, 3);
+   |     ^^^--------- argument #4 of type `isize` is missing
    |
 note: function defined here
-  --> $DIR/not-enough-arguments.rs:5:4
+  --> $DIR/not-enough-arguments.rs:8:4
    |
-LL | fn foo(a: isize, b: isize, c: isize, d:isize) {
-   |    ^^^                               -------
+LL | fn foo(a: isize, b: isize, c: isize, d: isize) {
+   |    ^^^                               --------
 help: provide the argument
    |
-LL |   foo(1, 2, 3, /* isize */);
-   |              +++++++++++++
+LL |     foo(1, 2, 3, /* isize */);
+   |                +++++++++++++
 
 error[E0061]: this function takes 6 arguments but 3 arguments were supplied
-  --> $DIR/not-enough-arguments.rs:29:3
+  --> $DIR/not-enough-arguments.rs:51:5
    |
-LL |   bar(1, 2, 3);
-   |   ^^^--------- three arguments of type `i32`, `i32`, and `i32` are missing
+LL |     bar(1, 2, 3);
+   |     ^^^--------- three arguments of type `i32`, `i32`, and `i32` are missing
    |
 note: function defined here
-  --> $DIR/not-enough-arguments.rs:10:4
+  --> $DIR/not-enough-arguments.rs:13:4
    |
-LL | fn bar(
-   |    ^^^
-...
-LL |     d: i32,
-   |     ------
-LL |     e: i32,
-   |     ------
-LL |     f: i32,
-   |     ------
+LL | fn bar(a: i32, b: i32, c: i32, d: i32, e: i32, f: i32) {
+   |    ^^^                         ------  ------  ------
 help: provide the arguments
    |
-LL |   bar(1, 2, 3, /* i32 */, /* i32 */, /* i32 */);
-   |              +++++++++++++++++++++++++++++++++
+LL |     bar(1, 2, 3, /* i32 */, /* i32 */, /* i32 */);
+   |                +++++++++++++++++++++++++++++++++
 
-error: aborting due to 2 previous errors
+error: aborting due to 5 previous errors
 
 For more information about this error, try `rustc --explain E0061`.
diff --git a/tests/ui/bitwise.rs b/tests/ui/numbers-arithmetic/bitwise-ops-platform.rs
index 0779e7f229c..60d552e904b 100644
--- a/tests/ui/bitwise.rs
+++ b/tests/ui/numbers-arithmetic/bitwise-ops-platform.rs
@@ -1,3 +1,5 @@
+//! Tests bitwise operations with platform-specific and negative number behavior.
+
 //@ run-pass
 
 #[cfg(any(target_pointer_width = "32"))]
diff --git a/tests/ui/parser/macro/auxiliary/unicode-control.rs b/tests/ui/parser/macro/auxiliary/unicode-control.rs
new file mode 100644
index 00000000000..8e73e3985ce
--- /dev/null
+++ b/tests/ui/parser/macro/auxiliary/unicode-control.rs
@@ -0,0 +1,19 @@
+#![allow(text_direction_codepoint_in_literal)]
+
+extern crate proc_macro;
+use proc_macro::*;
+
+#[proc_macro]
+pub fn create_rtl_in_string(_: TokenStream) -> TokenStream {
+    r#""‮test⁦ RTL in string literal""#.parse().unwrap()
+}
+
+#[proc_macro]
+pub fn forward_stream(s: TokenStream) -> TokenStream {
+    s
+}
+
+#[proc_macro]
+pub fn recollect_stream(s: TokenStream) -> TokenStream {
+    s.into_iter().collect()
+}
diff --git a/tests/ui/parser/macro/unicode-control-codepoints-macros.rs b/tests/ui/parser/macro/unicode-control-codepoints-macros.rs
new file mode 100644
index 00000000000..775c5077976
--- /dev/null
+++ b/tests/ui/parser/macro/unicode-control-codepoints-macros.rs
@@ -0,0 +1,49 @@
+// Regression test for #140281
+//@ edition: 2021
+//@ proc-macro: unicode-control.rs
+
+extern crate unicode_control;
+use unicode_control::*;
+
+macro_rules! foo {
+    ($x:expr) => {
+        $x
+    };
+}
+
+macro_rules! empty {
+    ($x:expr) => {};
+}
+
+fn main() {
+    let t = vec![
+        /// ‮test⁦ RTL in doc in vec
+        //~^ ERROR unicode codepoint changing visible direction of text present in doc comment
+        1
+    ];
+    foo!(
+        /**
+         * ‮test⁦ RTL in doc in macro
+         */
+        //~^^^ ERROR unicode codepoint changing visible direction of text present in doc comment
+        1
+    );
+    empty!(
+        /**
+         * ‮test⁦ RTL in doc in macro
+         */
+        //~^^^ ERROR unicode codepoint changing visible direction of text present in doc comment
+        1
+    );
+    let x = create_rtl_in_string!(); // OK
+    forward_stream!(
+        /// ‮test⁦ RTL in doc in proc macro
+        //~^ ERROR unicode codepoint changing visible direction of text present in doc comment
+        mod a {}
+    );
+    recollect_stream!(
+        /// ‮test⁦ RTL in doc in proc macro
+        //~^ ERROR unicode codepoint changing visible direction of text present in doc comment
+        mod b {}
+    );
+}
diff --git a/tests/ui/parser/macro/unicode-control-codepoints-macros.stderr b/tests/ui/parser/macro/unicode-control-codepoints-macros.stderr
new file mode 100644
index 00000000000..ca813399eac
--- /dev/null
+++ b/tests/ui/parser/macro/unicode-control-codepoints-macros.stderr
@@ -0,0 +1,57 @@
+error: unicode codepoint changing visible direction of text present in doc comment
+  --> $DIR/unicode-control-codepoints-macros.rs:20:9
+   |
+LL |         /// �test� RTL in doc in vec
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this doc comment contains invisible unicode text flow control codepoints
+   |
+   = note: these kind of unicode codepoints change the way text flows on applications that support them, but can cause confusion because they change the order of characters on the screen
+   = note: if their presence wasn't intentional, you can remove them
+   = note: if you want to keep them but make them visible in your source code, you can escape them: '\u{202e}', '\u{2066}'
+   = note: `#[deny(text_direction_codepoint_in_literal)]` on by default
+
+error: unicode codepoint changing visible direction of text present in doc comment
+  --> $DIR/unicode-control-codepoints-macros.rs:25:9
+   |
+LL | /         /**
+LL | |          * �test� RTL in doc in macro
+LL | |          */
+   | |___________^ this doc comment contains invisible unicode text flow control codepoints
+   |
+   = note: these kind of unicode codepoints change the way text flows on applications that support them, but can cause confusion because they change the order of characters on the screen
+   = note: if their presence wasn't intentional, you can remove them
+   = note: if you want to keep them but make them visible in your source code, you can escape them: '\u{202e}', '\u{2066}'
+
+error: unicode codepoint changing visible direction of text present in doc comment
+  --> $DIR/unicode-control-codepoints-macros.rs:32:9
+   |
+LL | /         /**
+LL | |          * �test� RTL in doc in macro
+LL | |          */
+   | |___________^ this doc comment contains invisible unicode text flow control codepoints
+   |
+   = note: these kind of unicode codepoints change the way text flows on applications that support them, but can cause confusion because they change the order of characters on the screen
+   = note: if their presence wasn't intentional, you can remove them
+   = note: if you want to keep them but make them visible in your source code, you can escape them: '\u{202e}', '\u{2066}'
+
+error: unicode codepoint changing visible direction of text present in doc comment
+  --> $DIR/unicode-control-codepoints-macros.rs:40:9
+   |
+LL |         /// �test� RTL in doc in proc macro
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this doc comment contains invisible unicode text flow control codepoints
+   |
+   = note: these kind of unicode codepoints change the way text flows on applications that support them, but can cause confusion because they change the order of characters on the screen
+   = note: if their presence wasn't intentional, you can remove them
+   = note: if you want to keep them but make them visible in your source code, you can escape them: '\u{202e}', '\u{2066}'
+
+error: unicode codepoint changing visible direction of text present in doc comment
+  --> $DIR/unicode-control-codepoints-macros.rs:45:9
+   |
+LL |         /// �test� RTL in doc in proc macro
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this doc comment contains invisible unicode text flow control codepoints
+   |
+   = note: these kind of unicode codepoints change the way text flows on applications that support them, but can cause confusion because they change the order of characters on the screen
+   = note: if their presence wasn't intentional, you can remove them
+   = note: if you want to keep them but make them visible in your source code, you can escape them: '\u{202e}', '\u{2066}'
+
+error: aborting due to 5 previous errors
+
diff --git a/tests/ui/parser/match-arm-comma-typo-issue-140991.fixed b/tests/ui/parser/match-arm-comma-typo-issue-140991.fixed
new file mode 100644
index 00000000000..4d99e4bdc1c
--- /dev/null
+++ b/tests/ui/parser/match-arm-comma-typo-issue-140991.fixed
@@ -0,0 +1,24 @@
+//@ run-rustfix
+
+pub enum Foo {
+    X, Y
+}
+
+pub fn typo1(foo: Foo) -> Foo {
+    use Foo::*;
+    match foo {
+        X => Y,
+        Y => X, //~ ERROR expected one of
+    }
+}
+
+pub fn typo2(foo: Foo) -> Foo {
+    use Foo::*;
+    match foo {
+        X => Y,
+        Y => X, //~ ERROR expected one of
+    }
+}
+
+
+fn main() { }
diff --git a/tests/ui/parser/match-arm-comma-typo-issue-140991.rs b/tests/ui/parser/match-arm-comma-typo-issue-140991.rs
new file mode 100644
index 00000000000..3baf1ff3fa1
--- /dev/null
+++ b/tests/ui/parser/match-arm-comma-typo-issue-140991.rs
@@ -0,0 +1,24 @@
+//@ run-rustfix
+
+pub enum Foo {
+    X, Y
+}
+
+pub fn typo1(foo: Foo) -> Foo {
+    use Foo::*;
+    match foo {
+        X => Y.
+        Y => X, //~ ERROR expected one of
+    }
+}
+
+pub fn typo2(foo: Foo) -> Foo {
+    use Foo::*;
+    match foo {
+        X => Y/
+        Y => X, //~ ERROR expected one of
+    }
+}
+
+
+fn main() { }
diff --git a/tests/ui/parser/match-arm-comma-typo-issue-140991.stderr b/tests/ui/parser/match-arm-comma-typo-issue-140991.stderr
new file mode 100644
index 00000000000..19532d14245
--- /dev/null
+++ b/tests/ui/parser/match-arm-comma-typo-issue-140991.stderr
@@ -0,0 +1,26 @@
+error: expected one of `(`, `,`, `.`, `::`, `?`, `}`, or an operator, found `=>`
+  --> $DIR/match-arm-comma-typo-issue-140991.rs:11:11
+   |
+LL |         Y => X,
+   |           ^^ expected one of 7 possible tokens
+   |
+help: you might have meant to write a `,` to end this `match` arm
+   |
+LL -         X => Y.
+LL +         X => Y,
+   |
+
+error: expected one of `!`, `,`, `.`, `::`, `?`, `{`, `}`, or an operator, found `=>`
+  --> $DIR/match-arm-comma-typo-issue-140991.rs:19:11
+   |
+LL |         Y => X,
+   |           ^^ expected one of 8 possible tokens
+   |
+help: you might have meant to write a `,` to end this `match` arm
+   |
+LL -         X => Y/
+LL +         X => Y,
+   |
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/parser/unicode-control-codepoints.rs b/tests/ui/parser/unicode-control-codepoints.rs
index 14e1cfe59d3..e3c906063c4 100644
--- a/tests/ui/parser/unicode-control-codepoints.rs
+++ b/tests/ui/parser/unicode-control-codepoints.rs
@@ -34,7 +34,7 @@ fn main() {
     //~^ ERROR unicode codepoint changing visible direction of text present in literal
 
     println!("{{‮}}");
-    //~^ ERROR unicode codepoint changing visible direction of text present in format string
+    //~^ ERROR unicode codepoint changing visible direction of text present in literal
 }
 
 //"/*‮ } ⁦if isAdmin⁩ ⁦ begin admins only */"
diff --git a/tests/ui/parser/unicode-control-codepoints.stderr b/tests/ui/parser/unicode-control-codepoints.stderr
index 27b95f9ac61..7978c1435f6 100644
--- a/tests/ui/parser/unicode-control-codepoints.stderr
+++ b/tests/ui/parser/unicode-control-codepoints.stderr
@@ -100,21 +100,6 @@ LL |     // if access_level != "us�e�r" { // Check if admin
    = note: `#[deny(text_direction_codepoint_in_comment)]` on by default
    = help: if their presence wasn't intentional, you can remove them
 
-error: unicode codepoint changing visible direction of text present in comment
-  --> $DIR/unicode-control-codepoints.rs:40:1
-   |
-LL | //"/*� } �if isAdmin� � begin admins only */"
-   | ^^^^^-^^^-^^^^^^^^^^-^-^^^^^^^^^^^^^^^^^^^^^^
-   | |    |   |          | |
-   | |    |   |          | '\u{2066}'
-   | |    |   |          '\u{2069}'
-   | |    |   '\u{2066}'
-   | |    '\u{202e}'
-   | this comment contains invisible unicode text flow control codepoints
-   |
-   = note: these kind of unicode codepoints change the way text flows on applications that support them, but can cause confusion because they change the order of characters on the screen
-   = help: if their presence wasn't intentional, you can remove them
-
 error: unicode codepoint changing visible direction of text present in literal
   --> $DIR/unicode-control-codepoints.rs:13:22
    |
@@ -207,14 +192,14 @@ LL -     let _ = cr#"�"#;
 LL +     let _ = cr#"\u{202e}"#;
    |
 
-error: unicode codepoint changing visible direction of text present in format string
+error: unicode codepoint changing visible direction of text present in literal
   --> $DIR/unicode-control-codepoints.rs:36:14
    |
 LL |     println!("{{�}}");
    |              ^^^-^^^
    |              |  |
    |              |  '\u{202e}'
-   |              this format string contains an invisible unicode text flow control codepoint
+   |              this literal contains an invisible unicode text flow control codepoint
    |
    = note: these kind of unicode codepoints change the way text flows on applications that support them, but can cause confusion because they change the order of characters on the screen
    = help: if their presence wasn't intentional, you can remove them
@@ -224,6 +209,21 @@ LL -     println!("{{�}}");
 LL +     println!("{{\u{202e}}}");
    |
 
+error: unicode codepoint changing visible direction of text present in comment
+  --> $DIR/unicode-control-codepoints.rs:40:1
+   |
+LL | //"/*� } �if isAdmin� � begin admins only */"
+   | ^^^^^-^^^-^^^^^^^^^^-^-^^^^^^^^^^^^^^^^^^^^^^
+   | |    |   |          | |
+   | |    |   |          | '\u{2066}'
+   | |    |   |          '\u{2069}'
+   | |    |   '\u{2066}'
+   | |    '\u{202e}'
+   | this comment contains invisible unicode text flow control codepoints
+   |
+   = note: these kind of unicode codepoints change the way text flows on applications that support them, but can cause confusion because they change the order of characters on the screen
+   = help: if their presence wasn't intentional, you can remove them
+
 error: unicode codepoint changing visible direction of text present in doc comment
   --> $DIR/unicode-control-codepoints.rs:43:1
    |
diff --git a/tests/ui/bind-by-move.rs b/tests/ui/pattern/pattern-match-arc-move.rs
index 99f3536e533..bc79401e4e3 100644
--- a/tests/ui/bind-by-move.rs
+++ b/tests/ui/pattern/pattern-match-arc-move.rs
@@ -1,3 +1,5 @@
+//! Tests moving an `Arc` value out of an `Option` in a match expression.
+
 //@ run-pass
 
 use std::sync::Arc;
diff --git a/tests/ui/pattern/pattern-match-invalid-variant.rs b/tests/ui/pattern/pattern-match-invalid-variant.rs
new file mode 100644
index 00000000000..183031553c0
--- /dev/null
+++ b/tests/ui/pattern/pattern-match-invalid-variant.rs
@@ -0,0 +1,19 @@
+//! Tests invalid enum variant in a match expression.
+
+enum Color {
+    Rgb(isize, isize, isize),
+    Rgba(isize, isize, isize, isize),
+}
+
+fn main() {
+    let red: Color = Color::Rgb(255, 0, 0);
+    match red {
+        Color::Rgb(r, g, b) => {
+            println!("rgb");
+        }
+        Color::Hsl(h, s, l) => {
+            //~^ ERROR no variant
+            println!("hsl");
+        }
+    }
+}
diff --git a/tests/ui/bogus-tag.stderr b/tests/ui/pattern/pattern-match-invalid-variant.stderr
index d94bd489ec6..08a99f696f6 100644
--- a/tests/ui/bogus-tag.stderr
+++ b/tests/ui/pattern/pattern-match-invalid-variant.stderr
@@ -1,10 +1,10 @@
 error[E0599]: no variant or associated item named `Hsl` found for enum `Color` in the current scope
-  --> $DIR/bogus-tag.rs:7:16
+  --> $DIR/pattern-match-invalid-variant.rs:14:16
    |
-LL | enum Color { Rgb(isize, isize, isize), Rgba(isize, isize, isize, isize), }
+LL | enum Color {
    | ---------- variant or associated item `Hsl` not found for this enum
 ...
-LL |         Color::Hsl(h, s, l) => { println!("hsl"); }
+LL |         Color::Hsl(h, s, l) => {
    |                ^^^ variant or associated item not found in `Color`
 
 error: aborting due to 1 previous error
diff --git a/tests/ui/print-request/emit-warning-print-link-info-without-staticlib.rs b/tests/ui/print-request/emit-warning-print-link-info-without-staticlib.rs
new file mode 100644
index 00000000000..b100c062bba
--- /dev/null
+++ b/tests/ui/print-request/emit-warning-print-link-info-without-staticlib.rs
@@ -0,0 +1,5 @@
+//@ compile-flags: --print native-static-libs
+//@ check-pass
+//~? WARN cannot output linkage information without staticlib crate-type
+
+fn main() {}
diff --git a/tests/ui/print-request/emit-warning-print-link-info-without-staticlib.stderr b/tests/ui/print-request/emit-warning-print-link-info-without-staticlib.stderr
new file mode 100644
index 00000000000..ceff08baa13
--- /dev/null
+++ b/tests/ui/print-request/emit-warning-print-link-info-without-staticlib.stderr
@@ -0,0 +1,6 @@
+warning: cannot output linkage information without staticlib crate-type
+
+note: consider `--crate-type staticlib` to print linkage information
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/print-request/emit-warning-while-exe-and-print-link-info.rs b/tests/ui/print-request/emit-warning-while-exe-and-print-link-info.rs
new file mode 100644
index 00000000000..3e9ca457a9c
--- /dev/null
+++ b/tests/ui/print-request/emit-warning-while-exe-and-print-link-info.rs
@@ -0,0 +1,3 @@
+//@ compile-flags: --print native-static-libs --crate-type staticlib  --emit metadata
+//@ check-pass
+//~? WARN cannot output linkage information when --emit link is not passed
diff --git a/tests/ui/print-request/emit-warning-while-exe-and-print-link-info.stderr b/tests/ui/print-request/emit-warning-while-exe-and-print-link-info.stderr
new file mode 100644
index 00000000000..b32e1437d6b
--- /dev/null
+++ b/tests/ui/print-request/emit-warning-while-exe-and-print-link-info.stderr
@@ -0,0 +1,4 @@
+warning: cannot output linkage information when --emit link is not passed
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/print-request/stability.rs b/tests/ui/print-request/stability.rs
index 54142ce78ce..fbcdf916cc7 100644
--- a/tests/ui/print-request/stability.rs
+++ b/tests/ui/print-request/stability.rs
@@ -110,3 +110,4 @@ fn main() {}
 //[check_cfg]~? ERROR the `-Z unstable-options` flag must also be passed to enable the `check-cfg` print option
 //[supported_crate_types]~? ERROR the `-Z unstable-options` flag must also be passed to enable the `supported-crate-types` print option
 //[target_spec_json]~? ERROR the `-Z unstable-options` flag must also be passed to enable the `target-spec-json` print option
+//[native_static_libs]~? WARNING cannot output linkage information without staticlib crate-type
diff --git a/tests/ui/print_type_sizes/niche-filling.rs b/tests/ui/print_type_sizes/niche-filling.rs
index 36739e3fc04..719bc2a07dc 100644
--- a/tests/ui/print_type_sizes/niche-filling.rs
+++ b/tests/ui/print_type_sizes/niche-filling.rs
@@ -55,7 +55,14 @@ pub struct NestedNonZero {
 
 impl Default for NestedNonZero {
     fn default() -> Self {
-        NestedNonZero { pre: 0, val: unsafe { NonZero::new_unchecked(1) }, post: 0 }
+        // Ideally we'd call NonZero::new_unchecked, but this test is supposed
+        // to be target-independent and NonZero::new_unchecked is #[track_caller]
+        // (see #129658) so mentioning that function pulls in std::panic::Location
+        // which contains a &str, whose layout is target-dependent.
+        const ONE: NonZero<u32> = const {
+            unsafe { std::mem::transmute(1u32) }
+        };
+        NestedNonZero { pre: 0, val: ONE, post: 0 }
     }
 }
 
diff --git a/tests/ui/print_type_sizes/niche-filling.stdout b/tests/ui/print_type_sizes/niche-filling.stdout
index 70612490a47..3342f68dd70 100644
--- a/tests/ui/print_type_sizes/niche-filling.stdout
+++ b/tests/ui/print_type_sizes/niche-filling.stdout
@@ -72,10 +72,6 @@ print-type-size type: `core::num::niche_types::NonZeroU32Inner`: 4 bytes, alignm
 print-type-size     field `.0`: 4 bytes
 print-type-size type: `std::num::NonZero<u32>`: 4 bytes, alignment: 4 bytes
 print-type-size     field `.0`: 4 bytes
-print-type-size type: `std::option::Option<std::num::NonZero<u32>>`: 4 bytes, alignment: 4 bytes
-print-type-size     variant `Some`: 4 bytes
-print-type-size         field `.0`: 4 bytes
-print-type-size     variant `None`: 0 bytes
 print-type-size type: `Enum4<(), (), (), MyOption<u8>>`: 2 bytes, alignment: 1 bytes
 print-type-size     variant `Four`: 2 bytes
 print-type-size         field `.0`: 2 bytes
diff --git a/tests/ui/proc-macro/no-macro-use-attr.stderr b/tests/ui/proc-macro/no-macro-use-attr.stderr
index 4913672450a..0bef563fbb9 100644
--- a/tests/ui/proc-macro/no-macro-use-attr.stderr
+++ b/tests/ui/proc-macro/no-macro-use-attr.stderr
@@ -2,13 +2,17 @@ warning: unused extern crate
   --> $DIR/no-macro-use-attr.rs:6:1
    |
 LL | extern crate test_macros;
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove it
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^ unused
    |
 note: the lint level is defined here
   --> $DIR/no-macro-use-attr.rs:4:9
    |
 LL | #![warn(unused_extern_crates)]
    |         ^^^^^^^^^^^^^^^^^^^^
+help: remove the unused `extern crate`
+   |
+LL - extern crate test_macros;
+   |
 
 warning: 1 warning emitted
 
diff --git a/tests/ui/repeat-expr/copy-check-when-count-inferred-later.rs b/tests/ui/repeat-expr/copy-check-when-count-inferred-later.rs
new file mode 100644
index 00000000000..b9d123cbefa
--- /dev/null
+++ b/tests/ui/repeat-expr/copy-check-when-count-inferred-later.rs
@@ -0,0 +1,11 @@
+#![feature(generic_arg_infer)]
+
+// Test that we enforce repeat expr element types are `Copy` even
+// when the repeat count is only inferred at a later point in type
+// checking.
+
+fn main() {
+    let a = [String::new(); _];
+    //~^ ERROR: the trait bound `String: Copy` is not satisfied
+    let b: [_; 2] = a;
+}
diff --git a/tests/ui/repeat-expr/copy-check-when-count-inferred-later.stderr b/tests/ui/repeat-expr/copy-check-when-count-inferred-later.stderr
new file mode 100644
index 00000000000..d974f5add50
--- /dev/null
+++ b/tests/ui/repeat-expr/copy-check-when-count-inferred-later.stderr
@@ -0,0 +1,14 @@
+error[E0277]: the trait bound `String: Copy` is not satisfied
+  --> $DIR/copy-check-when-count-inferred-later.rs:8:14
+   |
+LL |     let a = [String::new(); _];
+   |              ^^^^^^^^^^^^^
+   |              |
+   |              the trait `Copy` is not implemented for `String`
+   |              help: create an inline `const` block: `const { String::new() }`
+   |
+   = note: the `Copy` trait is required because this value will be copied for each element of the array
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/resolve/extern-crate-lint-issue-141785.rs b/tests/ui/resolve/extern-crate-lint-issue-141785.rs
new file mode 100644
index 00000000000..8d044d666df
--- /dev/null
+++ b/tests/ui/resolve/extern-crate-lint-issue-141785.rs
@@ -0,0 +1,11 @@
+//@ check-pass
+//@ edition:2018
+
+#![no_implicit_prelude]
+#![warn(unused_extern_crates)]
+
+extern crate std;
+fn main() {
+    let r = 1u16..10;
+    std::println!("{:?}", r.is_empty());
+}
diff --git a/tests/ui/resolve/tuple-struct-alias.stderr b/tests/ui/resolve/tuple-struct-alias.stderr
index a739ea43eed..bf026a499b8 100644
--- a/tests/ui/resolve/tuple-struct-alias.stderr
+++ b/tests/ui/resolve/tuple-struct-alias.stderr
@@ -6,8 +6,6 @@ LL | struct S(u8, u16);
 ...
 LL |         A(..) => {}
    |         ^ help: a tuple struct with a similar name exists: `S`
-   |
-   = note: can't use a type alias as a constructor
 
 error[E0423]: expected function, tuple struct or tuple variant, found type alias `A`
   --> $DIR/tuple-struct-alias.rs:5:13
@@ -16,9 +14,18 @@ LL | struct S(u8, u16);
    | ------------------ similarly named tuple struct `S` defined here
 ...
 LL |     let s = A(0, 1);
-   |             ^ help: a tuple struct with a similar name exists: `S`
+   |             ^
+   |
+help: a tuple struct with a similar name exists
+   |
+LL -     let s = A(0, 1);
+LL +     let s = S(0, 1);
+   |
+help: you might have meant to use `:` for type annotation
+   |
+LL -     let s = A(0, 1);
+LL +     let s: A(0, 1);
    |
-   = note: can't use a type alias as a constructor
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/rust-2018/extern-crate-idiomatic-in-2018.stderr b/tests/ui/rust-2018/extern-crate-idiomatic-in-2018.stderr
index a68d99c14ce..248d42ba3f4 100644
--- a/tests/ui/rust-2018/extern-crate-idiomatic-in-2018.stderr
+++ b/tests/ui/rust-2018/extern-crate-idiomatic-in-2018.stderr
@@ -2,7 +2,7 @@ error: unused extern crate
   --> $DIR/extern-crate-idiomatic-in-2018.rs:12:1
    |
 LL | extern crate edition_lint_paths;
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove it
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unused
    |
 note: the lint level is defined here
   --> $DIR/extern-crate-idiomatic-in-2018.rs:9:9
@@ -10,6 +10,10 @@ note: the lint level is defined here
 LL | #![deny(rust_2018_idioms)]
    |         ^^^^^^^^^^^^^^^^
    = note: `#[deny(unused_extern_crates)]` implied by `#[deny(rust_2018_idioms)]`
+help: remove the unused `extern crate`
+   |
+LL - extern crate edition_lint_paths;
+   |
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/rust-2018/issue-54400-unused-extern-crate-attr-span.rs b/tests/ui/rust-2018/issue-54400-unused-extern-crate-attr-span.rs
index 573942bd095..467914d6a5e 100644
--- a/tests/ui/rust-2018/issue-54400-unused-extern-crate-attr-span.rs
+++ b/tests/ui/rust-2018/issue-54400-unused-extern-crate-attr-span.rs
@@ -8,7 +8,7 @@
 
 // The suggestion span should include the attribute.
 
-#[cfg(not(FALSE))] //~ HELP remove it
+#[cfg(not(FALSE))] //~ HELP remove
 extern crate edition_lint_paths;
 //~^ ERROR unused extern crate
 
diff --git a/tests/ui/rust-2018/issue-54400-unused-extern-crate-attr-span.stderr b/tests/ui/rust-2018/issue-54400-unused-extern-crate-attr-span.stderr
index 038a9dd967b..9efc3493d34 100644
--- a/tests/ui/rust-2018/issue-54400-unused-extern-crate-attr-span.stderr
+++ b/tests/ui/rust-2018/issue-54400-unused-extern-crate-attr-span.stderr
@@ -1,11 +1,8 @@
 error: unused extern crate
   --> $DIR/issue-54400-unused-extern-crate-attr-span.rs:12:1
    |
-LL | / #[cfg(not(FALSE))]
-LL | | extern crate edition_lint_paths;
-   | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-
-   | |________________________________|
-   |                                  help: remove it
+LL | extern crate edition_lint_paths;
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unused
    |
 note: the lint level is defined here
   --> $DIR/issue-54400-unused-extern-crate-attr-span.rs:6:9
@@ -13,6 +10,11 @@ note: the lint level is defined here
 LL | #![deny(rust_2018_idioms)]
    |         ^^^^^^^^^^^^^^^^
    = note: `#[deny(unused_extern_crates)]` implied by `#[deny(rust_2018_idioms)]`
+help: remove the unused `extern crate`
+   |
+LL - #[cfg(not(FALSE))]
+LL - extern crate edition_lint_paths;
+   |
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/rust-2018/remove-extern-crate.stderr b/tests/ui/rust-2018/remove-extern-crate.stderr
index cb090c621e9..a530d40188b 100644
--- a/tests/ui/rust-2018/remove-extern-crate.stderr
+++ b/tests/ui/rust-2018/remove-extern-crate.stderr
@@ -2,7 +2,7 @@ warning: unused extern crate
   --> $DIR/remove-extern-crate.rs:11:1
    |
 LL | extern crate core;
-   | ^^^^^^^^^^^^^^^^^^ help: remove it
+   | ^^^^^^^^^^^^^^^^^^ unused
    |
 note: the lint level is defined here
   --> $DIR/remove-extern-crate.rs:7:9
@@ -10,6 +10,11 @@ note: the lint level is defined here
 LL | #![warn(rust_2018_idioms)]
    |         ^^^^^^^^^^^^^^^^
    = note: `#[warn(unused_extern_crates)]` implied by `#[warn(rust_2018_idioms)]`
+help: remove the unused `extern crate`
+   |
+LL - extern crate core;
+LL +
+   |
 
 warning: `extern crate` is not idiomatic in the new edition
   --> $DIR/remove-extern-crate.rs:35:5
diff --git a/tests/ui/rust-2018/removing-extern-crate-malformed-cfg.fixed b/tests/ui/rust-2018/removing-extern-crate-malformed-cfg.fixed
new file mode 100644
index 00000000000..26c1c9015da
--- /dev/null
+++ b/tests/ui/rust-2018/removing-extern-crate-malformed-cfg.fixed
@@ -0,0 +1,15 @@
+//@ edition:2018
+//@ aux-build:../removing-extern-crate.rs
+//@ run-rustfix
+
+#![warn(rust_2018_idioms)]
+
+ //~ WARNING unused extern crate
+ //~ WARNING unused extern crate
+
+mod another {
+     //~ WARNING unused extern crate
+     //~ WARNING unused extern crate
+}
+
+fn main() {}
diff --git a/tests/ui/rust-2018/removing-extern-crate-malformed-cfg.rs b/tests/ui/rust-2018/removing-extern-crate-malformed-cfg.rs
new file mode 100644
index 00000000000..c5b629fa90b
--- /dev/null
+++ b/tests/ui/rust-2018/removing-extern-crate-malformed-cfg.rs
@@ -0,0 +1,17 @@
+//@ edition:2018
+//@ aux-build:../removing-extern-crate.rs
+//@ run-rustfix
+
+#![warn(rust_2018_idioms)]
+
+#[cfg_attr(test, "macro_use")] //~ ERROR expected
+extern crate removing_extern_crate as foo; //~ WARNING unused extern crate
+extern crate core; //~ WARNING unused extern crate
+
+mod another {
+    #[cfg_attr(test)] //~ ERROR expected
+    extern crate removing_extern_crate as foo; //~ WARNING unused extern crate
+    extern crate core; //~ WARNING unused extern crate
+}
+
+fn main() {}
diff --git a/tests/ui/rust-2018/removing-extern-crate-malformed-cfg.stderr b/tests/ui/rust-2018/removing-extern-crate-malformed-cfg.stderr
new file mode 100644
index 00000000000..0e834707bf9
--- /dev/null
+++ b/tests/ui/rust-2018/removing-extern-crate-malformed-cfg.stderr
@@ -0,0 +1,76 @@
+error: expected identifier, found `"macro_use"`
+  --> $DIR/removing-extern-crate-malformed-cfg.rs:7:18
+   |
+LL | #[cfg_attr(test, "macro_use")]
+   |                  ^^^^^^^^^^^ expected identifier
+   |
+   = help: the valid syntax is `#[cfg_attr(condition, attribute, other_attribute, ...)]`
+   = note: for more information, visit <https://doc.rust-lang.org/reference/conditional-compilation.html#the-cfg_attr-attribute>
+
+error: expected one of `(`, `,`, `::`, or `=`, found `<eof>`
+  --> $DIR/removing-extern-crate-malformed-cfg.rs:12:16
+   |
+LL |     #[cfg_attr(test)]
+   |                ^^^^ expected one of `(`, `,`, `::`, or `=`
+   |
+   = help: the valid syntax is `#[cfg_attr(condition, attribute, other_attribute, ...)]`
+   = note: for more information, visit <https://doc.rust-lang.org/reference/conditional-compilation.html#the-cfg_attr-attribute>
+
+warning: unused extern crate
+  --> $DIR/removing-extern-crate-malformed-cfg.rs:8:1
+   |
+LL | extern crate removing_extern_crate as foo;
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unused
+   |
+note: the lint level is defined here
+  --> $DIR/removing-extern-crate-malformed-cfg.rs:5:9
+   |
+LL | #![warn(rust_2018_idioms)]
+   |         ^^^^^^^^^^^^^^^^
+   = note: `#[warn(unused_extern_crates)]` implied by `#[warn(rust_2018_idioms)]`
+help: remove the unused `extern crate`
+   |
+LL - #[cfg_attr(test, "macro_use")]
+LL - extern crate removing_extern_crate as foo;
+LL +
+   |
+
+warning: unused extern crate
+  --> $DIR/removing-extern-crate-malformed-cfg.rs:9:1
+   |
+LL | extern crate core;
+   | ^^^^^^^^^^^^^^^^^^ unused
+   |
+help: remove the unused `extern crate`
+   |
+LL - extern crate core;
+LL +
+   |
+
+warning: unused extern crate
+  --> $DIR/removing-extern-crate-malformed-cfg.rs:13:5
+   |
+LL |     extern crate removing_extern_crate as foo;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unused
+   |
+help: remove the unused `extern crate`
+   |
+LL -     #[cfg_attr(test)]
+LL -     extern crate removing_extern_crate as foo;
+LL +
+   |
+
+warning: unused extern crate
+  --> $DIR/removing-extern-crate-malformed-cfg.rs:14:5
+   |
+LL |     extern crate core;
+   |     ^^^^^^^^^^^^^^^^^^ unused
+   |
+help: remove the unused `extern crate`
+   |
+LL -     extern crate core;
+LL +
+   |
+
+error: aborting due to 2 previous errors; 4 warnings emitted
+
diff --git a/tests/ui/rust-2018/removing-extern-crate.stderr b/tests/ui/rust-2018/removing-extern-crate.stderr
index 57312542640..b6f8314ce4b 100644
--- a/tests/ui/rust-2018/removing-extern-crate.stderr
+++ b/tests/ui/rust-2018/removing-extern-crate.stderr
@@ -2,7 +2,7 @@ warning: unused extern crate
   --> $DIR/removing-extern-crate.rs:8:1
    |
 LL | extern crate dummy_crate as foo;
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove it
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unused
    |
 note: the lint level is defined here
   --> $DIR/removing-extern-crate.rs:6:9
@@ -10,24 +10,47 @@ note: the lint level is defined here
 LL | #![warn(rust_2018_idioms)]
    |         ^^^^^^^^^^^^^^^^
    = note: `#[warn(unused_extern_crates)]` implied by `#[warn(rust_2018_idioms)]`
+help: remove the unused `extern crate`
+   |
+LL - extern crate dummy_crate as foo;
+LL +
+   |
 
 warning: unused extern crate
   --> $DIR/removing-extern-crate.rs:9:1
    |
 LL | extern crate core;
-   | ^^^^^^^^^^^^^^^^^^ help: remove it
+   | ^^^^^^^^^^^^^^^^^^ unused
+   |
+help: remove the unused `extern crate`
+   |
+LL - extern crate core;
+LL +
+   |
 
 warning: unused extern crate
   --> $DIR/removing-extern-crate.rs:12:5
    |
 LL |     extern crate dummy_crate as foo;
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove it
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unused
+   |
+help: remove the unused `extern crate`
+   |
+LL -     extern crate dummy_crate as foo;
+LL +
+   |
 
 warning: unused extern crate
   --> $DIR/removing-extern-crate.rs:13:5
    |
 LL |     extern crate core;
-   |     ^^^^^^^^^^^^^^^^^^ help: remove it
+   |     ^^^^^^^^^^^^^^^^^^ unused
+   |
+help: remove the unused `extern crate`
+   |
+LL -     extern crate core;
+LL +
+   |
 
 warning: 4 warnings emitted
 
diff --git a/tests/ui/self/arbitrary-self-types-dyn-incompatible.rs b/tests/ui/self/arbitrary-self-types-dyn-incompatible.rs
index 0477d9d79c7..b223f18327b 100644
--- a/tests/ui/self/arbitrary-self-types-dyn-incompatible.rs
+++ b/tests/ui/self/arbitrary-self-types-dyn-incompatible.rs
@@ -28,7 +28,6 @@ impl Bar for usize {
 fn make_foo() {
     let x = Rc::new(5usize) as Rc<dyn Foo>;
     //~^ ERROR E0038
-    //~| ERROR E0038
 }
 
 fn make_bar() {
diff --git a/tests/ui/self/arbitrary-self-types-dyn-incompatible.stderr b/tests/ui/self/arbitrary-self-types-dyn-incompatible.stderr
index 9fb4c80329d..fe4802c9b3a 100644
--- a/tests/ui/self/arbitrary-self-types-dyn-incompatible.stderr
+++ b/tests/ui/self/arbitrary-self-types-dyn-incompatible.stderr
@@ -1,11 +1,11 @@
 error[E0038]: the trait `Foo` is not dyn compatible
-  --> $DIR/arbitrary-self-types-dyn-incompatible.rs:29:32
+  --> $DIR/arbitrary-self-types-dyn-incompatible.rs:29:39
    |
 LL |     fn foo(self: &Rc<Self>) -> usize;
    |                  --------- help: consider changing method `foo`'s `self` parameter to be `&self`: `&Self`
 ...
 LL |     let x = Rc::new(5usize) as Rc<dyn Foo>;
-   |                                ^^^^^^^^^^^ `Foo` is not dyn compatible
+   |                                       ^^^ `Foo` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
       for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
@@ -17,26 +17,6 @@ LL |     fn foo(self: &Rc<Self>) -> usize;
    |                  ^^^^^^^^^ ...because method `foo`'s `self` parameter cannot be dispatched on
    = help: only type `usize` implements `Foo`; consider using it directly instead.
 
-error[E0038]: the trait `Foo` is not dyn compatible
-  --> $DIR/arbitrary-self-types-dyn-incompatible.rs:29:13
-   |
-LL |     fn foo(self: &Rc<Self>) -> usize;
-   |                  --------- help: consider changing method `foo`'s `self` parameter to be `&self`: `&Self`
-...
-LL |     let x = Rc::new(5usize) as Rc<dyn Foo>;
-   |             ^^^^^^^^^^^^^^^ `Foo` is not dyn compatible
-   |
-note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
-  --> $DIR/arbitrary-self-types-dyn-incompatible.rs:4:18
-   |
-LL | trait Foo {
-   |       --- this trait is not dyn compatible...
-LL |     fn foo(self: &Rc<Self>) -> usize;
-   |                  ^^^^^^^^^ ...because method `foo`'s `self` parameter cannot be dispatched on
-   = help: only type `usize` implements `Foo`; consider using it directly instead.
-   = note: required for the cast from `Rc<usize>` to `Rc<dyn Foo>`
-
-error: aborting due to 2 previous errors
+error: aborting due to 1 previous error
 
 For more information about this error, try `rustc --explain E0038`.
diff --git a/tests/ui/statics/unsizing-wfcheck-issue-127299.rs b/tests/ui/statics/unsizing-wfcheck-issue-127299.rs
index fd07937d90f..14ba38d7535 100644
--- a/tests/ui/statics/unsizing-wfcheck-issue-127299.rs
+++ b/tests/ui/statics/unsizing-wfcheck-issue-127299.rs
@@ -12,6 +12,5 @@ pub struct Lint {
 static FOO: &Lint = &Lint { desc: "desc" };
 //~^ ERROR cannot be shared between threads safely
 //~| ERROR is not dyn compatible
-//~| ERROR is not dyn compatible
 
 fn main() {}
diff --git a/tests/ui/statics/unsizing-wfcheck-issue-127299.stderr b/tests/ui/statics/unsizing-wfcheck-issue-127299.stderr
index 28427161e87..e401277a020 100644
--- a/tests/ui/statics/unsizing-wfcheck-issue-127299.stderr
+++ b/tests/ui/statics/unsizing-wfcheck-issue-127299.stderr
@@ -51,7 +51,6 @@ LL | trait Qux {
    |       --- this trait is not dyn compatible...
 LL |     fn bar() -> i32;
    |        ^^^ ...because associated function `bar` has no `self` parameter
-   = note: required for the cast from `&'static str` to `&'static (dyn Qux + 'static)`
 help: consider turning `bar` into a method by giving it a `&self` argument
    |
 LL |     fn bar(&self) -> i32;
@@ -61,30 +60,7 @@ help: alternatively, consider constraining `bar` so it does not apply to trait o
 LL |     fn bar() -> i32 where Self: Sized;
    |                     +++++++++++++++++
 
-error[E0038]: the trait `Qux` is not dyn compatible
-  --> $DIR/unsizing-wfcheck-issue-127299.rs:12:35
-   |
-LL | static FOO: &Lint = &Lint { desc: "desc" };
-   |                                   ^^^^^^ `Qux` is not dyn compatible
-   |
-note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
-  --> $DIR/unsizing-wfcheck-issue-127299.rs:4:8
-   |
-LL | trait Qux {
-   |       --- this trait is not dyn compatible...
-LL |     fn bar() -> i32;
-   |        ^^^ ...because associated function `bar` has no `self` parameter
-help: consider turning `bar` into a method by giving it a `&self` argument
-   |
-LL |     fn bar(&self) -> i32;
-   |            +++++
-help: alternatively, consider constraining `bar` so it does not apply to trait objects
-   |
-LL |     fn bar() -> i32 where Self: Sized;
-   |                     +++++++++++++++++
-
-error: aborting due to 4 previous errors
+error: aborting due to 3 previous errors
 
 Some errors have detailed explanations: E0038, E0277.
 For more information about an error, try `rustc --explain E0038`.
diff --git a/tests/ui/stats/input-stats.rs b/tests/ui/stats/input-stats.rs
index f19a53cc610..e760e2894e3 100644
--- a/tests/ui/stats/input-stats.rs
+++ b/tests/ui/stats/input-stats.rs
@@ -3,6 +3,10 @@
 //@ only-64bit
 // layout randomization affects the hir stat output
 //@ needs-deterministic-layouts
+//
+// Filter out the percentages because a change to a single count can affect
+// many or all percentages, which makes the diffs hard to read.
+//@ normalize-stderr: "\([0-9 ][0-9]\.[0-9]%\)" -> "(NN.N%)"
 
 // Type layouts sometimes change. When that happens, until the next bootstrap
 // bump occurs, stage1 and stage2 will give different outputs for this test.
diff --git a/tests/ui/stats/input-stats.stderr b/tests/ui/stats/input-stats.stderr
index b369af62f87..58ab1a72556 100644
--- a/tests/ui/stats/input-stats.stderr
+++ b/tests/ui/stats/input-stats.stderr
@@ -1,178 +1,178 @@
 ast-stats-1 PRE EXPANSION AST STATS
 ast-stats-1 Name                Accumulated Size         Count     Item Size
 ast-stats-1 ----------------------------------------------------------------
-ast-stats-1 Crate                     40 ( 0.6%)             1            40
-ast-stats-1 GenericArgs               40 ( 0.6%)             1            40
-ast-stats-1 - AngleBracketed            40 ( 0.6%)             1
-ast-stats-1 ExprField                 48 ( 0.7%)             1            48
-ast-stats-1 Attribute                 64 ( 0.9%)             2            32
-ast-stats-1 - DocComment                32 ( 0.5%)             1
-ast-stats-1 - Normal                    32 ( 0.5%)             1
-ast-stats-1 WherePredicate            72 ( 1.1%)             1            72
-ast-stats-1 - BoundPredicate            72 ( 1.1%)             1
-ast-stats-1 ForeignItem               80 ( 1.2%)             1            80
-ast-stats-1 - Fn                        80 ( 1.2%)             1
-ast-stats-1 Arm                       96 ( 1.4%)             2            48
-ast-stats-1 Local                     96 ( 1.4%)             1            96
-ast-stats-1 FnDecl                   120 ( 1.8%)             5            24
-ast-stats-1 Param                    160 ( 2.4%)             4            40
-ast-stats-1 Stmt                     160 ( 2.4%)             5            32
-ast-stats-1 - Let                       32 ( 0.5%)             1
-ast-stats-1 - MacCall                   32 ( 0.5%)             1
-ast-stats-1 - Expr                      96 ( 1.4%)             3
-ast-stats-1 Block                    192 ( 2.8%)             6            32
-ast-stats-1 FieldDef                 208 ( 3.1%)             2           104
-ast-stats-1 Variant                  208 ( 3.1%)             2           104
-ast-stats-1 AssocItem                320 ( 4.7%)             4            80
-ast-stats-1 - Fn                       160 ( 2.4%)             2
-ast-stats-1 - Type                     160 ( 2.4%)             2
-ast-stats-1 GenericBound             352 ( 5.2%)             4            88
-ast-stats-1 - Trait                    352 ( 5.2%)             4
-ast-stats-1 GenericParam             480 ( 7.1%)             5            96
-ast-stats-1 Pat                      504 ( 7.5%)             7            72
-ast-stats-1 - Struct                    72 ( 1.1%)             1
-ast-stats-1 - Wild                      72 ( 1.1%)             1
-ast-stats-1 - Ident                    360 ( 5.3%)             5
-ast-stats-1 Expr                     576 ( 8.5%)             8            72
-ast-stats-1 - Match                     72 ( 1.1%)             1
-ast-stats-1 - Path                      72 ( 1.1%)             1
-ast-stats-1 - Struct                    72 ( 1.1%)             1
-ast-stats-1 - Lit                      144 ( 2.1%)             2
-ast-stats-1 - Block                    216 ( 3.2%)             3
-ast-stats-1 PathSegment              744 (11.0%)            31            24
-ast-stats-1 Ty                       896 (13.3%)            14            64
-ast-stats-1 - Ptr                       64 ( 0.9%)             1
-ast-stats-1 - Ref                       64 ( 0.9%)             1
-ast-stats-1 - ImplicitSelf             128 ( 1.9%)             2
-ast-stats-1 - Path                     640 ( 9.5%)            10
-ast-stats-1 Item                   1_296 (19.2%)             9           144
-ast-stats-1 - Enum                     144 ( 2.1%)             1
-ast-stats-1 - ForeignMod               144 ( 2.1%)             1
-ast-stats-1 - Impl                     144 ( 2.1%)             1
-ast-stats-1 - Trait                    144 ( 2.1%)             1
-ast-stats-1 - Fn                       288 ( 4.3%)             2
-ast-stats-1 - Use                      432 ( 6.4%)             3
+ast-stats-1 Crate                     40 (NN.N%)             1            40
+ast-stats-1 GenericArgs               40 (NN.N%)             1            40
+ast-stats-1 - AngleBracketed            40 (NN.N%)             1
+ast-stats-1 ExprField                 48 (NN.N%)             1            48
+ast-stats-1 Attribute                 64 (NN.N%)             2            32
+ast-stats-1 - DocComment                32 (NN.N%)             1
+ast-stats-1 - Normal                    32 (NN.N%)             1
+ast-stats-1 WherePredicate            72 (NN.N%)             1            72
+ast-stats-1 - BoundPredicate            72 (NN.N%)             1
+ast-stats-1 ForeignItem               80 (NN.N%)             1            80
+ast-stats-1 - Fn                        80 (NN.N%)             1
+ast-stats-1 Arm                       96 (NN.N%)             2            48
+ast-stats-1 Local                     96 (NN.N%)             1            96
+ast-stats-1 FnDecl                   120 (NN.N%)             5            24
+ast-stats-1 Param                    160 (NN.N%)             4            40
+ast-stats-1 Stmt                     160 (NN.N%)             5            32
+ast-stats-1 - Let                       32 (NN.N%)             1
+ast-stats-1 - MacCall                   32 (NN.N%)             1
+ast-stats-1 - Expr                      96 (NN.N%)             3
+ast-stats-1 Block                    192 (NN.N%)             6            32
+ast-stats-1 FieldDef                 208 (NN.N%)             2           104
+ast-stats-1 Variant                  208 (NN.N%)             2           104
+ast-stats-1 AssocItem                320 (NN.N%)             4            80
+ast-stats-1 - Fn                       160 (NN.N%)             2
+ast-stats-1 - Type                     160 (NN.N%)             2
+ast-stats-1 GenericBound             352 (NN.N%)             4            88
+ast-stats-1 - Trait                    352 (NN.N%)             4
+ast-stats-1 GenericParam             480 (NN.N%)             5            96
+ast-stats-1 Pat                      504 (NN.N%)             7            72
+ast-stats-1 - Struct                    72 (NN.N%)             1
+ast-stats-1 - Wild                      72 (NN.N%)             1
+ast-stats-1 - Ident                    360 (NN.N%)             5
+ast-stats-1 Expr                     576 (NN.N%)             8            72
+ast-stats-1 - Match                     72 (NN.N%)             1
+ast-stats-1 - Path                      72 (NN.N%)             1
+ast-stats-1 - Struct                    72 (NN.N%)             1
+ast-stats-1 - Lit                      144 (NN.N%)             2
+ast-stats-1 - Block                    216 (NN.N%)             3
+ast-stats-1 PathSegment              744 (NN.N%)            31            24
+ast-stats-1 Ty                       896 (NN.N%)            14            64
+ast-stats-1 - Ptr                       64 (NN.N%)             1
+ast-stats-1 - Ref                       64 (NN.N%)             1
+ast-stats-1 - ImplicitSelf             128 (NN.N%)             2
+ast-stats-1 - Path                     640 (NN.N%)            10
+ast-stats-1 Item                   1_296 (NN.N%)             9           144
+ast-stats-1 - Enum                     144 (NN.N%)             1
+ast-stats-1 - ForeignMod               144 (NN.N%)             1
+ast-stats-1 - Impl                     144 (NN.N%)             1
+ast-stats-1 - Trait                    144 (NN.N%)             1
+ast-stats-1 - Fn                       288 (NN.N%)             2
+ast-stats-1 - Use                      432 (NN.N%)             3
 ast-stats-1 ----------------------------------------------------------------
 ast-stats-1 Total                  6_752                   116
 ast-stats-1
 ast-stats-2 POST EXPANSION AST STATS
 ast-stats-2 Name                Accumulated Size         Count     Item Size
 ast-stats-2 ----------------------------------------------------------------
-ast-stats-2 Crate                     40 ( 0.5%)             1            40
-ast-stats-2 GenericArgs               40 ( 0.5%)             1            40
-ast-stats-2 - AngleBracketed            40 ( 0.5%)             1
-ast-stats-2 ExprField                 48 ( 0.6%)             1            48
-ast-stats-2 WherePredicate            72 ( 1.0%)             1            72
-ast-stats-2 - BoundPredicate            72 ( 1.0%)             1
-ast-stats-2 ForeignItem               80 ( 1.1%)             1            80
-ast-stats-2 - Fn                        80 ( 1.1%)             1
-ast-stats-2 Arm                       96 ( 1.3%)             2            48
-ast-stats-2 Local                     96 ( 1.3%)             1            96
-ast-stats-2 FnDecl                   120 ( 1.6%)             5            24
-ast-stats-2 InlineAsm                120 ( 1.6%)             1           120
-ast-stats-2 Attribute                128 ( 1.7%)             4            32
-ast-stats-2 - DocComment                32 ( 0.4%)             1
-ast-stats-2 - Normal                    96 ( 1.3%)             3
-ast-stats-2 Param                    160 ( 2.2%)             4            40
-ast-stats-2 Stmt                     160 ( 2.2%)             5            32
-ast-stats-2 - Let                       32 ( 0.4%)             1
-ast-stats-2 - Semi                      32 ( 0.4%)             1
-ast-stats-2 - Expr                      96 ( 1.3%)             3
-ast-stats-2 Block                    192 ( 2.6%)             6            32
-ast-stats-2 FieldDef                 208 ( 2.8%)             2           104
-ast-stats-2 Variant                  208 ( 2.8%)             2           104
-ast-stats-2 AssocItem                320 ( 4.3%)             4            80
-ast-stats-2 - Fn                       160 ( 2.2%)             2
-ast-stats-2 - Type                     160 ( 2.2%)             2
-ast-stats-2 GenericBound             352 ( 4.7%)             4            88
-ast-stats-2 - Trait                    352 ( 4.7%)             4
-ast-stats-2 GenericParam             480 ( 6.5%)             5            96
-ast-stats-2 Pat                      504 ( 6.8%)             7            72
-ast-stats-2 - Struct                    72 ( 1.0%)             1
-ast-stats-2 - Wild                      72 ( 1.0%)             1
-ast-stats-2 - Ident                    360 ( 4.9%)             5
-ast-stats-2 Expr                     648 ( 8.7%)             9            72
-ast-stats-2 - InlineAsm                 72 ( 1.0%)             1
-ast-stats-2 - Match                     72 ( 1.0%)             1
-ast-stats-2 - Path                      72 ( 1.0%)             1
-ast-stats-2 - Struct                    72 ( 1.0%)             1
-ast-stats-2 - Lit                      144 ( 1.9%)             2
-ast-stats-2 - Block                    216 ( 2.9%)             3
-ast-stats-2 PathSegment              864 (11.7%)            36            24
-ast-stats-2 Ty                       896 (12.1%)            14            64
-ast-stats-2 - Ptr                       64 ( 0.9%)             1
-ast-stats-2 - Ref                       64 ( 0.9%)             1
-ast-stats-2 - ImplicitSelf             128 ( 1.7%)             2
-ast-stats-2 - Path                     640 ( 8.6%)            10
-ast-stats-2 Item                   1_584 (21.4%)            11           144
-ast-stats-2 - Enum                     144 ( 1.9%)             1
-ast-stats-2 - ExternCrate              144 ( 1.9%)             1
-ast-stats-2 - ForeignMod               144 ( 1.9%)             1
-ast-stats-2 - Impl                     144 ( 1.9%)             1
-ast-stats-2 - Trait                    144 ( 1.9%)             1
-ast-stats-2 - Fn                       288 ( 3.9%)             2
-ast-stats-2 - Use                      576 ( 7.8%)             4
+ast-stats-2 Crate                     40 (NN.N%)             1            40
+ast-stats-2 GenericArgs               40 (NN.N%)             1            40
+ast-stats-2 - AngleBracketed            40 (NN.N%)             1
+ast-stats-2 ExprField                 48 (NN.N%)             1            48
+ast-stats-2 WherePredicate            72 (NN.N%)             1            72
+ast-stats-2 - BoundPredicate            72 (NN.N%)             1
+ast-stats-2 ForeignItem               80 (NN.N%)             1            80
+ast-stats-2 - Fn                        80 (NN.N%)             1
+ast-stats-2 Arm                       96 (NN.N%)             2            48
+ast-stats-2 Local                     96 (NN.N%)             1            96
+ast-stats-2 FnDecl                   120 (NN.N%)             5            24
+ast-stats-2 InlineAsm                120 (NN.N%)             1           120
+ast-stats-2 Attribute                128 (NN.N%)             4            32
+ast-stats-2 - DocComment                32 (NN.N%)             1
+ast-stats-2 - Normal                    96 (NN.N%)             3
+ast-stats-2 Param                    160 (NN.N%)             4            40
+ast-stats-2 Stmt                     160 (NN.N%)             5            32
+ast-stats-2 - Let                       32 (NN.N%)             1
+ast-stats-2 - Semi                      32 (NN.N%)             1
+ast-stats-2 - Expr                      96 (NN.N%)             3
+ast-stats-2 Block                    192 (NN.N%)             6            32
+ast-stats-2 FieldDef                 208 (NN.N%)             2           104
+ast-stats-2 Variant                  208 (NN.N%)             2           104
+ast-stats-2 AssocItem                320 (NN.N%)             4            80
+ast-stats-2 - Fn                       160 (NN.N%)             2
+ast-stats-2 - Type                     160 (NN.N%)             2
+ast-stats-2 GenericBound             352 (NN.N%)             4            88
+ast-stats-2 - Trait                    352 (NN.N%)             4
+ast-stats-2 GenericParam             480 (NN.N%)             5            96
+ast-stats-2 Pat                      504 (NN.N%)             7            72
+ast-stats-2 - Struct                    72 (NN.N%)             1
+ast-stats-2 - Wild                      72 (NN.N%)             1
+ast-stats-2 - Ident                    360 (NN.N%)             5
+ast-stats-2 Expr                     648 (NN.N%)             9            72
+ast-stats-2 - InlineAsm                 72 (NN.N%)             1
+ast-stats-2 - Match                     72 (NN.N%)             1
+ast-stats-2 - Path                      72 (NN.N%)             1
+ast-stats-2 - Struct                    72 (NN.N%)             1
+ast-stats-2 - Lit                      144 (NN.N%)             2
+ast-stats-2 - Block                    216 (NN.N%)             3
+ast-stats-2 PathSegment              864 (NN.N%)            36            24
+ast-stats-2 Ty                       896 (NN.N%)            14            64
+ast-stats-2 - Ptr                       64 (NN.N%)             1
+ast-stats-2 - Ref                       64 (NN.N%)             1
+ast-stats-2 - ImplicitSelf             128 (NN.N%)             2
+ast-stats-2 - Path                     640 (NN.N%)            10
+ast-stats-2 Item                   1_584 (NN.N%)            11           144
+ast-stats-2 - Enum                     144 (NN.N%)             1
+ast-stats-2 - ExternCrate              144 (NN.N%)             1
+ast-stats-2 - ForeignMod               144 (NN.N%)             1
+ast-stats-2 - Impl                     144 (NN.N%)             1
+ast-stats-2 - Trait                    144 (NN.N%)             1
+ast-stats-2 - Fn                       288 (NN.N%)             2
+ast-stats-2 - Use                      576 (NN.N%)             4
 ast-stats-2 ----------------------------------------------------------------
 ast-stats-2 Total                  7_416                   127
 ast-stats-2
 hir-stats HIR STATS
 hir-stats Name                Accumulated Size         Count     Item Size
 hir-stats ----------------------------------------------------------------
-hir-stats ForeignItemRef            24 ( 0.3%)             1            24
-hir-stats Lifetime                  28 ( 0.3%)             1            28
-hir-stats Mod                       32 ( 0.4%)             1            32
-hir-stats ExprField                 40 ( 0.4%)             1            40
-hir-stats TraitItemRef              56 ( 0.6%)             2            28
-hir-stats GenericArg                64 ( 0.7%)             4            16
-hir-stats - Type                      16 ( 0.2%)             1
-hir-stats - Lifetime                  48 ( 0.5%)             3
-hir-stats Param                     64 ( 0.7%)             2            32
-hir-stats Body                      72 ( 0.8%)             3            24
-hir-stats ImplItemRef               72 ( 0.8%)             2            36
-hir-stats InlineAsm                 72 ( 0.8%)             1            72
-hir-stats Local                     72 ( 0.8%)             1            72
-hir-stats WherePredicate            72 ( 0.8%)             3            24
-hir-stats - BoundPredicate            72 ( 0.8%)             3
-hir-stats Arm                       80 ( 0.9%)             2            40
-hir-stats Stmt                      96 ( 1.1%)             3            32
-hir-stats - Expr                      32 ( 0.4%)             1
-hir-stats - Let                       32 ( 0.4%)             1
-hir-stats - Semi                      32 ( 0.4%)             1
-hir-stats FnDecl                   120 ( 1.3%)             3            40
-hir-stats Attribute                128 ( 1.4%)             4            32
-hir-stats FieldDef                 128 ( 1.4%)             2            64
-hir-stats GenericArgs              144 ( 1.6%)             3            48
-hir-stats Variant                  144 ( 1.6%)             2            72
-hir-stats GenericBound             256 ( 2.8%)             4            64
-hir-stats - Trait                    256 ( 2.8%)             4
-hir-stats Block                    288 ( 3.2%)             6            48
-hir-stats Pat                      360 ( 4.0%)             5            72
-hir-stats - Struct                    72 ( 0.8%)             1
-hir-stats - Wild                      72 ( 0.8%)             1
-hir-stats - Binding                  216 ( 2.4%)             3
-hir-stats GenericParam             400 ( 4.5%)             5            80
-hir-stats Generics                 560 ( 6.2%)            10            56
-hir-stats Ty                       720 ( 8.0%)            15            48
-hir-stats - Ptr                       48 ( 0.5%)             1
-hir-stats - Ref                       48 ( 0.5%)             1
-hir-stats - Path                     624 ( 6.9%)            13
-hir-stats Expr                     768 ( 8.5%)            12            64
-hir-stats - InlineAsm                 64 ( 0.7%)             1
-hir-stats - Match                     64 ( 0.7%)             1
-hir-stats - Path                      64 ( 0.7%)             1
-hir-stats - Struct                    64 ( 0.7%)             1
-hir-stats - Lit                      128 ( 1.4%)             2
-hir-stats - Block                    384 ( 4.3%)             6
-hir-stats Item                     968 (10.8%)            11            88
-hir-stats - Enum                      88 ( 1.0%)             1
-hir-stats - ExternCrate               88 ( 1.0%)             1
-hir-stats - ForeignMod                88 ( 1.0%)             1
-hir-stats - Impl                      88 ( 1.0%)             1
-hir-stats - Trait                     88 ( 1.0%)             1
-hir-stats - Fn                       176 ( 2.0%)             2
-hir-stats - Use                      352 ( 3.9%)             4
-hir-stats Path                   1_240 (13.8%)            31            40
-hir-stats PathSegment            1_920 (21.4%)            40            48
+hir-stats ForeignItemRef            24 (NN.N%)             1            24
+hir-stats Lifetime                  28 (NN.N%)             1            28
+hir-stats Mod                       32 (NN.N%)             1            32
+hir-stats ExprField                 40 (NN.N%)             1            40
+hir-stats TraitItemRef              56 (NN.N%)             2            28
+hir-stats GenericArg                64 (NN.N%)             4            16
+hir-stats - Type                      16 (NN.N%)             1
+hir-stats - Lifetime                  48 (NN.N%)             3
+hir-stats Param                     64 (NN.N%)             2            32
+hir-stats Body                      72 (NN.N%)             3            24
+hir-stats ImplItemRef               72 (NN.N%)             2            36
+hir-stats InlineAsm                 72 (NN.N%)             1            72
+hir-stats Local                     72 (NN.N%)             1            72
+hir-stats WherePredicate            72 (NN.N%)             3            24
+hir-stats - BoundPredicate            72 (NN.N%)             3
+hir-stats Arm                       80 (NN.N%)             2            40
+hir-stats Stmt                      96 (NN.N%)             3            32
+hir-stats - Expr                      32 (NN.N%)             1
+hir-stats - Let                       32 (NN.N%)             1
+hir-stats - Semi                      32 (NN.N%)             1
+hir-stats FnDecl                   120 (NN.N%)             3            40
+hir-stats Attribute                128 (NN.N%)             4            32
+hir-stats FieldDef                 128 (NN.N%)             2            64
+hir-stats GenericArgs              144 (NN.N%)             3            48
+hir-stats Variant                  144 (NN.N%)             2            72
+hir-stats GenericBound             256 (NN.N%)             4            64
+hir-stats - Trait                    256 (NN.N%)             4
+hir-stats Block                    288 (NN.N%)             6            48
+hir-stats Pat                      360 (NN.N%)             5            72
+hir-stats - Struct                    72 (NN.N%)             1
+hir-stats - Wild                      72 (NN.N%)             1
+hir-stats - Binding                  216 (NN.N%)             3
+hir-stats GenericParam             400 (NN.N%)             5            80
+hir-stats Generics                 560 (NN.N%)            10            56
+hir-stats Ty                       720 (NN.N%)            15            48
+hir-stats - Ptr                       48 (NN.N%)             1
+hir-stats - Ref                       48 (NN.N%)             1
+hir-stats - Path                     624 (NN.N%)            13
+hir-stats Expr                     768 (NN.N%)            12            64
+hir-stats - InlineAsm                 64 (NN.N%)             1
+hir-stats - Match                     64 (NN.N%)             1
+hir-stats - Path                      64 (NN.N%)             1
+hir-stats - Struct                    64 (NN.N%)             1
+hir-stats - Lit                      128 (NN.N%)             2
+hir-stats - Block                    384 (NN.N%)             6
+hir-stats Item                     968 (NN.N%)            11            88
+hir-stats - Enum                      88 (NN.N%)             1
+hir-stats - ExternCrate               88 (NN.N%)             1
+hir-stats - ForeignMod                88 (NN.N%)             1
+hir-stats - Impl                      88 (NN.N%)             1
+hir-stats - Trait                     88 (NN.N%)             1
+hir-stats - Fn                       176 (NN.N%)             2
+hir-stats - Use                      352 (NN.N%)             4
+hir-stats Path                   1_040 (NN.N%)            26            40
+hir-stats PathSegment            1_776 (NN.N%)            37            48
 hir-stats ----------------------------------------------------------------
-hir-stats Total                  8_988                   180
+hir-stats Total                  8_644                   172
 hir-stats
diff --git a/tests/ui/bare-static-string.rs b/tests/ui/str/str-static-literal.rs
index b71cf38cfe8..61630f0f22b 100644
--- a/tests/ui/bare-static-string.rs
+++ b/tests/ui/str/str-static-literal.rs
@@ -1,3 +1,5 @@
+//! Check that a bare string literal is typed as a `&'static str` and is usable.
+
 //@ run-pass
 
 pub fn main() {
diff --git a/tests/ui/suggestions/unnamable-types.rs b/tests/ui/suggestions/unnamable-types.rs
index 094584ff850..6772217a2f6 100644
--- a/tests/ui/suggestions/unnamable-types.rs
+++ b/tests/ui/suggestions/unnamable-types.rs
@@ -1,7 +1,7 @@
 // Test that we do not suggest to add type annotations for unnamable types.
 
 #![crate_type="lib"]
-#![feature(coroutines, stmt_expr_attributes)]
+#![feature(coroutines, stmt_expr_attributes, const_async_blocks)]
 
 const A = 5;
 //~^ ERROR: missing type for `const` item
diff --git a/tests/ui/threads-sendsync/tls-dont-move-after-init.rs b/tests/ui/threads-sendsync/tls-dont-move-after-init.rs
new file mode 100644
index 00000000000..54fcc32e9bd
--- /dev/null
+++ b/tests/ui/threads-sendsync/tls-dont-move-after-init.rs
@@ -0,0 +1,37 @@
+//@ run-pass
+//@ needs-threads
+
+use std::cell::Cell;
+use std::thread;
+
+#[derive(Default)]
+struct Foo {
+    ptr: Cell<*const Foo>,
+}
+
+impl Foo {
+    fn touch(&self) {
+        if self.ptr.get().is_null() {
+            self.ptr.set(self);
+        } else {
+            assert!(self.ptr.get() == self);
+        }
+    }
+}
+
+impl Drop for Foo {
+    fn drop(&mut self) {
+        self.touch();
+    }
+}
+
+thread_local!(static FOO: Foo = Foo::default());
+
+fn main() {
+    thread::spawn(|| {
+        FOO.with(|foo| foo.touch());
+        FOO.with(|foo| foo.touch());
+    })
+    .join()
+    .unwrap();
+}
diff --git a/tests/ui/traits/const-traits/staged-api.stderr b/tests/ui/traits/const-traits/staged-api.stderr
index cdf577287ee..4756c490cb1 100644
--- a/tests/ui/traits/const-traits/staged-api.stderr
+++ b/tests/ui/traits/const-traits/staged-api.stderr
@@ -71,16 +71,11 @@ error: const function that might be (indirectly) exposed to stable cannot use `#
 LL |     Unstable::func();
    |     ^^^^^^^^^^^^^^^^
    |
-help: if the function is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do)
+help: if the function is not (yet) meant to be exposed to stable const contexts, add `#[rustc_const_unstable]`
    |
 LL + #[rustc_const_unstable(feature = "...", issue = "...")]
 LL | const fn const_context() {
    |
-help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval)
-   |
-LL + #[rustc_allow_const_fn_unstable(const_trait_impl)]
-LL | const fn const_context() {
-   |
 
 error: const function that might be (indirectly) exposed to stable cannot use `#[feature(unstable)]`
   --> $DIR/staged-api.rs:38:5
@@ -88,16 +83,11 @@ error: const function that might be (indirectly) exposed to stable cannot use `#
 LL |     Unstable::func();
    |     ^^^^^^^^^^^^^^^^
    |
-help: if the function is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do)
+help: if the function is not (yet) meant to be exposed to stable const contexts, add `#[rustc_const_unstable]`
    |
 LL + #[rustc_const_unstable(feature = "...", issue = "...")]
 LL | const fn const_context() {
    |
-help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval)
-   |
-LL + #[rustc_allow_const_fn_unstable(unstable)]
-LL | const fn const_context() {
-   |
 
 error: const function that might be (indirectly) exposed to stable cannot use `#[feature(const_trait_impl)]`
   --> $DIR/staged-api.rs:41:5
@@ -105,16 +95,11 @@ error: const function that might be (indirectly) exposed to stable cannot use `#
 LL |     Foo::func();
    |     ^^^^^^^^^^^
    |
-help: if the function is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do)
+help: if the function is not (yet) meant to be exposed to stable const contexts, add `#[rustc_const_unstable]`
    |
 LL + #[rustc_const_unstable(feature = "...", issue = "...")]
 LL | const fn const_context() {
    |
-help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval)
-   |
-LL + #[rustc_allow_const_fn_unstable(const_trait_impl)]
-LL | const fn const_context() {
-   |
 
 error: const function that might be (indirectly) exposed to stable cannot use `#[feature(unstable)]`
   --> $DIR/staged-api.rs:41:5
@@ -122,16 +107,11 @@ error: const function that might be (indirectly) exposed to stable cannot use `#
 LL |     Foo::func();
    |     ^^^^^^^^^^^
    |
-help: if the function is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do)
+help: if the function is not (yet) meant to be exposed to stable const contexts, add `#[rustc_const_unstable]`
    |
 LL + #[rustc_const_unstable(feature = "...", issue = "...")]
 LL | const fn const_context() {
    |
-help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval)
-   |
-LL + #[rustc_allow_const_fn_unstable(unstable)]
-LL | const fn const_context() {
-   |
 
 error: const function that might be (indirectly) exposed to stable cannot use `#[feature(const_trait_impl)]`
   --> $DIR/staged-api.rs:44:5
@@ -139,16 +119,11 @@ error: const function that might be (indirectly) exposed to stable cannot use `#
 LL |     Unstable2::func();
    |     ^^^^^^^^^^^^^^^^^
    |
-help: if the function is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do)
+help: if the function is not (yet) meant to be exposed to stable const contexts, add `#[rustc_const_unstable]`
    |
 LL + #[rustc_const_unstable(feature = "...", issue = "...")]
 LL | const fn const_context() {
    |
-help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval)
-   |
-LL + #[rustc_allow_const_fn_unstable(const_trait_impl)]
-LL | const fn const_context() {
-   |
 
 error: const function that might be (indirectly) exposed to stable cannot use `#[feature(unstable)]`
   --> $DIR/staged-api.rs:44:5
@@ -156,16 +131,11 @@ error: const function that might be (indirectly) exposed to stable cannot use `#
 LL |     Unstable2::func();
    |     ^^^^^^^^^^^^^^^^^
    |
-help: if the function is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do)
+help: if the function is not (yet) meant to be exposed to stable const contexts, add `#[rustc_const_unstable]`
    |
 LL + #[rustc_const_unstable(feature = "...", issue = "...")]
 LL | const fn const_context() {
    |
-help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval)
-   |
-LL + #[rustc_allow_const_fn_unstable(unstable)]
-LL | const fn const_context() {
-   |
 
 error: const function that might be (indirectly) exposed to stable cannot use `#[feature(const_trait_impl)]`
   --> $DIR/staged-api.rs:47:5
@@ -173,16 +143,11 @@ error: const function that might be (indirectly) exposed to stable cannot use `#
 LL |     conditionally_const::<Foo>();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-help: if the function is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do)
+help: if the function is not (yet) meant to be exposed to stable const contexts, add `#[rustc_const_unstable]`
    |
 LL + #[rustc_const_unstable(feature = "...", issue = "...")]
 LL | const fn const_context() {
    |
-help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval)
-   |
-LL + #[rustc_allow_const_fn_unstable(const_trait_impl)]
-LL | const fn const_context() {
-   |
 
 error: const function that might be (indirectly) exposed to stable cannot use `#[feature(const_trait_impl)]`
   --> $DIR/staged-api.rs:63:5
@@ -190,16 +155,11 @@ error: const function that might be (indirectly) exposed to stable cannot use `#
 LL |     Unstable::func();
    |     ^^^^^^^^^^^^^^^^
    |
-help: if the function is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do)
+help: if the function is not (yet) meant to be exposed to stable const contexts, add `#[rustc_const_unstable]`
    |
 LL + #[rustc_const_unstable(feature = "...", issue = "...")]
 LL | const fn stable_const_context() {
    |
-help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval)
-   |
-LL + #[rustc_allow_const_fn_unstable(const_trait_impl)]
-LL | const fn stable_const_context() {
-   |
 
 error: const function that might be (indirectly) exposed to stable cannot use `#[feature(unstable)]`
   --> $DIR/staged-api.rs:63:5
@@ -207,16 +167,11 @@ error: const function that might be (indirectly) exposed to stable cannot use `#
 LL |     Unstable::func();
    |     ^^^^^^^^^^^^^^^^
    |
-help: if the function is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do)
+help: if the function is not (yet) meant to be exposed to stable const contexts, add `#[rustc_const_unstable]`
    |
 LL + #[rustc_const_unstable(feature = "...", issue = "...")]
 LL | const fn stable_const_context() {
    |
-help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval)
-   |
-LL + #[rustc_allow_const_fn_unstable(unstable)]
-LL | const fn stable_const_context() {
-   |
 
 error: const function that might be (indirectly) exposed to stable cannot use `#[feature(const_trait_impl)]`
   --> $DIR/staged-api.rs:66:5
@@ -224,16 +179,11 @@ error: const function that might be (indirectly) exposed to stable cannot use `#
 LL |     Foo::func();
    |     ^^^^^^^^^^^
    |
-help: if the function is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do)
+help: if the function is not (yet) meant to be exposed to stable const contexts, add `#[rustc_const_unstable]`
    |
 LL + #[rustc_const_unstable(feature = "...", issue = "...")]
 LL | const fn stable_const_context() {
    |
-help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval)
-   |
-LL + #[rustc_allow_const_fn_unstable(const_trait_impl)]
-LL | const fn stable_const_context() {
-   |
 
 error: const function that might be (indirectly) exposed to stable cannot use `#[feature(unstable)]`
   --> $DIR/staged-api.rs:66:5
@@ -241,16 +191,11 @@ error: const function that might be (indirectly) exposed to stable cannot use `#
 LL |     Foo::func();
    |     ^^^^^^^^^^^
    |
-help: if the function is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do)
+help: if the function is not (yet) meant to be exposed to stable const contexts, add `#[rustc_const_unstable]`
    |
 LL + #[rustc_const_unstable(feature = "...", issue = "...")]
 LL | const fn stable_const_context() {
    |
-help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval)
-   |
-LL + #[rustc_allow_const_fn_unstable(unstable)]
-LL | const fn stable_const_context() {
-   |
 
 error: const function that might be (indirectly) exposed to stable cannot use `#[feature(local_feature)]`
   --> $DIR/staged-api.rs:69:5
@@ -259,16 +204,11 @@ LL |     const_context_not_const_stable();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = help: mark the callee as `#[rustc_const_stable_indirect]` if it does not itself require any unstable features
-help: if the caller is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do)
+help: if the caller is not (yet) meant to be exposed to stable const contexts, add `#[rustc_const_unstable]`
    |
 LL + #[rustc_const_unstable(feature = "...", issue = "...")]
 LL | const fn stable_const_context() {
    |
-help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval)
-   |
-LL + #[rustc_allow_const_fn_unstable(local_feature)]
-LL | const fn stable_const_context() {
-   |
 
 error: const function that might be (indirectly) exposed to stable cannot use `#[feature(const_trait_impl)]`
   --> $DIR/staged-api.rs:71:5
@@ -276,16 +216,11 @@ error: const function that might be (indirectly) exposed to stable cannot use `#
 LL |     conditionally_const::<Foo>();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-help: if the function is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do)
+help: if the function is not (yet) meant to be exposed to stable const contexts, add `#[rustc_const_unstable]`
    |
 LL + #[rustc_const_unstable(feature = "...", issue = "...")]
 LL | const fn stable_const_context() {
    |
-help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval)
-   |
-LL + #[rustc_allow_const_fn_unstable(const_trait_impl)]
-LL | const fn stable_const_context() {
-   |
 
 error: const function that might be (indirectly) exposed to stable cannot use `#[feature(const_trait_impl)]`
   --> $DIR/staged-api.rs:76:5
@@ -293,16 +228,11 @@ error: const function that might be (indirectly) exposed to stable cannot use `#
 LL |     Unstable::func();
    |     ^^^^^^^^^^^^^^^^
    |
-help: if the function is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do)
+help: if the function is not (yet) meant to be exposed to stable const contexts, add `#[rustc_const_unstable]`
    |
 LL + #[rustc_const_unstable(feature = "...", issue = "...")]
 LL | const fn implicitly_stable_const_context() {
    |
-help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval)
-   |
-LL + #[rustc_allow_const_fn_unstable(const_trait_impl)]
-LL | const fn implicitly_stable_const_context() {
-   |
 
 error: const function that might be (indirectly) exposed to stable cannot use `#[feature(unstable)]`
   --> $DIR/staged-api.rs:76:5
@@ -310,16 +240,11 @@ error: const function that might be (indirectly) exposed to stable cannot use `#
 LL |     Unstable::func();
    |     ^^^^^^^^^^^^^^^^
    |
-help: if the function is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do)
+help: if the function is not (yet) meant to be exposed to stable const contexts, add `#[rustc_const_unstable]`
    |
 LL + #[rustc_const_unstable(feature = "...", issue = "...")]
 LL | const fn implicitly_stable_const_context() {
    |
-help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval)
-   |
-LL + #[rustc_allow_const_fn_unstable(unstable)]
-LL | const fn implicitly_stable_const_context() {
-   |
 
 error: const function that might be (indirectly) exposed to stable cannot use `#[feature(const_trait_impl)]`
   --> $DIR/staged-api.rs:79:5
@@ -327,16 +252,11 @@ error: const function that might be (indirectly) exposed to stable cannot use `#
 LL |     Foo::func();
    |     ^^^^^^^^^^^
    |
-help: if the function is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do)
+help: if the function is not (yet) meant to be exposed to stable const contexts, add `#[rustc_const_unstable]`
    |
 LL + #[rustc_const_unstable(feature = "...", issue = "...")]
 LL | const fn implicitly_stable_const_context() {
    |
-help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval)
-   |
-LL + #[rustc_allow_const_fn_unstable(const_trait_impl)]
-LL | const fn implicitly_stable_const_context() {
-   |
 
 error: const function that might be (indirectly) exposed to stable cannot use `#[feature(unstable)]`
   --> $DIR/staged-api.rs:79:5
@@ -344,16 +264,11 @@ error: const function that might be (indirectly) exposed to stable cannot use `#
 LL |     Foo::func();
    |     ^^^^^^^^^^^
    |
-help: if the function is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do)
+help: if the function is not (yet) meant to be exposed to stable const contexts, add `#[rustc_const_unstable]`
    |
 LL + #[rustc_const_unstable(feature = "...", issue = "...")]
 LL | const fn implicitly_stable_const_context() {
    |
-help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval)
-   |
-LL + #[rustc_allow_const_fn_unstable(unstable)]
-LL | const fn implicitly_stable_const_context() {
-   |
 
 error: const function that might be (indirectly) exposed to stable cannot use `#[feature(local_feature)]`
   --> $DIR/staged-api.rs:82:5
@@ -362,16 +277,11 @@ LL |     const_context_not_const_stable();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = help: mark the callee as `#[rustc_const_stable_indirect]` if it does not itself require any unstable features
-help: if the caller is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do)
+help: if the caller is not (yet) meant to be exposed to stable const contexts, add `#[rustc_const_unstable]`
    |
 LL + #[rustc_const_unstable(feature = "...", issue = "...")]
 LL | const fn implicitly_stable_const_context() {
    |
-help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval)
-   |
-LL + #[rustc_allow_const_fn_unstable(local_feature)]
-LL | const fn implicitly_stable_const_context() {
-   |
 
 error: const function that might be (indirectly) exposed to stable cannot use `#[feature(const_trait_impl)]`
   --> $DIR/staged-api.rs:84:5
@@ -379,16 +289,11 @@ error: const function that might be (indirectly) exposed to stable cannot use `#
 LL |     conditionally_const::<Foo>();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-help: if the function is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do)
+help: if the function is not (yet) meant to be exposed to stable const contexts, add `#[rustc_const_unstable]`
    |
 LL + #[rustc_const_unstable(feature = "...", issue = "...")]
 LL | const fn implicitly_stable_const_context() {
    |
-help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval)
-   |
-LL + #[rustc_allow_const_fn_unstable(const_trait_impl)]
-LL | const fn implicitly_stable_const_context() {
-   |
 
 error: aborting due to 24 previous errors
 
diff --git a/tests/ui/traits/issue-20692.rs b/tests/ui/traits/issue-20692.rs
index 10611a232f7..79edc389ec4 100644
--- a/tests/ui/traits/issue-20692.rs
+++ b/tests/ui/traits/issue-20692.rs
@@ -2,7 +2,6 @@ trait Array: Sized + Copy {}
 
 fn f<T: Array>(x: &T) {
     let _ = x
-    //~^ ERROR `Array` is not dyn compatible
     as
     &dyn Array;
     //~^ ERROR `Array` is not dyn compatible
diff --git a/tests/ui/traits/issue-20692.stderr b/tests/ui/traits/issue-20692.stderr
index 32e29de49a1..d4a18899dcb 100644
--- a/tests/ui/traits/issue-20692.stderr
+++ b/tests/ui/traits/issue-20692.stderr
@@ -1,8 +1,8 @@
 error[E0038]: the trait `Array` is not dyn compatible
-  --> $DIR/issue-20692.rs:7:5
+  --> $DIR/issue-20692.rs:6:10
    |
 LL |     &dyn Array;
-   |     ^^^^^^^^^^ `Array` is not dyn compatible
+   |          ^^^^^ `Array` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
       for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
@@ -14,23 +14,6 @@ LL | trait Array: Sized + Copy {}
    |       |      ...because it requires `Self: Sized`
    |       this trait is not dyn compatible...
 
-error[E0038]: the trait `Array` is not dyn compatible
-  --> $DIR/issue-20692.rs:4:13
-   |
-LL |     let _ = x
-   |             ^ `Array` is not dyn compatible
-   |
-note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
-  --> $DIR/issue-20692.rs:1:14
-   |
-LL | trait Array: Sized + Copy {}
-   |       -----  ^^^^^   ^^^^ ...because it requires `Self: Sized`
-   |       |      |
-   |       |      ...because it requires `Self: Sized`
-   |       this trait is not dyn compatible...
-   = note: required for the cast from `&T` to `&dyn Array`
-
-error: aborting due to 2 previous errors
+error: aborting due to 1 previous error
 
 For more information about this error, try `rustc --explain E0038`.
diff --git a/tests/ui/traits/issue-38604.rs b/tests/ui/traits/issue-38604.rs
index d90aa61ef9f..70f0ef0cb9c 100644
--- a/tests/ui/traits/issue-38604.rs
+++ b/tests/ui/traits/issue-38604.rs
@@ -12,5 +12,5 @@ impl Foo for () {
 
 fn main() {
     let _f: Box<dyn Foo> = //~ ERROR `Foo` is not dyn compatible
-        Box::new(()); //~ ERROR `Foo` is not dyn compatible
+        Box::new(());
 }
diff --git a/tests/ui/traits/issue-38604.stderr b/tests/ui/traits/issue-38604.stderr
index e6a6b44e730..0f39dc536eb 100644
--- a/tests/ui/traits/issue-38604.stderr
+++ b/tests/ui/traits/issue-38604.stderr
@@ -1,8 +1,8 @@
 error[E0038]: the trait `Foo` is not dyn compatible
-  --> $DIR/issue-38604.rs:14:13
+  --> $DIR/issue-38604.rs:14:21
    |
 LL |     let _f: Box<dyn Foo> =
-   |             ^^^^^^^^^^^^ `Foo` is not dyn compatible
+   |                     ^^^ `Foo` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
       for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
@@ -14,23 +14,6 @@ LL | trait Foo where u32: Q<Self> {
    |       this trait is not dyn compatible...
    = help: only type `()` implements `Foo`; consider using it directly instead.
 
-error[E0038]: the trait `Foo` is not dyn compatible
-  --> $DIR/issue-38604.rs:15:9
-   |
-LL |         Box::new(());
-   |         ^^^^^^^^^^^^ `Foo` is not dyn compatible
-   |
-note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
-  --> $DIR/issue-38604.rs:2:22
-   |
-LL | trait Foo where u32: Q<Self> {
-   |       ---            ^^^^^^^ ...because it uses `Self` as a type parameter
-   |       |
-   |       this trait is not dyn compatible...
-   = help: only type `()` implements `Foo`; consider using it directly instead.
-   = note: required for the cast from `Box<()>` to `Box<dyn Foo>`
-
-error: aborting due to 2 previous errors
+error: aborting due to 1 previous error
 
 For more information about this error, try `rustc --explain E0038`.
diff --git a/tests/ui/traits/item-privacy.rs b/tests/ui/traits/item-privacy.rs
index cdfd667a6f1..9f75e6e4c12 100644
--- a/tests/ui/traits/item-privacy.rs
+++ b/tests/ui/traits/item-privacy.rs
@@ -99,9 +99,7 @@ fn check_assoc_const() {
     S::C; // OK
     // A, B, C are resolved as inherent items, their traits don't need to be in scope
     <dyn C>::A;
-    //~^ ERROR associated constant `A` is private
-    //~| ERROR the trait `assoc_const::C` is not dyn compatible
-    //~| ERROR the trait `assoc_const::C` is not dyn compatible
+    //~^ ERROR the trait `assoc_const::C` is not dyn compatible
     <dyn C>::B;
     //~^ ERROR the trait `assoc_const::C` is not dyn compatible
     C::C; // OK
diff --git a/tests/ui/traits/item-privacy.stderr b/tests/ui/traits/item-privacy.stderr
index 1d3d8cb9843..bf59cd079a5 100644
--- a/tests/ui/traits/item-privacy.stderr
+++ b/tests/ui/traits/item-privacy.stderr
@@ -131,44 +131,10 @@ LL + use assoc_const::B;
    |
 
 error[E0038]: the trait `assoc_const::C` is not dyn compatible
-  --> $DIR/item-privacy.rs:101:6
+  --> $DIR/item-privacy.rs:101:10
    |
 LL |     <dyn C>::A;
-   |      ^^^^^ `assoc_const::C` is not dyn compatible
-   |
-note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
-  --> $DIR/item-privacy.rs:25:15
-   |
-LL |         const A: u8 = 0;
-   |               ^ ...because it contains this associated `const`
-...
-LL |         const B: u8 = 0;
-   |               ^ ...because it contains this associated `const`
-...
-LL |     pub trait C: A + B {
-   |               - this trait is not dyn compatible...
-LL |         const C: u8 = 0;
-   |               ^ ...because it contains this associated `const`
-   = help: consider moving `C` to another trait
-   = help: consider moving `A` to another trait
-   = help: consider moving `B` to another trait
-   = help: only type `S` implements `assoc_const::C`; consider using it directly instead.
-
-error[E0624]: associated constant `A` is private
-  --> $DIR/item-privacy.rs:101:14
-   |
-LL |         const A: u8 = 0;
-   |         ----------- private associated constant defined here
-...
-LL |     <dyn C>::A;
-   |              ^ private associated constant
-
-error[E0038]: the trait `assoc_const::C` is not dyn compatible
-  --> $DIR/item-privacy.rs:101:5
-   |
-LL |     <dyn C>::A;
-   |     ^^^^^^^^^^ `assoc_const::C` is not dyn compatible
+   |          ^ `assoc_const::C` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
       for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
@@ -190,10 +156,10 @@ LL |         const C: u8 = 0;
    = help: only type `S` implements `assoc_const::C`; consider using it directly instead.
 
 error[E0038]: the trait `assoc_const::C` is not dyn compatible
-  --> $DIR/item-privacy.rs:105:5
+  --> $DIR/item-privacy.rs:103:10
    |
 LL |     <dyn C>::B;
-   |     ^^^^^^^^^^ `assoc_const::C` is not dyn compatible
+   |          ^ `assoc_const::C` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
       for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
@@ -215,7 +181,7 @@ LL |         const C: u8 = 0;
    = help: only type `S` implements `assoc_const::C`; consider using it directly instead.
 
 error[E0223]: ambiguous associated type
-  --> $DIR/item-privacy.rs:118:12
+  --> $DIR/item-privacy.rs:116:12
    |
 LL |     let _: S::A;
    |            ^^^^
@@ -227,7 +193,7 @@ LL +     let _: <S as Example>::A;
    |
 
 error[E0223]: ambiguous associated type
-  --> $DIR/item-privacy.rs:119:12
+  --> $DIR/item-privacy.rs:117:12
    |
 LL |     let _: S::B;
    |            ^^^^
@@ -239,7 +205,7 @@ LL +     let _: <S as assoc_ty::B>::B;
    |
 
 error[E0223]: ambiguous associated type
-  --> $DIR/item-privacy.rs:120:12
+  --> $DIR/item-privacy.rs:118:12
    |
 LL |     let _: S::C;
    |            ^^^^
@@ -251,7 +217,7 @@ LL +     let _: <S as assoc_ty::C>::C;
    |
 
 error[E0624]: associated type `A` is private
-  --> $DIR/item-privacy.rs:122:12
+  --> $DIR/item-privacy.rs:120:12
    |
 LL |         type A = u8;
    |         ------ the associated type is defined here
@@ -260,7 +226,7 @@ LL |     let _: T::A;
    |            ^^^^ private associated type
 
 error[E0624]: associated type `A` is private
-  --> $DIR/item-privacy.rs:131:9
+  --> $DIR/item-privacy.rs:129:9
    |
 LL |         type A = u8;
    |         ------ the associated type is defined here
@@ -268,7 +234,7 @@ LL |         type A = u8;
 LL |         A = u8,
    |         ^^^^^^ private associated type
 
-error: aborting due to 17 previous errors
+error: aborting due to 15 previous errors
 
 Some errors have detailed explanations: E0038, E0223, E0599, E0624.
 For more information about an error, try `rustc --explain E0038`.
diff --git a/tests/ui/traits/next-solver/normalize/normalize-place-elem.rs b/tests/ui/traits/next-solver/normalize/normalize-place-elem.rs
new file mode 100644
index 00000000000..9a600875bb9
--- /dev/null
+++ b/tests/ui/traits/next-solver/normalize/normalize-place-elem.rs
@@ -0,0 +1,32 @@
+//@ check-pass
+//@ compile-flags: -Znext-solver
+
+// Regression test for <https://github.com/rust-lang/trait-system-refactor-initiative/issues/221>.
+// Ensure that we normalize after applying projection elems in MIR typeck.
+
+use std::marker::PhantomData;
+
+#[derive(Copy, Clone)]
+struct Span;
+
+trait AstKind {
+    type Inner;
+}
+
+struct WithSpan;
+impl AstKind for WithSpan {
+    type Inner
+        = (i32,);
+}
+
+struct Expr<'a> { f: &'a <WithSpan as AstKind>::Inner }
+
+impl Expr<'_> {
+    fn span(self) {
+        match self {
+            Self { f: (n,) } => {},
+        }
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/traits/non_lifetime_binders/supertrait-dyn-compatibility.rs b/tests/ui/traits/non_lifetime_binders/supertrait-dyn-compatibility.rs
index 28785ae3dea..96345732f0f 100644
--- a/tests/ui/traits/non_lifetime_binders/supertrait-dyn-compatibility.rs
+++ b/tests/ui/traits/non_lifetime_binders/supertrait-dyn-compatibility.rs
@@ -18,7 +18,5 @@ impl<T: ?Sized> Bar<T> for () {}
 fn main() {
     let x: &dyn Foo = &();
     //~^ ERROR the trait `Foo` is not dyn compatible
-    //~| ERROR the trait `Foo` is not dyn compatible
     needs_bar(x);
-    //~^ ERROR the trait `Foo` is not dyn compatible
 }
diff --git a/tests/ui/traits/non_lifetime_binders/supertrait-dyn-compatibility.stderr b/tests/ui/traits/non_lifetime_binders/supertrait-dyn-compatibility.stderr
index 43b69d0b50e..aead19c4527 100644
--- a/tests/ui/traits/non_lifetime_binders/supertrait-dyn-compatibility.stderr
+++ b/tests/ui/traits/non_lifetime_binders/supertrait-dyn-compatibility.stderr
@@ -8,10 +8,10 @@ LL | #![feature(non_lifetime_binders)]
    = note: `#[warn(incomplete_features)]` on by default
 
 error[E0038]: the trait `Foo` is not dyn compatible
-  --> $DIR/supertrait-dyn-compatibility.rs:19:23
+  --> $DIR/supertrait-dyn-compatibility.rs:19:17
    |
 LL |     let x: &dyn Foo = &();
-   |                       ^^^ `Foo` is not dyn compatible
+   |                 ^^^ `Foo` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
       for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
@@ -22,40 +22,7 @@ LL | trait Foo: for<T> Bar<T> {}
    |       |
    |       this trait is not dyn compatible...
    = help: only type `()` implements `Foo`; consider using it directly instead.
-   = note: required for the cast from `&()` to `&dyn Foo`
 
-error[E0038]: the trait `Foo` is not dyn compatible
-  --> $DIR/supertrait-dyn-compatibility.rs:19:12
-   |
-LL |     let x: &dyn Foo = &();
-   |            ^^^^^^^^ `Foo` is not dyn compatible
-   |
-note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
-  --> $DIR/supertrait-dyn-compatibility.rs:4:12
-   |
-LL | trait Foo: for<T> Bar<T> {}
-   |       ---  ^^^^^^^^^^^^^ ...because where clause cannot reference non-lifetime `for<...>` variables
-   |       |
-   |       this trait is not dyn compatible...
-   = help: only type `()` implements `Foo`; consider using it directly instead.
-
-error[E0038]: the trait `Foo` is not dyn compatible
-  --> $DIR/supertrait-dyn-compatibility.rs:22:5
-   |
-LL |     needs_bar(x);
-   |     ^^^^^^^^^ `Foo` is not dyn compatible
-   |
-note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
-  --> $DIR/supertrait-dyn-compatibility.rs:4:12
-   |
-LL | trait Foo: for<T> Bar<T> {}
-   |       ---  ^^^^^^^^^^^^^ ...because where clause cannot reference non-lifetime `for<...>` variables
-   |       |
-   |       this trait is not dyn compatible...
-   = help: only type `()` implements `Foo`; consider using it directly instead.
-
-error: aborting due to 3 previous errors; 1 warning emitted
+error: aborting due to 1 previous error; 1 warning emitted
 
 For more information about this error, try `rustc --explain E0038`.
diff --git a/tests/ui/traits/object/canonicalize-fresh-infer-vars-issue-103626.rs b/tests/ui/traits/object/canonicalize-fresh-infer-vars-issue-103626.rs
index 6fcd67b4950..9ac3b84dc12 100644
--- a/tests/ui/traits/object/canonicalize-fresh-infer-vars-issue-103626.rs
+++ b/tests/ui/traits/object/canonicalize-fresh-infer-vars-issue-103626.rs
@@ -9,8 +9,6 @@ trait Try {
 fn w<'a, T: 'a, F: Fn(&'a T)>() {
     let b: &dyn FromResidual = &();
     //~^ ERROR: the trait `FromResidual` is not dyn compatible
-    //~| ERROR: the trait `FromResidual` is not dyn compatible
-    //~| ERROR the type parameter `R` must be explicitly specified
 }
 
 fn main() {}
diff --git a/tests/ui/traits/object/canonicalize-fresh-infer-vars-issue-103626.stderr b/tests/ui/traits/object/canonicalize-fresh-infer-vars-issue-103626.stderr
index b4bbd65b2f4..707aa9e9713 100644
--- a/tests/ui/traits/object/canonicalize-fresh-infer-vars-issue-103626.stderr
+++ b/tests/ui/traits/object/canonicalize-fresh-infer-vars-issue-103626.stderr
@@ -1,47 +1,8 @@
-error[E0393]: the type parameter `R` must be explicitly specified
-  --> $DIR/canonicalize-fresh-infer-vars-issue-103626.rs:10:17
-   |
-LL | trait FromResidual<R = <Self as Try>::Residual> {
-   | ----------------------------------------------- type parameter `R` must be specified for this
-...
-LL |     let b: &dyn FromResidual = &();
-   |                 ^^^^^^^^^^^^
-   |
-   = note: because the parameter default references `Self`, the parameter must be specified on the object type
-help: set the type parameter to the desired type
-   |
-LL |     let b: &dyn FromResidual<R> = &();
-   |                             +++
-
 error[E0038]: the trait `FromResidual` is not dyn compatible
-  --> $DIR/canonicalize-fresh-infer-vars-issue-103626.rs:10:32
-   |
-LL |     let b: &dyn FromResidual = &();
-   |                                ^^^ `FromResidual` is not dyn compatible
-   |
-note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
-  --> $DIR/canonicalize-fresh-infer-vars-issue-103626.rs:2:8
-   |
-LL | trait FromResidual<R = <Self as Try>::Residual> {
-   |       ------------ this trait is not dyn compatible...
-LL |     fn from_residual(residual: R) -> Self;
-   |        ^^^^^^^^^^^^^ ...because associated function `from_residual` has no `self` parameter
-   = note: required for the cast from `&()` to `&dyn FromResidual<{type error}>`
-help: consider turning `from_residual` into a method by giving it a `&self` argument
-   |
-LL |     fn from_residual(&self, residual: R) -> Self;
-   |                      ++++++
-help: alternatively, consider constraining `from_residual` so it does not apply to trait objects
-   |
-LL |     fn from_residual(residual: R) -> Self where Self: Sized;
-   |                                           +++++++++++++++++
-
-error[E0038]: the trait `FromResidual` is not dyn compatible
-  --> $DIR/canonicalize-fresh-infer-vars-issue-103626.rs:10:12
+  --> $DIR/canonicalize-fresh-infer-vars-issue-103626.rs:10:17
    |
 LL |     let b: &dyn FromResidual = &();
-   |            ^^^^^^^^^^^^^^^^^ `FromResidual` is not dyn compatible
+   |                 ^^^^^^^^^^^^ `FromResidual` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
       for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
@@ -60,7 +21,6 @@ help: alternatively, consider constraining `from_residual` so it does not apply
 LL |     fn from_residual(residual: R) -> Self where Self: Sized;
    |                                           +++++++++++++++++
 
-error: aborting due to 3 previous errors
+error: aborting due to 1 previous error
 
-Some errors have detailed explanations: E0038, E0393.
-For more information about an error, try `rustc --explain E0038`.
+For more information about this error, try `rustc --explain E0038`.
diff --git a/tests/ui/traits/object/macro-matcher.stderr b/tests/ui/traits/object/macro-matcher.stderr
index 3c668ce99c7..94d5c189a43 100644
--- a/tests/ui/traits/object/macro-matcher.stderr
+++ b/tests/ui/traits/object/macro-matcher.stderr
@@ -1,19 +1,19 @@
-error[E0224]: at least one trait is required for an object type
-  --> $DIR/macro-matcher.rs:11:8
-   |
-LL |     m!(dyn 'static +);
-   |        ^^^^^^^^^^^^^
-
 error[E0038]: the trait `Copy` is not dyn compatible
-  --> $DIR/macro-matcher.rs:8:8
+  --> $DIR/macro-matcher.rs:8:12
    |
 LL |     m!(dyn Copy + Send + 'static);
-   |        ^^^^^^^^^^^^^^^^^^^^^^^^^ `Copy` is not dyn compatible
+   |            ^^^^ `Copy` is not dyn compatible
    |
    = note: the trait is not dyn compatible because it requires `Self: Sized`
    = note: for a trait to be dyn compatible it needs to allow building a vtable
            for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
 
+error[E0224]: at least one trait is required for an object type
+  --> $DIR/macro-matcher.rs:11:8
+   |
+LL |     m!(dyn 'static +);
+   |        ^^^^^^^^^^^^^
+
 error: aborting due to 2 previous errors
 
 Some errors have detailed explanations: E0038, E0224.
diff --git a/tests/ui/traits/object/safety.rs b/tests/ui/traits/object/safety.rs
index f4abcf8542e..ec039557b63 100644
--- a/tests/ui/traits/object/safety.rs
+++ b/tests/ui/traits/object/safety.rs
@@ -13,5 +13,4 @@ impl Tr for St {
 
 fn main() {
     let _: &dyn Tr = &St; //~ ERROR E0038
-    //~^ ERROR E0038
 }
diff --git a/tests/ui/traits/object/safety.stderr b/tests/ui/traits/object/safety.stderr
index 593e42619f4..c5637b43526 100644
--- a/tests/ui/traits/object/safety.stderr
+++ b/tests/ui/traits/object/safety.stderr
@@ -1,8 +1,8 @@
 error[E0038]: the trait `Tr` is not dyn compatible
-  --> $DIR/safety.rs:15:22
+  --> $DIR/safety.rs:15:17
    |
 LL |     let _: &dyn Tr = &St;
-   |                      ^^^ `Tr` is not dyn compatible
+   |                 ^^ `Tr` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
       for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
@@ -13,7 +13,6 @@ LL | trait Tr {
 LL |     fn foo();
    |        ^^^ ...because associated function `foo` has no `self` parameter
    = help: only type `St` implements `Tr`; consider using it directly instead.
-   = note: required for the cast from `&St` to `&dyn Tr`
 help: consider turning `foo` into a method by giving it a `&self` argument
    |
 LL |     fn foo(&self);
@@ -23,30 +22,6 @@ help: alternatively, consider constraining `foo` so it does not apply to trait o
 LL |     fn foo() where Self: Sized;
    |              +++++++++++++++++
 
-error[E0038]: the trait `Tr` is not dyn compatible
-  --> $DIR/safety.rs:15:12
-   |
-LL |     let _: &dyn Tr = &St;
-   |            ^^^^^^^ `Tr` is not dyn compatible
-   |
-note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
-  --> $DIR/safety.rs:4:8
-   |
-LL | trait Tr {
-   |       -- this trait is not dyn compatible...
-LL |     fn foo();
-   |        ^^^ ...because associated function `foo` has no `self` parameter
-   = help: only type `St` implements `Tr`; consider using it directly instead.
-help: consider turning `foo` into a method by giving it a `&self` argument
-   |
-LL |     fn foo(&self);
-   |            +++++
-help: alternatively, consider constraining `foo` so it does not apply to trait objects
-   |
-LL |     fn foo() where Self: Sized;
-   |              +++++++++++++++++
-
-error: aborting due to 2 previous errors
+error: aborting due to 1 previous error
 
 For more information about this error, try `rustc --explain E0038`.
diff --git a/tests/ui/traits/test-2.rs b/tests/ui/traits/test-2.rs
index 4ee880da87a..1b7fc55b99a 100644
--- a/tests/ui/traits/test-2.rs
+++ b/tests/ui/traits/test-2.rs
@@ -12,5 +12,4 @@ fn main() {
     //~^ ERROR method takes 1 generic argument but 2
     (Box::new(10) as Box<dyn bar>).dup();
     //~^ ERROR E0038
-    //~| ERROR E0038
 }
diff --git a/tests/ui/traits/test-2.stderr b/tests/ui/traits/test-2.stderr
index b52839c300e..6a8109281a8 100644
--- a/tests/ui/traits/test-2.stderr
+++ b/tests/ui/traits/test-2.stderr
@@ -27,10 +27,10 @@ LL | trait bar { fn dup(&self) -> Self; fn blah<X>(&self); }
    |                                       ^^^^ -
 
 error[E0038]: the trait `bar` is not dyn compatible
-  --> $DIR/test-2.rs:13:22
+  --> $DIR/test-2.rs:13:30
    |
 LL |     (Box::new(10) as Box<dyn bar>).dup();
-   |                      ^^^^^^^^^^^^ `bar` is not dyn compatible
+   |                              ^^^ `bar` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
       for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
@@ -49,31 +49,7 @@ LL | trait bar { fn dup(&self) -> Self; fn blah<X>(&self); }
            consider defining an enum where each variant holds one of these types,
            implementing `bar` for this new enum and using it instead
 
-error[E0038]: the trait `bar` is not dyn compatible
-  --> $DIR/test-2.rs:13:6
-   |
-LL |     (Box::new(10) as Box<dyn bar>).dup();
-   |      ^^^^^^^^^^^^ `bar` is not dyn compatible
-   |
-note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
-  --> $DIR/test-2.rs:4:30
-   |
-LL | trait bar { fn dup(&self) -> Self; fn blah<X>(&self); }
-   |       ---                    ^^^^     ^^^^ ...because method `blah` has generic type parameters
-   |       |                      |
-   |       |                      ...because method `dup` references the `Self` type in its return type
-   |       this trait is not dyn compatible...
-   = help: consider moving `dup` to another trait
-   = help: consider moving `blah` to another trait
-   = help: the following types implement `bar`:
-             i32
-             u32
-           consider defining an enum where each variant holds one of these types,
-           implementing `bar` for this new enum and using it instead
-   = note: required for the cast from `Box<{integer}>` to `Box<dyn bar>`
-
-error: aborting due to 4 previous errors
+error: aborting due to 3 previous errors
 
 Some errors have detailed explanations: E0038, E0107.
 For more information about an error, try `rustc --explain E0038`.
diff --git a/tests/ui/transmutability/enums/repr/should_handle_all.rs b/tests/ui/transmutability/enums/repr/should_handle_all.rs
index dec0126f22d..192b7cdcf72 100644
--- a/tests/ui/transmutability/enums/repr/should_handle_all.rs
+++ b/tests/ui/transmutability/enums/repr/should_handle_all.rs
@@ -1,8 +1,7 @@
 //@ check-pass
 #![crate_type = "lib"]
-#![feature(repr128)]
 #![feature(transmutability)]
-#![allow(dead_code, incomplete_features, non_camel_case_types)]
+#![allow(dead_code, non_camel_case_types)]
 
 mod assert {
     use std::mem::{Assume, TransmuteFrom};
diff --git a/tests/ui/transmute/unnecessary-transmutation.stderr b/tests/ui/transmute/unnecessary-transmutation.stderr
index 602e964f5b2..0132ac4776b 100644
--- a/tests/ui/transmute/unnecessary-transmutation.stderr
+++ b/tests/ui/transmute/unnecessary-transmutation.stderr
@@ -1,9 +1,12 @@
 error: unnecessary transmute
-  --> $DIR/unnecessary-transmutation.rs:16:29
+  --> $DIR/unnecessary-transmutation.rs:7:14
    |
-LL | pub static X: u8 = unsafe { transmute(true) };
-   |                             ^^^^^^^^^^^^^^^ help: replace this with: `(true) as u8`
+LL |     unsafe { transmute(x) }
+   |              ---------^^^
+   |              |
+   |              help: replace this with: `u32::to_ne_bytes`
    |
+   = help: there's also `to_le_bytes` and `to_be_bytes` if you expect a particular byte order
 note: the lint level is defined here
   --> $DIR/unnecessary-transmutation.rs:2:9
    |
@@ -11,36 +14,72 @@ LL | #![deny(unnecessary_transmutes)]
    |         ^^^^^^^^^^^^^^^^^^^^^^
 
 error: unnecessary transmute
-  --> $DIR/unnecessary-transmutation.rs:18:28
+  --> $DIR/unnecessary-transmutation.rs:12:14
+   |
+LL |     unsafe { transmute(from) }
+   |              ^^^^^^^^^^^^^^^
+   |
+help: replace this with
+   |
+LL -     unsafe { transmute(from) }
+LL +     unsafe { (from) as u8 }
    |
-LL | pub const Y: u8 = unsafe { transmute(true) };
-   |                            ^^^^^^^^^^^^^^^ help: replace this with: `(true) as u8`
 
 error: unnecessary transmute
-  --> $DIR/unnecessary-transmutation.rs:7:14
+  --> $DIR/unnecessary-transmutation.rs:16:29
    |
-LL |     unsafe { transmute(x) }
-   |              ^^^^^^^^^^^^ help: replace this with: `u32::to_ne_bytes(x)`
+LL | pub static X: u8 = unsafe { transmute(true) };
+   |                             ^^^^^^^^^^^^^^^
+   |
+help: replace this with
+   |
+LL - pub static X: u8 = unsafe { transmute(true) };
+LL + pub static X: u8 = unsafe { (true) as u8 };
    |
-   = help: there's also `to_le_bytes` and `to_be_bytes` if you expect a particular byte order
 
 error: unnecessary transmute
-  --> $DIR/unnecessary-transmutation.rs:12:14
+  --> $DIR/unnecessary-transmutation.rs:18:28
+   |
+LL | pub const Y: u8 = unsafe { transmute(true) };
+   |                            ^^^^^^^^^^^^^^^
+   |
+help: replace this with
+   |
+LL - pub const Y: u8 = unsafe { transmute(true) };
+LL + pub const Y: u8 = unsafe { (true) as u8 };
    |
-LL |     unsafe { transmute(from) }
-   |              ^^^^^^^^^^^^^^^ help: replace this with: `(from) as u8`
 
 error: unnecessary transmute
   --> $DIR/unnecessary-transmutation.rs:24:18
    |
 LL |         unsafe { transmute(x) }
-   |                  ^^^^^^^^^^^^ help: replace this with: `(x) as u8`
+   |                  ^^^^^^^^^^^^
+   |
+help: replace this with
+   |
+LL -         unsafe { transmute(x) }
+LL +         unsafe { (x) as u8 }
+   |
+
+error: unnecessary transmute
+  --> $DIR/unnecessary-transmutation.rs:30:22
+   |
+LL |     const { unsafe { transmute::<_, u8>(true) } };
+   |                      ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: replace this with
+   |
+LL -     const { unsafe { transmute::<_, u8>(true) } };
+LL +     const { unsafe { (true) as u8 } };
+   |
 
 error: unnecessary transmute
   --> $DIR/unnecessary-transmutation.rs:33:22
    |
 LL |         let x: u16 = transmute(*b"01");
-   |                      ^^^^^^^^^^^^^^^^^ help: replace this with: `u16::from_ne_bytes(*b"01")`
+   |                      ---------^^^^^^^^
+   |                      |
+   |                      help: replace this with: `u16::from_ne_bytes`
    |
    = help: there's also `from_le_bytes` and `from_be_bytes` if you expect a particular byte order
 
@@ -48,7 +87,9 @@ error: unnecessary transmute
   --> $DIR/unnecessary-transmutation.rs:35:26
    |
 LL |         let x: [u8; 2] = transmute(x);
-   |                          ^^^^^^^^^^^^ help: replace this with: `u16::to_ne_bytes(x)`
+   |                          ---------^^^
+   |                          |
+   |                          help: replace this with: `u16::to_ne_bytes`
    |
    = help: there's also `to_le_bytes` and `to_be_bytes` if you expect a particular byte order
 
@@ -56,7 +97,9 @@ error: unnecessary transmute
   --> $DIR/unnecessary-transmutation.rs:37:22
    |
 LL |         let x: u32 = transmute(*b"0123");
-   |                      ^^^^^^^^^^^^^^^^^^^ help: replace this with: `u32::from_ne_bytes(*b"0123")`
+   |                      ---------^^^^^^^^^^
+   |                      |
+   |                      help: replace this with: `u32::from_ne_bytes`
    |
    = help: there's also `from_le_bytes` and `from_be_bytes` if you expect a particular byte order
 
@@ -64,7 +107,9 @@ error: unnecessary transmute
   --> $DIR/unnecessary-transmutation.rs:39:26
    |
 LL |         let x: [u8; 4] = transmute(x);
-   |                          ^^^^^^^^^^^^ help: replace this with: `u32::to_ne_bytes(x)`
+   |                          ---------^^^
+   |                          |
+   |                          help: replace this with: `u32::to_ne_bytes`
    |
    = help: there's also `to_le_bytes` and `to_be_bytes` if you expect a particular byte order
 
@@ -72,7 +117,9 @@ error: unnecessary transmute
   --> $DIR/unnecessary-transmutation.rs:41:22
    |
 LL |         let x: u64 = transmute(*b"feriscat");
-   |                      ^^^^^^^^^^^^^^^^^^^^^^^ help: replace this with: `u64::from_ne_bytes(*b"feriscat")`
+   |                      ---------^^^^^^^^^^^^^^
+   |                      |
+   |                      help: replace this with: `u64::from_ne_bytes`
    |
    = help: there's also `from_le_bytes` and `from_be_bytes` if you expect a particular byte order
 
@@ -80,7 +127,9 @@ error: unnecessary transmute
   --> $DIR/unnecessary-transmutation.rs:43:26
    |
 LL |         let x: [u8; 8] = transmute(x);
-   |                          ^^^^^^^^^^^^ help: replace this with: `u64::to_ne_bytes(x)`
+   |                          ---------^^^
+   |                          |
+   |                          help: replace this with: `u64::to_ne_bytes`
    |
    = help: there's also `to_le_bytes` and `to_be_bytes` if you expect a particular byte order
 
@@ -88,7 +137,9 @@ error: unnecessary transmute
   --> $DIR/unnecessary-transmutation.rs:46:22
    |
 LL |         let y: i16 = transmute(*b"01");
-   |                      ^^^^^^^^^^^^^^^^^ help: replace this with: `i16::from_ne_bytes(*b"01")`
+   |                      ---------^^^^^^^^
+   |                      |
+   |                      help: replace this with: `i16::from_ne_bytes`
    |
    = help: there's also `from_le_bytes` and `from_be_bytes` if you expect a particular byte order
 
@@ -96,7 +147,9 @@ error: unnecessary transmute
   --> $DIR/unnecessary-transmutation.rs:48:26
    |
 LL |         let y: [u8; 2] = transmute(y);
-   |                          ^^^^^^^^^^^^ help: replace this with: `i16::to_ne_bytes(y)`
+   |                          ---------^^^
+   |                          |
+   |                          help: replace this with: `i16::to_ne_bytes`
    |
    = help: there's also `to_le_bytes` and `to_be_bytes` if you expect a particular byte order
 
@@ -104,7 +157,9 @@ error: unnecessary transmute
   --> $DIR/unnecessary-transmutation.rs:50:22
    |
 LL |         let y: i32 = transmute(*b"0123");
-   |                      ^^^^^^^^^^^^^^^^^^^ help: replace this with: `i32::from_ne_bytes(*b"0123")`
+   |                      ---------^^^^^^^^^^
+   |                      |
+   |                      help: replace this with: `i32::from_ne_bytes`
    |
    = help: there's also `from_le_bytes` and `from_be_bytes` if you expect a particular byte order
 
@@ -112,7 +167,9 @@ error: unnecessary transmute
   --> $DIR/unnecessary-transmutation.rs:52:26
    |
 LL |         let y: [u8; 4] = transmute(y);
-   |                          ^^^^^^^^^^^^ help: replace this with: `i32::to_ne_bytes(y)`
+   |                          ---------^^^
+   |                          |
+   |                          help: replace this with: `i32::to_ne_bytes`
    |
    = help: there's also `to_le_bytes` and `to_be_bytes` if you expect a particular byte order
 
@@ -120,7 +177,9 @@ error: unnecessary transmute
   --> $DIR/unnecessary-transmutation.rs:54:22
    |
 LL |         let y: i64 = transmute(*b"feriscat");
-   |                      ^^^^^^^^^^^^^^^^^^^^^^^ help: replace this with: `i64::from_ne_bytes(*b"feriscat")`
+   |                      ---------^^^^^^^^^^^^^^
+   |                      |
+   |                      help: replace this with: `i64::from_ne_bytes`
    |
    = help: there's also `from_le_bytes` and `from_be_bytes` if you expect a particular byte order
 
@@ -128,7 +187,9 @@ error: unnecessary transmute
   --> $DIR/unnecessary-transmutation.rs:56:26
    |
 LL |         let y: [u8; 8] = transmute(y);
-   |                          ^^^^^^^^^^^^ help: replace this with: `i64::to_ne_bytes(y)`
+   |                          ---------^^^
+   |                          |
+   |                          help: replace this with: `i64::to_ne_bytes`
    |
    = help: there's also `to_le_bytes` and `to_be_bytes` if you expect a particular byte order
 
@@ -136,7 +197,9 @@ error: unnecessary transmute
   --> $DIR/unnecessary-transmutation.rs:59:22
    |
 LL |         let z: f32 = transmute(*b"0123");
-   |                      ^^^^^^^^^^^^^^^^^^^ help: replace this with: `f32::from_ne_bytes(*b"0123")`
+   |                      ---------^^^^^^^^^^
+   |                      |
+   |                      help: replace this with: `f32::from_ne_bytes`
    |
    = help: there's also `from_le_bytes` and `from_be_bytes` if you expect a particular byte order
 
@@ -144,7 +207,9 @@ error: unnecessary transmute
   --> $DIR/unnecessary-transmutation.rs:61:26
    |
 LL |         let z: [u8; 4] = transmute(z);
-   |                          ^^^^^^^^^^^^ help: replace this with: `f32::to_ne_bytes(z)`
+   |                          ---------^^^
+   |                          |
+   |                          help: replace this with: `f32::to_ne_bytes`
    |
    = help: there's also `to_le_bytes` and `to_be_bytes` if you expect a particular byte order
 
@@ -152,7 +217,9 @@ error: unnecessary transmute
   --> $DIR/unnecessary-transmutation.rs:63:22
    |
 LL |         let z: f64 = transmute(*b"feriscat");
-   |                      ^^^^^^^^^^^^^^^^^^^^^^^ help: replace this with: `f64::from_ne_bytes(*b"feriscat")`
+   |                      ---------^^^^^^^^^^^^^^
+   |                      |
+   |                      help: replace this with: `f64::from_ne_bytes`
    |
    = help: there's also `from_le_bytes` and `from_be_bytes` if you expect a particular byte order
 
@@ -160,7 +227,9 @@ error: unnecessary transmute
   --> $DIR/unnecessary-transmutation.rs:65:26
    |
 LL |         let z: [u8; 8] = transmute(z);
-   |                          ^^^^^^^^^^^^ help: replace this with: `f64::to_ne_bytes(z)`
+   |                          ---------^^^
+   |                          |
+   |                          help: replace this with: `f64::to_ne_bytes`
    |
    = help: there's also `to_le_bytes` and `to_be_bytes` if you expect a particular byte order
 
@@ -168,119 +237,164 @@ error: unnecessary transmute
   --> $DIR/unnecessary-transmutation.rs:68:22
    |
 LL |         let y: u32 = transmute('🦀');
-   |                      ^^^^^^^^^^^^^^^ help: replace this with: `u32::from('🦀')`
+   |                      ---------^^^^^^
+   |                      |
+   |                      help: replace this with: `u32::from`
 
 error: unnecessary transmute
   --> $DIR/unnecessary-transmutation.rs:70:23
    |
 LL |         let y: char = transmute(y);
-   |                       ^^^^^^^^^^^^ help: replace this with: `char::from_u32_unchecked(y)`
+   |                       ---------^^^
+   |                       |
+   |                       help: replace this with: `char::from_u32_unchecked`
    |
-   = help: consider `char::from_u32(…).unwrap()`
+   = help: consider using `char::from_u32(…).unwrap()`
 
 error: unnecessary transmute
   --> $DIR/unnecessary-transmutation.rs:72:22
    |
 LL |         let y: i32 = transmute('🐱');
-   |                      ^^^^^^^^^^^^^^^ help: replace this with: `u32::from('🐱').cast_signed()`
+   |                      ^^^^^^^^^^^^^^^
+   |
+help: replace this with
+   |
+LL -         let y: i32 = transmute('🐱');
+LL +         let y: i32 = u32::from('🐱').cast_signed();
+   |
 
 error: unnecessary transmute
   --> $DIR/unnecessary-transmutation.rs:74:23
    |
 LL |         let y: char = transmute(y);
-   |                       ^^^^^^^^^^^^ help: replace this with: `char::from_u32_unchecked(i32::cast_unsigned(y))`
+   |                       ^^^^^^^^^^^^
+   |
+   = help: consider using `char::from_u32(i32::cast_unsigned(…)).unwrap()`
+help: replace this with
+   |
+LL -         let y: char = transmute(y);
+LL +         let y: char = char::from_u32_unchecked(i32::cast_unsigned(y));
    |
-   = help: consider `char::from_u32(i32::cast_unsigned(…)).unwrap()`
 
 error: unnecessary transmute
   --> $DIR/unnecessary-transmutation.rs:77:22
    |
 LL |         let x: u16 = transmute(8i16);
-   |                      ^^^^^^^^^^^^^^^ help: replace this with: `i16::cast_unsigned(8i16)`
+   |                      ---------^^^^^^
+   |                      |
+   |                      help: replace this with: `i16::cast_unsigned`
 
 error: unnecessary transmute
   --> $DIR/unnecessary-transmutation.rs:79:22
    |
 LL |         let x: i16 = transmute(x);
-   |                      ^^^^^^^^^^^^ help: replace this with: `u16::cast_signed(x)`
+   |                      ---------^^^
+   |                      |
+   |                      help: replace this with: `u16::cast_signed`
 
 error: unnecessary transmute
   --> $DIR/unnecessary-transmutation.rs:81:22
    |
 LL |         let x: u32 = transmute(4i32);
-   |                      ^^^^^^^^^^^^^^^ help: replace this with: `i32::cast_unsigned(4i32)`
+   |                      ---------^^^^^^
+   |                      |
+   |                      help: replace this with: `i32::cast_unsigned`
 
 error: unnecessary transmute
   --> $DIR/unnecessary-transmutation.rs:83:22
    |
 LL |         let x: i32 = transmute(x);
-   |                      ^^^^^^^^^^^^ help: replace this with: `u32::cast_signed(x)`
+   |                      ---------^^^
+   |                      |
+   |                      help: replace this with: `u32::cast_signed`
 
 error: unnecessary transmute
   --> $DIR/unnecessary-transmutation.rs:85:22
    |
 LL |         let x: u64 = transmute(7i64);
-   |                      ^^^^^^^^^^^^^^^ help: replace this with: `i64::cast_unsigned(7i64)`
+   |                      ---------^^^^^^
+   |                      |
+   |                      help: replace this with: `i64::cast_unsigned`
 
 error: unnecessary transmute
   --> $DIR/unnecessary-transmutation.rs:87:22
    |
 LL |         let x: i64 = transmute(x);
-   |                      ^^^^^^^^^^^^ help: replace this with: `u64::cast_signed(x)`
+   |                      ---------^^^
+   |                      |
+   |                      help: replace this with: `u64::cast_signed`
 
 error: unnecessary transmute
   --> $DIR/unnecessary-transmutation.rs:90:22
    |
 LL |         let y: f32 = transmute(1u32);
-   |                      ^^^^^^^^^^^^^^^ help: replace this with: `f32::from_bits(1u32)`
+   |                      ---------^^^^^^
+   |                      |
+   |                      help: replace this with: `f32::from_bits`
 
 error: unnecessary transmute
   --> $DIR/unnecessary-transmutation.rs:92:22
    |
 LL |         let y: u32 = transmute(y);
-   |                      ^^^^^^^^^^^^ help: replace this with: `f32::to_bits(y)`
+   |                      ---------^^^
+   |                      |
+   |                      help: replace this with: `f32::to_bits`
 
 error: unnecessary transmute
   --> $DIR/unnecessary-transmutation.rs:94:22
    |
 LL |         let y: f64 = transmute(3u64);
-   |                      ^^^^^^^^^^^^^^^ help: replace this with: `f64::from_bits(3u64)`
+   |                      ---------^^^^^^
+   |                      |
+   |                      help: replace this with: `f64::from_bits`
 
 error: unnecessary transmute
   --> $DIR/unnecessary-transmutation.rs:96:22
    |
 LL |         let y: u64 = transmute(2.0);
-   |                      ^^^^^^^^^^^^^^ help: replace this with: `f64::to_bits(2.0)`
+   |                      ---------^^^^^
+   |                      |
+   |                      help: replace this with: `f64::to_bits`
 
 error: unnecessary transmute
   --> $DIR/unnecessary-transmutation.rs:99:22
    |
 LL |         let y: f64 = transmute(1i64);
-   |                      ^^^^^^^^^^^^^^^ help: replace this with: `f64::from_bits(i64::cast_unsigned(1i64))`
+   |                      ^^^^^^^^^^^^^^^
+   |
+help: replace this with
+   |
+LL -         let y: f64 = transmute(1i64);
+LL +         let y: f64 = f64::from_bits(i64::cast_unsigned(1i64));
+   |
 
 error: unnecessary transmute
   --> $DIR/unnecessary-transmutation.rs:101:22
    |
 LL |         let y: i64 = transmute(1f64);
-   |                      ^^^^^^^^^^^^^^^ help: replace this with: `f64::to_bits(1f64).cast_signed()`
+   |                      ^^^^^^^^^^^^^^^
+   |
+help: replace this with
+   |
+LL -         let y: i64 = transmute(1f64);
+LL +         let y: i64 = f64::to_bits(1f64).cast_signed();
+   |
 
 error: unnecessary transmute
   --> $DIR/unnecessary-transmutation.rs:106:21
    |
 LL |         let z: u8 = transmute(z);
-   |                     ^^^^^^^^^^^^ help: replace this with: `u8::from(z)`
+   |                     ---------^^^
+   |                     |
+   |                     help: replace this with: `u8::from`
 
 error: unnecessary transmute
   --> $DIR/unnecessary-transmutation.rs:111:21
    |
 LL |         let z: i8 = transmute(z);
-   |                     ^^^^^^^^^^^^ help: replace this with: `i8::from(z)`
-
-error: unnecessary transmute
-  --> $DIR/unnecessary-transmutation.rs:30:22
-   |
-LL |     const { unsafe { transmute::<_, u8>(true) } };
-   |                      ^^^^^^^^^^^^^^^^^^^^^^^^ help: replace this with: `(true) as u8`
+   |                     ---------^^^
+   |                     |
+   |                     help: replace this with: `i8::from`
 
 error: aborting due to 40 previous errors
 
diff --git a/tests/ui/type-alias-impl-trait/issue-53678-coroutine-and-const-fn.rs b/tests/ui/type-alias-impl-trait/issue-53678-coroutine-and-const-fn.rs
index f02ccbbb93c..b258d2e156d 100644
--- a/tests/ui/type-alias-impl-trait/issue-53678-coroutine-and-const-fn.rs
+++ b/tests/ui/type-alias-impl-trait/issue-53678-coroutine-and-const-fn.rs
@@ -1,4 +1,4 @@
-#![feature(coroutines, coroutine_trait, rustc_attrs)]
+#![feature(coroutines, coroutine_trait, rustc_attrs, const_async_blocks)]
 #![feature(type_alias_impl_trait)]
 
 //@ check-pass
diff --git a/tests/ui/type/type-parameter-defaults-referencing-Self-ppaux.rs b/tests/ui/type/type-parameter-defaults-referencing-Self-ppaux.rs
index 444453dc694..b877ef569f6 100644
--- a/tests/ui/type/type-parameter-defaults-referencing-Self-ppaux.rs
+++ b/tests/ui/type/type-parameter-defaults-referencing-Self-ppaux.rs
@@ -13,5 +13,4 @@ fn main() {
     let x: i32 = 5;
     let y = x as dyn MyAdd<i32>;
     //~^ ERROR E0038
-    //~| ERROR cast to unsized type: `i32` as `dyn MyAdd<i32>`
 }
diff --git a/tests/ui/type/type-parameter-defaults-referencing-Self-ppaux.stderr b/tests/ui/type/type-parameter-defaults-referencing-Self-ppaux.stderr
index eea2e75a238..33478740d65 100644
--- a/tests/ui/type/type-parameter-defaults-referencing-Self-ppaux.stderr
+++ b/tests/ui/type/type-parameter-defaults-referencing-Self-ppaux.stderr
@@ -1,20 +1,8 @@
-error[E0620]: cast to unsized type: `i32` as `dyn MyAdd<i32>`
-  --> $DIR/type-parameter-defaults-referencing-Self-ppaux.rs:14:13
-   |
-LL |     let y = x as dyn MyAdd<i32>;
-   |             ^^^^^^^^^^^^^^^^^^^
-   |
-help: consider using a box or reference as appropriate
-  --> $DIR/type-parameter-defaults-referencing-Self-ppaux.rs:14:13
-   |
-LL |     let y = x as dyn MyAdd<i32>;
-   |             ^
-
 error[E0038]: the trait `MyAdd` is not dyn compatible
-  --> $DIR/type-parameter-defaults-referencing-Self-ppaux.rs:14:18
+  --> $DIR/type-parameter-defaults-referencing-Self-ppaux.rs:14:22
    |
 LL |     let y = x as dyn MyAdd<i32>;
-   |                  ^^^^^^^^^^^^^^ `MyAdd` is not dyn compatible
+   |                      ^^^^^^^^^^ `MyAdd` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
       for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
@@ -25,7 +13,6 @@ LL | trait MyAdd<Rhs=Self> { fn add(&self, other: &Rhs) -> Self; }
    = help: consider moving `add` to another trait
    = help: only type `i32` implements `MyAdd`; consider using it directly instead.
 
-error: aborting due to 2 previous errors
+error: aborting due to 1 previous error
 
-Some errors have detailed explanations: E0038, E0620.
-For more information about an error, try `rustc --explain E0038`.
+For more information about this error, try `rustc --explain E0038`.
diff --git a/tests/ui/typeck/consider-borrowing-141810-1.rs b/tests/ui/typeck/consider-borrowing-141810-1.rs
new file mode 100644
index 00000000000..94c2d690915
--- /dev/null
+++ b/tests/ui/typeck/consider-borrowing-141810-1.rs
@@ -0,0 +1,9 @@
+fn main() {
+    let x = if true {
+        &true
+    } else if false { //~ ERROR `if` and `else` have incompatible types [E0308]
+        true //~ HELP consider borrowing here
+    } else {
+        true
+    };
+}
diff --git a/tests/ui/typeck/consider-borrowing-141810-1.stderr b/tests/ui/typeck/consider-borrowing-141810-1.stderr
new file mode 100644
index 00000000000..9291721ac71
--- /dev/null
+++ b/tests/ui/typeck/consider-borrowing-141810-1.stderr
@@ -0,0 +1,28 @@
+error[E0308]: `if` and `else` have incompatible types
+  --> $DIR/consider-borrowing-141810-1.rs:4:12
+   |
+LL |        let x = if true {
+   |  ______________-
+LL | |          &true
+   | |          ----- expected because of this
+LL | |      } else if false {
+   | | ____________^
+LL | ||         true
+LL | ||     } else {
+LL | ||         true
+LL | ||     };
+   | ||     ^
+   | ||_____|
+   |  |_____`if` and `else` have incompatible types
+   |        expected `&bool`, found `bool`
+   |
+help: consider borrowing here
+   |
+LL ~         &true
+LL |     } else {
+LL ~         &true
+   |
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/typeck/consider-borrowing-141810-2.rs b/tests/ui/typeck/consider-borrowing-141810-2.rs
new file mode 100644
index 00000000000..e32e689efb7
--- /dev/null
+++ b/tests/ui/typeck/consider-borrowing-141810-2.rs
@@ -0,0 +1,8 @@
+fn main() {
+    let x = if true {
+        &()
+    } else if false { //~ ERROR `if` and `else` have incompatible types [E0308]
+    } else {
+    };
+
+}
diff --git a/tests/ui/typeck/consider-borrowing-141810-2.stderr b/tests/ui/typeck/consider-borrowing-141810-2.stderr
new file mode 100644
index 00000000000..dd229897283
--- /dev/null
+++ b/tests/ui/typeck/consider-borrowing-141810-2.stderr
@@ -0,0 +1,19 @@
+error[E0308]: `if` and `else` have incompatible types
+  --> $DIR/consider-borrowing-141810-2.rs:4:12
+   |
+LL |        let x = if true {
+   |  ______________-
+LL | |          &()
+   | |          --- expected because of this
+LL | |      } else if false {
+   | | ____________^
+LL | ||     } else {
+LL | ||     };
+   | ||     ^
+   | ||_____|
+   |  |_____`if` and `else` have incompatible types
+   |        expected `&()`, found `()`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/typeck/consider-borrowing-141810-3.rs b/tests/ui/typeck/consider-borrowing-141810-3.rs
new file mode 100644
index 00000000000..d38828de7c1
--- /dev/null
+++ b/tests/ui/typeck/consider-borrowing-141810-3.rs
@@ -0,0 +1,7 @@
+fn main() {
+    let x = if true {
+        &()
+    } else if false { //~ ERROR `if` and `else` have incompatible types [E0308]
+
+    };
+}
diff --git a/tests/ui/typeck/consider-borrowing-141810-3.stderr b/tests/ui/typeck/consider-borrowing-141810-3.stderr
new file mode 100644
index 00000000000..0b0c5f191a0
--- /dev/null
+++ b/tests/ui/typeck/consider-borrowing-141810-3.stderr
@@ -0,0 +1,22 @@
+error[E0308]: `if` and `else` have incompatible types
+  --> $DIR/consider-borrowing-141810-3.rs:4:12
+   |
+LL |        let x = if true {
+   |  ______________-
+LL | |          &()
+   | |          --- expected because of this
+LL | |      } else if false {
+   | | ____________^
+LL | ||
+LL | ||     };
+   | ||     ^
+   | ||_____|
+   |  |_____`if` and `else` have incompatible types
+   |        expected `&()`, found `()`
+   |
+   = note: `if` expressions without `else` evaluate to `()`
+   = note: consider adding an `else` block that evaluates to the expected type
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/typeck/consider-borrowing-141810-4.rs b/tests/ui/typeck/consider-borrowing-141810-4.rs
new file mode 100644
index 00000000000..754af7920a8
--- /dev/null
+++ b/tests/ui/typeck/consider-borrowing-141810-4.rs
@@ -0,0 +1,11 @@
+fn baz(x: &String) {}
+
+fn bar() {
+    baz({
+        String::from("hi") //~ ERROR mismatched types
+    });
+}
+
+fn main() {
+    bar();
+}
diff --git a/tests/ui/typeck/consider-borrowing-141810-4.stderr b/tests/ui/typeck/consider-borrowing-141810-4.stderr
new file mode 100644
index 00000000000..80869d4a5d5
--- /dev/null
+++ b/tests/ui/typeck/consider-borrowing-141810-4.stderr
@@ -0,0 +1,14 @@
+error[E0308]: mismatched types
+  --> $DIR/consider-borrowing-141810-4.rs:5:9
+   |
+LL |         String::from("hi")
+   |         ^^^^^^^^^^^^^^^^^^ expected `&String`, found `String`
+   |
+help: consider borrowing here
+   |
+LL |         &String::from("hi")
+   |         +
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/ufcs/ufcs-partially-resolved.stderr b/tests/ui/ufcs/ufcs-partially-resolved.stderr
index 0a9c190cb35..69d6bd74a73 100644
--- a/tests/ui/ufcs/ufcs-partially-resolved.stderr
+++ b/tests/ui/ufcs/ufcs-partially-resolved.stderr
@@ -235,8 +235,6 @@ LL |     <u8 as Dr>::X;
    |     ^^^^^^^^^^^^-
    |                 |
    |                 help: an associated function with a similar name exists: `Z`
-   |
-   = note: can't use a type alias as a constructor
 
 error[E0575]: expected associated type, found associated function `Dr::Z`
   --> $DIR/ufcs-partially-resolved.rs:54:12
diff --git a/tests/ui/unsafe-binders/cat-projection.rs b/tests/ui/unsafe-binders/cat-projection.rs
new file mode 100644
index 00000000000..0ce8579a688
--- /dev/null
+++ b/tests/ui/unsafe-binders/cat-projection.rs
@@ -0,0 +1,24 @@
+//@ revisions: e2015 e2021
+//@[e2015] edition: 2015
+//@[e2021] edition: 2021
+//@ check-pass
+
+#![feature(unsafe_binders)]
+#![allow(incomplete_features)]
+
+use std::unsafe_binder::unwrap_binder;
+
+#[derive(Copy, Clone)]
+pub struct S([usize; 8]);
+
+// Regression test for <https://github.com/rust-lang/rust/issues/141418>.
+pub fn by_value(x: unsafe<'a> S) -> usize {
+    unsafe { (|| unwrap_binder!(x).0[0])() }
+}
+
+// Regression test for <https://github.com/rust-lang/rust/issues/141417>.
+pub fn by_ref(x: unsafe<'a> &'a S) -> usize {
+    unsafe { (|| unwrap_binder!(x).0[0])() }
+}
+
+fn main() {}
diff --git a/tests/ui/unsafe-binders/unused-lifetimes-2.fixed b/tests/ui/unsafe-binders/unused-lifetimes-2.fixed
new file mode 100644
index 00000000000..714a5fdaf03
--- /dev/null
+++ b/tests/ui/unsafe-binders/unused-lifetimes-2.fixed
@@ -0,0 +1,20 @@
+// regression test for #141758
+//@ run-rustfix
+//@ check-pass
+
+#![warn(unused_lifetimes)]
+#![allow(incomplete_features, unused_imports, dead_code)]
+#![feature(unsafe_binders)]
+
+use std::unsafe_binder::unwrap_binder;
+
+#[derive(Copy, Clone)]
+pub struct S([usize; 8]);
+
+// Regression test for <https://github.com/rust-lang/rust/issues/141418>.
+pub fn by_value(_x: unsafe<'a> &'a S) -> usize {
+    //~^ WARN lifetime parameter `'b` never used
+    0
+}
+
+fn main() {}
diff --git a/tests/ui/unsafe-binders/unused-lifetimes-2.rs b/tests/ui/unsafe-binders/unused-lifetimes-2.rs
new file mode 100644
index 00000000000..5b34cf91163
--- /dev/null
+++ b/tests/ui/unsafe-binders/unused-lifetimes-2.rs
@@ -0,0 +1,20 @@
+// regression test for #141758
+//@ run-rustfix
+//@ check-pass
+
+#![warn(unused_lifetimes)]
+#![allow(incomplete_features, unused_imports, dead_code)]
+#![feature(unsafe_binders)]
+
+use std::unsafe_binder::unwrap_binder;
+
+#[derive(Copy, Clone)]
+pub struct S([usize; 8]);
+
+// Regression test for <https://github.com/rust-lang/rust/issues/141418>.
+pub fn by_value(_x: unsafe<'a, 'b> &'a S) -> usize {
+    //~^ WARN lifetime parameter `'b` never used
+    0
+}
+
+fn main() {}
diff --git a/tests/ui/unsafe-binders/unused-lifetimes-2.stderr b/tests/ui/unsafe-binders/unused-lifetimes-2.stderr
new file mode 100644
index 00000000000..bca8a15d56b
--- /dev/null
+++ b/tests/ui/unsafe-binders/unused-lifetimes-2.stderr
@@ -0,0 +1,16 @@
+warning: lifetime parameter `'b` never used
+  --> $DIR/unused-lifetimes-2.rs:15:32
+   |
+LL | pub fn by_value(_x: unsafe<'a, 'b> &'a S) -> usize {
+   |                              --^^
+   |                              |
+   |                              help: elide the unused lifetime
+   |
+note: the lint level is defined here
+  --> $DIR/unused-lifetimes-2.rs:5:9
+   |
+LL | #![warn(unused_lifetimes)]
+   |         ^^^^^^^^^^^^^^^^
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/unsafe-binders/unused-lifetimes.fixed b/tests/ui/unsafe-binders/unused-lifetimes.fixed
new file mode 100644
index 00000000000..4295b6a848c
--- /dev/null
+++ b/tests/ui/unsafe-binders/unused-lifetimes.fixed
@@ -0,0 +1,20 @@
+// regression test for #141758
+//@ run-rustfix
+//@ check-pass
+
+#![warn(unused_lifetimes)]
+#![allow(incomplete_features, unused_imports, dead_code)]
+#![feature(unsafe_binders)]
+
+use std::unsafe_binder::unwrap_binder;
+
+#[derive(Copy, Clone)]
+pub struct S([usize; 8]);
+
+// Regression test for <https://github.com/rust-lang/rust/issues/141418>.
+pub fn by_value(_x: S) -> usize {
+    //~^ WARN lifetime parameter `'a` never used
+    0
+}
+
+fn main() {}
diff --git a/tests/ui/unsafe-binders/unused-lifetimes.rs b/tests/ui/unsafe-binders/unused-lifetimes.rs
new file mode 100644
index 00000000000..b1382328318
--- /dev/null
+++ b/tests/ui/unsafe-binders/unused-lifetimes.rs
@@ -0,0 +1,20 @@
+// regression test for #141758
+//@ run-rustfix
+//@ check-pass
+
+#![warn(unused_lifetimes)]
+#![allow(incomplete_features, unused_imports, dead_code)]
+#![feature(unsafe_binders)]
+
+use std::unsafe_binder::unwrap_binder;
+
+#[derive(Copy, Clone)]
+pub struct S([usize; 8]);
+
+// Regression test for <https://github.com/rust-lang/rust/issues/141418>.
+pub fn by_value(_x: unsafe<'a> S) -> usize {
+    //~^ WARN lifetime parameter `'a` never used
+    0
+}
+
+fn main() {}
diff --git a/tests/ui/unsafe-binders/unused-lifetimes.stderr b/tests/ui/unsafe-binders/unused-lifetimes.stderr
new file mode 100644
index 00000000000..d9a5216301f
--- /dev/null
+++ b/tests/ui/unsafe-binders/unused-lifetimes.stderr
@@ -0,0 +1,14 @@
+warning: lifetime parameter `'a` never used
+  --> $DIR/unused-lifetimes.rs:15:28
+   |
+LL | pub fn by_value(_x: unsafe<'a> S) -> usize {
+   |                     -------^^-- help: elide the unused lifetime
+   |
+note: the lint level is defined here
+  --> $DIR/unused-lifetimes.rs:5:9
+   |
+LL | #![warn(unused_lifetimes)]
+   |         ^^^^^^^^^^^^^^^^
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/unsafe/move-out-of-non-copy.rs b/tests/ui/unsafe/move-out-of-non-copy.rs
new file mode 100644
index 00000000000..ca6bf4277a1
--- /dev/null
+++ b/tests/ui/unsafe/move-out-of-non-copy.rs
@@ -0,0 +1,15 @@
+//@ compile-flags: -Zvalidate-mir
+
+// Regression test for <https://github.com/rust-lang/rust/issues/141394>.
+
+#![feature(unsafe_binders)]
+#![allow(incomplete_features)]
+
+use std::unsafe_binder::unwrap_binder;
+
+fn id<T>(x: unsafe<> T) -> T {
+    //~^ ERROR the trait bound `T: Copy` is not satisfied
+    unsafe { unwrap_binder!(x) }
+}
+
+fn main() {}
diff --git a/tests/ui/unsafe/move-out-of-non-copy.stderr b/tests/ui/unsafe/move-out-of-non-copy.stderr
new file mode 100644
index 00000000000..4598742c92b
--- /dev/null
+++ b/tests/ui/unsafe/move-out-of-non-copy.stderr
@@ -0,0 +1,14 @@
+error[E0277]: the trait bound `T: Copy` is not satisfied
+  --> $DIR/move-out-of-non-copy.rs:10:13
+   |
+LL | fn id<T>(x: unsafe<> T) -> T {
+   |             ^^^^^^^^^^ the trait `Copy` is not implemented for `T`
+   |
+help: consider restricting type parameter `T` with trait `Copy`
+   |
+LL | fn id<T: std::marker::Copy>(x: unsafe<> T) -> T {
+   |        +++++++++++++++++++
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/wf/wf-dyn-incompatible.stderr b/tests/ui/wf/wf-dyn-incompatible.stderr
index e61b37d9293..2ba17b7aaef 100644
--- a/tests/ui/wf/wf-dyn-incompatible.stderr
+++ b/tests/ui/wf/wf-dyn-incompatible.stderr
@@ -1,8 +1,8 @@
 error[E0038]: the trait `A` is not dyn compatible
-  --> $DIR/wf-dyn-incompatible.rs:9:13
+  --> $DIR/wf-dyn-incompatible.rs:9:18
    |
 LL |     let _x: &dyn A;
-   |             ^^^^^^ `A` is not dyn compatible
+   |                  ^ `A` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
       for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
diff --git a/triagebot.toml b/triagebot.toml
index 9d7a0ef5aec..2bd0c185ad7 100644
--- a/triagebot.toml
+++ b/triagebot.toml
@@ -593,6 +593,13 @@ trigger_files = [
     "src/doc/rustc-dev-guide",
 ]
 
+[autolabel."A-LLVM"]
+trigger_files = [
+    "src/llvm-project",
+    "compiler/rustc_llvm",
+    "compiler/rustc_codegen_llvm",
+]
+
 [notify-zulip."I-prioritize"]
 zulip_stream = 245100 # #t-compiler/prioritization/alerts
 topic = "#{number} {title}"
@@ -1170,7 +1177,6 @@ contributing_url = "https://rustc-dev-guide.rust-lang.org/getting-started.html"
 users_on_vacation = [
     "fmease",
     "jyn514",
-    "spastorino",
 ]
 
 [[assign.warn_non_default_branch.exceptions]]
@@ -1190,6 +1196,7 @@ compiler = [
     "@BoxyUwU",
     "@compiler-errors",
     "@davidtwco",
+    "@eholk",
     "@fee1-dead",
     "@fmease",
     "@jieyouxu",
@@ -1409,8 +1416,10 @@ compiletest = [
 "/src/tools/rustdoc-gui-test" =                          ["bootstrap", "@onur-ozkan"]
 "/src/tools/libcxx-version" =                            ["@onur-ozkan"]
 
-# Enable tracking of PR review assignment
-# Documentation at: https://forge.rust-lang.org/triagebot/pr-assignment-tracking.html
+# Enable review queue tracking
+# Documentation at: https://forge.rust-lang.org/triagebot/review-queue-tracking.html
+[assign.review_prefs]
+
 [pr-tracking]
 
 # Enable issue transfers within the org
@@ -1432,3 +1441,8 @@ days-threshold = 14
 # Prevents mentions in commits to avoid users being spammed
 # Documentation at: https://forge.rust-lang.org/triagebot/no-mentions.html
 [no-mentions]
+
+# Allow members to formally register concerns (`@rustbot concern my concern`)
+# Documentation at: https://forge.rust-lang.org/triagebot/concern.html
+[concern]
+labels = ["S-waiting-on-concerns"]