about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_ast/src/tokenstream.rs4
-rw-r--r--compiler/rustc_ast_pretty/src/pprust/state.rs40
-rw-r--r--compiler/rustc_builtin_macros/src/assert/context.rs4
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/default.rs4
-rw-r--r--compiler/rustc_codegen_cranelift/src/driver/aot.rs2
-rw-r--r--compiler/rustc_codegen_gcc/src/lib.rs6
-rw-r--r--compiler/rustc_codegen_llvm/src/asm.rs1
-rw-r--r--compiler/rustc_codegen_llvm/src/back/archive.rs1
-rw-r--r--compiler/rustc_codegen_llvm/src/back/lto.rs20
-rw-r--r--compiler/rustc_codegen_llvm/src/back/write.rs24
-rw-r--r--compiler/rustc_codegen_llvm/src/builder.rs1
-rw-r--r--compiler/rustc_codegen_llvm/src/callee.rs1
-rw-r--r--compiler/rustc_codegen_llvm/src/common.rs1
-rw-r--r--compiler/rustc_codegen_llvm/src/consts.rs1
-rw-r--r--compiler/rustc_codegen_llvm/src/coverageinfo/map_data.rs1
-rw-r--r--compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs1
-rw-r--r--compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs1
-rw-r--r--compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs1
-rw-r--r--compiler/rustc_codegen_llvm/src/debuginfo/mod.rs1
-rw-r--r--compiler/rustc_codegen_llvm/src/debuginfo/utils.rs2
-rw-r--r--compiler/rustc_codegen_llvm/src/declare.rs1
-rw-r--r--compiler/rustc_codegen_llvm/src/intrinsic.rs1
-rw-r--r--compiler/rustc_codegen_llvm/src/lib.rs10
-rw-r--r--compiler/rustc_codegen_llvm/src/llvm/ffi.rs8
-rw-r--r--compiler/rustc_codegen_llvm/src/mono_item.rs1
-rw-r--r--compiler/rustc_codegen_llvm/src/type_of.rs1
-rw-r--r--compiler/rustc_codegen_ssa/messages.ftl2
-rw-r--r--compiler/rustc_codegen_ssa/src/assert_module_sources.rs1
-rw-r--r--compiler/rustc_codegen_ssa/src/back/link.rs40
-rw-r--r--compiler/rustc_codegen_ssa/src/back/linker.rs1
-rw-r--r--compiler/rustc_codegen_ssa/src/back/rpath.rs1
-rw-r--r--compiler/rustc_codegen_ssa/src/back/symbol_export.rs3
-rw-r--r--compiler/rustc_codegen_ssa/src/back/write.rs12
-rw-r--r--compiler/rustc_codegen_ssa/src/base.rs5
-rw-r--r--compiler/rustc_codegen_ssa/src/errors.rs4
-rw-r--r--compiler/rustc_codegen_ssa/src/lib.rs3
-rw-r--r--compiler/rustc_codegen_ssa/src/meth.rs1
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/analyze.rs1
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/block.rs1
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/locals.rs2
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/mod.rs1
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/operand.rs1
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/place.rs11
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/rvalue.rs1
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/statement.rs1
-rw-r--r--compiler/rustc_codegen_ssa/src/mono_item.rs1
-rw-r--r--compiler/rustc_codegen_ssa/src/size_of_val.rs1
-rw-r--r--compiler/rustc_codegen_ssa/src/traits/write.rs6
-rw-r--r--compiler/rustc_const_eval/messages.ftl7
-rw-r--r--compiler/rustc_const_eval/src/const_eval/dummy_machine.rs4
-rw-r--r--compiler/rustc_const_eval/src/const_eval/error.rs9
-rw-r--r--compiler/rustc_const_eval/src/const_eval/eval_queries.rs1
-rw-r--r--compiler/rustc_const_eval/src/const_eval/machine.rs3
-rw-r--r--compiler/rustc_const_eval/src/const_eval/mod.rs1
-rw-r--r--compiler/rustc_const_eval/src/const_eval/valtrees.rs1
-rw-r--r--compiler/rustc_const_eval/src/errors.rs16
-rw-r--r--compiler/rustc_const_eval/src/interpret/cast.rs1
-rw-r--r--compiler/rustc_const_eval/src/interpret/discriminant.rs9
-rw-r--r--compiler/rustc_const_eval/src/interpret/eval_context.rs18
-rw-r--r--compiler/rustc_const_eval/src/interpret/intern.rs1
-rw-r--r--compiler/rustc_const_eval/src/interpret/intrinsics.rs25
-rw-r--r--compiler/rustc_const_eval/src/interpret/machine.rs2
-rw-r--r--compiler/rustc_const_eval/src/interpret/memory.rs2
-rw-r--r--compiler/rustc_const_eval/src/interpret/operand.rs23
-rw-r--r--compiler/rustc_const_eval/src/interpret/operator.rs242
-rw-r--r--compiler/rustc_const_eval/src/interpret/place.rs1
-rw-r--r--compiler/rustc_const_eval/src/interpret/projection.rs2
-rw-r--r--compiler/rustc_const_eval/src/interpret/step.rs15
-rw-r--r--compiler/rustc_const_eval/src/interpret/terminator.rs3
-rw-r--r--compiler/rustc_const_eval/src/interpret/traits.rs1
-rw-r--r--compiler/rustc_const_eval/src/interpret/util.rs1
-rw-r--r--compiler/rustc_const_eval/src/interpret/validity.rs1
-rw-r--r--compiler/rustc_const_eval/src/interpret/visitor.rs1
-rw-r--r--compiler/rustc_const_eval/src/lib.rs3
-rw-r--r--compiler/rustc_const_eval/src/transform/check_consts/check.rs2
-rw-r--r--compiler/rustc_const_eval/src/transform/check_consts/ops.rs1
-rw-r--r--compiler/rustc_const_eval/src/transform/check_consts/post_drop_elaboration.rs1
-rw-r--r--compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs1
-rw-r--r--compiler/rustc_const_eval/src/util/alignment.rs1
-rw-r--r--compiler/rustc_const_eval/src/util/caller_location.rs1
-rw-r--r--compiler/rustc_error_messages/src/lib.rs4
-rw-r--r--compiler/rustc_expand/src/mbe.rs5
-rw-r--r--compiler/rustc_expand/src/mbe/quoted.rs30
-rw-r--r--compiler/rustc_expand/src/mbe/transcribe.rs15
-rw-r--r--compiler/rustc_expand/src/proc_macro_server.rs8
-rw-r--r--compiler/rustc_hir_analysis/src/check/region.rs4
-rw-r--r--compiler/rustc_hir_typeck/src/coercion.rs2
-rw-r--r--compiler/rustc_incremental/src/assert_dep_graph.rs2
-rw-r--r--compiler/rustc_incremental/src/lib.rs3
-rw-r--r--compiler/rustc_incremental/src/persist/dirty_clean.rs1
-rw-r--r--compiler/rustc_incremental/src/persist/file_format.rs1
-rw-r--r--compiler/rustc_incremental/src/persist/fs.rs1
-rw-r--r--compiler/rustc_incremental/src/persist/load.rs1
-rw-r--r--compiler/rustc_incremental/src/persist/save.rs1
-rw-r--r--compiler/rustc_incremental/src/persist/work_product.rs1
-rw-r--r--compiler/rustc_infer/messages.ftl4
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/mod.rs5
-rw-r--r--compiler/rustc_interface/src/interface.rs2
-rw-r--r--compiler/rustc_interface/src/lib.rs3
-rw-r--r--compiler/rustc_interface/src/passes.rs3
-rw-r--r--compiler/rustc_interface/src/util.rs2
-rw-r--r--compiler/rustc_lint/messages.ftl4
-rw-r--r--compiler/rustc_lint/src/builtin.rs10
-rw-r--r--compiler/rustc_lint/src/context.rs2
-rw-r--r--compiler/rustc_lint/src/context/diagnostics.rs1
-rw-r--r--compiler/rustc_lint/src/context/diagnostics/check_cfg.rs30
-rw-r--r--compiler/rustc_lint/src/early.rs1
-rw-r--r--compiler/rustc_lint/src/for_loops_over_fallibles.rs17
-rw-r--r--compiler/rustc_lint/src/foreign_modules.rs1
-rw-r--r--compiler/rustc_lint/src/internal.rs1
-rw-r--r--compiler/rustc_lint/src/late.rs2
-rw-r--r--compiler/rustc_lint/src/levels.rs1
-rw-r--r--compiler/rustc_lint/src/lib.rs3
-rw-r--r--compiler/rustc_lint/src/lints.rs39
-rw-r--r--compiler/rustc_lint/src/types.rs2
-rw-r--r--compiler/rustc_lint/src/unused.rs1
-rw-r--r--compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp19
-rw-r--r--compiler/rustc_metadata/messages.ftl6
-rw-r--r--compiler/rustc_metadata/src/creader.rs1
-rw-r--r--compiler/rustc_metadata/src/dependency_format.rs13
-rw-r--r--compiler/rustc_metadata/src/errors.rs4
-rw-r--r--compiler/rustc_metadata/src/lib.rs3
-rw-r--r--compiler/rustc_metadata/src/locator.rs1
-rw-r--r--compiler/rustc_metadata/src/native_libs.rs2
-rw-r--r--compiler/rustc_metadata/src/rmeta/decoder.rs1
-rw-r--r--compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs4
-rw-r--r--compiler/rustc_metadata/src/rmeta/encoder.rs3
-rw-r--r--compiler/rustc_metadata/src/rmeta/table.rs1
-rw-r--r--compiler/rustc_middle/src/hir/map/mod.rs6
-rw-r--r--compiler/rustc_middle/src/hooks/mod.rs1
-rw-r--r--compiler/rustc_middle/src/lib.rs3
-rw-r--r--compiler/rustc_middle/src/lint.rs1
-rw-r--r--compiler/rustc_middle/src/middle/region.rs1
-rw-r--r--compiler/rustc_middle/src/middle/stability.rs1
-rw-r--r--compiler/rustc_middle/src/mir/interpret/allocation/provenance_map.rs6
-rw-r--r--compiler/rustc_middle/src/mir/interpret/error.rs22
-rw-r--r--compiler/rustc_middle/src/mir/interpret/mod.rs1
-rw-r--r--compiler/rustc_middle/src/mir/interpret/queries.rs1
-rw-r--r--compiler/rustc_middle/src/mir/mod.rs1
-rw-r--r--compiler/rustc_middle/src/mir/mono.rs1
-rw-r--r--compiler/rustc_middle/src/mir/patch.rs1
-rw-r--r--compiler/rustc_middle/src/mir/pretty.rs1
-rw-r--r--compiler/rustc_middle/src/mir/tcx.rs18
-rw-r--r--compiler/rustc_middle/src/query/mod.rs19
-rw-r--r--compiler/rustc_middle/src/thir.rs1
-rw-r--r--compiler/rustc_middle/src/ty/_match.rs1
-rw-r--r--compiler/rustc_middle/src/ty/adt.rs1
-rw-r--r--compiler/rustc_middle/src/ty/consts.rs1
-rw-r--r--compiler/rustc_middle/src/ty/context.rs3
-rw-r--r--compiler/rustc_middle/src/ty/erase_regions.rs1
-rw-r--r--compiler/rustc_middle/src/ty/fold.rs1
-rw-r--r--compiler/rustc_middle/src/ty/generic_args.rs1
-rw-r--r--compiler/rustc_middle/src/ty/generics.rs1
-rw-r--r--compiler/rustc_middle/src/ty/impls_ty.rs1
-rw-r--r--compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs1
-rw-r--r--compiler/rustc_middle/src/ty/inhabitedness/mod.rs1
-rw-r--r--compiler/rustc_middle/src/ty/instance.rs1
-rw-r--r--compiler/rustc_middle/src/ty/layout.rs1
-rw-r--r--compiler/rustc_middle/src/ty/mod.rs1
-rw-r--r--compiler/rustc_middle/src/ty/normalize_erasing_regions.rs1
-rw-r--r--compiler/rustc_middle/src/ty/opaque_types.rs1
-rw-r--r--compiler/rustc_middle/src/ty/predicate.rs1
-rw-r--r--compiler/rustc_middle/src/ty/print/mod.rs1
-rw-r--r--compiler/rustc_middle/src/ty/print/pretty.rs2
-rw-r--r--compiler/rustc_middle/src/ty/region.rs1
-rw-r--r--compiler/rustc_middle/src/ty/relate.rs1
-rw-r--r--compiler/rustc_middle/src/ty/rvalue_scopes.rs1
-rw-r--r--compiler/rustc_middle/src/ty/trait_def.rs5
-rw-r--r--compiler/rustc_middle/src/ty/util.rs1
-rw-r--r--compiler/rustc_middle/src/ty/walk.rs1
-rw-r--r--compiler/rustc_middle/src/util/call_kind.rs1
-rw-r--r--compiler/rustc_middle/src/util/find_self_call.rs1
-rw-r--r--compiler/rustc_mir_build/messages.ftl23
-rw-r--r--compiler/rustc_mir_build/src/build/block.rs1
-rw-r--r--compiler/rustc_mir_build/src/build/cfg.rs1
-rw-r--r--compiler/rustc_mir_build/src/build/custom/parse.rs2
-rw-r--r--compiler/rustc_mir_build/src/build/expr/as_constant.rs1
-rw-r--r--compiler/rustc_mir_build/src/build/expr/as_operand.rs1
-rw-r--r--compiler/rustc_mir_build/src/build/expr/as_place.rs1
-rw-r--r--compiler/rustc_mir_build/src/build/expr/as_rvalue.rs1
-rw-r--r--compiler/rustc_mir_build/src/build/expr/as_temp.rs1
-rw-r--r--compiler/rustc_mir_build/src/build/expr/into.rs1
-rw-r--r--compiler/rustc_mir_build/src/build/expr/stmt.rs1
-rw-r--r--compiler/rustc_mir_build/src/build/matches/mod.rs4
-rw-r--r--compiler/rustc_mir_build/src/build/matches/simplify.rs1
-rw-r--r--compiler/rustc_mir_build/src/build/matches/test.rs1
-rw-r--r--compiler/rustc_mir_build/src/build/matches/util.rs1
-rw-r--r--compiler/rustc_mir_build/src/build/misc.rs1
-rw-r--r--compiler/rustc_mir_build/src/build/scope.rs1
-rw-r--r--compiler/rustc_mir_build/src/errors.rs28
-rw-r--r--compiler/rustc_mir_build/src/lib.rs3
-rw-r--r--compiler/rustc_mir_build/src/thir/constant.rs1
-rw-r--r--compiler/rustc_mir_build/src/thir/cx/block.rs4
-rw-r--r--compiler/rustc_mir_build/src/thir/cx/expr.rs1
-rw-r--r--compiler/rustc_mir_build/src/thir/cx/mod.rs1
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/check_match.rs1
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs1
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/mod.rs1
-rw-r--r--compiler/rustc_mir_build/src/thir/util.rs1
-rw-r--r--compiler/rustc_mir_dataflow/src/drop_flag_effects.rs1
-rw-r--r--compiler/rustc_mir_dataflow/src/elaborate_drops.rs1
-rw-r--r--compiler/rustc_mir_dataflow/src/framework/engine.rs1
-rw-r--r--compiler/rustc_mir_dataflow/src/impls/initialized.rs1
-rw-r--r--compiler/rustc_mir_dataflow/src/lib.rs3
-rw-r--r--compiler/rustc_mir_dataflow/src/move_paths/builder.rs1
-rw-r--r--compiler/rustc_mir_dataflow/src/rustc_peek.rs1
-rw-r--r--compiler/rustc_mir_dataflow/src/value_analysis.rs1
-rw-r--r--compiler/rustc_mir_transform/src/dataflow_const_prop.rs31
-rw-r--r--compiler/rustc_mir_transform/src/gvn.rs19
-rw-r--r--compiler/rustc_mir_transform/src/known_panics_lint.rs67
-rw-r--r--compiler/rustc_monomorphize/src/collector.rs1
-rw-r--r--compiler/rustc_monomorphize/src/collector/move_check.rs1
-rw-r--r--compiler/rustc_monomorphize/src/lib.rs3
-rw-r--r--compiler/rustc_monomorphize/src/partitioning.rs1
-rw-r--r--compiler/rustc_monomorphize/src/polymorphize.rs1
-rw-r--r--compiler/rustc_parse/src/lexer/mod.rs1
-rw-r--r--compiler/rustc_parse/src/lexer/unescape_error_reporting.rs1
-rw-r--r--compiler/rustc_parse/src/lib.rs3
-rw-r--r--compiler/rustc_parse/src/parser/diagnostics.rs1
-rw-r--r--compiler/rustc_parse/src/parser/expr.rs1
-rw-r--r--compiler/rustc_parse/src/parser/item.rs1
-rw-r--r--compiler/rustc_passes/src/check_attr.rs1
-rw-r--r--compiler/rustc_passes/src/diagnostic_items.rs2
-rw-r--r--compiler/rustc_passes/src/errors.rs4
-rw-r--r--compiler/rustc_passes/src/lib.rs3
-rw-r--r--compiler/rustc_passes/src/liveness.rs2
-rw-r--r--compiler/rustc_passes/src/loops.rs172
-rw-r--r--compiler/rustc_passes/src/reachable.rs1
-rw-r--r--compiler/rustc_passes/src/stability.rs6
-rw-r--r--compiler/rustc_passes/src/weak_lang_items.rs2
-rw-r--r--compiler/rustc_resolve/src/late.rs8
-rw-r--r--compiler/rustc_session/src/config.rs24
-rw-r--r--compiler/rustc_session/src/filesearch.rs8
-rw-r--r--compiler/rustc_session/src/session.rs25
-rw-r--r--compiler/rustc_smir/src/rustc_smir/context.rs47
-rw-r--r--compiler/rustc_ty_utils/src/abi.rs1
-rw-r--r--compiler/rustc_ty_utils/src/consts.rs1
-rw-r--r--compiler/rustc_ty_utils/src/instance.rs1
-rw-r--r--compiler/rustc_ty_utils/src/layout.rs1
-rw-r--r--compiler/rustc_ty_utils/src/lib.rs3
-rw-r--r--compiler/rustc_ty_utils/src/needs_drop.rs1
-rw-r--r--compiler/rustc_ty_utils/src/opaque_types.rs1
-rw-r--r--compiler/rustc_ty_utils/src/sig_types.rs1
-rw-r--r--compiler/rustc_ty_utils/src/ty.rs1
-rw-r--r--compiler/stable_mir/src/compiler_interface.rs15
-rw-r--r--compiler/stable_mir/src/mir/mono.rs4
-rw-r--r--compiler/stable_mir/src/ty.rs35
-rw-r--r--library/core/Cargo.toml4
-rw-r--r--library/core/src/fmt/mod.rs7
-rw-r--r--library/core/src/internal_macros.rs41
-rw-r--r--library/core/src/lib.rs1
-rw-r--r--library/core/src/slice/ascii.rs9
-rw-r--r--library/core/src/str/iter.rs6
-rw-r--r--library/core/src/str/mod.rs104
-rw-r--r--library/core/src/task/wake.rs11
-rw-r--r--library/core/tests/result.rs1
-rw-r--r--library/proc_macro/src/lib.rs12
-rw-r--r--library/std/Cargo.toml10
-rw-r--r--library/std/build.rs11
-rw-r--r--library/std/src/lib.rs4
-rw-r--r--library/std/src/sys/thread_local/fast_local.rs247
-rw-r--r--library/std/src/sys/thread_local/fast_local/eager.rs82
-rw-r--r--library/std/src/sys/thread_local/fast_local/lazy.rs122
-rw-r--r--library/std/src/sys/thread_local/fast_local/mod.rs122
-rw-r--r--library/std/src/sys/thread_local/mod.rs7
-rw-r--r--library/std/src/sys/thread_local/static_local.rs144
-rw-r--r--library/std/src/thread/mod.rs2
-rw-r--r--src/bootstrap/src/lib.rs2
-rw-r--r--src/librustdoc/clean/types.rs2
-rw-r--r--src/librustdoc/core.rs2
-rw-r--r--src/librustdoc/formats/cache.rs2
-rw-r--r--src/librustdoc/passes/collect_trait_impls.rs2
-rw-r--r--src/librustdoc/scrape_examples.rs2
-rw-r--r--src/tools/clippy/clippy_utils/src/lib.rs2
-rw-r--r--src/tools/compiletest/src/json.rs4
-rw-r--r--src/tools/miri/rust-version2
-rw-r--r--src/tools/miri/src/concurrency/data_race.rs11
-rw-r--r--src/tools/miri/src/helpers.rs4
-rw-r--r--src/tools/miri/src/intrinsics/atomic.rs8
-rw-r--r--src/tools/miri/src/intrinsics/mod.rs8
-rw-r--r--src/tools/miri/src/intrinsics/simd.rs36
-rw-r--r--src/tools/miri/src/machine.rs2
-rw-r--r--src/tools/miri/src/operator.rs12
-rw-r--r--src/tools/miri/src/shims/x86/mod.rs58
-rw-r--r--src/tools/miri/tests/fail/intrinsics/simd-shl-too-far.rs2
-rw-r--r--src/tools/miri/tests/fail/intrinsics/simd-shl-too-far.stderr4
-rw-r--r--src/tools/miri/tests/fail/intrinsics/simd-shr-too-far.rs2
-rw-r--r--src/tools/miri/tests/fail/intrinsics/simd-shr-too-far.stderr4
-rw-r--r--src/tools/miri/tests/fail/intrinsics/unchecked_add1.rs2
-rw-r--r--src/tools/miri/tests/fail/intrinsics/unchecked_add1.stderr4
-rw-r--r--src/tools/miri/tests/fail/intrinsics/unchecked_add2.rs2
-rw-r--r--src/tools/miri/tests/fail/intrinsics/unchecked_add2.stderr4
-rw-r--r--src/tools/miri/tests/fail/intrinsics/unchecked_mul1.rs2
-rw-r--r--src/tools/miri/tests/fail/intrinsics/unchecked_mul1.stderr4
-rw-r--r--src/tools/miri/tests/fail/intrinsics/unchecked_mul2.rs2
-rw-r--r--src/tools/miri/tests/fail/intrinsics/unchecked_mul2.stderr4
-rw-r--r--src/tools/miri/tests/fail/intrinsics/unchecked_sub1.rs2
-rw-r--r--src/tools/miri/tests/fail/intrinsics/unchecked_sub1.stderr4
-rw-r--r--src/tools/miri/tests/fail/intrinsics/unchecked_sub2.rs2
-rw-r--r--src/tools/miri/tests/fail/intrinsics/unchecked_sub2.stderr4
-rw-r--r--src/tools/run-make-support/src/cc.rs8
-rw-r--r--src/tools/run-make-support/src/rustc.rs9
-rw-r--r--src/tools/tidy/src/allowed_run_make_makefiles.txt7
-rw-r--r--src/tools/tidy/src/issues.txt2
-rw-r--r--src/tools/tidy/src/style.rs2
-rw-r--r--tests/codegen/noalias-freeze.rs21
-rw-r--r--tests/crashes/124348.rs7
-rw-r--r--tests/run-make/alloc-no-oom-handling/rmake.rs2
-rw-r--r--tests/run-make/alloc-no-rc/rmake.rs2
-rw-r--r--tests/run-make/alloc-no-sync/rmake.rs2
-rw-r--r--tests/run-make/core-no-oom-handling/Makefile6
-rw-r--r--tests/run-make/core-no-oom-handling/rmake.rs16
-rw-r--r--tests/run-make/deref-impl-rustdoc-ice/bar.rs (renamed from tests/run-make/issue-38237/bar.rs)0
-rw-r--r--tests/run-make/deref-impl-rustdoc-ice/baz.rs (renamed from tests/run-make/issue-38237/baz.rs)0
-rw-r--r--tests/run-make/deref-impl-rustdoc-ice/foo.rs (renamed from tests/run-make/issue-38237/foo.rs)0
-rw-r--r--tests/run-make/deref-impl-rustdoc-ice/rmake.rs16
-rw-r--r--tests/run-make/external-crate-panic-handle-no-lint/app.rs (renamed from tests/run-make/issue-53964/app.rs)0
-rw-r--r--tests/run-make/external-crate-panic-handle-no-lint/panic.rs (renamed from tests/run-make/issue-53964/panic.rs)0
-rw-r--r--tests/run-make/external-crate-panic-handle-no-lint/rmake.rs12
-rw-r--r--tests/run-make/issue-24445/Makefile11
-rw-r--r--tests/run-make/issue-30063/Makefile36
-rw-r--r--tests/run-make/issue-38237/Makefile6
-rw-r--r--tests/run-make/issue-46239/Makefile6
-rw-r--r--tests/run-make/issue-46239/main.rs8
-rw-r--r--tests/run-make/issue-53964/Makefile5
-rw-r--r--tests/run-make/non-pie-thread-local/foo.c (renamed from tests/run-make/issue-24445/foo.c)0
-rw-r--r--tests/run-make/non-pie-thread-local/foo.rs (renamed from tests/run-make/issue-24445/foo.rs)0
-rw-r--r--tests/run-make/non-pie-thread-local/rmake.rs34
-rw-r--r--tests/run-make/reset-codegen-1/foo.rs (renamed from tests/run-make/issue-30063/foo.rs)0
-rw-r--r--tests/run-make/reset-codegen-1/rmake.rs38
-rw-r--r--tests/run-make/rustdoc-scrape-examples-macros/Makefile19
-rw-r--r--tests/run-make/rustdoc-scrape-examples-macros/rmake.rs64
-rw-r--r--tests/ui-fulldeps/stable-mir/check_intrinsics.rs54
-rw-r--r--tests/ui/async-await/async-is-unwindsafe.rs1
-rw-r--r--tests/ui/async-await/async-is-unwindsafe.stderr43
-rw-r--r--tests/ui/async-await/context-is-sorta-unwindsafe.rs14
-rw-r--r--tests/ui/check-cfg/cargo-build-script.rs22
-rw-r--r--tests/ui/check-cfg/cargo-build-script.stderr43
-rw-r--r--tests/ui/consts/const-int-unchecked.stderr6
-rw-r--r--tests/ui/consts/erroneous_type_in_const_return_value.rs12
-rw-r--r--tests/ui/consts/erroneous_type_in_const_return_value.stderr14
-rw-r--r--tests/ui/consts/erroneous_type_in_promoted.rs14
-rw-r--r--tests/ui/consts/erroneous_type_in_promoted.stderr14
-rw-r--r--tests/ui/extern-flag/empty-extern-arg.stderr9
-rw-r--r--tests/ui/fn/fn_def_opaque_coercion_to_fn_ptr.rs57
-rw-r--r--tests/ui/fn/fn_def_opaque_coercion_to_fn_ptr.stderr38
-rw-r--r--tests/ui/inference/note-and-explain-ReVar-124973.rs8
-rw-r--r--tests/ui/inference/note-and-explain-ReVar-124973.stderr13
-rw-r--r--tests/ui/lint/for_loop_over_fallibles.rs22
-rw-r--r--tests/ui/lint/for_loop_over_fallibles.stderr62
-rw-r--r--tests/ui/lint/missing_copy_impl_trivial_bounds.rs21
-rw-r--r--tests/ui/loops/loop-if-else-break-issue-123261.fixed31
-rw-r--r--tests/ui/loops/loop-if-else-break-issue-123261.rs31
-rw-r--r--tests/ui/loops/loop-if-else-break-issue-123261.stderr59
-rw-r--r--tests/ui/parser/break-in-unlabeled-block-in-macro.stderr38
-rw-r--r--tests/ui/privacy/pub-priv-dep/auxiliary/diamond_priv_dep.rs9
-rw-r--r--tests/ui/privacy/pub-priv-dep/auxiliary/diamond_pub_dep.rs9
-rw-r--r--tests/ui/privacy/pub-priv-dep/auxiliary/indirect1.rs4
-rw-r--r--tests/ui/privacy/pub-priv-dep/auxiliary/indirect2.rs4
-rw-r--r--tests/ui/privacy/pub-priv-dep/auxiliary/pm.rs22
-rw-r--r--tests/ui/privacy/pub-priv-dep/auxiliary/priv_dep.rs9
-rw-r--r--tests/ui/privacy/pub-priv-dep/auxiliary/reexport.rs5
-rw-r--r--tests/ui/privacy/pub-priv-dep/auxiliary/shared.rs1
-rw-r--r--tests/ui/privacy/pub-priv-dep/diamond_deps.rs48
-rw-r--r--tests/ui/privacy/pub-priv-dep/diamond_deps.stderr14
-rw-r--r--tests/ui/privacy/pub-priv-dep/pub-priv1.rs67
-rw-r--r--tests/ui/privacy/pub-priv-dep/pub-priv1.stderr62
-rw-r--r--tests/ui/privacy/pub-priv-dep/reexport_from_priv.rs15
-rw-r--r--tests/ui/privacy/pub-priv-dep/shared_both_private.rs32
-rw-r--r--tests/ui/privacy/pub-priv-dep/shared_direct_private.rs39
-rw-r--r--tests/ui/privacy/pub-priv-dep/shared_indirect.rs29
-rw-r--r--tests/ui/pub/pub-reexport-priv-extern-crate.stderr5
-rw-r--r--tests/ui/rfcs/rfc-2396-target_feature-11/safe-calls.stderr2
-rw-r--r--tests/ui/threads-sendsync/issue-43733-2.rs30
-rw-r--r--tests/ui/threads-sendsync/issue-43733.rs32
-rw-r--r--tests/ui/threads-sendsync/issue-43733.stderr19
-rw-r--r--tests/ui/unsafe/edition-2024-unsafe_op_in_unsafe_fn.stderr3
-rw-r--r--tests/ui/unsafe/unsafe_op_in_unsafe_fn/edition_2024_default.stderr3
-rw-r--r--tests/ui/unsafe/unsafe_op_in_unsafe_fn/in_2024_compatibility.stderr3
-rw-r--r--tests/ui/unsafe/unsafe_op_in_unsafe_fn/rfc-2585-unsafe_op_in_unsafe_fn.stderr12
-rw-r--r--tests/ui/unsafe/unsafe_op_in_unsafe_fn/wrapping-unsafe-block-sugg.stderr17
-rw-r--r--triagebot.toml4
382 files changed, 2836 insertions, 1408 deletions
diff --git a/compiler/rustc_ast/src/tokenstream.rs b/compiler/rustc_ast/src/tokenstream.rs
index fb666550e93..3d46415507d 100644
--- a/compiler/rustc_ast/src/tokenstream.rs
+++ b/compiler/rustc_ast/src/tokenstream.rs
@@ -661,11 +661,11 @@ impl TokenStream {
             if attr_style == AttrStyle::Inner {
                 vec![
                     TokenTree::token_joint(token::Pound, span),
-                    TokenTree::token_alone(token::Not, span),
+                    TokenTree::token_joint_hidden(token::Not, span),
                     body,
                 ]
             } else {
-                vec![TokenTree::token_alone(token::Pound, span), body]
+                vec![TokenTree::token_joint_hidden(token::Pound, span), body]
             }
         }
     }
diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs
index 545b98a9135..f02fe4cf0a7 100644
--- a/compiler/rustc_ast_pretty/src/pprust/state.rs
+++ b/compiler/rustc_ast_pretty/src/pprust/state.rs
@@ -681,22 +681,40 @@ pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::Dere
         }
     }
 
+    // The easiest way to implement token stream pretty printing would be to
+    // print each token followed by a single space. But that would produce ugly
+    // output, so we go to some effort to do better.
+    //
+    // First, we track whether each token that appears in source code is
+    // followed by a space, with `Spacing`, and reproduce that in the output.
+    // This works well in a lot of cases. E.g. `stringify!(x + y)` produces
+    // "x + y" and `stringify!(x+y)` produces "x+y".
+    //
+    // But this doesn't work for code produced by proc macros (which have no
+    // original source text representation) nor for code produced by decl
+    // macros (which are tricky because the whitespace after tokens appearing
+    // in macro rules isn't always what you want in the produced output). For
+    // these we mostly use `Spacing::Alone`, which is the conservative choice.
+    //
+    // So we have a backup mechanism for when `Spacing::Alone` occurs between a
+    // pair of tokens: we check if that pair of tokens can obviously go
+    // together without a space between them. E.g. token `x` followed by token
+    // `,` is better printed as `x,` than `x ,`. (Even if the original source
+    // code was `x ,`.)
+    //
+    // Finally, we must be careful about changing the output. Token pretty
+    // printing is used by `stringify!` and `impl Display for
+    // proc_macro::TokenStream`, and some programs rely on the output having a
+    // particular form, even though they shouldn't. In particular, some proc
+    // macros do `format!({stream})` on a token stream and then "parse" the
+    // output with simple string matching that can't handle whitespace changes.
+    // E.g. we have seen cases where a proc macro can handle `a :: b` but not
+    // `a::b`. See #117433 for some examples.
     fn print_tts(&mut self, tts: &TokenStream, convert_dollar_crate: bool) {
         let mut iter = tts.trees().peekable();
         while let Some(tt) = iter.next() {
             let spacing = self.print_tt(tt, convert_dollar_crate);
             if let Some(next) = iter.peek() {
-                // Should we print a space after `tt`? There are two guiding
-                // factors.
-                // - `spacing` is the more important and accurate one. Most
-                //   tokens have good spacing information, and
-                //   `Joint`/`JointHidden` get used a lot.
-                // - `space_between` is the backup. Code produced by proc
-                //   macros has worse spacing information, with no
-                //   `JointHidden` usage and too much `Alone` usage, which
-                //   would result in over-spaced output such as
-                //   `( x () , y . z )`. `space_between` avoids some of the
-                //   excess whitespace.
                 if spacing == Spacing::Alone && space_between(tt, next) {
                     self.space();
                 }
diff --git a/compiler/rustc_builtin_macros/src/assert/context.rs b/compiler/rustc_builtin_macros/src/assert/context.rs
index 085ea3458bb..78144226114 100644
--- a/compiler/rustc_builtin_macros/src/assert/context.rs
+++ b/compiler/rustc_builtin_macros/src/assert/context.rs
@@ -153,7 +153,7 @@ impl<'cx, 'a> Context<'cx, 'a> {
     fn build_panic(&self, expr_str: &str, panic_path: Path) -> P<Expr> {
         let escaped_expr_str = escape_to_fmt(expr_str);
         let initial = [
-            TokenTree::token_joint_hidden(
+            TokenTree::token_joint(
                 token::Literal(token::Lit {
                     kind: token::LitKind::Str,
                     symbol: Symbol::intern(&if self.fmt_string.is_empty() {
@@ -172,7 +172,7 @@ impl<'cx, 'a> Context<'cx, 'a> {
         ];
         let captures = self.capture_decls.iter().flat_map(|cap| {
             [
-                TokenTree::token_joint_hidden(
+                TokenTree::token_joint(
                     token::Ident(cap.ident.name, IdentIsRaw::No),
                     cap.ident.span,
                 ),
diff --git a/compiler/rustc_builtin_macros/src/deriving/default.rs b/compiler/rustc_builtin_macros/src/deriving/default.rs
index bf92ddb3370..577523a1d5a 100644
--- a/compiler/rustc_builtin_macros/src/deriving/default.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/default.rs
@@ -3,7 +3,7 @@ use crate::deriving::generic::*;
 use crate::errors;
 use core::ops::ControlFlow;
 use rustc_ast as ast;
-use rustc_ast::visit::walk_list;
+use rustc_ast::visit::visit_opt;
 use rustc_ast::{attr, EnumDef, VariantData};
 use rustc_expand::base::{Annotatable, DummyResult, ExtCtxt};
 use rustc_span::symbol::Ident;
@@ -224,7 +224,7 @@ impl<'a, 'b> rustc_ast::visit::Visitor<'a> for DetectNonVariantDefaultAttr<'a, '
         self.visit_ident(v.ident);
         self.visit_vis(&v.vis);
         self.visit_variant_data(&v.data);
-        walk_list!(self, visit_anon_const, &v.disr_expr);
+        visit_opt!(self, visit_anon_const, &v.disr_expr);
         for attr in &v.attrs {
             rustc_ast::visit::walk_attribute(self, attr);
         }
diff --git a/compiler/rustc_codegen_cranelift/src/driver/aot.rs b/compiler/rustc_codegen_cranelift/src/driver/aot.rs
index fce4690f97d..394c810176a 100644
--- a/compiler/rustc_codegen_cranelift/src/driver/aot.rs
+++ b/compiler/rustc_codegen_cranelift/src/driver/aot.rs
@@ -200,7 +200,7 @@ fn produce_final_output_artifacts(
     // to get rid of it.
     for output_type in crate_output.outputs.keys() {
         match *output_type {
-            OutputType::Bitcode => {
+            OutputType::Bitcode | OutputType::ThinLinkBitcode => {
                 // Cranelift doesn't have bitcode
                 // user_wants_bitcode = true;
                 // // Copy to .bc, but always keep the .0.bc. There is a later
diff --git a/compiler/rustc_codegen_gcc/src/lib.rs b/compiler/rustc_codegen_gcc/src/lib.rs
index 3f2fadce9e4..b1785e150ad 100644
--- a/compiler/rustc_codegen_gcc/src/lib.rs
+++ b/compiler/rustc_codegen_gcc/src/lib.rs
@@ -335,6 +335,10 @@ impl ThinBufferMethods for ThinBuffer {
     fn data(&self) -> &[u8] {
         unimplemented!();
     }
+
+    fn thin_link_data(&self) -> &[u8] {
+        unimplemented!();
+    }
 }
 
 pub struct GccContext {
@@ -414,7 +418,7 @@ impl WriteBackendMethods for GccCodegenBackend {
         back::write::codegen(cgcx, dcx, module, config)
     }
 
-    fn prepare_thin(_module: ModuleCodegen<Self::Module>) -> (String, Self::ThinBuffer) {
+    fn prepare_thin(_module: ModuleCodegen<Self::Module>, _emit_summary: bool) -> (String, Self::ThinBuffer) {
         unimplemented!();
     }
 
diff --git a/compiler/rustc_codegen_llvm/src/asm.rs b/compiler/rustc_codegen_llvm/src/asm.rs
index 71d4343ee07..db28c6857b7 100644
--- a/compiler/rustc_codegen_llvm/src/asm.rs
+++ b/compiler/rustc_codegen_llvm/src/asm.rs
@@ -16,6 +16,7 @@ use rustc_middle::{bug, span_bug, ty::Instance};
 use rustc_span::{Pos, Span};
 use rustc_target::abi::*;
 use rustc_target::asm::*;
+use tracing::debug;
 
 use libc::{c_char, c_uint};
 use smallvec::SmallVec;
diff --git a/compiler/rustc_codegen_llvm/src/back/archive.rs b/compiler/rustc_codegen_llvm/src/back/archive.rs
index c304c0cbd3b..fa7e7e5377a 100644
--- a/compiler/rustc_codegen_llvm/src/back/archive.rs
+++ b/compiler/rustc_codegen_llvm/src/back/archive.rs
@@ -18,6 +18,7 @@ use rustc_codegen_ssa::back::archive::{
     get_native_object_symbols, try_extract_macho_fat_archive, ArArchiveBuilder,
     ArchiveBuildFailure, ArchiveBuilder, ArchiveBuilderBuilder, UnknownArchiveKind,
 };
+use tracing::trace;
 
 use rustc_session::cstore::DllImport;
 use rustc_session::Session;
diff --git a/compiler/rustc_codegen_llvm/src/back/lto.rs b/compiler/rustc_codegen_llvm/src/back/lto.rs
index e61af863dc0..bb7c8fe2ea7 100644
--- a/compiler/rustc_codegen_llvm/src/back/lto.rs
+++ b/compiler/rustc_codegen_llvm/src/back/lto.rs
@@ -20,6 +20,7 @@ use rustc_middle::bug;
 use rustc_middle::dep_graph::WorkProduct;
 use rustc_middle::middle::exported_symbols::{SymbolExportInfo, SymbolExportLevel};
 use rustc_session::config::{self, CrateType, Lto};
+use tracing::{debug, info};
 
 use std::collections::BTreeMap;
 use std::ffi::{CStr, CString};
@@ -229,9 +230,12 @@ pub(crate) fn run_thin(
     thin_lto(cgcx, &dcx, modules, upstream_modules, cached_modules, &symbols_below_threshold)
 }
 
-pub(crate) fn prepare_thin(module: ModuleCodegen<ModuleLlvm>) -> (String, ThinBuffer) {
+pub(crate) fn prepare_thin(
+    module: ModuleCodegen<ModuleLlvm>,
+    emit_summary: bool,
+) -> (String, ThinBuffer) {
     let name = module.name;
-    let buffer = ThinBuffer::new(module.module_llvm.llmod(), true);
+    let buffer = ThinBuffer::new(module.module_llvm.llmod(), true, emit_summary);
     (name, buffer)
 }
 
@@ -671,9 +675,9 @@ unsafe impl Send for ThinBuffer {}
 unsafe impl Sync for ThinBuffer {}
 
 impl ThinBuffer {
-    pub fn new(m: &llvm::Module, is_thin: bool) -> ThinBuffer {
+    pub fn new(m: &llvm::Module, is_thin: bool, emit_summary: bool) -> ThinBuffer {
         unsafe {
-            let buffer = llvm::LLVMRustThinLTOBufferCreate(m, is_thin);
+            let buffer = llvm::LLVMRustThinLTOBufferCreate(m, is_thin, emit_summary);
             ThinBuffer(buffer)
         }
     }
@@ -687,6 +691,14 @@ impl ThinBufferMethods for ThinBuffer {
             slice::from_raw_parts(ptr, len)
         }
     }
+
+    fn thin_link_data(&self) -> &[u8] {
+        unsafe {
+            let ptr = llvm::LLVMRustThinLTOBufferThinLinkDataPtr(self.0) as *const _;
+            let len = llvm::LLVMRustThinLTOBufferThinLinkDataLen(self.0);
+            slice::from_raw_parts(ptr, len)
+        }
+    }
 }
 
 impl Drop for ThinBuffer {
diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs
index 49f9d7ddab6..02e3bb06dda 100644
--- a/compiler/rustc_codegen_llvm/src/back/write.rs
+++ b/compiler/rustc_codegen_llvm/src/back/write.rs
@@ -35,6 +35,7 @@ use rustc_session::Session;
 use rustc_span::symbol::sym;
 use rustc_span::InnerSpan;
 use rustc_target::spec::{CodeModel, RelocModel, SanitizerSet, SplitDebuginfo, TlsModel};
+use tracing::debug;
 
 use crate::llvm::diagnostic::OptimizationDiagnosticKind;
 use libc::{c_char, c_int, c_void, size_t};
@@ -708,13 +709,15 @@ pub(crate) unsafe fn codegen(
         //   asm from LLVM and use `gcc` to create the object file.
 
         let bc_out = cgcx.output_filenames.temp_path(OutputType::Bitcode, module_name);
+        let bc_summary_out =
+            cgcx.output_filenames.temp_path(OutputType::ThinLinkBitcode, module_name);
         let obj_out = cgcx.output_filenames.temp_path(OutputType::Object, module_name);
 
         if config.bitcode_needed() {
             let _timer = cgcx
                 .prof
                 .generic_activity_with_arg("LLVM_module_codegen_make_bitcode", &*module.name);
-            let thin = ThinBuffer::new(llmod, config.emit_thin_lto);
+            let thin = ThinBuffer::new(llmod, config.emit_thin_lto, config.emit_thin_lto_summary);
             let data = thin.data();
 
             if let Some(bitcode_filename) = bc_out.file_name() {
@@ -725,6 +728,25 @@ pub(crate) unsafe fn codegen(
                 );
             }
 
+            if config.emit_thin_lto_summary
+                && let Some(thin_link_bitcode_filename) = bc_summary_out.file_name()
+            {
+                let summary_data = thin.thin_link_data();
+                cgcx.prof.artifact_size(
+                    "llvm_bitcode_summary",
+                    thin_link_bitcode_filename.to_string_lossy(),
+                    summary_data.len() as u64,
+                );
+
+                let _timer = cgcx.prof.generic_activity_with_arg(
+                    "LLVM_module_codegen_emit_bitcode_summary",
+                    &*module.name,
+                );
+                if let Err(err) = fs::write(&bc_summary_out, summary_data) {
+                    dcx.emit_err(WriteBytecode { path: &bc_summary_out, err });
+                }
+            }
+
             if config.emit_bc || config.emit_obj == EmitObj::Bitcode {
                 let _timer = cgcx
                     .prof
diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs
index 230c58dfcaf..72ff9ea118e 100644
--- a/compiler/rustc_codegen_llvm/src/builder.rs
+++ b/compiler/rustc_codegen_llvm/src/builder.rs
@@ -30,6 +30,7 @@ use std::borrow::Cow;
 use std::iter;
 use std::ops::Deref;
 use std::ptr;
+use tracing::{debug, instrument};
 
 // All Builders must have an llfn associated with them
 #[must_use]
diff --git a/compiler/rustc_codegen_llvm/src/callee.rs b/compiler/rustc_codegen_llvm/src/callee.rs
index e675362ac33..659c6ae0d86 100644
--- a/compiler/rustc_codegen_llvm/src/callee.rs
+++ b/compiler/rustc_codegen_llvm/src/callee.rs
@@ -12,6 +12,7 @@ use crate::value::Value;
 
 use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt};
 use rustc_middle::ty::{self, Instance, TypeVisitableExt};
+use tracing::debug;
 
 /// Codegens a reference to a fn/method item, monomorphizing and
 /// inlining as it goes.
diff --git a/compiler/rustc_codegen_llvm/src/common.rs b/compiler/rustc_codegen_llvm/src/common.rs
index ec33ce6292a..ab8036a1410 100644
--- a/compiler/rustc_codegen_llvm/src/common.rs
+++ b/compiler/rustc_codegen_llvm/src/common.rs
@@ -19,6 +19,7 @@ use rustc_target::spec::Target;
 
 use libc::{c_char, c_uint};
 use std::fmt::Write;
+use tracing::debug;
 
 /*
 * A note on nomenclature of linking: "extern", "foreign", and "upcall".
diff --git a/compiler/rustc_codegen_llvm/src/consts.rs b/compiler/rustc_codegen_llvm/src/consts.rs
index 9e85c2d88f9..a2314f4850c 100644
--- a/compiler/rustc_codegen_llvm/src/consts.rs
+++ b/compiler/rustc_codegen_llvm/src/consts.rs
@@ -25,6 +25,7 @@ use rustc_target::abi::{
     Align, AlignFromBytesError, HasDataLayout, Primitive, Scalar, Size, WrappingRange,
 };
 use std::ops::Range;
+use tracing::{debug, instrument, trace};
 
 pub fn const_alloc_to_llvm<'ll>(
     cx: &CodegenCx<'ll, '_>,
diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/map_data.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/map_data.rs
index d85d9411f03..b969fe27a99 100644
--- a/compiler/rustc_codegen_llvm/src/coverageinfo/map_data.rs
+++ b/compiler/rustc_codegen_llvm/src/coverageinfo/map_data.rs
@@ -9,6 +9,7 @@ use rustc_middle::mir::coverage::{
 };
 use rustc_middle::ty::Instance;
 use rustc_span::Symbol;
+use tracing::{debug, instrument};
 
 /// Holds all of the coverage mapping data associated with a function instance,
 /// collected during traversal of `Coverage` statements in the function's MIR.
diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs
index 3f3969bbca3..d2c0f20c285 100644
--- a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs
+++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs
@@ -14,6 +14,7 @@ use rustc_middle::mir;
 use rustc_middle::ty::{self, TyCtxt};
 use rustc_span::def_id::DefIdSet;
 use rustc_span::Symbol;
+use tracing::debug;
 
 /// Generates and exports the Coverage Map.
 ///
diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs
index 26ea95f0f0d..7b7f8c885bb 100644
--- a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs
+++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs
@@ -17,6 +17,7 @@ use rustc_middle::mir::coverage::CoverageKind;
 use rustc_middle::ty::layout::HasTyCtxt;
 use rustc_middle::ty::Instance;
 use rustc_target::abi::{Align, Size};
+use tracing::{debug, instrument};
 
 use std::cell::RefCell;
 
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
index f44738ba642..10d3c0d0e74 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
@@ -41,6 +41,7 @@ use rustc_symbol_mangling::typeid_for_trait_ref;
 use rustc_target::abi::{Align, Size};
 use rustc_target::spec::DebuginfoKind;
 use smallvec::smallvec;
+use tracing::{debug, instrument};
 
 use libc::{c_char, c_longlong, c_uint};
 use std::borrow::Cow;
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs
index 6149c18696c..3486ce4becb 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs
@@ -42,6 +42,7 @@ use std::cell::OnceCell;
 use std::cell::RefCell;
 use std::iter;
 use std::ops::Range;
+use tracing::debug;
 
 mod create_scope_map;
 pub mod gdb;
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/utils.rs b/compiler/rustc_codegen_llvm/src/debuginfo/utils.rs
index c758010c581..155e7a89fd8 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/utils.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/utils.rs
@@ -6,7 +6,7 @@ use super::CodegenUnitDebugContext;
 use rustc_hir::def_id::DefId;
 use rustc_middle::ty::layout::{HasParamEnv, LayoutOf};
 use rustc_middle::ty::{self, Ty};
-use trace;
+use tracing::trace;
 
 use crate::common::CodegenCx;
 use crate::llvm;
diff --git a/compiler/rustc_codegen_llvm/src/declare.rs b/compiler/rustc_codegen_llvm/src/declare.rs
index 7117c4a0ed9..bf86d0e0569 100644
--- a/compiler/rustc_codegen_llvm/src/declare.rs
+++ b/compiler/rustc_codegen_llvm/src/declare.rs
@@ -24,6 +24,7 @@ use rustc_data_structures::fx::FxIndexSet;
 use rustc_middle::ty::{Instance, Ty};
 use rustc_sanitizers::{cfi, kcfi};
 use smallvec::SmallVec;
+use tracing::debug;
 
 /// Declare a function.
 ///
diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs
index 897132a8e9c..3d2ce550b23 100644
--- a/compiler/rustc_codegen_llvm/src/intrinsic.rs
+++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs
@@ -21,6 +21,7 @@ use rustc_middle::{bug, span_bug};
 use rustc_span::{sym, Span, Symbol};
 use rustc_target::abi::{self, Align, Float, HasDataLayout, Primitive, Size};
 use rustc_target::spec::{HasTargetSpec, PanicStrategy};
+use tracing::debug;
 
 use std::cmp::Ordering;
 
diff --git a/compiler/rustc_codegen_llvm/src/lib.rs b/compiler/rustc_codegen_llvm/src/lib.rs
index 1cecf682e5d..0029ec9d09a 100644
--- a/compiler/rustc_codegen_llvm/src/lib.rs
+++ b/compiler/rustc_codegen_llvm/src/lib.rs
@@ -15,9 +15,6 @@
 #![feature(let_chains)]
 #![feature(impl_trait_in_assoc_type)]
 
-#[macro_use]
-extern crate tracing;
-
 use back::owned_target_machine::OwnedTargetMachine;
 use back::write::{create_informational_target_machine, create_target_machine};
 
@@ -240,8 +237,11 @@ impl WriteBackendMethods for LlvmCodegenBackend {
     ) -> Result<CompiledModule, FatalError> {
         back::write::codegen(cgcx, dcx, module, config)
     }
-    fn prepare_thin(module: ModuleCodegen<Self::Module>) -> (String, Self::ThinBuffer) {
-        back::lto::prepare_thin(module)
+    fn prepare_thin(
+        module: ModuleCodegen<Self::Module>,
+        emit_summary: bool,
+    ) -> (String, Self::ThinBuffer) {
+        back::lto::prepare_thin(module, emit_summary)
     }
     fn serialize_module(module: ModuleCodegen<Self::Module>) -> (String, Self::ModuleBuffer) {
         (module.name, back::lto::ModuleBuffer::new(module.module_llvm.llmod()))
diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
index 7a34e21628d..132e1f9e8fd 100644
--- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
@@ -2350,10 +2350,16 @@ extern "C" {
     #[allow(improper_ctypes)]
     pub fn LLVMRustModuleInstructionStats(M: &Module, Str: &RustString);
 
-    pub fn LLVMRustThinLTOBufferCreate(M: &Module, is_thin: bool) -> &'static mut ThinLTOBuffer;
+    pub fn LLVMRustThinLTOBufferCreate(
+        M: &Module,
+        is_thin: bool,
+        emit_summary: bool,
+    ) -> &'static mut ThinLTOBuffer;
     pub fn LLVMRustThinLTOBufferFree(M: &'static mut ThinLTOBuffer);
     pub fn LLVMRustThinLTOBufferPtr(M: &ThinLTOBuffer) -> *const c_char;
     pub fn LLVMRustThinLTOBufferLen(M: &ThinLTOBuffer) -> size_t;
+    pub fn LLVMRustThinLTOBufferThinLinkDataPtr(M: &ThinLTOBuffer) -> *const c_char;
+    pub fn LLVMRustThinLTOBufferThinLinkDataLen(M: &ThinLTOBuffer) -> size_t;
     pub fn LLVMRustCreateThinLTOData(
         Modules: *const ThinLTOModule,
         NumModules: c_uint,
diff --git a/compiler/rustc_codegen_llvm/src/mono_item.rs b/compiler/rustc_codegen_llvm/src/mono_item.rs
index 29100a64171..a7df08421a3 100644
--- a/compiler/rustc_codegen_llvm/src/mono_item.rs
+++ b/compiler/rustc_codegen_llvm/src/mono_item.rs
@@ -13,6 +13,7 @@ use rustc_middle::ty::layout::{FnAbiOf, LayoutOf};
 use rustc_middle::ty::{self, Instance, TypeVisitableExt};
 use rustc_session::config::CrateType;
 use rustc_target::spec::RelocModel;
+use tracing::debug;
 
 impl<'tcx> PreDefineMethods<'tcx> for CodegenCx<'_, 'tcx> {
     fn predefine_static(
diff --git a/compiler/rustc_codegen_llvm/src/type_of.rs b/compiler/rustc_codegen_llvm/src/type_of.rs
index 5f60fd23a5f..011d8ab57c7 100644
--- a/compiler/rustc_codegen_llvm/src/type_of.rs
+++ b/compiler/rustc_codegen_llvm/src/type_of.rs
@@ -8,6 +8,7 @@ use rustc_middle::ty::{self, Ty, TypeVisitableExt};
 use rustc_target::abi::{Abi, Align, FieldsShape};
 use rustc_target::abi::{Float, Int, Pointer};
 use rustc_target::abi::{Scalar, Size, Variants};
+use tracing::debug;
 
 use std::fmt::Write;
 
diff --git a/compiler/rustc_codegen_ssa/messages.ftl b/compiler/rustc_codegen_ssa/messages.ftl
index d159fe58d3e..1a851ad04a1 100644
--- a/compiler/rustc_codegen_ssa/messages.ftl
+++ b/compiler/rustc_codegen_ssa/messages.ftl
@@ -212,6 +212,8 @@ codegen_ssa_rlib_only_rmeta_found = could not find rlib for: `{$crate_name}`, fo
 
 codegen_ssa_select_cpp_build_tool_workload = in the Visual Studio installer, ensure the "C++ build tools" workload is selected
 
+codegen_ssa_self_contained_linker_missing = the self-contained linker was requested, but it wasn't found in the target's sysroot, or in rustc's sysroot
+
 codegen_ssa_shuffle_indices_evaluation = could not evaluate shuffle_indices at compile time
 
 codegen_ssa_specify_libraries_to_link = use the `-l` flag to specify native libraries to link
diff --git a/compiler/rustc_codegen_ssa/src/assert_module_sources.rs b/compiler/rustc_codegen_ssa/src/assert_module_sources.rs
index e441aea8400..6e7d736eb29 100644
--- a/compiler/rustc_codegen_ssa/src/assert_module_sources.rs
+++ b/compiler/rustc_codegen_ssa/src/assert_module_sources.rs
@@ -37,6 +37,7 @@ use rustc_span::{Span, Symbol};
 use std::borrow::Cow;
 use std::fmt;
 use thin_vec::ThinVec;
+use tracing::debug;
 
 #[allow(missing_docs)]
 pub fn assert_module_sources(tcx: TyCtxt<'_>, set_reuse: &dyn Fn(&mut CguReuseTracker)) {
diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs
index 37b8f81ad94..bdb808b1d4f 100644
--- a/compiler/rustc_codegen_ssa/src/back/link.rs
+++ b/compiler/rustc_codegen_ssa/src/back/link.rs
@@ -52,6 +52,7 @@ use std::ops::Deref;
 use std::path::{Path, PathBuf};
 use std::process::{ExitStatus, Output, Stdio};
 use std::{env, fmt, fs, io, mem, str};
+use tracing::{debug, info, warn};
 
 pub fn ensure_removed(dcx: &DiagCtxt, path: &Path) {
     if let Err(e) = fs::remove_file(path) {
@@ -786,12 +787,33 @@ fn link_natively(
         if matches!(flavor, LinkerFlavor::Gnu(Cc::Yes, _))
             && unknown_arg_regex.is_match(&out)
             && out.contains("-no-pie")
-            && cmd.get_args().iter().any(|e| e.to_string_lossy() == "-no-pie")
+            && cmd.get_args().iter().any(|e| e == "-no-pie")
         {
             info!("linker output: {:?}", out);
             warn!("Linker does not support -no-pie command line option. Retrying without.");
             for arg in cmd.take_args() {
-                if arg.to_string_lossy() != "-no-pie" {
+                if arg != "-no-pie" {
+                    cmd.arg(arg);
+                }
+            }
+            info!("{:?}", &cmd);
+            continue;
+        }
+
+        // Check if linking failed with an error message that indicates the driver didn't recognize
+        // the `-fuse-ld=lld` option. If so, re-perform the link step without it. This avoids having
+        // to spawn multiple instances on the happy path to do version checking, and ensures things
+        // keep working on the tier 1 baseline of GLIBC 2.17+. That is generally understood as GCCs
+        // circa RHEL/CentOS 7, 4.5 or so, whereas lld support was added in GCC 9.
+        if matches!(flavor, LinkerFlavor::Gnu(Cc::Yes, Lld::Yes))
+            && unknown_arg_regex.is_match(&out)
+            && out.contains("-fuse-ld=lld")
+            && cmd.get_args().iter().any(|e| e.to_string_lossy() == "-fuse-ld=lld")
+        {
+            info!("linker output: {:?}", out);
+            warn!("The linker driver does not support `-fuse-ld=lld`. Retrying without it.");
+            for arg in cmd.take_args() {
+                if arg.to_string_lossy() != "-fuse-ld=lld" {
                     cmd.arg(arg);
                 }
             }
@@ -804,7 +826,7 @@ fn link_natively(
         if matches!(flavor, LinkerFlavor::Gnu(Cc::Yes, _))
             && unknown_arg_regex.is_match(&out)
             && (out.contains("-static-pie") || out.contains("--no-dynamic-linker"))
-            && cmd.get_args().iter().any(|e| e.to_string_lossy() == "-static-pie")
+            && cmd.get_args().iter().any(|e| e == "-static-pie")
         {
             info!("linker output: {:?}", out);
             warn!(
@@ -843,7 +865,7 @@ fn link_natively(
             assert!(pre_objects_static.is_empty() || !pre_objects_static_pie.is_empty());
             assert!(post_objects_static.is_empty() || !post_objects_static_pie.is_empty());
             for arg in cmd.take_args() {
-                if arg.to_string_lossy() == "-static-pie" {
+                if arg == "-static-pie" {
                     // Replace the output kind.
                     cmd.arg("-static");
                 } else if pre_objects_static_pie.contains(&arg) {
@@ -3119,13 +3141,21 @@ fn add_lld_args(
 
     let self_contained_linker = self_contained_cli || self_contained_target;
     if self_contained_linker && !sess.opts.cg.link_self_contained.is_linker_disabled() {
+        let mut linker_path_exists = false;
         for path in sess.get_tools_search_paths(false) {
+            let linker_path = path.join("gcc-ld");
+            linker_path_exists |= linker_path.exists();
             cmd.arg({
                 let mut arg = OsString::from("-B");
-                arg.push(path.join("gcc-ld"));
+                arg.push(linker_path);
                 arg
             });
         }
+        if !linker_path_exists {
+            // As a sanity check, we emit an error if none of these paths exist: we want
+            // self-contained linking and have no linker.
+            sess.dcx().emit_fatal(errors::SelfContainedLinkerMissing);
+        }
     }
 
     // 2. Implement the "linker flavor" part of this feature by asking `cc` to use some kind of
diff --git a/compiler/rustc_codegen_ssa/src/back/linker.rs b/compiler/rustc_codegen_ssa/src/back/linker.rs
index f85056f8ad4..a82478900b1 100644
--- a/compiler/rustc_codegen_ssa/src/back/linker.rs
+++ b/compiler/rustc_codegen_ssa/src/back/linker.rs
@@ -22,6 +22,7 @@ use rustc_session::Session;
 use rustc_target::spec::{Cc, LinkOutputKind, LinkerFlavor, Lld};
 
 use cc::windows_registry;
+use tracing::{debug, warn};
 
 /// Disables non-English messages from localized linkers.
 /// Such messages may cause issues with text encoding on Windows (#35785)
diff --git a/compiler/rustc_codegen_ssa/src/back/rpath.rs b/compiler/rustc_codegen_ssa/src/back/rpath.rs
index ebbf49af184..3114f1c38ae 100644
--- a/compiler/rustc_codegen_ssa/src/back/rpath.rs
+++ b/compiler/rustc_codegen_ssa/src/back/rpath.rs
@@ -3,6 +3,7 @@ use rustc_data_structures::fx::FxHashSet;
 use rustc_fs_util::try_canonicalize;
 use std::ffi::OsString;
 use std::path::{Path, PathBuf};
+use tracing::debug;
 
 pub struct RPathConfig<'a> {
     pub libs: &'a [&'a Path],
diff --git a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs
index 0e335bf00cf..79d6641a0da 100644
--- a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs
+++ b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs
@@ -18,6 +18,7 @@ use rustc_middle::ty::{GenericArgKind, GenericArgsRef};
 use rustc_middle::util::Providers;
 use rustc_session::config::{CrateType, OomStrategy};
 use rustc_target::spec::{SanitizerSet, TlsModel};
+use tracing::debug;
 
 pub fn threshold(tcx: TyCtxt<'_>) -> SymbolExportLevel {
     crates_export_threshold(tcx.crate_types())
@@ -399,7 +400,7 @@ fn upstream_monomorphizations_provider(
     tcx: TyCtxt<'_>,
     (): (),
 ) -> DefIdMap<UnordMap<GenericArgsRef<'_>, CrateNum>> {
-    let cnums = tcx.crates(());
+    let cnums = tcx.used_crates(());
 
     let mut instances: DefIdMap<UnordMap<_, _>> = Default::default();
 
diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs
index 53ba0da7d04..d57f4ddf8aa 100644
--- a/compiler/rustc_codegen_ssa/src/back/write.rs
+++ b/compiler/rustc_codegen_ssa/src/back/write.rs
@@ -49,6 +49,7 @@ use std::str;
 use std::sync::mpsc::{channel, Receiver, Sender};
 use std::sync::Arc;
 use std::thread;
+use tracing::debug;
 
 const PRE_LTO_BC_EXT: &str = "pre-lto.bc";
 
@@ -107,6 +108,7 @@ pub struct ModuleConfig {
     pub emit_asm: bool,
     pub emit_obj: EmitObj,
     pub emit_thin_lto: bool,
+    pub emit_thin_lto_summary: bool,
     pub bc_cmdline: String,
 
     // Miscellaneous flags. These are mostly copied from command-line
@@ -231,6 +233,10 @@ impl ModuleConfig {
             ),
             emit_obj,
             emit_thin_lto: sess.opts.unstable_opts.emit_thin_lto,
+            emit_thin_lto_summary: if_regular!(
+                sess.opts.output_types.contains_key(&OutputType::ThinLinkBitcode),
+                false
+            ),
             bc_cmdline: sess.target.bitcode_llvm_cmdline.to_string(),
 
             verify_llvm_ir: sess.verify_llvm_ir(),
@@ -282,6 +288,7 @@ impl ModuleConfig {
 
     pub fn bitcode_needed(&self) -> bool {
         self.emit_bc
+            || self.emit_thin_lto_summary
             || self.emit_obj == EmitObj::Bitcode
             || self.emit_obj == EmitObj::ObjectCode(BitcodeSection::Full)
     }
@@ -629,6 +636,9 @@ fn produce_final_output_artifacts(
                 // them for making an rlib.
                 copy_if_one_unit(OutputType::Bitcode, true);
             }
+            OutputType::ThinLinkBitcode => {
+                copy_if_one_unit(OutputType::ThinLinkBitcode, false);
+            }
             OutputType::LlvmAssembly => {
                 copy_if_one_unit(OutputType::LlvmAssembly, false);
             }
@@ -882,7 +892,7 @@ fn execute_optimize_work_item<B: ExtraBackendMethods>(
     match lto_type {
         ComputedLtoType::No => finish_intra_module_work(cgcx, module, module_config),
         ComputedLtoType::Thin => {
-            let (name, thin_buffer) = B::prepare_thin(module);
+            let (name, thin_buffer) = B::prepare_thin(module, false);
             if let Some(path) = bitcode {
                 fs::write(&path, thin_buffer.data()).unwrap_or_else(|e| {
                     panic!("Error writing pre-lto-bitcode file `{}`: {}", path.display(), e);
diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs
index 66bc5b6606d..b4556f8fcb8 100644
--- a/compiler/rustc_codegen_ssa/src/base.rs
+++ b/compiler/rustc_codegen_ssa/src/base.rs
@@ -45,6 +45,7 @@ use std::collections::BTreeSet;
 use std::time::{Duration, Instant};
 
 use itertools::Itertools;
+use tracing::{debug, info};
 
 pub fn bin_op_to_icmp_predicate(op: BinOp, signed: bool) -> IntPredicate {
     match op {
@@ -539,7 +540,7 @@ pub fn collect_debugger_visualizers_transitive(
     tcx.debugger_visualizers(LOCAL_CRATE)
         .iter()
         .chain(
-            tcx.crates(())
+            tcx.used_crates(())
                 .iter()
                 .filter(|&cnum| {
                     let used_crate_source = tcx.used_crate_source(*cnum);
@@ -849,7 +850,7 @@ impl CrateInfo {
         // `compiler_builtins` are always placed last to ensure that they're linked correctly.
         used_crates.extend(compiler_builtins);
 
-        let crates = tcx.crates(());
+        let crates = tcx.used_crates(());
         let n_crates = crates.len();
         let mut info = CrateInfo {
             target_cpu,
diff --git a/compiler/rustc_codegen_ssa/src/errors.rs b/compiler/rustc_codegen_ssa/src/errors.rs
index ed6a0c24410..3641e7842cf 100644
--- a/compiler/rustc_codegen_ssa/src/errors.rs
+++ b/compiler/rustc_codegen_ssa/src/errors.rs
@@ -414,6 +414,10 @@ pub struct UnableToExeLinker {
 pub struct MsvcMissingLinker;
 
 #[derive(Diagnostic)]
+#[diag(codegen_ssa_self_contained_linker_missing)]
+pub struct SelfContainedLinkerMissing;
+
+#[derive(Diagnostic)]
 #[diag(codegen_ssa_check_installed_visual_studio)]
 pub struct CheckInstalledVisualStudio;
 
diff --git a/compiler/rustc_codegen_ssa/src/lib.rs b/compiler/rustc_codegen_ssa/src/lib.rs
index 66a7a2e090a..1668104d7e2 100644
--- a/compiler/rustc_codegen_ssa/src/lib.rs
+++ b/compiler/rustc_codegen_ssa/src/lib.rs
@@ -15,9 +15,6 @@
 //! The backend-agnostic functions of this crate use functions defined in various traits that
 //! have to be implemented by each backend.
 
-#[macro_use]
-extern crate tracing;
-
 use rustc_ast as ast;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_data_structures::fx::FxIndexMap;
diff --git a/compiler/rustc_codegen_ssa/src/meth.rs b/compiler/rustc_codegen_ssa/src/meth.rs
index 23036e9bea0..d6fc8e536b4 100644
--- a/compiler/rustc_codegen_ssa/src/meth.rs
+++ b/compiler/rustc_codegen_ssa/src/meth.rs
@@ -5,6 +5,7 @@ use rustc_middle::ty::{self, GenericArgKind, Ty};
 use rustc_session::config::Lto;
 use rustc_symbol_mangling::typeid_for_trait_ref;
 use rustc_target::abi::call::FnAbi;
+use tracing::{debug, instrument};
 
 #[derive(Copy, Clone, Debug)]
 pub struct VirtualIndex(u64);
diff --git a/compiler/rustc_codegen_ssa/src/mir/analyze.rs b/compiler/rustc_codegen_ssa/src/mir/analyze.rs
index 09ae7cf6410..0577ba32ffd 100644
--- a/compiler/rustc_codegen_ssa/src/mir/analyze.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/analyze.rs
@@ -11,6 +11,7 @@ use rustc_middle::mir::visit::{MutatingUseContext, NonMutatingUseContext, PlaceC
 use rustc_middle::mir::{self, DefLocation, Location, TerminatorKind};
 use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf};
 use rustc_middle::{bug, span_bug};
+use tracing::debug;
 
 pub fn non_ssa_locals<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
     fx: &FunctionCx<'a, 'tcx, Bx>,
diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs
index ba6aad51316..1cb1ba99a5a 100644
--- a/compiler/rustc_codegen_ssa/src/mir/block.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/block.rs
@@ -24,6 +24,7 @@ use rustc_span::{source_map::Spanned, sym, Span};
 use rustc_target::abi::call::{ArgAbi, FnAbi, PassMode, Reg};
 use rustc_target::abi::{self, HasDataLayout, WrappingRange};
 use rustc_target::spec::abi::Abi;
+use tracing::{debug, info};
 
 use std::cmp;
 
diff --git a/compiler/rustc_codegen_ssa/src/mir/locals.rs b/compiler/rustc_codegen_ssa/src/mir/locals.rs
index 7db260c9f5b..c7f63eab829 100644
--- a/compiler/rustc_codegen_ssa/src/mir/locals.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/locals.rs
@@ -7,6 +7,8 @@ use rustc_index::IndexVec;
 use rustc_middle::mir;
 use rustc_middle::ty::print::with_no_trimmed_paths;
 use std::ops::{Index, IndexMut};
+use tracing::{debug, warn};
+
 pub(super) struct Locals<'tcx, V> {
     values: IndexVec<mir::Local, LocalRef<'tcx, V>>,
 }
diff --git a/compiler/rustc_codegen_ssa/src/mir/mod.rs b/compiler/rustc_codegen_ssa/src/mir/mod.rs
index cf6e2e8d14c..e8da9842882 100644
--- a/compiler/rustc_codegen_ssa/src/mir/mod.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/mod.rs
@@ -10,6 +10,7 @@ use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt, TyAndLayout};
 use rustc_middle::ty::{self, Instance, Ty, TyCtxt, TypeFoldable, TypeVisitableExt};
 use rustc_middle::{bug, span_bug};
 use rustc_target::abi::call::{FnAbi, PassMode};
+use tracing::{debug, instrument};
 
 use std::iter;
 
diff --git a/compiler/rustc_codegen_ssa/src/mir/operand.rs b/compiler/rustc_codegen_ssa/src/mir/operand.rs
index 32fd9b657f9..5b2f9a3be27 100644
--- a/compiler/rustc_codegen_ssa/src/mir/operand.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/operand.rs
@@ -16,6 +16,7 @@ use std::fmt;
 
 use arrayvec::ArrayVec;
 use either::Either;
+use tracing::debug;
 
 /// The representation of a Rust value. The enum variant is in fact
 /// uniquely determined by the value's type, but is kept as a
diff --git a/compiler/rustc_codegen_ssa/src/mir/place.rs b/compiler/rustc_codegen_ssa/src/mir/place.rs
index 971ac2defdc..7c3569a9dd2 100644
--- a/compiler/rustc_codegen_ssa/src/mir/place.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/place.rs
@@ -12,6 +12,7 @@ use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf, TyAndLayout};
 use rustc_middle::ty::{self, Ty};
 use rustc_target::abi::{Align, FieldsShape, Int, Pointer, Size, TagEncoding};
 use rustc_target::abi::{VariantIdx, Variants};
+use tracing::{debug, instrument};
 
 /// The location and extra runtime properties of the place.
 ///
@@ -159,9 +160,9 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> {
                 bx.inbounds_ptradd(self.val.llval, bx.const_usize(offset.bytes()))
             };
             let val = PlaceValue {
-                    llval,
+                llval,
                 llextra: if bx.cx().type_has_metadata(field.ty) { self.val.llextra } else { None },
-                    align: effective_field_align,
+                align: effective_field_align,
             };
             val.with_type(field)
         };
@@ -408,9 +409,9 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> {
         };
 
         let llval = bx.inbounds_gep(
-                    bx.cx().backend_type(self.layout),
-                    self.val.llval,
-                    &[bx.cx().const_usize(0), llindex],
+            bx.cx().backend_type(self.layout),
+            self.val.llval,
+            &[bx.cx().const_usize(0), llindex],
         );
         let align = self.val.align.restrict_for_offset(offset);
         PlaceValue::new_sized(llval, align).with_type(layout)
diff --git a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
index f9085f502d4..4dd80d34ea7 100644
--- a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
@@ -17,6 +17,7 @@ use rustc_span::{Span, DUMMY_SP};
 use rustc_target::abi::{self, FieldIdx, FIRST_VARIANT};
 
 use arrayvec::ArrayVec;
+use tracing::{debug, instrument};
 
 impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
     #[instrument(level = "trace", skip(self, bx))]
diff --git a/compiler/rustc_codegen_ssa/src/mir/statement.rs b/compiler/rustc_codegen_ssa/src/mir/statement.rs
index a0429022587..27494f48b09 100644
--- a/compiler/rustc_codegen_ssa/src/mir/statement.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/statement.rs
@@ -1,6 +1,7 @@
 use rustc_middle::mir::{self, NonDivergingIntrinsic};
 use rustc_middle::span_bug;
 use rustc_session::config::OptLevel;
+use tracing::instrument;
 
 use super::FunctionCx;
 use super::LocalRef;
diff --git a/compiler/rustc_codegen_ssa/src/mono_item.rs b/compiler/rustc_codegen_ssa/src/mono_item.rs
index 40921c2932f..0fbcb938d1a 100644
--- a/compiler/rustc_codegen_ssa/src/mono_item.rs
+++ b/compiler/rustc_codegen_ssa/src/mono_item.rs
@@ -9,6 +9,7 @@ use rustc_middle::span_bug;
 use rustc_middle::ty;
 use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf};
 use rustc_middle::ty::Instance;
+use tracing::debug;
 
 pub trait MonoItemExt<'a, 'tcx> {
     fn define<Bx: BuilderMethods<'a, 'tcx>>(&self, cx: &'a Bx::CodegenCx);
diff --git a/compiler/rustc_codegen_ssa/src/size_of_val.rs b/compiler/rustc_codegen_ssa/src/size_of_val.rs
index 032699f1fa1..130fe2eaf2f 100644
--- a/compiler/rustc_codegen_ssa/src/size_of_val.rs
+++ b/compiler/rustc_codegen_ssa/src/size_of_val.rs
@@ -9,6 +9,7 @@ use rustc_middle::bug;
 use rustc_middle::ty::print::{with_no_trimmed_paths, with_no_visible_paths};
 use rustc_middle::ty::{self, Ty};
 use rustc_target::abi::WrappingRange;
+use tracing::{debug, trace};
 
 pub fn size_and_align_of_dst<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
     bx: &mut Bx,
diff --git a/compiler/rustc_codegen_ssa/src/traits/write.rs b/compiler/rustc_codegen_ssa/src/traits/write.rs
index 048540894ac..f83e34ab01b 100644
--- a/compiler/rustc_codegen_ssa/src/traits/write.rs
+++ b/compiler/rustc_codegen_ssa/src/traits/write.rs
@@ -56,12 +56,16 @@ pub trait WriteBackendMethods: 'static + Sized + Clone {
         module: ModuleCodegen<Self::Module>,
         config: &ModuleConfig,
     ) -> Result<CompiledModule, FatalError>;
-    fn prepare_thin(module: ModuleCodegen<Self::Module>) -> (String, Self::ThinBuffer);
+    fn prepare_thin(
+        module: ModuleCodegen<Self::Module>,
+        want_summary: bool,
+    ) -> (String, Self::ThinBuffer);
     fn serialize_module(module: ModuleCodegen<Self::Module>) -> (String, Self::ModuleBuffer);
 }
 
 pub trait ThinBufferMethods: Send + Sync {
     fn data(&self) -> &[u8];
+    fn thin_link_data(&self) -> &[u8];
 }
 
 pub trait ModuleBufferMethods: Send + Sync {
diff --git a/compiler/rustc_const_eval/messages.ftl b/compiler/rustc_const_eval/messages.ftl
index 20f0f27517f..2dbeb7d5e0c 100644
--- a/compiler/rustc_const_eval/messages.ftl
+++ b/compiler/rustc_const_eval/messages.ftl
@@ -246,11 +246,10 @@ const_eval_offset_from_unsigned_overflow =
 
 const_eval_operator_non_const =
     cannot call non-const operator in {const_eval_const_context}s
-const_eval_overflow =
-    overflow executing `{$name}`
-
+const_eval_overflow_arith =
+    arithmetic overflow in `{$intrinsic}`
 const_eval_overflow_shift =
-    overflowing shift by {$val} in `{$name}`
+    overflowing shift by {$shift_amount} in `{$intrinsic}`
 
 const_eval_panic =
     the evaluated program panicked at '{$msg}', {$file}:{$line}:{$col}
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 94c9f056b30..530a05a1ed8 100644
--- a/compiler/rustc_const_eval/src/const_eval/dummy_machine.rs
+++ b/compiler/rustc_const_eval/src/const_eval/dummy_machine.rs
@@ -125,7 +125,7 @@ impl<'mir, 'tcx: 'mir> interpret::Machine<'mir, 'tcx> for DummyMachine {
         bin_op: BinOp,
         left: &interpret::ImmTy<'tcx, Self::Provenance>,
         right: &interpret::ImmTy<'tcx, Self::Provenance>,
-    ) -> interpret::InterpResult<'tcx, (ImmTy<'tcx, Self::Provenance>, bool)> {
+    ) -> interpret::InterpResult<'tcx, ImmTy<'tcx, Self::Provenance>> {
         use rustc_middle::mir::BinOp::*;
         Ok(match bin_op {
             Eq | Ne | Lt | Le | Gt | Ge => {
@@ -154,7 +154,7 @@ impl<'mir, 'tcx: 'mir> interpret::Machine<'mir, 'tcx> for DummyMachine {
                     Ge => left >= right,
                     _ => bug!(),
                 };
-                (ImmTy::from_bool(res, *ecx.tcx), false)
+                ImmTy::from_bool(res, *ecx.tcx)
             }
 
             // Some more operations are possible with atomics.
diff --git a/compiler/rustc_const_eval/src/const_eval/error.rs b/compiler/rustc_const_eval/src/const_eval/error.rs
index 08c9609eacf..7a1c2a7b6fa 100644
--- a/compiler/rustc_const_eval/src/const_eval/error.rs
+++ b/compiler/rustc_const_eval/src/const_eval/error.rs
@@ -2,7 +2,7 @@ use std::mem;
 
 use rustc_errors::{DiagArgName, DiagArgValue, DiagMessage, Diagnostic, IntoDiagArg};
 use rustc_hir::CRATE_HIR_ID;
-use rustc_middle::mir::interpret::Provenance;
+use rustc_middle::mir::interpret::{Provenance, ReportedErrorInfo};
 use rustc_middle::mir::AssertKind;
 use rustc_middle::query::TyCtxtAt;
 use rustc_middle::ty::TyCtxt;
@@ -139,9 +139,10 @@ where
             ErrorHandled::TooGeneric(span)
         }
         err_inval!(AlreadyReported(guar)) => ErrorHandled::Reported(guar, span),
-        err_inval!(Layout(LayoutError::ReferencesError(guar))) => {
-            ErrorHandled::Reported(guar.into(), span)
-        }
+        err_inval!(Layout(LayoutError::ReferencesError(guar))) => ErrorHandled::Reported(
+            ReportedErrorInfo::tainted_by_errors(guar),
+            span,
+        ),
         // Report remaining errors.
         _ => {
             let (our_span, frames) = get_span_and_frames();
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 6a9a21bbd8e..966951e7d9a 100644
--- a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs
+++ b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs
@@ -1,6 +1,7 @@
 use std::sync::atomic::Ordering::Relaxed;
 
 use either::{Left, Right};
+use tracing::{debug, instrument, trace};
 
 use rustc_hir::def::DefKind;
 use rustc_middle::bug;
diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs
index 310fd462d5f..b8b4426c2ec 100644
--- a/compiler/rustc_const_eval/src/const_eval/machine.rs
+++ b/compiler/rustc_const_eval/src/const_eval/machine.rs
@@ -21,6 +21,7 @@ use rustc_span::symbol::{sym, Symbol};
 use rustc_span::Span;
 use rustc_target::abi::{Align, Size};
 use rustc_target::spec::abi::Abi as CallAbi;
+use tracing::debug;
 
 use crate::errors::{LongRunning, LongRunningWarn};
 use crate::fluent_generated as fluent;
@@ -589,7 +590,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
         _bin_op: mir::BinOp,
         _left: &ImmTy<'tcx>,
         _right: &ImmTy<'tcx>,
-    ) -> InterpResult<'tcx, (ImmTy<'tcx>, bool)> {
+    ) -> InterpResult<'tcx, ImmTy<'tcx>> {
         throw_unsup_format!("pointer arithmetic or comparison is not supported at compile-time");
     }
 
diff --git a/compiler/rustc_const_eval/src/const_eval/mod.rs b/compiler/rustc_const_eval/src/const_eval/mod.rs
index a5c8c0bb82a..4ae4816e33a 100644
--- a/compiler/rustc_const_eval/src/const_eval/mod.rs
+++ b/compiler/rustc_const_eval/src/const_eval/mod.rs
@@ -6,6 +6,7 @@ use rustc_middle::mir::interpret::InterpErrorInfo;
 use rustc_middle::query::{Key, TyCtxtAt};
 use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_target::abi::VariantIdx;
+use tracing::instrument;
 
 use crate::interpret::{format_interp_error, InterpCx};
 
diff --git a/compiler/rustc_const_eval/src/const_eval/valtrees.rs b/compiler/rustc_const_eval/src/const_eval/valtrees.rs
index fbf2ca5ab0a..b906bfa775f 100644
--- a/compiler/rustc_const_eval/src/const_eval/valtrees.rs
+++ b/compiler/rustc_const_eval/src/const_eval/valtrees.rs
@@ -6,6 +6,7 @@ use rustc_middle::ty::layout::{LayoutCx, LayoutOf, TyAndLayout};
 use rustc_middle::ty::{self, ScalarInt, Ty, TyCtxt};
 use rustc_span::DUMMY_SP;
 use rustc_target::abi::{Abi, VariantIdx};
+use tracing::{debug, instrument, trace};
 
 use super::eval_queries::{mk_eval_cx_to_read_const_val, op_to_const};
 use super::machine::CompileTimeEvalContext;
diff --git a/compiler/rustc_const_eval/src/errors.rs b/compiler/rustc_const_eval/src/errors.rs
index 90d4f1168e4..e5ea4c3442e 100644
--- a/compiler/rustc_const_eval/src/errors.rs
+++ b/compiler/rustc_const_eval/src/errors.rs
@@ -1,5 +1,6 @@
 use std::borrow::Cow;
 
+use either::Either;
 use rustc_errors::{
     codes::*, Diag, DiagArgValue, DiagCtxt, DiagMessage, Diagnostic, EmissionGuarantee, Level,
 };
@@ -481,6 +482,8 @@ impl<'a> ReportErrorExt for UndefinedBehaviorInfo<'a> {
             DivisionOverflow => const_eval_division_overflow,
             RemainderOverflow => const_eval_remainder_overflow,
             PointerArithOverflow => const_eval_pointer_arithmetic_overflow,
+            ArithOverflow { .. } => const_eval_overflow_arith,
+            ShiftOverflow { .. } => const_eval_overflow_shift,
             InvalidMeta(InvalidMetaKind::SliceTooBig) => const_eval_invalid_meta_slice,
             InvalidMeta(InvalidMetaKind::TooBig) => const_eval_invalid_meta,
             UnterminatedCString(_) => const_eval_unterminated_c_string,
@@ -539,6 +542,19 @@ impl<'a> ReportErrorExt for UndefinedBehaviorInfo<'a> {
             | UninhabitedEnumVariantWritten(_)
             | UninhabitedEnumVariantRead(_) => {}
 
+            ArithOverflow { intrinsic } => {
+                diag.arg("intrinsic", intrinsic);
+            }
+            ShiftOverflow { intrinsic, shift_amount } => {
+                diag.arg("intrinsic", intrinsic);
+                diag.arg(
+                    "shift_amount",
+                    match shift_amount {
+                        Either::Left(v) => v.to_string(),
+                        Either::Right(v) => v.to_string(),
+                    },
+                );
+            }
             BoundsCheckFailed { len, index } => {
                 diag.arg("len", len);
                 diag.arg("index", index);
diff --git a/compiler/rustc_const_eval/src/interpret/cast.rs b/compiler/rustc_const_eval/src/interpret/cast.rs
index 799e12f9ac9..ecfb25e32cd 100644
--- a/compiler/rustc_const_eval/src/interpret/cast.rs
+++ b/compiler/rustc_const_eval/src/interpret/cast.rs
@@ -10,6 +10,7 @@ use rustc_middle::ty::{self, FloatTy, Ty};
 use rustc_middle::{bug, span_bug};
 use rustc_target::abi::Integer;
 use rustc_type_ir::TyKind::*;
+use tracing::trace;
 
 use super::{
     err_inval, throw_ub, throw_ub_custom, util::ensure_monomorphic_enough, FnVal, ImmTy, Immediate,
diff --git a/compiler/rustc_const_eval/src/interpret/discriminant.rs b/compiler/rustc_const_eval/src/interpret/discriminant.rs
index 8ddc741de23..0790f06e6e1 100644
--- a/compiler/rustc_const_eval/src/interpret/discriminant.rs
+++ b/compiler/rustc_const_eval/src/interpret/discriminant.rs
@@ -6,6 +6,7 @@ use rustc_middle::ty::layout::{LayoutOf, PrimitiveExt};
 use rustc_middle::ty::{self, ScalarInt, Ty};
 use rustc_target::abi::{self, TagEncoding};
 use rustc_target::abi::{VariantIdx, Variants};
+use tracing::{instrument, trace};
 
 use super::{
     err_ub, throw_ub, ImmTy, InterpCx, InterpResult, Machine, Readable, Scalar, Writeable,
@@ -172,7 +173,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                         let tag_val = ImmTy::from_uint(tag_bits, tag_layout);
                         let niche_start_val = ImmTy::from_uint(niche_start, tag_layout);
                         let variant_index_relative_val =
-                            self.wrapping_binary_op(mir::BinOp::Sub, &tag_val, &niche_start_val)?;
+                            self.binary_op(mir::BinOp::Sub, &tag_val, &niche_start_val)?;
                         let variant_index_relative =
                             variant_index_relative_val.to_scalar().assert_bits(tag_val.layout.size);
                         // Check if this is in the range that indicates an actual discriminant.
@@ -292,11 +293,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                 let variant_index_relative_val =
                     ImmTy::from_uint(variant_index_relative, tag_layout);
                 let tag = self
-                    .wrapping_binary_op(
-                        mir::BinOp::Add,
-                        &variant_index_relative_val,
-                        &niche_start_val,
-                    )?
+                    .binary_op(mir::BinOp::Add, &variant_index_relative_val, &niche_start_val)?
                     .to_scalar()
                     .assert_int();
                 Ok(Some((tag, tag_field)))
diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs
index 344bb7cd98b..d82623fa009 100644
--- a/compiler/rustc_const_eval/src/interpret/eval_context.rs
+++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs
@@ -2,6 +2,7 @@ use std::cell::Cell;
 use std::{fmt, mem};
 
 use either::{Either, Left, Right};
+use tracing::{debug, info, info_span, instrument, trace};
 
 use hir::CRATE_HIR_ID;
 use rustc_errors::DiagCtxt;
@@ -1181,9 +1182,20 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
     ) -> InterpResult<'tcx, OpTy<'tcx, M::Provenance>> {
         M::eval_mir_constant(self, *val, span, layout, |ecx, val, span, layout| {
             let const_val = val.eval(*ecx.tcx, ecx.param_env, span).map_err(|err| {
-                if M::ALL_CONSTS_ARE_PRECHECKED && !matches!(err, ErrorHandled::TooGeneric(..)) {
-                    // Looks like the const is not captued by `required_consts`, that's bad.
-                    bug!("interpret const eval failure of {val:?} which is not in required_consts");
+                if M::ALL_CONSTS_ARE_PRECHECKED {
+                    match err {
+                        ErrorHandled::TooGeneric(..) => {},
+                        ErrorHandled::Reported(reported, span) => {
+                            if reported.is_tainted_by_errors() {
+                                // const-eval will return "tainted" errors if e.g. the layout cannot
+                                // be computed as the type references non-existing names.
+                                // See <https://github.com/rust-lang/rust/issues/124348>.
+                            } else {
+                                // Looks like the const is not captued by `required_consts`, that's bad.
+                                span_bug!(span, "interpret const eval failure of {val:?} which is not in required_consts");
+                            }
+                        }
+                    }
                 }
                 err.emit_note(*ecx.tcx);
                 err
diff --git a/compiler/rustc_const_eval/src/interpret/intern.rs b/compiler/rustc_const_eval/src/interpret/intern.rs
index 3565b4fb516..c34b658fb37 100644
--- a/compiler/rustc_const_eval/src/interpret/intern.rs
+++ b/compiler/rustc_const_eval/src/interpret/intern.rs
@@ -23,6 +23,7 @@ use rustc_middle::query::TyCtxtAt;
 use rustc_middle::ty::layout::TyAndLayout;
 use rustc_span::def_id::LocalDefId;
 use rustc_span::sym;
+use tracing::{instrument, trace};
 
 use super::{err_ub, AllocId, Allocation, InterpCx, MPlaceTy, Machine, MemoryKind, PlaceTy};
 use crate::const_eval;
diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs
index 72dad562695..3a8f8dc4cb9 100644
--- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs
+++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs
@@ -14,6 +14,7 @@ use rustc_middle::{
 };
 use rustc_span::symbol::{sym, Symbol};
 use rustc_target::abi::Size;
+use tracing::trace;
 
 use super::{
     err_inval, err_ub_custom, err_unsup_format, memory::MemoryKind, throw_inval, throw_ub_custom,
@@ -286,9 +287,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                     let (val, overflowed) = {
                         let a_offset = ImmTy::from_uint(a_offset, usize_layout);
                         let b_offset = ImmTy::from_uint(b_offset, usize_layout);
-                        self.overflowing_binary_op(BinOp::Sub, &a_offset, &b_offset)?
+                        self.binary_op(BinOp::SubWithOverflow, &a_offset, &b_offset)?
+                            .to_scalar_pair()
                     };
-                    if overflowed {
+                    if overflowed.to_bool()? {
                         // a < b
                         if intrinsic_name == sym::ptr_offset_from_unsigned {
                             throw_ub_custom!(
@@ -300,7 +302,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                         // The signed form of the intrinsic allows this. If we interpret the
                         // difference as isize, we'll get the proper signed difference. If that
                         // seems *positive*, they were more than isize::MAX apart.
-                        let dist = val.to_scalar().to_target_isize(self)?;
+                        let dist = val.to_target_isize(self)?;
                         if dist >= 0 {
                             throw_ub_custom!(
                                 fluent::const_eval_offset_from_underflow,
@@ -310,7 +312,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                         dist
                     } else {
                         // b >= a
-                        let dist = val.to_scalar().to_target_isize(self)?;
+                        let dist = val.to_target_isize(self)?;
                         // If converting to isize produced a *negative* result, we had an overflow
                         // because they were more than isize::MAX apart.
                         if dist < 0 {
@@ -516,9 +518,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         // Performs an exact division, resulting in undefined behavior where
         // `x % y != 0` or `y == 0` or `x == T::MIN && y == -1`.
         // First, check x % y != 0 (or if that computation overflows).
-        let (res, overflow) = self.overflowing_binary_op(BinOp::Rem, a, b)?;
-        assert!(!overflow); // All overflow is UB, so this should never return on overflow.
-        if res.to_scalar().assert_bits(a.layout.size) != 0 {
+        let rem = self.binary_op(BinOp::Rem, a, b)?;
+        if rem.to_scalar().assert_bits(a.layout.size) != 0 {
             throw_ub_custom!(
                 fluent::const_eval_exact_div_has_remainder,
                 a = format!("{a}"),
@@ -526,7 +527,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
             )
         }
         // `Rem` says this is all right, so we can let `Div` do its job.
-        self.binop_ignore_overflow(BinOp::Div, a, b, &dest.clone().into())
+        let res = self.binary_op(BinOp::Div, a, b)?;
+        self.write_immediate(*res, dest)
     }
 
     pub fn saturating_arith(
@@ -539,8 +541,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         assert!(matches!(l.layout.ty.kind(), ty::Int(..) | ty::Uint(..)));
         assert!(matches!(mir_op, BinOp::Add | BinOp::Sub));
 
-        let (val, overflowed) = self.overflowing_binary_op(mir_op, l, r)?;
-        Ok(if overflowed {
+        let (val, overflowed) =
+            self.binary_op(mir_op.wrapping_to_overflowing().unwrap(), l, r)?.to_scalar_pair();
+        Ok(if overflowed.to_bool()? {
             let size = l.layout.size;
             let num_bits = size.bits();
             if l.layout.abi.is_signed() {
@@ -571,7 +574,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                 }
             }
         } else {
-            val.to_scalar()
+            val
         })
     }
 
diff --git a/compiler/rustc_const_eval/src/interpret/machine.rs b/compiler/rustc_const_eval/src/interpret/machine.rs
index 2eaebc1924b..72a16dbe4d6 100644
--- a/compiler/rustc_const_eval/src/interpret/machine.rs
+++ b/compiler/rustc_const_eval/src/interpret/machine.rs
@@ -252,7 +252,7 @@ pub trait Machine<'mir, 'tcx: 'mir>: Sized {
         bin_op: mir::BinOp,
         left: &ImmTy<'tcx, Self::Provenance>,
         right: &ImmTy<'tcx, Self::Provenance>,
-    ) -> InterpResult<'tcx, (ImmTy<'tcx, Self::Provenance>, bool)>;
+    ) -> InterpResult<'tcx, ImmTy<'tcx, Self::Provenance>>;
 
     /// Generate the NaN returned by a float operation, given the list of inputs.
     /// (This is all inputs, not just NaN inputs!)
diff --git a/compiler/rustc_const_eval/src/interpret/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs
index 737f2fd8bb9..23273e69444 100644
--- a/compiler/rustc_const_eval/src/interpret/memory.rs
+++ b/compiler/rustc_const_eval/src/interpret/memory.rs
@@ -21,6 +21,8 @@ use rustc_middle::mir::display_allocation;
 use rustc_middle::ty::{self, Instance, ParamEnv, Ty, TyCtxt};
 use rustc_target::abi::{Align, HasDataLayout, Size};
 
+use tracing::{debug, instrument, trace};
+
 use crate::fluent_generated as fluent;
 
 use super::{
diff --git a/compiler/rustc_const_eval/src/interpret/operand.rs b/compiler/rustc_const_eval/src/interpret/operand.rs
index bad9732f483..8f01b872010 100644
--- a/compiler/rustc_const_eval/src/interpret/operand.rs
+++ b/compiler/rustc_const_eval/src/interpret/operand.rs
@@ -4,10 +4,11 @@
 use std::assert_matches::assert_matches;
 
 use either::{Either, Left, Right};
+use tracing::trace;
 
 use rustc_hir::def::Namespace;
 use rustc_middle::mir::interpret::ScalarSizeMismatch;
-use rustc_middle::ty::layout::{LayoutOf, TyAndLayout};
+use rustc_middle::ty::layout::{HasParamEnv, HasTyCtxt, LayoutOf, TyAndLayout};
 use rustc_middle::ty::print::{FmtPrinter, PrettyPrinter};
 use rustc_middle::ty::{ConstInt, ScalarInt, Ty, TyCtxt};
 use rustc_middle::{bug, span_bug};
@@ -249,6 +250,15 @@ impl<'tcx, Prov: Provenance> ImmTy<'tcx, Prov> {
         Self::from_scalar(Scalar::from_i8(c as i8), layout)
     }
 
+    pub fn from_pair(a: Self, b: Self, tcx: TyCtxt<'tcx>) -> Self {
+        let layout = tcx
+            .layout_of(
+                ty::ParamEnv::reveal_all().and(Ty::new_tup(tcx, &[a.layout.ty, b.layout.ty])),
+            )
+            .unwrap();
+        Self::from_scalar_pair(a.to_scalar(), b.to_scalar(), layout)
+    }
+
     /// Return the immediate as a `ScalarInt`. Ensures that it has the size that the layout of the
     /// immediate indicates.
     #[inline]
@@ -270,6 +280,17 @@ impl<'tcx, Prov: Provenance> ImmTy<'tcx, Prov> {
         ConstInt::new(int, self.layout.ty.is_signed(), self.layout.ty.is_ptr_sized_integral())
     }
 
+    #[inline]
+    #[cfg_attr(debug_assertions, track_caller)] // only in debug builds due to perf (see #98980)
+    pub fn to_pair(self, cx: &(impl HasTyCtxt<'tcx> + HasParamEnv<'tcx>)) -> (Self, Self) {
+        let layout = self.layout;
+        let (val0, val1) = self.to_scalar_pair();
+        (
+            ImmTy::from_scalar(val0, layout.field(cx, 0)),
+            ImmTy::from_scalar(val1, layout.field(cx, 1)),
+        )
+    }
+
     /// Compute the "sub-immediate" that is located within the `base` at the given offset with the
     /// given layout.
     // Not called `offset` to avoid confusion with the trait method.
diff --git a/compiler/rustc_const_eval/src/interpret/operator.rs b/compiler/rustc_const_eval/src/interpret/operator.rs
index 5f59e3d887e..62641b868e6 100644
--- a/compiler/rustc_const_eval/src/interpret/operator.rs
+++ b/compiler/rustc_const_eval/src/interpret/operator.rs
@@ -1,78 +1,23 @@
+use either::Either;
+
 use rustc_apfloat::{Float, FloatConvert};
 use rustc_middle::mir;
 use rustc_middle::mir::interpret::{InterpResult, Scalar};
 use rustc_middle::ty::layout::{LayoutOf, TyAndLayout};
-use rustc_middle::ty::{self, FloatTy, ScalarInt, Ty};
+use rustc_middle::ty::{self, FloatTy, ScalarInt};
 use rustc_middle::{bug, span_bug};
 use rustc_span::symbol::sym;
-use rustc_target::abi::Abi;
-
-use super::{err_ub, throw_ub, throw_ub_custom, ImmTy, Immediate, InterpCx, Machine, PlaceTy};
+use tracing::trace;
 
-use crate::fluent_generated as fluent;
-
-impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
-    /// Applies the binary operation `op` to the two operands and writes a tuple of the result
-    /// and a boolean signifying the potential overflow to the destination.
-    pub fn binop_with_overflow(
-        &mut self,
-        op: mir::BinOp,
-        left: &ImmTy<'tcx, M::Provenance>,
-        right: &ImmTy<'tcx, M::Provenance>,
-        dest: &PlaceTy<'tcx, M::Provenance>,
-    ) -> InterpResult<'tcx> {
-        let (val, overflowed) = self.overflowing_binary_op(op, left, right)?;
-        debug_assert_eq!(
-            Ty::new_tup(self.tcx.tcx, &[val.layout.ty, self.tcx.types.bool]),
-            dest.layout.ty,
-            "type mismatch for result of {op:?}",
-        );
-        // Write the result to `dest`.
-        if let Abi::ScalarPair(..) = dest.layout.abi {
-            // We can use the optimized path and avoid `place_field` (which might do
-            // `force_allocation`).
-            let pair = Immediate::ScalarPair(val.to_scalar(), Scalar::from_bool(overflowed));
-            self.write_immediate(pair, dest)?;
-        } else {
-            assert!(self.tcx.sess.opts.unstable_opts.randomize_layout);
-            // With randomized layout, `(int, bool)` might cease to be a `ScalarPair`, so we have to
-            // do a component-wise write here. This code path is slower than the above because
-            // `place_field` will have to `force_allocate` locals here.
-            let val_field = self.project_field(dest, 0)?;
-            self.write_scalar(val.to_scalar(), &val_field)?;
-            let overflowed_field = self.project_field(dest, 1)?;
-            self.write_scalar(Scalar::from_bool(overflowed), &overflowed_field)?;
-        }
-        Ok(())
-    }
-
-    /// Applies the binary operation `op` to the arguments and writes the result to the
-    /// destination.
-    pub fn binop_ignore_overflow(
-        &mut self,
-        op: mir::BinOp,
-        left: &ImmTy<'tcx, M::Provenance>,
-        right: &ImmTy<'tcx, M::Provenance>,
-        dest: &PlaceTy<'tcx, M::Provenance>,
-    ) -> InterpResult<'tcx> {
-        let val = self.wrapping_binary_op(op, left, right)?;
-        assert_eq!(val.layout.ty, dest.layout.ty, "type mismatch for result of {op:?}");
-        self.write_immediate(*val, dest)
-    }
-}
+use super::{err_ub, throw_ub, ImmTy, InterpCx, Machine};
 
 impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
-    fn three_way_compare<T: Ord>(&self, lhs: T, rhs: T) -> (ImmTy<'tcx, M::Provenance>, bool) {
+    fn three_way_compare<T: Ord>(&self, lhs: T, rhs: T) -> ImmTy<'tcx, M::Provenance> {
         let res = Ord::cmp(&lhs, &rhs);
-        return (ImmTy::from_ordering(res, *self.tcx), false);
+        return ImmTy::from_ordering(res, *self.tcx);
     }
 
-    fn binary_char_op(
-        &self,
-        bin_op: mir::BinOp,
-        l: char,
-        r: char,
-    ) -> (ImmTy<'tcx, M::Provenance>, bool) {
+    fn binary_char_op(&self, bin_op: mir::BinOp, l: char, r: char) -> ImmTy<'tcx, M::Provenance> {
         use rustc_middle::mir::BinOp::*;
 
         if bin_op == Cmp {
@@ -88,15 +33,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
             Ge => l >= r,
             _ => span_bug!(self.cur_span(), "Invalid operation on char: {:?}", bin_op),
         };
-        (ImmTy::from_bool(res, *self.tcx), false)
+        ImmTy::from_bool(res, *self.tcx)
     }
 
-    fn binary_bool_op(
-        &self,
-        bin_op: mir::BinOp,
-        l: bool,
-        r: bool,
-    ) -> (ImmTy<'tcx, M::Provenance>, bool) {
+    fn binary_bool_op(&self, bin_op: mir::BinOp, l: bool, r: bool) -> ImmTy<'tcx, M::Provenance> {
         use rustc_middle::mir::BinOp::*;
 
         let res = match bin_op {
@@ -111,7 +51,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
             BitXor => l ^ r,
             _ => span_bug!(self.cur_span(), "Invalid operation on bool: {:?}", bin_op),
         };
-        (ImmTy::from_bool(res, *self.tcx), false)
+        ImmTy::from_bool(res, *self.tcx)
     }
 
     fn binary_float_op<F: Float + FloatConvert<F> + Into<Scalar<M::Provenance>>>(
@@ -120,14 +60,14 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         layout: TyAndLayout<'tcx>,
         l: F,
         r: F,
-    ) -> (ImmTy<'tcx, M::Provenance>, bool) {
+    ) -> ImmTy<'tcx, M::Provenance> {
         use rustc_middle::mir::BinOp::*;
 
         // Performs appropriate non-deterministic adjustments of NaN results.
         let adjust_nan =
             |f: F| -> F { if f.is_nan() { M::generate_nan(self, &[l, r]) } else { f } };
 
-        let val = match bin_op {
+        match bin_op {
             Eq => ImmTy::from_bool(l == r, *self.tcx),
             Ne => ImmTy::from_bool(l != r, *self.tcx),
             Lt => ImmTy::from_bool(l < r, *self.tcx),
@@ -140,8 +80,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
             Div => ImmTy::from_scalar(adjust_nan((l / r).value).into(), layout),
             Rem => ImmTy::from_scalar(adjust_nan((l % r).value).into(), layout),
             _ => span_bug!(self.cur_span(), "invalid float op: `{:?}`", bin_op),
-        };
-        (val, false)
+        }
     }
 
     fn binary_int_op(
@@ -149,7 +88,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         bin_op: mir::BinOp,
         left: &ImmTy<'tcx, M::Provenance>,
         right: &ImmTy<'tcx, M::Provenance>,
-    ) -> InterpResult<'tcx, (ImmTy<'tcx, M::Provenance>, bool)> {
+    ) -> InterpResult<'tcx, ImmTy<'tcx, M::Provenance>> {
         use rustc_middle::mir::BinOp::*;
 
         // This checks the size, so that we can just assert it below.
@@ -169,25 +108,27 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
             ShrUnchecked => Some(sym::unchecked_shr),
             _ => None,
         };
+        let with_overflow = bin_op.is_overflowing();
 
         // Shift ops can have an RHS with a different numeric type.
         if matches!(bin_op, Shl | ShlUnchecked | Shr | ShrUnchecked) {
             let size = left.layout.size.bits();
-            // The shift offset is implicitly masked to the type size. (This is the one MIR operator
-            // that does *not* directly map to a single LLVM operation.) Compute how much we
-            // actually shift and whether there was an overflow due to shifting too much.
+            // Compute the equivalent shift modulo `size` that is in the range `0..size`. (This is
+            // the one MIR operator that does *not* directly map to a single LLVM operation.)
             let (shift_amount, overflow) = if right.layout.abi.is_signed() {
                 let shift_amount = r_signed();
                 let overflow = shift_amount < 0 || shift_amount >= i128::from(size);
                 // Deliberately wrapping `as` casts: shift_amount *can* be negative, but the result
                 // of the `as` will be equal modulo `size` (since it is a power of two).
                 let masked_amount = (shift_amount as u128) % u128::from(size);
-                assert_eq!(overflow, shift_amount != (masked_amount as i128));
+                assert_eq!(overflow, shift_amount != i128::try_from(masked_amount).unwrap());
                 (masked_amount, overflow)
             } else {
                 let shift_amount = r_unsigned();
+                let overflow = shift_amount >= u128::from(size);
                 let masked_amount = shift_amount % u128::from(size);
-                (masked_amount, shift_amount != masked_amount)
+                assert_eq!(overflow, shift_amount != masked_amount);
+                (masked_amount, overflow)
             };
             let shift_amount = u32::try_from(shift_amount).unwrap(); // we masked so this will always fit
             // Compute the shifted result.
@@ -209,19 +150,18 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                 ScalarInt::truncate_from_uint(result, left.layout.size).0
             };
 
-            if overflow && let Some(intrinsic_name) = throw_ub_on_overflow {
-                throw_ub_custom!(
-                    fluent::const_eval_overflow_shift,
-                    val = if right.layout.abi.is_signed() {
-                        r_signed().to_string()
+            if overflow && let Some(intrinsic) = throw_ub_on_overflow {
+                throw_ub!(ShiftOverflow {
+                    intrinsic,
+                    shift_amount: if right.layout.abi.is_signed() {
+                        Either::Right(r_signed())
                     } else {
-                        r_unsigned().to_string()
-                    },
-                    name = intrinsic_name
-                );
+                        Either::Left(r_unsigned())
+                    }
+                });
             }
 
-            return Ok((ImmTy::from_scalar_int(result, left.layout), overflow));
+            return Ok(ImmTy::from_scalar_int(result, left.layout));
         }
 
         // For the remaining ops, the types must be the same on both sides
@@ -246,7 +186,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                 _ => None,
             };
             if let Some(op) = op {
-                return Ok((ImmTy::from_bool(op(&l_signed(), &r_signed()), *self.tcx), false));
+                return Ok(ImmTy::from_bool(op(&l_signed(), &r_signed()), *self.tcx));
             }
             if bin_op == Cmp {
                 return Ok(self.three_way_compare(l_signed(), r_signed()));
@@ -256,9 +196,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                 Rem if r.is_null() => throw_ub!(RemainderByZero),
                 Div => Some(i128::overflowing_div),
                 Rem => Some(i128::overflowing_rem),
-                Add | AddUnchecked => Some(i128::overflowing_add),
-                Sub | SubUnchecked => Some(i128::overflowing_sub),
-                Mul | MulUnchecked => Some(i128::overflowing_mul),
+                Add | AddUnchecked | AddWithOverflow => Some(i128::overflowing_add),
+                Sub | SubUnchecked | SubWithOverflow => Some(i128::overflowing_sub),
+                Mul | MulUnchecked | MulWithOverflow => Some(i128::overflowing_mul),
                 _ => None,
             };
             if let Some(op) = op {
@@ -282,10 +222,16 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                 // If that truncation loses any information, we have an overflow.
                 let (result, lossy) = ScalarInt::truncate_from_int(result, left.layout.size);
                 let overflow = oflo || lossy;
-                if overflow && let Some(intrinsic_name) = throw_ub_on_overflow {
-                    throw_ub_custom!(fluent::const_eval_overflow, name = intrinsic_name);
+                if overflow && let Some(intrinsic) = throw_ub_on_overflow {
+                    throw_ub!(ArithOverflow { intrinsic });
                 }
-                return Ok((ImmTy::from_scalar_int(result, left.layout), overflow));
+                let res = ImmTy::from_scalar_int(result, left.layout);
+                return Ok(if with_overflow {
+                    let overflow = ImmTy::from_bool(overflow, *self.tcx);
+                    ImmTy::from_pair(res, overflow, *self.tcx)
+                } else {
+                    res
+                });
             }
         }
         // From here on it's okay to treat everything as unsigned.
@@ -296,7 +242,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
             return Ok(self.three_way_compare(l, r));
         }
 
-        let val = match bin_op {
+        Ok(match bin_op {
             Eq => ImmTy::from_bool(l == r, *self.tcx),
             Ne => ImmTy::from_bool(l != r, *self.tcx),
 
@@ -309,40 +255,42 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
             BitAnd => ImmTy::from_uint(l & r, left.layout),
             BitXor => ImmTy::from_uint(l ^ r, left.layout),
 
-            Add | AddUnchecked | Sub | SubUnchecked | Mul | MulUnchecked | Rem | Div => {
+            _ => {
                 assert!(!left.layout.abi.is_signed());
                 let op: fn(u128, u128) -> (u128, bool) = match bin_op {
-                    Add | AddUnchecked => u128::overflowing_add,
-                    Sub | SubUnchecked => u128::overflowing_sub,
-                    Mul | MulUnchecked => u128::overflowing_mul,
+                    Add | AddUnchecked | AddWithOverflow => u128::overflowing_add,
+                    Sub | SubUnchecked | SubWithOverflow => u128::overflowing_sub,
+                    Mul | MulUnchecked | MulWithOverflow => u128::overflowing_mul,
                     Div if r == 0 => throw_ub!(DivisionByZero),
                     Rem if r == 0 => throw_ub!(RemainderByZero),
                     Div => u128::overflowing_div,
                     Rem => u128::overflowing_rem,
-                    _ => bug!(),
+                    _ => span_bug!(
+                        self.cur_span(),
+                        "invalid binary op {:?}: {:?}, {:?} (both {})",
+                        bin_op,
+                        left,
+                        right,
+                        right.layout.ty,
+                    ),
                 };
                 let (result, oflo) = op(l, r);
                 // Truncate to target type.
                 // If that truncation loses any information, we have an overflow.
                 let (result, lossy) = ScalarInt::truncate_from_uint(result, left.layout.size);
                 let overflow = oflo || lossy;
-                if overflow && let Some(intrinsic_name) = throw_ub_on_overflow {
-                    throw_ub_custom!(fluent::const_eval_overflow, name = intrinsic_name);
+                if overflow && let Some(intrinsic) = throw_ub_on_overflow {
+                    throw_ub!(ArithOverflow { intrinsic });
+                }
+                let res = ImmTy::from_scalar_int(result, left.layout);
+                if with_overflow {
+                    let overflow = ImmTy::from_bool(overflow, *self.tcx);
+                    ImmTy::from_pair(res, overflow, *self.tcx)
+                } else {
+                    res
                 }
-                return Ok((ImmTy::from_scalar_int(result, left.layout), overflow));
             }
-
-            _ => span_bug!(
-                self.cur_span(),
-                "invalid binary op {:?}: {:?}, {:?} (both {})",
-                bin_op,
-                left,
-                right,
-                right.layout.ty,
-            ),
-        };
-
-        Ok((val, false))
+        })
     }
 
     fn binary_ptr_op(
@@ -350,7 +298,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         bin_op: mir::BinOp,
         left: &ImmTy<'tcx, M::Provenance>,
         right: &ImmTy<'tcx, M::Provenance>,
-    ) -> InterpResult<'tcx, (ImmTy<'tcx, M::Provenance>, bool)> {
+    ) -> InterpResult<'tcx, ImmTy<'tcx, M::Provenance>> {
         use rustc_middle::mir::BinOp::*;
 
         match bin_op {
@@ -369,10 +317,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                     offset_count.checked_mul(pointee_size).ok_or(err_ub!(PointerArithOverflow))?;
 
                 let offset_ptr = self.ptr_offset_inbounds(ptr, offset_bytes)?;
-                Ok((
-                    ImmTy::from_scalar(Scalar::from_maybe_pointer(offset_ptr, self), left.layout),
-                    false,
-                ))
+                Ok(ImmTy::from_scalar(Scalar::from_maybe_pointer(offset_ptr, self), left.layout))
             }
 
             // Fall back to machine hook so Miri can support more pointer ops.
@@ -380,13 +325,15 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         }
     }
 
-    /// Returns the result of the specified operation, and whether it overflowed.
-    pub fn overflowing_binary_op(
+    /// Returns the result of the specified operation.
+    ///
+    /// Whether this produces a scalar or a pair depends on the specific `bin_op`.
+    pub fn binary_op(
         &self,
         bin_op: mir::BinOp,
         left: &ImmTy<'tcx, M::Provenance>,
         right: &ImmTy<'tcx, M::Provenance>,
-    ) -> InterpResult<'tcx, (ImmTy<'tcx, M::Provenance>, bool)> {
+    ) -> InterpResult<'tcx, ImmTy<'tcx, M::Provenance>> {
         trace!(
             "Running binary op {:?}: {:?} ({}), {:?} ({})",
             bin_op,
@@ -458,24 +405,13 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         }
     }
 
-    #[inline]
-    pub fn wrapping_binary_op(
-        &self,
-        bin_op: mir::BinOp,
-        left: &ImmTy<'tcx, M::Provenance>,
-        right: &ImmTy<'tcx, M::Provenance>,
-    ) -> InterpResult<'tcx, ImmTy<'tcx, M::Provenance>> {
-        let (val, _overflow) = self.overflowing_binary_op(bin_op, left, right)?;
-        Ok(val)
-    }
-
     /// Returns the result of the specified operation, whether it overflowed, and
     /// the result type.
-    pub fn overflowing_unary_op(
+    pub fn unary_op(
         &self,
         un_op: mir::UnOp,
         val: &ImmTy<'tcx, M::Provenance>,
-    ) -> InterpResult<'tcx, (ImmTy<'tcx, M::Provenance>, bool)> {
+    ) -> InterpResult<'tcx, ImmTy<'tcx, M::Provenance>> {
         use rustc_middle::mir::UnOp::*;
 
         let layout = val.layout;
@@ -489,7 +425,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                     Not => !val,
                     _ => span_bug!(self.cur_span(), "Invalid bool op {:?}", un_op),
                 };
-                Ok((ImmTy::from_bool(res, *self.tcx), false))
+                Ok(ImmTy::from_bool(res, *self.tcx))
             }
             ty::Float(fty) => {
                 // No NaN adjustment here, `-` is a bitwise operation!
@@ -498,37 +434,25 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                     (Neg, FloatTy::F64) => Scalar::from_f64(-val.to_f64()?),
                     _ => span_bug!(self.cur_span(), "Invalid float op {:?}", un_op),
                 };
-                Ok((ImmTy::from_scalar(res, layout), false))
+                Ok(ImmTy::from_scalar(res, layout))
             }
             _ => {
                 assert!(layout.ty.is_integral());
                 let val = val.to_bits(layout.size)?;
-                let (res, overflow) = match un_op {
-                    Not => (self.truncate(!val, layout), false), // bitwise negation, then truncate
+                let res = match un_op {
+                    Not => self.truncate(!val, layout), // bitwise negation, then truncate
                     Neg => {
                         // arithmetic negation
                         assert!(layout.abi.is_signed());
                         let val = self.sign_extend(val, layout) as i128;
-                        let (res, overflow) = val.overflowing_neg();
+                        let res = val.wrapping_neg();
                         let res = res as u128;
                         // Truncate to target type.
-                        // If that truncation loses any information, we have an overflow.
-                        let truncated = self.truncate(res, layout);
-                        (truncated, overflow || self.sign_extend(truncated, layout) != res)
+                        self.truncate(res, layout)
                     }
                 };
-                Ok((ImmTy::from_uint(res, layout), overflow))
+                Ok(ImmTy::from_uint(res, layout))
             }
         }
     }
-
-    #[inline]
-    pub fn wrapping_unary_op(
-        &self,
-        un_op: mir::UnOp,
-        val: &ImmTy<'tcx, M::Provenance>,
-    ) -> InterpResult<'tcx, ImmTy<'tcx, M::Provenance>> {
-        let (val, _overflow) = self.overflowing_unary_op(un_op, val)?;
-        Ok(val)
-    }
 }
diff --git a/compiler/rustc_const_eval/src/interpret/place.rs b/compiler/rustc_const_eval/src/interpret/place.rs
index 9ced825853b..588db0f547f 100644
--- a/compiler/rustc_const_eval/src/interpret/place.rs
+++ b/compiler/rustc_const_eval/src/interpret/place.rs
@@ -5,6 +5,7 @@
 use std::assert_matches::assert_matches;
 
 use either::{Either, Left, Right};
+use tracing::{instrument, trace};
 
 use rustc_ast::Mutability;
 use rustc_middle::mir;
diff --git a/compiler/rustc_const_eval/src/interpret/projection.rs b/compiler/rustc_const_eval/src/interpret/projection.rs
index 0a2fedb4840..cfc4d701aa7 100644
--- a/compiler/rustc_const_eval/src/interpret/projection.rs
+++ b/compiler/rustc_const_eval/src/interpret/projection.rs
@@ -18,6 +18,8 @@ use rustc_middle::{bug, span_bug};
 use rustc_target::abi::Size;
 use rustc_target::abi::{self, VariantIdx};
 
+use tracing::{debug, instrument};
+
 use super::{
     throw_ub, throw_unsup_format, InterpCx, InterpResult, MPlaceTy, Machine, MemPlaceMeta, OpTy,
     Provenance, Scalar,
diff --git a/compiler/rustc_const_eval/src/interpret/step.rs b/compiler/rustc_const_eval/src/interpret/step.rs
index cb72d55a9ba..58210fe3971 100644
--- a/compiler/rustc_const_eval/src/interpret/step.rs
+++ b/compiler/rustc_const_eval/src/interpret/step.rs
@@ -3,6 +3,7 @@
 //! The main entry point is the `step` method.
 
 use either::Either;
+use tracing::{info, instrument, trace};
 
 use rustc_index::IndexSlice;
 use rustc_middle::mir;
@@ -167,19 +168,17 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                 let left = self.read_immediate(&self.eval_operand(left, layout)?)?;
                 let layout = util::binop_right_homogeneous(bin_op).then_some(left.layout);
                 let right = self.read_immediate(&self.eval_operand(right, layout)?)?;
-                if let Some(bin_op) = bin_op.overflowing_to_wrapping() {
-                    self.binop_with_overflow(bin_op, &left, &right, &dest)?;
-                } else {
-                    self.binop_ignore_overflow(bin_op, &left, &right, &dest)?;
-                }
+                let result = self.binary_op(bin_op, &left, &right)?;
+                assert_eq!(result.layout, dest.layout, "layout mismatch for result of {bin_op:?}");
+                self.write_immediate(*result, &dest)?;
             }
 
             UnaryOp(un_op, ref operand) => {
                 // The operand always has the same type as the result.
                 let val = self.read_immediate(&self.eval_operand(operand, Some(dest.layout))?)?;
-                let val = self.wrapping_unary_op(un_op, &val)?;
-                assert_eq!(val.layout, dest.layout, "layout mismatch for result of {un_op:?}");
-                self.write_immediate(*val, &dest)?;
+                let result = self.unary_op(un_op, &val)?;
+                assert_eq!(result.layout, dest.layout, "layout mismatch for result of {un_op:?}");
+                self.write_immediate(*result, &dest)?;
             }
 
             Aggregate(box ref kind, ref operands) => {
diff --git a/compiler/rustc_const_eval/src/interpret/terminator.rs b/compiler/rustc_const_eval/src/interpret/terminator.rs
index b82c1857858..360cefb5a1f 100644
--- a/compiler/rustc_const_eval/src/interpret/terminator.rs
+++ b/compiler/rustc_const_eval/src/interpret/terminator.rs
@@ -1,6 +1,7 @@
 use std::borrow::Cow;
 
 use either::Either;
+use tracing::trace;
 
 use rustc_middle::span_bug;
 use rustc_middle::{
@@ -97,7 +98,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                 for (const_int, target) in targets.iter() {
                     // Compare using MIR BinOp::Eq, to also support pointer values.
                     // (Avoiding `self.binary_op` as that does some redundant layout computation.)
-                    let res = self.wrapping_binary_op(
+                    let res = self.binary_op(
                         mir::BinOp::Eq,
                         &discr,
                         &ImmTy::from_uint(const_int, discr.layout),
diff --git a/compiler/rustc_const_eval/src/interpret/traits.rs b/compiler/rustc_const_eval/src/interpret/traits.rs
index b603ef0d27a..8b590459405 100644
--- a/compiler/rustc_const_eval/src/interpret/traits.rs
+++ b/compiler/rustc_const_eval/src/interpret/traits.rs
@@ -2,6 +2,7 @@ use rustc_middle::mir::interpret::{InterpResult, Pointer};
 use rustc_middle::ty::layout::LayoutOf;
 use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_target::abi::{Align, Size};
+use tracing::trace;
 
 use super::util::ensure_monomorphic_enough;
 use super::{InterpCx, Machine};
diff --git a/compiler/rustc_const_eval/src/interpret/util.rs b/compiler/rustc_const_eval/src/interpret/util.rs
index e304d1e1cc5..f0f9df73d94 100644
--- a/compiler/rustc_const_eval/src/interpret/util.rs
+++ b/compiler/rustc_const_eval/src/interpret/util.rs
@@ -7,6 +7,7 @@ use rustc_middle::ty::{
     self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor,
 };
 use std::ops::ControlFlow;
+use tracing::debug;
 
 use super::{throw_inval, InterpCx, MPlaceTy, MemPlaceMeta, MemoryKind};
 
diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs
index e36d30184c8..cf6027a312f 100644
--- a/compiler/rustc_const_eval/src/interpret/validity.rs
+++ b/compiler/rustc_const_eval/src/interpret/validity.rs
@@ -8,6 +8,7 @@ use std::fmt::Write;
 use std::num::NonZero;
 
 use either::{Left, Right};
+use tracing::trace;
 
 use hir::def::DefKind;
 use rustc_ast::Mutability;
diff --git a/compiler/rustc_const_eval/src/interpret/visitor.rs b/compiler/rustc_const_eval/src/interpret/visitor.rs
index 59bcc5174cb..692eb6c17e6 100644
--- a/compiler/rustc_const_eval/src/interpret/visitor.rs
+++ b/compiler/rustc_const_eval/src/interpret/visitor.rs
@@ -6,6 +6,7 @@ use rustc_middle::mir::interpret::InterpResult;
 use rustc_middle::ty::{self, Ty};
 use rustc_target::abi::FieldIdx;
 use rustc_target::abi::{FieldsShape, VariantIdx, Variants};
+use tracing::trace;
 
 use std::num::NonZero;
 
diff --git a/compiler/rustc_const_eval/src/lib.rs b/compiler/rustc_const_eval/src/lib.rs
index 7b293e2b533..b14780c0d98 100644
--- a/compiler/rustc_const_eval/src/lib.rs
+++ b/compiler/rustc_const_eval/src/lib.rs
@@ -14,9 +14,6 @@
 #![feature(yeet_expr)]
 #![feature(if_let_guard)]
 
-#[macro_use]
-extern crate tracing;
-
 pub mod const_eval;
 mod errors;
 pub mod interpret;
diff --git a/compiler/rustc_const_eval/src/transform/check_consts/check.rs b/compiler/rustc_const_eval/src/transform/check_consts/check.rs
index c8c54143f61..5fbf5b41109 100644
--- a/compiler/rustc_const_eval/src/transform/check_consts/check.rs
+++ b/compiler/rustc_const_eval/src/transform/check_consts/check.rs
@@ -20,6 +20,8 @@ use rustc_type_ir::visit::{TypeSuperVisitable, TypeVisitor};
 use std::mem;
 use std::ops::Deref;
 
+use tracing::{debug, instrument, trace};
+
 use super::ops::{self, NonConstOp, Status};
 use super::qualifs::{self, HasMutInterior, NeedsDrop, NeedsNonConstDrop};
 use super::resolver::FlowSensitiveAnalysis;
diff --git a/compiler/rustc_const_eval/src/transform/check_consts/ops.rs b/compiler/rustc_const_eval/src/transform/check_consts/ops.rs
index 8775685e8c7..8406e0f4876 100644
--- a/compiler/rustc_const_eval/src/transform/check_consts/ops.rs
+++ b/compiler/rustc_const_eval/src/transform/check_consts/ops.rs
@@ -19,6 +19,7 @@ use rustc_session::parse::feature_err;
 use rustc_span::symbol::sym;
 use rustc_span::{BytePos, Pos, Span, Symbol};
 use rustc_trait_selection::traits::SelectionContext;
+use tracing::debug;
 
 use super::ConstCx;
 use crate::errors;
diff --git a/compiler/rustc_const_eval/src/transform/check_consts/post_drop_elaboration.rs b/compiler/rustc_const_eval/src/transform/check_consts/post_drop_elaboration.rs
index 5cd13783c23..f0763f1e490 100644
--- a/compiler/rustc_const_eval/src/transform/check_consts/post_drop_elaboration.rs
+++ b/compiler/rustc_const_eval/src/transform/check_consts/post_drop_elaboration.rs
@@ -2,6 +2,7 @@ use rustc_middle::mir::visit::Visitor;
 use rustc_middle::mir::{self, BasicBlock, Location};
 use rustc_middle::ty::{Ty, TyCtxt};
 use rustc_span::{symbol::sym, Span};
+use tracing::trace;
 
 use super::check::Qualifs;
 use super::ops::{self, NonConstOp};
diff --git a/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs b/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs
index 7e8a208659b..5949444e599 100644
--- a/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs
+++ b/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs
@@ -13,6 +13,7 @@ use rustc_middle::ty::{self, AdtDef, GenericArgsRef, Ty};
 use rustc_trait_selection::traits::{
     ImplSource, Obligation, ObligationCause, ObligationCtxt, SelectionContext,
 };
+use tracing::{instrument, trace};
 
 use super::ConstCx;
 
diff --git a/compiler/rustc_const_eval/src/util/alignment.rs b/compiler/rustc_const_eval/src/util/alignment.rs
index 8642dfccd78..528274e6aba 100644
--- a/compiler/rustc_const_eval/src/util/alignment.rs
+++ b/compiler/rustc_const_eval/src/util/alignment.rs
@@ -1,6 +1,7 @@
 use rustc_middle::mir::*;
 use rustc_middle::ty::{self, TyCtxt};
 use rustc_target::abi::Align;
+use tracing::debug;
 
 /// Returns `true` if this place is allowed to be less aligned
 /// than its containing struct (because it is within a packed
diff --git a/compiler/rustc_const_eval/src/util/caller_location.rs b/compiler/rustc_const_eval/src/util/caller_location.rs
index 403bc1eca13..bc5fe39f867 100644
--- a/compiler/rustc_const_eval/src/util/caller_location.rs
+++ b/compiler/rustc_const_eval/src/util/caller_location.rs
@@ -5,6 +5,7 @@ use rustc_middle::query::TyCtxtAt;
 use rustc_middle::ty::layout::LayoutOf;
 use rustc_middle::ty::{self, Mutability};
 use rustc_span::symbol::Symbol;
+use tracing::trace;
 
 use crate::const_eval::{mk_eval_cx_to_read_const_val, CanAccessMutGlobal, CompileTimeEvalContext};
 use crate::interpret::*;
diff --git a/compiler/rustc_error_messages/src/lib.rs b/compiler/rustc_error_messages/src/lib.rs
index ad82c2d96e7..2a8f4222064 100644
--- a/compiler/rustc_error_messages/src/lib.rs
+++ b/compiler/rustc_error_messages/src/lib.rs
@@ -5,9 +5,6 @@
 #![feature(type_alias_impl_trait)]
 #![allow(internal_features)]
 
-#[macro_use]
-extern crate tracing;
-
 use fluent_bundle::FluentResource;
 use fluent_syntax::parser::ParserError;
 use icu_provider_adapters::fallback::{LocaleFallbackProvider, LocaleFallbacker};
@@ -20,6 +17,7 @@ use std::fmt;
 use std::fs;
 use std::io;
 use std::path::{Path, PathBuf};
+use tracing::{instrument, trace};
 
 #[cfg(not(parallel_compiler))]
 use std::cell::LazyCell as Lazy;
diff --git a/compiler/rustc_expand/src/mbe.rs b/compiler/rustc_expand/src/mbe.rs
index a805c4fcf7b..08d4a039454 100644
--- a/compiler/rustc_expand/src/mbe.rs
+++ b/compiler/rustc_expand/src/mbe.rs
@@ -68,12 +68,15 @@ pub(crate) enum KleeneOp {
 /// `MetaVarExpr` are "first-class" token trees. Useful for parsing macros.
 #[derive(Debug, PartialEq, Encodable, Decodable)]
 enum TokenTree {
+    /// A token. Unlike `tokenstream::TokenTree::Token` this lacks a `Spacing`.
+    /// See the comments about `Spacing` in the `transcribe` function.
     Token(Token),
     /// A delimited sequence, e.g. `($e:expr)` (RHS) or `{ $e }` (LHS).
     Delimited(DelimSpan, DelimSpacing, Delimited),
     /// A kleene-style repetition sequence, e.g. `$($e:expr)*` (RHS) or `$($e),*` (LHS).
     Sequence(DelimSpan, SequenceRepetition),
-    /// e.g., `$var`.
+    /// e.g., `$var`. The span covers the leading dollar and the ident. (The span within the ident
+    /// only covers the ident, e.g. `var`.)
     MetaVar(Span, Ident),
     /// e.g., `$var:expr`. Only appears on the LHS.
     MetaVarDecl(Span, Ident /* name to bind */, Option<NonterminalKind>),
diff --git a/compiler/rustc_expand/src/mbe/quoted.rs b/compiler/rustc_expand/src/mbe/quoted.rs
index d3ea48e2e2a..8ad7cb15c92 100644
--- a/compiler/rustc_expand/src/mbe/quoted.rs
+++ b/compiler/rustc_expand/src/mbe/quoted.rs
@@ -62,7 +62,10 @@ pub(super) fn parse(
         match tree {
             TokenTree::MetaVar(start_sp, ident) if parsing_patterns => {
                 let span = match trees.next() {
-                    Some(&tokenstream::TokenTree::Token(Token { kind: token::Colon, span }, _)) => {
+                    Some(&tokenstream::TokenTree::Token(
+                        Token { kind: token::Colon, span: colon_span },
+                        _,
+                    )) => {
                         match trees.next() {
                             Some(tokenstream::TokenTree::Token(token, _)) => match token.ident() {
                                 Some((fragment, _)) => {
@@ -126,10 +129,12 @@ pub(super) fn parse(
                                 }
                                 _ => token.span,
                             },
-                            tree => tree.map_or(span, tokenstream::TokenTree::span),
+                            Some(tree) => tree.span(),
+                            None => colon_span,
                         }
                     }
-                    tree => tree.map_or(start_sp, tokenstream::TokenTree::span),
+                    Some(tree) => tree.span(),
+                    None => start_sp,
                 };
 
                 result.push(TokenTree::MetaVarDecl(span, ident, None));
@@ -176,7 +181,7 @@ fn parse_tree<'a>(
     // Depending on what `tree` is, we could be parsing different parts of a macro
     match tree {
         // `tree` is a `$` token. Look at the next token in `trees`
-        &tokenstream::TokenTree::Token(Token { kind: token::Dollar, span }, _) => {
+        &tokenstream::TokenTree::Token(Token { kind: token::Dollar, span: dollar_span }, _) => {
             // FIXME: Handle `Invisible`-delimited groups in a more systematic way
             // during parsing.
             let mut next = outer_trees.next();
@@ -209,7 +214,7 @@ fn parse_tree<'a>(
                                         err.emit();
                                         // Returns early the same read `$` to avoid spanning
                                         // unrelated diagnostics that could be performed afterwards
-                                        return TokenTree::token(token::Dollar, span);
+                                        return TokenTree::token(token::Dollar, dollar_span);
                                     }
                                     Ok(elem) => {
                                         maybe_emit_macro_metavar_expr_feature(
@@ -251,7 +256,7 @@ fn parse_tree<'a>(
                 // special metavariable that names the crate of the invocation.
                 Some(tokenstream::TokenTree::Token(token, _)) if token.is_ident() => {
                     let (ident, is_raw) = token.ident().unwrap();
-                    let span = ident.span.with_lo(span.lo());
+                    let span = ident.span.with_lo(dollar_span.lo());
                     if ident.name == kw::Crate && matches!(is_raw, IdentIsRaw::No) {
                         TokenTree::token(token::Ident(kw::DollarCrate, is_raw), span)
                     } else {
@@ -260,16 +265,19 @@ fn parse_tree<'a>(
                 }
 
                 // `tree` is followed by another `$`. This is an escaped `$`.
-                Some(&tokenstream::TokenTree::Token(Token { kind: token::Dollar, span }, _)) => {
+                Some(&tokenstream::TokenTree::Token(
+                    Token { kind: token::Dollar, span: dollar_span2 },
+                    _,
+                )) => {
                     if parsing_patterns {
                         span_dollar_dollar_or_metavar_in_the_lhs_err(
                             sess,
-                            &Token { kind: token::Dollar, span },
+                            &Token { kind: token::Dollar, span: dollar_span2 },
                         );
                     } else {
-                        maybe_emit_macro_metavar_expr_feature(features, sess, span);
+                        maybe_emit_macro_metavar_expr_feature(features, sess, dollar_span2);
                     }
-                    TokenTree::token(token::Dollar, span)
+                    TokenTree::token(token::Dollar, dollar_span2)
                 }
 
                 // `tree` is followed by some other token. This is an error.
@@ -281,7 +289,7 @@ fn parse_tree<'a>(
                 }
 
                 // There are no more tokens. Just return the `$` we already have.
-                None => TokenTree::token(token::Dollar, span),
+                None => TokenTree::token(token::Dollar, dollar_span),
             }
         }
 
diff --git a/compiler/rustc_expand/src/mbe/transcribe.rs b/compiler/rustc_expand/src/mbe/transcribe.rs
index 3901b82eb52..8a084dcb4fe 100644
--- a/compiler/rustc_expand/src/mbe/transcribe.rs
+++ b/compiler/rustc_expand/src/mbe/transcribe.rs
@@ -253,8 +253,23 @@ pub(super) fn transcribe<'a>(
             mbe::TokenTree::MetaVar(mut sp, mut original_ident) => {
                 // Find the matched nonterminal from the macro invocation, and use it to replace
                 // the meta-var.
+                //
+                // We use `Spacing::Alone` everywhere here, because that's the conservative choice
+                // and spacing of declarative macros is tricky. E.g. in this macro:
+                // ```
+                // macro_rules! idents {
+                //     ($($a:ident,)*) => { stringify!($($a)*) }
+                // }
+                // ```
+                // `$a` has no whitespace after it and will be marked `JointHidden`. If you then
+                // call `idents!(x,y,z,)`, each of `x`, `y`, and `z` will be marked as `Joint`. So
+                // if you choose to use `$x`'s spacing or the identifier's spacing, you'll end up
+                // producing "xyz", which is bad because it effectively merges tokens.
+                // `Spacing::Alone` is the safer option. Fortunately, `space_between` will avoid
+                // some of the unnecessary whitespace.
                 let ident = MacroRulesNormalizedIdent::new(original_ident);
                 if let Some(cur_matched) = lookup_cur_matched(ident, interp, &repeats) {
+                    // njn: explain the use of alone here
                     let tt = match cur_matched {
                         MatchedSingle(ParseNtResult::Tt(tt)) => {
                             // `tt`s are emitted into the output stream directly as "raw tokens",
diff --git a/compiler/rustc_expand/src/proc_macro_server.rs b/compiler/rustc_expand/src/proc_macro_server.rs
index 1f3547c841a..ec7e4416b91 100644
--- a/compiler/rustc_expand/src/proc_macro_server.rs
+++ b/compiler/rustc_expand/src/proc_macro_server.rs
@@ -309,10 +309,10 @@ impl ToInternal<SmallVec<[tokenstream::TokenTree; 2]>>
         use rustc_ast::token::*;
 
         // The code below is conservative, using `token_alone`/`Spacing::Alone`
-        // in most places. When the resulting code is pretty-printed by
-        // `print_tts` it ends up with spaces between most tokens, which is
-        // safe but ugly. It's hard in general to do better when working at the
-        // token level.
+        // in most places. It's hard in general to do better when working at
+        // the token level. When the resulting code is pretty-printed by
+        // `print_tts` the `space_between` function helps avoid a lot of
+        // unnecessary whitespace, so the results aren't too bad.
         let (tree, rustc) = self;
         match tree {
             TokenTree::Punct(Punct { ch, joint, span }) => {
diff --git a/compiler/rustc_hir_analysis/src/check/region.rs b/compiler/rustc_hir_analysis/src/check/region.rs
index 4540310937d..e51f95eed02 100644
--- a/compiler/rustc_hir_analysis/src/check/region.rs
+++ b/compiler/rustc_hir_analysis/src/check/region.rs
@@ -6,7 +6,7 @@
 //!
 //! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/borrow_check.html
 
-use rustc_ast::visit::walk_list;
+use rustc_ast::visit::visit_opt;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
@@ -168,7 +168,7 @@ fn resolve_block<'tcx>(visitor: &mut RegionResolutionVisitor<'tcx>, blk: &'tcx h
                 hir::StmtKind::Expr(..) | hir::StmtKind::Semi(..) => visitor.visit_stmt(statement),
             }
         }
-        walk_list!(visitor, visit_expr, &blk.expr);
+        visit_opt!(visitor, visit_expr, &blk.expr);
     }
 
     visitor.cx = prev_cx;
diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs
index 33c24433ca3..11a1c65b749 100644
--- a/compiler/rustc_hir_typeck/src/coercion.rs
+++ b/compiler/rustc_hir_typeck/src/coercion.rs
@@ -1159,7 +1159,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             let sig = self
                 .at(cause, self.param_env)
                 .trace(prev_ty, new_ty)
-                .lub(DefineOpaqueTypes::No, a_sig, b_sig)
+                .lub(DefineOpaqueTypes::Yes, a_sig, b_sig)
                 .map(|ok| self.register_infer_ok_obligations(ok))?;
 
             // Reify both sides and return the reified fn pointer type.
diff --git a/compiler/rustc_incremental/src/assert_dep_graph.rs b/compiler/rustc_incremental/src/assert_dep_graph.rs
index 8c66f239f8e..41caa5d4765 100644
--- a/compiler/rustc_incremental/src/assert_dep_graph.rs
+++ b/compiler/rustc_incremental/src/assert_dep_graph.rs
@@ -49,10 +49,10 @@ use rustc_middle::ty::TyCtxt;
 use rustc_middle::{bug, span_bug};
 use rustc_span::symbol::{sym, Symbol};
 use rustc_span::Span;
-
 use std::env;
 use std::fs::{self, File};
 use std::io::{BufWriter, Write};
+use tracing::debug;
 
 #[allow(missing_docs)]
 pub fn assert_dep_graph(tcx: TyCtxt<'_>) {
diff --git a/compiler/rustc_incremental/src/lib.rs b/compiler/rustc_incremental/src/lib.rs
index 79402c88de4..960a2d012e0 100644
--- a/compiler/rustc_incremental/src/lib.rs
+++ b/compiler/rustc_incremental/src/lib.rs
@@ -6,9 +6,6 @@
 #![feature(rustdoc_internals)]
 #![allow(internal_features)]
 
-#[macro_use]
-extern crate tracing;
-
 mod assert_dep_graph;
 mod errors;
 mod persist;
diff --git a/compiler/rustc_incremental/src/persist/dirty_clean.rs b/compiler/rustc_incremental/src/persist/dirty_clean.rs
index e901ca36dad..2a0d681fa37 100644
--- a/compiler/rustc_incremental/src/persist/dirty_clean.rs
+++ b/compiler/rustc_incremental/src/persist/dirty_clean.rs
@@ -33,6 +33,7 @@ use rustc_middle::ty::TyCtxt;
 use rustc_span::symbol::{sym, Symbol};
 use rustc_span::Span;
 use thin_vec::ThinVec;
+use tracing::debug;
 
 const LOADED_FROM_DISK: Symbol = sym::loaded_from_disk;
 const EXCEPT: Symbol = sym::except;
diff --git a/compiler/rustc_incremental/src/persist/file_format.rs b/compiler/rustc_incremental/src/persist/file_format.rs
index b459f82f23e..303785bdb22 100644
--- a/compiler/rustc_incremental/src/persist/file_format.rs
+++ b/compiler/rustc_incremental/src/persist/file_format.rs
@@ -19,6 +19,7 @@ use std::env;
 use std::fs;
 use std::io::{self, Read};
 use std::path::{Path, PathBuf};
+use tracing::debug;
 
 /// The first few bytes of files generated by incremental compilation.
 const FILE_MAGIC: &[u8] = b"RSIC";
diff --git a/compiler/rustc_incremental/src/persist/fs.rs b/compiler/rustc_incremental/src/persist/fs.rs
index 193042b8cdf..9afea3d66b0 100644
--- a/compiler/rustc_incremental/src/persist/fs.rs
+++ b/compiler/rustc_incremental/src/persist/fs.rs
@@ -125,6 +125,7 @@ use std::path::{Path, PathBuf};
 use std::time::{Duration, SystemTime, UNIX_EPOCH};
 
 use rand::{thread_rng, RngCore};
+use tracing::debug;
 
 #[cfg(test)]
 mod tests;
diff --git a/compiler/rustc_incremental/src/persist/load.rs b/compiler/rustc_incremental/src/persist/load.rs
index 9e6ce066785..6c3f73cf465 100644
--- a/compiler/rustc_incremental/src/persist/load.rs
+++ b/compiler/rustc_incremental/src/persist/load.rs
@@ -12,6 +12,7 @@ use rustc_session::Session;
 use rustc_span::ErrorGuaranteed;
 use std::path::{Path, PathBuf};
 use std::sync::Arc;
+use tracing::{debug, warn};
 
 use super::data::*;
 use super::file_format;
diff --git a/compiler/rustc_incremental/src/persist/save.rs b/compiler/rustc_incremental/src/persist/save.rs
index 9777f769280..3bf582bd26c 100644
--- a/compiler/rustc_incremental/src/persist/save.rs
+++ b/compiler/rustc_incremental/src/persist/save.rs
@@ -11,6 +11,7 @@ use rustc_serialize::Encodable as RustcEncodable;
 use rustc_session::Session;
 use std::fs;
 use std::sync::Arc;
+use tracing::debug;
 
 use super::data::*;
 use super::dirty_clean;
diff --git a/compiler/rustc_incremental/src/persist/work_product.rs b/compiler/rustc_incremental/src/persist/work_product.rs
index 906233ef53e..e230da9dfb1 100644
--- a/compiler/rustc_incremental/src/persist/work_product.rs
+++ b/compiler/rustc_incremental/src/persist/work_product.rs
@@ -10,6 +10,7 @@ use rustc_middle::dep_graph::{WorkProduct, WorkProductId};
 use rustc_session::Session;
 use std::fs as std_fs;
 use std::path::Path;
+use tracing::debug;
 
 /// Copies a CGU work product to the incremental compilation directory, so next compilation can
 /// find and reuse it.
diff --git a/compiler/rustc_infer/messages.ftl b/compiler/rustc_infer/messages.ftl
index 8f1c4ad462a..fbe8d31370c 100644
--- a/compiler/rustc_infer/messages.ftl
+++ b/compiler/rustc_infer/messages.ftl
@@ -104,10 +104,10 @@ infer_compare_impl_item_obligation = ...so that the definition in impl matches t
 infer_consider_specifying_length = consider specifying the actual array length
 infer_data_flows = ...but data{$label_var1_exists ->
     [true] {" "}from `{$label_var1}`
-    *[false] -> {""}
+    *[false] {""}
 } flows{$label_var2_exists ->
     [true] {" "}into `{$label_var2}`
-    *[false] -> {""}
+    *[false] {""}
 } here
 
 infer_data_lifetime_flow = ...but data with one lifetime flows into the other here
diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
index 46a7e7b2399..e0894ed31bf 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
@@ -173,7 +173,10 @@ pub(super) fn note_and_explain_region<'tcx>(
 
         ty::ReError(_) => return,
 
-        ty::ReVar(_) | ty::ReBound(..) | ty::ReErased => {
+        // FIXME(#125431): `ReVar` shouldn't reach here.
+        ty::ReVar(_) => (format!("lifetime `{region}`"), alt_span),
+
+        ty::ReBound(..) | ty::ReErased => {
             bug!("unexpected region for note_and_explain_region: {:?}", region);
         }
     };
diff --git a/compiler/rustc_interface/src/interface.rs b/compiler/rustc_interface/src/interface.rs
index d43be6cebcb..5254a6576f9 100644
--- a/compiler/rustc_interface/src/interface.rs
+++ b/compiler/rustc_interface/src/interface.rs
@@ -11,7 +11,6 @@ use rustc_data_structures::sync::Lrc;
 use rustc_errors::registry::Registry;
 use rustc_errors::{DiagCtxt, ErrorGuaranteed};
 use rustc_lint::LintStore;
-
 use rustc_middle::ty;
 use rustc_middle::ty::CurrentGcx;
 use rustc_middle::util::Providers;
@@ -28,6 +27,7 @@ use rustc_span::FileName;
 use std::path::PathBuf;
 use std::result;
 use std::sync::Arc;
+use tracing::trace;
 
 pub type Result<T> = result::Result<T, ErrorGuaranteed>;
 
diff --git a/compiler/rustc_interface/src/lib.rs b/compiler/rustc_interface/src/lib.rs
index 75df006a56f..c1d460ddd08 100644
--- a/compiler/rustc_interface/src/lib.rs
+++ b/compiler/rustc_interface/src/lib.rs
@@ -4,9 +4,6 @@
 #![feature(thread_spawn_unchecked)]
 #![feature(try_blocks)]
 
-#[macro_use]
-extern crate tracing;
-
 mod callbacks;
 mod errors;
 pub mod interface;
diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs
index 76d5d7a3ac2..33995f80162 100644
--- a/compiler/rustc_interface/src/passes.rs
+++ b/compiler/rustc_interface/src/passes.rs
@@ -39,6 +39,7 @@ use std::io::{self, BufWriter, Write};
 use std::path::{Path, PathBuf};
 use std::sync::LazyLock;
 use std::{env, fs, iter};
+use tracing::{info, instrument};
 
 pub fn parse<'a>(sess: &'a Session) -> PResult<'a, ast::Crate> {
     let krate = sess.time("parse_crate", || match &sess.io.input {
@@ -458,7 +459,7 @@ fn write_out_deps(tcx: TyCtxt<'_>, outputs: &OutputFilenames, out_filenames: &[P
                 }
             }
 
-            for &cnum in tcx.crates(()) {
+            for &cnum in tcx.crates_including_speculative(()) {
                 let source = tcx.used_crate_source(cnum);
                 if let Some((path, _)) = &source.dylib {
                     files.push(escape_dep_filename(&path.display().to_string()));
diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs
index 987e48a1a76..8dac524bb5b 100644
--- a/compiler/rustc_interface/src/util.rs
+++ b/compiler/rustc_interface/src/util.rs
@@ -1,5 +1,4 @@
 use crate::errors;
-use info;
 use rustc_ast as ast;
 use rustc_codegen_ssa::traits::CodegenBackend;
 #[cfg(parallel_compiler)]
@@ -23,6 +22,7 @@ use std::sync::atomic::{AtomicBool, Ordering};
 use std::sync::OnceLock;
 use std::thread;
 use std::{env, iter};
+use tracing::info;
 
 /// Function pointer type that constructs a new CodegenBackend.
 pub type MakeBackendFn = fn() -> Box<dyn CodegenBackend>;
diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl
index 6f6480a4964..a9304f27fe5 100644
--- a/compiler/rustc_lint/messages.ftl
+++ b/compiler/rustc_lint/messages.ftl
@@ -263,7 +263,7 @@ lint_extern_without_abi = extern declarations without an explicit ABI are deprec
     .help = the default ABI is {$default_abi}
 
 lint_for_loops_over_fallibles =
-    for loop over {$article} `{$ty}`. This is more readably written as an `if let` statement
+    for loop over {$article} `{$ref_prefix}{$ty}`. This is more readably written as an `if let` statement
     .suggestion = consider using `if let` to clear intent
     .remove_next = to iterate over `{$recv_snip}` remove the call to `next`
     .use_while_let = to check pattern in a loop use `while let`
@@ -627,7 +627,7 @@ lint_pattern_in_foreign = patterns aren't allowed in foreign function declaratio
     .label = pattern not allowed in foreign function
 
 lint_private_extern_crate_reexport =
-    extern crate `{$ident}` is private, and cannot be re-exported (error E0365), consider declaring with `pub`
+    extern crate `{$ident}` is private, and cannot be re-exported, consider declaring with `pub`
 
 lint_proc_macro_back_compat = using an old version of `{$crate_name}`
     .note = older versions of the `{$crate_name}` crate will stop compiling in future versions of Rust; please update to `{$crate_name}` v{$fixed_version}, or switch to one of the `{$crate_name}` alternatives
diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs
index 0f059bceae7..85d54ce563d 100644
--- a/compiler/rustc_lint/src/builtin.rs
+++ b/compiler/rustc_lint/src/builtin.rs
@@ -70,6 +70,7 @@ use rustc_target::abi::Abi;
 use rustc_trait_selection::infer::{InferCtxtExt, TyCtxtInferExt};
 use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _;
 use rustc_trait_selection::traits::{self, misc::type_allowed_to_implement_copy};
+use tracing::debug;
 
 use crate::nonstandard_style::{method_context, MethodLateContext};
 
@@ -674,11 +675,10 @@ impl<'tcx> LateLintPass<'tcx> for MissingCopyImplementations {
                 return;
             }
         }
-        let param_env = ty::ParamEnv::empty();
-        if ty.is_copy_modulo_regions(cx.tcx, param_env) {
+        if ty.is_copy_modulo_regions(cx.tcx, cx.param_env) {
             return;
         }
-        if type_implements_negative_copy_modulo_regions(cx.tcx, ty, param_env) {
+        if type_implements_negative_copy_modulo_regions(cx.tcx, ty, cx.param_env) {
             return;
         }
         if def.is_variant_list_non_exhaustive()
@@ -694,7 +694,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingCopyImplementations {
                 .tcx
                 .infer_ctxt()
                 .build()
-                .type_implements_trait(iter_trait, [ty], param_env)
+                .type_implements_trait(iter_trait, [ty], cx.param_env)
                 .must_apply_modulo_regions()
         {
             return;
@@ -711,7 +711,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingCopyImplementations {
 
         if type_allowed_to_implement_copy(
             cx.tcx,
-            param_env,
+            cx.param_env,
             ty,
             traits::ObligationCause::misc(item.span, item.owner_id.def_id),
         )
diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs
index deeb3ae090c..c23a67f6131 100644
--- a/compiler/rustc_lint/src/context.rs
+++ b/compiler/rustc_lint/src/context.rs
@@ -39,10 +39,10 @@ use rustc_span::edit_distance::find_best_match_for_names;
 use rustc_span::symbol::{sym, Ident, Symbol};
 use rustc_span::Span;
 use rustc_target::abi;
-
 use std::cell::Cell;
 use std::iter;
 use std::slice;
+use tracing::debug;
 
 mod diagnostics;
 
diff --git a/compiler/rustc_lint/src/context/diagnostics.rs b/compiler/rustc_lint/src/context/diagnostics.rs
index 236eeee6152..23c5e0a9f5f 100644
--- a/compiler/rustc_lint/src/context/diagnostics.rs
+++ b/compiler/rustc_lint/src/context/diagnostics.rs
@@ -9,6 +9,7 @@ use rustc_errors::{elided_lifetime_in_path_suggestion, DiagArgValue, MultiSpan};
 use rustc_middle::middle::stability;
 use rustc_session::lint::{BuiltinLintDiag, Lint};
 use rustc_span::BytePos;
+use tracing::debug;
 
 use crate::{lints, EarlyContext, LintContext as _};
 
diff --git a/compiler/rustc_lint/src/context/diagnostics/check_cfg.rs b/compiler/rustc_lint/src/context/diagnostics/check_cfg.rs
index 020ca1753cf..c69e680cb64 100644
--- a/compiler/rustc_lint/src/context/diagnostics/check_cfg.rs
+++ b/compiler/rustc_lint/src/context/diagnostics/check_cfg.rs
@@ -42,6 +42,22 @@ fn to_check_cfg_arg(name: Symbol, value: Option<Symbol>, quotes: EscapeQuotes) -
     }
 }
 
+fn cargo_help_sub(
+    sess: &Session,
+    inst: &impl Fn(EscapeQuotes) -> String,
+) -> lints::UnexpectedCfgCargoHelp {
+    // We don't want to suggest the `build.rs` way to expected cfgs if we are already in a
+    // `build.rs`. We therefor do a best effort check (looking if the `--crate-name` is
+    // `build_script_build`) to try to figure out if we are building a Cargo build script
+
+    let unescaped = &inst(EscapeQuotes::No);
+    if matches!(&sess.opts.crate_name, Some(crate_name) if crate_name == "build_script_build") {
+        lints::UnexpectedCfgCargoHelp::lint_cfg(unescaped)
+    } else {
+        lints::UnexpectedCfgCargoHelp::lint_cfg_and_build_rs(unescaped, &inst(EscapeQuotes::Yes))
+    }
+}
+
 pub(super) fn unexpected_cfg_name(
     sess: &Session,
     (name, name_span): (Symbol, Span),
@@ -162,14 +178,7 @@ pub(super) fn unexpected_cfg_name(
     let inst = |escape_quotes| to_check_cfg_arg(name, value.map(|(v, _s)| v), escape_quotes);
 
     let invocation_help = if is_from_cargo {
-        let sub = if !is_feature_cfg {
-            Some(lints::UnexpectedCfgCargoHelp::new(
-                &inst(EscapeQuotes::No),
-                &inst(EscapeQuotes::Yes),
-            ))
-        } else {
-            None
-        };
+        let sub = if !is_feature_cfg { Some(cargo_help_sub(sess, &inst)) } else { None };
         lints::unexpected_cfg_name::InvocationHelp::Cargo { sub }
     } else {
         lints::unexpected_cfg_name::InvocationHelp::Rustc(lints::UnexpectedCfgRustcHelp::new(
@@ -267,10 +276,7 @@ pub(super) fn unexpected_cfg_value(
                 Some(lints::unexpected_cfg_value::CargoHelp::DefineFeatures)
             }
         } else if !is_cfg_a_well_know_name {
-            Some(lints::unexpected_cfg_value::CargoHelp::Other(lints::UnexpectedCfgCargoHelp::new(
-                &inst(EscapeQuotes::No),
-                &inst(EscapeQuotes::Yes),
-            )))
+            Some(lints::unexpected_cfg_value::CargoHelp::Other(cargo_help_sub(sess, &inst)))
         } else {
             None
         };
diff --git a/compiler/rustc_lint/src/early.rs b/compiler/rustc_lint/src/early.rs
index 736c7a11069..329221612b5 100644
--- a/compiler/rustc_lint/src/early.rs
+++ b/compiler/rustc_lint/src/early.rs
@@ -26,6 +26,7 @@ use rustc_session::lint::{BufferedEarlyLint, LintBuffer, LintPass};
 use rustc_session::Session;
 use rustc_span::symbol::Ident;
 use rustc_span::Span;
+use tracing::debug;
 
 macro_rules! lint_callback { ($cx:expr, $f:ident, $($args:expr),*) => ({
     $cx.pass.$f(&$cx.context, $($args),*);
diff --git a/compiler/rustc_lint/src/for_loops_over_fallibles.rs b/compiler/rustc_lint/src/for_loops_over_fallibles.rs
index a6876d8aae7..b05f5e7638b 100644
--- a/compiler/rustc_lint/src/for_loops_over_fallibles.rs
+++ b/compiler/rustc_lint/src/for_loops_over_fallibles.rs
@@ -52,14 +52,27 @@ impl<'tcx> LateLintPass<'tcx> for ForLoopsOverFallibles {
 
         let ty = cx.typeck_results().expr_ty(arg);
 
-        let &ty::Adt(adt, args) = ty.kind() else { return };
+        let (adt, args, ref_mutability) = match ty.kind() {
+            &ty::Adt(adt, args) => (adt, args, None),
+            &ty::Ref(_, ty, mutability) => match ty.kind() {
+                &ty::Adt(adt, args) => (adt, args, Some(mutability)),
+                _ => return,
+            },
+            _ => return,
+        };
 
         let (article, ty, var) = match adt.did() {
+            did if cx.tcx.is_diagnostic_item(sym::Option, did) && ref_mutability.is_some() => ("a", "Option", "Some"),
             did if cx.tcx.is_diagnostic_item(sym::Option, did) => ("an", "Option", "Some"),
             did if cx.tcx.is_diagnostic_item(sym::Result, did) => ("a", "Result", "Ok"),
             _ => return,
         };
 
+        let ref_prefix = match ref_mutability {
+            None => "",
+            Some(ref_mutability) => ref_mutability.ref_prefix_str(),
+        };
+
         let sub = if let Some(recv) = extract_iterator_next_call(cx, arg)
             && let Ok(recv_snip) = cx.sess().source_map().span_to_snippet(recv.span)
         {
@@ -85,7 +98,7 @@ impl<'tcx> LateLintPass<'tcx> for ForLoopsOverFallibles {
         cx.emit_span_lint(
             FOR_LOOPS_OVER_FALLIBLES,
             arg.span,
-            ForLoopsOverFalliblesDiag { article, ty, sub, question_mark, suggestion },
+            ForLoopsOverFalliblesDiag { article, ref_prefix, ty, sub, question_mark, suggestion },
         );
     }
 }
diff --git a/compiler/rustc_lint/src/foreign_modules.rs b/compiler/rustc_lint/src/foreign_modules.rs
index 2c86964feef..5da1cbc2283 100644
--- a/compiler/rustc_lint/src/foreign_modules.rs
+++ b/compiler/rustc_lint/src/foreign_modules.rs
@@ -8,6 +8,7 @@ use rustc_middle::ty::{self, Instance, Ty, TyCtxt};
 use rustc_session::declare_lint;
 use rustc_span::{sym, Span, Symbol};
 use rustc_target::abi::FIRST_VARIANT;
+use tracing::{debug, instrument};
 
 use crate::lints::{BuiltinClashingExtern, BuiltinClashingExternSub};
 use crate::{types, LintVec};
diff --git a/compiler/rustc_lint/src/internal.rs b/compiler/rustc_lint/src/internal.rs
index 153d91ce28c..6e291a327fa 100644
--- a/compiler/rustc_lint/src/internal.rs
+++ b/compiler/rustc_lint/src/internal.rs
@@ -15,6 +15,7 @@ use rustc_session::{declare_lint_pass, declare_tool_lint};
 use rustc_span::hygiene::{ExpnKind, MacroKind};
 use rustc_span::symbol::{kw, sym, Symbol};
 use rustc_span::Span;
+use tracing::debug;
 
 declare_tool_lint! {
     /// The `default_hash_type` lint detects use of [`std::collections::HashMap`]/[`std::collections::HashSet`],
diff --git a/compiler/rustc_lint/src/late.rs b/compiler/rustc_lint/src/late.rs
index ca188277b9d..b638ab10e11 100644
--- a/compiler/rustc_lint/src/late.rs
+++ b/compiler/rustc_lint/src/late.rs
@@ -26,9 +26,9 @@ use rustc_middle::ty::{self, TyCtxt};
 use rustc_session::lint::LintPass;
 use rustc_session::Session;
 use rustc_span::Span;
-
 use std::any::Any;
 use std::cell::Cell;
+use tracing::debug;
 
 /// Extract the [`LintStore`] from [`Session`].
 ///
diff --git a/compiler/rustc_lint/src/levels.rs b/compiler/rustc_lint/src/levels.rs
index 12b3d1d2f9e..98e321076c5 100644
--- a/compiler/rustc_lint/src/levels.rs
+++ b/compiler/rustc_lint/src/levels.rs
@@ -41,6 +41,7 @@ use rustc_session::parse::feature_err;
 use rustc_session::Session;
 use rustc_span::symbol::{sym, Symbol};
 use rustc_span::{Span, DUMMY_SP};
+use tracing::{debug, instrument};
 
 use crate::errors::{
     MalformedAttribute, MalformedAttributeSub, OverruledAttribute, OverruledAttributeSub,
diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs
index 64fcc7e46e0..0ccfe23ae37 100644
--- a/compiler/rustc_lint/src/lib.rs
+++ b/compiler/rustc_lint/src/lib.rs
@@ -39,9 +39,6 @@
 #![feature(rustc_attrs)]
 #![allow(internal_features)]
 
-#[macro_use]
-extern crate tracing;
-
 mod async_fn_in_trait;
 pub mod builtin;
 mod context;
diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs
index 3bd6faca379..2f44bc4764e 100644
--- a/compiler/rustc_lint/src/lints.rs
+++ b/compiler/rustc_lint/src/lints.rs
@@ -620,6 +620,7 @@ pub enum PtrNullChecksDiag<'a> {
 #[diag(lint_for_loops_over_fallibles)]
 pub struct ForLoopsOverFalliblesDiag<'a> {
     pub article: &'static str,
+    pub ref_prefix: &'static str,
     pub ty: &'static str,
     #[subdiagnostic]
     pub sub: ForLoopsOverFalliblesLoopSub<'a>,
@@ -1961,21 +1962,33 @@ pub struct UnitBindingsDiag {
 pub struct BuiltinNamedAsmLabel;
 
 #[derive(Subdiagnostic)]
-#[help(lint_unexpected_cfg_add_cargo_feature)]
-#[help(lint_unexpected_cfg_add_cargo_toml_lint_cfg)]
-#[help(lint_unexpected_cfg_add_build_rs_println)]
-pub struct UnexpectedCfgCargoHelp {
-    pub build_rs_println: String,
-    pub cargo_toml_lint_cfg: String,
+pub enum UnexpectedCfgCargoHelp {
+    #[help(lint_unexpected_cfg_add_cargo_feature)]
+    #[help(lint_unexpected_cfg_add_cargo_toml_lint_cfg)]
+    LintCfg { cargo_toml_lint_cfg: String },
+    #[help(lint_unexpected_cfg_add_cargo_feature)]
+    #[help(lint_unexpected_cfg_add_cargo_toml_lint_cfg)]
+    #[help(lint_unexpected_cfg_add_build_rs_println)]
+    LintCfgAndBuildRs { cargo_toml_lint_cfg: String, build_rs_println: String },
 }
 
 impl UnexpectedCfgCargoHelp {
-    pub fn new(unescaped: &str, escaped: &str) -> Self {
-        Self {
-            cargo_toml_lint_cfg: format!(
-                "\n [lints.rust]\n unexpected_cfgs = {{ level = \"warn\", check-cfg = ['{unescaped}'] }}",
-            ),
-            build_rs_println: format!("println!(\"cargo::rustc-check-cfg={escaped}\");",),
+    fn cargo_toml_lint_cfg(unescaped: &str) -> String {
+        format!(
+            "\n [lints.rust]\n unexpected_cfgs = {{ level = \"warn\", check-cfg = ['{unescaped}'] }}"
+        )
+    }
+
+    pub fn lint_cfg(unescaped: &str) -> Self {
+        UnexpectedCfgCargoHelp::LintCfg {
+            cargo_toml_lint_cfg: Self::cargo_toml_lint_cfg(unescaped),
+        }
+    }
+
+    pub fn lint_cfg_and_build_rs(unescaped: &str, escaped: &str) -> Self {
+        UnexpectedCfgCargoHelp::LintCfgAndBuildRs {
+            cargo_toml_lint_cfg: Self::cargo_toml_lint_cfg(unescaped),
+            build_rs_println: format!("println!(\"cargo::rustc-check-cfg={escaped}\");"),
         }
     }
 }
@@ -2227,7 +2240,7 @@ pub struct MacroUseDeprecated;
 pub struct UnusedMacroUse;
 
 #[derive(LintDiagnostic)]
-#[diag(lint_private_extern_crate_reexport)]
+#[diag(lint_private_extern_crate_reexport, code = E0365)]
 pub struct PrivateExternCrateReexport {
     pub ident: Ident,
 }
diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs
index f9f766f832a..9d3a838666a 100644
--- a/compiler/rustc_lint/src/types.rs
+++ b/compiler/rustc_lint/src/types.rs
@@ -31,9 +31,9 @@ use rustc_span::{Span, Symbol};
 use rustc_target::abi::{Abi, Size, WrappingRange};
 use rustc_target::abi::{Integer, TagEncoding, Variants};
 use rustc_target::spec::abi::Abi as SpecAbi;
-
 use std::iter;
 use std::ops::ControlFlow;
+use tracing::debug;
 
 declare_lint! {
     /// The `unused_comparisons` lint detects comparisons made useless by
diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs
index 8866b2be078..a6993547c8f 100644
--- a/compiler/rustc_lint/src/unused.rs
+++ b/compiler/rustc_lint/src/unused.rs
@@ -22,6 +22,7 @@ use rustc_span::symbol::{kw, sym};
 use rustc_span::{BytePos, Span};
 use std::iter;
 use std::ops::ControlFlow;
+use tracing::instrument;
 
 declare_lint! {
     /// The `unused_must_use` lint detects unused result of a type flagged as
diff --git a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
index 067374c0261..3fcf3aca8af 100644
--- a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
+++ b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
@@ -1488,13 +1488,15 @@ LLVMRustPrepareThinLTOImport(const LLVMRustThinLTOData *Data, LLVMModuleRef M,
 // a ThinLTO summary attached.
 struct LLVMRustThinLTOBuffer {
   std::string data;
+  std::string thin_link_data;
 };
 
 extern "C" LLVMRustThinLTOBuffer*
-LLVMRustThinLTOBufferCreate(LLVMModuleRef M, bool is_thin) {
+LLVMRustThinLTOBufferCreate(LLVMModuleRef M, bool is_thin, bool emit_summary) {
   auto Ret = std::make_unique<LLVMRustThinLTOBuffer>();
   {
     auto OS = raw_string_ostream(Ret->data);
+    auto ThinLinkOS = raw_string_ostream(Ret->thin_link_data);
     {
       if (is_thin) {
         PassBuilder PB;
@@ -1508,7 +1510,10 @@ LLVMRustThinLTOBufferCreate(LLVMModuleRef M, bool is_thin) {
         PB.registerLoopAnalyses(LAM);
         PB.crossRegisterProxies(LAM, FAM, CGAM, MAM);
         ModulePassManager MPM;
-        MPM.addPass(ThinLTOBitcodeWriterPass(OS, nullptr));
+        // We only pass ThinLinkOS to be filled in if we want the summary,
+        // because otherwise LLVM does extra work and may double-emit some
+        // errors or warnings.
+        MPM.addPass(ThinLTOBitcodeWriterPass(OS, emit_summary ? &ThinLinkOS : nullptr));
         MPM.run(*unwrap(M), MAM);
       } else {
         WriteBitcodeToFile(*unwrap(M), OS);
@@ -1533,6 +1538,16 @@ LLVMRustThinLTOBufferLen(const LLVMRustThinLTOBuffer *Buffer) {
   return Buffer->data.length();
 }
 
+extern "C" const void*
+LLVMRustThinLTOBufferThinLinkDataPtr(const LLVMRustThinLTOBuffer *Buffer) {
+  return Buffer->thin_link_data.data();
+}
+
+extern "C" size_t
+LLVMRustThinLTOBufferThinLinkDataLen(const LLVMRustThinLTOBuffer *Buffer) {
+  return Buffer->thin_link_data.length();
+}
+
 // This is what we used to parse upstream bitcode for actual ThinLTO
 // processing. We'll call this once per module optimized through ThinLTO, and
 // it'll be called concurrently on many threads.
diff --git a/compiler/rustc_metadata/messages.ftl b/compiler/rustc_metadata/messages.ftl
index 2f5dfad265c..932603cd6b2 100644
--- a/compiler/rustc_metadata/messages.ftl
+++ b/compiler/rustc_metadata/messages.ftl
@@ -91,9 +91,6 @@ metadata_found_staticlib =
     found staticlib `{$crate_name}` instead of rlib or dylib{$add_info}
     .help = please recompile that crate using --crate-type lib
 
-metadata_framework_only_windows =
-    link kind `raw-dylib` is only supported on Windows targets
-
 metadata_global_alloc_required =
     no global memory allocator found but one is required; link to std or add `#[global_allocator]` to a static item that implements the GlobalAlloc trait
 
@@ -233,6 +230,9 @@ metadata_profiler_builtins_needs_core =
 metadata_raw_dylib_no_nul =
     link name must not contain NUL characters if link kind is `raw-dylib`
 
+metadata_raw_dylib_only_windows =
+    link kind `raw-dylib` is only supported on Windows targets
+
 metadata_renaming_no_link =
     renaming of the library `{$lib_name}` was specified, however this crate contains no `#[link(...)]` attributes referencing this library
 
diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs
index be1a73ef0a7..44a3e9760e1 100644
--- a/compiler/rustc_metadata/src/creader.rs
+++ b/compiler/rustc_metadata/src/creader.rs
@@ -27,6 +27,7 @@ use rustc_span::edition::Edition;
 use rustc_span::symbol::{sym, Symbol};
 use rustc_span::{Span, DUMMY_SP};
 use rustc_target::spec::{PanicStrategy, Target, TargetTriple};
+use tracing::{debug, info, trace};
 
 use proc_macro::bridge::client::ProcMacro;
 use std::error::Error;
diff --git a/compiler/rustc_metadata/src/dependency_format.rs b/compiler/rustc_metadata/src/dependency_format.rs
index 99181f9c860..bf9bbfb8cfa 100644
--- a/compiler/rustc_metadata/src/dependency_format.rs
+++ b/compiler/rustc_metadata/src/dependency_format.rs
@@ -65,6 +65,7 @@ use rustc_middle::ty::TyCtxt;
 use rustc_session::config::CrateType;
 use rustc_session::cstore::CrateDepKind;
 use rustc_session::cstore::LinkagePreference::{self, RequireDynamic, RequireStatic};
+use tracing::info;
 
 pub(crate) fn calculate(tcx: TyCtxt<'_>) -> Dependencies {
     tcx.crate_types()
@@ -143,7 +144,7 @@ fn calculate_type(tcx: TyCtxt<'_>, ty: CrateType) -> DependencyList {
                     && sess.crt_static(Some(ty))
                     && !sess.target.crt_static_allows_dylibs)
             {
-                for &cnum in tcx.crates(()).iter() {
+                for &cnum in tcx.used_crates(()).iter() {
                     if tcx.dep_kind(cnum).macros_only() {
                         continue;
                     }
@@ -164,7 +165,7 @@ fn calculate_type(tcx: TyCtxt<'_>, ty: CrateType) -> DependencyList {
     // Sweep all crates for found dylibs. Add all dylibs, as well as their
     // dependencies, ensuring there are no conflicts. The only valid case for a
     // dependency to be relied upon twice is for both cases to rely on a dylib.
-    for &cnum in tcx.crates(()).iter() {
+    for &cnum in tcx.used_crates(()).iter() {
         if tcx.dep_kind(cnum).macros_only() {
             continue;
         }
@@ -182,7 +183,7 @@ fn calculate_type(tcx: TyCtxt<'_>, ty: CrateType) -> DependencyList {
     }
 
     // Collect what we've got so far in the return vector.
-    let last_crate = tcx.crates(()).len();
+    let last_crate = tcx.used_crates(()).len();
     let mut ret = (1..last_crate + 1)
         .map(|cnum| match formats.get(&CrateNum::new(cnum)) {
             Some(&RequireDynamic) => Linkage::Dynamic,
@@ -196,7 +197,7 @@ fn calculate_type(tcx: TyCtxt<'_>, ty: CrateType) -> DependencyList {
     //
     // If the crate hasn't been included yet and it's not actually required
     // (e.g., it's an allocator) then we skip it here as well.
-    for &cnum in tcx.crates(()).iter() {
+    for &cnum in tcx.used_crates(()).iter() {
         let src = tcx.used_crate_source(cnum);
         if src.dylib.is_none()
             && !formats.contains_key(&cnum)
@@ -284,7 +285,7 @@ fn add_library(
 
 fn attempt_static(tcx: TyCtxt<'_>, unavailable: &mut Vec<CrateNum>) -> Option<DependencyList> {
     let all_crates_available_as_rlib = tcx
-        .crates(())
+        .used_crates(())
         .iter()
         .copied()
         .filter_map(|cnum| {
@@ -305,7 +306,7 @@ fn attempt_static(tcx: TyCtxt<'_>, unavailable: &mut Vec<CrateNum>) -> Option<De
     // All crates are available in an rlib format, so we're just going to link
     // everything in explicitly so long as it's actually required.
     let mut ret = tcx
-        .crates(())
+        .used_crates(())
         .iter()
         .map(|&cnum| match tcx.dep_kind(cnum) {
             CrateDepKind::Explicit => Linkage::Static,
diff --git a/compiler/rustc_metadata/src/errors.rs b/compiler/rustc_metadata/src/errors.rs
index fb0010f2c5d..47d183a0440 100644
--- a/compiler/rustc_metadata/src/errors.rs
+++ b/compiler/rustc_metadata/src/errors.rs
@@ -142,8 +142,8 @@ pub struct LinkFrameworkApple {
 }
 
 #[derive(Diagnostic)]
-#[diag(metadata_framework_only_windows, code = E0455)]
-pub struct FrameworkOnlyWindows {
+#[diag(metadata_raw_dylib_only_windows, code = E0455)]
+pub struct RawDylibOnlyWindows {
     #[primary_span]
     pub span: Span,
 }
diff --git a/compiler/rustc_metadata/src/lib.rs b/compiler/rustc_metadata/src/lib.rs
index 00bb4c435c8..acaf9fb0fc3 100644
--- a/compiler/rustc_metadata/src/lib.rs
+++ b/compiler/rustc_metadata/src/lib.rs
@@ -20,9 +20,6 @@
 
 extern crate proc_macro;
 
-#[macro_use]
-extern crate tracing;
-
 pub use rmeta::provide;
 
 mod dependency_format;
diff --git a/compiler/rustc_metadata/src/locator.rs b/compiler/rustc_metadata/src/locator.rs
index 6ff19974c1e..73443de3553 100644
--- a/compiler/rustc_metadata/src/locator.rs
+++ b/compiler/rustc_metadata/src/locator.rs
@@ -231,6 +231,7 @@ use rustc_session::Session;
 use rustc_span::symbol::Symbol;
 use rustc_span::Span;
 use rustc_target::spec::{Target, TargetTriple};
+use tracing::{debug, info};
 
 use snap::read::FrameDecoder;
 use std::borrow::Cow;
diff --git a/compiler/rustc_metadata/src/native_libs.rs b/compiler/rustc_metadata/src/native_libs.rs
index 58760be921a..1254ebead07 100644
--- a/compiler/rustc_metadata/src/native_libs.rs
+++ b/compiler/rustc_metadata/src/native_libs.rs
@@ -151,7 +151,7 @@ impl<'tcx> Collector<'tcx> {
                             }
                             "raw-dylib" => {
                                 if !sess.target.is_like_windows {
-                                    sess.dcx().emit_err(errors::FrameworkOnlyWindows { span });
+                                    sess.dcx().emit_err(errors::RawDylibOnlyWindows { span });
                                 }
                                 NativeLibKind::RawDylib
                             }
diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs
index f91e121a240..695525e755d 100644
--- a/compiler/rustc_metadata/src/rmeta/decoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/decoder.rs
@@ -28,6 +28,7 @@ use rustc_session::cstore::{CrateSource, ExternCrate};
 use rustc_session::Session;
 use rustc_span::symbol::kw;
 use rustc_span::{BytePos, Pos, SpanData, SpanDecoder, SyntaxContext, DUMMY_SP};
+use tracing::debug;
 
 use proc_macro::bridge::client::ProcMacro;
 use std::iter::TrustedLen;
diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
index c783149a695..4cad317ce80 100644
--- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
+++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
@@ -435,7 +435,7 @@ pub(in crate::rmeta) fn provide(providers: &mut Providers) {
             // traversal, but not globally minimal across all crates.
             let bfs_queue = &mut VecDeque::new();
 
-            for &cnum in tcx.crates(()) {
+            for &cnum in tcx.crates_including_speculative(()) {
                 // Ignore crates without a corresponding local `extern crate` item.
                 if tcx.missing_extern_crate_item(cnum) {
                     continue;
@@ -505,7 +505,7 @@ pub(in crate::rmeta) fn provide(providers: &mut Providers) {
             tcx.arena
                 .alloc_slice(&CStore::from_tcx(tcx).crate_dependencies_in_postorder(LOCAL_CRATE))
         },
-        crates: |tcx, ()| {
+        crates_including_speculative: |tcx, ()| {
             // The list of loaded crates is now frozen in query cache,
             // so make sure cstore is not mutably accessed from here on.
             tcx.untracked().cstore.freeze();
diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs
index db0dc6d9064..4587a4315e3 100644
--- a/compiler/rustc_metadata/src/rmeta/encoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/encoder.rs
@@ -33,6 +33,7 @@ use std::collections::hash_map::Entry;
 use std::fs::File;
 use std::io::{Read, Seek, Write};
 use std::path::{Path, PathBuf};
+use tracing::{debug, instrument, trace};
 
 pub(super) struct EncodeContext<'a, 'tcx> {
     opaque: opaque::FileEncoder,
@@ -1898,7 +1899,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
 
         let deps = self
             .tcx
-            .crates(())
+            .crates_including_speculative(())
             .iter()
             .map(|&cnum| {
                 let dep = CrateDep {
diff --git a/compiler/rustc_metadata/src/rmeta/table.rs b/compiler/rustc_metadata/src/rmeta/table.rs
index 019cb91c765..23a6ceb4d3e 100644
--- a/compiler/rustc_metadata/src/rmeta/table.rs
+++ b/compiler/rustc_metadata/src/rmeta/table.rs
@@ -2,6 +2,7 @@ use crate::rmeta::*;
 
 use rustc_hir::def::CtorOf;
 use rustc_index::Idx;
+use tracing::trace;
 
 pub(super) trait IsDefault: Default {
     fn is_default(&self) -> bool;
diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs
index f3f24f77177..b17af47fbcd 100644
--- a/compiler/rustc_middle/src/hir/map/mod.rs
+++ b/compiler/rustc_middle/src/hir/map/mod.rs
@@ -1016,7 +1016,7 @@ pub(super) fn crate_hash(tcx: TyCtxt<'_>, _: LocalCrate) -> Svh {
     let krate = tcx.hir_crate(());
     let hir_body_hash = krate.opt_hir_hash.expect("HIR hash missing while computing crate hash");
 
-    let upstream_crates = upstream_crates(tcx);
+    let upstream_crates = upstream_crates_for_hashing(tcx);
 
     let resolutions = tcx.resolutions(());
 
@@ -1085,9 +1085,9 @@ pub(super) fn crate_hash(tcx: TyCtxt<'_>, _: LocalCrate) -> Svh {
     Svh::new(crate_hash)
 }
 
-fn upstream_crates(tcx: TyCtxt<'_>) -> Vec<(StableCrateId, Svh)> {
+fn upstream_crates_for_hashing(tcx: TyCtxt<'_>) -> Vec<(StableCrateId, Svh)> {
     let mut upstream_crates: Vec<_> = tcx
-        .crates(())
+        .crates_including_speculative(())
         .iter()
         .map(|&cnum| {
             let stable_crate_id = tcx.stable_crate_id(cnum);
diff --git a/compiler/rustc_middle/src/hooks/mod.rs b/compiler/rustc_middle/src/hooks/mod.rs
index d35b9fc46e4..bf10a71dbae 100644
--- a/compiler/rustc_middle/src/hooks/mod.rs
+++ b/compiler/rustc_middle/src/hooks/mod.rs
@@ -10,6 +10,7 @@ use rustc_hir::def_id::{DefId, DefPathHash};
 use rustc_session::StableCrateId;
 use rustc_span::def_id::{CrateNum, LocalDefId};
 use rustc_span::{ExpnHash, ExpnId, DUMMY_SP};
+use tracing::instrument;
 
 macro_rules! declare_hooks {
     ($($(#[$attr:meta])*hook $name:ident($($arg:ident: $K:ty),*) -> $V:ty;)*) => {
diff --git a/compiler/rustc_middle/src/lib.rs b/compiler/rustc_middle/src/lib.rs
index 70437fdcb6f..d47e393c912 100644
--- a/compiler/rustc_middle/src/lib.rs
+++ b/compiler/rustc_middle/src/lib.rs
@@ -63,9 +63,6 @@
 #![feature(yeet_expr)]
 // tidy-alphabetical-end
 
-#[macro_use]
-extern crate tracing;
-
 #[cfg(test)]
 mod tests;
 
diff --git a/compiler/rustc_middle/src/lint.rs b/compiler/rustc_middle/src/lint.rs
index 086582e60a3..d82d23d62af 100644
--- a/compiler/rustc_middle/src/lint.rs
+++ b/compiler/rustc_middle/src/lint.rs
@@ -12,6 +12,7 @@ use rustc_session::lint::{
 use rustc_session::Session;
 use rustc_span::hygiene::{ExpnKind, MacroKind};
 use rustc_span::{symbol, DesugaringKind, Span, Symbol, DUMMY_SP};
+use tracing::instrument;
 
 use crate::ty::TyCtxt;
 
diff --git a/compiler/rustc_middle/src/middle/region.rs b/compiler/rustc_middle/src/middle/region.rs
index de07ba9700a..6e89dc494fa 100644
--- a/compiler/rustc_middle/src/middle/region.rs
+++ b/compiler/rustc_middle/src/middle/region.rs
@@ -13,6 +13,7 @@ use rustc_hir as hir;
 use rustc_hir::{HirId, HirIdMap, Node};
 use rustc_macros::{HashStable, TyDecodable, TyEncodable};
 use rustc_span::{Span, DUMMY_SP};
+use tracing::debug;
 
 use std::fmt;
 use std::ops::Deref;
diff --git a/compiler/rustc_middle/src/middle/stability.rs b/compiler/rustc_middle/src/middle/stability.rs
index e5df05763b0..a377e35b2e9 100644
--- a/compiler/rustc_middle/src/middle/stability.rs
+++ b/compiler/rustc_middle/src/middle/stability.rs
@@ -23,6 +23,7 @@ use rustc_session::Session;
 use rustc_span::symbol::{sym, Symbol};
 use rustc_span::Span;
 use std::num::NonZero;
+use tracing::debug;
 
 #[derive(PartialEq, Clone, Copy, Debug)]
 pub enum StabilityLevel {
diff --git a/compiler/rustc_middle/src/mir/interpret/allocation/provenance_map.rs b/compiler/rustc_middle/src/mir/interpret/allocation/provenance_map.rs
index e974279f191..4e37295a571 100644
--- a/compiler/rustc_middle/src/mir/interpret/allocation/provenance_map.rs
+++ b/compiler/rustc_middle/src/mir/interpret/allocation/provenance_map.rs
@@ -3,12 +3,12 @@
 
 use std::cmp;
 
+use super::{alloc_range, AllocError, AllocRange, AllocResult, CtfeProvenance, Provenance};
 use rustc_data_structures::sorted_map::SortedMap;
 use rustc_macros::HashStable;
-use rustc_target::abi::{HasDataLayout, Size};
-
-use super::{alloc_range, AllocError, AllocRange, AllocResult, CtfeProvenance, Provenance};
 use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
+use rustc_target::abi::{HasDataLayout, Size};
+use tracing::trace;
 
 /// Stores the provenance information of pointers stored in memory.
 #[derive(Clone, PartialEq, Eq, Hash, Debug)]
diff --git a/compiler/rustc_middle/src/mir/interpret/error.rs b/compiler/rustc_middle/src/mir/interpret/error.rs
index 6e152cbcb65..eabbcc2033f 100644
--- a/compiler/rustc_middle/src/mir/interpret/error.rs
+++ b/compiler/rustc_middle/src/mir/interpret/error.rs
@@ -1,19 +1,22 @@
-use super::{AllocId, AllocRange, ConstAllocation, Pointer, Scalar};
+use std::borrow::Cow;
+use std::{any::Any, backtrace::Backtrace, fmt};
 
-use crate::error;
-use crate::mir::{ConstAlloc, ConstValue};
-use crate::ty::{self, layout, tls, Ty, TyCtxt, ValTree};
+use either::Either;
 
 use rustc_ast_ir::Mutability;
 use rustc_data_structures::sync::Lock;
 use rustc_errors::{DiagArgName, DiagArgValue, DiagMessage, ErrorGuaranteed, IntoDiagArg};
 use rustc_macros::{HashStable, TyDecodable, TyEncodable};
 use rustc_session::CtfeBacktrace;
+use rustc_span::Symbol;
 use rustc_span::{def_id::DefId, Span, DUMMY_SP};
 use rustc_target::abi::{call, Align, Size, VariantIdx, WrappingRange};
 
-use std::borrow::Cow;
-use std::{any::Any, backtrace::Backtrace, fmt};
+use super::{AllocId, AllocRange, ConstAllocation, Pointer, Scalar};
+
+use crate::error;
+use crate::mir::{ConstAlloc, ConstValue};
+use crate::ty::{self, layout, tls, Ty, TyCtxt, ValTree};
 
 #[derive(Debug, Copy, Clone, PartialEq, Eq, HashStable, TyEncodable, TyDecodable)]
 pub enum ErrorHandled {
@@ -63,6 +66,9 @@ impl ReportedErrorInfo {
     pub fn tainted_by_errors(error: ErrorGuaranteed) -> ReportedErrorInfo {
         ReportedErrorInfo { is_tainted_by_errors: true, error }
     }
+    pub fn is_tainted_by_errors(&self) -> bool {
+        self.is_tainted_by_errors
+    }
 }
 
 impl From<ErrorGuaranteed> for ReportedErrorInfo {
@@ -310,6 +316,10 @@ pub enum UndefinedBehaviorInfo<'tcx> {
     RemainderOverflow,
     /// Overflowing inbounds pointer arithmetic.
     PointerArithOverflow,
+    /// Overflow in arithmetic that may not overflow.
+    ArithOverflow { intrinsic: Symbol },
+    /// Shift by too much.
+    ShiftOverflow { intrinsic: Symbol, shift_amount: Either<u128, i128> },
     /// Invalid metadata in a wide pointer
     InvalidMeta(InvalidMetaKind),
     /// Reading a C string that does not end within its allocation.
diff --git a/compiler/rustc_middle/src/mir/interpret/mod.rs b/compiler/rustc_middle/src/mir/interpret/mod.rs
index 739b1410e6d..16093cfca6a 100644
--- a/compiler/rustc_middle/src/mir/interpret/mod.rs
+++ b/compiler/rustc_middle/src/mir/interpret/mod.rs
@@ -15,6 +15,7 @@ use std::num::NonZero;
 use std::sync::atomic::{AtomicU32, Ordering};
 
 use smallvec::{smallvec, SmallVec};
+use tracing::{debug, trace};
 
 use rustc_ast::LitKind;
 use rustc_data_structures::fx::FxHashMap;
diff --git a/compiler/rustc_middle/src/mir/interpret/queries.rs b/compiler/rustc_middle/src/mir/interpret/queries.rs
index 04d6301116e..a8518195469 100644
--- a/compiler/rustc_middle/src/mir/interpret/queries.rs
+++ b/compiler/rustc_middle/src/mir/interpret/queries.rs
@@ -9,6 +9,7 @@ use rustc_hir::def::DefKind;
 use rustc_hir::def_id::DefId;
 use rustc_session::lint;
 use rustc_span::{Span, DUMMY_SP};
+use tracing::{debug, instrument};
 
 impl<'tcx> TyCtxt<'tcx> {
     /// Evaluates a constant without providing any generic parameters. This is useful to evaluate consts
diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs
index 25cc9ac47c8..2b2b9392a70 100644
--- a/compiler/rustc_middle/src/mir/mod.rs
+++ b/compiler/rustc_middle/src/mir/mod.rs
@@ -37,6 +37,7 @@ use rustc_span::symbol::Symbol;
 use rustc_span::{Span, DUMMY_SP};
 
 use either::Either;
+use tracing::trace;
 
 use std::borrow::Cow;
 use std::cell::RefCell;
diff --git a/compiler/rustc_middle/src/mir/mono.rs b/compiler/rustc_middle/src/mir/mono.rs
index daab6c85581..a3d2140eb1b 100644
--- a/compiler/rustc_middle/src/mir/mono.rs
+++ b/compiler/rustc_middle/src/mir/mono.rs
@@ -18,6 +18,7 @@ use rustc_span::symbol::Symbol;
 use rustc_span::Span;
 use std::fmt;
 use std::hash::Hash;
+use tracing::debug;
 
 /// Describes how a monomorphization will be instantiated in object files.
 #[derive(PartialEq)]
diff --git a/compiler/rustc_middle/src/mir/patch.rs b/compiler/rustc_middle/src/mir/patch.rs
index 33412297017..18c48d99b81 100644
--- a/compiler/rustc_middle/src/mir/patch.rs
+++ b/compiler/rustc_middle/src/mir/patch.rs
@@ -1,4 +1,5 @@
 use rustc_middle::mir::*;
+use tracing::debug;
 
 /// This struct represents a patch to MIR, which can add
 /// new statements and basic blocks and patch over block
diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs
index 7e8598b49df..7bfb4ac867a 100644
--- a/compiler/rustc_middle/src/mir/pretty.rs
+++ b/compiler/rustc_middle/src/mir/pretty.rs
@@ -15,6 +15,7 @@ use rustc_middle::mir::interpret::{
 use rustc_middle::mir::visit::Visitor;
 use rustc_middle::mir::*;
 use rustc_target::abi::Size;
+use tracing::trace;
 
 const INDENT: &str = "    ";
 /// Alignment for lining up comments following MIR statements
diff --git a/compiler/rustc_middle/src/mir/tcx.rs b/compiler/rustc_middle/src/mir/tcx.rs
index c421c937dc3..a122cffdb87 100644
--- a/compiler/rustc_middle/src/mir/tcx.rs
+++ b/compiler/rustc_middle/src/mir/tcx.rs
@@ -5,6 +5,7 @@
 
 use crate::mir::*;
 use rustc_hir as hir;
+use tracing::{debug, instrument};
 
 #[derive(Copy, Clone, Debug, TypeFoldable, TypeVisitable)]
 pub struct PlaceTy<'tcx> {
@@ -297,9 +298,11 @@ impl BorrowKind {
 impl BinOp {
     pub(crate) fn to_hir_binop(self) -> hir::BinOpKind {
         match self {
-            BinOp::Add => hir::BinOpKind::Add,
-            BinOp::Sub => hir::BinOpKind::Sub,
-            BinOp::Mul => hir::BinOpKind::Mul,
+            // HIR `+`/`-`/`*` can map to either of these MIR BinOp, depending
+            // on whether overflow checks are enabled or not.
+            BinOp::Add | BinOp::AddWithOverflow => hir::BinOpKind::Add,
+            BinOp::Sub | BinOp::SubWithOverflow => hir::BinOpKind::Sub,
+            BinOp::Mul | BinOp::MulWithOverflow => hir::BinOpKind::Mul,
             BinOp::Div => hir::BinOpKind::Div,
             BinOp::Rem => hir::BinOpKind::Rem,
             BinOp::BitXor => hir::BinOpKind::BitXor,
@@ -313,10 +316,8 @@ impl BinOp {
             BinOp::Gt => hir::BinOpKind::Gt,
             BinOp::Le => hir::BinOpKind::Le,
             BinOp::Ge => hir::BinOpKind::Ge,
+            // We don't have HIR syntax for these.
             BinOp::Cmp
-            | BinOp::AddWithOverflow
-            | BinOp::SubWithOverflow
-            | BinOp::MulWithOverflow
             | BinOp::AddUnchecked
             | BinOp::SubUnchecked
             | BinOp::MulUnchecked
@@ -338,6 +339,11 @@ impl BinOp {
         })
     }
 
+    /// Returns whether this is a `FooWithOverflow`
+    pub fn is_overflowing(self) -> bool {
+        self.overflowing_to_wrapping().is_some()
+    }
+
     /// If this is a `Foo`, return `Some(FooWithOverflow)`.
     pub fn wrapping_to_overflowing(self) -> Option<BinOp> {
         Some(match self {
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index c2f7a227f66..5a6decc4f94 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -780,7 +780,7 @@ rustc_queries! {
         separate_provide_extern
     }
 
-    /// Maps from a trait item to the trait item "descriptor".
+    /// Maps from a trait/impl item to the trait/impl item "descriptor".
     query associated_item(key: DefId) -> ty::AssocItem {
         desc { |tcx| "computing associated item data for `{}`", tcx.def_path_str(key) }
         cache_on_disk_if { key.is_local() }
@@ -1860,13 +1860,22 @@ rustc_queries! {
         eval_always
         desc { "calculating the stability index for the local crate" }
     }
-    query crates(_: ()) -> &'tcx [CrateNum] {
+    /// All loaded crates, including those loaded purely for doc links or diagnostics.
+    /// (Diagnostics include lints, so speculatively loaded crates may occur in successful
+    /// compilation even without doc links.)
+    /// Should be used when encoding crate metadata (and therefore when generating crate hash,
+    /// depinfo and similar things), to avoid dangling crate references in other encoded data,
+    /// like source maps.
+    /// May also be used for diagnostics - if we are loading a crate anyway we can suggest some
+    /// items from it as well.
+    /// But otherwise, `used_crates` should generally be used.
+    query crates_including_speculative(_: ()) -> &'tcx [CrateNum] {
         eval_always
         desc { "fetching all foreign CrateNum instances" }
     }
-    // Crates that are loaded non-speculatively (not for diagnostics or doc links).
-    // FIXME: This is currently only used for collecting lang items, but should be used instead of
-    // `crates` in most other cases too.
+    /// Crates that are loaded non-speculatively (not for diagnostics or doc links).
+    /// Should be used to maintain observable language behavior, for example when collecting lang
+    /// items or impls from all crates, or collecting libraries to link.
     query used_crates(_: ()) -> &'tcx [CrateNum] {
         eval_always
         desc { "fetching `CrateNum`s for all crates loaded non-speculatively" }
diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs
index c68b7a6c9eb..454897aa672 100644
--- a/compiler/rustc_middle/src/thir.rs
+++ b/compiler/rustc_middle/src/thir.rs
@@ -32,6 +32,7 @@ use rustc_target::asm::InlineAsmRegOrRegClass;
 use std::cmp::Ordering;
 use std::fmt;
 use std::ops::Index;
+use tracing::instrument;
 
 pub mod visit;
 
diff --git a/compiler/rustc_middle/src/ty/_match.rs b/compiler/rustc_middle/src/ty/_match.rs
index e28e4d66faf..f30270abd5c 100644
--- a/compiler/rustc_middle/src/ty/_match.rs
+++ b/compiler/rustc_middle/src/ty/_match.rs
@@ -1,6 +1,7 @@
 use crate::ty::error::TypeError;
 use crate::ty::relate::{self, Relate, RelateResult, TypeRelation};
 use crate::ty::{self, InferConst, Ty, TyCtxt};
+use tracing::{debug, instrument};
 
 /// A type "A" *matches* "B" if the fresh types in B could be
 /// instantiated with values so as to make it equal to A. Matching is
diff --git a/compiler/rustc_middle/src/ty/adt.rs b/compiler/rustc_middle/src/ty/adt.rs
index 77da3fbe1d7..48193754077 100644
--- a/compiler/rustc_middle/src/ty/adt.rs
+++ b/compiler/rustc_middle/src/ty/adt.rs
@@ -17,6 +17,7 @@ use rustc_query_system::ich::StableHashingContext;
 use rustc_session::DataTypeKind;
 use rustc_span::symbol::sym;
 use rustc_target::abi::{ReprOptions, VariantIdx, FIRST_VARIANT};
+use tracing::{debug, info, trace};
 
 use std::cell::RefCell;
 use std::hash::{Hash, Hasher};
diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs
index f7cc055be11..40a0dbeb2c2 100644
--- a/compiler/rustc_middle/src/ty/consts.rs
+++ b/compiler/rustc_middle/src/ty/consts.rs
@@ -8,6 +8,7 @@ use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::LocalDefId;
 use rustc_macros::{HashStable, TyDecodable, TyEncodable};
 use rustc_type_ir::{self as ir, TypeFlags, WithCachedTypeInfo};
+use tracing::{debug, instrument};
 
 mod int;
 mod kind;
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index 896114e2483..6e53b5bb520 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -74,6 +74,7 @@ use rustc_target::spec::abi;
 use rustc_type_ir::TyKind::*;
 use rustc_type_ir::WithCachedTypeInfo;
 use rustc_type_ir::{CollectAndApply, Interner, TypeFlags};
+use tracing::{debug, instrument};
 
 use std::assert_matches::assert_matches;
 use std::borrow::Borrow;
@@ -1611,7 +1612,7 @@ impl<'tcx> TyCtxt<'tcx> {
 
     pub fn all_traits(self) -> impl Iterator<Item = DefId> + 'tcx {
         iter::once(LOCAL_CRATE)
-            .chain(self.crates(()).iter().copied())
+            .chain(self.used_crates(()).iter().copied())
             .flat_map(move |cnum| self.traits(cnum).iter().copied())
     }
 
diff --git a/compiler/rustc_middle/src/ty/erase_regions.rs b/compiler/rustc_middle/src/ty/erase_regions.rs
index cfd36fd8c7c..cd6e7df31f7 100644
--- a/compiler/rustc_middle/src/ty/erase_regions.rs
+++ b/compiler/rustc_middle/src/ty/erase_regions.rs
@@ -1,6 +1,7 @@
 use crate::query::Providers;
 use crate::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable};
 use crate::ty::{self, Ty, TyCtxt, TypeFlags, TypeVisitableExt};
+use tracing::debug;
 
 pub(super) fn provide(providers: &mut Providers) {
     *providers = Providers { erase_regions_ty, ..*providers };
diff --git a/compiler/rustc_middle/src/ty/fold.rs b/compiler/rustc_middle/src/ty/fold.rs
index fd3bee16e26..d432aeada2c 100644
--- a/compiler/rustc_middle/src/ty/fold.rs
+++ b/compiler/rustc_middle/src/ty/fold.rs
@@ -1,6 +1,7 @@
 use crate::ty::{self, Binder, BoundTy, Ty, TyCtxt, TypeVisitableExt};
 use rustc_data_structures::fx::FxIndexMap;
 use rustc_hir::def_id::DefId;
+use tracing::{debug, instrument};
 
 pub use rustc_type_ir::fold::{FallibleTypeFolder, TypeFoldable, TypeFolder, TypeSuperFoldable};
 
diff --git a/compiler/rustc_middle/src/ty/generic_args.rs b/compiler/rustc_middle/src/ty/generic_args.rs
index cb11bb3ef16..c7b15c64b08 100644
--- a/compiler/rustc_middle/src/ty/generic_args.rs
+++ b/compiler/rustc_middle/src/ty/generic_args.rs
@@ -18,6 +18,7 @@ use rustc_macros::{
 use rustc_serialize::{Decodable, Encodable};
 use rustc_type_ir::WithCachedTypeInfo;
 use smallvec::SmallVec;
+use tracing::debug;
 
 use core::intrinsics;
 use std::marker::PhantomData;
diff --git a/compiler/rustc_middle/src/ty/generics.rs b/compiler/rustc_middle/src/ty/generics.rs
index cfaca05c2f0..870e4865aea 100644
--- a/compiler/rustc_middle/src/ty/generics.rs
+++ b/compiler/rustc_middle/src/ty/generics.rs
@@ -6,6 +6,7 @@ use rustc_hir::def_id::DefId;
 use rustc_macros::{HashStable, TyDecodable, TyEncodable};
 use rustc_span::symbol::{kw, Symbol};
 use rustc_span::Span;
+use tracing::instrument;
 
 use super::{Clause, InstantiatedPredicates, ParamConst, ParamTy, Ty, TyCtxt};
 
diff --git a/compiler/rustc_middle/src/ty/impls_ty.rs b/compiler/rustc_middle/src/ty/impls_ty.rs
index ef7a7a99ff7..efcf428c213 100644
--- a/compiler/rustc_middle/src/ty/impls_ty.rs
+++ b/compiler/rustc_middle/src/ty/impls_ty.rs
@@ -12,6 +12,7 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher, ToStableHas
 use rustc_query_system::ich::StableHashingContext;
 use std::cell::RefCell;
 use std::ptr;
+use tracing::trace;
 
 impl<'a, 'tcx, H, T> HashStable<StableHashingContext<'a>> for &'tcx ty::list::RawList<H, T>
 where
diff --git a/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs b/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs
index e3eea83ba49..54b8507babf 100644
--- a/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs
+++ b/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs
@@ -1,5 +1,6 @@
 use rustc_macros::HashStable;
 use smallvec::SmallVec;
+use tracing::instrument;
 
 use crate::ty::context::TyCtxt;
 use crate::ty::{self, DefId, OpaqueTypeKey, ParamEnv, Ty};
diff --git a/compiler/rustc_middle/src/ty/inhabitedness/mod.rs b/compiler/rustc_middle/src/ty/inhabitedness/mod.rs
index da5d57db5be..afdf2cbc726 100644
--- a/compiler/rustc_middle/src/ty/inhabitedness/mod.rs
+++ b/compiler/rustc_middle/src/ty/inhabitedness/mod.rs
@@ -48,6 +48,7 @@ use crate::ty::context::TyCtxt;
 use crate::ty::{self, DefId, Ty, TypeVisitableExt, VariantDef, Visibility};
 
 use rustc_type_ir::TyKind::*;
+use tracing::instrument;
 
 pub mod inhabited_predicate;
 
diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs
index a08fde976bc..7da7f69a954 100644
--- a/compiler/rustc_middle/src/ty/instance.rs
+++ b/compiler/rustc_middle/src/ty/instance.rs
@@ -14,6 +14,7 @@ use rustc_macros::{
 use rustc_middle::ty::normalize_erasing_regions::NormalizationError;
 use rustc_span::def_id::LOCAL_CRATE;
 use rustc_span::Symbol;
+use tracing::{debug, instrument};
 
 use std::assert_matches::assert_matches;
 use std::fmt;
diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs
index cf701f837d8..60ce8744032 100644
--- a/compiler/rustc_middle/src/ty/layout.rs
+++ b/compiler/rustc_middle/src/ty/layout.rs
@@ -19,6 +19,7 @@ use rustc_target::abi::*;
 use rustc_target::spec::{
     abi::Abi as SpecAbi, HasTargetSpec, HasWasmCAbiOpt, PanicStrategy, Target, WasmCAbi,
 };
+use tracing::debug;
 
 use std::borrow::Cow;
 use std::cmp;
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index f27409894fa..79cfeb71d47 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -61,6 +61,7 @@ use rustc_span::{ExpnId, ExpnKind, Span};
 use rustc_target::abi::{Align, FieldIdx, Integer, IntegerType, VariantIdx};
 pub use rustc_target::abi::{ReprFlags, ReprOptions};
 pub use rustc_type_ir::{DebugWithInfcx, InferCtxtLike, WithInfcx};
+use tracing::{debug, instrument};
 pub use vtable::*;
 
 use std::assert_matches::assert_matches;
diff --git a/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs b/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs
index 115cf3eeb22..e2cfabfdafa 100644
--- a/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs
+++ b/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs
@@ -11,6 +11,7 @@ use crate::traits::query::NoSolution;
 use crate::ty::fold::{FallibleTypeFolder, TypeFoldable, TypeFolder};
 use crate::ty::{self, EarlyBinder, GenericArgsRef, Ty, TyCtxt, TypeVisitableExt};
 use rustc_macros::{HashStable, TyDecodable, TyEncodable};
+use tracing::{debug, instrument};
 
 #[derive(Debug, Copy, Clone, HashStable, TyEncodable, TyDecodable)]
 pub enum NormalizationError<'tcx> {
diff --git a/compiler/rustc_middle/src/ty/opaque_types.rs b/compiler/rustc_middle/src/ty/opaque_types.rs
index fa5265c58e4..bbcbcdce1b2 100644
--- a/compiler/rustc_middle/src/ty/opaque_types.rs
+++ b/compiler/rustc_middle/src/ty/opaque_types.rs
@@ -5,6 +5,7 @@ use crate::ty::{GenericArg, GenericArgKind};
 use rustc_data_structures::fx::FxHashMap;
 use rustc_span::def_id::DefId;
 use rustc_span::Span;
+use tracing::{debug, instrument, trace};
 
 /// Converts generic params of a TypeFoldable from one
 /// item's generics to another. Usually from a function's generics
diff --git a/compiler/rustc_middle/src/ty/predicate.rs b/compiler/rustc_middle/src/ty/predicate.rs
index 293cc0a7eca..efb6cf25546 100644
--- a/compiler/rustc_middle/src/ty/predicate.rs
+++ b/compiler/rustc_middle/src/ty/predicate.rs
@@ -4,6 +4,7 @@ use rustc_hir::def_id::DefId;
 use rustc_macros::{extension, HashStable};
 use rustc_type_ir as ir;
 use std::cmp::Ordering;
+use tracing::instrument;
 
 use crate::ty::{
     self, DebruijnIndex, EarlyBinder, PredicatePolarity, Ty, TyCtxt, TypeFlags, Upcast, UpcastFrom,
diff --git a/compiler/rustc_middle/src/ty/print/mod.rs b/compiler/rustc_middle/src/ty/print/mod.rs
index dc77f59f3d0..3c27df9529a 100644
--- a/compiler/rustc_middle/src/ty/print/mod.rs
+++ b/compiler/rustc_middle/src/ty/print/mod.rs
@@ -7,6 +7,7 @@ use rustc_data_structures::sso::SsoHashSet;
 use rustc_hir as hir;
 use rustc_hir::def_id::{CrateNum, DefId, LocalDefId};
 use rustc_hir::definitions::{DefPathData, DisambiguatedDefPathData};
+use tracing::{debug, instrument, trace};
 
 // `pretty` is a separate module only for organization.
 mod pretty;
diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs
index a1ead1bb59f..0bcd02aaa3a 100644
--- a/compiler/rustc_middle/src/ty/print/pretty.rs
+++ b/compiler/rustc_middle/src/ty/print/pretty.rs
@@ -3258,7 +3258,7 @@ fn for_each_def(tcx: TyCtxt<'_>, mut collect_fn: impl for<'b> FnMut(&'b Ident, N
     let queue = &mut Vec::new();
     let mut seen_defs: DefIdSet = Default::default();
 
-    for &cnum in tcx.crates(()).iter() {
+    for &cnum in tcx.crates_including_speculative(()).iter() {
         let def_id = cnum.as_def_id();
 
         // Ignore crates that are not direct dependencies.
diff --git a/compiler/rustc_middle/src/ty/region.rs b/compiler/rustc_middle/src/ty/region.rs
index d7da37385e1..958e7e40168 100644
--- a/compiler/rustc_middle/src/ty/region.rs
+++ b/compiler/rustc_middle/src/ty/region.rs
@@ -8,6 +8,7 @@ use rustc_span::{ErrorGuaranteed, DUMMY_SP};
 use rustc_type_ir::RegionKind as IrRegionKind;
 pub use rustc_type_ir::RegionVid;
 use std::ops::Deref;
+use tracing::debug;
 
 use crate::ty::{self, BoundVar, TyCtxt, TypeFlags};
 
diff --git a/compiler/rustc_middle/src/ty/relate.rs b/compiler/rustc_middle/src/ty/relate.rs
index 947de3f3aaa..f02b4849f83 100644
--- a/compiler/rustc_middle/src/ty/relate.rs
+++ b/compiler/rustc_middle/src/ty/relate.rs
@@ -14,6 +14,7 @@ use rustc_hir::def_id::DefId;
 use rustc_macros::TypeVisitable;
 use rustc_target::spec::abi;
 use std::iter;
+use tracing::{debug, instrument};
 
 use super::Pattern;
 
diff --git a/compiler/rustc_middle/src/ty/rvalue_scopes.rs b/compiler/rustc_middle/src/ty/rvalue_scopes.rs
index cb2f7284eaa..8ec7946e718 100644
--- a/compiler/rustc_middle/src/ty/rvalue_scopes.rs
+++ b/compiler/rustc_middle/src/ty/rvalue_scopes.rs
@@ -2,6 +2,7 @@ use crate::middle::region::{Scope, ScopeData, ScopeTree};
 use rustc_hir as hir;
 use rustc_hir::ItemLocalMap;
 use rustc_macros::{HashStable, TyDecodable, TyEncodable};
+use tracing::debug;
 
 /// `RvalueScopes` is a mapping from sub-expressions to _extended_ lifetime as determined by
 /// rules laid out in `rustc_hir_analysis::check::rvalue_scopes`.
diff --git a/compiler/rustc_middle/src/ty/trait_def.rs b/compiler/rustc_middle/src/ty/trait_def.rs
index cf1cbb93410..37a34f28338 100644
--- a/compiler/rustc_middle/src/ty/trait_def.rs
+++ b/compiler/rustc_middle/src/ty/trait_def.rs
@@ -5,6 +5,7 @@ use hir::def_id::LOCAL_CRATE;
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
 use std::iter;
+use tracing::debug;
 
 use rustc_data_structures::fx::FxIndexMap;
 use rustc_errors::ErrorGuaranteed;
@@ -205,7 +206,7 @@ pub(super) fn trait_impls_of_provider(tcx: TyCtxt<'_>, trait_id: DefId) -> Trait
     // Traits defined in the current crate can't have impls in upstream
     // crates, so we don't bother querying the cstore.
     if !trait_id.is_local() {
-        for &cnum in tcx.crates(()).iter() {
+        for &cnum in tcx.used_crates(()).iter() {
             for &(impl_def_id, simplified_self_ty) in
                 tcx.implementations_of_trait((cnum, trait_id)).iter()
             {
@@ -247,7 +248,7 @@ pub(super) fn incoherent_impls_provider(
     let mut impls = Vec::new();
 
     let mut res = Ok(());
-    for cnum in iter::once(LOCAL_CRATE).chain(tcx.crates(()).iter().copied()) {
+    for cnum in iter::once(LOCAL_CRATE).chain(tcx.used_crates(()).iter().copied()) {
         let incoherent_impls = match tcx.crate_incoherent_impls((cnum, simp)) {
             Ok(impls) => impls,
             Err(e) => {
diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs
index 8c14f1e080a..5a3d90221eb 100644
--- a/compiler/rustc_middle/src/ty/util.rs
+++ b/compiler/rustc_middle/src/ty/util.rs
@@ -24,6 +24,7 @@ use rustc_target::abi::{Float, Integer, IntegerType, Size};
 use rustc_target::spec::abi::Abi;
 use smallvec::{smallvec, SmallVec};
 use std::{fmt, iter};
+use tracing::{debug, instrument, trace};
 
 #[derive(Copy, Clone, Debug)]
 pub struct Discr<'tcx> {
diff --git a/compiler/rustc_middle/src/ty/walk.rs b/compiler/rustc_middle/src/ty/walk.rs
index 089e61749c3..a9421aacff8 100644
--- a/compiler/rustc_middle/src/ty/walk.rs
+++ b/compiler/rustc_middle/src/ty/walk.rs
@@ -5,6 +5,7 @@ use crate::ty::{self, Ty};
 use crate::ty::{GenericArg, GenericArgKind};
 use rustc_data_structures::sso::SsoHashSet;
 use smallvec::{smallvec, SmallVec};
+use tracing::debug;
 
 // The TypeWalker's stack is hot enough that it's worth going to some effort to
 // avoid heap allocations.
diff --git a/compiler/rustc_middle/src/util/call_kind.rs b/compiler/rustc_middle/src/util/call_kind.rs
index 4e2a2c6ae0a..a4cbfe86711 100644
--- a/compiler/rustc_middle/src/util/call_kind.rs
+++ b/compiler/rustc_middle/src/util/call_kind.rs
@@ -8,6 +8,7 @@ use rustc_hir::def_id::DefId;
 use rustc_hir::{lang_items, LangItem};
 use rustc_span::symbol::Ident;
 use rustc_span::{sym, DesugaringKind, Span};
+use tracing::debug;
 
 #[derive(Clone, Copy, PartialEq, Eq, Debug)]
 pub enum CallDesugaringKind {
diff --git a/compiler/rustc_middle/src/util/find_self_call.rs b/compiler/rustc_middle/src/util/find_self_call.rs
index 0ca4fce5da9..027e2703e98 100644
--- a/compiler/rustc_middle/src/util/find_self_call.rs
+++ b/compiler/rustc_middle/src/util/find_self_call.rs
@@ -3,6 +3,7 @@ use crate::ty::GenericArgsRef;
 use crate::ty::{self, TyCtxt};
 use rustc_span::def_id::DefId;
 use rustc_span::source_map::Spanned;
+use tracing::debug;
 
 /// Checks if the specified `local` is used as the `self` parameter of a method call
 /// in the provided `BasicBlock`. If it is, then the `DefId` of the called method is
diff --git a/compiler/rustc_mir_build/messages.ftl b/compiler/rustc_mir_build/messages.ftl
index 0bb44dbb870..67e1e15defa 100644
--- a/compiler/rustc_mir_build/messages.ftl
+++ b/compiler/rustc_mir_build/messages.ftl
@@ -335,12 +335,12 @@ mir_build_unsafe_fn_safe_body = an unsafe function restricts its caller, but its
 mir_build_unsafe_not_inherited = items do not inherit unsafety from separate enclosing items
 
 mir_build_unsafe_op_in_unsafe_fn_borrow_of_layout_constrained_field_requires_unsafe =
-    borrow of layout constrained field with interior mutability is unsafe and requires unsafe block (error E0133)
+    borrow of layout constrained field with interior mutability is unsafe and requires unsafe block
     .note = references to fields of layout constrained fields lose the constraints. Coupled with interior mutability, the field can be changed to invalid values
     .label = borrow of layout constrained field with interior mutability
 
 mir_build_unsafe_op_in_unsafe_fn_call_to_fn_with_requires_unsafe =
-    call to function `{$function}` with `#[target_feature]` is unsafe and requires unsafe block (error E0133)
+    call to function `{$function}` with `#[target_feature]` is unsafe and requires unsafe block
     .help = in order for the call to be safe, the context requires the following additional target {$missing_target_features_count ->
         [1] feature
         *[count] features
@@ -355,48 +355,47 @@ mir_build_unsafe_op_in_unsafe_fn_call_to_fn_with_requires_unsafe =
     .label = call to function with `#[target_feature]`
 
 mir_build_unsafe_op_in_unsafe_fn_call_to_unsafe_fn_requires_unsafe =
-    call to unsafe function `{$function}` is unsafe and requires unsafe block (error E0133)
+    call to unsafe function `{$function}` is unsafe and requires unsafe block
     .note = consult the function's documentation for information on how to avoid undefined behavior
     .label = call to unsafe function
 
 mir_build_unsafe_op_in_unsafe_fn_call_to_unsafe_fn_requires_unsafe_nameless =
-    call to unsafe function is unsafe and requires unsafe block (error E0133)
+    call to unsafe function is unsafe and requires unsafe block
     .note = consult the function's documentation for information on how to avoid undefined behavior
     .label = call to unsafe function
 
 mir_build_unsafe_op_in_unsafe_fn_deref_raw_pointer_requires_unsafe =
-    dereference of raw pointer is unsafe and requires unsafe block (error E0133)
+    dereference of raw pointer is unsafe and requires unsafe block
     .note = raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior
     .label = dereference of raw pointer
 
 mir_build_unsafe_op_in_unsafe_fn_extern_static_requires_unsafe =
-    use of extern static is unsafe and requires unsafe block (error E0133)
+    use of extern static is unsafe and requires unsafe block
     .note = extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior
     .label = use of extern static
 
 mir_build_unsafe_op_in_unsafe_fn_initializing_type_with_requires_unsafe =
-    initializing type with `rustc_layout_scalar_valid_range` attr is unsafe and requires unsafe
-    block (error E0133)
+    initializing type with `rustc_layout_scalar_valid_range` attr is unsafe and requires unsafe block
     .note = initializing a layout restricted type's field with a value outside the valid range is undefined behavior
     .label = initializing type with `rustc_layout_scalar_valid_range` attr
 
 mir_build_unsafe_op_in_unsafe_fn_inline_assembly_requires_unsafe =
-    use of inline assembly is unsafe and requires unsafe block (error E0133)
+    use of inline assembly is unsafe and requires unsafe block
     .note = inline assembly is entirely unchecked and can cause undefined behavior
     .label = use of inline assembly
 
 mir_build_unsafe_op_in_unsafe_fn_mutable_static_requires_unsafe =
-    use of mutable static is unsafe and requires unsafe block (error E0133)
+    use of mutable static is unsafe and requires unsafe block
     .note = mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior
     .label = use of mutable static
 
 mir_build_unsafe_op_in_unsafe_fn_mutation_of_layout_constrained_field_requires_unsafe =
-    mutation of layout constrained field is unsafe and requires unsafe block (error E0133)
+    mutation of layout constrained field is unsafe and requires unsafe block
     .note = mutating layout constrained fields cannot statically be checked for valid values
     .label = mutation of layout constrained field
 
 mir_build_unsafe_op_in_unsafe_fn_union_field_requires_unsafe =
-    access to union field is unsafe and requires unsafe block (error E0133)
+    access to union field is unsafe and requires unsafe block
     .note = the field may not be properly initialized: using uninitialized data will cause undefined behavior
     .label = access to union field
 
diff --git a/compiler/rustc_mir_build/src/build/block.rs b/compiler/rustc_mir_build/src/build/block.rs
index 6ae98e15946..c1d645aa42c 100644
--- a/compiler/rustc_mir_build/src/build/block.rs
+++ b/compiler/rustc_mir_build/src/build/block.rs
@@ -5,6 +5,7 @@ use rustc_middle::span_bug;
 use rustc_middle::thir::*;
 use rustc_middle::{mir::*, ty};
 use rustc_span::Span;
+use tracing::debug;
 
 impl<'a, 'tcx> Builder<'a, 'tcx> {
     pub(crate) fn ast_block(
diff --git a/compiler/rustc_mir_build/src/build/cfg.rs b/compiler/rustc_mir_build/src/build/cfg.rs
index 18e45291e9a..6034c8fadc5 100644
--- a/compiler/rustc_mir_build/src/build/cfg.rs
+++ b/compiler/rustc_mir_build/src/build/cfg.rs
@@ -3,6 +3,7 @@
 use crate::build::CFG;
 use rustc_middle::mir::*;
 use rustc_middle::ty::TyCtxt;
+use tracing::debug;
 
 impl<'tcx> CFG<'tcx> {
     pub(crate) fn block_data(&self, blk: BasicBlock) -> &BasicBlockData<'tcx> {
diff --git a/compiler/rustc_mir_build/src/build/custom/parse.rs b/compiler/rustc_mir_build/src/build/custom/parse.rs
index 0384b9bc154..8bcd429b67e 100644
--- a/compiler/rustc_mir_build/src/build/custom/parse.rs
+++ b/compiler/rustc_mir_build/src/build/custom/parse.rs
@@ -38,7 +38,7 @@ macro_rules! parse_by_kind {
     ) => {{
         let expr_id = $self.preparse($expr_id);
         let expr = &$self.thir[expr_id];
-        debug!("Trying to parse {:?} as {}", expr.kind, $expected);
+        tracing::debug!("Trying to parse {:?} as {}", expr.kind, $expected);
         let $expr_name = expr;
         match &expr.kind {
             $(
diff --git a/compiler/rustc_mir_build/src/build/expr/as_constant.rs b/compiler/rustc_mir_build/src/build/expr/as_constant.rs
index 817f5f787b1..b4dd423f344 100644
--- a/compiler/rustc_mir_build/src/build/expr/as_constant.rs
+++ b/compiler/rustc_mir_build/src/build/expr/as_constant.rs
@@ -11,6 +11,7 @@ use rustc_middle::ty::{
 };
 use rustc_middle::{bug, span_bug};
 use rustc_target::abi::Size;
+use tracing::{instrument, trace};
 
 impl<'a, 'tcx> Builder<'a, 'tcx> {
     /// Compile `expr`, yielding a compile-time constant. Assumes that
diff --git a/compiler/rustc_mir_build/src/build/expr/as_operand.rs b/compiler/rustc_mir_build/src/build/expr/as_operand.rs
index 076ee7f85ff..09ce134a2bf 100644
--- a/compiler/rustc_mir_build/src/build/expr/as_operand.rs
+++ b/compiler/rustc_mir_build/src/build/expr/as_operand.rs
@@ -5,6 +5,7 @@ use crate::build::{BlockAnd, BlockAndExtension, Builder, NeedsTemporary};
 use rustc_middle::middle::region;
 use rustc_middle::mir::*;
 use rustc_middle::thir::*;
+use tracing::{debug, instrument};
 
 impl<'a, 'tcx> Builder<'a, 'tcx> {
     /// Returns an operand suitable for use until the end of the current
diff --git a/compiler/rustc_mir_build/src/build/expr/as_place.rs b/compiler/rustc_mir_build/src/build/expr/as_place.rs
index 9963629fc52..93d0d4e59ba 100644
--- a/compiler/rustc_mir_build/src/build/expr/as_place.rs
+++ b/compiler/rustc_mir_build/src/build/expr/as_place.rs
@@ -15,6 +15,7 @@ use rustc_middle::ty::AdtDef;
 use rustc_middle::ty::{self, CanonicalUserTypeAnnotation, Ty, Variance};
 use rustc_span::Span;
 use rustc_target::abi::{FieldIdx, VariantIdx, FIRST_VARIANT};
+use tracing::{debug, instrument, trace};
 
 use std::assert_matches::assert_matches;
 use std::iter;
diff --git a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs
index 60a2827a3e2..9f9b566bb8f 100644
--- a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs
+++ b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs
@@ -18,6 +18,7 @@ use rustc_middle::ty::cast::{mir_cast_kind, CastTy};
 use rustc_middle::ty::layout::IntegerExt;
 use rustc_middle::ty::{self, Ty, UpvarArgs};
 use rustc_span::{Span, DUMMY_SP};
+use tracing::debug;
 
 impl<'a, 'tcx> Builder<'a, 'tcx> {
     /// Returns an rvalue suitable for use until the end of the current
diff --git a/compiler/rustc_mir_build/src/build/expr/as_temp.rs b/compiler/rustc_mir_build/src/build/expr/as_temp.rs
index 27e66e7f54d..607c7c3259c 100644
--- a/compiler/rustc_mir_build/src/build/expr/as_temp.rs
+++ b/compiler/rustc_mir_build/src/build/expr/as_temp.rs
@@ -6,6 +6,7 @@ use rustc_data_structures::stack::ensure_sufficient_stack;
 use rustc_middle::middle::region;
 use rustc_middle::mir::*;
 use rustc_middle::thir::*;
+use tracing::{debug, instrument};
 
 impl<'a, 'tcx> Builder<'a, 'tcx> {
     /// Compile `expr` into a fresh temporary. This is used when building
diff --git a/compiler/rustc_mir_build/src/build/expr/into.rs b/compiler/rustc_mir_build/src/build/expr/into.rs
index f8c91073045..9349133d2db 100644
--- a/compiler/rustc_mir_build/src/build/expr/into.rs
+++ b/compiler/rustc_mir_build/src/build/expr/into.rs
@@ -12,6 +12,7 @@ use rustc_middle::thir::*;
 use rustc_middle::ty::CanonicalUserTypeAnnotation;
 use rustc_span::source_map::Spanned;
 use std::iter;
+use tracing::{debug, instrument};
 
 impl<'a, 'tcx> Builder<'a, 'tcx> {
     /// Compile `expr`, storing the result into `destination`, which
diff --git a/compiler/rustc_mir_build/src/build/expr/stmt.rs b/compiler/rustc_mir_build/src/build/expr/stmt.rs
index 7f5e45e20cc..2bdeb579a02 100644
--- a/compiler/rustc_mir_build/src/build/expr/stmt.rs
+++ b/compiler/rustc_mir_build/src/build/expr/stmt.rs
@@ -3,6 +3,7 @@ use crate::build::{BlockAnd, BlockAndExtension, BlockFrame, Builder};
 use rustc_middle::middle::region;
 use rustc_middle::mir::*;
 use rustc_middle::thir::*;
+use tracing::debug;
 
 impl<'a, 'tcx> Builder<'a, 'tcx> {
     /// Builds a block of MIR statements to evaluate the THIR `expr`.
diff --git a/compiler/rustc_mir_build/src/build/matches/mod.rs b/compiler/rustc_mir_build/src/build/matches/mod.rs
index 3fc719394bf..54138789369 100644
--- a/compiler/rustc_mir_build/src/build/matches/mod.rs
+++ b/compiler/rustc_mir_build/src/build/matches/mod.rs
@@ -20,6 +20,8 @@ use rustc_middle::ty::{self, CanonicalUserTypeAnnotation, Ty};
 use rustc_span::symbol::Symbol;
 use rustc_span::{BytePos, Pos, Span};
 use rustc_target::abi::VariantIdx;
+use tracing::{debug, instrument};
+
 // helper functions, broken out by category:
 mod simplify;
 mod test;
@@ -925,7 +927,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 for subpattern in prefix.iter() {
                     self.visit_primary_bindings(subpattern, pattern_user_ty.clone().index(), f);
                 }
-                for subpattern in slice {
+                if let Some(subpattern) = slice {
                     self.visit_primary_bindings(
                         subpattern,
                         pattern_user_ty.clone().subslice(from, to),
diff --git a/compiler/rustc_mir_build/src/build/matches/simplify.rs b/compiler/rustc_mir_build/src/build/matches/simplify.rs
index 90f12e55ff4..543301c71a0 100644
--- a/compiler/rustc_mir_build/src/build/matches/simplify.rs
+++ b/compiler/rustc_mir_build/src/build/matches/simplify.rs
@@ -14,6 +14,7 @@
 
 use crate::build::matches::{MatchPair, PatternExtraData, TestCase};
 use crate::build::Builder;
+use tracing::{debug, instrument};
 
 use std::mem;
 
diff --git a/compiler/rustc_mir_build/src/build/matches/test.rs b/compiler/rustc_mir_build/src/build/matches/test.rs
index f3faeb4158e..2040071e76e 100644
--- a/compiler/rustc_mir_build/src/build/matches/test.rs
+++ b/compiler/rustc_mir_build/src/build/matches/test.rs
@@ -18,6 +18,7 @@ use rustc_span::def_id::DefId;
 use rustc_span::source_map::Spanned;
 use rustc_span::symbol::{sym, Symbol};
 use rustc_span::{Span, DUMMY_SP};
+use tracing::{debug, instrument};
 
 use std::cmp::Ordering;
 
diff --git a/compiler/rustc_mir_build/src/build/matches/util.rs b/compiler/rustc_mir_build/src/build/matches/util.rs
index 14c74c761eb..770f689724a 100644
--- a/compiler/rustc_mir_build/src/build/matches/util.rs
+++ b/compiler/rustc_mir_build/src/build/matches/util.rs
@@ -7,6 +7,7 @@ use rustc_middle::thir::{self, *};
 use rustc_middle::ty::TypeVisitableExt;
 use rustc_middle::ty::{self, Ty};
 use rustc_span::Span;
+use tracing::debug;
 
 impl<'a, 'tcx> Builder<'a, 'tcx> {
     pub(crate) fn field_match_pairs<'pat>(
diff --git a/compiler/rustc_mir_build/src/build/misc.rs b/compiler/rustc_mir_build/src/build/misc.rs
index c263de79c3b..04e6d24e5a1 100644
--- a/compiler/rustc_mir_build/src/build/misc.rs
+++ b/compiler/rustc_mir_build/src/build/misc.rs
@@ -7,6 +7,7 @@ use rustc_middle::mir::*;
 use rustc_middle::ty::{self, Ty};
 use rustc_span::Span;
 use rustc_trait_selection::infer::InferCtxtExt;
+use tracing::debug;
 
 impl<'a, 'tcx> Builder<'a, 'tcx> {
     /// Adds a new temporary value of type `ty` storing the result of
diff --git a/compiler/rustc_mir_build/src/build/scope.rs b/compiler/rustc_mir_build/src/build/scope.rs
index be32363fec5..c7850c7aea8 100644
--- a/compiler/rustc_mir_build/src/build/scope.rs
+++ b/compiler/rustc_mir_build/src/build/scope.rs
@@ -94,6 +94,7 @@ use rustc_middle::{bug, span_bug};
 use rustc_session::lint::Level;
 use rustc_span::source_map::Spanned;
 use rustc_span::{Span, DUMMY_SP};
+use tracing::{debug, instrument};
 
 #[derive(Debug)]
 pub struct Scopes<'tcx> {
diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs
index e2a28467b84..38e6c00add8 100644
--- a/compiler/rustc_mir_build/src/errors.rs
+++ b/compiler/rustc_mir_build/src/errors.rs
@@ -21,7 +21,7 @@ pub struct UnconditionalRecursion {
 }
 
 #[derive(LintDiagnostic)]
-#[diag(mir_build_unsafe_op_in_unsafe_fn_call_to_unsafe_fn_requires_unsafe)]
+#[diag(mir_build_unsafe_op_in_unsafe_fn_call_to_unsafe_fn_requires_unsafe, code = E0133)]
 #[note]
 pub struct UnsafeOpInUnsafeFnCallToUnsafeFunctionRequiresUnsafe {
     #[label]
@@ -32,7 +32,7 @@ pub struct UnsafeOpInUnsafeFnCallToUnsafeFunctionRequiresUnsafe {
 }
 
 #[derive(LintDiagnostic)]
-#[diag(mir_build_unsafe_op_in_unsafe_fn_call_to_unsafe_fn_requires_unsafe_nameless)]
+#[diag(mir_build_unsafe_op_in_unsafe_fn_call_to_unsafe_fn_requires_unsafe_nameless, code = E0133)]
 #[note]
 pub struct UnsafeOpInUnsafeFnCallToUnsafeFunctionRequiresUnsafeNameless {
     #[label]
@@ -42,7 +42,7 @@ pub struct UnsafeOpInUnsafeFnCallToUnsafeFunctionRequiresUnsafeNameless {
 }
 
 #[derive(LintDiagnostic)]
-#[diag(mir_build_unsafe_op_in_unsafe_fn_inline_assembly_requires_unsafe)]
+#[diag(mir_build_unsafe_op_in_unsafe_fn_inline_assembly_requires_unsafe, code = E0133)]
 #[note]
 pub struct UnsafeOpInUnsafeFnUseOfInlineAssemblyRequiresUnsafe {
     #[label]
@@ -52,7 +52,7 @@ pub struct UnsafeOpInUnsafeFnUseOfInlineAssemblyRequiresUnsafe {
 }
 
 #[derive(LintDiagnostic)]
-#[diag(mir_build_unsafe_op_in_unsafe_fn_initializing_type_with_requires_unsafe)]
+#[diag(mir_build_unsafe_op_in_unsafe_fn_initializing_type_with_requires_unsafe, code = E0133)]
 #[note]
 pub struct UnsafeOpInUnsafeFnInitializingTypeWithRequiresUnsafe {
     #[label]
@@ -62,7 +62,7 @@ pub struct UnsafeOpInUnsafeFnInitializingTypeWithRequiresUnsafe {
 }
 
 #[derive(LintDiagnostic)]
-#[diag(mir_build_unsafe_op_in_unsafe_fn_mutable_static_requires_unsafe)]
+#[diag(mir_build_unsafe_op_in_unsafe_fn_mutable_static_requires_unsafe, code = E0133)]
 #[note]
 pub struct UnsafeOpInUnsafeFnUseOfMutableStaticRequiresUnsafe {
     #[label]
@@ -72,7 +72,7 @@ pub struct UnsafeOpInUnsafeFnUseOfMutableStaticRequiresUnsafe {
 }
 
 #[derive(LintDiagnostic)]
-#[diag(mir_build_unsafe_op_in_unsafe_fn_extern_static_requires_unsafe)]
+#[diag(mir_build_unsafe_op_in_unsafe_fn_extern_static_requires_unsafe, code = E0133)]
 #[note]
 pub struct UnsafeOpInUnsafeFnUseOfExternStaticRequiresUnsafe {
     #[label]
@@ -82,7 +82,7 @@ pub struct UnsafeOpInUnsafeFnUseOfExternStaticRequiresUnsafe {
 }
 
 #[derive(LintDiagnostic)]
-#[diag(mir_build_unsafe_op_in_unsafe_fn_deref_raw_pointer_requires_unsafe)]
+#[diag(mir_build_unsafe_op_in_unsafe_fn_deref_raw_pointer_requires_unsafe, code = E0133)]
 #[note]
 pub struct UnsafeOpInUnsafeFnDerefOfRawPointerRequiresUnsafe {
     #[label]
@@ -92,7 +92,7 @@ pub struct UnsafeOpInUnsafeFnDerefOfRawPointerRequiresUnsafe {
 }
 
 #[derive(LintDiagnostic)]
-#[diag(mir_build_unsafe_op_in_unsafe_fn_union_field_requires_unsafe)]
+#[diag(mir_build_unsafe_op_in_unsafe_fn_union_field_requires_unsafe, code = E0133)]
 #[note]
 pub struct UnsafeOpInUnsafeFnAccessToUnionFieldRequiresUnsafe {
     #[label]
@@ -102,7 +102,10 @@ pub struct UnsafeOpInUnsafeFnAccessToUnionFieldRequiresUnsafe {
 }
 
 #[derive(LintDiagnostic)]
-#[diag(mir_build_unsafe_op_in_unsafe_fn_mutation_of_layout_constrained_field_requires_unsafe)]
+#[diag(
+    mir_build_unsafe_op_in_unsafe_fn_mutation_of_layout_constrained_field_requires_unsafe,
+    code = E0133
+)]
 #[note]
 pub struct UnsafeOpInUnsafeFnMutationOfLayoutConstrainedFieldRequiresUnsafe {
     #[label]
@@ -112,7 +115,10 @@ pub struct UnsafeOpInUnsafeFnMutationOfLayoutConstrainedFieldRequiresUnsafe {
 }
 
 #[derive(LintDiagnostic)]
-#[diag(mir_build_unsafe_op_in_unsafe_fn_borrow_of_layout_constrained_field_requires_unsafe)]
+#[diag(
+    mir_build_unsafe_op_in_unsafe_fn_borrow_of_layout_constrained_field_requires_unsafe,
+    code = E0133,
+)]
 pub struct UnsafeOpInUnsafeFnBorrowOfLayoutConstrainedFieldRequiresUnsafe {
     #[label]
     pub span: Span,
@@ -121,7 +127,7 @@ pub struct UnsafeOpInUnsafeFnBorrowOfLayoutConstrainedFieldRequiresUnsafe {
 }
 
 #[derive(LintDiagnostic)]
-#[diag(mir_build_unsafe_op_in_unsafe_fn_call_to_fn_with_requires_unsafe)]
+#[diag(mir_build_unsafe_op_in_unsafe_fn_call_to_fn_with_requires_unsafe, code = E0133)]
 #[help]
 pub struct UnsafeOpInUnsafeFnCallToFunctionWithRequiresUnsafe {
     #[label]
diff --git a/compiler/rustc_mir_build/src/lib.rs b/compiler/rustc_mir_build/src/lib.rs
index 2e1cb0e1b5e..74600c6b12e 100644
--- a/compiler/rustc_mir_build/src/lib.rs
+++ b/compiler/rustc_mir_build/src/lib.rs
@@ -10,9 +10,6 @@
 #![feature(let_chains)]
 #![feature(try_blocks)]
 
-#[macro_use]
-extern crate tracing;
-
 mod build;
 mod check_unsafety;
 mod errors;
diff --git a/compiler/rustc_mir_build/src/thir/constant.rs b/compiler/rustc_mir_build/src/thir/constant.rs
index 03c7c1fd6ec..31bc72184ca 100644
--- a/compiler/rustc_mir_build/src/thir/constant.rs
+++ b/compiler/rustc_mir_build/src/thir/constant.rs
@@ -2,6 +2,7 @@ use rustc_ast as ast;
 use rustc_middle::bug;
 use rustc_middle::mir::interpret::{LitToConstError, LitToConstInput};
 use rustc_middle::ty::{self, ParamEnv, ScalarInt, TyCtxt};
+use tracing::trace;
 
 use crate::build::parse_float_into_scalar;
 
diff --git a/compiler/rustc_mir_build/src/thir/cx/block.rs b/compiler/rustc_mir_build/src/thir/cx/block.rs
index d4a347975db..54eafdd828a 100644
--- a/compiler/rustc_mir_build/src/thir/cx/block.rs
+++ b/compiler/rustc_mir_build/src/thir/cx/block.rs
@@ -1,12 +1,12 @@
 use crate::thir::cx::Cx;
 
 use rustc_hir as hir;
+use rustc_index::Idx;
 use rustc_middle::middle::region;
 use rustc_middle::thir::*;
 use rustc_middle::ty;
-
-use rustc_index::Idx;
 use rustc_middle::ty::CanonicalUserTypeAnnotation;
+use tracing::debug;
 
 impl<'tcx> Cx<'tcx> {
     pub(crate) fn mirror_block(&mut self, block: &'tcx hir::Block<'tcx>) -> BlockId {
diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs
index b7766666960..28f9300b97a 100644
--- a/compiler/rustc_mir_build/src/thir/cx/expr.rs
+++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs
@@ -25,6 +25,7 @@ use rustc_middle::{bug, span_bug};
 use rustc_span::source_map::Spanned;
 use rustc_span::{sym, Span, DUMMY_SP};
 use rustc_target::abi::{FieldIdx, FIRST_VARIANT};
+use tracing::{debug, info, instrument, trace};
 
 impl<'tcx> Cx<'tcx> {
     pub(crate) fn mirror_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) -> ExprId {
diff --git a/compiler/rustc_mir_build/src/thir/cx/mod.rs b/compiler/rustc_mir_build/src/thir/cx/mod.rs
index d1d21f88aef..3c0e2521d88 100644
--- a/compiler/rustc_mir_build/src/thir/cx/mod.rs
+++ b/compiler/rustc_mir_build/src/thir/cx/mod.rs
@@ -17,6 +17,7 @@ use rustc_middle::bug;
 use rustc_middle::middle::region;
 use rustc_middle::thir::*;
 use rustc_middle::ty::{self, RvalueScopes, TyCtxt};
+use tracing::instrument;
 
 pub(crate) fn thir_body(
     tcx: TyCtxt<'_>,
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 592f0dcf4ef..30f57c8c622 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
@@ -24,6 +24,7 @@ use rustc_session::lint::builtin::{
 };
 use rustc_span::hygiene::DesugaringKind;
 use rustc_span::{sym, Span};
+use tracing::instrument;
 
 pub(crate) fn check_match(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(), ErrorGuaranteed> {
     let typeck_results = tcx.typeck(def_id);
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 c6f81c3cb99..bac47fafbfd 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
@@ -12,6 +12,7 @@ use rustc_span::{ErrorGuaranteed, Span};
 use rustc_target::abi::{FieldIdx, VariantIdx};
 use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
 use rustc_trait_selection::traits::{self, ObligationCause};
+use tracing::{debug, instrument, trace};
 
 use std::cell::Cell;
 
diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs
index dc845b3d4ac..7408c679f00 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs
@@ -25,6 +25,7 @@ use rustc_middle::{bug, span_bug};
 use rustc_span::def_id::LocalDefId;
 use rustc_span::{ErrorGuaranteed, Span};
 use rustc_target::abi::{FieldIdx, Integer};
+use tracing::{debug, instrument};
 
 use std::cmp::Ordering;
 
diff --git a/compiler/rustc_mir_build/src/thir/util.rs b/compiler/rustc_mir_build/src/thir/util.rs
index 340eb3c2eea..53a2a0852eb 100644
--- a/compiler/rustc_mir_build/src/thir/util.rs
+++ b/compiler/rustc_mir_build/src/thir/util.rs
@@ -1,6 +1,7 @@
 use rustc_hir as hir;
 use rustc_middle::bug;
 use rustc_middle::ty::{self, CanonicalUserType, TyCtxt, UserType};
+use tracing::debug;
 
 pub(crate) trait UserAnnotatedTyHelpers<'tcx> {
     fn tcx(&self) -> TyCtxt<'tcx>;
diff --git a/compiler/rustc_mir_dataflow/src/drop_flag_effects.rs b/compiler/rustc_mir_dataflow/src/drop_flag_effects.rs
index de1ca8d823b..82c59d7d959 100644
--- a/compiler/rustc_mir_dataflow/src/drop_flag_effects.rs
+++ b/compiler/rustc_mir_dataflow/src/drop_flag_effects.rs
@@ -1,6 +1,7 @@
 use crate::elaborate_drops::DropFlagState;
 use rustc_middle::mir::{self, Body, Location, Terminator, TerminatorKind};
 use rustc_target::abi::VariantIdx;
+use tracing::debug;
 
 use super::move_paths::{InitKind, LookupResult, MoveData, MovePathIndex};
 use super::MoveDataParamEnv;
diff --git a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs
index 185e87baed8..bdc59e84356 100644
--- a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs
+++ b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs
@@ -11,6 +11,7 @@ use rustc_span::source_map::Spanned;
 use rustc_span::DUMMY_SP;
 use rustc_target::abi::{FieldIdx, VariantIdx, FIRST_VARIANT};
 use std::{fmt, iter};
+use tracing::{debug, instrument};
 
 /// The value of an inserted drop flag.
 #[derive(Debug, PartialEq, Eq, Copy, Clone)]
diff --git a/compiler/rustc_mir_dataflow/src/framework/engine.rs b/compiler/rustc_mir_dataflow/src/framework/engine.rs
index ea9cf6565e7..564a99e5df8 100644
--- a/compiler/rustc_mir_dataflow/src/framework/engine.rs
+++ b/compiler/rustc_mir_dataflow/src/framework/engine.rs
@@ -19,6 +19,7 @@ use rustc_middle::mir::{create_dump_file, dump_enabled};
 use rustc_middle::ty::print::with_no_trimmed_paths;
 use rustc_middle::ty::TyCtxt;
 use rustc_span::symbol::{sym, Symbol};
+use tracing::{debug, error};
 
 use super::fmt::DebugWithContext;
 use super::graphviz;
diff --git a/compiler/rustc_mir_dataflow/src/impls/initialized.rs b/compiler/rustc_mir_dataflow/src/impls/initialized.rs
index 180168c7316..f0b79dab0c9 100644
--- a/compiler/rustc_mir_dataflow/src/impls/initialized.rs
+++ b/compiler/rustc_mir_dataflow/src/impls/initialized.rs
@@ -3,6 +3,7 @@ use rustc_index::Idx;
 use rustc_middle::bug;
 use rustc_middle::mir::{self, Body, CallReturnPlaces, Location, TerminatorEdges};
 use rustc_middle::ty::{self, TyCtxt};
+use tracing::{debug, instrument};
 
 use crate::drop_flag_effects_for_function_entry;
 use crate::drop_flag_effects_for_location;
diff --git a/compiler/rustc_mir_dataflow/src/lib.rs b/compiler/rustc_mir_dataflow/src/lib.rs
index 5e96a73f6c5..0b397a67d45 100644
--- a/compiler/rustc_mir_dataflow/src/lib.rs
+++ b/compiler/rustc_mir_dataflow/src/lib.rs
@@ -4,9 +4,6 @@
 #![feature(let_chains)]
 #![feature(try_blocks)]
 
-#[macro_use]
-extern crate tracing;
-
 use rustc_middle::ty;
 
 // Please change the public `use` directives cautiously, as they might be used by external tools.
diff --git a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs
index 521ecb1b9a5..1fb77bef3d4 100644
--- a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs
+++ b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs
@@ -4,6 +4,7 @@ use rustc_middle::mir::*;
 use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt};
 use rustc_middle::{bug, span_bug};
 use smallvec::{smallvec, SmallVec};
+use tracing::debug;
 
 use std::mem;
 
diff --git a/compiler/rustc_mir_dataflow/src/rustc_peek.rs b/compiler/rustc_mir_dataflow/src/rustc_peek.rs
index d7e3c91b875..1de9055273b 100644
--- a/compiler/rustc_mir_dataflow/src/rustc_peek.rs
+++ b/compiler/rustc_mir_dataflow/src/rustc_peek.rs
@@ -18,6 +18,7 @@ use rustc_middle::mir::{self, Body, Local, Location};
 use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_span::symbol::{sym, Symbol};
 use rustc_span::Span;
+use tracing::{debug, info};
 
 pub struct SanityCheck;
 
diff --git a/compiler/rustc_mir_dataflow/src/value_analysis.rs b/compiler/rustc_mir_dataflow/src/value_analysis.rs
index 1e5322dd99b..5e2d88f94ca 100644
--- a/compiler/rustc_mir_dataflow/src/value_analysis.rs
+++ b/compiler/rustc_mir_dataflow/src/value_analysis.rs
@@ -45,6 +45,7 @@ use rustc_middle::mir::visit::{MutatingUseContext, PlaceContext, Visitor};
 use rustc_middle::mir::*;
 use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_target::abi::{FieldIdx, VariantIdx};
+use tracing::debug;
 
 use crate::lattice::{HasBottom, HasTop};
 use crate::{
diff --git a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs
index 3d24a56cdd7..53a016f01ec 100644
--- a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs
+++ b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs
@@ -165,9 +165,7 @@ impl<'tcx> ValueAnalysis<'tcx> for ConstAnalysis<'_, 'tcx> {
                     }
                 }
             }
-            Rvalue::BinaryOp(overflowing_op, box (left, right))
-                if let Some(op) = overflowing_op.overflowing_to_wrapping() =>
-            {
+            Rvalue::BinaryOp(op, box (left, right)) if op.is_overflowing() => {
                 // Flood everything now, so we can use `insert_value_idx` directly later.
                 state.flood(target.as_ref(), self.map());
 
@@ -177,7 +175,7 @@ impl<'tcx> ValueAnalysis<'tcx> for ConstAnalysis<'_, 'tcx> {
                 let overflow_target = self.map().apply(target, TrackElem::Field(1_u32.into()));
 
                 if value_target.is_some() || overflow_target.is_some() {
-                    let (val, overflow) = self.binary_op(state, op, left, right);
+                    let (val, overflow) = self.binary_op(state, *op, left, right);
 
                     if let Some(value_target) = value_target {
                         // We have flooded `target` earlier.
@@ -186,7 +184,7 @@ impl<'tcx> ValueAnalysis<'tcx> for ConstAnalysis<'_, 'tcx> {
                     if let Some(overflow_target) = overflow_target {
                         let overflow = match overflow {
                             FlatSet::Top => FlatSet::Top,
-                            FlatSet::Elem(overflow) => FlatSet::Elem(Scalar::from_bool(overflow)),
+                            FlatSet::Elem(overflow) => FlatSet::Elem(overflow),
                             FlatSet::Bottom => FlatSet::Bottom,
                         };
                         // We have flooded `target` earlier.
@@ -266,15 +264,16 @@ impl<'tcx> ValueAnalysis<'tcx> for ConstAnalysis<'_, 'tcx> {
                     FlatSet::Top => FlatSet::Top,
                 }
             }
-            Rvalue::BinaryOp(op, box (left, right)) => {
+            Rvalue::BinaryOp(op, box (left, right)) if !op.is_overflowing() => {
                 // Overflows must be ignored here.
+                // The overflowing operators are handled in `handle_assign`.
                 let (val, _overflow) = self.binary_op(state, *op, left, right);
                 val
             }
             Rvalue::UnaryOp(op, operand) => match self.eval_operand(operand, state) {
                 FlatSet::Elem(value) => self
                     .ecx
-                    .wrapping_unary_op(*op, &value)
+                    .unary_op(*op, &value)
                     .map_or(FlatSet::Top, |val| self.wrap_immediate(*val)),
                 FlatSet::Bottom => FlatSet::Bottom,
                 FlatSet::Top => FlatSet::Top,
@@ -439,7 +438,7 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> {
         op: BinOp,
         left: &Operand<'tcx>,
         right: &Operand<'tcx>,
-    ) -> (FlatSet<Scalar>, FlatSet<bool>) {
+    ) -> (FlatSet<Scalar>, FlatSet<Scalar>) {
         let left = self.eval_operand(left, state);
         let right = self.eval_operand(right, state);
 
@@ -447,9 +446,17 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> {
             (FlatSet::Bottom, _) | (_, FlatSet::Bottom) => (FlatSet::Bottom, FlatSet::Bottom),
             // Both sides are known, do the actual computation.
             (FlatSet::Elem(left), FlatSet::Elem(right)) => {
-                match self.ecx.overflowing_binary_op(op, &left, &right) {
-                    Ok((val, overflow)) => {
-                        (FlatSet::Elem(val.to_scalar()), FlatSet::Elem(overflow))
+                match self.ecx.binary_op(op, &left, &right) {
+                    // Ideally this would return an Immediate, since it's sometimes
+                    // a pair and sometimes not. But as a hack we always return a pair
+                    // and just make the 2nd component `Bottom` when it does not exist.
+                    Ok(val) => {
+                        if matches!(val.layout.abi, Abi::ScalarPair(..)) {
+                            let (val, overflow) = val.to_scalar_pair();
+                            (FlatSet::Elem(val), FlatSet::Elem(overflow))
+                        } else {
+                            (FlatSet::Elem(val.to_scalar()), FlatSet::Bottom)
+                        }
                     }
                     _ => (FlatSet::Top, FlatSet::Top),
                 }
@@ -475,7 +482,7 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> {
                         (FlatSet::Elem(arg_scalar), FlatSet::Bottom)
                     }
                     BinOp::Mul if layout.ty.is_integral() && arg_value == 0 => {
-                        (FlatSet::Elem(arg_scalar), FlatSet::Elem(false))
+                        (FlatSet::Elem(arg_scalar), FlatSet::Elem(Scalar::from_bool(false)))
                     }
                     _ => (FlatSet::Top, FlatSet::Top),
                 }
diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs
index 1f3e407180b..9d2e7153eb5 100644
--- a/compiler/rustc_mir_transform/src/gvn.rs
+++ b/compiler/rustc_mir_transform/src/gvn.rs
@@ -223,7 +223,7 @@ enum Value<'tcx> {
     NullaryOp(NullOp<'tcx>, Ty<'tcx>),
     UnaryOp(UnOp, VnIndex),
     BinaryOp(BinOp, VnIndex, VnIndex),
-    CheckedBinaryOp(BinOp, VnIndex, VnIndex),
+    CheckedBinaryOp(BinOp, VnIndex, VnIndex), // FIXME get rid of this, work like MIR instead
     Cast {
         kind: CastKind,
         value: VnIndex,
@@ -497,7 +497,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
             UnaryOp(un_op, operand) => {
                 let operand = self.evaluated[operand].as_ref()?;
                 let operand = self.ecx.read_immediate(operand).ok()?;
-                let (val, _) = self.ecx.overflowing_unary_op(un_op, &operand).ok()?;
+                let val = self.ecx.unary_op(un_op, &operand).ok()?;
                 val.into()
             }
             BinaryOp(bin_op, lhs, rhs) => {
@@ -505,7 +505,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
                 let lhs = self.ecx.read_immediate(lhs).ok()?;
                 let rhs = self.evaluated[rhs].as_ref()?;
                 let rhs = self.ecx.read_immediate(rhs).ok()?;
-                let (val, _) = self.ecx.overflowing_binary_op(bin_op, &lhs, &rhs).ok()?;
+                let val = self.ecx.binary_op(bin_op, &lhs, &rhs).ok()?;
                 val.into()
             }
             CheckedBinaryOp(bin_op, lhs, rhs) => {
@@ -513,14 +513,11 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
                 let lhs = self.ecx.read_immediate(lhs).ok()?;
                 let rhs = self.evaluated[rhs].as_ref()?;
                 let rhs = self.ecx.read_immediate(rhs).ok()?;
-                let (val, overflowed) = self.ecx.overflowing_binary_op(bin_op, &lhs, &rhs).ok()?;
-                let tuple = Ty::new_tup_from_iter(
-                    self.tcx,
-                    [val.layout.ty, self.tcx.types.bool].into_iter(),
-                );
-                let tuple = self.ecx.layout_of(tuple).ok()?;
-                ImmTy::from_scalar_pair(val.to_scalar(), Scalar::from_bool(overflowed), tuple)
-                    .into()
+                let val = self
+                    .ecx
+                    .binary_op(bin_op.wrapping_to_overflowing().unwrap(), &lhs, &rhs)
+                    .ok()?;
+                val.into()
             }
             Cast { kind, value, from: _, to } => match kind {
                 CastKind::IntToInt | CastKind::IntToFloat => {
diff --git a/compiler/rustc_mir_transform/src/known_panics_lint.rs b/compiler/rustc_mir_transform/src/known_panics_lint.rs
index 38fc37a3a31..0fa5c1b9126 100644
--- a/compiler/rustc_mir_transform/src/known_panics_lint.rs
+++ b/compiler/rustc_mir_transform/src/known_panics_lint.rs
@@ -304,20 +304,25 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
 
     fn check_unary_op(&mut self, op: UnOp, arg: &Operand<'tcx>, location: Location) -> Option<()> {
         let arg = self.eval_operand(arg)?;
-        if let (val, true) = self.use_ecx(|this| {
-            let val = this.ecx.read_immediate(&arg)?;
-            let (_res, overflow) = this.ecx.overflowing_unary_op(op, &val)?;
-            Ok((val, overflow))
-        })? {
-            // `AssertKind` only has an `OverflowNeg` variant, so make sure that is
-            // appropriate to use.
-            assert_eq!(op, UnOp::Neg, "Neg is the only UnOp that can overflow");
-            self.report_assert_as_lint(
-                location,
-                AssertLintKind::ArithmeticOverflow,
-                AssertKind::OverflowNeg(val.to_const_int()),
-            );
-            return None;
+        // The only operator that can overflow is `Neg`.
+        if op == UnOp::Neg && arg.layout.ty.is_integral() {
+            // Compute this as `0 - arg` so we can use `SubWithOverflow` to check for overflow.
+            let (arg, overflow) = self.use_ecx(|this| {
+                let arg = this.ecx.read_immediate(&arg)?;
+                let (_res, overflow) = this
+                    .ecx
+                    .binary_op(BinOp::SubWithOverflow, &ImmTy::from_int(0, arg.layout), &arg)?
+                    .to_scalar_pair();
+                Ok((arg, overflow.to_bool()?))
+            })?;
+            if overflow {
+                self.report_assert_as_lint(
+                    location,
+                    AssertLintKind::ArithmeticOverflow,
+                    AssertKind::OverflowNeg(arg.to_const_int()),
+                );
+                return None;
+            }
         }
 
         Some(())
@@ -363,11 +368,20 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
             }
         }
 
-        if let (Some(l), Some(r)) = (l, r) {
-            // The remaining operators are handled through `overflowing_binary_op`.
+        // Div/Rem are handled via the assertions they trigger.
+        // But for Add/Sub/Mul, those assertions only exist in debug builds, and we want to
+        // lint in release builds as well, so we check on the operation instead.
+        // So normalize to the "overflowing" operator, and then ensure that it
+        // actually is an overflowing operator.
+        let op = op.wrapping_to_overflowing().unwrap_or(op);
+        // The remaining operators are handled through `wrapping_to_overflowing`.
+        if let (Some(l), Some(r)) = (l, r)
+            && l.layout.ty.is_integral()
+            && op.is_overflowing()
+        {
             if self.use_ecx(|this| {
-                let (_res, overflow) = this.ecx.overflowing_binary_op(op, &l, &r)?;
-                Ok(overflow)
+                let (_res, overflow) = this.ecx.binary_op(op, &l, &r)?.to_scalar_pair();
+                overflow.to_bool()
             })? {
                 self.report_assert_as_lint(
                     location,
@@ -399,8 +413,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
             }
             Rvalue::BinaryOp(op, box (left, right)) => {
                 trace!("checking BinaryOp(op = {:?}, left = {:?}, right = {:?})", op, left, right);
-                let op = op.overflowing_to_wrapping().unwrap_or(*op);
-                self.check_binary_op(op, left, right, location)?;
+                self.check_binary_op(*op, left, right, location)?;
             }
 
             // Do not try creating references (#67862)
@@ -547,17 +560,15 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
                 let right = self.eval_operand(right)?;
                 let right = self.use_ecx(|this| this.ecx.read_immediate(&right))?;
 
-                if let Some(bin_op) = bin_op.overflowing_to_wrapping() {
-                    let (val, overflowed) =
-                        self.use_ecx(|this| this.ecx.overflowing_binary_op(bin_op, &left, &right))?;
-                    let overflowed = ImmTy::from_bool(overflowed, self.tcx);
+                let val = self.use_ecx(|this| this.ecx.binary_op(bin_op, &left, &right))?;
+                if matches!(val.layout.abi, Abi::ScalarPair(..)) {
+                    // FIXME `Value` should properly support pairs in `Immediate`... but currently it does not.
+                    let (val, overflow) = val.to_pair(&self.ecx);
                     Value::Aggregate {
                         variant: VariantIdx::ZERO,
-                        fields: [Value::from(val), overflowed.into()].into_iter().collect(),
+                        fields: [val.into(), overflow.into()].into_iter().collect(),
                     }
                 } else {
-                    let val =
-                        self.use_ecx(|this| this.ecx.wrapping_binary_op(bin_op, &left, &right))?;
                     val.into()
                 }
             }
@@ -566,7 +577,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
                 let operand = self.eval_operand(operand)?;
                 let val = self.use_ecx(|this| this.ecx.read_immediate(&operand))?;
 
-                let val = self.use_ecx(|this| this.ecx.wrapping_unary_op(un_op, &val))?;
+                let val = self.use_ecx(|this| this.ecx.unary_op(un_op, &val))?;
                 val.into()
             }
 
diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs
index 4b435649216..76972ff2263 100644
--- a/compiler/rustc_monomorphize/src/collector.rs
+++ b/compiler/rustc_monomorphize/src/collector.rs
@@ -236,6 +236,7 @@ use rustc_span::symbol::{sym, Ident};
 use rustc_span::{Span, DUMMY_SP};
 use rustc_target::abi::Size;
 use std::path::PathBuf;
+use tracing::{debug, instrument, trace};
 
 use crate::errors::{
     self, EncounteredErrorWhileInstantiating, NoOptimizedMir, RecursionLimit, TypeLengthLimit,
diff --git a/compiler/rustc_monomorphize/src/collector/move_check.rs b/compiler/rustc_monomorphize/src/collector/move_check.rs
index 4cc7275ab80..851f86e86b8 100644
--- a/compiler/rustc_monomorphize/src/collector/move_check.rs
+++ b/compiler/rustc_monomorphize/src/collector/move_check.rs
@@ -1,4 +1,5 @@
 use rustc_session::lint::builtin::LARGE_ASSIGNMENTS;
+use tracing::debug;
 
 use super::*;
 use crate::errors::LargeAssignmentsLint;
diff --git a/compiler/rustc_monomorphize/src/lib.rs b/compiler/rustc_monomorphize/src/lib.rs
index ddfb42a6f4a..b298fe5813f 100644
--- a/compiler/rustc_monomorphize/src/lib.rs
+++ b/compiler/rustc_monomorphize/src/lib.rs
@@ -2,9 +2,6 @@
 #![feature(is_sorted)]
 #![allow(rustc::potential_query_instability)]
 
-#[macro_use]
-extern crate tracing;
-
 use rustc_hir::lang_items::LangItem;
 use rustc_middle::bug;
 use rustc_middle::query::{Providers, TyCtxtAt};
diff --git a/compiler/rustc_monomorphize/src/partitioning.rs b/compiler/rustc_monomorphize/src/partitioning.rs
index 8f7b4c6472c..21d52004728 100644
--- a/compiler/rustc_monomorphize/src/partitioning.rs
+++ b/compiler/rustc_monomorphize/src/partitioning.rs
@@ -116,6 +116,7 @@ use rustc_middle::ty::{self, visit::TypeVisitableExt, InstanceDef, TyCtxt};
 use rustc_session::config::{DumpMonoStatsFormat, SwitchWithOptPath};
 use rustc_session::CodegenUnits;
 use rustc_span::symbol::Symbol;
+use tracing::debug;
 
 use crate::collector::UsageMap;
 use crate::collector::{self, MonoItemCollectionStrategy};
diff --git a/compiler/rustc_monomorphize/src/polymorphize.rs b/compiler/rustc_monomorphize/src/polymorphize.rs
index 14ebe27ac23..dc13766d145 100644
--- a/compiler/rustc_monomorphize/src/polymorphize.rs
+++ b/compiler/rustc_monomorphize/src/polymorphize.rs
@@ -18,6 +18,7 @@ use rustc_middle::ty::{
     GenericArgsRef, Ty, TyCtxt, UnusedGenericParams,
 };
 use rustc_span::symbol::sym;
+use tracing::{debug, instrument};
 
 use crate::errors::UnusedGenericParamsHint;
 
diff --git a/compiler/rustc_parse/src/lexer/mod.rs b/compiler/rustc_parse/src/lexer/mod.rs
index 6eb8bed6a8c..d3a6a033978 100644
--- a/compiler/rustc_parse/src/lexer/mod.rs
+++ b/compiler/rustc_parse/src/lexer/mod.rs
@@ -18,6 +18,7 @@ use rustc_session::lint::BuiltinLintDiag;
 use rustc_session::parse::ParseSess;
 use rustc_span::symbol::Symbol;
 use rustc_span::{edition::Edition, BytePos, Pos, Span};
+use tracing::debug;
 
 mod diagnostics;
 mod tokentrees;
diff --git a/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs b/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs
index fa242a32a18..cad25c66827 100644
--- a/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs
+++ b/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs
@@ -6,6 +6,7 @@ use std::ops::Range;
 use rustc_errors::{Applicability, DiagCtxt, ErrorGuaranteed};
 use rustc_lexer::unescape::{EscapeError, Mode};
 use rustc_span::{BytePos, Span};
+use tracing::debug;
 
 use crate::errors::{MoreThanOneCharNote, MoreThanOneCharSugg, NoBraceUnicodeSub, UnescapeError};
 
diff --git a/compiler/rustc_parse/src/lib.rs b/compiler/rustc_parse/src/lib.rs
index 0f973dfcd79..322739be3fb 100644
--- a/compiler/rustc_parse/src/lib.rs
+++ b/compiler/rustc_parse/src/lib.rs
@@ -10,9 +10,6 @@
 #![feature(iter_intersperse)]
 #![feature(let_chains)]
 
-#[macro_use]
-extern crate tracing;
-
 use rustc_ast as ast;
 use rustc_ast::token;
 use rustc_ast::tokenstream::TokenStream;
diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs
index ac12787f2ef..9677eea0604 100644
--- a/compiler/rustc_parse/src/parser/diagnostics.rs
+++ b/compiler/rustc_parse/src/parser/diagnostics.rs
@@ -45,6 +45,7 @@ use rustc_span::{BytePos, Span, SpanSnippetError, Symbol, DUMMY_SP};
 use std::mem::take;
 use std::ops::{Deref, DerefMut};
 use thin_vec::{thin_vec, ThinVec};
+use tracing::{debug, trace};
 
 /// Creates a placeholder argument.
 pub(super) fn dummy_arg(ident: Ident, guar: ErrorGuaranteed) -> Param {
diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs
index fd3f63a04de..1b99bc015b6 100644
--- a/compiler/rustc_parse/src/parser/expr.rs
+++ b/compiler/rustc_parse/src/parser/expr.rs
@@ -36,6 +36,7 @@ use rustc_span::source_map::{self, Spanned};
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
 use rustc_span::{BytePos, ErrorGuaranteed, Pos, Span};
 use thin_vec::{thin_vec, ThinVec};
+use tracing::instrument;
 
 /// Possibly accepts an `token::Interpolated` expression (a pre-parsed expression
 /// dropped into the token stream, which happens while parsing the result of
diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs
index f43ddadc2ea..53757c38e8b 100644
--- a/compiler/rustc_parse/src/parser/item.rs
+++ b/compiler/rustc_parse/src/parser/item.rs
@@ -23,6 +23,7 @@ use rustc_span::{Span, DUMMY_SP};
 use std::fmt::Write;
 use std::mem;
 use thin_vec::{thin_vec, ThinVec};
+use tracing::debug;
 
 impl<'a> Parser<'a> {
     /// Parses a source module as a crate. This is the main entry point for the parser.
diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs
index 1924533e280..4fe84b91b8b 100644
--- a/compiler/rustc_passes/src/check_attr.rs
+++ b/compiler/rustc_passes/src/check_attr.rs
@@ -39,6 +39,7 @@ use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt;
 use rustc_trait_selection::traits::ObligationCtxt;
 use std::cell::Cell;
 use std::collections::hash_map::Entry;
+use tracing::debug;
 
 #[derive(LintDiagnostic)]
 #[diag(passes_diagnostic_diagnostic_on_unimplemented_only_for_traits)]
diff --git a/compiler/rustc_passes/src/diagnostic_items.rs b/compiler/rustc_passes/src/diagnostic_items.rs
index 906ecdfe5ab..78653e5f95a 100644
--- a/compiler/rustc_passes/src/diagnostic_items.rs
+++ b/compiler/rustc_passes/src/diagnostic_items.rs
@@ -82,7 +82,7 @@ fn all_diagnostic_items(tcx: TyCtxt<'_>, (): ()) -> DiagnosticItems {
     let mut items = DiagnosticItems::default();
 
     // Collect diagnostic items in other crates.
-    for &cnum in tcx.crates(()).iter().chain(std::iter::once(&LOCAL_CRATE)) {
+    for &cnum in tcx.crates_including_speculative(()).iter().chain(std::iter::once(&LOCAL_CRATE)) {
         for (&name, &def_id) in &tcx.diagnostic_items(cnum).name_to_id {
             collect_item(tcx, &mut items, name, def_id);
         }
diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs
index 180552785fe..7fdd9924b51 100644
--- a/compiler/rustc_passes/src/errors.rs
+++ b/compiler/rustc_passes/src/errors.rs
@@ -1100,7 +1100,7 @@ pub struct BreakInsideCoroutine<'a> {
 pub struct OutsideLoop<'a> {
     #[primary_span]
     #[label]
-    pub span: Span,
+    pub spans: Vec<Span>,
     pub name: &'a str,
     pub is_break: bool,
     #[subdiagnostic]
@@ -1112,7 +1112,7 @@ pub struct OutsideLoopSuggestion {
     #[suggestion_part(code = "'block: ")]
     pub block_span: Span,
     #[suggestion_part(code = " 'block")]
-    pub break_span: Span,
+    pub break_spans: Vec<Span>,
 }
 
 #[derive(Diagnostic)]
diff --git a/compiler/rustc_passes/src/lib.rs b/compiler/rustc_passes/src/lib.rs
index d3608759eec..045a0a1525b 100644
--- a/compiler/rustc_passes/src/lib.rs
+++ b/compiler/rustc_passes/src/lib.rs
@@ -12,9 +12,6 @@
 #![feature(map_try_insert)]
 #![feature(try_blocks)]
 
-#[macro_use]
-extern crate tracing;
-
 use rustc_middle::query::Providers;
 
 pub mod abi_test;
diff --git a/compiler/rustc_passes/src/liveness.rs b/compiler/rustc_passes/src/liveness.rs
index b50cb158b1f..b0a753604e2 100644
--- a/compiler/rustc_passes/src/liveness.rs
+++ b/compiler/rustc_passes/src/liveness.rs
@@ -99,10 +99,10 @@ use rustc_middle::ty::{self, RootVariableMinCaptureList, Ty, TyCtxt};
 use rustc_session::lint;
 use rustc_span::symbol::{kw, sym, Symbol};
 use rustc_span::{BytePos, Span};
-
 use std::io;
 use std::io::prelude::*;
 use std::rc::Rc;
+use tracing::{debug, instrument};
 
 mod rwu_table;
 
diff --git a/compiler/rustc_passes/src/loops.rs b/compiler/rustc_passes/src/loops.rs
index 3b20112eab7..2587a18b8c8 100644
--- a/compiler/rustc_passes/src/loops.rs
+++ b/compiler/rustc_passes/src/loops.rs
@@ -1,3 +1,5 @@
+use std::collections::BTreeMap;
+use std::fmt;
 use Context::*;
 
 use rustc_hir as hir;
@@ -25,22 +27,55 @@ enum Context {
     Closure(Span),
     Coroutine { coroutine_span: Span, kind: hir::CoroutineDesugaring, source: hir::CoroutineSource },
     UnlabeledBlock(Span),
+    UnlabeledIfBlock(Span),
     LabeledBlock,
     Constant,
 }
 
-#[derive(Copy, Clone)]
+#[derive(Clone)]
+struct BlockInfo {
+    name: String,
+    spans: Vec<Span>,
+    suggs: Vec<Span>,
+}
+
+#[derive(PartialEq)]
+enum BreakContextKind {
+    Break,
+    Continue,
+}
+
+impl fmt::Display for BreakContextKind {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        match self {
+            BreakContextKind::Break => "break",
+            BreakContextKind::Continue => "continue",
+        }
+        .fmt(f)
+    }
+}
+
+#[derive(Clone)]
 struct CheckLoopVisitor<'a, 'tcx> {
     sess: &'a Session,
     tcx: TyCtxt<'tcx>,
-    cx: Context,
+    // Keep track of a stack of contexts, so that suggestions
+    // are not made for contexts where it would be incorrect,
+    // such as adding a label for an `if`.
+    // e.g. `if 'foo: {}` would be incorrect.
+    cx_stack: Vec<Context>,
+    block_breaks: BTreeMap<Span, BlockInfo>,
 }
 
 fn check_mod_loops(tcx: TyCtxt<'_>, module_def_id: LocalModDefId) {
-    tcx.hir().visit_item_likes_in_module(
-        module_def_id,
-        &mut CheckLoopVisitor { sess: tcx.sess, tcx, cx: Normal },
-    );
+    let mut check = CheckLoopVisitor {
+        sess: tcx.sess,
+        tcx,
+        cx_stack: vec![Normal],
+        block_breaks: Default::default(),
+    };
+    tcx.hir().visit_item_likes_in_module(module_def_id, &mut check);
+    check.report_outside_loop_error();
 }
 
 pub(crate) fn provide(providers: &mut Providers) {
@@ -83,6 +118,45 @@ impl<'a, 'hir> Visitor<'hir> for CheckLoopVisitor<'a, 'hir> {
 
     fn visit_expr(&mut self, e: &'hir hir::Expr<'hir>) {
         match e.kind {
+            hir::ExprKind::If(cond, then, else_opt) => {
+                self.visit_expr(cond);
+
+                let get_block = |ck_loop: &CheckLoopVisitor<'a, 'hir>,
+                                 expr: &hir::Expr<'hir>|
+                 -> Option<&hir::Block<'hir>> {
+                    if let hir::ExprKind::Block(b, None) = expr.kind
+                        && matches!(
+                            ck_loop.cx_stack.last(),
+                            Some(&Normal)
+                                | Some(&Constant)
+                                | Some(&UnlabeledBlock(_))
+                                | Some(&UnlabeledIfBlock(_))
+                        )
+                    {
+                        Some(b)
+                    } else {
+                        None
+                    }
+                };
+
+                if let Some(b) = get_block(self, then) {
+                    self.with_context(UnlabeledIfBlock(b.span.shrink_to_lo()), |v| {
+                        v.visit_block(b)
+                    });
+                } else {
+                    self.visit_expr(then);
+                }
+
+                if let Some(else_expr) = else_opt {
+                    if let Some(b) = get_block(self, else_expr) {
+                        self.with_context(UnlabeledIfBlock(b.span.shrink_to_lo()), |v| {
+                            v.visit_block(b)
+                        });
+                    } else {
+                        self.visit_expr(else_expr);
+                    }
+                }
+            }
             hir::ExprKind::Loop(ref b, _, source, _) => {
                 self.with_context(Loop(source), |v| v.visit_block(b));
             }
@@ -101,11 +175,14 @@ impl<'a, 'hir> Visitor<'hir> for CheckLoopVisitor<'a, 'hir> {
             hir::ExprKind::Block(ref b, Some(_label)) => {
                 self.with_context(LabeledBlock, |v| v.visit_block(b));
             }
-            hir::ExprKind::Block(ref b, None) if matches!(self.cx, Fn) => {
+            hir::ExprKind::Block(ref b, None) if matches!(self.cx_stack.last(), Some(&Fn)) => {
                 self.with_context(Normal, |v| v.visit_block(b));
             }
             hir::ExprKind::Block(ref b, None)
-                if matches!(self.cx, Normal | Constant | UnlabeledBlock(_)) =>
+                if matches!(
+                    self.cx_stack.last(),
+                    Some(&Normal) | Some(&Constant) | Some(&UnlabeledBlock(_))
+                ) =>
             {
                 self.with_context(UnlabeledBlock(b.span.shrink_to_lo()), |v| v.visit_block(b));
             }
@@ -178,7 +255,12 @@ impl<'a, 'hir> Visitor<'hir> for CheckLoopVisitor<'a, 'hir> {
                     Some(label) => sp_lo.with_hi(label.ident.span.hi()),
                     None => sp_lo.shrink_to_lo(),
                 };
-                self.require_break_cx("break", e.span, label_sp);
+                self.require_break_cx(
+                    BreakContextKind::Break,
+                    e.span,
+                    label_sp,
+                    self.cx_stack.len() - 1,
+                );
             }
             hir::ExprKind::Continue(destination) => {
                 self.require_label_in_labeled_block(e.span, &destination, "continue");
@@ -200,7 +282,12 @@ impl<'a, 'hir> Visitor<'hir> for CheckLoopVisitor<'a, 'hir> {
                     }
                     Err(_) => {}
                 }
-                self.require_break_cx("continue", e.span, e.span)
+                self.require_break_cx(
+                    BreakContextKind::Continue,
+                    e.span,
+                    e.span,
+                    self.cx_stack.len() - 1,
+                )
             }
             _ => intravisit::walk_expr(self, e),
         }
@@ -212,18 +299,26 @@ impl<'a, 'hir> CheckLoopVisitor<'a, 'hir> {
     where
         F: FnOnce(&mut CheckLoopVisitor<'a, 'hir>),
     {
-        let old_cx = self.cx;
-        self.cx = cx;
+        self.cx_stack.push(cx);
         f(self);
-        self.cx = old_cx;
+        self.cx_stack.pop();
     }
 
-    fn require_break_cx(&self, name: &str, span: Span, break_span: Span) {
-        let is_break = name == "break";
-        match self.cx {
+    fn require_break_cx(
+        &mut self,
+        br_cx_kind: BreakContextKind,
+        span: Span,
+        break_span: Span,
+        cx_pos: usize,
+    ) {
+        match self.cx_stack[cx_pos] {
             LabeledBlock | Loop(_) => {}
             Closure(closure_span) => {
-                self.sess.dcx().emit_err(BreakInsideClosure { span, closure_span, name });
+                self.sess.dcx().emit_err(BreakInsideClosure {
+                    span,
+                    closure_span,
+                    name: &br_cx_kind.to_string(),
+                });
             }
             Coroutine { coroutine_span, kind, source } => {
                 let kind = match kind {
@@ -239,17 +334,32 @@ impl<'a, 'hir> CheckLoopVisitor<'a, 'hir> {
                 self.sess.dcx().emit_err(BreakInsideCoroutine {
                     span,
                     coroutine_span,
-                    name,
+                    name: &br_cx_kind.to_string(),
                     kind,
                     source,
                 });
             }
-            UnlabeledBlock(block_span) if is_break && block_span.eq_ctxt(break_span) => {
-                let suggestion = Some(OutsideLoopSuggestion { block_span, break_span });
-                self.sess.dcx().emit_err(OutsideLoop { span, name, is_break, suggestion });
+            UnlabeledBlock(block_span)
+                if br_cx_kind == BreakContextKind::Break && block_span.eq_ctxt(break_span) =>
+            {
+                let block = self.block_breaks.entry(block_span).or_insert_with(|| BlockInfo {
+                    name: br_cx_kind.to_string(),
+                    spans: vec![],
+                    suggs: vec![],
+                });
+                block.spans.push(span);
+                block.suggs.push(break_span);
+            }
+            UnlabeledIfBlock(_) if br_cx_kind == BreakContextKind::Break => {
+                self.require_break_cx(br_cx_kind, span, break_span, cx_pos - 1);
             }
-            Normal | Constant | Fn | UnlabeledBlock(_) => {
-                self.sess.dcx().emit_err(OutsideLoop { span, name, is_break, suggestion: None });
+            Normal | Constant | Fn | UnlabeledBlock(_) | UnlabeledIfBlock(_) => {
+                self.sess.dcx().emit_err(OutsideLoop {
+                    spans: vec![span],
+                    name: &br_cx_kind.to_string(),
+                    is_break: br_cx_kind == BreakContextKind::Break,
+                    suggestion: None,
+                });
             }
         }
     }
@@ -261,7 +371,7 @@ impl<'a, 'hir> CheckLoopVisitor<'a, 'hir> {
         cf_type: &str,
     ) -> bool {
         if !span.is_desugaring(DesugaringKind::QuestionMark)
-            && self.cx == LabeledBlock
+            && self.cx_stack.last() == Some(&LabeledBlock)
             && label.label.is_none()
         {
             self.sess.dcx().emit_err(UnlabeledInLabeledBlock { span, cf_type });
@@ -269,4 +379,18 @@ impl<'a, 'hir> CheckLoopVisitor<'a, 'hir> {
         }
         false
     }
+
+    fn report_outside_loop_error(&mut self) {
+        for (s, block) in &self.block_breaks {
+            self.sess.dcx().emit_err(OutsideLoop {
+                spans: block.spans.clone(),
+                name: &block.name,
+                is_break: true,
+                suggestion: Some(OutsideLoopSuggestion {
+                    block_span: *s,
+                    break_spans: block.suggs.clone(),
+                }),
+            });
+        }
+    }
 }
diff --git a/compiler/rustc_passes/src/reachable.rs b/compiler/rustc_passes/src/reachable.rs
index 55b7c6dce4d..ab1dd248556 100644
--- a/compiler/rustc_passes/src/reachable.rs
+++ b/compiler/rustc_passes/src/reachable.rs
@@ -37,6 +37,7 @@ use rustc_middle::query::Providers;
 use rustc_middle::ty::{self, ExistentialTraitRef, TyCtxt};
 use rustc_privacy::DefIdVisitor;
 use rustc_session::config::CrateType;
+use tracing::debug;
 
 /// Determines whether this item is recursive for reachability. See `is_recursively_reachable_local`
 /// below for details.
diff --git a/compiler/rustc_passes/src/stability.rs b/compiler/rustc_passes/src/stability.rs
index 05c833cdfb6..31c709f2eb6 100644
--- a/compiler/rustc_passes/src/stability.rs
+++ b/compiler/rustc_passes/src/stability.rs
@@ -25,9 +25,9 @@ use rustc_session::lint::builtin::{INEFFECTIVE_UNSTABLE_TRAIT_IMPL, USELESS_DEPR
 use rustc_span::symbol::{sym, Symbol};
 use rustc_span::Span;
 use rustc_target::spec::abi::Abi;
-
 use std::mem::replace;
 use std::num::NonZero;
+use tracing::{debug, info};
 
 #[derive(PartialEq)]
 enum AnnotationKind {
@@ -1020,7 +1020,7 @@ pub fn check_unused_or_stable_features(tcx: TyCtxt<'_>) {
         // stabilization diagnostic, but it can be avoided when there are no
         // `remaining_lib_features`.
         let mut all_implications = remaining_implications.clone();
-        for &cnum in tcx.crates(()) {
+        for &cnum in tcx.used_crates(()) {
             all_implications
                 .extend_unord(tcx.stability_implications(cnum).items().map(|(k, v)| (*k, *v)));
         }
@@ -1033,7 +1033,7 @@ pub fn check_unused_or_stable_features(tcx: TyCtxt<'_>) {
             &all_implications,
         );
 
-        for &cnum in tcx.crates(()) {
+        for &cnum in tcx.used_crates(()) {
             if remaining_lib_features.is_empty() && remaining_implications.is_empty() {
                 break;
             }
diff --git a/compiler/rustc_passes/src/weak_lang_items.rs b/compiler/rustc_passes/src/weak_lang_items.rs
index 90691ca1790..d80addf1236 100644
--- a/compiler/rustc_passes/src/weak_lang_items.rs
+++ b/compiler/rustc_passes/src/weak_lang_items.rs
@@ -68,7 +68,7 @@ fn verify(tcx: TyCtxt<'_>, items: &lang_items::LanguageItems) {
     }
 
     let mut missing = FxHashSet::default();
-    for &cnum in tcx.crates(()).iter() {
+    for &cnum in tcx.used_crates(()).iter() {
         for &item in tcx.missing_lang_items(cnum).iter() {
             missing.insert(item);
         }
diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs
index d1d0e336cfe..63d0d6c260d 100644
--- a/compiler/rustc_resolve/src/late.rs
+++ b/compiler/rustc_resolve/src/late.rs
@@ -12,7 +12,7 @@ use crate::{Module, ModuleOrUniformRoot, NameBinding, ParentScope, PathResult};
 use crate::{ResolutionError, Resolver, Segment, UseError};
 
 use rustc_ast::ptr::P;
-use rustc_ast::visit::{walk_list, AssocCtxt, BoundKind, FnCtxt, FnKind, Visitor};
+use rustc_ast::visit::{visit_opt, walk_list, AssocCtxt, BoundKind, FnCtxt, FnKind, Visitor};
 use rustc_ast::*;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap};
 use rustc_errors::{codes::*, Applicability, DiagArgValue, IntoDiagArg, StashKey};
@@ -3280,7 +3280,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
     fn resolve_local(&mut self, local: &'ast Local) {
         debug!("resolving local ({:?})", local);
         // Resolve the type.
-        walk_list!(self, visit_ty, &local.ty);
+        visit_opt!(self, visit_ty, &local.ty);
 
         // Resolve the initializer.
         if let Some((init, els)) = local.kind.init_else_opt() {
@@ -3479,8 +3479,8 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
     fn resolve_arm(&mut self, arm: &'ast Arm) {
         self.with_rib(ValueNS, RibKind::Normal, |this| {
             this.resolve_pattern_top(&arm.pat, PatternSource::Match);
-            walk_list!(this, visit_expr, &arm.guard);
-            walk_list!(this, visit_expr, &arm.body);
+            visit_opt!(this, visit_expr, &arm.guard);
+            visit_opt!(this, visit_expr, &arm.body);
         });
     }
 
diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs
index 7dd9fdf60f9..5ac4d194e87 100644
--- a/compiler/rustc_session/src/config.rs
+++ b/compiler/rustc_session/src/config.rs
@@ -465,6 +465,7 @@ impl FromStr for SplitDwarfKind {
 #[derive(Encodable, Decodable)]
 pub enum OutputType {
     Bitcode,
+    ThinLinkBitcode,
     Assembly,
     LlvmAssembly,
     Mir,
@@ -492,6 +493,7 @@ impl OutputType {
         match *self {
             OutputType::Exe | OutputType::DepInfo | OutputType::Metadata => true,
             OutputType::Bitcode
+            | OutputType::ThinLinkBitcode
             | OutputType::Assembly
             | OutputType::LlvmAssembly
             | OutputType::Mir
@@ -502,6 +504,7 @@ impl OutputType {
     pub fn shorthand(&self) -> &'static str {
         match *self {
             OutputType::Bitcode => "llvm-bc",
+            OutputType::ThinLinkBitcode => "thin-link-bitcode",
             OutputType::Assembly => "asm",
             OutputType::LlvmAssembly => "llvm-ir",
             OutputType::Mir => "mir",
@@ -518,6 +521,7 @@ impl OutputType {
             "llvm-ir" => OutputType::LlvmAssembly,
             "mir" => OutputType::Mir,
             "llvm-bc" => OutputType::Bitcode,
+            "thin-link-bitcode" => OutputType::ThinLinkBitcode,
             "obj" => OutputType::Object,
             "metadata" => OutputType::Metadata,
             "link" => OutputType::Exe,
@@ -528,8 +532,9 @@ impl OutputType {
 
     fn shorthands_display() -> String {
         format!(
-            "`{}`, `{}`, `{}`, `{}`, `{}`, `{}`, `{}`, `{}`",
+            "`{}`, `{}`, `{}`, `{}`, `{}`, `{}`, `{}`, `{}`, `{}`",
             OutputType::Bitcode.shorthand(),
+            OutputType::ThinLinkBitcode.shorthand(),
             OutputType::Assembly.shorthand(),
             OutputType::LlvmAssembly.shorthand(),
             OutputType::Mir.shorthand(),
@@ -543,6 +548,7 @@ impl OutputType {
     pub fn extension(&self) -> &'static str {
         match *self {
             OutputType::Bitcode => "bc",
+            OutputType::ThinLinkBitcode => "indexing.o",
             OutputType::Assembly => "s",
             OutputType::LlvmAssembly => "ll",
             OutputType::Mir => "mir",
@@ -559,9 +565,11 @@ impl OutputType {
             | OutputType::LlvmAssembly
             | OutputType::Mir
             | OutputType::DepInfo => true,
-            OutputType::Bitcode | OutputType::Object | OutputType::Metadata | OutputType::Exe => {
-                false
-            }
+            OutputType::Bitcode
+            | OutputType::ThinLinkBitcode
+            | OutputType::Object
+            | OutputType::Metadata
+            | OutputType::Exe => false,
         }
     }
 }
@@ -644,6 +652,7 @@ impl OutputTypes {
     pub fn should_codegen(&self) -> bool {
         self.0.keys().any(|k| match *k {
             OutputType::Bitcode
+            | OutputType::ThinLinkBitcode
             | OutputType::Assembly
             | OutputType::LlvmAssembly
             | OutputType::Mir
@@ -657,6 +666,7 @@ impl OutputTypes {
     pub fn should_link(&self) -> bool {
         self.0.keys().any(|k| match *k {
             OutputType::Bitcode
+            | OutputType::ThinLinkBitcode
             | OutputType::Assembly
             | OutputType::LlvmAssembly
             | OutputType::Mir
@@ -1769,6 +1779,12 @@ fn parse_output_types(
                         display = OutputType::shorthands_display(),
                     ))
                 });
+                if output_type == OutputType::ThinLinkBitcode && !unstable_opts.unstable_options {
+                    early_dcx.early_fatal(format!(
+                        "{} requested but -Zunstable-options not specified",
+                        OutputType::ThinLinkBitcode.shorthand()
+                    ));
+                }
                 output_types.insert(output_type, path);
             }
         }
diff --git a/compiler/rustc_session/src/filesearch.rs b/compiler/rustc_session/src/filesearch.rs
index f4e2436efb9..9cb8cd836e6 100644
--- a/compiler/rustc_session/src/filesearch.rs
+++ b/compiler/rustc_session/src/filesearch.rs
@@ -51,6 +51,14 @@ pub fn make_target_lib_path(sysroot: &Path, target_triple: &str) -> PathBuf {
     PathBuf::from_iter([sysroot, Path::new(&rustlib_path), Path::new("lib")])
 }
 
+/// Returns a path to the target's `bin` folder within its `rustlib` path in the sysroot. This is
+/// where binaries are usually installed, e.g. the self-contained linkers, lld-wrappers, LLVM tools,
+/// etc.
+pub fn make_target_bin_path(sysroot: &Path, target_triple: &str) -> PathBuf {
+    let rustlib_path = rustc_target::target_rustlib_path(sysroot, target_triple);
+    PathBuf::from_iter([sysroot, Path::new(&rustlib_path), Path::new("bin")])
+}
+
 #[cfg(unix)]
 fn current_dll_path() -> Result<PathBuf, String> {
     use std::ffi::{CStr, OsStr};
diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs
index a2872fc1661..a5cf136db6a 100644
--- a/compiler/rustc_session/src/session.rs
+++ b/compiler/rustc_session/src/session.rs
@@ -449,15 +449,24 @@ impl Session {
         )
     }
 
-    /// Returns a list of directories where target-specific tool binaries are located.
+    /// Returns a list of directories where target-specific tool binaries are located. Some fallback
+    /// directories are also returned, for example if `--sysroot` is used but tools are missing
+    /// (#125246): we also add the bin directories to the sysroot where rustc is located.
     pub fn get_tools_search_paths(&self, self_contained: bool) -> Vec<PathBuf> {
-        let rustlib_path = rustc_target::target_rustlib_path(&self.sysroot, config::host_triple());
-        let p = PathBuf::from_iter([
-            Path::new(&self.sysroot),
-            Path::new(&rustlib_path),
-            Path::new("bin"),
-        ]);
-        if self_contained { vec![p.clone(), p.join("self-contained")] } else { vec![p] }
+        let bin_path = filesearch::make_target_bin_path(&self.sysroot, config::host_triple());
+        let fallback_sysroot_paths = filesearch::sysroot_candidates()
+            .into_iter()
+            .map(|sysroot| filesearch::make_target_bin_path(&sysroot, config::host_triple()));
+        let search_paths = std::iter::once(bin_path).chain(fallback_sysroot_paths);
+
+        if self_contained {
+            // The self-contained tools are expected to be e.g. in `bin/self-contained` in the
+            // sysroot's `rustlib` path, so we add such a subfolder to the bin path, and the
+            // fallback paths.
+            search_paths.flat_map(|path| [path.clone(), path.join("self-contained")]).collect()
+        } else {
+            search_paths.collect()
+        }
     }
 
     pub fn init_incr_comp_session(&self, session_dir: PathBuf, lock_file: flock::Lock) {
diff --git a/compiler/rustc_smir/src/rustc_smir/context.rs b/compiler/rustc_smir/src/rustc_smir/context.rs
index fd31c020f89..7afe46f2cbe 100644
--- a/compiler/rustc_smir/src/rustc_smir/context.rs
+++ b/compiler/rustc_smir/src/rustc_smir/context.rs
@@ -23,8 +23,8 @@ use stable_mir::mir::{BinOp, Body, Place};
 use stable_mir::target::{MachineInfo, MachineSize};
 use stable_mir::ty::{
     AdtDef, AdtKind, Allocation, ClosureDef, ClosureKind, Const, FieldDef, FnDef, ForeignDef,
-    ForeignItemKind, GenericArgs, LineInfo, PolyFnSig, RigidTy, Span, Ty, TyKind, UintTy,
-    VariantDef,
+    ForeignItemKind, GenericArgs, IntrinsicDef, LineInfo, PolyFnSig, RigidTy, Span, Ty, TyKind,
+    UintTy, VariantDef,
 };
 use stable_mir::{Crate, CrateDef, CrateItem, CrateNum, DefId, Error, Filename, ItemKind, Symbol};
 use std::cell::RefCell;
@@ -126,7 +126,7 @@ impl<'tcx> Context for TablesWrapper<'tcx> {
         let mut tables = self.0.borrow_mut();
         let tcx = tables.tcx;
         iter::once(LOCAL_CRATE)
-            .chain(tables.tcx.crates(()).iter().copied())
+            .chain(tables.tcx.used_crates(()).iter().copied())
             .flat_map(|cnum| tcx.trait_impls_in_crate(cnum).iter())
             .map(|impl_def_id| tables.impl_def(*impl_def_id))
             .collect()
@@ -201,14 +201,19 @@ impl<'tcx> Context for TablesWrapper<'tcx> {
 
     fn external_crates(&self) -> Vec<stable_mir::Crate> {
         let tables = self.0.borrow();
-        tables.tcx.crates(()).iter().map(|crate_num| smir_crate(tables.tcx, *crate_num)).collect()
+        tables
+            .tcx
+            .used_crates(())
+            .iter()
+            .map(|crate_num| smir_crate(tables.tcx, *crate_num))
+            .collect()
     }
 
     fn find_crates(&self, name: &str) -> Vec<stable_mir::Crate> {
         let tables = self.0.borrow();
         let crates: Vec<stable_mir::Crate> = [LOCAL_CRATE]
             .iter()
-            .chain(tables.tcx.crates(()).iter())
+            .chain(tables.tcx.used_crates(()).iter())
             .filter_map(|crate_num| {
                 let crate_name = tables.tcx.crate_name(*crate_num).to_string();
                 (name == crate_name).then(|| smir_crate(tables.tcx, *crate_num))
@@ -307,6 +312,28 @@ impl<'tcx> Context for TablesWrapper<'tcx> {
         sig.stable(&mut *tables)
     }
 
+    fn intrinsic(&self, def: DefId) -> Option<IntrinsicDef> {
+        let mut tables = self.0.borrow_mut();
+        let tcx = tables.tcx;
+        let def_id = def.internal(&mut *tables, tcx);
+        let intrinsic = tcx.intrinsic_raw(def_id);
+        intrinsic.map(|_| IntrinsicDef(def))
+    }
+
+    fn intrinsic_name(&self, def: IntrinsicDef) -> Symbol {
+        let mut tables = self.0.borrow_mut();
+        let tcx = tables.tcx;
+        let def_id = def.0.internal(&mut *tables, tcx);
+        tcx.intrinsic(def_id).unwrap().name.to_string()
+    }
+
+    fn intrinsic_must_be_overridden(&self, def: IntrinsicDef) -> bool {
+        let mut tables = self.0.borrow_mut();
+        let tcx = tables.tcx;
+        let def_id = def.0.internal(&mut *tables, tcx);
+        tcx.intrinsic_raw(def_id).unwrap().must_be_overridden
+    }
+
     fn closure_sig(&self, args: &GenericArgs) -> PolyFnSig {
         let mut tables = self.0.borrow_mut();
         let tcx = tables.tcx;
@@ -645,16 +672,6 @@ impl<'tcx> Context for TablesWrapper<'tcx> {
         }
     }
 
-    /// Retrieve the plain intrinsic name of an instance.
-    ///
-    /// This assumes that the instance is an intrinsic.
-    fn intrinsic_name(&self, def: InstanceDef) -> Symbol {
-        let tables = self.0.borrow_mut();
-        let instance = tables.instances[def];
-        let intrinsic = tables.tcx.intrinsic(instance.def_id()).unwrap();
-        intrinsic.name.to_string()
-    }
-
     fn ty_layout(&self, ty: Ty) -> Result<Layout, Error> {
         let mut tables = self.0.borrow_mut();
         let tcx = tables.tcx;
diff --git a/compiler/rustc_ty_utils/src/abi.rs b/compiler/rustc_ty_utils/src/abi.rs
index 9090bb30f89..6f513f24948 100644
--- a/compiler/rustc_ty_utils/src/abi.rs
+++ b/compiler/rustc_ty_utils/src/abi.rs
@@ -14,6 +14,7 @@ use rustc_target::abi::call::{
 };
 use rustc_target::abi::*;
 use rustc_target::spec::abi::Abi as SpecAbi;
+use tracing::debug;
 
 use std::iter;
 
diff --git a/compiler/rustc_ty_utils/src/consts.rs b/compiler/rustc_ty_utils/src/consts.rs
index b40a0d0a58e..67ffb8a58b5 100644
--- a/compiler/rustc_ty_utils/src/consts.rs
+++ b/compiler/rustc_ty_utils/src/consts.rs
@@ -11,6 +11,7 @@ use rustc_middle::ty::{self, Expr, TyCtxt, TypeVisitableExt};
 use rustc_middle::{mir, thir};
 use rustc_span::Span;
 use rustc_target::abi::{VariantIdx, FIRST_VARIANT};
+use tracing::{debug, instrument};
 
 use std::iter;
 
diff --git a/compiler/rustc_ty_utils/src/instance.rs b/compiler/rustc_ty_utils/src/instance.rs
index 41f482d8a70..0d089205c1e 100644
--- a/compiler/rustc_ty_utils/src/instance.rs
+++ b/compiler/rustc_ty_utils/src/instance.rs
@@ -9,6 +9,7 @@ use rustc_middle::ty::{self, Instance, TyCtxt, TypeVisitableExt};
 use rustc_span::sym;
 use rustc_trait_selection::traits;
 use rustc_type_ir::ClosureKind;
+use tracing::debug;
 use traits::{translate_args, Reveal};
 
 use crate::errors::UnexpectedFnPtrAssociatedItem;
diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs
index 1ef22497a8f..1dee14fae57 100644
--- a/compiler/rustc_ty_utils/src/layout.rs
+++ b/compiler/rustc_ty_utils/src/layout.rs
@@ -16,6 +16,7 @@ use rustc_session::{DataTypeKind, FieldInfo, FieldKind, SizeKind, VariantInfo};
 use rustc_span::sym;
 use rustc_span::symbol::Symbol;
 use rustc_target::abi::*;
+use tracing::{debug, instrument, trace};
 
 use std::fmt::Debug;
 use std::iter;
diff --git a/compiler/rustc_ty_utils/src/lib.rs b/compiler/rustc_ty_utils/src/lib.rs
index e8c5c54d3a0..bd89265d942 100644
--- a/compiler/rustc_ty_utils/src/lib.rs
+++ b/compiler/rustc_ty_utils/src/lib.rs
@@ -16,9 +16,6 @@
 #![feature(let_chains)]
 #![feature(never_type)]
 
-#[macro_use]
-extern crate tracing;
-
 use rustc_middle::query::Providers;
 
 mod abi;
diff --git a/compiler/rustc_ty_utils/src/needs_drop.rs b/compiler/rustc_ty_utils/src/needs_drop.rs
index 4e23fb30383..72ee1a48249 100644
--- a/compiler/rustc_ty_utils/src/needs_drop.rs
+++ b/compiler/rustc_ty_utils/src/needs_drop.rs
@@ -9,6 +9,7 @@ use rustc_middle::ty::GenericArgsRef;
 use rustc_middle::ty::{self, EarlyBinder, Ty, TyCtxt};
 use rustc_session::Limit;
 use rustc_span::sym;
+use tracing::debug;
 
 use crate::errors::NeedsDropOverflow;
 
diff --git a/compiler/rustc_ty_utils/src/opaque_types.rs b/compiler/rustc_ty_utils/src/opaque_types.rs
index be227ec8b9a..ccc522053a6 100644
--- a/compiler/rustc_ty_utils/src/opaque_types.rs
+++ b/compiler/rustc_ty_utils/src/opaque_types.rs
@@ -8,6 +8,7 @@ use rustc_middle::ty::util::{CheckRegions, NotUniqueParam};
 use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_middle::ty::{TypeSuperVisitable, TypeVisitable, TypeVisitor};
 use rustc_span::Span;
+use tracing::{instrument, trace};
 
 use crate::errors::{DuplicateArg, NotParam};
 
diff --git a/compiler/rustc_ty_utils/src/sig_types.rs b/compiler/rustc_ty_utils/src/sig_types.rs
index 2d8c78267d9..97a1b94263e 100644
--- a/compiler/rustc_ty_utils/src/sig_types.rs
+++ b/compiler/rustc_ty_utils/src/sig_types.rs
@@ -8,6 +8,7 @@ use rustc_middle::span_bug;
 use rustc_middle::ty::{self, TyCtxt};
 use rustc_span::Span;
 use rustc_type_ir::visit::TypeVisitable;
+use tracing::{instrument, trace};
 
 pub trait SpannedTypeVisitor<'tcx> {
     type Result: VisitorResult = ();
diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs
index 3094956fa5f..617e8a54365 100644
--- a/compiler/rustc_ty_utils/src/ty.rs
+++ b/compiler/rustc_ty_utils/src/ty.rs
@@ -10,6 +10,7 @@ use rustc_middle::ty::{TypeSuperVisitable, TypeVisitable, Upcast};
 use rustc_span::def_id::{DefId, LocalDefId, CRATE_DEF_ID};
 use rustc_span::DUMMY_SP;
 use rustc_trait_selection::traits;
+use tracing::{debug, instrument};
 
 #[instrument(level = "debug", skip(tcx), ret)]
 fn sized_constraint_for_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Option<Ty<'tcx>> {
diff --git a/compiler/stable_mir/src/compiler_interface.rs b/compiler/stable_mir/src/compiler_interface.rs
index 231d9ba49a3..4dd64228bba 100644
--- a/compiler/stable_mir/src/compiler_interface.rs
+++ b/compiler/stable_mir/src/compiler_interface.rs
@@ -13,8 +13,8 @@ use crate::target::MachineInfo;
 use crate::ty::{
     AdtDef, AdtKind, Allocation, ClosureDef, ClosureKind, Const, FieldDef, FnDef, ForeignDef,
     ForeignItemKind, ForeignModule, ForeignModuleDef, GenericArgs, GenericPredicates, Generics,
-    ImplDef, ImplTrait, LineInfo, PolyFnSig, RigidTy, Span, TraitDecl, TraitDef, Ty, TyKind,
-    UintTy, VariantDef,
+    ImplDef, ImplTrait, IntrinsicDef, LineInfo, PolyFnSig, RigidTy, Span, TraitDecl, TraitDef, Ty,
+    TyKind, UintTy, VariantDef,
 };
 use crate::{
     mir, Crate, CrateItem, CrateItems, CrateNum, DefId, Error, Filename, ImplTraitDecls, ItemKind,
@@ -88,6 +88,16 @@ pub trait Context {
     /// Retrieve the function signature for the given generic arguments.
     fn fn_sig(&self, def: FnDef, args: &GenericArgs) -> PolyFnSig;
 
+    /// Retrieve the intrinsic definition if the item corresponds one.
+    fn intrinsic(&self, item: DefId) -> Option<IntrinsicDef>;
+
+    /// Retrieve the plain function name of an intrinsic.
+    fn intrinsic_name(&self, def: IntrinsicDef) -> Symbol;
+
+    /// Returns whether the intrinsic has no meaningful body and all backends
+    /// need to shim all calls to it.
+    fn intrinsic_must_be_overridden(&self, def: IntrinsicDef) -> bool;
+
     /// Retrieve the closure signature for the given generic arguments.
     fn closure_sig(&self, args: &GenericArgs) -> PolyFnSig;
 
@@ -198,7 +208,6 @@ pub trait Context {
     fn vtable_allocation(&self, global_alloc: &GlobalAlloc) -> Option<AllocId>;
     fn krate(&self, def_id: DefId) -> Crate;
     fn instance_name(&self, def: InstanceDef, trimmed: bool) -> Symbol;
-    fn intrinsic_name(&self, def: InstanceDef) -> Symbol;
 
     /// Return information about the target machine.
     fn target_info(&self) -> MachineInfo;
diff --git a/compiler/stable_mir/src/mir/mono.rs b/compiler/stable_mir/src/mir/mono.rs
index 394038926f6..572f1499c5a 100644
--- a/compiler/stable_mir/src/mir/mono.rs
+++ b/compiler/stable_mir/src/mir/mono.rs
@@ -106,7 +106,9 @@ impl Instance {
     /// which is more convenient to match with intrinsic symbols.
     pub fn intrinsic_name(&self) -> Option<Symbol> {
         match self.kind {
-            InstanceKind::Intrinsic => Some(with(|context| context.intrinsic_name(self.def))),
+            InstanceKind::Intrinsic => {
+                Some(with(|context| context.intrinsic(self.def.def_id()).unwrap().fn_name()))
+            }
             InstanceKind::Item | InstanceKind::Virtual { .. } | InstanceKind::Shim => None,
         }
     }
diff --git a/compiler/stable_mir/src/ty.rs b/compiler/stable_mir/src/ty.rs
index 321c56b623a..f3ac2bfcdb0 100644
--- a/compiler/stable_mir/src/ty.rs
+++ b/compiler/stable_mir/src/ty.rs
@@ -621,6 +621,41 @@ impl FnDef {
     pub fn body(&self) -> Option<Body> {
         with(|ctx| ctx.has_body(self.0).then(|| ctx.mir_body(self.0)))
     }
+
+    /// Get the information of the intrinsic if this function is a definition of one.
+    pub fn as_intrinsic(&self) -> Option<IntrinsicDef> {
+        with(|cx| cx.intrinsic(self.def_id()))
+    }
+
+    /// Check if the function is an intrinsic.
+    #[inline]
+    pub fn is_intrinsic(&self) -> bool {
+        self.as_intrinsic().is_some()
+    }
+}
+
+crate_def! {
+    pub IntrinsicDef;
+}
+
+impl IntrinsicDef {
+    /// Returns the plain name of the intrinsic.
+    /// e.g., `transmute` for `core::intrinsics::transmute`.
+    pub fn fn_name(&self) -> Symbol {
+        with(|cx| cx.intrinsic_name(*self))
+    }
+
+    /// Returns whether the intrinsic has no meaningful body and all backends
+    /// need to shim all calls to it.
+    pub fn must_be_overridden(&self) -> bool {
+        with(|cx| cx.intrinsic_must_be_overridden(*self))
+    }
+}
+
+impl From<IntrinsicDef> for FnDef {
+    fn from(def: IntrinsicDef) -> Self {
+        FnDef(def.0)
+    }
 }
 
 crate_def! {
diff --git a/library/core/Cargo.toml b/library/core/Cargo.toml
index daf2612833d..0c264234123 100644
--- a/library/core/Cargo.toml
+++ b/library/core/Cargo.toml
@@ -46,6 +46,8 @@ check-cfg = [
     'cfg(bootstrap)',
     'cfg(no_fp_fmt_parse)',
     'cfg(stdarch_intel_sde)',
-    # This matches `EXTRA_CHECK_CFGS` in `src/bootstrap/src/lib.rs`.
+    # core use #[path] imports to portable-simd `core_simd` crate
+    # and to stdarch `core_arch` crate which messes-up with Cargo list
+    # of declared features, we therefor expect any feature cfg
     'cfg(feature, values(any()))',
 ]
diff --git a/library/core/src/fmt/mod.rs b/library/core/src/fmt/mod.rs
index 9b372eac524..60a27863413 100644
--- a/library/core/src/fmt/mod.rs
+++ b/library/core/src/fmt/mod.rs
@@ -340,7 +340,9 @@ impl<'a> Arguments<'a> {
     #[rustc_const_unstable(feature = "const_fmt_arguments_new", issue = "none")]
     pub const fn new_const(pieces: &'a [&'static str]) -> Self {
         if pieces.len() > 1 {
-            panic!("invalid args");
+            // Since panic!() expands to panic_fmt(format_args!()), using panic! here is both a
+            // bit silly and also significantly increases the amount of MIR generated by panics.
+            crate::panicking::panic_nounwind("invalid args");
         }
         Arguments { pieces, fmt: None, args: &[] }
     }
@@ -350,7 +352,8 @@ impl<'a> Arguments<'a> {
     #[inline]
     pub fn new_v1(pieces: &'a [&'static str], args: &'a [rt::Argument<'a>]) -> Arguments<'a> {
         if pieces.len() < args.len() || pieces.len() > args.len() + 1 {
-            panic!("invalid args");
+            // See Arguments::new_const for why we don't use panic!.
+            crate::panicking::panic_nounwind("invalid args");
         }
         Arguments { pieces, fmt: None, args }
     }
diff --git a/library/core/src/internal_macros.rs b/library/core/src/internal_macros.rs
index bf53b2245ac..d3a4d6aff2d 100644
--- a/library/core/src/internal_macros.rs
+++ b/library/core/src/internal_macros.rs
@@ -80,47 +80,6 @@ macro_rules! forward_ref_op_assign {
     }
 }
 
-/// Create a zero-size type similar to a closure type, but named.
-macro_rules! impl_fn_for_zst {
-    ($(
-        $( #[$attr: meta] )*
-        struct $Name: ident impl$( <$( $lifetime : lifetime ),+> )? Fn =
-            |$( $arg: ident: $ArgTy: ty ),*| -> $ReturnTy: ty
-            $body: block;
-    )+) => {
-        $(
-            $( #[$attr] )*
-            struct $Name;
-
-            impl $( <$( $lifetime ),+> )? Fn<($( $ArgTy, )*)> for $Name {
-                #[inline]
-                extern "rust-call" fn call(&self, ($( $arg, )*): ($( $ArgTy, )*)) -> $ReturnTy {
-                    $body
-                }
-            }
-
-            impl $( <$( $lifetime ),+> )? FnMut<($( $ArgTy, )*)> for $Name {
-                #[inline]
-                extern "rust-call" fn call_mut(
-                    &mut self,
-                    ($( $arg, )*): ($( $ArgTy, )*)
-                ) -> $ReturnTy {
-                    Fn::call(&*self, ($( $arg, )*))
-                }
-            }
-
-            impl $( <$( $lifetime ),+> )? FnOnce<($( $ArgTy, )*)> for $Name {
-                type Output = $ReturnTy;
-
-                #[inline]
-                extern "rust-call" fn call_once(self, ($( $arg, )*): ($( $ArgTy, )*)) -> $ReturnTy {
-                    Fn::call(&self, ($( $arg, )*))
-                }
-            }
-        )+
-    }
-}
-
 /// A macro for defining `#[cfg]` if-else statements.
 ///
 /// `cfg_if` is similar to the `if/elif` C preprocessor macro by allowing definition of a cascade
diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs
index dcf68b36c7a..206d1ab8852 100644
--- a/library/core/src/lib.rs
+++ b/library/core/src/lib.rs
@@ -255,6 +255,7 @@
 #![feature(trait_alias)]
 #![feature(transparent_unions)]
 #![feature(try_blocks)]
+#![feature(type_alias_impl_trait)]
 #![feature(unboxed_closures)]
 #![feature(unsized_fn_params)]
 #![feature(with_negative_coherence)]
diff --git a/library/core/src/slice/ascii.rs b/library/core/src/slice/ascii.rs
index 8ad045275ad..19c91ba2eb9 100644
--- a/library/core/src/slice/ascii.rs
+++ b/library/core/src/slice/ascii.rs
@@ -108,7 +108,7 @@ impl [u8] {
                   without modifying the original"]
     #[stable(feature = "inherent_ascii_escape", since = "1.60.0")]
     pub fn escape_ascii(&self) -> EscapeAscii<'_> {
-        EscapeAscii { inner: self.iter().flat_map(EscapeByte) }
+        EscapeAscii { inner: self.iter().flat_map(|byte| byte.escape_ascii()) }
     }
 
     /// Returns a byte slice with leading ASCII whitespace bytes removed.
@@ -190,12 +190,7 @@ impl [u8] {
     }
 }
 
-impl_fn_for_zst! {
-    #[derive(Clone)]
-    struct EscapeByte impl Fn = |byte: &u8| -> ascii::EscapeDefault {
-        ascii::escape_default(*byte)
-    };
-}
+type EscapeByte = impl (Fn(&u8) -> ascii::EscapeDefault) + Copy;
 
 /// An iterator over the escaped version of a byte slice.
 ///
diff --git a/library/core/src/str/iter.rs b/library/core/src/str/iter.rs
index 19627f28e64..d61f04102e5 100644
--- a/library/core/src/str/iter.rs
+++ b/library/core/src/str/iter.rs
@@ -1274,8 +1274,10 @@ pub struct SplitWhitespace<'a> {
 #[stable(feature = "split_ascii_whitespace", since = "1.34.0")]
 #[derive(Clone, Debug)]
 pub struct SplitAsciiWhitespace<'a> {
-    pub(super) inner:
-        Map<Filter<SliceSplit<'a, u8, IsAsciiWhitespace>, BytesIsNotEmpty>, UnsafeBytesToStr>,
+    pub(super) inner: Map<
+        Filter<SliceSplit<'a, u8, IsAsciiWhitespace>, BytesIsNotEmpty<'a>>,
+        UnsafeBytesToStr<'a>,
+    >,
 }
 
 /// An iterator over the substrings of a string,
diff --git a/library/core/src/str/mod.rs b/library/core/src/str/mod.rs
index 669cdc92e35..edda4d1b687 100644
--- a/library/core/src/str/mod.rs
+++ b/library/core/src/str/mod.rs
@@ -983,7 +983,7 @@ impl str {
     #[cfg_attr(not(test), rustc_diagnostic_item = "str_split_whitespace")]
     #[inline]
     pub fn split_whitespace(&self) -> SplitWhitespace<'_> {
-        SplitWhitespace { inner: self.split(IsWhitespace).filter(IsNotEmpty) }
+        SplitWhitespace { inner: self.split(char::is_whitespace).filter(|s| !s.is_empty()) }
     }
 
     /// Splits a string slice by ASCII whitespace.
@@ -1032,8 +1032,13 @@ impl str {
     #[stable(feature = "split_ascii_whitespace", since = "1.34.0")]
     #[inline]
     pub fn split_ascii_whitespace(&self) -> SplitAsciiWhitespace<'_> {
-        let inner =
-            self.as_bytes().split(IsAsciiWhitespace).filter(BytesIsNotEmpty).map(UnsafeBytesToStr);
+        let inner = self
+            .as_bytes()
+            .split(u8::is_ascii_whitespace)
+            .filter(|s| !s.is_empty())
+            // SAFETY: the byte slice came from a string and was only split
+            // along character boundaries, so the resulting slices are strings.
+            .map(|bytes| unsafe { from_utf8_unchecked(bytes) });
         SplitAsciiWhitespace { inner }
     }
 
@@ -1085,7 +1090,11 @@ impl str {
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn lines(&self) -> Lines<'_> {
-        Lines(self.split_inclusive('\n').map(LinesMap))
+        Lines(self.split_inclusive('\n').map(|line| {
+            let Some(line) = line.strip_suffix('\n') else { return line };
+            let Some(line) = line.strip_suffix('\r') else { return line };
+            line
+        }))
     }
 
     /// An iterator over the lines of a string.
@@ -2636,14 +2645,19 @@ impl str {
     #[stable(feature = "str_escape", since = "1.34.0")]
     pub fn escape_debug(&self) -> EscapeDebug<'_> {
         let mut chars = self.chars();
-        EscapeDebug {
-            inner: chars
-                .next()
-                .map(|first| first.escape_debug_ext(EscapeDebugExtArgs::ESCAPE_ALL))
-                .into_iter()
-                .flatten()
-                .chain(chars.flat_map(CharEscapeDebugContinue)),
-        }
+        let first = chars
+            .next()
+            .map(|first| first.escape_debug_ext(EscapeDebugExtArgs::ESCAPE_ALL))
+            .into_iter()
+            .flatten();
+        let inner = first.chain(chars.flat_map(|c| {
+            c.escape_debug_ext(EscapeDebugExtArgs {
+                escape_grapheme_extended: false,
+                escape_single_quote: true,
+                escape_double_quote: true,
+            })
+        }));
+        EscapeDebug { inner }
     }
 
     /// Return an iterator that escapes each char in `self` with [`char::escape_default`].
@@ -2681,7 +2695,7 @@ impl str {
                   without modifying the original"]
     #[stable(feature = "str_escape", since = "1.34.0")]
     pub fn escape_default(&self) -> EscapeDefault<'_> {
-        EscapeDefault { inner: self.chars().flat_map(CharEscapeDefault) }
+        EscapeDefault { inner: self.chars().flat_map(char::escape_default) }
     }
 
     /// Return an iterator that escapes each char in `self` with [`char::escape_unicode`].
@@ -2719,7 +2733,7 @@ impl str {
                   without modifying the original"]
     #[stable(feature = "str_escape", since = "1.34.0")]
     pub fn escape_unicode(&self) -> EscapeUnicode<'_> {
-        EscapeUnicode { inner: self.chars().flat_map(CharEscapeUnicode) }
+        EscapeUnicode { inner: self.chars().flat_map(char::escape_unicode) }
     }
 }
 
@@ -2750,59 +2764,15 @@ impl Default for &mut str {
     }
 }
 
-impl_fn_for_zst! {
-    /// A nameable, cloneable fn type
-    #[derive(Clone)]
-    struct LinesMap impl<'a> Fn = |line: &'a str| -> &'a str {
-        let Some(line) = line.strip_suffix('\n') else { return line };
-        let Some(line) = line.strip_suffix('\r') else { return line };
-        line
-    };
-
-    #[derive(Clone)]
-    struct CharEscapeDebugContinue impl Fn = |c: char| -> char::EscapeDebug {
-        c.escape_debug_ext(EscapeDebugExtArgs {
-            escape_grapheme_extended: false,
-            escape_single_quote: true,
-            escape_double_quote: true
-        })
-    };
-
-    #[derive(Clone)]
-    struct CharEscapeUnicode impl Fn = |c: char| -> char::EscapeUnicode {
-        c.escape_unicode()
-    };
-    #[derive(Clone)]
-    struct CharEscapeDefault impl Fn = |c: char| -> char::EscapeDefault {
-        c.escape_default()
-    };
-
-    #[derive(Clone)]
-    struct IsWhitespace impl Fn = |c: char| -> bool {
-        c.is_whitespace()
-    };
-
-    #[derive(Clone)]
-    struct IsAsciiWhitespace impl Fn = |byte: &u8| -> bool {
-        byte.is_ascii_whitespace()
-    };
-
-    #[derive(Clone)]
-    struct IsNotEmpty impl<'a, 'b> Fn = |s: &'a &'b str| -> bool {
-        !s.is_empty()
-    };
-
-    #[derive(Clone)]
-    struct BytesIsNotEmpty impl<'a, 'b> Fn = |s: &'a &'b [u8]| -> bool {
-        !s.is_empty()
-    };
-
-    #[derive(Clone)]
-    struct UnsafeBytesToStr impl<'a> Fn = |bytes: &'a [u8]| -> &'a str {
-        // SAFETY: not safe
-        unsafe { from_utf8_unchecked(bytes) }
-    };
-}
+type LinesMap = impl (Fn(&str) -> &str) + Copy;
+type CharEscapeDebugContinue = impl (FnMut(char) -> char::EscapeDebug) + Copy;
+type CharEscapeUnicode = impl (Fn(char) -> char::EscapeUnicode) + Copy;
+type CharEscapeDefault = impl (Fn(char) -> char::EscapeDefault) + Copy;
+type IsWhitespace = impl (Fn(char) -> bool) + Copy;
+type IsAsciiWhitespace = impl (Fn(&u8) -> bool) + Copy;
+type IsNotEmpty = impl (Fn(&&str) -> bool) + Copy;
+type BytesIsNotEmpty<'a> = impl (FnMut(&&'a [u8]) -> bool) + Copy;
+type UnsafeBytesToStr<'a> = impl (FnMut(&'a [u8]) -> &'a str) + Copy;
 
 // This is required to make `impl From<&str> for Box<dyn Error>` and `impl<E> From<E> for Box<dyn Error>` not overlap.
 #[stable(feature = "rust1", since = "1.0.0")]
diff --git a/library/core/src/task/wake.rs b/library/core/src/task/wake.rs
index 7691721b91e..3d21b09fa8a 100644
--- a/library/core/src/task/wake.rs
+++ b/library/core/src/task/wake.rs
@@ -5,6 +5,7 @@ use crate::mem::transmute;
 use crate::any::Any;
 use crate::fmt;
 use crate::marker::PhantomData;
+use crate::panic::AssertUnwindSafe;
 use crate::ptr;
 
 /// A `RawWaker` allows the implementor of a task executor to create a [`Waker`]
@@ -236,7 +237,7 @@ enum ExtData<'a> {
 pub struct Context<'a> {
     waker: &'a Waker,
     local_waker: &'a LocalWaker,
-    ext: ExtData<'a>,
+    ext: AssertUnwindSafe<ExtData<'a>>,
     // Ensure we future-proof against variance changes by forcing
     // the lifetime to be invariant (argument-position lifetimes
     // are contravariant while return-position lifetimes are
@@ -279,7 +280,9 @@ impl<'a> Context<'a> {
     #[unstable(feature = "context_ext", issue = "123392")]
     #[rustc_const_unstable(feature = "const_waker", issue = "102012")]
     pub const fn ext(&mut self) -> &mut dyn Any {
-        match &mut self.ext {
+        // FIXME: this field makes Context extra-weird about unwind safety
+        // can we justify AssertUnwindSafe if we stabilize this? do we care?
+        match &mut *self.ext {
             ExtData::Some(data) => *data,
             ExtData::None(unit) => unit,
         }
@@ -353,7 +356,7 @@ impl<'a> ContextBuilder<'a> {
     #[rustc_const_unstable(feature = "const_waker", issue = "102012")]
     #[unstable(feature = "context_ext", issue = "123392")]
     pub const fn from(cx: &'a mut Context<'_>) -> Self {
-        let ext = match &mut cx.ext {
+        let ext = match &mut *cx.ext {
             ExtData::Some(ext) => ExtData::Some(*ext),
             ExtData::None(()) => ExtData::None(()),
         };
@@ -396,7 +399,7 @@ impl<'a> ContextBuilder<'a> {
     #[rustc_const_unstable(feature = "const_waker", issue = "102012")]
     pub const fn build(self) -> Context<'a> {
         let ContextBuilder { waker, local_waker, ext, _marker, _marker2 } = self;
-        Context { waker, local_waker, ext, _marker, _marker2 }
+        Context { waker, local_waker, ext: AssertUnwindSafe(ext), _marker, _marker2 }
     }
 }
 
diff --git a/library/core/tests/result.rs b/library/core/tests/result.rs
index a47ef7aa1eb..00a6fd75b4f 100644
--- a/library/core/tests/result.rs
+++ b/library/core/tests/result.rs
@@ -170,6 +170,7 @@ pub fn test_iter() {
 }
 
 #[test]
+#[allow(for_loops_over_fallibles)]
 pub fn test_iter_mut() {
     let mut ok: Result<isize, &'static str> = Ok(100);
     for loc in ok.iter_mut() {
diff --git a/library/proc_macro/src/lib.rs b/library/proc_macro/src/lib.rs
index 23ae2e7dc0d..3d7d36b27e5 100644
--- a/library/proc_macro/src/lib.rs
+++ b/library/proc_macro/src/lib.rs
@@ -815,6 +815,18 @@ pub enum Delimiter {
     /// "macro variable" `$var`. It is important to preserve operator priorities in cases like
     /// `$var * 3` where `$var` is `1 + 2`.
     /// Invisible delimiters might not survive roundtrip of a token stream through a string.
+    ///
+    /// <div class="warning">
+    ///
+    /// Note: rustc currently can ignore the grouping of tokens delimited by `None` in the output
+    /// of a proc_macro. Only `None`-delimited groups created by a macro_rules macro in the input
+    /// of a proc_macro macro are preserved, and only in very specific circumstances.
+    /// Any `None`-delimited groups (re)created by a proc_macro will therefore not preserve
+    /// operator priorities as indicated above. The other `Delimiter` variants should be used
+    /// instead in this context. This is a rustc bug. For details, see
+    /// [rust-lang/rust#67062](https://github.com/rust-lang/rust/issues/67062).
+    ///
+    /// </div>
     #[stable(feature = "proc_macro_lib2", since = "1.29.0")]
     None,
 }
diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml
index 4b8ee4c1309..e56f03808b3 100644
--- a/library/std/Cargo.toml
+++ b/library/std/Cargo.toml
@@ -100,10 +100,14 @@ test = true
 
 [lints.rust.unexpected_cfgs]
 level = "warn"
+# x.py uses beta cargo, so `check-cfg` entries do not yet take effect
+# for rust-lang/rust. But for users of `-Zbuild-std` it does.
+# The unused warning is waiting for rust-lang/cargo#13925 to reach beta.
 check-cfg = [
     'cfg(bootstrap)',
-    'cfg(backtrace_in_libstd)',
-    'cfg(netbsd10)',
     'cfg(target_arch, values("xtensa"))',
-    'cfg(feature, values("std", "as_crate"))',
+    # std use #[path] imports to portable-simd `std_float` crate
+    # and to the `backtrace` crate which messes-up with Cargo list
+    # of declared features, we therefor expect any feature cfg
+    'cfg(feature, values(any()))',
 ]
diff --git a/library/std/build.rs b/library/std/build.rs
index 7a47b52e8e4..7d975df545e 100644
--- a/library/std/build.rs
+++ b/library/std/build.rs
@@ -7,9 +7,13 @@ fn main() {
     let target_vendor =
         env::var("CARGO_CFG_TARGET_VENDOR").expect("CARGO_CFG_TARGET_VENDOR was not set");
     let target_env = env::var("CARGO_CFG_TARGET_ENV").expect("CARGO_CFG_TARGET_ENV was not set");
+
+    println!("cargo:rustc-check-cfg=cfg(netbsd10)");
     if target_os == "netbsd" && env::var("RUSTC_STD_NETBSD10").is_ok() {
         println!("cargo:rustc-cfg=netbsd10");
     }
+
+    println!("cargo:rustc-check-cfg=cfg(restricted_std)");
     if target_os == "linux"
         || target_os == "android"
         || target_os == "netbsd"
@@ -59,8 +63,11 @@ fn main() {
         // - arch=avr
         // - JSON targets
         // - Any new targets that have not been explicitly added above.
-        println!("cargo:rustc-cfg=feature=\"restricted-std\"");
+        println!("cargo:rustc-cfg=restricted_std");
     }
-    println!("cargo:rustc-env=STD_ENV_ARCH={}", env::var("CARGO_CFG_TARGET_ARCH").unwrap());
+
+    println!("cargo:rustc-check-cfg=cfg(backtrace_in_libstd)");
     println!("cargo:rustc-cfg=backtrace_in_libstd");
+
+    println!("cargo:rustc-env=STD_ENV_ARCH={}", env::var("CARGO_CFG_TARGET_ARCH").unwrap());
 }
diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs
index 949c543a264..4a18db3d5a3 100644
--- a/library/std/src/lib.rs
+++ b/library/std/src/lib.rs
@@ -213,9 +213,9 @@
 //! [array]: prim@array
 //! [slice]: prim@slice
 
-#![cfg_attr(not(feature = "restricted-std"), stable(feature = "rust1", since = "1.0.0"))]
+#![cfg_attr(not(restricted_std), stable(feature = "rust1", since = "1.0.0"))]
 #![cfg_attr(
-    feature = "restricted-std",
+    restricted_std,
     unstable(
         feature = "restricted_std",
         issue = "none",
diff --git a/library/std/src/sys/thread_local/fast_local.rs b/library/std/src/sys/thread_local/fast_local.rs
deleted file mode 100644
index 49b51a729e4..00000000000
--- a/library/std/src/sys/thread_local/fast_local.rs
+++ /dev/null
@@ -1,247 +0,0 @@
-use super::lazy::LazyKeyInner;
-use crate::cell::Cell;
-use crate::sys::thread_local_dtor::register_dtor;
-use crate::{fmt, mem, panic, ptr};
-
-#[doc(hidden)]
-#[allow_internal_unstable(thread_local_internals, cfg_target_thread_local, thread_local)]
-#[allow_internal_unsafe]
-#[unstable(feature = "thread_local_internals", issue = "none")]
-#[rustc_macro_transparency = "semitransparent"]
-pub macro thread_local_inner {
-    // used to generate the `LocalKey` value for const-initialized thread locals
-    (@key $t:ty, const $init:expr) => {{
-        #[inline]
-        #[deny(unsafe_op_in_unsafe_fn)]
-        unsafe fn __getit(
-            _init: $crate::option::Option<&mut $crate::option::Option<$t>>,
-        ) -> $crate::option::Option<&'static $t> {
-            const INIT_EXPR: $t = $init;
-            // If the platform has support for `#[thread_local]`, use it.
-            #[thread_local]
-            // We use `UnsafeCell` here instead of `static mut` to ensure any generated TLS shims
-            // have a nonnull attribute on their return value.
-            static VAL: $crate::cell::UnsafeCell<$t> = $crate::cell::UnsafeCell::new(INIT_EXPR);
-
-            // If a dtor isn't needed we can do something "very raw" and
-            // just get going.
-            if !$crate::mem::needs_drop::<$t>() {
-                unsafe {
-                    return $crate::option::Option::Some(&*VAL.get())
-                }
-            }
-
-            // 0 == dtor not registered
-            // 1 == dtor registered, dtor not run
-            // 2 == dtor registered and is running or has run
-            #[thread_local]
-            static STATE: $crate::cell::Cell<$crate::primitive::u8> = $crate::cell::Cell::new(0);
-
-            // Safety: Performs `drop_in_place(ptr as *mut $t)`, and requires
-            // all that comes with it.
-            unsafe extern "C" fn destroy(ptr: *mut $crate::primitive::u8) {
-                $crate::thread::local_impl::abort_on_dtor_unwind(|| {
-                    let old_state = STATE.replace(2);
-                    $crate::debug_assert_eq!(old_state, 1);
-                    // Safety: safety requirement is passed on to caller.
-                    unsafe { $crate::ptr::drop_in_place(ptr.cast::<$t>()); }
-                });
-            }
-
-            unsafe {
-                match STATE.get() {
-                    // 0 == we haven't registered a destructor, so do
-                    //   so now.
-                    0 => {
-                        $crate::thread::local_impl::Key::<$t>::register_dtor(
-                            VAL.get() as *mut $crate::primitive::u8,
-                            destroy,
-                        );
-                        STATE.set(1);
-                        $crate::option::Option::Some(&*VAL.get())
-                    }
-                    // 1 == the destructor is registered and the value
-                    //   is valid, so return the pointer.
-                    1 => $crate::option::Option::Some(&*VAL.get()),
-                    // otherwise the destructor has already run, so we
-                    // can't give access.
-                    _ => $crate::option::Option::None,
-                }
-            }
-        }
-
-        unsafe {
-            $crate::thread::LocalKey::new(__getit)
-        }
-    }},
-
-    // used to generate the `LocalKey` value for `thread_local!`
-    (@key $t:ty, $init:expr) => {
-        {
-            #[inline]
-            fn __init() -> $t { $init }
-
-            #[inline]
-            unsafe fn __getit(
-                init: $crate::option::Option<&mut $crate::option::Option<$t>>,
-            ) -> $crate::option::Option<&'static $t> {
-                #[thread_local]
-                static __KEY: $crate::thread::local_impl::Key<$t> =
-                    $crate::thread::local_impl::Key::<$t>::new();
-
-                unsafe {
-                    __KEY.get(move || {
-                        if let $crate::option::Option::Some(init) = init {
-                            if let $crate::option::Option::Some(value) = init.take() {
-                                return value;
-                            }
-                            if $crate::cfg!(debug_assertions) {
-                                $crate::unreachable!("missing default value");
-                            }
-                        }
-                        __init()
-                    })
-                }
-            }
-
-            unsafe {
-                $crate::thread::LocalKey::new(__getit)
-            }
-        }
-    },
-    ($(#[$attr:meta])* $vis:vis $name:ident, $t:ty, $($init:tt)*) => {
-        $(#[$attr])* $vis const $name: $crate::thread::LocalKey<$t> =
-            $crate::thread::local_impl::thread_local_inner!(@key $t, $($init)*);
-    },
-}
-
-#[derive(Copy, Clone)]
-enum DtorState {
-    Unregistered,
-    Registered,
-    RunningOrHasRun,
-}
-
-// This data structure has been carefully constructed so that the fast path
-// only contains one branch on x86. That optimization is necessary to avoid
-// duplicated tls lookups on OSX.
-//
-// LLVM issue: https://bugs.llvm.org/show_bug.cgi?id=41722
-pub struct Key<T> {
-    // If `LazyKeyInner::get` returns `None`, that indicates either:
-    //   * The value has never been initialized
-    //   * The value is being recursively initialized
-    //   * The value has already been destroyed or is being destroyed
-    // To determine which kind of `None`, check `dtor_state`.
-    //
-    // This is very optimizer friendly for the fast path - initialized but
-    // not yet dropped.
-    inner: LazyKeyInner<T>,
-
-    // Metadata to keep track of the state of the destructor. Remember that
-    // this variable is thread-local, not global.
-    dtor_state: Cell<DtorState>,
-}
-
-impl<T> fmt::Debug for Key<T> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        f.debug_struct("Key").finish_non_exhaustive()
-    }
-}
-impl<T> Key<T> {
-    pub const fn new() -> Key<T> {
-        Key { inner: LazyKeyInner::new(), dtor_state: Cell::new(DtorState::Unregistered) }
-    }
-
-    // note that this is just a publicly-callable function only for the
-    // const-initialized form of thread locals, basically a way to call the
-    // free `register_dtor` function defined elsewhere in std.
-    pub unsafe fn register_dtor(a: *mut u8, dtor: unsafe extern "C" fn(*mut u8)) {
-        unsafe {
-            register_dtor(a, dtor);
-        }
-    }
-
-    pub unsafe fn get<F: FnOnce() -> T>(&self, init: F) -> Option<&'static T> {
-        // SAFETY: See the definitions of `LazyKeyInner::get` and
-        // `try_initialize` for more information.
-        //
-        // The caller must ensure no mutable references are ever active to
-        // the inner cell or the inner T when this is called.
-        // The `try_initialize` is dependant on the passed `init` function
-        // for this.
-        unsafe {
-            match self.inner.get() {
-                Some(val) => Some(val),
-                None => self.try_initialize(init),
-            }
-        }
-    }
-
-    // `try_initialize` is only called once per fast thread local variable,
-    // except in corner cases where thread_local dtors reference other
-    // thread_local's, or it is being recursively initialized.
-    //
-    // Macos: Inlining this function can cause two `tlv_get_addr` calls to
-    // be performed for every call to `Key::get`.
-    // LLVM issue: https://bugs.llvm.org/show_bug.cgi?id=41722
-    #[inline(never)]
-    unsafe fn try_initialize<F: FnOnce() -> T>(&self, init: F) -> Option<&'static T> {
-        // SAFETY: See comment above (this function doc).
-        if !mem::needs_drop::<T>() || unsafe { self.try_register_dtor() } {
-            // SAFETY: See comment above (this function doc).
-            Some(unsafe { self.inner.initialize(init) })
-        } else {
-            None
-        }
-    }
-
-    // `try_register_dtor` is only called once per fast thread local
-    // variable, except in corner cases where thread_local dtors reference
-    // other thread_local's, or it is being recursively initialized.
-    unsafe fn try_register_dtor(&self) -> bool {
-        match self.dtor_state.get() {
-            DtorState::Unregistered => {
-                // SAFETY: dtor registration happens before initialization.
-                // Passing `self` as a pointer while using `destroy_value<T>`
-                // is safe because the function will build a pointer to a
-                // Key<T>, which is the type of self and so find the correct
-                // size.
-                unsafe { register_dtor(self as *const _ as *mut u8, destroy_value::<T>) };
-                self.dtor_state.set(DtorState::Registered);
-                true
-            }
-            DtorState::Registered => {
-                // recursively initialized
-                true
-            }
-            DtorState::RunningOrHasRun => false,
-        }
-    }
-}
-
-unsafe extern "C" fn destroy_value<T>(ptr: *mut u8) {
-    let ptr = ptr as *mut Key<T>;
-
-    // SAFETY:
-    //
-    // The pointer `ptr` has been built just above and comes from
-    // `try_register_dtor` where it is originally a Key<T> coming from `self`,
-    // making it non-NUL and of the correct type.
-    //
-    // Right before we run the user destructor be sure to set the
-    // `Option<T>` to `None`, and `dtor_state` to `RunningOrHasRun`. This
-    // causes future calls to `get` to run `try_initialize_drop` again,
-    // which will now fail, and return `None`.
-    //
-    // Wrap the call in a catch to ensure unwinding is caught in the event
-    // a panic takes place in a destructor.
-    if let Err(_) = panic::catch_unwind(panic::AssertUnwindSafe(|| unsafe {
-        let Key { inner, dtor_state } = &*ptr;
-        let value = inner.take();
-        dtor_state.set(DtorState::RunningOrHasRun);
-        drop(value);
-    })) {
-        rtabort!("thread local panicked on drop");
-    }
-}
diff --git a/library/std/src/sys/thread_local/fast_local/eager.rs b/library/std/src/sys/thread_local/fast_local/eager.rs
new file mode 100644
index 00000000000..c2bc580530b
--- /dev/null
+++ b/library/std/src/sys/thread_local/fast_local/eager.rs
@@ -0,0 +1,82 @@
+use crate::cell::{Cell, UnsafeCell};
+use crate::ptr::{self, drop_in_place};
+use crate::sys::thread_local::abort_on_dtor_unwind;
+use crate::sys::thread_local_dtor::register_dtor;
+
+#[derive(Clone, Copy)]
+enum State {
+    Initial,
+    Alive,
+    Destroyed,
+}
+
+#[allow(missing_debug_implementations)]
+pub struct Storage<T> {
+    state: Cell<State>,
+    val: UnsafeCell<T>,
+}
+
+impl<T> Storage<T> {
+    pub const fn new(val: T) -> Storage<T> {
+        Storage { state: Cell::new(State::Initial), val: UnsafeCell::new(val) }
+    }
+
+    /// Get a reference to the TLS value. If the TLS variable has been destroyed,
+    /// `None` is returned.
+    ///
+    /// # Safety
+    /// * The `self` reference must remain valid until the TLS destructor has been
+    ///   run.
+    /// * The returned reference may only be used until thread destruction occurs
+    ///   and may not be used after reentrant initialization has occurred.
+    ///
+    // FIXME(#110897): return NonNull instead of lying about the lifetime.
+    #[inline]
+    pub unsafe fn get(&self) -> Option<&'static T> {
+        match self.state.get() {
+            // SAFETY: as the state is not `Destroyed`, the value cannot have
+            // been destroyed yet. The reference fulfills the terms outlined
+            // above.
+            State::Alive => unsafe { Some(&*self.val.get()) },
+            State::Destroyed => None,
+            State::Initial => unsafe { self.initialize() },
+        }
+    }
+
+    #[cold]
+    unsafe fn initialize(&self) -> Option<&'static T> {
+        // Register the destructor
+
+        // SAFETY:
+        // * the destructor will be called at thread destruction.
+        // * the caller guarantees that `self` will be valid until that time.
+        unsafe {
+            register_dtor(ptr::from_ref(self).cast_mut().cast(), destroy::<T>);
+        }
+        self.state.set(State::Alive);
+        // SAFETY: as the state is not `Destroyed`, the value cannot have
+        // been destroyed yet. The reference fulfills the terms outlined
+        // above.
+        unsafe { Some(&*self.val.get()) }
+    }
+}
+
+/// Transition an `Alive` TLS variable into the `Destroyed` state, dropping its
+/// value.
+///
+/// # Safety
+/// * Must only be called at thread destruction.
+/// * `ptr` must point to an instance of `Storage` with `Alive` state and be
+///   valid for accessing that instance.
+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.
+        storage.state.set(State::Destroyed);
+        unsafe {
+            drop_in_place(storage.val.get());
+        }
+    })
+}
diff --git a/library/std/src/sys/thread_local/fast_local/lazy.rs b/library/std/src/sys/thread_local/fast_local/lazy.rs
new file mode 100644
index 00000000000..14371768d30
--- /dev/null
+++ b/library/std/src/sys/thread_local/fast_local/lazy.rs
@@ -0,0 +1,122 @@
+use crate::cell::UnsafeCell;
+use crate::hint::unreachable_unchecked;
+use crate::mem::forget;
+use crate::ptr;
+use crate::sys::thread_local::abort_on_dtor_unwind;
+use crate::sys::thread_local_dtor::register_dtor;
+
+pub unsafe trait DestroyedState: Sized {
+    fn register_dtor<T>(s: &Storage<T, Self>);
+}
+
+unsafe impl DestroyedState for ! {
+    fn register_dtor<T>(_: &Storage<T, !>) {}
+}
+
+unsafe impl DestroyedState for () {
+    fn register_dtor<T>(s: &Storage<T, ()>) {
+        unsafe {
+            register_dtor(ptr::from_ref(s).cast_mut().cast(), destroy::<T>);
+        }
+    }
+}
+
+enum State<T, D> {
+    Initial,
+    Alive(T),
+    Destroyed(D),
+}
+
+#[allow(missing_debug_implementations)]
+pub struct Storage<T, D> {
+    state: UnsafeCell<State<T, D>>,
+}
+
+impl<T, D> Storage<T, D>
+where
+    D: DestroyedState,
+{
+    pub const fn new() -> Storage<T, D> {
+        Storage { state: UnsafeCell::new(State::Initial) }
+    }
+
+    /// Get a reference to the TLS value, potentially initializing it with the
+    /// provided parameters. If the TLS variable has been destroyed, `None` is
+    /// returned.
+    ///
+    /// # Safety
+    /// * The `self` reference must remain valid until the TLS destructor is run,
+    ///   at which point the returned reference is invalidated.
+    /// * The returned reference may only be used until thread destruction occurs
+    ///   and may not be used after reentrant initialization has occurred.
+    ///
+    // FIXME(#110897): return NonNull instead of lying about the lifetime.
+    #[inline]
+    pub unsafe fn get_or_init(
+        &self,
+        i: Option<&mut Option<T>>,
+        f: impl FnOnce() -> T,
+    ) -> Option<&'static T> {
+        // SAFETY:
+        // No mutable reference to the inner value exists outside the calls to
+        // `replace`. The lifetime of the returned reference fulfills the terms
+        // outlined above.
+        let state = unsafe { &*self.state.get() };
+        match state {
+            State::Alive(v) => Some(v),
+            State::Destroyed(_) => None,
+            State::Initial => unsafe { self.initialize(i, f) },
+        }
+    }
+
+    #[cold]
+    unsafe fn initialize(
+        &self,
+        i: Option<&mut Option<T>>,
+        f: impl FnOnce() -> T,
+    ) -> Option<&'static T> {
+        // Perform initialization
+
+        let v = i.and_then(Option::take).unwrap_or_else(f);
+
+        // SAFETY:
+        // If references to the inner value exist, they were created in `f`
+        // and are invalidated here. The caller promises to never use them
+        // after this.
+        let old = unsafe { self.state.get().replace(State::Alive(v)) };
+        match old {
+            // 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),
+        }
+
+        // SAFETY:
+        // Initialization was completed and the state was set to `Alive`, so the
+        // reference fulfills the terms outlined above.
+        unsafe {
+            let State::Alive(v) = &*self.state.get() else { unreachable_unchecked() };
+            Some(v)
+        }
+    }
+}
+
+/// Transition an `Alive` TLS variable into the `Destroyed` state, dropping its
+/// value.
+///
+/// # Safety
+/// * Must only be called at thread destruction.
+/// * `ptr` must point to an instance of `Storage<T, ()>` and be valid for
+///   accessing that instance.
+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);
+    })
+}
diff --git a/library/std/src/sys/thread_local/fast_local/mod.rs b/library/std/src/sys/thread_local/fast_local/mod.rs
new file mode 100644
index 00000000000..25379071cb7
--- /dev/null
+++ b/library/std/src/sys/thread_local/fast_local/mod.rs
@@ -0,0 +1,122 @@
+//! Thread local support for platforms with native TLS.
+//!
+//! To achieve the best performance, we choose from four different types for
+//! the TLS variable, depending from the method of initialization used (`const`
+//! or lazy) and the drop requirements of the stored type:
+//!
+//! |         | `Drop`               | `!Drop`             |
+//! |--------:|:--------------------:|:-------------------:|
+//! | `const` | `EagerStorage<T>`    | `T`                 |
+//! | lazy    | `LazyStorage<T, ()>` | `LazyStorage<T, !>` |
+//!
+//! For `const` initialization and `!Drop` types, we simply use `T` directly,
+//! but for other situations, we implement a state machine to handle
+//! initialization of the variable and its destructor and destruction.
+//! Upon accessing the TLS variable, the current state is compared:
+//!
+//! 1. If the state is `Initial`, initialize the storage, transition the state
+//!    to `Alive` and (if applicable) register the destructor, and return a
+//!    reference to the value.
+//! 2. If the state is `Alive`, initialization was previously completed, so
+//!    return a reference to the value.
+//! 3. If the state is `Destroyed`, the destructor has been run already, so
+//!    return [`None`].
+//!
+//! The TLS destructor sets the state to `Destroyed` and drops the current value.
+//!
+//! To simplify the code, we make `LazyStorage` generic over the destroyed state
+//! and use the `!` type (never type) as type parameter for `!Drop` types. This
+//! eliminates the `Destroyed` state for these values, which can allow more niche
+//! optimizations to occur for the `State` enum. For `Drop` types, `()` is used.
+
+#![deny(unsafe_op_in_unsafe_fn)]
+
+mod eager;
+mod lazy;
+
+pub use eager::Storage as EagerStorage;
+pub use lazy::Storage as LazyStorage;
+
+#[doc(hidden)]
+#[allow_internal_unstable(
+    thread_local_internals,
+    cfg_target_thread_local,
+    thread_local,
+    never_type
+)]
+#[allow_internal_unsafe]
+#[unstable(feature = "thread_local_internals", issue = "none")]
+#[rustc_macro_transparency = "semitransparent"]
+pub macro thread_local_inner {
+    // used to generate the `LocalKey` value for const-initialized thread locals
+    (@key $t:ty, const $init:expr) => {{
+        const __INIT: $t = $init;
+
+        #[inline]
+        #[deny(unsafe_op_in_unsafe_fn)]
+        unsafe fn __getit(
+            _init: $crate::option::Option<&mut $crate::option::Option<$t>>,
+        ) -> $crate::option::Option<&'static $t> {
+            use $crate::thread::local_impl::EagerStorage;
+            use $crate::mem::needs_drop;
+            use $crate::ptr::addr_of;
+
+            if needs_drop::<$t>() {
+                #[thread_local]
+                static VAL: EagerStorage<$t> = EagerStorage::new(__INIT);
+                unsafe {
+                    VAL.get()
+                }
+            } else {
+                #[thread_local]
+                static VAL: $t = __INIT;
+                unsafe {
+                    $crate::option::Option::Some(&*addr_of!(VAL))
+                }
+            }
+        }
+
+        unsafe {
+            $crate::thread::LocalKey::new(__getit)
+        }
+    }},
+
+    // used to generate the `LocalKey` value for `thread_local!`
+    (@key $t:ty, $init:expr) => {{
+        #[inline]
+        fn __init() -> $t {
+            $init
+        }
+
+        #[inline]
+        #[deny(unsafe_op_in_unsafe_fn)]
+        unsafe fn __getit(
+            init: $crate::option::Option<&mut $crate::option::Option<$t>>,
+        ) -> $crate::option::Option<&'static $t> {
+            use $crate::thread::local_impl::LazyStorage;
+            use $crate::mem::needs_drop;
+
+            if needs_drop::<$t>() {
+                #[thread_local]
+                static VAL: LazyStorage<$t, ()> = LazyStorage::new();
+                unsafe {
+                    VAL.get_or_init(init, __init)
+                }
+            } else {
+                #[thread_local]
+                static VAL: LazyStorage<$t, !> = LazyStorage::new();
+                unsafe {
+                    VAL.get_or_init(init, __init)
+                }
+            }
+        }
+
+        unsafe {
+            $crate::thread::LocalKey::new(__getit)
+        }
+    }},
+    ($(#[$attr:meta])* $vis:vis $name:ident, $t:ty, $($init:tt)*) => {
+        $(#[$attr])* $vis const $name: $crate::thread::LocalKey<$t> =
+            $crate::thread::local_impl::thread_local_inner!(@key $t, $($init)*);
+    },
+}
diff --git a/library/std/src/sys/thread_local/mod.rs b/library/std/src/sys/thread_local/mod.rs
index 7500c95d8b4..36f6f907e72 100644
--- a/library/std/src/sys/thread_local/mod.rs
+++ b/library/std/src/sys/thread_local/mod.rs
@@ -10,12 +10,12 @@ cfg_if::cfg_if! {
         #[doc(hidden)]
         mod static_local;
         #[doc(hidden)]
-        pub use static_local::{Key, thread_local_inner};
+        pub use static_local::{EagerStorage, LazyStorage, thread_local_inner};
     } else if #[cfg(target_thread_local)] {
         #[doc(hidden)]
         mod fast_local;
         #[doc(hidden)]
-        pub use fast_local::{Key, thread_local_inner};
+        pub use fast_local::{EagerStorage, LazyStorage, thread_local_inner};
     } else {
         #[doc(hidden)]
         mod os_local;
@@ -24,6 +24,9 @@ cfg_if::cfg_if! {
     }
 }
 
+// Not used by the fast-local TLS anymore.
+// FIXME(#110897): remove this.
+#[allow(unused)]
 mod lazy {
     use crate::cell::UnsafeCell;
     use crate::hint;
diff --git a/library/std/src/sys/thread_local/static_local.rs b/library/std/src/sys/thread_local/static_local.rs
index 162c3fbd97a..6beda2e7188 100644
--- a/library/std/src/sys/thread_local/static_local.rs
+++ b/library/std/src/sys/thread_local/static_local.rs
@@ -1,5 +1,7 @@
-use super::lazy::LazyKeyInner;
-use crate::fmt;
+//! On some targets like wasm there's no threads, so no need to generate
+//! thread locals and we can instead just use plain statics!
+
+use crate::cell::UnsafeCell;
 
 #[doc(hidden)]
 #[allow_internal_unstable(thread_local_internals)]
@@ -9,22 +11,17 @@ use crate::fmt;
 pub macro thread_local_inner {
     // used to generate the `LocalKey` value for const-initialized thread locals
     (@key $t:ty, const $init:expr) => {{
-        #[inline] // see comments below
+        const __INIT: $t = $init;
+
+        #[inline]
         #[deny(unsafe_op_in_unsafe_fn)]
         unsafe fn __getit(
             _init: $crate::option::Option<&mut $crate::option::Option<$t>>,
         ) -> $crate::option::Option<&'static $t> {
-            const INIT_EXPR: $t = $init;
-
-            // wasm without atomics maps directly to `static mut`, and dtors
-            // aren't implemented because thread dtors aren't really a thing
-            // on wasm right now
-            //
-            // FIXME(#84224) this should come after the `target_thread_local`
-            // block.
-            static mut VAL: $t = INIT_EXPR;
-            // SAFETY: we only ever create shared references, so there's no mutable aliasing.
-            unsafe { $crate::option::Option::Some(&*$crate::ptr::addr_of!(VAL)) }
+            use $crate::thread::local_impl::EagerStorage;
+
+            static VAL: EagerStorage<$t> = EagerStorage { value: __INIT };
+            $crate::option::Option::Some(&VAL.value)
         }
 
         unsafe {
@@ -33,74 +30,83 @@ pub macro thread_local_inner {
     }},
 
     // used to generate the `LocalKey` value for `thread_local!`
-    (@key $t:ty, $init:expr) => {
-        {
-            #[inline]
-            fn __init() -> $t { $init }
-            #[inline]
-            unsafe fn __getit(
-                init: $crate::option::Option<&mut $crate::option::Option<$t>>,
-            ) -> $crate::option::Option<&'static $t> {
-                static __KEY: $crate::thread::local_impl::Key<$t> =
-                    $crate::thread::local_impl::Key::new();
-
-                unsafe {
-                    __KEY.get(move || {
-                        if let $crate::option::Option::Some(init) = init {
-                            if let $crate::option::Option::Some(value) = init.take() {
-                                return value;
-                            } else if $crate::cfg!(debug_assertions) {
-                                $crate::unreachable!("missing default value");
-                            }
-                        }
-                        __init()
-                    })
-                }
-            }
-
-            unsafe {
-                $crate::thread::LocalKey::new(__getit)
-            }
+    (@key $t:ty, $init:expr) => {{
+        #[inline]
+        fn __init() -> $t { $init }
+
+        #[inline]
+        #[deny(unsafe_op_in_unsafe_fn)]
+        unsafe fn __getit(
+            init: $crate::option::Option<&mut $crate::option::Option<$t>>,
+        ) -> $crate::option::Option<&'static $t> {
+            use $crate::thread::local_impl::LazyStorage;
+
+            static VAL: LazyStorage<$t> = LazyStorage::new();
+            unsafe { $crate::option::Option::Some(VAL.get(init, __init)) }
         }
-    },
+
+        unsafe {
+            $crate::thread::LocalKey::new(__getit)
+        }
+    }},
     ($(#[$attr:meta])* $vis:vis $name:ident, $t:ty, $($init:tt)*) => {
         $(#[$attr])* $vis const $name: $crate::thread::LocalKey<$t> =
             $crate::thread::local_impl::thread_local_inner!(@key $t, $($init)*);
     },
 }
 
-/// On some targets like wasm there's no threads, so no need to generate
-/// thread locals and we can instead just use plain statics!
-
-pub struct Key<T> {
-    inner: LazyKeyInner<T>,
+#[allow(missing_debug_implementations)]
+pub struct EagerStorage<T> {
+    pub value: T,
 }
 
-unsafe impl<T> Sync for Key<T> {}
+// SAFETY: the target doesn't have threads.
+unsafe impl<T> Sync for EagerStorage<T> {}
 
-impl<T> fmt::Debug for Key<T> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        f.debug_struct("Key").finish_non_exhaustive()
-    }
+#[allow(missing_debug_implementations)]
+pub struct LazyStorage<T> {
+    value: UnsafeCell<Option<T>>,
 }
 
-impl<T> Key<T> {
-    pub const fn new() -> Key<T> {
-        Key { inner: LazyKeyInner::new() }
+impl<T> LazyStorage<T> {
+    pub const fn new() -> LazyStorage<T> {
+        LazyStorage { value: UnsafeCell::new(None) }
     }
 
-    pub unsafe fn get(&self, init: impl FnOnce() -> T) -> Option<&'static T> {
-        // SAFETY: The caller must ensure no reference is ever handed out to
-        // the inner cell nor mutable reference to the Option<T> inside said
-        // cell. This make it safe to hand a reference, though the lifetime
-        // of 'static is itself unsafe, making the get method unsafe.
-        let value = unsafe {
-            match self.inner.get() {
-                Some(ref value) => value,
-                None => self.inner.initialize(init),
-            }
-        };
-
-        Some(value)
+    /// Gets a reference to the contained value, initializing it if necessary.
+    ///
+    /// # Safety
+    /// The returned reference may not be used after reentrant initialization has occurred.
+    #[inline]
+    pub unsafe fn get(
+        &'static self,
+        i: Option<&mut Option<T>>,
+        f: impl FnOnce() -> T,
+    ) -> &'static T {
+        let value = unsafe { &*self.value.get() };
+        match value {
+            Some(v) => v,
+            None => self.initialize(i, f),
+        }
+    }
+
+    #[cold]
+    unsafe fn initialize(
+        &'static self,
+        i: Option<&mut Option<T>>,
+        f: impl FnOnce() -> T,
+    ) -> &'static T {
+        let value = i.and_then(Option::take).unwrap_or_else(f);
+        // Destroy the old value, after updating the TLS variable as the
+        // destructor might reference it.
+        // FIXME(#110897): maybe panic on recursive initialization.
+        unsafe {
+            self.value.get().replace(Some(value));
+        }
+        // SAFETY: we just set this to `Some`.
+        unsafe { (*self.value.get()).as_ref().unwrap_unchecked() }
     }
 }
+
+// SAFETY: the target doesn't have threads.
+unsafe impl<T> Sync for LazyStorage<T> {}
diff --git a/library/std/src/thread/mod.rs b/library/std/src/thread/mod.rs
index 78bc9af6c4d..22215873933 100644
--- a/library/std/src/thread/mod.rs
+++ b/library/std/src/thread/mod.rs
@@ -205,7 +205,7 @@ cfg_if::cfg_if! {
         #[doc(hidden)]
         #[unstable(feature = "thread_local_internals", issue = "none")]
         pub mod local_impl {
-            pub use crate::sys::thread_local::{thread_local_inner, Key, abort_on_dtor_unwind};
+            pub use crate::sys::thread_local::*;
         }
     }
 }
diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs
index 38de5e38000..52c94465cd3 100644
--- a/src/bootstrap/src/lib.rs
+++ b/src/bootstrap/src/lib.rs
@@ -92,8 +92,6 @@ const EXTRA_CHECK_CFGS: &[(Option<Mode>, &str, Option<&[&'static str]>)] = &[
     (Some(Mode::Std), "no_global_oom_handling", None),
     (Some(Mode::Std), "no_rc", None),
     (Some(Mode::Std), "no_sync", None),
-    (Some(Mode::Std), "netbsd10", None),
-    (Some(Mode::Std), "backtrace_in_libstd", None),
     /* Extra values not defined in the built-in targets yet, but used in std */
     (Some(Mode::Std), "target_env", Some(&["libnx", "p2"])),
     (Some(Mode::Std), "target_os", Some(&["visionos"])),
diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs
index b54ec624524..7aab07c06a3 100644
--- a/src/librustdoc/clean/types.rs
+++ b/src/librustdoc/clean/types.rs
@@ -1937,7 +1937,7 @@ impl PrimitiveType {
             let mut primitive_locations = FxHashMap::default();
             // NOTE: technically this misses crates that are only passed with `--extern` and not loaded when checking the crate.
             // This is a degenerate case that I don't plan to support.
-            for &crate_num in tcx.crates(()) {
+            for &crate_num in tcx.crates_including_speculative(()) {
                 let e = ExternalCrate { crate_num };
                 let crate_name = e.name(tcx);
                 debug!(?crate_num, ?crate_name);
diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs
index feb03b9a823..462b31f159b 100644
--- a/src/librustdoc/core.rs
+++ b/src/librustdoc/core.rs
@@ -347,7 +347,7 @@ pub(crate) fn run_global_ctxt(
         show_coverage,
     };
 
-    for cnum in tcx.crates(()) {
+    for cnum in tcx.crates_including_speculative(()) {
         crate::visit_lib::lib_embargo_visit_item(&mut ctxt, cnum.as_def_id());
     }
 
diff --git a/src/librustdoc/formats/cache.rs b/src/librustdoc/formats/cache.rs
index a3b88a880f2..28ddf76a3a6 100644
--- a/src/librustdoc/formats/cache.rs
+++ b/src/librustdoc/formats/cache.rs
@@ -155,7 +155,7 @@ impl Cache {
 
         // Cache where all our extern crates are located
         // FIXME: this part is specific to HTML so it'd be nice to remove it from the common code
-        for &crate_num in tcx.crates(()) {
+        for &crate_num in tcx.crates_including_speculative(()) {
             let e = ExternalCrate { crate_num };
 
             let name = e.name(tcx);
diff --git a/src/librustdoc/passes/collect_trait_impls.rs b/src/librustdoc/passes/collect_trait_impls.rs
index c92cf9d3e80..22daac9efb1 100644
--- a/src/librustdoc/passes/collect_trait_impls.rs
+++ b/src/librustdoc/passes/collect_trait_impls.rs
@@ -47,7 +47,7 @@ pub(crate) fn collect_trait_impls(mut krate: Crate, cx: &mut DocContext<'_>) ->
     // External trait impls.
     {
         let _prof_timer = tcx.sess.prof.generic_activity("build_extern_trait_impls");
-        for &cnum in tcx.crates(()) {
+        for &cnum in tcx.crates_including_speculative(()) {
             for &impl_def_id in tcx.trait_impls_in_crate(cnum) {
                 cx.with_param_env(impl_def_id, |cx| {
                     inline::build_impl(cx, impl_def_id, None, &mut new_items_external);
diff --git a/src/librustdoc/scrape_examples.rs b/src/librustdoc/scrape_examples.rs
index e9b380fdeac..64753a58a2b 100644
--- a/src/librustdoc/scrape_examples.rs
+++ b/src/librustdoc/scrape_examples.rs
@@ -283,7 +283,7 @@ pub(crate) fn run(
         // Collect CrateIds corresponding to provided target crates
         // If two different versions of the crate in the dependency tree, then examples will be collected from both.
         let all_crates = tcx
-            .crates(())
+            .crates_including_speculative(())
             .iter()
             .chain([&LOCAL_CRATE])
             .map(|crate_num| (crate_num, tcx.crate_name(*crate_num)))
diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs
index 4c603bda770..94d4656377f 100644
--- a/src/tools/clippy/clippy_utils/src/lib.rs
+++ b/src/tools/clippy/clippy_utils/src/lib.rs
@@ -647,7 +647,7 @@ fn item_children_by_name(tcx: TyCtxt<'_>, def_id: DefId, name: Symbol) -> Vec<Re
 /// This function is expensive and should be used sparingly.
 pub fn def_path_res(cx: &LateContext<'_>, path: &[&str]) -> Vec<Res> {
     fn find_crates(tcx: TyCtxt<'_>, name: Symbol) -> impl Iterator<Item = DefId> + '_ {
-        tcx.crates(())
+        tcx.crates_including_speculative(())
             .iter()
             .copied()
             .filter(move |&num| tcx.crate_name(num) == name)
diff --git a/src/tools/compiletest/src/json.rs b/src/tools/compiletest/src/json.rs
index 10726b98420..29e8809e5bd 100644
--- a/src/tools/compiletest/src/json.rs
+++ b/src/tools/compiletest/src/json.rs
@@ -282,7 +282,7 @@ fn push_expected_errors(
 
     // Add notes for the backtrace
     for span in primary_spans {
-        for frame in &span.expansion {
+        if let Some(frame) = &span.expansion {
             push_backtrace(expected_errors, frame, file_name);
         }
     }
@@ -315,7 +315,7 @@ fn push_backtrace(
         });
     }
 
-    for previous_expansion in &expansion.span.expansion {
+    if let Some(previous_expansion) = &expansion.span.expansion {
         push_backtrace(expected_errors, previous_expansion, file_name);
     }
 }
diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version
index 22a6a297259..d3840775da9 100644
--- a/src/tools/miri/rust-version
+++ b/src/tools/miri/rust-version
@@ -1 +1 @@
-9cdfe285ca724c801dc9f78d22b24ea69b787f26
+78dd504f2fd87c0cfabff7d9174253411caf2f80
diff --git a/src/tools/miri/src/concurrency/data_race.rs b/src/tools/miri/src/concurrency/data_race.rs
index 3e8703d5cfc..a2884778578 100644
--- a/src/tools/miri/src/concurrency/data_race.rs
+++ b/src/tools/miri/src/concurrency/data_race.rs
@@ -648,7 +648,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: MiriInterpCxExt<'mir, 'tcx> {
         place: &MPlaceTy<'tcx, Provenance>,
         rhs: &ImmTy<'tcx, Provenance>,
         op: mir::BinOp,
-        neg: bool,
+        not: bool,
         atomic: AtomicRwOrd,
     ) -> InterpResult<'tcx, ImmTy<'tcx, Provenance>> {
         let this = self.eval_context_mut();
@@ -656,9 +656,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: MiriInterpCxExt<'mir, 'tcx> {
 
         let old = this.allow_data_races_mut(|this| this.read_immediate(place))?;
 
-        // Atomics wrap around on overflow.
-        let val = this.wrapping_binary_op(op, &old, rhs)?;
-        let val = if neg { this.wrapping_unary_op(mir::UnOp::Not, &val)? } else { val };
+        let val = this.binary_op(op, &old, rhs)?;
+        let val = if not { this.unary_op(mir::UnOp::Not, &val)? } else { val };
         this.allow_data_races_mut(|this| this.write_immediate(*val, place))?;
 
         this.validate_atomic_rmw(place, atomic)?;
@@ -700,7 +699,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: MiriInterpCxExt<'mir, 'tcx> {
         this.atomic_access_check(place, AtomicAccessType::Rmw)?;
 
         let old = this.allow_data_races_mut(|this| this.read_immediate(place))?;
-        let lt = this.wrapping_binary_op(mir::BinOp::Lt, &old, &rhs)?.to_scalar().to_bool()?;
+        let lt = this.binary_op(mir::BinOp::Lt, &old, &rhs)?.to_scalar().to_bool()?;
 
         #[rustfmt::skip] // rustfmt makes this unreadable
         let new_val = if min {
@@ -744,7 +743,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: MiriInterpCxExt<'mir, 'tcx> {
         // Read as immediate for the sake of `binary_op()`
         let old = this.allow_data_races_mut(|this| this.read_immediate(place))?;
         // `binary_op` will bail if either of them is not a scalar.
-        let eq = this.wrapping_binary_op(mir::BinOp::Eq, &old, expect_old)?;
+        let eq = this.binary_op(mir::BinOp::Eq, &old, expect_old)?;
         // If the operation would succeed, but is "weak", fail some portion
         // of the time, based on `success_rate`.
         let success_rate = 1.0 - this.machine.cmpxchg_weak_failure_rate;
diff --git a/src/tools/miri/src/helpers.rs b/src/tools/miri/src/helpers.rs
index 4050ae3c4bf..bd160380cd5 100644
--- a/src/tools/miri/src/helpers.rs
+++ b/src/tools/miri/src/helpers.rs
@@ -126,7 +126,7 @@ fn try_resolve_did(tcx: TyCtxt<'_>, path: &[&str], namespace: Option<Namespace>)
     // the one in the sysroot and the one locally built by `cargo test`.)
     // FIXME: can we prefer the one from the sysroot?
     'crates: for krate in
-        tcx.crates(()).iter().filter(|&&krate| tcx.crate_name(krate).as_str() == crate_name)
+        tcx.used_crates(()).iter().filter(|&&krate| tcx.crate_name(krate).as_str() == crate_name)
     {
         let mut cur_item = DefId { krate: *krate, index: CRATE_DEF_INDEX };
         // Go over the modules.
@@ -1365,7 +1365,7 @@ pub fn get_local_crates(tcx: TyCtxt<'_>) -> Vec<CrateNum> {
         .map(|crates| crates.split(',').map(|krate| krate.to_string()).collect::<Vec<_>>())
         .unwrap_or_default();
     let mut local_crates = Vec::new();
-    for &crate_num in tcx.crates(()) {
+    for &crate_num in tcx.crates_including_speculative(()) {
         let name = tcx.crate_name(crate_num);
         let name = name.as_str();
         if local_crate_names.iter().any(|local_name| local_name == name) {
diff --git a/src/tools/miri/src/intrinsics/atomic.rs b/src/tools/miri/src/intrinsics/atomic.rs
index 501dbc1603e..0daf59c943c 100644
--- a/src/tools/miri/src/intrinsics/atomic.rs
+++ b/src/tools/miri/src/intrinsics/atomic.rs
@@ -4,8 +4,8 @@ use crate::*;
 use helpers::check_arg_count;
 
 pub enum AtomicOp {
-    /// The `bool` indicates whether the result of the operation should be negated
-    /// (must be a boolean-typed operation).
+    /// The `bool` indicates whether the result of the operation should be negated (`UnOp::Not`,
+    /// must be a boolean-typed operation).
     MirOp(mir::BinOp, bool),
     Max,
     Min,
@@ -213,8 +213,8 @@ trait EvalContextPrivExt<'mir, 'tcx: 'mir>: MiriInterpCxExt<'mir, 'tcx> {
                 this.write_immediate(*old, dest)?; // old value is returned
                 Ok(())
             }
-            AtomicOp::MirOp(op, neg) => {
-                let old = this.atomic_rmw_op_immediate(&place, &rhs, op, neg, atomic)?;
+            AtomicOp::MirOp(op, not) => {
+                let old = this.atomic_rmw_op_immediate(&place, &rhs, op, not, atomic)?;
                 this.write_immediate(*old, dest)?; // old value is returned
                 Ok(())
             }
diff --git a/src/tools/miri/src/intrinsics/mod.rs b/src/tools/miri/src/intrinsics/mod.rs
index fdf637f2e8f..973a0c84a88 100644
--- a/src/tools/miri/src/intrinsics/mod.rs
+++ b/src/tools/miri/src/intrinsics/mod.rs
@@ -362,8 +362,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                     "frem_algebraic" => mir::BinOp::Rem,
                     _ => bug!(),
                 };
-                let res = this.wrapping_binary_op(op, &a, &b)?;
-                // `wrapping_binary_op` already called `generate_nan` if necessary.
+                let res = this.binary_op(op, &a, &b)?;
+                // `binary_op` already called `generate_nan` if necessary.
                 this.write_immediate(*res, dest)?;
             }
 
@@ -408,12 +408,12 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                     ),
                     _ => {}
                 }
-                let res = this.wrapping_binary_op(op, &a, &b)?;
+                let res = this.binary_op(op, &a, &b)?;
                 if !float_finite(&res)? {
                     throw_ub_format!("`{intrinsic_name}` intrinsic produced non-finite value as result");
                 }
                 // This cannot be a NaN so we also don't have to apply any non-determinism.
-                // (Also, `wrapping_binary_op` already called `generate_nan` if needed.)
+                // (Also, `binary_op` already called `generate_nan` if needed.)
                 this.write_immediate(*res, dest)?;
             }
 
diff --git a/src/tools/miri/src/intrinsics/simd.rs b/src/tools/miri/src/intrinsics/simd.rs
index e178187ffa6..67a2d565fa2 100644
--- a/src/tools/miri/src/intrinsics/simd.rs
+++ b/src/tools/miri/src/intrinsics/simd.rs
@@ -1,3 +1,5 @@
+use either::Either;
+
 use rustc_apfloat::{Float, Round};
 use rustc_middle::ty::layout::{HasParamEnv, LayoutOf};
 use rustc_middle::{mir, ty, ty::FloatTy};
@@ -82,7 +84,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                     let val = match which {
                         Op::MirOp(mir_op) => {
                             // This already does NaN adjustments
-                            this.wrapping_unary_op(mir_op, &op)?.to_scalar()
+                            this.unary_op(mir_op, &op)?.to_scalar()
                         }
                         Op::Abs => {
                             // Works for f32 and f64.
@@ -217,8 +219,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                     "mul" => Op::MirOp(BinOp::Mul),
                     "div" => Op::MirOp(BinOp::Div),
                     "rem" => Op::MirOp(BinOp::Rem),
-                    "shl" => Op::MirOp(BinOp::Shl),
-                    "shr" => Op::MirOp(BinOp::Shr),
+                    "shl" => Op::MirOp(BinOp::ShlUnchecked),
+                    "shr" => Op::MirOp(BinOp::ShrUnchecked),
                     "and" => Op::MirOp(BinOp::BitAnd),
                     "or" => Op::MirOp(BinOp::BitOr),
                     "xor" => Op::MirOp(BinOp::BitXor),
@@ -243,15 +245,19 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                     let val = match which {
                         Op::MirOp(mir_op) => {
                             // This does NaN adjustments.
-                            let (val, overflowed) = this.overflowing_binary_op(mir_op, &left, &right)?;
-                            if matches!(mir_op, BinOp::Shl | BinOp::Shr) {
-                                // Shifts have extra UB as SIMD operations that the MIR binop does not have.
-                                // See <https://github.com/rust-lang/rust/issues/91237>.
-                                if overflowed {
-                                    let r_val = right.to_scalar().to_bits(right.layout.size)?;
-                                    throw_ub_format!("overflowing shift by {r_val} in `simd_{intrinsic_name}` in SIMD lane {i}");
+                            let val = this.binary_op(mir_op, &left, &right).map_err(|err| {
+                                match err.kind() {
+                                    InterpError::UndefinedBehavior(UndefinedBehaviorInfo::ShiftOverflow { shift_amount, .. }) => {
+                                        // This resets the interpreter backtrace, but it's not worth avoiding that.
+                                        let shift_amount = match shift_amount {
+                                            Either::Left(v) => v.to_string(),
+                                            Either::Right(v) => v.to_string(),
+                                        };
+                                        err_ub_format!("overflowing shift by {shift_amount} in `simd_{intrinsic_name}` in lane {i}").into()
+                                    }
+                                    _ => err
                                 }
-                            }
+                            })?;
                             if matches!(mir_op, BinOp::Eq | BinOp::Ne | BinOp::Lt | BinOp::Le | BinOp::Gt | BinOp::Ge) {
                                 // Special handling for boolean-returning operations
                                 assert_eq!(val.layout.ty, this.tcx.types.bool);
@@ -370,11 +376,11 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                     let op = this.read_immediate(&this.project_index(&op, i)?)?;
                     res = match which {
                         Op::MirOp(mir_op) => {
-                            this.wrapping_binary_op(mir_op, &res, &op)?
+                            this.binary_op(mir_op, &res, &op)?
                         }
                         Op::MirOpBool(mir_op) => {
                             let op = imm_from_bool(simd_element_to_bool(op)?);
-                            this.wrapping_binary_op(mir_op, &res, &op)?
+                            this.binary_op(mir_op, &res, &op)?
                         }
                         Op::MinMax(mmop) => {
                             if matches!(res.layout.ty.kind(), ty::Float(_)) {
@@ -385,7 +391,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                                     MinMax::Min => BinOp::Le,
                                     MinMax::Max => BinOp::Ge,
                                 };
-                                if this.wrapping_binary_op(mirop, &res, &op)?.to_scalar().to_bool()? {
+                                if this.binary_op(mirop, &res, &op)?.to_scalar().to_bool()? {
                                     res
                                 } else {
                                     op
@@ -414,7 +420,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 let mut res = init;
                 for i in 0..op_len {
                     let op = this.read_immediate(&this.project_index(&op, i)?)?;
-                    res = this.wrapping_binary_op(mir_op, &res, &op)?;
+                    res = this.binary_op(mir_op, &res, &op)?;
                 }
                 this.write_immediate(*res, dest)?;
             }
diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs
index cbf02d701bc..0c6a2560b13 100644
--- a/src/tools/miri/src/machine.rs
+++ b/src/tools/miri/src/machine.rs
@@ -1025,7 +1025,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> {
         bin_op: mir::BinOp,
         left: &ImmTy<'tcx, Provenance>,
         right: &ImmTy<'tcx, Provenance>,
-    ) -> InterpResult<'tcx, (ImmTy<'tcx, Provenance>, bool)> {
+    ) -> InterpResult<'tcx, ImmTy<'tcx, Provenance>> {
         ecx.binary_ptr_op(bin_op, left, right)
     }
 
diff --git a/src/tools/miri/src/operator.rs b/src/tools/miri/src/operator.rs
index d99be39177b..7a008266dbc 100644
--- a/src/tools/miri/src/operator.rs
+++ b/src/tools/miri/src/operator.rs
@@ -14,7 +14,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         bin_op: mir::BinOp,
         left: &ImmTy<'tcx, Provenance>,
         right: &ImmTy<'tcx, Provenance>,
-    ) -> InterpResult<'tcx, (ImmTy<'tcx, Provenance>, bool)> {
+    ) -> InterpResult<'tcx, ImmTy<'tcx, Provenance>> {
         use rustc_middle::mir::BinOp::*;
 
         let this = self.eval_context_ref();
@@ -45,7 +45,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                     Ge => left >= right,
                     _ => bug!(),
                 };
-                (ImmTy::from_bool(res, *this.tcx), false)
+                ImmTy::from_bool(res, *this.tcx)
             }
 
             // Some more operations are possible with atomics.
@@ -60,16 +60,14 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                     right.to_scalar().to_target_usize(this)?,
                     this.machine.layouts.usize,
                 );
-                let (result, overflowing) = this.overflowing_binary_op(bin_op, &left, &right)?;
+                let result = this.binary_op(bin_op, &left, &right)?;
                 // Construct a new pointer with the provenance of `ptr` (the LHS).
                 let result_ptr = Pointer::new(
                     ptr.provenance,
                     Size::from_bytes(result.to_scalar().to_target_usize(this)?),
                 );
-                (
-                    ImmTy::from_scalar(Scalar::from_maybe_pointer(result_ptr, this), left.layout),
-                    overflowing,
-                )
+
+                ImmTy::from_scalar(Scalar::from_maybe_pointer(result_ptr, this), left.layout)
             }
 
             _ => span_bug!(this.cur_span(), "Invalid operator on pointers: {:?}", bin_op),
diff --git a/src/tools/miri/src/shims/x86/mod.rs b/src/tools/miri/src/shims/x86/mod.rs
index 48b7222917b..04ad979cf5d 100644
--- a/src/tools/miri/src/shims/x86/mod.rs
+++ b/src/tools/miri/src/shims/x86/mod.rs
@@ -50,13 +50,16 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>:
                 let a = this.read_immediate(a)?;
                 let b = this.read_immediate(b)?;
 
-                let (sum, overflow1) = this.overflowing_binary_op(mir::BinOp::Add, &a, &b)?;
-                let (sum, overflow2) = this.overflowing_binary_op(
-                    mir::BinOp::Add,
-                    &sum,
-                    &ImmTy::from_uint(c_in, a.layout),
-                )?;
-                let c_out = overflow1 | overflow2;
+                let (sum, overflow1) =
+                    this.binary_op(mir::BinOp::AddWithOverflow, &a, &b)?.to_pair(this);
+                let (sum, overflow2) = this
+                    .binary_op(
+                        mir::BinOp::AddWithOverflow,
+                        &sum,
+                        &ImmTy::from_uint(c_in, a.layout),
+                    )?
+                    .to_pair(this);
+                let c_out = overflow1.to_scalar().to_bool()? | overflow2.to_scalar().to_bool()?;
 
                 this.write_scalar(Scalar::from_u8(c_out.into()), &this.project_field(dest, 0)?)?;
                 this.write_immediate(*sum, &this.project_field(dest, 1)?)?;
@@ -76,13 +79,16 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>:
                 let a = this.read_immediate(a)?;
                 let b = this.read_immediate(b)?;
 
-                let (sub, overflow1) = this.overflowing_binary_op(mir::BinOp::Sub, &a, &b)?;
-                let (sub, overflow2) = this.overflowing_binary_op(
-                    mir::BinOp::Sub,
-                    &sub,
-                    &ImmTy::from_uint(b_in, a.layout),
-                )?;
-                let b_out = overflow1 | overflow2;
+                let (sub, overflow1) =
+                    this.binary_op(mir::BinOp::SubWithOverflow, &a, &b)?.to_pair(this);
+                let (sub, overflow2) = this
+                    .binary_op(
+                        mir::BinOp::SubWithOverflow,
+                        &sub,
+                        &ImmTy::from_uint(b_in, a.layout),
+                    )?
+                    .to_pair(this);
+                let b_out = overflow1.to_scalar().to_bool()? | overflow2.to_scalar().to_bool()?;
 
                 this.write_scalar(Scalar::from_u8(b_out.into()), &this.project_field(dest, 0)?)?;
                 this.write_immediate(*sub, &this.project_field(dest, 1)?)?;
@@ -245,7 +251,7 @@ fn bin_op_float<'tcx, F: rustc_apfloat::Float>(
 ) -> InterpResult<'tcx, Scalar<Provenance>> {
     match which {
         FloatBinOp::Arith(which) => {
-            let res = this.wrapping_binary_op(which, left, right)?;
+            let res = this.binary_op(which, left, right)?;
             Ok(res.to_scalar())
         }
         FloatBinOp::Cmp { gt, lt, eq, unord } => {
@@ -744,12 +750,9 @@ fn int_abs<'tcx>(
         let op = this.read_immediate(&this.project_index(&op, i)?)?;
         let dest = this.project_index(&dest, i)?;
 
-        let lt_zero = this.wrapping_binary_op(mir::BinOp::Lt, &op, &zero)?;
-        let res = if lt_zero.to_scalar().to_bool()? {
-            this.wrapping_unary_op(mir::UnOp::Neg, &op)?
-        } else {
-            op
-        };
+        let lt_zero = this.binary_op(mir::BinOp::Lt, &op, &zero)?;
+        let res =
+            if lt_zero.to_scalar().to_bool()? { this.unary_op(mir::UnOp::Neg, &op)? } else { op };
 
         this.write_immediate(*res, &dest)?;
     }
@@ -832,7 +835,7 @@ fn horizontal_bin_op<'tcx>(
             let res = if saturating {
                 Immediate::from(this.saturating_arith(which, &lhs, &rhs)?)
             } else {
-                *this.wrapping_binary_op(which, &lhs, &rhs)?
+                *this.binary_op(which, &lhs, &rhs)?
             };
 
             this.write_immediate(res, &this.project_index(&dest, j)?)?;
@@ -884,8 +887,8 @@ fn conditional_dot_product<'tcx>(
                 let left = this.read_immediate(&this.project_index(&left, j)?)?;
                 let right = this.read_immediate(&this.project_index(&right, j)?)?;
 
-                let mul = this.wrapping_binary_op(mir::BinOp::Mul, &left, &right)?;
-                sum = this.wrapping_binary_op(mir::BinOp::Add, &sum, &mul)?;
+                let mul = this.binary_op(mir::BinOp::Mul, &left, &right)?;
+                sum = this.binary_op(mir::BinOp::Add, &sum, &mul)?;
             }
         }
 
@@ -1276,11 +1279,8 @@ fn psign<'tcx>(
         let left = this.read_immediate(&this.project_index(&left, i)?)?;
         let right = this.read_scalar(&this.project_index(&right, i)?)?.to_int(dest.layout.size)?;
 
-        let res = this.wrapping_binary_op(
-            mir::BinOp::Mul,
-            &left,
-            &ImmTy::from_int(right.signum(), dest.layout),
-        )?;
+        let res =
+            this.binary_op(mir::BinOp::Mul, &left, &ImmTy::from_int(right.signum(), dest.layout))?;
 
         this.write_immediate(*res, &dest)?;
     }
diff --git a/src/tools/miri/tests/fail/intrinsics/simd-shl-too-far.rs b/src/tools/miri/tests/fail/intrinsics/simd-shl-too-far.rs
index 8a49c8403ae..12aa7c10af4 100644
--- a/src/tools/miri/tests/fail/intrinsics/simd-shl-too-far.rs
+++ b/src/tools/miri/tests/fail/intrinsics/simd-shl-too-far.rs
@@ -10,6 +10,6 @@ fn main() {
     unsafe {
         let x = i32x2(1, 1);
         let y = i32x2(100, 0);
-        simd_shl(x, y); //~ERROR: overflowing shift by 100 in `simd_shl` in SIMD lane 0
+        simd_shl(x, y); //~ERROR: overflowing shift by 100 in `simd_shl` in lane 0
     }
 }
diff --git a/src/tools/miri/tests/fail/intrinsics/simd-shl-too-far.stderr b/src/tools/miri/tests/fail/intrinsics/simd-shl-too-far.stderr
index 3a4ec008b44..475067db801 100644
--- a/src/tools/miri/tests/fail/intrinsics/simd-shl-too-far.stderr
+++ b/src/tools/miri/tests/fail/intrinsics/simd-shl-too-far.stderr
@@ -1,8 +1,8 @@
-error: Undefined Behavior: overflowing shift by 100 in `simd_shl` in SIMD lane 0
+error: Undefined Behavior: overflowing shift by 100 in `simd_shl` in lane 0
   --> $DIR/simd-shl-too-far.rs:LL:CC
    |
 LL |         simd_shl(x, y);
-   |         ^^^^^^^^^^^^^^ overflowing shift by 100 in `simd_shl` in SIMD lane 0
+   |         ^^^^^^^^^^^^^^ overflowing shift by 100 in `simd_shl` in lane 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
diff --git a/src/tools/miri/tests/fail/intrinsics/simd-shr-too-far.rs b/src/tools/miri/tests/fail/intrinsics/simd-shr-too-far.rs
index 433998cbde6..ada7cf408c4 100644
--- a/src/tools/miri/tests/fail/intrinsics/simd-shr-too-far.rs
+++ b/src/tools/miri/tests/fail/intrinsics/simd-shr-too-far.rs
@@ -10,6 +10,6 @@ fn main() {
     unsafe {
         let x = i32x2(1, 1);
         let y = i32x2(20, 40);
-        simd_shr(x, y); //~ERROR: overflowing shift by 40 in `simd_shr` in SIMD lane 1
+        simd_shr(x, y); //~ERROR: overflowing shift by 40 in `simd_shr` in lane 1
     }
 }
diff --git a/src/tools/miri/tests/fail/intrinsics/simd-shr-too-far.stderr b/src/tools/miri/tests/fail/intrinsics/simd-shr-too-far.stderr
index 07636b8c0bb..0d6307837de 100644
--- a/src/tools/miri/tests/fail/intrinsics/simd-shr-too-far.stderr
+++ b/src/tools/miri/tests/fail/intrinsics/simd-shr-too-far.stderr
@@ -1,8 +1,8 @@
-error: Undefined Behavior: overflowing shift by 40 in `simd_shr` in SIMD lane 1
+error: Undefined Behavior: overflowing shift by 40 in `simd_shr` in lane 1
   --> $DIR/simd-shr-too-far.rs:LL:CC
    |
 LL |         simd_shr(x, y);
-   |         ^^^^^^^^^^^^^^ overflowing shift by 40 in `simd_shr` in SIMD lane 1
+   |         ^^^^^^^^^^^^^^ overflowing shift by 40 in `simd_shr` in lane 1
    |
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
diff --git a/src/tools/miri/tests/fail/intrinsics/unchecked_add1.rs b/src/tools/miri/tests/fail/intrinsics/unchecked_add1.rs
index 3f8b4e55151..0ed758da2a3 100644
--- a/src/tools/miri/tests/fail/intrinsics/unchecked_add1.rs
+++ b/src/tools/miri/tests/fail/intrinsics/unchecked_add1.rs
@@ -1,4 +1,4 @@
 fn main() {
     // MAX overflow
-    let _val = unsafe { 40000u16.unchecked_add(30000) }; //~ ERROR: overflow executing `unchecked_add`
+    let _val = unsafe { 40000u16.unchecked_add(30000) }; //~ ERROR: arithmetic overflow in `unchecked_add`
 }
diff --git a/src/tools/miri/tests/fail/intrinsics/unchecked_add1.stderr b/src/tools/miri/tests/fail/intrinsics/unchecked_add1.stderr
index 922de4226fa..eae9ec7a44d 100644
--- a/src/tools/miri/tests/fail/intrinsics/unchecked_add1.stderr
+++ b/src/tools/miri/tests/fail/intrinsics/unchecked_add1.stderr
@@ -1,8 +1,8 @@
-error: Undefined Behavior: overflow executing `unchecked_add`
+error: Undefined Behavior: arithmetic overflow in `unchecked_add`
   --> $DIR/unchecked_add1.rs:LL:CC
    |
 LL |     let _val = unsafe { 40000u16.unchecked_add(30000) };
-   |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflow executing `unchecked_add`
+   |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ arithmetic overflow in `unchecked_add`
    |
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
diff --git a/src/tools/miri/tests/fail/intrinsics/unchecked_add2.rs b/src/tools/miri/tests/fail/intrinsics/unchecked_add2.rs
index 3283dbf8e7e..3b495203eb4 100644
--- a/src/tools/miri/tests/fail/intrinsics/unchecked_add2.rs
+++ b/src/tools/miri/tests/fail/intrinsics/unchecked_add2.rs
@@ -1,4 +1,4 @@
 fn main() {
     // MIN overflow
-    let _val = unsafe { (-30000i16).unchecked_add(-8000) }; //~ ERROR: overflow executing `unchecked_add`
+    let _val = unsafe { (-30000i16).unchecked_add(-8000) }; //~ ERROR: arithmetic overflow in `unchecked_add`
 }
diff --git a/src/tools/miri/tests/fail/intrinsics/unchecked_add2.stderr b/src/tools/miri/tests/fail/intrinsics/unchecked_add2.stderr
index 05456eaf195..6a0dcfcd227 100644
--- a/src/tools/miri/tests/fail/intrinsics/unchecked_add2.stderr
+++ b/src/tools/miri/tests/fail/intrinsics/unchecked_add2.stderr
@@ -1,8 +1,8 @@
-error: Undefined Behavior: overflow executing `unchecked_add`
+error: Undefined Behavior: arithmetic overflow in `unchecked_add`
   --> $DIR/unchecked_add2.rs:LL:CC
    |
 LL |     let _val = unsafe { (-30000i16).unchecked_add(-8000) };
-   |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflow executing `unchecked_add`
+   |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ arithmetic overflow in `unchecked_add`
    |
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
diff --git a/src/tools/miri/tests/fail/intrinsics/unchecked_mul1.rs b/src/tools/miri/tests/fail/intrinsics/unchecked_mul1.rs
index 2feed7759ec..3dc83a2dcef 100644
--- a/src/tools/miri/tests/fail/intrinsics/unchecked_mul1.rs
+++ b/src/tools/miri/tests/fail/intrinsics/unchecked_mul1.rs
@@ -1,4 +1,4 @@
 fn main() {
     // MAX overflow
-    let _val = unsafe { 300u16.unchecked_mul(250u16) }; //~ ERROR: overflow executing `unchecked_mul`
+    let _val = unsafe { 300u16.unchecked_mul(250u16) }; //~ ERROR: arithmetic overflow in `unchecked_mul`
 }
diff --git a/src/tools/miri/tests/fail/intrinsics/unchecked_mul1.stderr b/src/tools/miri/tests/fail/intrinsics/unchecked_mul1.stderr
index 533beaa65ff..e37d9827c8c 100644
--- a/src/tools/miri/tests/fail/intrinsics/unchecked_mul1.stderr
+++ b/src/tools/miri/tests/fail/intrinsics/unchecked_mul1.stderr
@@ -1,8 +1,8 @@
-error: Undefined Behavior: overflow executing `unchecked_mul`
+error: Undefined Behavior: arithmetic overflow in `unchecked_mul`
   --> $DIR/unchecked_mul1.rs:LL:CC
    |
 LL |     let _val = unsafe { 300u16.unchecked_mul(250u16) };
-   |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflow executing `unchecked_mul`
+   |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ arithmetic overflow in `unchecked_mul`
    |
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
diff --git a/src/tools/miri/tests/fail/intrinsics/unchecked_mul2.rs b/src/tools/miri/tests/fail/intrinsics/unchecked_mul2.rs
index 42cd509404a..49cd293737c 100644
--- a/src/tools/miri/tests/fail/intrinsics/unchecked_mul2.rs
+++ b/src/tools/miri/tests/fail/intrinsics/unchecked_mul2.rs
@@ -1,4 +1,4 @@
 fn main() {
     // MIN overflow
-    let _val = unsafe { 1_000_000_000i32.unchecked_mul(-4) }; //~ ERROR: overflow executing `unchecked_mul`
+    let _val = unsafe { 1_000_000_000i32.unchecked_mul(-4) }; //~ ERROR: arithmetic overflow in `unchecked_mul`
 }
diff --git a/src/tools/miri/tests/fail/intrinsics/unchecked_mul2.stderr b/src/tools/miri/tests/fail/intrinsics/unchecked_mul2.stderr
index 4c6bae6f0bf..949077ce61d 100644
--- a/src/tools/miri/tests/fail/intrinsics/unchecked_mul2.stderr
+++ b/src/tools/miri/tests/fail/intrinsics/unchecked_mul2.stderr
@@ -1,8 +1,8 @@
-error: Undefined Behavior: overflow executing `unchecked_mul`
+error: Undefined Behavior: arithmetic overflow in `unchecked_mul`
   --> $DIR/unchecked_mul2.rs:LL:CC
    |
 LL |     let _val = unsafe { 1_000_000_000i32.unchecked_mul(-4) };
-   |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflow executing `unchecked_mul`
+   |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ arithmetic overflow in `unchecked_mul`
    |
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
diff --git a/src/tools/miri/tests/fail/intrinsics/unchecked_sub1.rs b/src/tools/miri/tests/fail/intrinsics/unchecked_sub1.rs
index e5178bf4eff..f24c9742094 100644
--- a/src/tools/miri/tests/fail/intrinsics/unchecked_sub1.rs
+++ b/src/tools/miri/tests/fail/intrinsics/unchecked_sub1.rs
@@ -1,4 +1,4 @@
 fn main() {
     // MIN overflow
-    let _val = unsafe { 14u32.unchecked_sub(22) }; //~ ERROR: overflow executing `unchecked_sub`
+    let _val = unsafe { 14u32.unchecked_sub(22) }; //~ ERROR: arithmetic overflow in `unchecked_sub`
 }
diff --git a/src/tools/miri/tests/fail/intrinsics/unchecked_sub1.stderr b/src/tools/miri/tests/fail/intrinsics/unchecked_sub1.stderr
index 72187e20e23..39bfd8a2384 100644
--- a/src/tools/miri/tests/fail/intrinsics/unchecked_sub1.stderr
+++ b/src/tools/miri/tests/fail/intrinsics/unchecked_sub1.stderr
@@ -1,8 +1,8 @@
-error: Undefined Behavior: overflow executing `unchecked_sub`
+error: Undefined Behavior: arithmetic overflow in `unchecked_sub`
   --> $DIR/unchecked_sub1.rs:LL:CC
    |
 LL |     let _val = unsafe { 14u32.unchecked_sub(22) };
-   |                         ^^^^^^^^^^^^^^^^^^^^^^^ overflow executing `unchecked_sub`
+   |                         ^^^^^^^^^^^^^^^^^^^^^^^ arithmetic overflow in `unchecked_sub`
    |
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
diff --git a/src/tools/miri/tests/fail/intrinsics/unchecked_sub2.rs b/src/tools/miri/tests/fail/intrinsics/unchecked_sub2.rs
index ac9fd1e5d06..74b08b1dfb4 100644
--- a/src/tools/miri/tests/fail/intrinsics/unchecked_sub2.rs
+++ b/src/tools/miri/tests/fail/intrinsics/unchecked_sub2.rs
@@ -1,4 +1,4 @@
 fn main() {
     // MAX overflow
-    let _val = unsafe { 30000i16.unchecked_sub(-7000) }; //~ ERROR: overflow executing `unchecked_sub`
+    let _val = unsafe { 30000i16.unchecked_sub(-7000) }; //~ ERROR: arithmetic overflow in `unchecked_sub`
 }
diff --git a/src/tools/miri/tests/fail/intrinsics/unchecked_sub2.stderr b/src/tools/miri/tests/fail/intrinsics/unchecked_sub2.stderr
index ec28384f633..604eba99e01 100644
--- a/src/tools/miri/tests/fail/intrinsics/unchecked_sub2.stderr
+++ b/src/tools/miri/tests/fail/intrinsics/unchecked_sub2.stderr
@@ -1,8 +1,8 @@
-error: Undefined Behavior: overflow executing `unchecked_sub`
+error: Undefined Behavior: arithmetic overflow in `unchecked_sub`
   --> $DIR/unchecked_sub2.rs:LL:CC
    |
 LL |     let _val = unsafe { 30000i16.unchecked_sub(-7000) };
-   |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflow executing `unchecked_sub`
+   |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ arithmetic overflow in `unchecked_sub`
    |
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
diff --git a/src/tools/run-make-support/src/cc.rs b/src/tools/run-make-support/src/cc.rs
index a67f5c8a9ee..799c36b1049 100644
--- a/src/tools/run-make-support/src/cc.rs
+++ b/src/tools/run-make-support/src/cc.rs
@@ -45,6 +45,14 @@ impl Cc {
         self
     }
 
+    /// Adds directories to the list that the linker searches for libraries.
+    /// Equivalent to `-L`.
+    pub fn library_search_path<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
+        self.cmd.arg("-L");
+        self.cmd.arg(path.as_ref());
+        self
+    }
+
     /// Specify `-o` or `-Fe`/`-Fo` depending on platform/compiler. This assumes that the executable
     /// is under `$TMPDIR`.
     pub fn out_exe(&mut self, name: &str) -> &mut Self {
diff --git a/src/tools/run-make-support/src/rustc.rs b/src/tools/run-make-support/src/rustc.rs
index f581204d5f1..1c83b630861 100644
--- a/src/tools/run-make-support/src/rustc.rs
+++ b/src/tools/run-make-support/src/rustc.rs
@@ -156,13 +156,20 @@ impl Rustc {
         self
     }
 
-    /// Add a directory to the library search path. Equivalent to `-L`` in rustc.
+    /// Add a directory to the library search path. Equivalent to `-L` in rustc.
     pub fn library_search_path<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
         self.cmd.arg("-L");
         self.cmd.arg(path.as_ref());
         self
     }
 
+    /// Override the system root. Equivalent to `--sysroot` in rustc.
+    pub fn sysroot<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
+        self.cmd.arg("--sysroot");
+        self.cmd.arg(path.as_ref());
+        self
+    }
+
     /// Specify the edition year.
     pub fn edition(&mut self, edition: &str) -> &mut Self {
         self.cmd.arg("--edition");
diff --git a/src/tools/tidy/src/allowed_run_make_makefiles.txt b/src/tools/tidy/src/allowed_run_make_makefiles.txt
index 9233dd8c89f..ad900ce0386 100644
--- a/src/tools/tidy/src/allowed_run_make_makefiles.txt
+++ b/src/tools/tidy/src/allowed_run_make_makefiles.txt
@@ -25,7 +25,6 @@ run-make/compiler-rt-works-on-mingw/Makefile
 run-make/compressed-debuginfo/Makefile
 run-make/const-prop-lint/Makefile
 run-make/const_fn_mir/Makefile
-run-make/core-no-oom-handling/Makefile
 run-make/crate-data-smoke/Makefile
 run-make/crate-hash-rustc-version/Makefile
 run-make/crate-name-priority/Makefile
@@ -98,24 +97,19 @@ run-make/issue-15460/Makefile
 run-make/issue-18943/Makefile
 run-make/issue-20626/Makefile
 run-make/issue-22131/Makefile
-run-make/issue-24445/Makefile
 run-make/issue-25581/Makefile
 run-make/issue-26006/Makefile
 run-make/issue-26092/Makefile
 run-make/issue-28595/Makefile
-run-make/issue-30063/Makefile
 run-make/issue-33329/Makefile
 run-make/issue-35164/Makefile
 run-make/issue-36710/Makefile
 run-make/issue-37839/Makefile
 run-make/issue-37893/Makefile
-run-make/issue-38237/Makefile
 run-make/issue-40535/Makefile
-run-make/issue-46239/Makefile
 run-make/issue-47384/Makefile
 run-make/issue-47551/Makefile
 run-make/issue-51671/Makefile
-run-make/issue-53964/Makefile
 run-make/issue-64153/Makefile
 run-make/issue-68794-textrel-on-minimal-lib/Makefile
 run-make/issue-69368/Makefile
@@ -233,7 +227,6 @@ run-make/rlib-format-packed-bundled-libs/Makefile
 run-make/rmeta-preferred/Makefile
 run-make/rustc-macro-dep-files/Makefile
 run-make/rustdoc-io-error/Makefile
-run-make/rustdoc-scrape-examples-macros/Makefile
 run-make/rustdoc-verify-output-files/Makefile
 run-make/rustdoc-with-output-option/Makefile
 run-make/sanitizer-cdylib-link/Makefile
diff --git a/src/tools/tidy/src/issues.txt b/src/tools/tidy/src/issues.txt
index 6b8106bbc21..881b4f84173 100644
--- a/src/tools/tidy/src/issues.txt
+++ b/src/tools/tidy/src/issues.txt
@@ -3988,8 +3988,6 @@ ui/test-attrs/issue-52557.rs
 ui/test-attrs/issue-53675-a-test-called-panic.rs
 ui/threads-sendsync/issue-24313.rs
 ui/threads-sendsync/issue-29488.rs
-ui/threads-sendsync/issue-43733-2.rs
-ui/threads-sendsync/issue-43733.rs
 ui/threads-sendsync/issue-4446.rs
 ui/threads-sendsync/issue-4448.rs
 ui/threads-sendsync/issue-8827.rs
diff --git a/src/tools/tidy/src/style.rs b/src/tools/tidy/src/style.rs
index 9cabab582d0..64cc2277620 100644
--- a/src/tools/tidy/src/style.rs
+++ b/src/tools/tidy/src/style.rs
@@ -243,7 +243,7 @@ pub fn is_in(full_path: &Path, parent_folder_to_find: &str, folder_to_find: &str
         if parent.file_name().map_or_else(
             || false,
             |f| {
-                f.to_string_lossy() == folder_to_find
+                f == folder_to_find
                     && parent
                         .parent()
                         .and_then(|f| f.file_name())
diff --git a/tests/codegen/noalias-freeze.rs b/tests/codegen/noalias-freeze.rs
new file mode 100644
index 00000000000..8086f3afbbc
--- /dev/null
+++ b/tests/codegen/noalias-freeze.rs
@@ -0,0 +1,21 @@
+//@ compile-flags: -Copt-level=1
+
+// References returned by a Frozen pointer type
+// could be marked as "noalias", which caused miscompilation errors.
+// This test runs the most minimal possible code that can reproduce this bug,
+// and checks that noalias does not appear.
+// See https://github.com/rust-lang/rust/issues/46239
+
+#![crate_type = "lib"]
+
+fn project<T>(x: &(T,)) -> &T { &x.0 }
+
+fn dummy() {}
+
+// CHECK-LABEL: @foo(
+// CHECK-NOT: noalias
+#[no_mangle]
+pub fn foo() {
+    let f = (dummy as fn(),);
+    (*project(&f))();
+}
diff --git a/tests/crashes/124348.rs b/tests/crashes/124348.rs
deleted file mode 100644
index 554f383026c..00000000000
--- a/tests/crashes/124348.rs
+++ /dev/null
@@ -1,7 +0,0 @@
-//@ known-bug: #124348
-enum Eek {
-    TheConst,
-    UnusedByTheConst(Sum),
-}
-
-const EEK_ZERO: &[Eek] = &[];
diff --git a/tests/run-make/alloc-no-oom-handling/rmake.rs b/tests/run-make/alloc-no-oom-handling/rmake.rs
index fec3c653294..4bca5d1f1ef 100644
--- a/tests/run-make/alloc-no-oom-handling/rmake.rs
+++ b/tests/run-make/alloc-no-oom-handling/rmake.rs
@@ -1,4 +1,4 @@
-// This test checks that alloc can still compile correctly
+// This test checks that alloc can still compile successfully
 // when the unstable no_global_oom_handling feature is turned on.
 // See https://github.com/rust-lang/rust/pull/84266
 
diff --git a/tests/run-make/alloc-no-rc/rmake.rs b/tests/run-make/alloc-no-rc/rmake.rs
index c5744a3f5ee..8ff73324b08 100644
--- a/tests/run-make/alloc-no-rc/rmake.rs
+++ b/tests/run-make/alloc-no-rc/rmake.rs
@@ -1,4 +1,4 @@
-// This test checks that alloc can still compile correctly
+// This test checks that alloc can still compile successfully
 // when the unstable no_rc feature is turned on.
 // See https://github.com/rust-lang/rust/pull/84266
 
diff --git a/tests/run-make/alloc-no-sync/rmake.rs b/tests/run-make/alloc-no-sync/rmake.rs
index 6410eca80ab..3a3ceed6867 100644
--- a/tests/run-make/alloc-no-sync/rmake.rs
+++ b/tests/run-make/alloc-no-sync/rmake.rs
@@ -1,4 +1,4 @@
-// This test checks that alloc can still compile correctly
+// This test checks that alloc can still compile successfully
 // when the unstable no_sync feature is turned on.
 // See https://github.com/rust-lang/rust/pull/84266
 
diff --git a/tests/run-make/core-no-oom-handling/Makefile b/tests/run-make/core-no-oom-handling/Makefile
deleted file mode 100644
index 28c5261ff85..00000000000
--- a/tests/run-make/core-no-oom-handling/Makefile
+++ /dev/null
@@ -1,6 +0,0 @@
-include ../tools.mk
-
-FAKEROOT=$(TMPDIR)/fakeroot
-
-all:
-	$(RUSTC) --edition=2021 -Dwarnings --crate-type=rlib ../../../library/core/src/lib.rs --sysroot=$(FAKEROOT) --cfg no_global_oom_handling
diff --git a/tests/run-make/core-no-oom-handling/rmake.rs b/tests/run-make/core-no-oom-handling/rmake.rs
new file mode 100644
index 00000000000..75767421cd1
--- /dev/null
+++ b/tests/run-make/core-no-oom-handling/rmake.rs
@@ -0,0 +1,16 @@
+// This test checks that the core library can still compile successfully
+// when the no_global_oom_handling feature is turned on.
+// See https://github.com/rust-lang/rust/pull/110649
+
+use run_make_support::{rustc, tmp_dir};
+
+fn main() {
+    rustc()
+        .edition("2021")
+        .arg("-Dwarnings")
+        .crate_type("rlib")
+        .input("../../../library/core/src/lib.rs")
+        .sysroot(tmp_dir().join("fakeroot"))
+        .cfg("no_global_oom_handling")
+        .run();
+}
diff --git a/tests/run-make/issue-38237/bar.rs b/tests/run-make/deref-impl-rustdoc-ice/bar.rs
index 2b839f3a3b3..2b839f3a3b3 100644
--- a/tests/run-make/issue-38237/bar.rs
+++ b/tests/run-make/deref-impl-rustdoc-ice/bar.rs
diff --git a/tests/run-make/issue-38237/baz.rs b/tests/run-make/deref-impl-rustdoc-ice/baz.rs
index cd2425f9b69..cd2425f9b69 100644
--- a/tests/run-make/issue-38237/baz.rs
+++ b/tests/run-make/deref-impl-rustdoc-ice/baz.rs
diff --git a/tests/run-make/issue-38237/foo.rs b/tests/run-make/deref-impl-rustdoc-ice/foo.rs
index a106e4fde5c..a106e4fde5c 100644
--- a/tests/run-make/issue-38237/foo.rs
+++ b/tests/run-make/deref-impl-rustdoc-ice/foo.rs
diff --git a/tests/run-make/deref-impl-rustdoc-ice/rmake.rs b/tests/run-make/deref-impl-rustdoc-ice/rmake.rs
new file mode 100644
index 00000000000..c2156de03a9
--- /dev/null
+++ b/tests/run-make/deref-impl-rustdoc-ice/rmake.rs
@@ -0,0 +1,16 @@
+// A very specific set of circumstances (mainly, implementing Deref, and
+// having a procedural macro and a Debug derivation in external crates) caused
+// an internal compiler error (ICE) when trying to use rustdoc. This test
+// reproduces the exact circumstances which caused the bug and checks
+// that it does not happen again.
+// See https://github.com/rust-lang/rust/issues/38237
+
+//@ ignore-cross-compile
+
+use run_make_support::{rustc, rustdoc, tmp_dir};
+
+fn main() {
+    rustc().input("foo.rs").run();
+    rustc().input("bar.rs").run();
+    rustdoc().input("baz.rs").library_search_path(tmp_dir()).output(tmp_dir()).run();
+}
diff --git a/tests/run-make/issue-53964/app.rs b/tests/run-make/external-crate-panic-handle-no-lint/app.rs
index 8127b9578bf..8127b9578bf 100644
--- a/tests/run-make/issue-53964/app.rs
+++ b/tests/run-make/external-crate-panic-handle-no-lint/app.rs
diff --git a/tests/run-make/issue-53964/panic.rs b/tests/run-make/external-crate-panic-handle-no-lint/panic.rs
index a8781205071..a8781205071 100644
--- a/tests/run-make/issue-53964/panic.rs
+++ b/tests/run-make/external-crate-panic-handle-no-lint/panic.rs
diff --git a/tests/run-make/external-crate-panic-handle-no-lint/rmake.rs b/tests/run-make/external-crate-panic-handle-no-lint/rmake.rs
new file mode 100644
index 00000000000..de4023282ef
--- /dev/null
+++ b/tests/run-make/external-crate-panic-handle-no-lint/rmake.rs
@@ -0,0 +1,12 @@
+// Defining a crate that provides panic handling as an external crate
+// could uselessly trigger the "unused external crate" lint. In this test,
+// if the lint is triggered, it will trip #![deny(unused_extern_crates)],
+// and cause the test to fail.
+// See https://github.com/rust-lang/rust/issues/53964
+
+use run_make_support::{rustc, tmp_dir};
+
+fn main() {
+    rustc().input("panic.rs").run();
+    rustc().input("app.rs").panic("abort").emit("obj").library_search_path(tmp_dir()).run();
+}
diff --git a/tests/run-make/issue-24445/Makefile b/tests/run-make/issue-24445/Makefile
deleted file mode 100644
index a13910aa73e..00000000000
--- a/tests/run-make/issue-24445/Makefile
+++ /dev/null
@@ -1,11 +0,0 @@
-# ignore-cross-compile
-include ../tools.mk
-
-# only-linux
-
-all:
-	$(RUSTC) foo.rs
-	$(CC) foo.c -lfoo -L $(TMPDIR) -Wl,--gc-sections -lpthread -ldl -o $(TMPDIR)/foo
-	$(call RUN,foo)
-	$(CC) foo.c -lfoo -L $(TMPDIR) -Wl,--gc-sections -lpthread -ldl -pie -fPIC -o $(TMPDIR)/foo
-	$(call RUN,foo)
diff --git a/tests/run-make/issue-30063/Makefile b/tests/run-make/issue-30063/Makefile
deleted file mode 100644
index 8a69ca79f51..00000000000
--- a/tests/run-make/issue-30063/Makefile
+++ /dev/null
@@ -1,36 +0,0 @@
-# ignore-cross-compile
-include ../tools.mk
-
-all:
-	rm -f $(TMPDIR)/foo-output
-	$(RUSTC) -C codegen-units=4 -o $(TMPDIR)/foo-output foo.rs
-	rm $(TMPDIR)/foo-output
-
-	rm -f $(TMPDIR)/asm-output
-	$(RUSTC) -C codegen-units=4 --emit=asm -o $(TMPDIR)/asm-output foo.rs
-	rm $(TMPDIR)/asm-output
-
-	rm -f $(TMPDIR)/bc-output
-	$(RUSTC) -C codegen-units=4 --emit=llvm-bc -o $(TMPDIR)/bc-output foo.rs
-	rm $(TMPDIR)/bc-output
-
-	rm -f $(TMPDIR)/ir-output
-	$(RUSTC) -C codegen-units=4 --emit=llvm-ir -o $(TMPDIR)/ir-output foo.rs
-	rm $(TMPDIR)/ir-output
-
-	rm -f $(TMPDIR)/link-output
-	$(RUSTC) -C codegen-units=4 --emit=link -o $(TMPDIR)/link-output foo.rs
-	rm $(TMPDIR)/link-output
-
-	rm -f $(TMPDIR)/obj-output
-	$(RUSTC) -C codegen-units=4 --emit=obj -o $(TMPDIR)/obj-output foo.rs
-	rm $(TMPDIR)/obj-output
-
-	rm -f $(TMPDIR)/dep-output
-	$(RUSTC) -C codegen-units=4 --emit=dep-info -o $(TMPDIR)/dep-output foo.rs
-	rm $(TMPDIR)/dep-output
-
-#	# (This case doesn't work yet, and may be fundamentally wrong-headed anyway.)
-#	rm -f $(TMPDIR)/multi-output
-#	$(RUSTC) -C codegen-units=4 --emit=asm,obj -o $(TMPDIR)/multi-output foo.rs
-#	rm $(TMPDIR)/multi-output
diff --git a/tests/run-make/issue-38237/Makefile b/tests/run-make/issue-38237/Makefile
deleted file mode 100644
index 80dddc5bd13..00000000000
--- a/tests/run-make/issue-38237/Makefile
+++ /dev/null
@@ -1,6 +0,0 @@
-# ignore-cross-compile
-include ../tools.mk
-
-all:
-	$(RUSTC) foo.rs; $(RUSTC) bar.rs
-	$(RUSTDOC) baz.rs -L $(TMPDIR) -o $(TMPDIR)
diff --git a/tests/run-make/issue-46239/Makefile b/tests/run-make/issue-46239/Makefile
deleted file mode 100644
index 0006ced2515..00000000000
--- a/tests/run-make/issue-46239/Makefile
+++ /dev/null
@@ -1,6 +0,0 @@
-# ignore-cross-compile
-include ../tools.mk
-
-all:
-	$(RUSTC) main.rs -C opt-level=1
-	$(call RUN,main)
diff --git a/tests/run-make/issue-46239/main.rs b/tests/run-make/issue-46239/main.rs
deleted file mode 100644
index b7df5cf4d81..00000000000
--- a/tests/run-make/issue-46239/main.rs
+++ /dev/null
@@ -1,8 +0,0 @@
-fn project<T>(x: &(T,)) -> &T { &x.0 }
-
-fn dummy() {}
-
-fn main() {
-    let f = (dummy as fn(),);
-    (*project(&f))();
-}
diff --git a/tests/run-make/issue-53964/Makefile b/tests/run-make/issue-53964/Makefile
deleted file mode 100644
index 6bd83021374..00000000000
--- a/tests/run-make/issue-53964/Makefile
+++ /dev/null
@@ -1,5 +0,0 @@
-include ../tools.mk
-
-all:
-	$(RUSTC) panic.rs
-	$(RUSTC) -C panic=abort --emit=obj app.rs -L $(TMPDIR)
diff --git a/tests/run-make/issue-24445/foo.c b/tests/run-make/non-pie-thread-local/foo.c
index bb4036b06e1..bb4036b06e1 100644
--- a/tests/run-make/issue-24445/foo.c
+++ b/tests/run-make/non-pie-thread-local/foo.c
diff --git a/tests/run-make/issue-24445/foo.rs b/tests/run-make/non-pie-thread-local/foo.rs
index b67f3847cd4..b67f3847cd4 100644
--- a/tests/run-make/issue-24445/foo.rs
+++ b/tests/run-make/non-pie-thread-local/foo.rs
diff --git a/tests/run-make/non-pie-thread-local/rmake.rs b/tests/run-make/non-pie-thread-local/rmake.rs
new file mode 100644
index 00000000000..1ef447e7860
--- /dev/null
+++ b/tests/run-make/non-pie-thread-local/rmake.rs
@@ -0,0 +1,34 @@
+// It was once required to use a position-independent executable (PIE)
+// in order to use the thread_local! macro, or some symbols would contain
+// a NULL address. This was fixed, and this test checks a non-PIE, then a PIE
+// build to see if this bug makes a resurgence.
+// See https://github.com/rust-lang/rust/pull/24448
+
+//@ ignore-cross-compile
+//@ only-linux
+
+use run_make_support::{cc, run, rustc, tmp_dir};
+
+fn main() {
+    rustc().input("foo.rs").run();
+    cc().input("foo.c")
+        .arg("-lfoo")
+        .library_search_path(tmp_dir())
+        .arg("-Wl,--gc-sections")
+        .arg("-lpthread")
+        .arg("-ldl")
+        .out_exe("foo")
+        .run();
+    run("foo");
+    cc().input("foo.c")
+        .arg("-lfoo")
+        .library_search_path(tmp_dir())
+        .arg("-Wl,--gc-sections")
+        .arg("-lpthread")
+        .arg("-ldl")
+        .arg("-pie")
+        .arg("-fPIC")
+        .out_exe("foo")
+        .run();
+    run("foo");
+}
diff --git a/tests/run-make/issue-30063/foo.rs b/tests/run-make/reset-codegen-1/foo.rs
index 45590d86ba6..45590d86ba6 100644
--- a/tests/run-make/issue-30063/foo.rs
+++ b/tests/run-make/reset-codegen-1/foo.rs
diff --git a/tests/run-make/reset-codegen-1/rmake.rs b/tests/run-make/reset-codegen-1/rmake.rs
new file mode 100644
index 00000000000..4b91ba7df90
--- /dev/null
+++ b/tests/run-make/reset-codegen-1/rmake.rs
@@ -0,0 +1,38 @@
+// When rustc received 4 codegen-units, an output path and an emit flag all simultaneously,
+// this could cause an annoying recompilation issue, uselessly lengthening the build process.
+// A fix was delivered, which resets codegen-units to 1 when necessary,
+// but as it directly affected the way codegen-units are manipulated,
+// this test was created to check that this fix did not cause compilation failures.
+// See https://github.com/rust-lang/rust/issues/30063
+
+//@ ignore-cross-compile
+
+use run_make_support::{rustc, tmp_dir};
+use std::fs;
+
+fn compile(output_file: &str, emit: Option<&str>) {
+    let mut rustc = rustc();
+    let rustc = rustc.codegen_units(4).output(tmp_dir().join(output_file)).input("foo.rs");
+    if let Some(emit) = emit {
+        rustc.emit(emit);
+    }
+    rustc.run();
+}
+
+fn main() {
+    let flags = [
+        ("foo-output", None),
+        ("asm-output", Some("asm")),
+        ("bc-output", Some("llvm-bc")),
+        ("ir-output", Some("llvm-ir")),
+        ("link-output", Some("link")),
+        ("obj-output", Some("obj")),
+        ("dep-output", Some("dep-info")),
+        ("multi-output", Some("asm,obj")),
+    ];
+    for (output_file, emit) in flags {
+        fs::remove_file(output_file).unwrap_or_default();
+        compile(output_file, emit);
+        fs::remove_file(output_file);
+    }
+}
diff --git a/tests/run-make/rustdoc-scrape-examples-macros/Makefile b/tests/run-make/rustdoc-scrape-examples-macros/Makefile
deleted file mode 100644
index edc19d8cb5d..00000000000
--- a/tests/run-make/rustdoc-scrape-examples-macros/Makefile
+++ /dev/null
@@ -1,19 +0,0 @@
-# ignore-cross-compile
-include ../../run-make/tools.mk
-
-OUTPUT_DIR := "$(TMPDIR)/rustdoc"
-DYLIB_NAME := $(shell echo | $(RUSTC) --crate-name foobar_macro --crate-type dylib --print file-names -)
-
-all:
-	$(RUSTC) src/proc.rs --crate-name foobar_macro --edition=2021 --crate-type proc-macro --emit=dep-info,link
-
-	$(RUSTC) src/lib.rs --crate-name foobar --edition=2021 --crate-type lib --emit=dep-info,link
-
-	$(RUSTDOC) examples/ex.rs --crate-name ex --crate-type bin --output $(OUTPUT_DIR) \
-		--extern foobar=$(TMPDIR)/libfoobar.rlib --extern foobar_macro=$(TMPDIR)/$(DYLIB_NAME) \
-		-Z unstable-options --scrape-examples-output-path $(TMPDIR)/ex.calls --scrape-examples-target-crate foobar
-
-	$(RUSTDOC) src/lib.rs --crate-name foobar --crate-type lib --output $(OUTPUT_DIR) \
-		-Z unstable-options --with-examples $(TMPDIR)/ex.calls
-
-	$(HTMLDOCCK) $(OUTPUT_DIR) src/lib.rs
diff --git a/tests/run-make/rustdoc-scrape-examples-macros/rmake.rs b/tests/run-make/rustdoc-scrape-examples-macros/rmake.rs
new file mode 100644
index 00000000000..81b7defafc6
--- /dev/null
+++ b/tests/run-make/rustdoc-scrape-examples-macros/rmake.rs
@@ -0,0 +1,64 @@
+//@ ignore-cross-compile
+
+use run_make_support::{htmldocck, rustc, rustdoc, tmp_dir};
+
+fn main() {
+    let tmp_dir = tmp_dir();
+    let out_dir = tmp_dir.join("rustdoc");
+    let ex_dir = tmp_dir.join("ex.calls");
+    let proc_crate_name = "foobar_macro";
+    let crate_name = "foobar";
+
+    let dylib_name = String::from_utf8(
+        rustc()
+            .crate_name(proc_crate_name)
+            .crate_type("dylib")
+            .arg("--print")
+            .arg("file-names")
+            .arg("-")
+            .command_output()
+            .stdout,
+    )
+    .unwrap();
+
+    rustc()
+        .input("src/proc.rs")
+        .crate_name(proc_crate_name)
+        .edition("2021")
+        .crate_type("proc-macro")
+        .emit("dep-info,link")
+        .run();
+    rustc()
+        .input("src/lib.rs")
+        .crate_name(crate_name)
+        .edition("2021")
+        .crate_type("lib")
+        .emit("dep-info,link")
+        .run();
+
+    rustdoc()
+        .input("examples/ex.rs")
+        .crate_name("ex")
+        .crate_type("bin")
+        .output(&out_dir)
+        .extern_(crate_name, tmp_dir.join(format!("lib{crate_name}.rlib")))
+        .extern_(proc_crate_name, tmp_dir.join(dylib_name.trim()))
+        .arg("-Zunstable-options")
+        .arg("--scrape-examples-output-path")
+        .arg(&ex_dir)
+        .arg("--scrape-examples-target-crate")
+        .arg(crate_name)
+        .run();
+
+    rustdoc()
+        .input("src/lib.rs")
+        .crate_name(crate_name)
+        .crate_type("lib")
+        .output(&out_dir)
+        .arg("-Zunstable-options")
+        .arg("--with-examples")
+        .arg(&ex_dir)
+        .run();
+
+    assert!(htmldocck().arg(out_dir).arg("src/lib.rs").status().unwrap().success());
+}
diff --git a/tests/ui-fulldeps/stable-mir/check_intrinsics.rs b/tests/ui-fulldeps/stable-mir/check_intrinsics.rs
index 171850b89bb..7e247ce0c75 100644
--- a/tests/ui-fulldeps/stable-mir/check_intrinsics.rs
+++ b/tests/ui-fulldeps/stable-mir/check_intrinsics.rs
@@ -11,6 +11,7 @@
 //@ ignore-windows-gnu mingw has troubles with linking https://github.com/rust-lang/rust/pull/116837
 
 #![feature(rustc_private)]
+#![feature(assert_matches)]
 
 extern crate rustc_hir;
 #[macro_use]
@@ -23,8 +24,8 @@ use rustc_smir::rustc_internal;
 use stable_mir::mir::mono::{Instance, InstanceKind};
 use stable_mir::mir::visit::{Location, MirVisitor};
 use stable_mir::mir::{LocalDecl, Terminator, TerminatorKind};
-use stable_mir::ty::{RigidTy, TyKind};
-use std::collections::HashSet;
+use stable_mir::ty::{FnDef, GenericArgs, RigidTy, TyKind};
+use std::assert_matches::assert_matches;
 use std::convert::TryFrom;
 use std::io::Write;
 use std::ops::ControlFlow;
@@ -39,9 +40,10 @@ fn test_intrinsics() -> ControlFlow<()> {
     visitor.visit_body(&main_body);
 
     let calls = visitor.calls;
-    assert_eq!(calls.len(), 2, "Expected 2 calls, but found: {calls:?}");
-    for intrinsic in &calls {
-        check_intrinsic(intrinsic)
+    assert_eq!(calls.len(), 3, "Expected 3 calls, but found: {calls:?}");
+    for (fn_def, args) in calls.into_iter() {
+        check_instance(&Instance::resolve(fn_def, &args).unwrap());
+        check_def(fn_def);
     }
 
     ControlFlow::Continue(())
@@ -53,22 +55,39 @@ fn test_intrinsics() -> ControlFlow<()> {
 ///
 /// If by any chance this test breaks because you changed how an intrinsic is implemented, please
 /// update the test to invoke a different intrinsic.
-fn check_intrinsic(intrinsic: &Instance) {
-    assert_eq!(intrinsic.kind, InstanceKind::Intrinsic);
-    let name = intrinsic.intrinsic_name().unwrap();
-    if intrinsic.has_body() {
-        let Some(body) = intrinsic.body() else { unreachable!("Expected a body") };
+fn check_instance(instance: &Instance) {
+    assert_eq!(instance.kind, InstanceKind::Intrinsic);
+    let name = instance.intrinsic_name().unwrap();
+    if instance.has_body() {
+        let Some(body) = instance.body() else { unreachable!("Expected a body") };
         assert!(!body.blocks.is_empty());
-        assert_eq!(&name, "likely");
+        assert_matches!(name.as_str(), "likely" | "vtable_size");
     } else {
-        assert!(intrinsic.body().is_none());
+        assert!(instance.body().is_none());
         assert_eq!(&name, "size_of_val");
     }
 }
 
+fn check_def(fn_def: FnDef) {
+    assert!(fn_def.is_intrinsic());
+    let intrinsic = fn_def.as_intrinsic().unwrap();
+    assert_eq!(fn_def, intrinsic.into());
+
+    let name = intrinsic.fn_name();
+    match name.as_str() {
+        "likely" | "size_of_val" => {
+            assert!(!intrinsic.must_be_overridden());
+        }
+        "vtable_size" => {
+            assert!(intrinsic.must_be_overridden());
+        }
+        _ => unreachable!("Unexpected intrinsic: {}", name),
+    }
+}
+
 struct CallsVisitor<'a> {
     locals: &'a [LocalDecl],
-    calls: HashSet<Instance>,
+    calls: Vec<(FnDef, GenericArgs)>,
 }
 
 impl<'a> MirVisitor for CallsVisitor<'a> {
@@ -77,10 +96,10 @@ impl<'a> MirVisitor for CallsVisitor<'a> {
             TerminatorKind::Call { func, .. } => {
                 let TyKind::RigidTy(RigidTy::FnDef(def, args)) =
                     func.ty(self.locals).unwrap().kind()
-                    else {
-                        return;
-                    };
-                self.calls.insert(Instance::resolve(def, &args).unwrap());
+                else {
+                    return;
+                };
+                self.calls.push((def, args.clone()));
             }
             _ => {}
         }
@@ -106,6 +125,7 @@ fn generate_input(path: &str) -> std::io::Result<()> {
         #![feature(core_intrinsics)]
         use std::intrinsics::*;
         pub fn use_intrinsics(init: bool) -> bool {{
+            let vtable_sz = unsafe {{ vtable_size(0 as *const ()) }};
             let sz = unsafe {{ size_of_val("hi") }};
             likely(init && sz == 2)
         }}
diff --git a/tests/ui/async-await/async-is-unwindsafe.rs b/tests/ui/async-await/async-is-unwindsafe.rs
index d0202f72f00..53009b6e741 100644
--- a/tests/ui/async-await/async-is-unwindsafe.rs
+++ b/tests/ui/async-await/async-is-unwindsafe.rs
@@ -11,7 +11,6 @@ fn main() {
 
     is_unwindsafe(async {
         //~^ ERROR the type `&mut Context<'_>` may not be safely transferred across an unwind boundary
-        //~| ERROR the type `&mut (dyn Any + 'static)` may not be safely transferred across an unwind boundary
         use std::ptr::null;
         use std::task::{Context, RawWaker, RawWakerVTable, Waker};
         let waker = unsafe {
diff --git a/tests/ui/async-await/async-is-unwindsafe.stderr b/tests/ui/async-await/async-is-unwindsafe.stderr
index 6bb06df9f39..5d87fc74768 100644
--- a/tests/ui/async-await/async-is-unwindsafe.stderr
+++ b/tests/ui/async-await/async-is-unwindsafe.stderr
@@ -6,18 +6,19 @@ LL |        is_unwindsafe(async {
    |  |_____|
    | ||
 LL | ||
-LL | ||
 LL | ||         use std::ptr::null;
+LL | ||         use std::task::{Context, RawWaker, RawWakerVTable, Waker};
 ...  ||
 LL | ||         drop(cx_ref);
 LL | ||     });
    | ||_____-^ `&mut Context<'_>` may not be safely transferred across an unwind boundary
    |  |_____|
-   |        within this `{async block@$DIR/async-is-unwindsafe.rs:12:19: 30:6}`
+   |        within this `{async block@$DIR/async-is-unwindsafe.rs:12:19: 29:6}`
    |
-   = help: within `{async block@$DIR/async-is-unwindsafe.rs:12:19: 30:6}`, the trait `UnwindSafe` is not implemented for `&mut Context<'_>`, which is required by `{async block@$DIR/async-is-unwindsafe.rs:12:19: 30:6}: UnwindSafe`
+   = help: within `{async block@$DIR/async-is-unwindsafe.rs:12:19: 29:6}`, the trait `UnwindSafe` is not implemented for `&mut Context<'_>`, which is required by `{async block@$DIR/async-is-unwindsafe.rs:12:19: 29:6}: UnwindSafe`
+   = note: `UnwindSafe` is implemented for `&Context<'_>`, but not for `&mut Context<'_>`
 note: future does not implement `UnwindSafe` as this value is used across an await
-  --> $DIR/async-is-unwindsafe.rs:26:18
+  --> $DIR/async-is-unwindsafe.rs:25:18
    |
 LL |         let cx_ref = &mut cx;
    |             ------ has type `&mut Context<'_>` which does not implement `UnwindSafe`
@@ -30,38 +31,6 @@ note: required by a bound in `is_unwindsafe`
 LL | fn is_unwindsafe(_: impl std::panic::UnwindSafe) {}
    |                          ^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_unwindsafe`
 
-error[E0277]: the type `&mut (dyn Any + 'static)` may not be safely transferred across an unwind boundary
-  --> $DIR/async-is-unwindsafe.rs:12:5
-   |
-LL |        is_unwindsafe(async {
-   |   _____^_____________-
-   |  |_____|
-   | ||
-LL | ||
-LL | ||
-LL | ||         use std::ptr::null;
-...  ||
-LL | ||         drop(cx_ref);
-LL | ||     });
-   | ||_____-^ `&mut (dyn Any + 'static)` may not be safely transferred across an unwind boundary
-   |  |_____|
-   |        within this `{async block@$DIR/async-is-unwindsafe.rs:12:19: 30:6}`
-   |
-   = help: within `{async block@$DIR/async-is-unwindsafe.rs:12:19: 30:6}`, the trait `UnwindSafe` is not implemented for `&mut (dyn Any + 'static)`, which is required by `{async block@$DIR/async-is-unwindsafe.rs:12:19: 30:6}: UnwindSafe`
-note: future does not implement `UnwindSafe` as this value is used across an await
-  --> $DIR/async-is-unwindsafe.rs:26:18
-   |
-LL |         let mut cx = Context::from_waker(&waker);
-   |             ------ has type `Context<'_>` which does not implement `UnwindSafe`
-...
-LL |         async {}.await; // this needs an inner await point
-   |                  ^^^^^ await occurs here, with `mut cx` maybe used later
-note: required by a bound in `is_unwindsafe`
-  --> $DIR/async-is-unwindsafe.rs:3:26
-   |
-LL | fn is_unwindsafe(_: impl std::panic::UnwindSafe) {}
-   |                          ^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_unwindsafe`
-
-error: aborting due to 2 previous errors
+error: aborting due to 1 previous error
 
 For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/async-await/context-is-sorta-unwindsafe.rs b/tests/ui/async-await/context-is-sorta-unwindsafe.rs
new file mode 100644
index 00000000000..278476ea237
--- /dev/null
+++ b/tests/ui/async-await/context-is-sorta-unwindsafe.rs
@@ -0,0 +1,14 @@
+//@ run-pass
+// Tests against a regression surfaced by crater in https://github.com/rust-lang/rust/issues/125193
+// Unwind Safety is not a very coherent concept, but we'd prefer no regressions until we kibosh it
+// and this is an unstable feature anyways sooo...
+
+use std::panic::UnwindSafe;
+use std::task::Context;
+
+fn unwind_safe<T: UnwindSafe>() {}
+
+fn main() {
+    unwind_safe::<Context<'_>>(); // test UnwindSafe
+    unwind_safe::<&Context<'_>>(); // test RefUnwindSafe
+}
diff --git a/tests/ui/check-cfg/cargo-build-script.rs b/tests/ui/check-cfg/cargo-build-script.rs
new file mode 100644
index 00000000000..a3ba8791441
--- /dev/null
+++ b/tests/ui/check-cfg/cargo-build-script.rs
@@ -0,0 +1,22 @@
+// This test checks that when we are building a build script provided
+// by Cargo we only suggest expecting the unexpected cfgs in the Cargo.toml.
+//
+//@ check-pass
+//@ no-auto-check-cfg
+//@ rustc-env:CARGO_CRATE_NAME=build_script_build
+//@ compile-flags:--crate-name=build_script_build
+//@ compile-flags:--check-cfg=cfg(has_bar)
+
+#[cfg(has_foo)]
+//~^ WARNING unexpected `cfg` condition name
+fn foo() {}
+
+#[cfg(has_foo = "yes")]
+//~^ WARNING unexpected `cfg` condition name
+fn foo() {}
+
+#[cfg(has_bar = "yes")]
+//~^ WARNING unexpected `cfg` condition value
+fn has_bar() {}
+
+fn main() {}
diff --git a/tests/ui/check-cfg/cargo-build-script.stderr b/tests/ui/check-cfg/cargo-build-script.stderr
new file mode 100644
index 00000000000..9ab3290ef22
--- /dev/null
+++ b/tests/ui/check-cfg/cargo-build-script.stderr
@@ -0,0 +1,43 @@
+warning: unexpected `cfg` condition name: `has_foo`
+  --> $DIR/cargo-build-script.rs:10:7
+   |
+LL | #[cfg(has_foo)]
+   |       ^^^^^^^
+   |
+   = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `has_bar`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, and `windows`
+   = help: consider using a Cargo feature instead
+   = help: or consider adding in `Cargo.toml` the `check-cfg` lint config for the lint:
+            [lints.rust]
+            unexpected_cfgs = { level = "warn", check-cfg = ['cfg(has_foo)'] }
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg/cargo-specifics.html> for more information about checking conditional configuration
+   = note: `#[warn(unexpected_cfgs)]` on by default
+
+warning: unexpected `cfg` condition name: `has_foo`
+  --> $DIR/cargo-build-script.rs:14:7
+   |
+LL | #[cfg(has_foo = "yes")]
+   |       ^^^^^^^^^^^^^^^
+   |
+   = help: consider using a Cargo feature instead
+   = help: or consider adding in `Cargo.toml` the `check-cfg` lint config for the lint:
+            [lints.rust]
+            unexpected_cfgs = { level = "warn", check-cfg = ['cfg(has_foo, values("yes"))'] }
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg/cargo-specifics.html> for more information about checking conditional configuration
+
+warning: unexpected `cfg` condition value: `yes`
+  --> $DIR/cargo-build-script.rs:18:7
+   |
+LL | #[cfg(has_bar = "yes")]
+   |       ^^^^^^^--------
+   |              |
+   |              help: remove the value
+   |
+   = note: no expected value for `has_bar`
+   = help: consider using a Cargo feature instead
+   = help: or consider adding in `Cargo.toml` the `check-cfg` lint config for the lint:
+            [lints.rust]
+            unexpected_cfgs = { level = "warn", check-cfg = ['cfg(has_bar, values("yes"))'] }
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg/cargo-specifics.html> for more information about checking conditional configuration
+
+warning: 3 warnings emitted
+
diff --git a/tests/ui/consts/const-int-unchecked.stderr b/tests/ui/consts/const-int-unchecked.stderr
index 84b222972a1..3130603231e 100644
--- a/tests/ui/consts/const-int-unchecked.stderr
+++ b/tests/ui/consts/const-int-unchecked.stderr
@@ -242,19 +242,19 @@ error[E0080]: evaluation of constant value failed
   --> $DIR/const-int-unchecked.rs:123:25
    |
 LL | const _: u16 = unsafe { std::intrinsics::unchecked_add(40000u16, 30000) };
-   |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflow executing `unchecked_add`
+   |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ arithmetic overflow in `unchecked_add`
 
 error[E0080]: evaluation of constant value failed
   --> $DIR/const-int-unchecked.rs:126:25
    |
 LL | const _: u32 = unsafe { std::intrinsics::unchecked_sub(14u32, 22) };
-   |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflow executing `unchecked_sub`
+   |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ arithmetic overflow in `unchecked_sub`
 
 error[E0080]: evaluation of constant value failed
   --> $DIR/const-int-unchecked.rs:129:25
    |
 LL | const _: u16 = unsafe { std::intrinsics::unchecked_mul(300u16, 250u16) };
-   |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflow executing `unchecked_mul`
+   |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ arithmetic overflow in `unchecked_mul`
 
 error[E0080]: evaluation of constant value failed
   --> $DIR/const-int-unchecked.rs:132:25
diff --git a/tests/ui/consts/erroneous_type_in_const_return_value.rs b/tests/ui/consts/erroneous_type_in_const_return_value.rs
new file mode 100644
index 00000000000..304211f77da
--- /dev/null
+++ b/tests/ui/consts/erroneous_type_in_const_return_value.rs
@@ -0,0 +1,12 @@
+//! ICE test #124348
+//! We should not be running const eval if the layout has errors.
+
+enum Eek {
+    TheConst,
+    UnusedByTheConst(Sum),
+    //~^ ERROR cannot find type `Sum` in this scope
+}
+
+const EEK_ZERO: &[Eek] = &[];
+
+fn main() {}
diff --git a/tests/ui/consts/erroneous_type_in_const_return_value.stderr b/tests/ui/consts/erroneous_type_in_const_return_value.stderr
new file mode 100644
index 00000000000..453f5b64097
--- /dev/null
+++ b/tests/ui/consts/erroneous_type_in_const_return_value.stderr
@@ -0,0 +1,14 @@
+error[E0412]: cannot find type `Sum` in this scope
+  --> $DIR/erroneous_type_in_const_return_value.rs:6:22
+   |
+LL |     UnusedByTheConst(Sum),
+   |                      ^^^ not found in this scope
+   |
+help: consider importing this trait
+   |
+LL + use std::iter::Sum;
+   |
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0412`.
diff --git a/tests/ui/consts/erroneous_type_in_promoted.rs b/tests/ui/consts/erroneous_type_in_promoted.rs
new file mode 100644
index 00000000000..32e33c2030f
--- /dev/null
+++ b/tests/ui/consts/erroneous_type_in_promoted.rs
@@ -0,0 +1,14 @@
+//! ICE test #124348
+//! We should not be running const eval if the layout has errors.
+
+enum Eek {
+    TheConst,
+    UnusedByTheConst(Sum),
+    //~^ ERROR cannot find type `Sum` in this scope
+}
+
+const fn foo() {
+    let x: &'static [Eek] = &[];
+}
+
+fn main() {}
diff --git a/tests/ui/consts/erroneous_type_in_promoted.stderr b/tests/ui/consts/erroneous_type_in_promoted.stderr
new file mode 100644
index 00000000000..0601fc9ebe7
--- /dev/null
+++ b/tests/ui/consts/erroneous_type_in_promoted.stderr
@@ -0,0 +1,14 @@
+error[E0412]: cannot find type `Sum` in this scope
+  --> $DIR/erroneous_type_in_promoted.rs:6:22
+   |
+LL |     UnusedByTheConst(Sum),
+   |                      ^^^ not found in this scope
+   |
+help: consider importing this trait
+   |
+LL + use std::iter::Sum;
+   |
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0412`.
diff --git a/tests/ui/extern-flag/empty-extern-arg.stderr b/tests/ui/extern-flag/empty-extern-arg.stderr
index 2785b12a0ae..6ad3effe0e2 100644
--- a/tests/ui/extern-flag/empty-extern-arg.stderr
+++ b/tests/ui/extern-flag/empty-extern-arg.stderr
@@ -1,13 +1,6 @@
 error: extern location for std does not exist: 
 
-error: `#[panic_handler]` function required, but not found
-
-error: unwinding panics are not supported without std
-   |
-   = help: using nightly cargo, use -Zbuild-std with panic="abort" to avoid unwinding
-   = note: since the core library is usually precompiled with panic="unwind", rebuilding your crate with panic="abort" may not be enough to fix the problem
-
 error: requires `sized` lang_item
 
-error: aborting due to 4 previous errors
+error: aborting due to 2 previous errors
 
diff --git a/tests/ui/fn/fn_def_opaque_coercion_to_fn_ptr.rs b/tests/ui/fn/fn_def_opaque_coercion_to_fn_ptr.rs
new file mode 100644
index 00000000000..5250e3a3d93
--- /dev/null
+++ b/tests/ui/fn/fn_def_opaque_coercion_to_fn_ptr.rs
@@ -0,0 +1,57 @@
+//! Test that coercing between function items of different functions works,
+//! as long as their signatures match. The resulting value is a function pointer.
+
+#![feature(type_alias_impl_trait)]
+
+fn foo<T>(t: T) -> T {
+    t
+}
+
+fn bar<T>(t: T) -> T {
+    t
+}
+
+type F = impl Sized;
+
+fn f(a: F) {
+    let mut x = bar::<F>;
+    x = foo::<()>; //~ ERROR: mismatched types
+    x(a);
+    x(());
+}
+
+type I = impl Sized;
+
+fn i(a: I) {
+    let mut x = bar::<()>;
+    x = foo::<I>; //~ ERROR: mismatched types
+    x(a);
+    x(());
+}
+
+type J = impl Sized;
+
+fn j(a: J) {
+    let x = match true {
+        true => bar::<J>,
+        false => foo::<()>,
+    };
+    x(a);
+    x(());
+}
+
+fn k() -> impl Sized {
+    fn bind<T, F: FnOnce(T) -> T>(_: T, f: F) -> F {
+        f
+    }
+    let x = match true {
+        true => {
+            let f = foo;
+            bind(k(), f)
+        }
+        false => bar::<()>,
+    };
+    todo!()
+}
+
+fn main() {}
diff --git a/tests/ui/fn/fn_def_opaque_coercion_to_fn_ptr.stderr b/tests/ui/fn/fn_def_opaque_coercion_to_fn_ptr.stderr
new file mode 100644
index 00000000000..0b3331b040d
--- /dev/null
+++ b/tests/ui/fn/fn_def_opaque_coercion_to_fn_ptr.stderr
@@ -0,0 +1,38 @@
+error[E0308]: mismatched types
+  --> $DIR/fn_def_opaque_coercion_to_fn_ptr.rs:18:9
+   |
+LL | type F = impl Sized;
+   |          ---------- the expected opaque type
+...
+LL |     let mut x = bar::<F>;
+   |                 -------- expected due to this value
+LL |     x = foo::<()>;
+   |         ^^^^^^^^^ expected fn item, found a different fn item
+   |
+   = note: expected fn item `fn(F) -> F {bar::<F>}`
+              found fn item `fn(()) {foo::<()>}`
+
+error[E0308]: mismatched types
+  --> $DIR/fn_def_opaque_coercion_to_fn_ptr.rs:27:9
+   |
+LL | fn foo<T>(t: T) -> T {
+   | -------------------- function `foo` defined here
+...
+LL | type I = impl Sized;
+   |          ---------- the found opaque type
+...
+LL |     let mut x = bar::<()>;
+   |                 --------- expected due to this value
+LL |     x = foo::<I>;
+   |         ^^^^^^^^ expected fn item, found a different fn item
+   |
+   = note: expected fn item `fn(()) {bar::<()>}`
+              found fn item `fn(I) -> I {foo::<I>}`
+help: use parentheses to call this function
+   |
+LL |     x = foo::<I>(/* I */);
+   |                 +++++++++
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/inference/note-and-explain-ReVar-124973.rs b/tests/ui/inference/note-and-explain-ReVar-124973.rs
new file mode 100644
index 00000000000..f1e24645636
--- /dev/null
+++ b/tests/ui/inference/note-and-explain-ReVar-124973.rs
@@ -0,0 +1,8 @@
+//@ edition:2018
+
+#![feature(c_variadic)]
+
+async unsafe extern "C" fn multiple_named_lifetimes<'a, 'b>(_: u8, ...) {}
+//~^ ERROR hidden type for `impl Future<Output = ()>` captures lifetime that does not appear in bounds
+
+fn main() {}
diff --git a/tests/ui/inference/note-and-explain-ReVar-124973.stderr b/tests/ui/inference/note-and-explain-ReVar-124973.stderr
new file mode 100644
index 00000000000..574f6508e4c
--- /dev/null
+++ b/tests/ui/inference/note-and-explain-ReVar-124973.stderr
@@ -0,0 +1,13 @@
+error[E0700]: hidden type for `impl Future<Output = ()>` captures lifetime that does not appear in bounds
+  --> $DIR/note-and-explain-ReVar-124973.rs:5:73
+   |
+LL | async unsafe extern "C" fn multiple_named_lifetimes<'a, 'b>(_: u8, ...) {}
+   | ----------------------------------------------------------------------- ^^
+   | |
+   | opaque type defined here
+   |
+   = note: hidden type `{async fn body of multiple_named_lifetimes<'a, 'b>()}` captures lifetime `'_`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0700`.
diff --git a/tests/ui/lint/for_loop_over_fallibles.rs b/tests/ui/lint/for_loop_over_fallibles.rs
index 52c3b8f2aae..89ac20c3521 100644
--- a/tests/ui/lint/for_loop_over_fallibles.rs
+++ b/tests/ui/lint/for_loop_over_fallibles.rs
@@ -41,3 +41,25 @@ fn _returns_result() -> Result<(), ()> {
 
     Ok(())
 }
+
+fn _by_ref() {
+    // Shared refs
+    for _ in &Some(1) {}
+    //~^ WARN for loop over a `&Option`. This is more readably written as an `if let` statement
+    //~| HELP to check pattern in a loop use `while let`
+    //~| HELP consider using `if let` to clear intent
+    for _ in &Ok::<_, ()>(1) {}
+    //~^ WARN for loop over a `&Result`. This is more readably written as an `if let` statement
+    //~| HELP to check pattern in a loop use `while let`
+    //~| HELP consider using `if let` to clear intent
+
+    // Mutable refs
+    for _ in &mut Some(1) {}
+    //~^ WARN for loop over a `&mut Option`. This is more readably written as an `if let` statement
+    //~| HELP to check pattern in a loop use `while let`
+    //~| HELP consider using `if let` to clear intent
+    for _ in &mut Ok::<_, ()>(1) {}
+    //~^ WARN for loop over a `&mut Result`. This is more readably written as an `if let` statement
+    //~| HELP to check pattern in a loop use `while let`
+    //~| HELP consider using `if let` to clear intent
+}
diff --git a/tests/ui/lint/for_loop_over_fallibles.stderr b/tests/ui/lint/for_loop_over_fallibles.stderr
index 96efdf85c49..f695de08257 100644
--- a/tests/ui/lint/for_loop_over_fallibles.stderr
+++ b/tests/ui/lint/for_loop_over_fallibles.stderr
@@ -97,5 +97,65 @@ help: consider using `if let` to clear intent
 LL |     if let Ok(_) = Ok::<_, ()>([0; 0]) {}
    |     ~~~~~~~~~~ ~~~
 
-warning: 6 warnings emitted
+warning: for loop over a `&Option`. This is more readably written as an `if let` statement
+  --> $DIR/for_loop_over_fallibles.rs:47:14
+   |
+LL |     for _ in &Some(1) {}
+   |              ^^^^^^^^
+   |
+help: to check pattern in a loop use `while let`
+   |
+LL |     while let Some(_) = &Some(1) {}
+   |     ~~~~~~~~~~~~~~~ ~~~
+help: consider using `if let` to clear intent
+   |
+LL |     if let Some(_) = &Some(1) {}
+   |     ~~~~~~~~~~~~ ~~~
+
+warning: for loop over a `&Result`. This is more readably written as an `if let` statement
+  --> $DIR/for_loop_over_fallibles.rs:51:14
+   |
+LL |     for _ in &Ok::<_, ()>(1) {}
+   |              ^^^^^^^^^^^^^^^
+   |
+help: to check pattern in a loop use `while let`
+   |
+LL |     while let Ok(_) = &Ok::<_, ()>(1) {}
+   |     ~~~~~~~~~~~~~ ~~~
+help: consider using `if let` to clear intent
+   |
+LL |     if let Ok(_) = &Ok::<_, ()>(1) {}
+   |     ~~~~~~~~~~ ~~~
+
+warning: for loop over a `&mut Option`. This is more readably written as an `if let` statement
+  --> $DIR/for_loop_over_fallibles.rs:57:14
+   |
+LL |     for _ in &mut Some(1) {}
+   |              ^^^^^^^^^^^^
+   |
+help: to check pattern in a loop use `while let`
+   |
+LL |     while let Some(_) = &mut Some(1) {}
+   |     ~~~~~~~~~~~~~~~ ~~~
+help: consider using `if let` to clear intent
+   |
+LL |     if let Some(_) = &mut Some(1) {}
+   |     ~~~~~~~~~~~~ ~~~
+
+warning: for loop over a `&mut Result`. This is more readably written as an `if let` statement
+  --> $DIR/for_loop_over_fallibles.rs:61:14
+   |
+LL |     for _ in &mut Ok::<_, ()>(1) {}
+   |              ^^^^^^^^^^^^^^^^^^^
+   |
+help: to check pattern in a loop use `while let`
+   |
+LL |     while let Ok(_) = &mut Ok::<_, ()>(1) {}
+   |     ~~~~~~~~~~~~~ ~~~
+help: consider using `if let` to clear intent
+   |
+LL |     if let Ok(_) = &mut Ok::<_, ()>(1) {}
+   |     ~~~~~~~~~~ ~~~
+
+warning: 10 warnings emitted
 
diff --git a/tests/ui/lint/missing_copy_impl_trivial_bounds.rs b/tests/ui/lint/missing_copy_impl_trivial_bounds.rs
new file mode 100644
index 00000000000..9b743417bd5
--- /dev/null
+++ b/tests/ui/lint/missing_copy_impl_trivial_bounds.rs
@@ -0,0 +1,21 @@
+//@ check-pass
+
+#![feature(trivial_bounds)]
+#![allow(trivial_bounds)]
+
+// Make sure that we still use the where-clauses from the struct when checking
+// if it may implement `Copy` unconditionally.
+// Fix for <https://github.com/rust-lang/rust/issues/125394>.
+
+pub trait Foo {
+    type Assoc;
+}
+
+pub struct Bar;
+
+// This needs to be public
+pub struct Baz2(<Bar as Foo>::Assoc)
+where
+    Bar: Foo;
+
+fn main() {}
diff --git a/tests/ui/loops/loop-if-else-break-issue-123261.fixed b/tests/ui/loops/loop-if-else-break-issue-123261.fixed
new file mode 100644
index 00000000000..f9e88c18ad0
--- /dev/null
+++ b/tests/ui/loops/loop-if-else-break-issue-123261.fixed
@@ -0,0 +1,31 @@
+//@ run-rustfix
+
+#![allow(unused)]
+
+fn main() {
+    let n = 1;
+    let m = 2;
+    let x = 'block: {
+        if n == 0 {
+            break 'block 1; //~ ERROR [E0268]
+        } else {
+            break 'block 2;
+        }
+    };
+
+    let y = 'block: {
+        if n == 0 {
+            break 'block 1; //~ ERROR [E0268]
+        }
+        break 'block 0;
+    };
+
+    let z = 'block: {
+        if n == 0 {
+            if m > 1 {
+                break 'block 3; //~ ERROR [E0268]
+            }
+        }
+        break 'block 1;
+    };
+}
diff --git a/tests/ui/loops/loop-if-else-break-issue-123261.rs b/tests/ui/loops/loop-if-else-break-issue-123261.rs
new file mode 100644
index 00000000000..a1f9dabe891
--- /dev/null
+++ b/tests/ui/loops/loop-if-else-break-issue-123261.rs
@@ -0,0 +1,31 @@
+//@ run-rustfix
+
+#![allow(unused)]
+
+fn main() {
+    let n = 1;
+    let m = 2;
+    let x = {
+        if n == 0 {
+            break 1; //~ ERROR [E0268]
+        } else {
+            break 2;
+        }
+    };
+
+    let y = {
+        if n == 0 {
+            break 1; //~ ERROR [E0268]
+        }
+        break 0;
+    };
+
+    let z = {
+        if n == 0 {
+            if m > 1 {
+                break 3; //~ ERROR [E0268]
+            }
+        }
+        break 1;
+    };
+}
diff --git a/tests/ui/loops/loop-if-else-break-issue-123261.stderr b/tests/ui/loops/loop-if-else-break-issue-123261.stderr
new file mode 100644
index 00000000000..7bd192fc00b
--- /dev/null
+++ b/tests/ui/loops/loop-if-else-break-issue-123261.stderr
@@ -0,0 +1,59 @@
+error[E0268]: `break` outside of a loop or labeled block
+  --> $DIR/loop-if-else-break-issue-123261.rs:10:13
+   |
+LL |             break 1;
+   |             ^^^^^^^ cannot `break` outside of a loop or labeled block
+LL |         } else {
+LL |             break 2;
+   |             ^^^^^^^ cannot `break` outside of a loop or labeled block
+   |
+help: consider labeling this block to be able to break within it
+   |
+LL ~     let x = 'block: {
+LL |         if n == 0 {
+LL ~             break 'block 1;
+LL |         } else {
+LL ~             break 'block 2;
+   |
+
+error[E0268]: `break` outside of a loop or labeled block
+  --> $DIR/loop-if-else-break-issue-123261.rs:18:13
+   |
+LL |             break 1;
+   |             ^^^^^^^ cannot `break` outside of a loop or labeled block
+LL |         }
+LL |         break 0;
+   |         ^^^^^^^ cannot `break` outside of a loop or labeled block
+   |
+help: consider labeling this block to be able to break within it
+   |
+LL ~     let y = 'block: {
+LL |         if n == 0 {
+LL ~             break 'block 1;
+LL |         }
+LL ~         break 'block 0;
+   |
+
+error[E0268]: `break` outside of a loop or labeled block
+  --> $DIR/loop-if-else-break-issue-123261.rs:26:17
+   |
+LL |                 break 3;
+   |                 ^^^^^^^ cannot `break` outside of a loop or labeled block
+...
+LL |         break 1;
+   |         ^^^^^^^ cannot `break` outside of a loop or labeled block
+   |
+help: consider labeling this block to be able to break within it
+   |
+LL ~     let z = 'block: {
+LL |         if n == 0 {
+LL |             if m > 1 {
+LL ~                 break 'block 3;
+LL |             }
+LL |         }
+LL ~         break 'block 1;
+   |
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0268`.
diff --git a/tests/ui/parser/break-in-unlabeled-block-in-macro.stderr b/tests/ui/parser/break-in-unlabeled-block-in-macro.stderr
index 9407e8ac002..2f46cb36750 100644
--- a/tests/ui/parser/break-in-unlabeled-block-in-macro.stderr
+++ b/tests/ui/parser/break-in-unlabeled-block-in-macro.stderr
@@ -21,16 +21,21 @@ LL |         foo!(());
    = note: this error originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0268]: `break` outside of a loop or labeled block
-  --> $DIR/break-in-unlabeled-block-in-macro.rs:27:19
-   |
-LL |         foo!(stmt break ());
-   |                   ^^^^^^^^ cannot `break` outside of a loop or labeled block
+  --> $DIR/break-in-unlabeled-block-in-macro.rs:33:17
    |
-help: consider labeling this block to be able to break within it
+LL |         foo!(=> break ());
+   |                 ^^^^^^^^ cannot `break` outside of a loop or labeled block
+
+error[E0268]: `break` outside of a loop or labeled block
+  --> $DIR/break-in-unlabeled-block-in-macro.rs:38:17
    |
-LL ~     'block: {
-LL ~         foo!(stmt break 'block ());
+LL |                 break ()
+   |                 ^^^^^^^^ cannot `break` outside of a loop or labeled block
+...
+LL |         bar!()
+   |         ------ in this macro invocation
    |
+   = note: this error originates in the macro `bar` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0268]: `break` outside of a loop or labeled block
   --> $DIR/break-in-unlabeled-block-in-macro.rs:12:11
@@ -48,21 +53,16 @@ LL |         'block: { break 'block $e; }
    |         +++++++         ++++++
 
 error[E0268]: `break` outside of a loop or labeled block
-  --> $DIR/break-in-unlabeled-block-in-macro.rs:33:17
+  --> $DIR/break-in-unlabeled-block-in-macro.rs:27:19
    |
-LL |         foo!(=> break ());
-   |                 ^^^^^^^^ cannot `break` outside of a loop or labeled block
-
-error[E0268]: `break` outside of a loop or labeled block
-  --> $DIR/break-in-unlabeled-block-in-macro.rs:38:17
+LL |         foo!(stmt break ());
+   |                   ^^^^^^^^ cannot `break` outside of a loop or labeled block
    |
-LL |                 break ()
-   |                 ^^^^^^^^ cannot `break` outside of a loop or labeled block
-...
-LL |         bar!()
-   |         ------ in this macro invocation
+help: consider labeling this block to be able to break within it
+   |
+LL ~     'block: {
+LL ~         foo!(stmt break 'block ());
    |
-   = note: this error originates in the macro `bar` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to 6 previous errors
 
diff --git a/tests/ui/privacy/pub-priv-dep/auxiliary/diamond_priv_dep.rs b/tests/ui/privacy/pub-priv-dep/auxiliary/diamond_priv_dep.rs
new file mode 100644
index 00000000000..ed76815a6ac
--- /dev/null
+++ b/tests/ui/privacy/pub-priv-dep/auxiliary/diamond_priv_dep.rs
@@ -0,0 +1,9 @@
+//@ aux-crate:shared=shared.rs
+
+extern crate shared;
+
+pub use shared::Shared;
+
+pub struct SharedInType {
+    pub f: Shared
+}
diff --git a/tests/ui/privacy/pub-priv-dep/auxiliary/diamond_pub_dep.rs b/tests/ui/privacy/pub-priv-dep/auxiliary/diamond_pub_dep.rs
new file mode 100644
index 00000000000..ed76815a6ac
--- /dev/null
+++ b/tests/ui/privacy/pub-priv-dep/auxiliary/diamond_pub_dep.rs
@@ -0,0 +1,9 @@
+//@ aux-crate:shared=shared.rs
+
+extern crate shared;
+
+pub use shared::Shared;
+
+pub struct SharedInType {
+    pub f: Shared
+}
diff --git a/tests/ui/privacy/pub-priv-dep/auxiliary/indirect1.rs b/tests/ui/privacy/pub-priv-dep/auxiliary/indirect1.rs
new file mode 100644
index 00000000000..0e4a73c7fc0
--- /dev/null
+++ b/tests/ui/privacy/pub-priv-dep/auxiliary/indirect1.rs
@@ -0,0 +1,4 @@
+//@ aux-crate:priv:indirect2=indirect2.rs
+//@ compile-flags: -Zunstable-options
+
+extern crate indirect2;
diff --git a/tests/ui/privacy/pub-priv-dep/auxiliary/indirect2.rs b/tests/ui/privacy/pub-priv-dep/auxiliary/indirect2.rs
new file mode 100644
index 00000000000..5f6b289eb14
--- /dev/null
+++ b/tests/ui/privacy/pub-priv-dep/auxiliary/indirect2.rs
@@ -0,0 +1,4 @@
+//@ aux-crate:shared=shared.rs
+
+// This is public.
+extern crate shared;
diff --git a/tests/ui/privacy/pub-priv-dep/auxiliary/pm.rs b/tests/ui/privacy/pub-priv-dep/auxiliary/pm.rs
new file mode 100644
index 00000000000..9e2aa898afe
--- /dev/null
+++ b/tests/ui/privacy/pub-priv-dep/auxiliary/pm.rs
@@ -0,0 +1,22 @@
+//@ force-host
+//@ no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+use proc_macro::TokenStream;
+
+#[proc_macro]
+pub fn fn_like(input: TokenStream) -> TokenStream {
+    "".parse().unwrap()
+}
+
+#[proc_macro_derive(PmDerive)]
+pub fn pm_derive(item: TokenStream) -> TokenStream {
+    "".parse().unwrap()
+}
+
+#[proc_macro_attribute]
+pub fn pm_attr(attr: TokenStream, item: TokenStream) -> TokenStream {
+    "".parse().unwrap()
+}
diff --git a/tests/ui/privacy/pub-priv-dep/auxiliary/priv_dep.rs b/tests/ui/privacy/pub-priv-dep/auxiliary/priv_dep.rs
index e7afeb84fb4..4eeecdc0569 100644
--- a/tests/ui/privacy/pub-priv-dep/auxiliary/priv_dep.rs
+++ b/tests/ui/privacy/pub-priv-dep/auxiliary/priv_dep.rs
@@ -1,2 +1,11 @@
 pub struct OtherType;
 pub trait OtherTrait {}
+
+#[macro_export]
+macro_rules! m {
+    () => {};
+}
+
+pub enum E {
+    V1
+}
diff --git a/tests/ui/privacy/pub-priv-dep/auxiliary/reexport.rs b/tests/ui/privacy/pub-priv-dep/auxiliary/reexport.rs
new file mode 100644
index 00000000000..0655e3ae2cf
--- /dev/null
+++ b/tests/ui/privacy/pub-priv-dep/auxiliary/reexport.rs
@@ -0,0 +1,5 @@
+//@ aux-crate:shared=shared.rs
+
+extern crate shared;
+
+pub use shared::Shared;
diff --git a/tests/ui/privacy/pub-priv-dep/auxiliary/shared.rs b/tests/ui/privacy/pub-priv-dep/auxiliary/shared.rs
new file mode 100644
index 00000000000..efc4daa7bef
--- /dev/null
+++ b/tests/ui/privacy/pub-priv-dep/auxiliary/shared.rs
@@ -0,0 +1 @@
+pub struct Shared;
diff --git a/tests/ui/privacy/pub-priv-dep/diamond_deps.rs b/tests/ui/privacy/pub-priv-dep/diamond_deps.rs
new file mode 100644
index 00000000000..0e1f6f36bc8
--- /dev/null
+++ b/tests/ui/privacy/pub-priv-dep/diamond_deps.rs
@@ -0,0 +1,48 @@
+//@ aux-crate:priv:diamond_priv_dep=diamond_priv_dep.rs
+//@ aux-crate:diamond_pub_dep=diamond_pub_dep.rs
+//@ compile-flags: -Zunstable-options
+
+// A diamond dependency:
+//
+//           diamond_reepxort
+//                  /\
+//        (public) /  \ (PRIVATE)
+//                /    \
+//   diamond_pub_dep  diamond_priv_dep
+//                \    /
+//        (public) \  /  (public)
+//                  \/
+//                shared
+//
+// Where the pub and private crates reexport something from the shared crate.
+//
+// Checks the behavior when the same shared item appears in the public API,
+// depending on whether it comes from the public side or the private side.
+//
+// NOTE: compiletest does not support deduplicating shared dependencies.
+// However, it should work well enough for this test, the only downside is
+// that diamond_shared gets built twice.
+
+#![crate_type = "lib"]
+#![deny(exported_private_dependencies)]
+
+extern crate diamond_priv_dep;
+extern crate diamond_pub_dep;
+
+// FIXME: This should trigger.
+pub fn leaks_priv() -> diamond_priv_dep::Shared {
+    diamond_priv_dep::Shared
+}
+
+pub fn leaks_pub() -> diamond_pub_dep::Shared {
+    diamond_pub_dep::Shared
+}
+
+pub struct PrivInStruct {
+    pub f: diamond_priv_dep::SharedInType
+//~^ ERROR type `diamond_priv_dep::SharedInType` from private dependency 'diamond_priv_dep' in public interface
+}
+
+pub struct PubInStruct {
+    pub f: diamond_pub_dep::SharedInType
+}
diff --git a/tests/ui/privacy/pub-priv-dep/diamond_deps.stderr b/tests/ui/privacy/pub-priv-dep/diamond_deps.stderr
new file mode 100644
index 00000000000..8a6d35a747b
--- /dev/null
+++ b/tests/ui/privacy/pub-priv-dep/diamond_deps.stderr
@@ -0,0 +1,14 @@
+error: type `diamond_priv_dep::SharedInType` from private dependency 'diamond_priv_dep' in public interface
+  --> $DIR/diamond_deps.rs:42:5
+   |
+LL |     pub f: diamond_priv_dep::SharedInType
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: the lint level is defined here
+  --> $DIR/diamond_deps.rs:27:9
+   |
+LL | #![deny(exported_private_dependencies)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/privacy/pub-priv-dep/pub-priv1.rs b/tests/ui/privacy/pub-priv-dep/pub-priv1.rs
index f26dbb47ba5..112eaf528be 100644
--- a/tests/ui/privacy/pub-priv-dep/pub-priv1.rs
+++ b/tests/ui/privacy/pub-priv-dep/pub-priv1.rs
@@ -1,12 +1,20 @@
 //@ aux-crate:priv:priv_dep=priv_dep.rs
 //@ aux-build:pub_dep.rs
+//@ aux-crate:priv:pm=pm.rs
 //@ compile-flags: -Zunstable-options
+
+// Basic behavior check of exported_private_dependencies from either a public
+// dependency or a private one.
+
 #![deny(exported_private_dependencies)]
 
 // This crate is a private dependency
-extern crate priv_dep;
+// FIXME: This should trigger.
+pub extern crate priv_dep;
 // This crate is a public dependency
 extern crate pub_dep;
+// This crate is a private dependency
+extern crate pm;
 
 use priv_dep::{OtherTrait, OtherType};
 use pub_dep::PubType;
@@ -25,7 +33,10 @@ pub struct PublicType {
 }
 
 impl PublicType {
-    pub fn pub_fn(param: OtherType) {}
+    pub fn pub_fn_param(param: OtherType) {}
+    //~^ ERROR type `OtherType` from private dependency 'priv_dep' in public interface
+
+    pub fn pub_fn_return() -> OtherType { OtherType }
     //~^ ERROR type `OtherType` from private dependency 'priv_dep' in public interface
 
     fn priv_fn(param: OtherType) {}
@@ -36,9 +47,61 @@ pub trait MyPubTrait {
 }
 //~^^ ERROR trait `OtherTrait` from private dependency 'priv_dep' in public interface
 
+pub trait WithSuperTrait: OtherTrait {}
+//~^ ERROR trait `OtherTrait` from private dependency 'priv_dep' in public interface
+
+pub trait PubLocalTraitWithAssoc {
+    type X;
+}
+
+pub struct PrivateAssoc;
+impl PubLocalTraitWithAssoc for PrivateAssoc {
+    type X = OtherType;
+//~^ ERROR type `OtherType` from private dependency 'priv_dep' in public interface
+}
+
+pub fn in_bounds<T: OtherTrait>(x: T) { unimplemented!() }
+//~^ ERROR trait `OtherTrait` from private dependency 'priv_dep' in public interface
+
+pub fn private_in_generic() -> std::num::Saturating<OtherType> { unimplemented!() }
+//~^ ERROR type `OtherType` from private dependency 'priv_dep' in public interface
+
+pub static STATIC: OtherType = OtherType;
+//~^ ERROR type `OtherType` from private dependency 'priv_dep' in public interface
+
+pub const CONST: OtherType = OtherType;
+//~^ ERROR type `OtherType` from private dependency 'priv_dep' in public interface
+
+pub type Alias = OtherType;
+//~^ ERROR type `OtherType` from private dependency 'priv_dep' in public interface
+
+pub struct PublicWithPrivateImpl;
+
+// FIXME: This should trigger.
+// See https://github.com/rust-lang/rust/issues/71043
+impl OtherTrait for PublicWithPrivateImpl {}
+
+pub trait PubTraitOnPrivate {}
+
+// FIXME: This should trigger.
+// See https://github.com/rust-lang/rust/issues/71043
+impl PubTraitOnPrivate for OtherType {}
+
 pub struct AllowedPrivType {
     #[allow(exported_private_dependencies)]
     pub allowed: OtherType,
 }
 
+// FIXME: This should trigger.
+pub use priv_dep::m;
+// FIXME: This should trigger.
+pub use pm::fn_like;
+// FIXME: This should trigger.
+pub use pm::PmDerive;
+// FIXME: This should trigger.
+pub use pm::pm_attr;
+
+// FIXME: This should trigger.
+pub use priv_dep::E::V1;
+
 fn main() {}
diff --git a/tests/ui/privacy/pub-priv-dep/pub-priv1.stderr b/tests/ui/privacy/pub-priv-dep/pub-priv1.stderr
index e62a440d8f5..53d461a5774 100644
--- a/tests/ui/privacy/pub-priv-dep/pub-priv1.stderr
+++ b/tests/ui/privacy/pub-priv-dep/pub-priv1.stderr
@@ -1,26 +1,74 @@
 error: type `OtherType` from private dependency 'priv_dep' in public interface
-  --> $DIR/pub-priv1.rs:21:5
+  --> $DIR/pub-priv1.rs:29:5
    |
 LL |     pub field: OtherType,
    |     ^^^^^^^^^^^^^^^^^^^^
    |
 note: the lint level is defined here
-  --> $DIR/pub-priv1.rs:4:9
+  --> $DIR/pub-priv1.rs:9:9
    |
 LL | #![deny(exported_private_dependencies)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: type `OtherType` from private dependency 'priv_dep' in public interface
-  --> $DIR/pub-priv1.rs:28:5
+  --> $DIR/pub-priv1.rs:36:5
    |
-LL |     pub fn pub_fn(param: OtherType) {}
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     pub fn pub_fn_param(param: OtherType) {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: type `OtherType` from private dependency 'priv_dep' in public interface
+  --> $DIR/pub-priv1.rs:39:5
+   |
+LL |     pub fn pub_fn_return() -> OtherType { OtherType }
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: trait `OtherTrait` from private dependency 'priv_dep' in public interface
-  --> $DIR/pub-priv1.rs:35:5
+  --> $DIR/pub-priv1.rs:46:5
    |
 LL |     type Foo: OtherTrait;
    |     ^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 3 previous errors
+error: trait `OtherTrait` from private dependency 'priv_dep' in public interface
+  --> $DIR/pub-priv1.rs:50:1
+   |
+LL | pub trait WithSuperTrait: OtherTrait {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: type `OtherType` from private dependency 'priv_dep' in public interface
+  --> $DIR/pub-priv1.rs:59:5
+   |
+LL |     type X = OtherType;
+   |     ^^^^^^
+
+error: trait `OtherTrait` from private dependency 'priv_dep' in public interface
+  --> $DIR/pub-priv1.rs:63:1
+   |
+LL | pub fn in_bounds<T: OtherTrait>(x: T) { unimplemented!() }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: type `OtherType` from private dependency 'priv_dep' in public interface
+  --> $DIR/pub-priv1.rs:66:1
+   |
+LL | pub fn private_in_generic() -> std::num::Saturating<OtherType> { unimplemented!() }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: type `OtherType` from private dependency 'priv_dep' in public interface
+  --> $DIR/pub-priv1.rs:69:1
+   |
+LL | pub static STATIC: OtherType = OtherType;
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: type `OtherType` from private dependency 'priv_dep' in public interface
+  --> $DIR/pub-priv1.rs:72:1
+   |
+LL | pub const CONST: OtherType = OtherType;
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: type `OtherType` from private dependency 'priv_dep' in public interface
+  --> $DIR/pub-priv1.rs:75:1
+   |
+LL | pub type Alias = OtherType;
+   | ^^^^^^^^^^^^^^
+
+error: aborting due to 11 previous errors
 
diff --git a/tests/ui/privacy/pub-priv-dep/reexport_from_priv.rs b/tests/ui/privacy/pub-priv-dep/reexport_from_priv.rs
new file mode 100644
index 00000000000..3c6e9825e72
--- /dev/null
+++ b/tests/ui/privacy/pub-priv-dep/reexport_from_priv.rs
@@ -0,0 +1,15 @@
+//@ aux-crate:priv:reexport=reexport.rs
+//@ compile-flags: -Zunstable-options
+//@ check-pass
+
+// Checks the behavior of a reexported item from a private dependency.
+
+#![crate_type = "lib"]
+#![deny(exported_private_dependencies)]
+
+extern crate reexport;
+
+// FIXME: This should trigger.
+pub fn leaks_priv() -> reexport::Shared {
+    reexport::Shared
+}
diff --git a/tests/ui/privacy/pub-priv-dep/shared_both_private.rs b/tests/ui/privacy/pub-priv-dep/shared_both_private.rs
new file mode 100644
index 00000000000..20a4b85c01e
--- /dev/null
+++ b/tests/ui/privacy/pub-priv-dep/shared_both_private.rs
@@ -0,0 +1,32 @@
+//@ aux-crate:priv:shared=shared.rs
+//@ aux-crate:reexport=reexport.rs
+//@ compile-flags: -Zunstable-options
+//@ check-pass
+
+// A shared dependency, where a private dependency reexports a public dependency.
+//
+//         shared_both_private
+//                  /\
+//       (PRIVATE) /  | (PRIVATE)
+//                /   |
+//        reexport    |
+//                \   |
+//        (public) \  /
+//                  \/
+//                shared
+
+#![crate_type = "lib"]
+#![deny(exported_private_dependencies)]
+
+extern crate shared;
+extern crate reexport;
+
+// FIXME: This should trigger.
+pub fn leaks_priv() -> shared::Shared {
+    shared::Shared
+}
+
+// FIXME: This should trigger.
+pub fn leaks_priv_reexport() -> reexport::Shared {
+    reexport::Shared
+}
diff --git a/tests/ui/privacy/pub-priv-dep/shared_direct_private.rs b/tests/ui/privacy/pub-priv-dep/shared_direct_private.rs
new file mode 100644
index 00000000000..b329a7acb58
--- /dev/null
+++ b/tests/ui/privacy/pub-priv-dep/shared_direct_private.rs
@@ -0,0 +1,39 @@
+//@ aux-crate:priv:shared=shared.rs
+//@ aux-crate:reexport=reexport.rs
+//@ compile-flags: -Zunstable-options
+//@ check-pass
+
+// A shared dependency, where the public side reexports the same item as a
+// direct private dependency.
+//
+//          shared_direct_private
+//                  /\
+//        (public) /  | (PRIVATE)
+//                /   |
+//        reexport    |
+//                \   |
+//        (public) \  /
+//                  \/
+//                shared
+//
+
+#![crate_type = "lib"]
+#![deny(exported_private_dependencies)]
+
+extern crate shared;
+extern crate reexport;
+
+// FIXME: Should this trigger?
+//
+// One could make an argument that I said I want "reexport" to be public, and
+// since "reexport" says "shared_direct_private" is public, then it should
+// transitively be public for me. However, as written, this is explicitly
+// referring to a dependency that is marked "private", which I think is
+// confusing.
+pub fn leaks_priv() -> shared::Shared {
+    shared::Shared
+}
+
+pub fn leaks_pub() -> reexport::Shared {
+    reexport::Shared
+}
diff --git a/tests/ui/privacy/pub-priv-dep/shared_indirect.rs b/tests/ui/privacy/pub-priv-dep/shared_indirect.rs
new file mode 100644
index 00000000000..34b624b4a1a
--- /dev/null
+++ b/tests/ui/privacy/pub-priv-dep/shared_indirect.rs
@@ -0,0 +1,29 @@
+//@ aux-crate:priv:shared=shared.rs
+//@ aux-crate:priv:indirect1=indirect1.rs
+//@ compile-flags: -Zunstable-options
+//@ check-pass
+
+// A shared dependency, where it is only indirectly public.
+//
+//            shared_indirect
+//                  /\
+//       (PRIVATE) /  | (PRIVATE)
+//                /   |
+//     indirect1 |    |
+//     (PRIVATE) |    |
+//     indirect2 |    |
+//                \   |
+//        (public) \  /
+//                  \/
+//                shared
+
+#![crate_type = "lib"]
+#![deny(exported_private_dependencies)]
+
+extern crate shared;
+extern crate indirect1;
+
+// FIXME: This should trigger.
+pub fn leaks_priv() -> shared::Shared {
+    shared::Shared
+}
diff --git a/tests/ui/pub/pub-reexport-priv-extern-crate.stderr b/tests/ui/pub/pub-reexport-priv-extern-crate.stderr
index c7fadc6f929..3fa5b0f9aef 100644
--- a/tests/ui/pub/pub-reexport-priv-extern-crate.stderr
+++ b/tests/ui/pub/pub-reexport-priv-extern-crate.stderr
@@ -22,7 +22,7 @@ note: the crate import `core` is defined here
 LL |         extern crate core;
    |         ^^^^^^^^^^^^^^^^^^
 
-error: extern crate `core` is private, and cannot be re-exported (error E0365), consider declaring with `pub`
+error[E0365]: extern crate `core` is private, and cannot be re-exported, consider declaring with `pub`
   --> $DIR/pub-reexport-priv-extern-crate.rs:2:9
    |
 LL | pub use core as reexported_core;
@@ -34,4 +34,5 @@ LL | pub use core as reexported_core;
 
 error: aborting due to 3 previous errors
 
-For more information about this error, try `rustc --explain E0603`.
+Some errors have detailed explanations: E0365, E0603.
+For more information about an error, try `rustc --explain E0365`.
diff --git a/tests/ui/rfcs/rfc-2396-target_feature-11/safe-calls.stderr b/tests/ui/rfcs/rfc-2396-target_feature-11/safe-calls.stderr
index aa660db3867..537819ab859 100644
--- a/tests/ui/rfcs/rfc-2396-target_feature-11/safe-calls.stderr
+++ b/tests/ui/rfcs/rfc-2396-target_feature-11/safe-calls.stderr
@@ -91,7 +91,7 @@ LL | const _: () = sse2_and_fxsr();
    = help: in order for the call to be safe, the context requires the following additional target features: sse2 and fxsr
    = note: the fxsr and sse2 target features being enabled in the build configuration does not remove the requirement to list them in `#[target_feature]`
 
-error: call to function `sse2` with `#[target_feature]` is unsafe and requires unsafe block (error E0133)
+error[E0133]: call to function `sse2` with `#[target_feature]` is unsafe and requires unsafe block
   --> $DIR/safe-calls.rs:70:5
    |
 LL |     sse2();
diff --git a/tests/ui/threads-sendsync/issue-43733-2.rs b/tests/ui/threads-sendsync/issue-43733-2.rs
deleted file mode 100644
index 372ebf2cff9..00000000000
--- a/tests/ui/threads-sendsync/issue-43733-2.rs
+++ /dev/null
@@ -1,30 +0,0 @@
-//@ needs-threads
-//@ dont-check-compiler-stderr
-#![feature(cfg_target_thread_local, thread_local_internals)]
-
-// On platforms *without* `#[thread_local]`, use
-// a custom non-`Sync` type to fake the same error.
-#[cfg(not(target_thread_local))]
-struct Key<T> {
-    _data: std::cell::UnsafeCell<Option<T>>,
-    _flag: std::cell::Cell<()>,
-}
-
-#[cfg(not(target_thread_local))]
-impl<T> Key<T> {
-    const fn new() -> Self {
-        Key {
-            _data: std::cell::UnsafeCell::new(None),
-            _flag: std::cell::Cell::new(()),
-        }
-    }
-}
-
-#[cfg(target_thread_local)]
-use std::thread::local_impl::Key;
-
-static __KEY: Key<()> = Key::new();
-//~^ ERROR `UnsafeCell<Option<()>>` cannot be shared between threads
-//~| ERROR cannot be shared between threads safely [E0277]
-
-fn main() {}
diff --git a/tests/ui/threads-sendsync/issue-43733.rs b/tests/ui/threads-sendsync/issue-43733.rs
deleted file mode 100644
index c90f60887cf..00000000000
--- a/tests/ui/threads-sendsync/issue-43733.rs
+++ /dev/null
@@ -1,32 +0,0 @@
-//@ needs-threads
-#![feature(thread_local)]
-#![feature(cfg_target_thread_local, thread_local_internals)]
-
-use std::cell::RefCell;
-
-type Foo = std::cell::RefCell<String>;
-
-#[cfg(target_thread_local)]
-#[thread_local]
-static __KEY: std::thread::local_impl::Key<Foo> = std::thread::local_impl::Key::new();
-
-#[cfg(not(target_thread_local))]
-static __KEY: std::thread::local_impl::Key<Foo> = std::thread::local_impl::Key::new();
-
-fn __getit(_: Option<&mut Option<RefCell<String>>>) -> std::option::Option<&'static Foo> {
-    __KEY.get(Default::default)
-    //~^ ERROR call to unsafe function `Key::<T>::get` is unsafe
-}
-
-static FOO: std::thread::LocalKey<Foo> = std::thread::LocalKey::new(__getit);
-//~^ ERROR call to unsafe function `LocalKey::<T>::new` is unsafe
-
-fn main() {
-    FOO.with(|foo| println!("{}", foo.borrow()));
-    std::thread::spawn(|| {
-        FOO.with(|foo| *foo.borrow_mut() += "foo");
-    })
-    .join()
-    .unwrap();
-    FOO.with(|foo| println!("{}", foo.borrow()));
-}
diff --git a/tests/ui/threads-sendsync/issue-43733.stderr b/tests/ui/threads-sendsync/issue-43733.stderr
deleted file mode 100644
index 9b13646a228..00000000000
--- a/tests/ui/threads-sendsync/issue-43733.stderr
+++ /dev/null
@@ -1,19 +0,0 @@
-error[E0133]: call to unsafe function `Key::<T>::get` is unsafe and requires unsafe function or block
-  --> $DIR/issue-43733.rs:17:5
-   |
-LL |     __KEY.get(Default::default)
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^ call to unsafe function
-   |
-   = note: consult the function's documentation for information on how to avoid undefined behavior
-
-error[E0133]: call to unsafe function `LocalKey::<T>::new` is unsafe and requires unsafe function or block
-  --> $DIR/issue-43733.rs:21:42
-   |
-LL | static FOO: std::thread::LocalKey<Foo> = std::thread::LocalKey::new(__getit);
-   |                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ call to unsafe function
-   |
-   = note: consult the function's documentation for information on how to avoid undefined behavior
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0133`.
diff --git a/tests/ui/unsafe/edition-2024-unsafe_op_in_unsafe_fn.stderr b/tests/ui/unsafe/edition-2024-unsafe_op_in_unsafe_fn.stderr
index 2eb1754392e..fe12dd72d9e 100644
--- a/tests/ui/unsafe/edition-2024-unsafe_op_in_unsafe_fn.stderr
+++ b/tests/ui/unsafe/edition-2024-unsafe_op_in_unsafe_fn.stderr
@@ -1,4 +1,4 @@
-warning: call to unsafe function `unsf` is unsafe and requires unsafe block (error E0133)
+warning[E0133]: call to unsafe function `unsf` is unsafe and requires unsafe block
   --> $DIR/edition-2024-unsafe_op_in_unsafe_fn.rs:10:5
    |
 LL |     unsf();
@@ -15,3 +15,4 @@ LL | unsafe fn foo() {
 
 warning: 1 warning emitted
 
+For more information about this error, try `rustc --explain E0133`.
diff --git a/tests/ui/unsafe/unsafe_op_in_unsafe_fn/edition_2024_default.stderr b/tests/ui/unsafe/unsafe_op_in_unsafe_fn/edition_2024_default.stderr
index e6d1d4e5cc7..05f36ab47cb 100644
--- a/tests/ui/unsafe/unsafe_op_in_unsafe_fn/edition_2024_default.stderr
+++ b/tests/ui/unsafe/unsafe_op_in_unsafe_fn/edition_2024_default.stderr
@@ -1,4 +1,4 @@
-warning: call to unsafe function `unsf` is unsafe and requires unsafe block (error E0133)
+warning[E0133]: call to unsafe function `unsf` is unsafe and requires unsafe block
   --> $DIR/edition_2024_default.rs:13:5
    |
 LL |     unsf();
@@ -15,3 +15,4 @@ LL | unsafe fn foo() {
 
 warning: 1 warning emitted
 
+For more information about this error, try `rustc --explain E0133`.
diff --git a/tests/ui/unsafe/unsafe_op_in_unsafe_fn/in_2024_compatibility.stderr b/tests/ui/unsafe/unsafe_op_in_unsafe_fn/in_2024_compatibility.stderr
index 5092c1e689d..3f97199458d 100644
--- a/tests/ui/unsafe/unsafe_op_in_unsafe_fn/in_2024_compatibility.stderr
+++ b/tests/ui/unsafe/unsafe_op_in_unsafe_fn/in_2024_compatibility.stderr
@@ -1,4 +1,4 @@
-error: call to unsafe function `unsf` is unsafe and requires unsafe block (error E0133)
+error[E0133]: call to unsafe function `unsf` is unsafe and requires unsafe block
   --> $DIR/in_2024_compatibility.rs:7:5
    |
 LL |     unsf();
@@ -20,3 +20,4 @@ LL | #![deny(rust_2024_compatibility)]
 
 error: aborting due to 1 previous error
 
+For more information about this error, try `rustc --explain E0133`.
diff --git a/tests/ui/unsafe/unsafe_op_in_unsafe_fn/rfc-2585-unsafe_op_in_unsafe_fn.stderr b/tests/ui/unsafe/unsafe_op_in_unsafe_fn/rfc-2585-unsafe_op_in_unsafe_fn.stderr
index 4bc604a110e..1f80342566c 100644
--- a/tests/ui/unsafe/unsafe_op_in_unsafe_fn/rfc-2585-unsafe_op_in_unsafe_fn.stderr
+++ b/tests/ui/unsafe/unsafe_op_in_unsafe_fn/rfc-2585-unsafe_op_in_unsafe_fn.stderr
@@ -1,4 +1,4 @@
-error: call to unsafe function `unsf` is unsafe and requires unsafe block (error E0133)
+error[E0133]: call to unsafe function `unsf` is unsafe and requires unsafe block
   --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:9:5
    |
 LL |     unsf();
@@ -17,7 +17,7 @@ note: the lint level is defined here
 LL | #![deny(unsafe_op_in_unsafe_fn)]
    |         ^^^^^^^^^^^^^^^^^^^^^^
 
-error: dereference of raw pointer is unsafe and requires unsafe block (error E0133)
+error[E0133]: dereference of raw pointer is unsafe and requires unsafe block
   --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:11:5
    |
 LL |     *PTR;
@@ -26,7 +26,7 @@ LL |     *PTR;
    = note: for more information, see issue #71668 <https://github.com/rust-lang/rust/issues/71668>
    = note: raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior
 
-error: use of mutable static is unsafe and requires unsafe block (error E0133)
+error[E0133]: use of mutable static is unsafe and requires unsafe block
   --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:13:5
    |
 LL |     VOID = ();
@@ -47,7 +47,7 @@ note: the lint level is defined here
 LL | #![deny(unused_unsafe)]
    |         ^^^^^^^^^^^^^
 
-error: call to unsafe function `unsf` is unsafe and requires unsafe block (error E0133)
+error[E0133]: call to unsafe function `unsf` is unsafe and requires unsafe block
   --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:24:5
    |
 LL |     unsf();
@@ -67,7 +67,7 @@ LL | #[deny(warnings)]
    |        ^^^^^^^^
    = note: `#[deny(unsafe_op_in_unsafe_fn)]` implied by `#[deny(warnings)]`
 
-error: dereference of raw pointer is unsafe and requires unsafe block (error E0133)
+error[E0133]: dereference of raw pointer is unsafe and requires unsafe block
   --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:26:5
    |
 LL |     *PTR;
@@ -76,7 +76,7 @@ LL |     *PTR;
    = note: for more information, see issue #71668 <https://github.com/rust-lang/rust/issues/71668>
    = note: raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior
 
-error: use of mutable static is unsafe and requires unsafe block (error E0133)
+error[E0133]: use of mutable static is unsafe and requires unsafe block
   --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:28:5
    |
 LL |     VOID = ();
diff --git a/tests/ui/unsafe/unsafe_op_in_unsafe_fn/wrapping-unsafe-block-sugg.stderr b/tests/ui/unsafe/unsafe_op_in_unsafe_fn/wrapping-unsafe-block-sugg.stderr
index b9f5969474d..1ce22ecfdc7 100644
--- a/tests/ui/unsafe/unsafe_op_in_unsafe_fn/wrapping-unsafe-block-sugg.stderr
+++ b/tests/ui/unsafe/unsafe_op_in_unsafe_fn/wrapping-unsafe-block-sugg.stderr
@@ -1,4 +1,4 @@
-error: call to unsafe function `unsf` is unsafe and requires unsafe block (error E0133)
+error[E0133]: call to unsafe function `unsf` is unsafe and requires unsafe block
   --> $DIR/wrapping-unsafe-block-sugg.rs:13:5
    |
 LL |     unsf();
@@ -17,7 +17,7 @@ note: the lint level is defined here
 LL | #![deny(unsafe_op_in_unsafe_fn)]
    |         ^^^^^^^^^^^^^^^^^^^^^^
 
-error: call to unsafe function `unsf` is unsafe and requires unsafe block (error E0133)
+error[E0133]: call to unsafe function `unsf` is unsafe and requires unsafe block
   --> $DIR/wrapping-unsafe-block-sugg.rs:17:5
    |
 LL |     unsf();
@@ -26,7 +26,7 @@ LL |     unsf();
    = note: for more information, see issue #71668 <https://github.com/rust-lang/rust/issues/71668>
    = note: consult the function's documentation for information on how to avoid undefined behavior
 
-error: dereference of raw pointer is unsafe and requires unsafe block (error E0133)
+error[E0133]: dereference of raw pointer is unsafe and requires unsafe block
   --> $DIR/wrapping-unsafe-block-sugg.rs:25:13
    |
 LL |     let y = *x;
@@ -40,7 +40,7 @@ note: an unsafe function restricts its caller, but its body is safe by default
 LL | pub unsafe fn bar(x: *const i32) -> i32 {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: dereference of raw pointer is unsafe and requires unsafe block (error E0133)
+error[E0133]: dereference of raw pointer is unsafe and requires unsafe block
   --> $DIR/wrapping-unsafe-block-sugg.rs:29:9
    |
 LL |     y + *x
@@ -49,7 +49,7 @@ LL |     y + *x
    = note: for more information, see issue #71668 <https://github.com/rust-lang/rust/issues/71668>
    = note: raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior
 
-error: use of mutable static is unsafe and requires unsafe block (error E0133)
+error[E0133]: use of mutable static is unsafe and requires unsafe block
   --> $DIR/wrapping-unsafe-block-sugg.rs:38:13
    |
 LL |     let y = BAZ;
@@ -63,7 +63,7 @@ note: an unsafe function restricts its caller, but its body is safe by default
 LL | pub unsafe fn baz() -> i32 {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: use of mutable static is unsafe and requires unsafe block (error E0133)
+error[E0133]: use of mutable static is unsafe and requires unsafe block
   --> $DIR/wrapping-unsafe-block-sugg.rs:42:9
    |
 LL |     y + BAZ
@@ -72,7 +72,7 @@ LL |     y + BAZ
    = note: for more information, see issue #71668 <https://github.com/rust-lang/rust/issues/71668>
    = note: mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior
 
-error: call to unsafe function `unsf` is unsafe and requires unsafe block (error E0133)
+error[E0133]: call to unsafe function `unsf` is unsafe and requires unsafe block
   --> $DIR/wrapping-unsafe-block-sugg.rs:48:36
    |
 LL | macro_rules! unsafe_macro { () => (unsf()) }
@@ -90,7 +90,7 @@ LL | pub unsafe fn unsafe_in_macro() {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: this error originates in the macro `unsafe_macro` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error: call to unsafe function `unsf` is unsafe and requires unsafe block (error E0133)
+error[E0133]: call to unsafe function `unsf` is unsafe and requires unsafe block
   --> $DIR/wrapping-unsafe-block-sugg.rs:48:36
    |
 LL | macro_rules! unsafe_macro { () => (unsf()) }
@@ -105,3 +105,4 @@ LL |     unsafe_macro!();
 
 error: aborting due to 8 previous errors
 
+For more information about this error, try `rustc --explain E0133`.
diff --git a/triagebot.toml b/triagebot.toml
index 2e45b257f81..95fa3befe60 100644
--- a/triagebot.toml
+++ b/triagebot.toml
@@ -842,6 +842,9 @@ cc = ["@Zalathar"]
 message = "Some changes occurred in coverage tests."
 cc = ["@Zalathar"]
 
+[mentions."src/tools/opt-dist"]
+cc = ["@kobzol"]
+
 [assign]
 warn_non_default_branch = true
 contributing_url = "https://rustc-dev-guide.rust-lang.org/getting-started.html"
@@ -1059,6 +1062,7 @@ project-exploit-mitigations = [
 "/src/tools/cargo" =                                     ["@ehuss"]
 "/src/tools/compiletest" =                               ["bootstrap", "@wesleywiser", "@oli-obk", "@compiler-errors", "@jieyouxu"]
 "/src/tools/linkchecker" =                               ["@ehuss"]
+"/src/tools/opt-dist" =                                  ["@kobzol"]
 "/src/tools/run-make-support" =                          ["@jieyouxu"]
 "/src/tools/rust-installer" =                            ["bootstrap"]
 "/src/tools/rustbook" =                                  ["@ehuss"]