about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/ci.yml8
-rw-r--r--CONTRIBUTING.md7
-rw-r--r--Cargo.lock212
-rw-r--r--Cargo.toml2
-rw-r--r--README.md128
-rw-r--r--compiler/rustc_ast/src/token.rs4
-rw-r--r--compiler/rustc_ast/src/util/comments.rs2
-rw-r--r--compiler/rustc_ast_lowering/src/expr.rs18
-rw-r--r--compiler/rustc_ast_lowering/src/item.rs46
-rw-r--r--compiler/rustc_ast_lowering/src/lib.rs19
-rw-r--r--compiler/rustc_ast_lowering/src/pat.rs6
-rw-r--r--compiler/rustc_borrowck/src/consumers.rs6
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs14
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/find_all_local_uses.rs2
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/mod.rs55
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/region_errors.rs24
-rw-r--r--compiler/rustc_borrowck/src/lib.rs5
-rw-r--r--compiler/rustc_borrowck/src/region_infer/mod.rs43
-rw-r--r--compiler/rustc_borrowck/src/type_check/free_region_relations.rs6
-rw-r--r--compiler/rustc_borrowck/src/type_check/input_output.rs45
-rw-r--r--compiler/rustc_borrowck/src/type_check/mod.rs14
-rw-r--r--compiler/rustc_builtin_macros/src/asm.rs2
-rw-r--r--compiler/rustc_builtin_macros/src/proc_macro_harness.rs2
-rw-r--r--compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs6
-rw-r--r--compiler/rustc_codegen_gcc/src/base.rs2
-rw-r--r--compiler/rustc_codegen_gcc/src/common.rs2
-rw-r--r--compiler/rustc_codegen_gcc/src/lib.rs2
-rw-r--r--compiler/rustc_codegen_llvm/src/attributes.rs15
-rw-r--r--compiler/rustc_codegen_llvm/src/back/write.rs2
-rw-r--r--compiler/rustc_codegen_llvm/src/context.rs14
-rw-r--r--compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs4
-rw-r--r--compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs2
-rw-r--r--compiler/rustc_codegen_llvm/src/intrinsic.rs2
-rw-r--r--compiler/rustc_codegen_llvm/src/llvm/ffi.rs7
-rw-r--r--compiler/rustc_codegen_llvm/src/llvm_util.rs4
-rw-r--r--compiler/rustc_codegen_ssa/src/back/link.rs8
-rw-r--r--compiler/rustc_codegen_ssa/src/back/symbol_export.rs6
-rw-r--r--compiler/rustc_codegen_ssa/src/back/write.rs2
-rw-r--r--compiler/rustc_codegen_ssa/src/base.rs4
-rw-r--r--compiler/rustc_codegen_ssa/src/codegen_attrs.rs25
-rw-r--r--compiler/rustc_codegen_ssa/src/debuginfo/mod.rs2
-rw-r--r--compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs2
-rw-r--r--compiler/rustc_codegen_ssa/src/meth.rs2
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/block.rs15
-rw-r--r--compiler/rustc_codegen_ssa/src/target_features.rs2
-rw-r--r--compiler/rustc_const_eval/src/interpret/intrinsics.rs14
-rw-r--r--compiler/rustc_const_eval/src/interpret/operand.rs17
-rw-r--r--compiler/rustc_const_eval/src/interpret/projection.rs4
-rw-r--r--compiler/rustc_const_eval/src/interpret/terminator.rs15
-rw-r--r--compiler/rustc_const_eval/src/transform/promote_consts.rs14
-rw-r--r--compiler/rustc_const_eval/src/transform/validate.rs9
-rw-r--r--compiler/rustc_data_structures/Cargo.toml8
-rw-r--r--compiler/rustc_data_structures/src/profiling.rs11
-rw-r--r--compiler/rustc_data_structures/src/stable_hasher.rs2
-rw-r--r--compiler/rustc_data_structures/src/transitive_relation.rs2
-rw-r--r--compiler/rustc_data_structures/src/unord.rs6
-rw-r--r--compiler/rustc_driver/src/lib.rs11
-rw-r--r--compiler/rustc_error_codes/src/error_codes.rs6
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0461.md30
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0462.md32
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0472.md31
-rw-r--r--compiler/rustc_error_messages/locales/en-US/lint.ftl3
-rw-r--r--compiler/rustc_error_messages/locales/en-US/parse.ftl3
-rw-r--r--compiler/rustc_error_messages/src/lib.rs6
-rw-r--r--compiler/rustc_errors/src/lib.rs4
-rw-r--r--compiler/rustc_expand/src/build.rs2
-rw-r--r--compiler/rustc_expand/src/mbe/diagnostics.rs40
-rw-r--r--compiler/rustc_expand/src/mbe/macro_parser.rs13
-rw-r--r--compiler/rustc_expand/src/mbe/macro_rules.rs12
-rw-r--r--compiler/rustc_expand/src/mbe/quoted.rs2
-rw-r--r--compiler/rustc_feature/src/active.rs2
-rw-r--r--compiler/rustc_graphviz/src/lib.rs2
-rw-r--r--compiler/rustc_hir/src/lang_items.rs5
-rw-r--r--compiler/rustc_hir_analysis/src/astconv/mod.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/check/check.rs30
-rw-r--r--compiler/rustc_hir_analysis/src/check/compare_impl_item.rs (renamed from compiler/rustc_hir_analysis/src/check/compare_method.rs)75
-rw-r--r--compiler/rustc_hir_analysis/src/check/intrinsic.rs8
-rw-r--r--compiler/rustc_hir_analysis/src/check/mod.rs14
-rw-r--r--compiler/rustc_hir_analysis/src/check/wfcheck.rs9
-rw-r--r--compiler/rustc_hir_analysis/src/coherence/builtin.rs8
-rw-r--r--compiler/rustc_hir_analysis/src/coherence/orphan.rs23
-rw-r--r--compiler/rustc_hir_analysis/src/collect.rs63
-rw-r--r--compiler/rustc_hir_analysis/src/collect/lifetimes.rs4
-rw-r--r--compiler/rustc_hir_analysis/src/collect/predicates_of.rs6
-rw-r--r--compiler/rustc_hir_analysis/src/collect/type_of.rs13
-rw-r--r--compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs9
-rw-r--r--compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs6
-rw-r--r--compiler/rustc_hir_typeck/src/callee.rs33
-rw-r--r--compiler/rustc_hir_typeck/src/coercion.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/demand.rs247
-rw-r--r--compiler/rustc_hir_typeck/src/expr.rs10
-rw-r--r--compiler/rustc_hir_typeck/src/expr_use_visitor.rs4
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs14
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs135
-rw-r--r--compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/cfg_build.rs1
-rw-r--r--compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/mod.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/generator_interior/mod.rs5
-rw-r--r--compiler/rustc_hir_typeck/src/lib.rs4
-rw-r--r--compiler/rustc_hir_typeck/src/method/mod.rs140
-rw-r--r--compiler/rustc_hir_typeck/src/method/probe.rs43
-rw-r--r--compiler/rustc_hir_typeck/src/method/suggest.rs1
-rw-r--r--compiler/rustc_hir_typeck/src/op.rs67
-rw-r--r--compiler/rustc_hir_typeck/src/pat.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/place_op.rs4
-rw-r--r--compiler/rustc_hir_typeck/src/upvar.rs32
-rw-r--r--compiler/rustc_incremental/src/assert_dep_graph.rs5
-rw-r--r--compiler/rustc_infer/src/infer/canonical/query_response.rs6
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/mod.rs10
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/note_region.rs427
-rw-r--r--compiler/rustc_infer/src/infer/mod.rs13
-rw-r--r--compiler/rustc_infer/src/infer/note.rs203
-rw-r--r--compiler/rustc_infer/src/infer/outlives/obligations.rs2
-rw-r--r--compiler/rustc_interface/src/tests.rs1
-rw-r--r--compiler/rustc_lexer/src/lib.rs2
-rw-r--r--compiler/rustc_lint/src/builtin.rs220
-rw-r--r--compiler/rustc_lint/src/context.rs25
-rw-r--r--compiler/rustc_lint/src/lib.rs4
-rw-r--r--compiler/rustc_lint/src/multiple_supertrait_upcastable.rs63
-rw-r--r--compiler/rustc_lint/src/non_fmt_panic.rs2
-rw-r--r--compiler/rustc_lint/src/unused.rs1
-rw-r--r--compiler/rustc_lint_defs/src/builtin.rs4
-rw-r--r--compiler/rustc_macros/src/diagnostics/subdiagnostic.rs2
-rw-r--r--compiler/rustc_macros/src/diagnostics/utils.rs2
-rw-r--r--compiler/rustc_metadata/src/creader.rs4
-rw-r--r--compiler/rustc_metadata/src/locator.rs8
-rw-r--r--compiler/rustc_metadata/src/rmeta/decoder.rs24
-rw-r--r--compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs2
-rw-r--r--compiler/rustc_metadata/src/rmeta/encoder.rs10
-rw-r--r--compiler/rustc_metadata/src/rmeta/mod.rs5
-rw-r--r--compiler/rustc_middle/Cargo.toml2
-rw-r--r--compiler/rustc_middle/src/dep_graph/dep_node.rs2
-rw-r--r--compiler/rustc_middle/src/hir/map/mod.rs26
-rw-r--r--compiler/rustc_middle/src/hir/mod.rs6
-rw-r--r--compiler/rustc_middle/src/infer/canonical.rs10
-rw-r--r--compiler/rustc_middle/src/middle/stability.rs4
-rw-r--r--compiler/rustc_middle/src/mir/mod.rs6
-rw-r--r--compiler/rustc_middle/src/mir/pretty.rs4
-rw-r--r--compiler/rustc_middle/src/mir/spanview.rs19
-rw-r--r--compiler/rustc_middle/src/mir/syntax.rs21
-rw-r--r--compiler/rustc_middle/src/mir/tcx.rs7
-rw-r--r--compiler/rustc_middle/src/mir/terminator.rs2
-rw-r--r--compiler/rustc_middle/src/mir/traversal.rs2
-rw-r--r--compiler/rustc_middle/src/query/mod.rs4
-rw-r--r--compiler/rustc_middle/src/traits/chalk.rs65
-rw-r--r--compiler/rustc_middle/src/traits/query.rs2
-rw-r--r--compiler/rustc_middle/src/traits/specialization_graph.rs9
-rw-r--r--compiler/rustc_middle/src/ty/closure.rs5
-rw-r--r--compiler/rustc_middle/src/ty/consts.rs2
-rw-r--r--compiler/rustc_middle/src/ty/consts/int.rs2
-rw-r--r--compiler/rustc_middle/src/ty/context.rs4
-rw-r--r--compiler/rustc_middle/src/ty/flags.rs2
-rw-r--r--compiler/rustc_middle/src/ty/generics.rs8
-rw-r--r--compiler/rustc_middle/src/ty/layout.rs2
-rw-r--r--compiler/rustc_middle/src/ty/mod.rs41
-rw-r--r--compiler/rustc_middle/src/ty/print/pretty.rs8
-rw-r--r--compiler/rustc_middle/src/ty/sty.rs12
-rw-r--r--compiler/rustc_middle/src/ty/subst.rs10
-rw-r--r--compiler/rustc_middle/src/ty/util.rs6
-rw-r--r--compiler/rustc_middle/src/ty/visit.rs18
-rw-r--r--compiler/rustc_middle/src/ty/walk.rs2
-rw-r--r--compiler/rustc_middle/src/values.rs23
-rw-r--r--compiler/rustc_mir_build/src/build/custom/parse/instruction.rs3
-rw-r--r--compiler/rustc_mir_build/src/build/expr/as_constant.rs4
-rw-r--r--compiler/rustc_mir_build/src/build/expr/as_operand.rs2
-rw-r--r--compiler/rustc_mir_build/src/build/expr/as_place.rs4
-rw-r--r--compiler/rustc_mir_build/src/build/matches/mod.rs2
-rw-r--r--compiler/rustc_mir_build/src/build/mod.rs12
-rw-r--r--compiler/rustc_mir_build/src/check_unsafety.rs8
-rw-r--r--compiler/rustc_mir_build/src/thir/cx/mod.rs11
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs2
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs4
-rw-r--r--compiler/rustc_mir_dataflow/src/impls/liveness.rs4
-rw-r--r--compiler/rustc_mir_dataflow/src/value_analysis.rs2
-rw-r--r--compiler/rustc_mir_transform/src/check_unsafety.rs6
-rw-r--r--compiler/rustc_mir_transform/src/coverage/mod.rs6
-rw-r--r--compiler/rustc_mir_transform/src/coverage/query.rs4
-rw-r--r--compiler/rustc_mir_transform/src/coverage/tests.rs2
-rw-r--r--compiler/rustc_mir_transform/src/deduce_param_attrs.rs2
-rw-r--r--compiler/rustc_mir_transform/src/dest_prop.rs2
-rw-r--r--compiler/rustc_mir_transform/src/lib.rs32
-rw-r--r--compiler/rustc_mir_transform/src/shim.rs31
-rw-r--r--compiler/rustc_mir_transform/src/simplify_try.rs2
-rw-r--r--compiler/rustc_monomorphize/src/collector.rs2
-rw-r--r--compiler/rustc_monomorphize/src/partitioning/mod.rs9
-rw-r--r--compiler/rustc_parse/src/errors.rs8
-rw-r--r--compiler/rustc_parse/src/parser/diagnostics.rs1
-rw-r--r--compiler/rustc_parse/src/parser/expr.rs10
-rw-r--r--compiler/rustc_parse/src/parser/item.rs2
-rw-r--r--compiler/rustc_parse/src/parser/mod.rs4
-rw-r--r--compiler/rustc_parse/src/parser/pat.rs18
-rw-r--r--compiler/rustc_parse/src/parser/ty.rs67
-rw-r--r--compiler/rustc_parse_format/src/lib.rs127
-rw-r--r--compiler/rustc_passes/src/check_attr.rs4
-rw-r--r--compiler/rustc_passes/src/dead.rs16
-rw-r--r--compiler/rustc_passes/src/debugger_visualizer.rs6
-rw-r--r--compiler/rustc_passes/src/diagnostic_items.rs10
-rw-r--r--compiler/rustc_passes/src/layout_test.rs2
-rw-r--r--compiler/rustc_passes/src/reachable.rs4
-rw-r--r--compiler/rustc_passes/src/stability.rs2
-rw-r--r--compiler/rustc_passes/src/weak_lang_items.rs4
-rw-r--r--compiler/rustc_query_impl/src/on_disk_cache.rs2
-rw-r--r--compiler/rustc_query_impl/src/plumbing.rs24
-rw-r--r--compiler/rustc_query_impl/src/profiling_support.rs2
-rw-r--r--compiler/rustc_query_system/src/query/config.rs2
-rw-r--r--compiler/rustc_query_system/src/query/job.rs104
-rw-r--r--compiler/rustc_query_system/src/query/mod.rs13
-rw-r--r--compiler/rustc_query_system/src/query/plumbing.rs83
-rw-r--r--compiler/rustc_query_system/src/values.rs10
-rw-r--r--compiler/rustc_resolve/src/late.rs40
-rw-r--r--compiler/rustc_resolve/src/lib.rs26
-rw-r--r--compiler/rustc_save_analysis/src/lib.rs6
-rw-r--r--compiler/rustc_session/src/options.rs8
-rw-r--r--compiler/rustc_session/src/parse.rs12
-rw-r--r--compiler/rustc_session/src/session.rs24
-rw-r--r--compiler/rustc_session/src/utils.rs2
-rw-r--r--compiler/rustc_span/Cargo.toml2
-rw-r--r--compiler/rustc_span/src/lib.rs3
-rw-r--r--compiler/rustc_span/src/symbol.rs7
-rw-r--r--compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs2
-rw-r--r--compiler/rustc_target/src/abi/call/loongarch.rs4
-rw-r--r--compiler/rustc_target/src/abi/call/riscv.rs4
-rw-r--r--compiler/rustc_target/src/spec/mod.rs4
-rw-r--r--compiler/rustc_trait_selection/src/lib.rs2
-rw-r--r--compiler/rustc_trait_selection/src/solve/assembly.rs150
-rw-r--r--compiler/rustc_trait_selection/src/solve/cache.rs257
-rw-r--r--compiler/rustc_trait_selection/src/solve/fulfill.rs92
-rw-r--r--compiler/rustc_trait_selection/src/solve/infcx_ext.rs55
-rw-r--r--compiler/rustc_trait_selection/src/solve/mod.rs309
-rw-r--r--compiler/rustc_trait_selection/src/solve/overflow.rs80
-rw-r--r--compiler/rustc_trait_selection/src/solve/project_goals.rs244
-rw-r--r--compiler/rustc_trait_selection/src/solve/trait_goals.rs180
-rw-r--r--compiler/rustc_trait_selection/src/traits/coherence.rs8
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/method_chain.rs27
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs96
-rw-r--r--compiler/rustc_trait_selection/src/traits/mod.rs5
-rw-r--r--compiler/rustc_trait_selection/src/traits/outlives_bounds.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/project.rs61
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/mod.rs14
-rw-r--r--compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs49
-rw-r--r--compiler/rustc_trait_selection/src/traits/util.rs1
-rw-r--r--compiler/rustc_trait_selection/src/traits/vtable.rs2
-rw-r--r--compiler/rustc_traits/src/chalk/db.rs2
-rw-r--r--compiler/rustc_traits/src/normalize_erasing_regions.rs2
-rw-r--r--compiler/rustc_ty_utils/src/consts.rs14
-rw-r--r--compiler/rustc_ty_utils/src/implied_bounds.rs2
-rw-r--r--compiler/rustc_ty_utils/src/instance.rs2
-rw-r--r--compiler/rustc_ty_utils/src/layout.rs4
-rw-r--r--compiler/rustc_ty_utils/src/ty.rs5
-rw-r--r--library/alloc/src/boxed.rs2
-rw-r--r--library/alloc/src/collections/binary_heap/tests.rs98
-rw-r--r--library/alloc/src/collections/btree/map/tests.rs6
-rw-r--r--library/alloc/src/collections/btree/mod.rs3
-rw-r--r--library/alloc/src/collections/btree/set/tests.rs4
-rw-r--r--library/alloc/src/collections/linked_list/tests.rs56
-rw-r--r--library/alloc/src/lib.rs4
-rw-r--r--library/alloc/src/testing/crash_test.rs (renamed from library/alloc/src/collections/btree/testing/crash_test.rs)0
-rw-r--r--library/alloc/src/testing/mod.rs (renamed from library/alloc/src/collections/btree/testing/mod.rs)0
-rw-r--r--library/alloc/src/testing/ord_chaos.rs (renamed from library/alloc/src/collections/btree/testing/ord_chaos.rs)0
-rw-r--r--library/alloc/src/testing/rng.rs (renamed from library/alloc/src/collections/btree/testing/rng.rs)0
-rw-r--r--library/alloc/src/vec/into_iter.rs23
-rw-r--r--library/alloc/src/vec/mod.rs2
-rw-r--r--library/alloc/tests/vec.rs29
-rw-r--r--library/core/src/any.rs2
-rw-r--r--library/core/src/cell.rs19
-rw-r--r--library/core/src/cell/lazy.rs4
-rw-r--r--library/core/src/char/decode.rs2
-rw-r--r--library/core/src/const_closure.rs4
-rw-r--r--library/core/src/convert/num.rs20
-rw-r--r--library/core/src/error.rs1
-rw-r--r--library/core/src/hash/mod.rs4
-rw-r--r--library/core/src/intrinsics.rs8
-rw-r--r--library/core/src/intrinsics/mir.rs1
-rw-r--r--library/core/src/iter/sources/empty.rs7
-rw-r--r--library/core/src/iter/traits/iterator.rs3
-rw-r--r--library/core/src/lib.rs2
-rw-r--r--library/core/src/mem/mod.rs3
-rw-r--r--library/core/src/ops/index.rs2
-rw-r--r--library/core/src/panicking.rs14
-rw-r--r--library/core/src/ptr/mod.rs52
-rw-r--r--library/core/src/slice/mod.rs18
-rw-r--r--library/core/src/str/mod.rs6
-rw-r--r--library/core/src/task/wake.rs4
-rw-r--r--library/core/tests/char.rs4
-rw-r--r--library/core/tests/lazy.rs6
-rw-r--r--library/std/src/io/stdio.rs3
-rw-r--r--library/std/src/panic.rs3
-rw-r--r--library/std/src/process.rs9
-rw-r--r--library/std/src/process/tests.rs94
-rw-r--r--library/std/src/sync/lazy_lock.rs5
-rw-r--r--library/std/src/sync/lazy_lock/tests.rs6
-rw-r--r--library/std/src/sync/mod.rs3
-rw-r--r--library/std/src/sync/mpmc/utils.rs2
-rw-r--r--library/std/src/sync/remutex.rs (renamed from library/std/src/sys_common/remutex.rs)0
-rw-r--r--library/std/src/sync/remutex/tests.rs (renamed from library/std/src/sys_common/remutex/tests.rs)2
-rw-r--r--library/std/src/sys/unix/fs.rs4
-rw-r--r--library/std/src/sys/unix/kernel_copy.rs4
-rw-r--r--library/std/src/sys/unix/mod.rs8
-rw-r--r--library/std/src/sys/unix/process/process_common.rs67
-rw-r--r--library/std/src/sys/unix/stack_overflow.rs4
-rw-r--r--library/std/src/sys/unix/thread.rs8
-rw-r--r--library/std/src/sys/unix/thread_parker/pthread.rs6
-rw-r--r--library/std/src/sys_common/mod.rs1
-rw-r--r--library/std/src/sys_common/process.rs11
-rw-r--r--library/std/src/sys_common/thread_local_key.rs25
-rw-r--r--src/bootstrap/CHANGELOG.md1
-rw-r--r--src/bootstrap/Cargo.toml5
-rw-r--r--src/bootstrap/README.md10
-rw-r--r--src/bootstrap/bin/llvm-config-wrapper.rs24
-rw-r--r--src/bootstrap/builder.rs129
-rw-r--r--src/bootstrap/clean.rs78
-rw-r--r--src/bootstrap/compile.rs35
-rw-r--r--src/bootstrap/config.rs9
-rw-r--r--src/bootstrap/dist.rs7
-rw-r--r--src/bootstrap/doc.rs63
-rw-r--r--src/bootstrap/flags.rs22
-rw-r--r--src/bootstrap/format.rs97
-rw-r--r--src/bootstrap/lib.rs12
-rw-r--r--src/bootstrap/mk/Makefile.in5
-rw-r--r--src/bootstrap/native.rs112
-rw-r--r--src/bootstrap/setup.rs4
-rw-r--r--src/bootstrap/test.rs3
-rw-r--r--src/ci/docker/host-x86_64/mingw-check-tidy/Dockerfile36
-rw-r--r--src/ci/docker/host-x86_64/mingw-check/Dockerfile1
-rw-r--r--src/ci/github-actions/ci.yml10
-rwxr-xr-xsrc/ci/run.sh10
-rw-r--r--src/doc/rustdoc/src/write-documentation/the-doc-attribute.md4
-rwxr-xr-xsrc/etc/pre-push.sh12
-rw-r--r--src/librustdoc/html/format.rs8
-rw-r--r--src/librustdoc/html/render/mod.rs5
-rw-r--r--src/librustdoc/html/render/write_shared.rs2
-rw-r--r--src/librustdoc/html/static/css/rustdoc.css94
-rw-r--r--src/librustdoc/html/static/css/themes/ayu.css32
-rw-r--r--src/librustdoc/html/static/css/themes/dark.css22
-rw-r--r--src/librustdoc/html/static/css/themes/light.css22
-rw-r--r--src/librustdoc/html/static/js/main.js12
-rw-r--r--src/librustdoc/html/static/js/search.js16
-rw-r--r--src/librustdoc/visit_ast.rs163
-rw-r--r--src/test/assembly/x86_64-no-jump-tables.rs34
-rw-r--r--src/test/codegen/comparison-operators-newtype.rs49
-rw-r--r--src/test/codegen/no-jump-tables.rs22
-rw-r--r--src/test/codegen/sanitizer-kcfi-emit-kcfi-operand-bundle-itanium-cxx-abi.rs9
-rw-r--r--src/test/codegen/unwind-abis/c-unwind-abi-panic-abort.rs3
-rw-r--r--src/test/codegen/unwind-and-panic-abort.rs3
-rw-r--r--src/test/codegen/vec-shrink-panik.rs16
-rw-r--r--src/test/mir-opt/building/custom/references.immut_ref.built.after.mir7
-rw-r--r--src/test/mir-opt/building/custom/references.mut_ref.built.after.mir7
-rw-r--r--src/test/mir-opt/building/custom/references.rs2
-rw-r--r--src/test/mir-opt/retag.core.ptr-drop_in_place.Test.SimplifyCfg-make_shim.after.mir7
-rw-r--r--src/test/rustdoc-gui/basic-code.goml1
-rw-r--r--src/test/rustdoc-gui/cursor.goml4
-rw-r--r--src/test/rustdoc-gui/docblock-code-block-line-number.goml54
-rw-r--r--src/test/rustdoc-gui/links-color.goml161
-rw-r--r--src/test/rustdoc-gui/scrape-examples-layout.goml35
-rw-r--r--src/test/rustdoc-gui/scrape-examples-toggle.goml45
-rw-r--r--src/test/rustdoc-gui/search-filter.goml6
-rw-r--r--src/test/rustdoc-gui/search-keyboard.goml2
-rw-r--r--src/test/rustdoc-gui/search-result-color.goml23
-rw-r--r--src/test/rustdoc-gui/search-result-description.goml2
-rw-r--r--src/test/rustdoc-gui/search-result-go-to-first.goml2
-rw-r--r--src/test/rustdoc-gui/search-result-keyword.goml2
-rw-r--r--src/test/rustdoc-gui/search-tab-change-title-fn-sig.goml46
-rw-r--r--src/test/rustdoc-gui/search-tab.goml76
-rw-r--r--src/test/rustdoc-gui/sidebar-source-code.goml47
-rw-r--r--src/test/rustdoc-gui/sidebar.goml44
-rw-r--r--src/test/rustdoc-gui/source-code-page.goml4
-rw-r--r--src/test/rustdoc-gui/src/scrape_examples/examples/check-many-1.rs10
-rw-r--r--src/test/rustdoc-gui/src/scrape_examples/examples/check-many-2.rs12
-rw-r--r--src/test/rustdoc-gui/src/scrape_examples/examples/check-many-3.rs12
-rw-r--r--src/test/rustdoc-gui/src/scrape_examples/examples/check-many-4.rs10
-rw-r--r--src/test/rustdoc-gui/src/scrape_examples/examples/check-many-5.rs10
-rw-r--r--src/test/rustdoc-gui/src/scrape_examples/examples/check-many-6.rs10
-rw-r--r--src/test/rustdoc-gui/src/scrape_examples/examples/check-many-7.rs10
-rw-r--r--src/test/rustdoc-ui/infinite-recursive-type-impl-trait-return.rs4
-rw-r--r--src/test/rustdoc-ui/infinite-recursive-type-impl-trait-return.stderr16
-rw-r--r--src/test/rustdoc-ui/infinite-recursive-type-impl-trait.rs5
-rw-r--r--src/test/rustdoc-ui/infinite-recursive-type-impl-trait.stderr16
-rw-r--r--src/test/rustdoc-ui/z-help.stdout1
-rw-r--r--src/test/rustdoc/impl-in-const-block.rs43
-rw-r--r--src/test/rustdoc/issue-105952.rs14
-rw-r--r--src/test/ui/argument-suggestions/extern-fn-arg-names.rs9
-rw-r--r--src/test/ui/argument-suggestions/extern-fn-arg-names.stderr26
-rw-r--r--src/test/ui/asm/bad-arch.mirunsafeck.stderr1
-rw-r--r--src/test/ui/asm/bad-arch.thirunsafeck.stderr1
-rw-r--r--src/test/ui/async-await/async-is-unwindsafe.rs30
-rw-r--r--src/test/ui/async-await/async-is-unwindsafe.stderr38
-rw-r--r--src/test/ui/async-await/track-caller/async-closure-gate.rs1
-rw-r--r--src/test/ui/async-await/track-caller/async-closure-gate.stderr15
-rw-r--r--src/test/ui/async-await/track-caller/panic-track-caller.nofeat.stderr29
-rw-r--r--src/test/ui/async-await/track-caller/panic-track-caller.rs29
-rw-r--r--src/test/ui/attributes/issue-105594-invalid-attr-validation.rs13
-rw-r--r--src/test/ui/attributes/issue-105594-invalid-attr-validation.stderr26
-rw-r--r--src/test/ui/attributes/z-crate-attr.rs (renamed from src/test/ui/z-crate-attr.rs)0
-rw-r--r--src/test/ui/borrowck/borrowck-move-out-of-overloaded-auto-deref.stderr4
-rw-r--r--src/test/ui/borrowck/unboxed-closures-move-upvar-from-non-once-ref-closure.fixed15
-rw-r--r--src/test/ui/borrowck/unboxed-closures-move-upvar-from-non-once-ref-closure.rs1
-rw-r--r--src/test/ui/borrowck/unboxed-closures-move-upvar-from-non-once-ref-closure.stderr6
-rw-r--r--src/test/ui/codemap_tests/tab_3.stderr4
-rw-r--r--src/test/ui/command/command-argv0-debug.rs21
-rw-r--r--src/test/ui/const-generics/generic_const_exprs/issue-94293.rs31
-rw-r--r--src/test/ui/const-generics/generic_const_exprs/issue-99647.rs15
-rw-r--r--src/test/ui/consts/assert-type-intrinsics.rs2
-rw-r--r--src/test/ui/consts/assert-type-intrinsics.stderr4
-rw-r--r--src/test/ui/consts/issue-104396.rs36
-rw-r--r--src/test/ui/consts/issue-104396.stderr11
-rw-r--r--src/test/ui/consts/promoted_const_call.rs19
-rw-r--r--src/test/ui/consts/promoted_const_call.stderr65
-rw-r--r--src/test/ui/consts/promoted_const_call2.rs14
-rw-r--r--src/test/ui/consts/promoted_const_call2.stderr50
-rw-r--r--src/test/ui/consts/promoted_const_call3.rs26
-rw-r--r--src/test/ui/consts/promoted_const_call3.stderr105
-rw-r--r--src/test/ui/consts/promoted_const_call4.rs18
-rw-r--r--src/test/ui/consts/promoted_const_call5.rs42
-rw-r--r--src/test/ui/consts/promoted_const_call5.stderr74
-rw-r--r--src/test/ui/error-codes/E0033-teach.rs12
-rw-r--r--src/test/ui/error-codes/E0033-teach.stderr33
-rw-r--r--src/test/ui/error-codes/E0033.rs11
-rw-r--r--src/test/ui/error-codes/E0033.stderr35
-rw-r--r--src/test/ui/error-codes/E0462.rs11
-rw-r--r--src/test/ui/error-codes/E0462.stderr13
-rw-r--r--src/test/ui/error-codes/auxiliary/found-staticlib.rs4
-rw-r--r--src/test/ui/feature-gates/feature-gate-multiple_supertrait_upcastable.rs12
-rw-r--r--src/test/ui/feature-gates/feature-gate-multiple_supertrait_upcastable.stderr57
-rw-r--r--src/test/ui/fmt/issue-103826.rs8
-rw-r--r--src/test/ui/fmt/issue-103826.stderr20
-rw-r--r--src/test/ui/fn/issue-3044.rs (renamed from src/test/ui/issues/issue-3044.rs)0
-rw-r--r--src/test/ui/fn/issue-3044.stderr (renamed from src/test/ui/issues/issue-3044.stderr)0
-rw-r--r--src/test/ui/fn/issue-3904.rs (renamed from src/test/ui/issues/issue-3904.rs)0
-rw-r--r--src/test/ui/generator/unresolved-ct-var-drop-tracking.rs15
-rw-r--r--src/test/ui/generator/unresolved-ct-var-drop-tracking.stderr78
-rw-r--r--src/test/ui/generic-associated-types/impl_bounds.rs1
-rw-r--r--src/test/ui/generic-associated-types/impl_bounds.stderr28
-rw-r--r--src/test/ui/imports/local-modularized-tricky-fail-1.rs1
-rw-r--r--src/test/ui/imports/local-modularized-tricky-fail-1.stderr31
-rw-r--r--src/test/ui/imports/macros.rs1
-rw-r--r--src/test/ui/imports/macros.stderr29
-rw-r--r--src/test/ui/intrinsics/panic-uninitialized-zeroed.rs52
-rw-r--r--src/test/ui/issues/issue-6470.rs17
-rw-r--r--src/test/ui/iterators/invalid-iterator-chain.stderr8
-rw-r--r--src/test/ui/late-bound-lifetimes/issue-36381.rs (renamed from src/test/ui/issues/issue-36381.rs)0
-rw-r--r--src/test/ui/lexer/lex-bad-char-literals-6.rs2
-rw-r--r--src/test/ui/lexer/lex-bad-char-literals-6.stderr41
-rw-r--r--src/test/ui/lint/must_not_suspend/tuple-mismatch.rs9
-rw-r--r--src/test/ui/lint/must_not_suspend/tuple-mismatch.stderr12
-rw-r--r--src/test/ui/lint/unused/must-use-box-from-raw.stderr2
-rw-r--r--src/test/ui/lint/unused_braces_macro.rs6
-rw-r--r--src/test/ui/macros/best-failure.rs11
-rw-r--r--src/test/ui/macros/best-failure.stderr21
-rw-r--r--src/test/ui/macros/issue-25385.rs (renamed from src/test/ui/issues/issue-25385.rs)0
-rw-r--r--src/test/ui/macros/issue-25385.stderr (renamed from src/test/ui/issues/issue-25385.stderr)0
-rw-r--r--src/test/ui/match/issue-5530.rs (renamed from src/test/ui/issues/issue-5530.rs)0
-rw-r--r--src/test/ui/match/single-line.rs3
-rw-r--r--src/test/ui/match/single-line.stderr12
-rw-r--r--src/test/ui/methods/issues/issue-105732.rs3
-rw-r--r--src/test/ui/methods/issues/issue-105732.stderr16
-rw-r--r--src/test/ui/mismatched_types/suggest-removing-tuple-struct-field.fixed (renamed from src/test/ui/mismatched_types/suggest-removing-tulpe-struct-field.fixed)0
-rw-r--r--src/test/ui/mismatched_types/suggest-removing-tuple-struct-field.rs (renamed from src/test/ui/mismatched_types/suggest-removing-tulpe-struct-field.rs)0
-rw-r--r--src/test/ui/mismatched_types/suggest-removing-tuple-struct-field.stderr (renamed from src/test/ui/mismatched_types/suggest-removing-tulpe-struct-field.stderr)8
-rw-r--r--src/test/ui/moves/move-fn-self-receiver.stderr12
-rw-r--r--src/test/ui/moves/moves-based-on-type-access-to-field.stderr4
-rw-r--r--src/test/ui/moves/moves-based-on-type-exprs.stderr8
-rw-r--r--src/test/ui/moves/pin-mut-reborrow.fixed15
-rw-r--r--src/test/ui/moves/pin-mut-reborrow.rs15
-rw-r--r--src/test/ui/moves/pin-mut-reborrow.stderr23
-rw-r--r--src/test/ui/moves/suggest-clone.fixed11
-rw-r--r--src/test/ui/moves/suggest-clone.rs11
-rw-r--r--src/test/ui/moves/suggest-clone.stderr22
-rw-r--r--src/test/ui/parser/intersection-patterns-1.fixed35
-rw-r--r--src/test/ui/parser/intersection-patterns-1.rs (renamed from src/test/ui/parser/intersection-patterns.rs)13
-rw-r--r--src/test/ui/parser/intersection-patterns-1.stderr (renamed from src/test/ui/parser/intersection-patterns.stderr)17
-rw-r--r--src/test/ui/parser/intersection-patterns-2.rs20
-rw-r--r--src/test/ui/parser/intersection-patterns-2.stderr13
-rw-r--r--src/test/ui/parser/issue-105634.rs8
-rw-r--r--src/test/ui/parser/kw-in-trait-bounds.rs16
-rw-r--r--src/test/ui/parser/kw-in-trait-bounds.stderr88
-rw-r--r--src/test/ui/parser/recover-fn-trait-from-fn-kw.rs12
-rw-r--r--src/test/ui/parser/recover-fn-trait-from-fn-kw.stderr48
-rw-r--r--src/test/ui/proc-macro/quote-debug.stdout1
-rw-r--r--src/test/ui/repr/transparent-enum-too-many-variants.rs10
-rw-r--r--src/test/ui/repr/transparent-enum-too-many-variants.stderr11
-rw-r--r--src/test/ui/resolve/auxiliary/issue-30535.rs (renamed from src/test/ui/issues/auxiliary/issue-30535.rs)0
-rw-r--r--src/test/ui/resolve/issue-30535.rs (renamed from src/test/ui/issues/issue-30535.rs)0
-rw-r--r--src/test/ui/resolve/issue-30535.stderr (renamed from src/test/ui/issues/issue-30535.stderr)0
-rw-r--r--src/test/ui/resolve/issue-39559-2.rs (renamed from src/test/ui/issues/issue-39559-2.rs)0
-rw-r--r--src/test/ui/resolve/issue-39559-2.stderr (renamed from src/test/ui/issues/issue-39559-2.stderr)0
-rw-r--r--src/test/ui/resolve/issue-39559.rs (renamed from src/test/ui/issues/issue-39559.rs)0
-rw-r--r--src/test/ui/resolve/issue-39559.stderr (renamed from src/test/ui/issues/issue-39559.stderr)0
-rw-r--r--src/test/ui/rust-2018/edition-lint-infer-outlives-macro.fixed137
-rw-r--r--src/test/ui/rust-2018/edition-lint-infer-outlives-macro.rs119
-rw-r--r--src/test/ui/rust-2018/edition-lint-infer-outlives-macro.stderr102
-rw-r--r--src/test/ui/static/issue-18118-2.rs (renamed from src/test/ui/issues/issue-18118-2.rs)0
-rw-r--r--src/test/ui/static/issue-18118-2.stderr (renamed from src/test/ui/issues/issue-18118-2.stderr)0
-rw-r--r--src/test/ui/static/issue-18118.rs (renamed from src/test/ui/issues/issue-18118.rs)0
-rw-r--r--src/test/ui/static/issue-18118.stderr (renamed from src/test/ui/issues/issue-18118.stderr)0
-rw-r--r--src/test/ui/suggestions/assoc-ct-for-assoc-method.rs25
-rw-r--r--src/test/ui/suggestions/assoc-ct-for-assoc-method.stderr47
-rw-r--r--src/test/ui/suggestions/bad-hex-float-lit.rs13
-rw-r--r--src/test/ui/suggestions/bad-hex-float-lit.stderr48
-rw-r--r--src/test/ui/suggestions/fn-to-method-deeply-nested.rs13
-rw-r--r--src/test/ui/suggestions/fn-to-method-deeply-nested.stderr39
-rw-r--r--src/test/ui/suggestions/issue-104287.rs10
-rw-r--r--src/test/ui/suggestions/issue-104287.stderr34
-rw-r--r--src/test/ui/suggestions/issue-105494.rs22
-rw-r--r--src/test/ui/suggestions/issue-105494.stderr54
-rw-r--r--src/test/ui/suggestions/method-access-to-range-literal-typo.rs30
-rw-r--r--src/test/ui/suggestions/method-access-to-range-literal-typo.stderr48
-rw-r--r--src/test/ui/suggestions/option-content-move.stderr8
-rw-r--r--src/test/ui/suggestions/shadowed-lplace-method-2.rs23
-rw-r--r--src/test/ui/suggestions/shadowed-lplace-method-2.stderr25
-rw-r--r--src/test/ui/suggestions/shadowed-lplace-method.fixed10
-rw-r--r--src/test/ui/suggestions/shadowed-lplace-method.rs10
-rw-r--r--src/test/ui/suggestions/shadowed-lplace-method.stderr26
-rw-r--r--src/test/ui/suggestions/unnamable-types.stderr4
-rw-r--r--src/test/ui/test-attrs/issue-52557.rs (renamed from src/test/ui/issues/issue-52557.rs)0
-rw-r--r--src/test/ui/traits/solver-cycles/inductive-canonical-cycle.rs28
-rw-r--r--src/test/ui/traits/solver-cycles/inductive-canonical-cycle.stderr26
-rw-r--r--src/test/ui/traits/trait-upcasting/multiple_supertrait_upcastable.rs10
-rw-r--r--src/test/ui/traits/trait-upcasting/multiple_supertrait_upcastable.stderr14
-rw-r--r--src/test/ui/type-alias-impl-trait/coherence.stderr2
-rw-r--r--src/test/ui/type-alias-impl-trait/destructuring.rs10
-rw-r--r--src/test/ui/type/issue-102598.rs8
-rw-r--r--src/test/ui/type/issue-102598.stderr43
-rw-r--r--src/test/ui/typeck/check-args-on-fn-err-2.rs5
-rw-r--r--src/test/ui/typeck/check-args-on-fn-err-2.stderr23
-rw-r--r--src/test/ui/typeck/check-args-on-fn-err.rs6
-rw-r--r--src/test/ui/typeck/check-args-on-fn-err.stderr9
-rw-r--r--src/test/ui/typeck/issue-22375.rs (renamed from src/test/ui/issues/issue-22375.rs)0
-rw-r--r--src/test/ui/typeck/issue-96530.rs20
-rw-r--r--src/test/ui/typeck/issue-96530.stderr9
-rw-r--r--src/test/ui/typeck/quiet-type-err-let-binding.rs17
-rw-r--r--src/test/ui/typeck/quiet-type-err-let-binding.stderr9
-rw-r--r--src/test/ui/typeck/typeck_type_placeholder_item.rs8
-rw-r--r--src/test/ui/typeck/typeck_type_placeholder_item.stderr23
-rw-r--r--src/test/ui/unboxed-closures/non-tupled-call.rs17
-rw-r--r--src/test/ui/unboxed-closures/non-tupled-call.stderr9
m---------src/tools/cargo0
-rw-r--r--src/tools/compiletest/src/common.rs4
-rw-r--r--src/tools/compiletest/src/runtest.rs8
-rw-r--r--src/tools/miri/CONTRIBUTING.md12
-rw-r--r--src/tools/miri/README.md18
-rwxr-xr-xsrc/tools/miri/miri2
-rw-r--r--src/tools/miri/rust-version2
-rw-r--r--src/tools/miri/src/bin/miri.rs12
-rw-r--r--src/tools/miri/src/borrow_tracker/mod.rs12
-rw-r--r--src/tools/miri/src/borrow_tracker/stacked_borrows/diagnostics.rs4
-rw-r--r--src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs5
-rw-r--r--src/tools/miri/src/concurrency/data_race.rs175
-rw-r--r--src/tools/miri/src/concurrency/init_once.rs6
-rw-r--r--src/tools/miri/src/concurrency/sync.rs33
-rw-r--r--src/tools/miri/src/concurrency/thread.rs12
-rw-r--r--src/tools/miri/src/concurrency/vector_clock.rs90
-rw-r--r--src/tools/miri/src/concurrency/weak_memory.rs2
-rw-r--r--src/tools/miri/src/diagnostics.rs33
-rw-r--r--src/tools/miri/src/eval.rs5
-rw-r--r--src/tools/miri/src/helpers.rs58
-rw-r--r--src/tools/miri/src/intptrcast.rs4
-rw-r--r--src/tools/miri/src/lib.rs3
-rw-r--r--src/tools/miri/src/machine.rs49
-rw-r--r--src/tools/miri/src/shims/env.rs20
-rw-r--r--src/tools/miri/src/shims/foreign_items.rs49
-rw-r--r--src/tools/miri/src/shims/intrinsics/mod.rs4
-rw-r--r--src/tools/miri/src/shims/mod.rs2
-rw-r--r--src/tools/miri/src/shims/os_str.rs80
-rw-r--r--src/tools/miri/src/shims/time.rs26
-rw-r--r--src/tools/miri/src/shims/tls.rs4
-rw-r--r--src/tools/miri/src/shims/unix/foreign_items.rs36
-rw-r--r--src/tools/miri/src/shims/unix/fs.rs188
-rw-r--r--src/tools/miri/src/shims/unix/linux/fd.rs191
-rw-r--r--src/tools/miri/src/shims/unix/linux/fd/epoll.rs53
-rw-r--r--src/tools/miri/src/shims/unix/linux/fd/event.rs38
-rw-r--r--src/tools/miri/src/shims/unix/linux/fd/socketpair.rs32
-rw-r--r--src/tools/miri/src/shims/unix/linux/foreign_items.rs45
-rw-r--r--src/tools/miri/src/shims/unix/linux/mod.rs1
-rw-r--r--src/tools/miri/src/shims/unix/linux/sync.rs29
-rw-r--r--src/tools/miri/src/shims/unix/macos/dlsym.rs2
-rw-r--r--src/tools/miri/src/shims/unix/macos/foreign_items.rs10
-rw-r--r--src/tools/miri/src/shims/unix/sync.rs66
-rw-r--r--src/tools/miri/src/shims/unix/thread.rs8
-rw-r--r--src/tools/miri/src/shims/windows/dlsym.rs4
-rw-r--r--src/tools/miri/src/shims/windows/foreign_items.rs21
-rw-r--r--src/tools/miri/src/shims/windows/sync.rs30
-rw-r--r--src/tools/miri/src/shims/windows/thread.rs6
-rw-r--r--src/tools/miri/test-cargo-miri/src/main.rs27
-rw-r--r--src/tools/miri/test-cargo-miri/subcrate/main.rs29
-rw-r--r--src/tools/miri/test-cargo-miri/subcrate/test.rs27
-rw-r--r--src/tools/miri/tests/fail/box-cell-alias.stderr2
-rw-r--r--src/tools/miri/tests/fail/crates/tokio_mvp.rs7
-rw-r--r--src/tools/miri/tests/fail/crates/tokio_mvp.stderr19
-rw-r--r--src/tools/miri/tests/fail/data_race/alloc_read_race.rs2
-rw-r--r--src/tools/miri/tests/fail/data_race/alloc_read_race.stderr11
-rw-r--r--src/tools/miri/tests/fail/data_race/alloc_write_race.rs2
-rw-r--r--src/tools/miri/tests/fail/data_race/alloc_write_race.stderr11
-rw-r--r--src/tools/miri/tests/fail/data_race/atomic_read_na_write_race1.rs2
-rw-r--r--src/tools/miri/tests/fail/data_race/atomic_read_na_write_race1.stderr11
-rw-r--r--src/tools/miri/tests/fail/data_race/atomic_read_na_write_race2.rs2
-rw-r--r--src/tools/miri/tests/fail/data_race/atomic_read_na_write_race2.stderr11
-rw-r--r--src/tools/miri/tests/fail/data_race/atomic_write_na_read_race1.rs2
-rw-r--r--src/tools/miri/tests/fail/data_race/atomic_write_na_read_race1.stderr11
-rw-r--r--src/tools/miri/tests/fail/data_race/atomic_write_na_read_race2.rs2
-rw-r--r--src/tools/miri/tests/fail/data_race/atomic_write_na_read_race2.stderr11
-rw-r--r--src/tools/miri/tests/fail/data_race/atomic_write_na_write_race1.rs2
-rw-r--r--src/tools/miri/tests/fail/data_race/atomic_write_na_write_race1.stderr11
-rw-r--r--src/tools/miri/tests/fail/data_race/atomic_write_na_write_race2.rs2
-rw-r--r--src/tools/miri/tests/fail/data_race/atomic_write_na_write_race2.stderr11
-rw-r--r--src/tools/miri/tests/fail/data_race/dangling_thread_async_race.rs2
-rw-r--r--src/tools/miri/tests/fail/data_race/dangling_thread_async_race.stderr11
-rw-r--r--src/tools/miri/tests/fail/data_race/dangling_thread_race.rs2
-rw-r--r--src/tools/miri/tests/fail/data_race/dangling_thread_race.stderr11
-rw-r--r--src/tools/miri/tests/fail/data_race/dealloc_read_race1.rs2
-rw-r--r--src/tools/miri/tests/fail/data_race/dealloc_read_race1.stderr11
-rw-r--r--src/tools/miri/tests/fail/data_race/dealloc_read_race2.rs2
-rw-r--r--src/tools/miri/tests/fail/data_race/dealloc_read_race_stack.rs2
-rw-r--r--src/tools/miri/tests/fail/data_race/dealloc_read_race_stack.stderr11
-rw-r--r--src/tools/miri/tests/fail/data_race/dealloc_write_race1.rs2
-rw-r--r--src/tools/miri/tests/fail/data_race/dealloc_write_race1.stderr11
-rw-r--r--src/tools/miri/tests/fail/data_race/dealloc_write_race2.rs2
-rw-r--r--src/tools/miri/tests/fail/data_race/dealloc_write_race_stack.rs2
-rw-r--r--src/tools/miri/tests/fail/data_race/dealloc_write_race_stack.stderr11
-rw-r--r--src/tools/miri/tests/fail/data_race/enable_after_join_to_main.rs2
-rw-r--r--src/tools/miri/tests/fail/data_race/enable_after_join_to_main.stderr11
-rw-r--r--src/tools/miri/tests/fail/data_race/fence_after_load.rs2
-rw-r--r--src/tools/miri/tests/fail/data_race/fence_after_load.stderr11
-rw-r--r--src/tools/miri/tests/fail/data_race/read_write_race.rs2
-rw-r--r--src/tools/miri/tests/fail/data_race/read_write_race.stderr11
-rw-r--r--src/tools/miri/tests/fail/data_race/read_write_race_stack.rs2
-rw-r--r--src/tools/miri/tests/fail/data_race/read_write_race_stack.stderr11
-rw-r--r--src/tools/miri/tests/fail/data_race/relax_acquire_race.rs2
-rw-r--r--src/tools/miri/tests/fail/data_race/relax_acquire_race.stderr11
-rw-r--r--src/tools/miri/tests/fail/data_race/release_seq_race.rs2
-rw-r--r--src/tools/miri/tests/fail/data_race/release_seq_race.stderr11
-rw-r--r--src/tools/miri/tests/fail/data_race/release_seq_race_same_thread.rs2
-rw-r--r--src/tools/miri/tests/fail/data_race/release_seq_race_same_thread.stderr11
-rw-r--r--src/tools/miri/tests/fail/data_race/rmw_race.rs2
-rw-r--r--src/tools/miri/tests/fail/data_race/rmw_race.stderr11
-rw-r--r--src/tools/miri/tests/fail/data_race/stack_pop_race.rs2
-rw-r--r--src/tools/miri/tests/fail/data_race/stack_pop_race.stderr11
-rw-r--r--src/tools/miri/tests/fail/data_race/write_write_race.rs2
-rw-r--r--src/tools/miri/tests/fail/data_race/write_write_race.stderr11
-rw-r--r--src/tools/miri/tests/fail/data_race/write_write_race_stack.rs2
-rw-r--r--src/tools/miri/tests/fail/data_race/write_write_race_stack.stderr11
-rw-r--r--src/tools/miri/tests/fail/function_calls/exported_symbol_clashing.stderr2
-rw-r--r--src/tools/miri/tests/fail/function_calls/exported_symbol_shim_clashing.stderr2
-rw-r--r--src/tools/miri/tests/fail/reading_half_a_pointer.rs2
-rw-r--r--src/tools/miri/tests/fail/stacked_borrows/alias_through_mutation.stderr2
-rw-r--r--src/tools/miri/tests/fail/stacked_borrows/aliasing_mut1.stderr2
-rw-r--r--src/tools/miri/tests/fail/stacked_borrows/aliasing_mut2.stderr2
-rw-r--r--src/tools/miri/tests/fail/stacked_borrows/aliasing_mut3.stderr2
-rw-r--r--src/tools/miri/tests/fail/stacked_borrows/aliasing_mut4.stderr2
-rw-r--r--src/tools/miri/tests/fail/stacked_borrows/box_exclusive_violation1.stderr2
-rw-r--r--src/tools/miri/tests/fail/stacked_borrows/box_noalias_violation.stderr2
-rw-r--r--src/tools/miri/tests/fail/stacked_borrows/buggy_as_mut_slice.stderr2
-rw-r--r--src/tools/miri/tests/fail/stacked_borrows/buggy_split_at_mut.stderr2
-rw-r--r--src/tools/miri/tests/fail/stacked_borrows/disable_mut_does_not_merge_srw.stderr2
-rw-r--r--src/tools/miri/tests/fail/stacked_borrows/drop_in_place_protector.rs27
-rw-r--r--src/tools/miri/tests/fail/stacked_borrows/drop_in_place_protector.stderr33
-rw-r--r--src/tools/miri/tests/fail/stacked_borrows/drop_in_place_retag.rs12
-rw-r--r--src/tools/miri/tests/fail/stacked_borrows/drop_in_place_retag.stderr29
-rw-r--r--src/tools/miri/tests/fail/stacked_borrows/fnentry_invalidation.stderr2
-rw-r--r--src/tools/miri/tests/fail/stacked_borrows/fnentry_invalidation2.stderr2
-rw-r--r--src/tools/miri/tests/fail/stacked_borrows/illegal_dealloc1.stderr2
-rw-r--r--src/tools/miri/tests/fail/stacked_borrows/illegal_read1.stderr2
-rw-r--r--src/tools/miri/tests/fail/stacked_borrows/illegal_read2.stderr2
-rw-r--r--src/tools/miri/tests/fail/stacked_borrows/illegal_read3.stderr2
-rw-r--r--src/tools/miri/tests/fail/stacked_borrows/illegal_read4.stderr2
-rw-r--r--src/tools/miri/tests/fail/stacked_borrows/illegal_read5.stderr2
-rw-r--r--src/tools/miri/tests/fail/stacked_borrows/illegal_read6.stderr2
-rw-r--r--src/tools/miri/tests/fail/stacked_borrows/illegal_read7.stderr2
-rw-r--r--src/tools/miri/tests/fail/stacked_borrows/illegal_read8.stderr2
-rw-r--r--src/tools/miri/tests/fail/stacked_borrows/illegal_read_despite_exposed1.stderr2
-rw-r--r--src/tools/miri/tests/fail/stacked_borrows/illegal_read_despite_exposed2.stderr2
-rw-r--r--src/tools/miri/tests/fail/stacked_borrows/illegal_write1.stderr2
-rw-r--r--src/tools/miri/tests/fail/stacked_borrows/illegal_write2.stderr2
-rw-r--r--src/tools/miri/tests/fail/stacked_borrows/illegal_write3.stderr2
-rw-r--r--src/tools/miri/tests/fail/stacked_borrows/illegal_write4.stderr2
-rw-r--r--src/tools/miri/tests/fail/stacked_borrows/illegal_write5.stderr2
-rw-r--r--src/tools/miri/tests/fail/stacked_borrows/illegal_write6.stderr2
-rw-r--r--src/tools/miri/tests/fail/stacked_borrows/illegal_write_despite_exposed1.stderr2
-rw-r--r--src/tools/miri/tests/fail/stacked_borrows/interior_mut1.stderr2
-rw-r--r--src/tools/miri/tests/fail/stacked_borrows/interior_mut2.stderr2
-rw-r--r--src/tools/miri/tests/fail/stacked_borrows/invalidate_against_protector1.stderr2
-rw-r--r--src/tools/miri/tests/fail/stacked_borrows/invalidate_against_protector2.stderr2
-rw-r--r--src/tools/miri/tests/fail/stacked_borrows/invalidate_against_protector3.stderr2
-rw-r--r--src/tools/miri/tests/fail/stacked_borrows/load_invalid_mut.stderr2
-rw-r--r--src/tools/miri/tests/fail/stacked_borrows/load_invalid_shr.stderr2
-rw-r--r--src/tools/miri/tests/fail/stacked_borrows/mut_exclusive_violation1.stderr2
-rw-r--r--src/tools/miri/tests/fail/stacked_borrows/mut_exclusive_violation2.stderr2
-rw-r--r--src/tools/miri/tests/fail/stacked_borrows/newtype_pair_retagging.stderr2
-rw-r--r--src/tools/miri/tests/fail/stacked_borrows/newtype_retagging.stderr2
-rw-r--r--src/tools/miri/tests/fail/stacked_borrows/outdated_local.stderr2
-rw-r--r--src/tools/miri/tests/fail/stacked_borrows/pass_invalid_mut.stderr2
-rw-r--r--src/tools/miri/tests/fail/stacked_borrows/pass_invalid_shr.stderr2
-rw-r--r--src/tools/miri/tests/fail/stacked_borrows/pointer_smuggling.stderr2
-rw-r--r--src/tools/miri/tests/fail/stacked_borrows/raw_tracking.stderr2
-rw-r--r--src/tools/miri/tests/fail/stacked_borrows/retag_data_race_read.rs2
-rw-r--r--src/tools/miri/tests/fail/stacked_borrows/retag_data_race_read.stderr11
-rw-r--r--src/tools/miri/tests/fail/stacked_borrows/retag_data_race_write.rs2
-rw-r--r--src/tools/miri/tests/fail/stacked_borrows/retag_data_race_write.stderr11
-rw-r--r--src/tools/miri/tests/fail/stacked_borrows/return_invalid_mut.stderr2
-rw-r--r--src/tools/miri/tests/fail/stacked_borrows/return_invalid_mut_option.stderr2
-rw-r--r--src/tools/miri/tests/fail/stacked_borrows/return_invalid_mut_tuple.stderr2
-rw-r--r--src/tools/miri/tests/fail/stacked_borrows/return_invalid_shr.stderr2
-rw-r--r--src/tools/miri/tests/fail/stacked_borrows/return_invalid_shr_option.stderr2
-rw-r--r--src/tools/miri/tests/fail/stacked_borrows/return_invalid_shr_tuple.stderr2
-rw-r--r--src/tools/miri/tests/fail/stacked_borrows/shared_rw_borrows_are_weak1.stderr2
-rw-r--r--src/tools/miri/tests/fail/stacked_borrows/shared_rw_borrows_are_weak2.stderr2
-rw-r--r--src/tools/miri/tests/fail/stacked_borrows/shr_frozen_violation1.stderr2
-rw-r--r--src/tools/miri/tests/fail/stacked_borrows/track_caller.stderr2
-rw-r--r--src/tools/miri/tests/fail/stacked_borrows/transmute-is-no-escape.stderr2
-rw-r--r--src/tools/miri/tests/fail/stacked_borrows/unescaped_static.stderr2
-rw-r--r--src/tools/miri/tests/fail/stacked_borrows/zst_slice.stderr2
-rw-r--r--src/tools/miri/tests/fail/unaligned_pointers/drop_in_place.rs25
-rw-r--r--src/tools/miri/tests/fail/unaligned_pointers/drop_in_place.stderr20
-rw-r--r--src/tools/miri/tests/pass-dep/page_size.rs13
-rw-r--r--src/tools/miri/tests/pass-dep/page_size_override.rs7
-rw-r--r--src/tools/miri/tests/pass-dep/shims/libc-fs.rs63
-rw-r--r--src/tools/miri/tests/pass-dep/shims/libc-misc.rs26
-rw-r--r--src/tools/miri/tests/pass-dep/tokio_mvp.rs6
-rw-r--r--src/tools/miri/tests/pass/provenance.rs7
-rw-r--r--src/tools/miri/tests/pass/shims/env/current_dir.rs3
-rw-r--r--src/tools/miri/tests/pass/shims/fs.rs42
-rw-r--r--src/tools/miri/tests/pass/vec.rs32
-rw-r--r--src/tools/remote-test-server/src/main.rs20
-rw-r--r--src/tools/tidy/src/error_codes_check.rs4
-rw-r--r--src/tools/tidy/src/ui_tests.rs2
-rw-r--r--triagebot.toml4
724 files changed, 10056 insertions, 3985 deletions
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 2b6e96b467e..23d3e71424b 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -41,16 +41,24 @@ jobs:
       TOOLSTATE_REPO: "https://github.com/rust-lang-nursery/rust-toolstate"
       CACHE_DOMAIN: ci-caches.rust-lang.org
     if: "github.event_name == 'pull_request'"
+    continue-on-error: "${{ matrix.tidy }}"
     strategy:
       matrix:
         include:
           - name: mingw-check
+            tidy: false
+            os: ubuntu-20.04-xl
+            env: {}
+          - name: mingw-check-tidy
+            tidy: true
             os: ubuntu-20.04-xl
             env: {}
           - name: x86_64-gnu-llvm-13
+            tidy: false
             os: ubuntu-20.04-xl
             env: {}
           - name: x86_64-gnu-tools
+            tidy: false
             env:
               CI_ONLY_WHEN_SUBMODULES_CHANGED: 1
             os: ubuntu-20.04-xl
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 223fd0065bf..d732075fb2d 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -8,9 +8,9 @@ members](https://rust-lang.zulipchat.com/#narrow/stream/122652-new-members)
 Zulip stream. We have lots of docs below of how to get started on your own, but
 the Zulip stream is the best place to *ask* for help.
 
-Documentation for contributing to Rust is located in the [Guide to Rustc Development](https://rustc-dev-guide.rust-lang.org/),
-commonly known as the [rustc-dev-guide]. Despite the name, this guide documents
-not just how to develop rustc (the Rust compiler), but also how to contribute to the standard library and rustdoc.
+Documentation for contributing to the compiler or tooling is located in the [Guide to Rustc
+Development][rustc-dev-guide], commonly known as the [rustc-dev-guide]. Documentation for the
+standard library in the [Standard library developers Guide][std-dev-guide], commonly known as the [std-dev-guide].
 
 ## About the [rustc-dev-guide]
 
@@ -35,6 +35,7 @@ refer to [this section][contributing-bug-reports] and [open an issue][issue temp
 
 [Contributing to Rust]: https://rustc-dev-guide.rust-lang.org/contributing.html#contributing-to-rust
 [rustc-dev-guide]: https://rustc-dev-guide.rust-lang.org/
+[std-dev-guide]: https://std-dev-guide.rust-lang.org/
 [contributing-bug-reports]: https://rustc-dev-guide.rust-lang.org/contributing.html#bug-reports
 [issue template]: https://github.com/rust-lang/rust/issues/new/choose
 [internals]: https://internals.rust-lang.org
diff --git a/Cargo.lock b/Cargo.lock
index 1d9a9240ccf..97148641670 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -30,7 +30,7 @@ version = "0.7.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "43bb833f0bf979d8475d38fbf09ed3b8a55e1885fe93ad3f93239fc6a4f17b98"
 dependencies = [
- "getrandom 0.2.0",
+ "getrandom 0.2.8",
  "once_cell",
  "version_check",
 ]
@@ -79,6 +79,15 @@ dependencies = [
 
 [[package]]
 name = "ansi_term"
+version = "0.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
+dependencies = [
+ "winapi",
+]
+
+[[package]]
+name = "ansi_term"
 version = "0.12.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2"
@@ -181,7 +190,7 @@ checksum = "cab84319d616cfb654d03394f38ab7e6f0919e181b1b57e1fd15e7fb4077d9a7"
 dependencies = [
  "addr2line",
  "cc",
- "cfg-if 1.0.0",
+ "cfg-if",
  "libc",
  "miniz_oxide",
  "object",
@@ -504,12 +513,6 @@ dependencies = [
 
 [[package]]
 name = "cfg-if"
-version = "0.1.10"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
-
-[[package]]
-name = "cfg-if"
 version = "1.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
@@ -707,7 +710,7 @@ dependencies = [
  "declare_clippy_lint",
  "if_chain",
  "itertools",
- "pulldown-cmark",
+ "pulldown-cmark 0.9.2",
  "quine-mc_cluskey",
  "regex-syntax",
  "rustc-semver",
@@ -951,7 +954,7 @@ version = "1.3.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d"
 dependencies = [
- "cfg-if 1.0.0",
+ "cfg-if",
 ]
 
 [[package]]
@@ -960,7 +963,7 @@ version = "0.5.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "c2dd04ddaf88237dc3b8d8f9a3c1004b506b54b3313403944054d23c0870c521"
 dependencies = [
- "cfg-if 1.0.0",
+ "cfg-if",
  "crossbeam-utils",
 ]
 
@@ -970,7 +973,7 @@ version = "0.8.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "715e8152b692bba2d374b53d4875445368fdf21a94751410af607a5ac677d1fc"
 dependencies = [
- "cfg-if 1.0.0",
+ "cfg-if",
  "crossbeam-epoch",
  "crossbeam-utils",
 ]
@@ -982,7 +985,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "01a9af1f4c2ef74bb8aa1f7e19706bc72d03598c8a570bb5de72243c7a9d9d5a"
 dependencies = [
  "autocfg",
- "cfg-if 1.0.0",
+ "cfg-if",
  "crossbeam-utils",
  "memoffset",
  "scopeguard",
@@ -994,7 +997,7 @@ version = "0.8.14"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "4fb766fa798726286dbbb842f174001dab8abc7b627a1dd86e0b7222a95d929f"
 dependencies = [
- "cfg-if 1.0.0",
+ "cfg-if",
 ]
 
 [[package]]
@@ -1029,6 +1032,16 @@ dependencies = [
 ]
 
 [[package]]
+name = "ctor"
+version = "0.1.26"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6d2301688392eb071b0bf1a37be05c469d3cc4dbbd95df672fe28ab021e6a096"
+dependencies = [
+ "quote",
+ "syn",
+]
+
+[[package]]
 name = "curl"
 version = "0.4.44"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1105,6 +1118,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8"
 
 [[package]]
+name = "difference"
+version = "2.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198"
+
+[[package]]
 name = "digest"
 version = "0.10.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1138,7 +1157,7 @@ version = "2.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1"
 dependencies = [
- "cfg-if 1.0.0",
+ "cfg-if",
  "dirs-sys-next",
 ]
 
@@ -1341,7 +1360,7 @@ version = "0.2.14"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "1d34cfa13a63ae058bfa601fe9e313bbdb3746427c1459185464ce0fcf62e1e8"
 dependencies = [
- "cfg-if 1.0.0",
+ "cfg-if",
  "libc",
  "redox_syscall",
  "winapi",
@@ -1359,7 +1378,7 @@ version = "1.0.23"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "b39522e96686d38f4bc984b9198e3a0613264abaebaff2c5c918bfa6b6da09af"
 dependencies = [
- "cfg-if 1.0.0",
+ "cfg-if",
  "crc32fast",
  "libc",
  "libz-sys",
@@ -1598,20 +1617,20 @@ version = "0.1.16"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce"
 dependencies = [
- "cfg-if 1.0.0",
+ "cfg-if",
  "libc",
  "wasi 0.9.0+wasi-snapshot-preview1",
 ]
 
 [[package]]
 name = "getrandom"
-version = "0.2.0"
+version = "0.2.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ee8025cf36f917e6a52cce185b7c7177689b838b7ec138364e50cc2277a56cf4"
+checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31"
 dependencies = [
- "cfg-if 0.1.10",
+ "cfg-if",
  "libc",
- "wasi 0.9.0+wasi-snapshot-preview1",
+ "wasi 0.11.0+wasi-snapshot-preview1",
 ]
 
 [[package]]
@@ -1685,6 +1704,21 @@ dependencies = [
 
 [[package]]
 name = "handlebars"
+version = "3.5.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4498fc115fa7d34de968184e473529abb40eeb6be8bc5f7faba3d08c316cb3e3"
+dependencies = [
+ "log",
+ "pest",
+ "pest_derive",
+ "quick-error 2.0.1",
+ "serde",
+ "serde_json",
+ "walkdir",
+]
+
+[[package]]
+name = "handlebars"
 version = "4.3.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "360d9740069b2f6cbb63ce2dbaa71a20d3185350cbb990d7bebeb9318415eb17"
@@ -1794,7 +1828,7 @@ version = "1.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f"
 dependencies = [
- "quick-error",
+ "quick-error 1.2.3",
 ]
 
 [[package]]
@@ -1966,7 +2000,7 @@ version = "0.1.12"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c"
 dependencies = [
- "cfg-if 1.0.0",
+ "cfg-if",
 ]
 
 [[package]]
@@ -1990,9 +2024,9 @@ dependencies = [
 
 [[package]]
 name = "io-lifetimes"
-version = "1.0.2"
+version = "1.0.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e394faa0efb47f9f227f1cd89978f854542b318a6f64fa695489c9c993056656"
+checksum = "46112a93252b123d31a119a8d1a1ac19deac4fac6e0e8b0df58f0d4e5870e63c"
 dependencies = [
  "libc",
  "windows-sys",
@@ -2000,9 +2034,9 @@ dependencies = [
 
 [[package]]
 name = "is-terminal"
-version = "0.4.0"
+version = "0.4.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "aae5bc6e2eb41c9def29a3e0f1306382807764b9b53112030eff57435667352d"
+checksum = "28dfb6c8100ccc63462345b67d1bbc3679177c75ee4bf59bf29c8b1d110b8189"
 dependencies = [
  "hermit-abi 0.2.6",
  "io-lifetimes",
@@ -2150,7 +2184,7 @@ version = "0.7.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "c0cf036d15402bea3c5d4de17b3fce76b3e4a56ebc1f577be0e7a72f7c607cf0"
 dependencies = [
- "cfg-if 1.0.0",
+ "cfg-if",
  "winapi",
 ]
 
@@ -2221,9 +2255,9 @@ dependencies = [
 
 [[package]]
 name = "linux-raw-sys"
-version = "0.1.3"
+version = "0.1.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8f9f08d8963a6c613f4b1a78f4f4a4dbfadf8e6545b2d72861731e4858b8b47f"
+checksum = "f051f77a7c8e6957c0696eac88f26b0117e54f52d3fc682ab19397a8812846a4"
 
 [[package]]
 name = "litemap"
@@ -2251,7 +2285,7 @@ version = "0.4.14"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710"
 dependencies = [
- "cfg-if 1.0.0",
+ "cfg-if",
 ]
 
 [[package]]
@@ -2328,12 +2362,12 @@ dependencies = [
  "clap_complete",
  "elasticlunr-rs",
  "env_logger 0.9.0",
- "handlebars",
+ "handlebars 4.3.3",
  "lazy_static",
  "log",
  "memchr",
  "opener",
- "pulldown-cmark",
+ "pulldown-cmark 0.9.2",
  "regex",
  "serde",
  "serde_json",
@@ -2344,6 +2378,19 @@ dependencies = [
 ]
 
 [[package]]
+name = "mdman"
+version = "0.1.0"
+dependencies = [
+ "anyhow",
+ "handlebars 3.5.5",
+ "pretty_assertions",
+ "pulldown-cmark 0.7.2",
+ "same-file",
+ "serde_json",
+ "url",
+]
+
+[[package]]
 name = "measureme"
 version = "10.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2433,7 +2480,7 @@ version = "0.1.0"
 dependencies = [
  "colored",
  "env_logger 0.9.0",
- "getrandom 0.2.0",
+ "getrandom 0.2.8",
  "lazy_static",
  "libc",
  "libffi",
@@ -2529,7 +2576,7 @@ version = "0.3.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "5a518809ac14b25b569624d0268eba1e88498f71615893dca57982bed7621abb"
 dependencies = [
- "cfg-if 1.0.0",
+ "cfg-if",
 ]
 
 [[package]]
@@ -2555,7 +2602,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "0c7ae222234c30df141154f159066c5093ff73b63204dcda7121eb082fc56a95"
 dependencies = [
  "bitflags",
- "cfg-if 1.0.0",
+ "cfg-if",
  "foreign-types",
  "libc",
  "once_cell",
@@ -2618,6 +2665,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "8e22443d1643a904602595ba1cd8f7d896afe56d26712531c5ff73a15b2fbf64"
 
 [[package]]
+name = "output_vt100"
+version = "0.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "628223faebab4e3e40667ee0b2336d34a5b960ff60ea743ddfdbcf7770bcfb66"
+dependencies = [
+ "winapi",
+]
+
+[[package]]
 name = "owo-colors"
 version = "3.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2625,11 +2681,11 @@ checksum = "decf7381921fea4dcb2549c5667eda59b3ec297ab7e2b5fc33eac69d2e7da87b"
 
 [[package]]
 name = "packed_simd_2"
-version = "0.3.4"
+version = "0.3.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3278e0492f961fd4ae70909f56b2723a7e8d01a228427294e19cdfdebda89a17"
+checksum = "a1914cd452d8fccd6f9db48147b29fd4ae05bea9dc5d9ad578509f72415de282"
 dependencies = [
- "cfg-if 0.1.10",
+ "cfg-if",
  "libm",
 ]
 
@@ -2638,7 +2694,7 @@ name = "panic_abort"
 version = "0.0.0"
 dependencies = [
  "alloc",
- "cfg-if 1.0.0",
+ "cfg-if",
  "compiler_builtins",
  "core",
  "libc",
@@ -2649,7 +2705,7 @@ name = "panic_unwind"
 version = "0.0.0"
 dependencies = [
  "alloc",
- "cfg-if 1.0.0",
+ "cfg-if",
  "compiler_builtins",
  "core",
  "libc",
@@ -2683,7 +2739,7 @@ version = "0.8.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "d76e8e1493bcac0d2766c42737f34458f1c8c50c0d23bcb24ea953affb273216"
 dependencies = [
- "cfg-if 1.0.0",
+ "cfg-if",
  "instant",
  "libc",
  "redox_syscall",
@@ -2697,7 +2753,7 @@ version = "0.9.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "4dc9e0dc2adc1c69d09143aff38d3d30c5c3f0df0dad82e6d25547af174ebec0"
 dependencies = [
- "cfg-if 1.0.0",
+ "cfg-if",
  "libc",
  "redox_syscall",
  "smallvec",
@@ -2859,6 +2915,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c"
 
 [[package]]
+name = "pretty_assertions"
+version = "0.6.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3f81e1644e1b54f5a68959a29aa86cde704219254669da328ecfdf6a1f09d427"
+dependencies = [
+ "ansi_term 0.11.0",
+ "ctor",
+ "difference",
+ "output_vt100",
+]
+
+[[package]]
 name = "pretty_env_logger"
 version = "0.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2935,6 +3003,17 @@ dependencies = [
 
 [[package]]
 name = "pulldown-cmark"
+version = "0.7.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ca36dea94d187597e104a5c8e4b07576a8a45aa5db48a65e12940d3eb7461f55"
+dependencies = [
+ "bitflags",
+ "memchr",
+ "unicase",
+]
+
+[[package]]
+name = "pulldown-cmark"
 version = "0.9.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "2d9cc634bc78768157b5cbfe988ffcd1dcba95cd2b2f03a88316c08c6d00ed63"
@@ -2957,6 +3036,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0"
 
 [[package]]
+name = "quick-error"
+version = "2.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3"
+
+[[package]]
 name = "quine-mc_cluskey"
 version = "0.2.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -3030,7 +3115,7 @@ version = "0.6.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "34cf66eb183df1c5876e2dcf6b13d57340741e8dc255b48e40a26de954d06ae7"
 dependencies = [
- "getrandom 0.2.0",
+ "getrandom 0.2.8",
 ]
 
 [[package]]
@@ -3099,7 +3184,7 @@ version = "0.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "528532f3d801c87aec9def2add9ca802fe569e44a544afe633765267840abe64"
 dependencies = [
- "getrandom 0.2.0",
+ "getrandom 0.2.8",
  "redox_syscall",
 ]
 
@@ -3590,7 +3675,7 @@ version = "0.0.0"
 dependencies = [
  "arrayvec",
  "bitflags",
- "cfg-if 0.1.10",
+ "cfg-if",
  "ena",
  "indexmap",
  "jobserver",
@@ -4038,6 +4123,7 @@ dependencies = [
  "rustc_ast",
  "rustc_attr",
  "rustc_data_structures",
+ "rustc_error_messages",
  "rustc_errors",
  "rustc_feature",
  "rustc_graphviz",
@@ -4374,7 +4460,7 @@ dependencies = [
 name = "rustc_span"
 version = "0.0.0"
 dependencies = [
- "cfg-if 0.1.10",
+ "cfg-if",
  "md-5",
  "rustc_arena",
  "rustc_data_structures",
@@ -4545,7 +4631,7 @@ dependencies = [
  "itertools",
  "minifier",
  "once_cell",
- "pulldown-cmark",
+ "pulldown-cmark 0.9.2",
  "rayon",
  "regex",
  "rustdoc-json-types",
@@ -4783,7 +4869,7 @@ version = "0.10.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "028f48d513f9678cda28f6e4064755b3fbb2af6acd672f2c209b62323f7aea0f"
 dependencies = [
- "cfg-if 1.0.0",
+ "cfg-if",
  "cpufeatures",
  "digest",
 ]
@@ -4794,7 +4880,7 @@ version = "0.10.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "99c3bd8169c58782adad9290a9af5939994036b76187f7b4f0e6de91dbbfc0ec"
 dependencies = [
- "cfg-if 1.0.0",
+ "cfg-if",
  "cpufeatures",
  "digest",
 ]
@@ -4936,7 +5022,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "c886bd4480155fd3ef527d45e9ac8dd7118a898a46530b7b94c3e21866259fce"
 dependencies = [
  "cc",
- "cfg-if 1.0.0",
+ "cfg-if",
  "libc",
  "psm",
  "winapi",
@@ -4954,7 +5040,7 @@ version = "0.0.0"
 dependencies = [
  "addr2line",
  "alloc",
- "cfg-if 1.0.0",
+ "cfg-if",
  "compiler_builtins",
  "core",
  "dlmalloc",
@@ -4978,7 +5064,7 @@ dependencies = [
 name = "std_detect"
 version = "0.1.5"
 dependencies = [
- "cfg-if 1.0.0",
+ "cfg-if",
  "compiler_builtins",
  "libc",
  "rustc-std-workspace-alloc",
@@ -5085,7 +5171,7 @@ version = "3.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "5cdb1ef4eaeeaddc8fbd371e5017057064af0911902ef36b39801f67cc6d79e4"
 dependencies = [
- "cfg-if 1.0.0",
+ "cfg-if",
  "fastrand",
  "libc",
  "redox_syscall",
@@ -5138,7 +5224,7 @@ dependencies = [
 name = "test"
 version = "0.0.0"
 dependencies = [
- "cfg-if 1.0.0",
+ "cfg-if",
  "core",
  "getopts",
  "libc",
@@ -5154,7 +5240,7 @@ version = "0.9.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "0639d10d8f4615f223a57275cf40f9bdb7cfbb806bcb7f7cc56e3beb55a576eb"
 dependencies = [
- "cfg-if 1.0.0",
+ "cfg-if",
  "getopts",
  "libc",
  "num_cpus",
@@ -5321,7 +5407,7 @@ version = "0.1.35"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "a400e31aa60b9d44a52a8ee0343b5b18566b03a8321e0d321f695cf56e940160"
 dependencies = [
- "cfg-if 1.0.0",
+ "cfg-if",
  "pin-project-lite",
  "tracing-attributes",
  "tracing-core",
@@ -5375,7 +5461,7 @@ version = "0.3.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "245da694cc7fc4729f3f418b304cb57789f1bed2a78c575407ab8a23f53cb4d3"
 dependencies = [
- "ansi_term",
+ "ansi_term 0.12.1",
  "lazy_static",
  "matchers",
  "parking_lot 0.11.2",
@@ -5394,7 +5480,7 @@ version = "0.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "3ce989c9962c7f61fe084dd4a230eec784649dfc2392467c790007c3a6e134e7"
 dependencies = [
- "ansi_term",
+ "ansi_term 0.12.1",
  "atty",
  "tracing-core",
  "tracing-log",
@@ -5407,7 +5493,7 @@ version = "1.6.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "97fee6b57c6a41524a810daee9286c02d7752c4253064d0b05472833a438f675"
 dependencies = [
- "cfg-if 1.0.0",
+ "cfg-if",
  "rand 0.8.5",
  "static_assertions",
 ]
@@ -5654,7 +5740,7 @@ name = "unwind"
 version = "0.0.0"
 dependencies = [
  "cc",
- "cfg-if 1.0.0",
+ "cfg-if",
  "compiler_builtins",
  "core",
  "libc",
@@ -5691,7 +5777,7 @@ version = "0.8.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7"
 dependencies = [
- "getrandom 0.2.0",
+ "getrandom 0.2.8",
 ]
 
 [[package]]
diff --git a/Cargo.toml b/Cargo.toml
index 000c10a1f90..1cec4a84480 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -25,6 +25,8 @@ members = [
   "src/tools/cargo/crates/credential/cargo-credential-1password",
   "src/tools/cargo/crates/credential/cargo-credential-macos-keychain",
   "src/tools/cargo/crates/credential/cargo-credential-wincred",
+  "src/tools/cargo/crates/mdman",
+  # "src/tools/cargo/crates/resolver-tests",
   "src/tools/rustdoc",
   "src/tools/rls",
   "src/tools/rustfmt",
diff --git a/README.md b/README.md
index 27e7145c5a9..ac39435a8c7 100644
--- a/README.md
+++ b/README.md
@@ -5,12 +5,8 @@ standard library, and documentation.
 
 [Rust]: https://www.rust-lang.org
 
-**Note: this README is for _users_ rather than _contributors_.
-If you wish to _contribute_ to the compiler, you should read the
-[Getting Started][gettingstarted] section of the rustc-dev-guide instead.
-You can ask for help in the [#new members Zulip stream][new-members].**
-
-[new-members]: https://rust-lang.zulipchat.com/#narrow/stream/122652-new-members
+**Note: this README is for _users_ rather than _contributors_.**
+If you wish to _contribute_ to the compiler, you should read [CONTRIBUTING.md](CONTRIBUTING.md) instead.
 
 ## Quick Start
 
@@ -24,22 +20,23 @@ Read ["Installation"] from [The Book].
 The Rust build system uses a Python script called `x.py` to build the compiler,
 which manages the bootstrapping process. It lives at the root of the project.
 
-The `x.py` command can be run directly on most systems in the following format:
+The `x.py` command can be run directly on most Unix systems in the following format:
 
 ```sh
 ./x.py <subcommand> [flags]
 ```
 
-This is how the documentation and examples assume you are running `x.py`.
-
-Systems such as Ubuntu 20.04 LTS do not create the necessary `python` command by default when Python is installed that allows `x.py` to be run directly. In that case, you can either create a symlink for `python` (Ubuntu provides the `python-is-python3` package for this), or run `x.py` using Python itself:
+This is how the documentation and examples assume you are running `x.py`. Some alternative ways are:
 
 ```sh
-# Python 3
-python3 x.py <subcommand> [flags]
+# On a Unix shell if you don't have the necessary `python3` command
+./x <subcommand> [flags]
 
-# Python 2.7
-python2.7 x.py <subcommand> [flags]
+# On the Windows Command Prompt (if .py files are configured to run Python)
+x.py <subcommand> [flags]
+
+# You can also run Python yourself, e.g.:
+python x.py <subcommand> [flags]
 ```
 
 More information about `x.py` can be found
@@ -48,20 +45,37 @@ by running it with the `--help` flag or reading the [rustc dev guide][rustcguide
 [gettingstarted]: https://rustc-dev-guide.rust-lang.org/getting-started.html
 [rustcguidebuild]: https://rustc-dev-guide.rust-lang.org/building/how-to-build-and-run.html
 
-### Building on a Unix-like system
-1. Make sure you have installed the dependencies:
+### Dependencies
+
+Make sure you have installed the dependencies:
 
-   * `g++` 5.1 or later or `clang++` 3.5 or later
    * `python` 3 or 2.7
-   * GNU `make` 3.81 or later
-   * `cmake` 3.13.4 or later
-   * `ninja`
-   * `curl`
    * `git`
-   * `ssl` which comes in `libssl-dev` or `openssl-devel`
+   * A C compiler (when building for the host, `cc` is enough; cross-compiling may need additional compilers)
+   * `curl` (not needed on Windows)
    * `pkg-config` if you are compiling on Linux and targeting Linux
+   * `libiconv` (already included with glibc on Debian-based distros)
+
+To build cargo, you'll also need OpenSSL (`libssl-dev` or `openssl-devel` on most Unix distros).
+
+If building LLVM from source, you'll need additional tools:
+
+* `g++`, `clang++`, or MSVC with versions listed on
+  [LLVM's documentation](https://llvm.org/docs/GettingStarted.html#host-c-toolchain-both-compiler-and-standard-library)
+* `ninja`, or GNU `make` 3.81 or later (ninja is recommended, especially on Windows)
+* `cmake` 3.13.4 or later
+* `libstdc++-static` may be required on some Linux distributions such as Fedora and Ubuntu
+
+On tier 1 or tier 2 with host tools platforms, you can also choose to download LLVM by setting `llvm.download-ci-llvm = true`.
+Otherwise, you'll need LLVM installed and `llvm-config` in your path.
+See [the rustc-dev-guide for more info][sysllvm].
+
+[sysllvm]: https://rustc-dev-guide.rust-lang.org/building/new-target.html#using-pre-built-llvm
+
+
+### Building on a Unix-like system
 
-2. Clone the [source] with `git`:
+1. Clone the [source] with `git`:
 
    ```sh
    git clone https://github.com/rust-lang/rust.git
@@ -70,22 +84,21 @@ by running it with the `--help` flag or reading the [rustc dev guide][rustcguide
 
 [source]: https://github.com/rust-lang/rust
 
-3. Configure the build settings:
+2. Configure the build settings:
 
     The Rust build system uses a file named `config.toml` in the root of the
     source tree to determine various configuration settings for the build.
-    Copy the default `config.toml.example` to `config.toml` to get started.
+    Set up the defaults intended for distros to get started. You can see a full list of options
+    in `config.toml.example`.
 
     ```sh
-    cp config.toml.example config.toml
+    printf 'profile = "user" \nchangelog-seen = 2 \n' > config.toml
     ```
 
     If you plan to use `x.py install` to create an installation, it is recommended
     that you set the `prefix` value in the `[install]` section to a directory.
 
-    Create an install directory if you are not installing in the default directory.
-
-4. Build and install:
+3. Build and install:
 
     ```sh
     ./x.py build && ./x.py install
@@ -93,15 +106,27 @@ by running it with the `--help` flag or reading the [rustc dev guide][rustcguide
 
     When complete, `./x.py install` will place several programs into
     `$PREFIX/bin`: `rustc`, the Rust compiler, and `rustdoc`, the
-    API-documentation tool. This install does not include [Cargo],
-    Rust's package manager. To build and install Cargo, you may
-    run `./x.py install cargo` or set the `build.extended` key in
-    `config.toml` to `true` to build and install all tools.
+    API-documentation tool. If you've set `profile = "user"` or `build.extended = true`, it will
+    also include [Cargo], Rust's package manager.
 
 [Cargo]: https://github.com/rust-lang/cargo
 
 ### Building on Windows
 
+On Windows, we suggest using [winget] to install dependencies by running the following in a terminal:
+
+```powershell
+winget install -e Python.Python.3
+winget install -e Kitware.CMake
+winget install -e Git.Git
+```
+
+Then edit your system's `PATH` variable and add: `C:\Program Files\CMake\bin`. See
+[this guide on editing the system `PATH`](https://www.java.com/en/download/help/path.html) from the
+Java documentation.
+
+[winget]: https://github.com/microsoft/winget-cli
+
 There are two prominent ABIs in use on Windows: the native (MSVC) ABI used by
 Visual Studio and the GNU ABI used by the GCC toolchain. Which version of Rust
 you need depends largely on what C/C++ libraries you want to interoperate with.
@@ -190,7 +215,7 @@ Windows build triples are:
     - `x86_64-pc-windows-msvc`
 
 The build triple can be specified by either specifying `--build=<triple>` when
-invoking `x.py` commands, or by copying the `config.toml` file (as described
+invoking `x.py` commands, or by creating a `config.toml` file (as described
 in [Installing From Source](#installing-from-source)), and modifying the
 `build` option under the `[build]` section.
 
@@ -204,9 +229,7 @@ configure script and makefile (the latter of which just invokes `x.py`).
 make && sudo make install
 ```
 
-When using the configure script, the generated `config.mk` file may override the
-`config.toml` file. To go back to the `config.toml` file, delete the generated
-`config.mk` file.
+`configure` generates a `config.toml` which can also be used with normal `x.py` invocations.
 
 ## Building Documentation
 
@@ -227,41 +250,20 @@ precompiled "snapshot" version of itself (made in an earlier stage of
 development). As such, source builds require an Internet connection to
 fetch snapshots, and an OS that can execute the available snapshot binaries.
 
-Snapshot binaries are currently built and tested on several platforms:
-
-| Platform / Architecture                     | x86 | x86_64 |
-|---------------------------------------------|-----|--------|
-| Windows (7, 8, 10, ...)                     | ✓   | ✓      |
-| Linux (kernel 3.2, glibc 2.17 or later)     | ✓   | ✓      |
-| macOS (10.7 Lion or later)                  | (\*) | ✓      |
-
-(\*): Apple dropped support for running 32-bit binaries starting from macOS 10.15 and iOS 11.
-Due to this decision from Apple, the targets are no longer useful to our users.
-Please read [our blog post][macx32] for more info.
-
-[macx32]: https://blog.rust-lang.org/2020/01/03/reducing-support-for-32-bit-apple-targets.html
+See https://doc.rust-lang.org/nightly/rustc/platform-support.html for a list of supported platforms.
+Only "host tools" platforms have a pre-compiled snapshot binary available; to compile for a platform
+without host tools you must cross-compile.
 
 You may find that other platforms work, but these are our officially
 supported build environments that are most likely to work.
 
 ## Getting Help
 
-The Rust community congregates in a few places:
-
-* [Stack Overflow] - Direct questions about using the language.
-* [users.rust-lang.org] - General discussion and broader questions.
-* [/r/rust] - News and general discussion.
-
-[Stack Overflow]: https://stackoverflow.com/questions/tagged/rust
-[/r/rust]: https://reddit.com/r/rust
-[users.rust-lang.org]: https://users.rust-lang.org/
+See https://www.rust-lang.org/community for a list of chat platforms and forums.
 
 ## Contributing
 
-If you are interested in contributing to the Rust project, please take a look
-at the [Getting Started][gettingstarted] guide in the [rustc-dev-guide].
-
-[rustc-dev-guide]: https://rustc-dev-guide.rust-lang.org
+See [CONTRIBUTING.md](CONTRIBUTING.md).
 
 ## License
 
diff --git a/compiler/rustc_ast/src/token.rs b/compiler/rustc_ast/src/token.rs
index 7b8c0d79a17..5b6cf30fa96 100644
--- a/compiler/rustc_ast/src/token.rs
+++ b/compiler/rustc_ast/src/token.rs
@@ -379,6 +379,10 @@ impl Token {
         }
     }
 
+    pub fn is_range_separator(&self) -> bool {
+        [DotDot, DotDotDot, DotDotEq].contains(&self.kind)
+    }
+
     pub fn is_op(&self) -> bool {
         match self.kind {
             Eq | Lt | Le | EqEq | Ne | Ge | Gt | AndAnd | OrOr | Not | Tilde | BinOp(_)
diff --git a/compiler/rustc_ast/src/util/comments.rs b/compiler/rustc_ast/src/util/comments.rs
index 35454c3a670..275ed02c2b9 100644
--- a/compiler/rustc_ast/src/util/comments.rs
+++ b/compiler/rustc_ast/src/util/comments.rs
@@ -51,7 +51,7 @@ pub fn beautify_doc_string(data: Symbol, kind: CommentKind) -> Symbol {
         if i != 0 || j != lines.len() { Some((i, j)) } else { None }
     }
 
-    fn get_horizontal_trim<'a>(lines: &'a [&str], kind: CommentKind) -> Option<String> {
+    fn get_horizontal_trim(lines: &[&str], kind: CommentKind) -> Option<String> {
         let mut i = usize::MAX;
         let mut first = true;
 
diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs
index a3f5c18f2e7..3634e6e47ce 100644
--- a/compiler/rustc_ast_lowering/src/expr.rs
+++ b/compiler/rustc_ast_lowering/src/expr.rs
@@ -656,18 +656,14 @@ impl<'hir> LoweringContext<'_, 'hir> {
             hir::ExprKind::Closure(c)
         };
 
-        let track_caller = self
-            .attrs
-            .get(&outer_hir_id.local_id)
-            .map_or(false, |attrs| attrs.into_iter().any(|attr| attr.has_name(sym::track_caller)));
-
         let hir_id = self.lower_node_id(closure_node_id);
-        if track_caller {
-            let unstable_span = self.mark_span_with_reason(
-                DesugaringKind::Async,
-                span,
-                self.allow_gen_future.clone(),
-            );
+        let unstable_span =
+            self.mark_span_with_reason(DesugaringKind::Async, span, self.allow_gen_future.clone());
+
+        if self.tcx.features().closure_track_caller
+            && let Some(attrs) = self.attrs.get(&outer_hir_id.local_id)
+            && attrs.into_iter().any(|attr| attr.has_name(sym::track_caller))
+        {
             self.lower_attrs(
                 hir_id,
                 &[Attribute {
diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs
index 9d4c2900eaf..b6b242bfc27 100644
--- a/compiler/rustc_ast_lowering/src/item.rs
+++ b/compiler/rustc_ast_lowering/src/item.rs
@@ -259,8 +259,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
                         body.as_deref(),
                     );
 
-                    let mut itctx = ImplTraitContext::Universal;
-                    let (generics, decl) = this.lower_generics(generics, id, &mut itctx, |this| {
+                    let itctx = ImplTraitContext::Universal;
+                    let (generics, decl) = this.lower_generics(generics, id, &itctx, |this| {
                         let ret_id = asyncness.opt_return_id();
                         this.lower_fn_decl(&decl, id, *fn_sig_span, FnDeclKind::Fn, ret_id)
                     });
@@ -369,9 +369,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
                 // method, it will not be considered an in-band
                 // lifetime to be added, but rather a reference to a
                 // parent lifetime.
-                let mut itctx = ImplTraitContext::Universal;
+                let itctx = ImplTraitContext::Universal;
                 let (generics, (trait_ref, lowered_ty)) =
-                    self.lower_generics(ast_generics, id, &mut itctx, |this| {
+                    self.lower_generics(ast_generics, id, &itctx, |this| {
                         let trait_ref = trait_ref.as_ref().map(|trait_ref| {
                             this.lower_trait_ref(
                                 trait_ref,
@@ -590,9 +590,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
             kind: match &i.kind {
                 ForeignItemKind::Fn(box Fn { sig, generics, .. }) => {
                     let fdec = &sig.decl;
-                    let mut itctx = ImplTraitContext::Universal;
+                    let itctx = ImplTraitContext::Universal;
                     let (generics, (fn_dec, fn_args)) =
-                        self.lower_generics(generics, i.id, &mut itctx, |this| {
+                        self.lower_generics(generics, i.id, &itctx, |this| {
                             (
                                 // Disallow `impl Trait` in foreign items.
                                 this.lower_fn_decl(
@@ -1184,8 +1184,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
         is_async: Option<(NodeId, Span)>,
     ) -> (&'hir hir::Generics<'hir>, hir::FnSig<'hir>) {
         let header = self.lower_fn_header(sig.header);
-        let mut itctx = ImplTraitContext::Universal;
-        let (generics, decl) = self.lower_generics(generics, id, &mut itctx, |this| {
+        let itctx = ImplTraitContext::Universal;
+        let (generics, decl) = self.lower_generics(generics, id, &itctx, |this| {
             this.lower_fn_decl(&sig.decl, id, sig.span, kind, is_async)
         });
         (generics, hir::FnSig { header, decl, span: self.lower_span(sig.span) })
@@ -1316,6 +1316,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
                 param.id,
                 &param.kind,
                 &param.bounds,
+                param.colon_span,
+                generics.span,
                 itctx,
                 PredicateOrigin::GenericParam,
             )
@@ -1365,6 +1367,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
         id: NodeId,
         kind: &GenericParamKind,
         bounds: &[GenericBound],
+        colon_span: Option<Span>,
+        parent_span: Span,
         itctx: &ImplTraitContext,
         origin: PredicateOrigin,
     ) -> Option<hir::WherePredicate<'hir>> {
@@ -1377,21 +1381,17 @@ impl<'hir> LoweringContext<'_, 'hir> {
 
         let ident = self.lower_ident(ident);
         let param_span = ident.span;
-        let span = bounds
-            .iter()
-            .fold(Some(param_span.shrink_to_hi()), |span: Option<Span>, bound| {
-                let bound_span = bound.span();
-                // We include bounds that come from a `#[derive(_)]` but point at the user's code,
-                // as we use this method to get a span appropriate for suggestions.
-                if !bound_span.can_be_used_for_suggestions() {
-                    None
-                } else if let Some(span) = span {
-                    Some(span.to(bound_span))
-                } else {
-                    Some(bound_span)
-                }
-            })
-            .unwrap_or(param_span.shrink_to_hi());
+
+        // Reconstruct the span of the entire predicate from the individual generic bounds.
+        let span_start = colon_span.unwrap_or_else(|| param_span.shrink_to_hi());
+        let span = bounds.iter().fold(span_start, |span_accum, bound| {
+            match bound.span().find_ancestor_inside(parent_span) {
+                Some(bound_span) => span_accum.to(bound_span),
+                None => span_accum,
+            }
+        });
+        let span = self.lower_span(span);
+
         match kind {
             GenericParamKind::Const { .. } => None,
             GenericParamKind::Type { .. } => {
diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs
index 0ef784a4453..1fbc45a58e5 100644
--- a/compiler/rustc_ast_lowering/src/lib.rs
+++ b/compiler/rustc_ast_lowering/src/lib.rs
@@ -414,7 +414,7 @@ fn compute_hir_hash(
     })
 }
 
-pub fn lower_to_hir<'hir>(tcx: TyCtxt<'hir>, (): ()) -> hir::Crate<'hir> {
+pub fn lower_to_hir(tcx: TyCtxt<'_>, (): ()) -> hir::Crate<'_> {
     let sess = tcx.sess;
     let krate = tcx.untracked_crate.steal();
     let mut resolver = tcx.resolver_for_lowering(()).steal();
@@ -1656,9 +1656,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
     // Lowers a function declaration.
     //
     // `decl`: the unlowered (AST) function declaration.
-    // `fn_def_id`: if `Some`, impl Trait arguments are lowered into generic parameters on the
-    //      given DefId, otherwise impl Trait is disallowed. Must be `Some` if
-    //      `make_ret_async` is also `Some`.
+    // `fn_node_id`: `impl Trait` arguments are lowered into generic parameters on the given `NodeId`.
     // `make_ret_async`: if `Some`, converts `-> T` into `-> impl Future<Output = T>` in the
     //      return type. This is used for `async fn` declarations. The `NodeId` is the ID of the
     //      return type `impl Trait` item, and the `Span` points to the `async` keyword.
@@ -1789,7 +1787,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
     //     type OpaqueTy<generics_from_parent_fn> = impl Future<Output = T>;
     //
     // `output`: unlowered output type (`T` in `-> T`)
-    // `fn_def_id`: `DefId` of the parent function (used to create child impl trait definition)
+    // `fn_node_id`: `NodeId` of the parent function (used to create child impl trait definition)
     // `opaque_ty_node_id`: `NodeId` of the opaque `impl Trait` type that should be created
     #[instrument(level = "debug", skip(self))]
     fn lower_async_fn_ret_ty(
@@ -2031,7 +2029,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         &mut self,
         output: &FnRetTy,
         span: Span,
-        mut nested_impl_trait_context: ImplTraitContext,
+        nested_impl_trait_context: ImplTraitContext,
     ) -> hir::GenericBound<'hir> {
         // Compute the `T` in `Future<Output = T>` from the return type.
         let output_ty = match output {
@@ -2039,7 +2037,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                 // Not `OpaqueTyOrigin::AsyncFn`: that's only used for the
                 // `impl Future` opaque type that `async fn` implicitly
                 // generates.
-                self.lower_ty(ty, &mut nested_impl_trait_context)
+                self.lower_ty(ty, &nested_impl_trait_context)
             }
             FnRetTy::Default(ret_ty_span) => self.arena.alloc(self.ty_tup(*ret_ty_span, &[])),
         };
@@ -2247,6 +2245,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
     ) -> (hir::GenericParam<'hir>, Option<hir::WherePredicate<'hir>>, hir::TyKind<'hir>) {
         // Add a definition for the in-band `Param`.
         let def_id = self.local_def_id(node_id);
+        let span = self.lower_span(span);
 
         // Set the name to `impl Bound1 + Bound2`.
         let param = hir::GenericParam {
@@ -2254,7 +2253,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
             def_id,
             name: ParamName::Plain(self.lower_ident(ident)),
             pure_wrt_drop: false,
-            span: self.lower_span(span),
+            span,
             kind: hir::GenericParamKind::Type { default: None, synthetic: true },
             colon_span: None,
         };
@@ -2264,6 +2263,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
             node_id,
             &GenericParamKind::Type { default: None },
             bounds,
+            /* colon_span */ None,
+            span,
             &ImplTraitContext::Universal,
             hir::PredicateOrigin::ImplTrait,
         );
@@ -2273,7 +2274,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         let ty = hir::TyKind::Path(hir::QPath::Resolved(
             None,
             self.arena.alloc(hir::Path {
-                span: self.lower_span(span),
+                span,
                 res,
                 segments:
                     arena_vec![self; hir::PathSegment::new(self.lower_ident(ident), hir_id, res)],
diff --git a/compiler/rustc_ast_lowering/src/pat.rs b/compiler/rustc_ast_lowering/src/pat.rs
index 16b012630da..06d885a45fb 100644
--- a/compiler/rustc_ast_lowering/src/pat.rs
+++ b/compiler/rustc_ast_lowering/src/pat.rs
@@ -37,7 +37,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                             qself,
                             path,
                             ParamMode::Optional,
-                            &mut ImplTraitContext::Disallowed(ImplTraitPosition::Path),
+                            &ImplTraitContext::Disallowed(ImplTraitPosition::Path),
                         );
                         let (pats, ddpos) = self.lower_pat_tuple(pats, "tuple struct");
                         break hir::PatKind::TupleStruct(qpath, pats, ddpos);
@@ -53,7 +53,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                             qself,
                             path,
                             ParamMode::Optional,
-                            &mut ImplTraitContext::Disallowed(ImplTraitPosition::Path),
+                            &ImplTraitContext::Disallowed(ImplTraitPosition::Path),
                         );
                         break hir::PatKind::Path(qpath);
                     }
@@ -63,7 +63,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                             qself,
                             path,
                             ParamMode::Optional,
-                            &mut ImplTraitContext::Disallowed(ImplTraitPosition::Path),
+                            &ImplTraitContext::Disallowed(ImplTraitPosition::Path),
                         );
 
                         let fs = self.arena.alloc_from_iter(fields.iter().map(|f| {
diff --git a/compiler/rustc_borrowck/src/consumers.rs b/compiler/rustc_borrowck/src/consumers.rs
index 86da767f322..becc04bbdab 100644
--- a/compiler/rustc_borrowck/src/consumers.rs
+++ b/compiler/rustc_borrowck/src/consumers.rs
@@ -28,10 +28,10 @@ pub use super::{
 ///     that shows how to do this at `src/test/run-make/obtain-borrowck/`.
 ///
 /// *   Polonius is highly unstable, so expect regular changes in its signature or other details.
-pub fn get_body_with_borrowck_facts<'tcx>(
-    tcx: TyCtxt<'tcx>,
+pub fn get_body_with_borrowck_facts(
+    tcx: TyCtxt<'_>,
     def: ty::WithOptConstParam<LocalDefId>,
-) -> BodyWithBorrowckFacts<'tcx> {
+) -> BodyWithBorrowckFacts<'_> {
     let (input_body, promoted) = tcx.mir_promoted(def);
     let infcx = tcx.infer_ctxt().with_opaque_type_inference(DefiningAnchor::Bind(def.did)).build();
     let input_body: &Body<'_> = &input_body.borrow();
diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
index 8d5c5a7124f..26212dd384c 100644
--- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
@@ -194,7 +194,13 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
 
                 if !seen_spans.contains(&move_span) {
                     if !closure {
-                        self.suggest_ref_or_clone(mpi, move_span, &mut err, &mut in_pattern);
+                        self.suggest_ref_or_clone(
+                            mpi,
+                            move_span,
+                            &mut err,
+                            &mut in_pattern,
+                            move_spans,
+                        );
                     }
 
                     self.explain_captures(
@@ -312,6 +318,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
         move_span: Span,
         err: &mut DiagnosticBuilder<'_, ErrorGuaranteed>,
         in_pattern: &mut bool,
+        move_spans: UseSpans<'_>,
     ) {
         struct ExpressionFinder<'hir> {
             expr_span: Span,
@@ -440,6 +447,11 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                         ) = call_expr.kind
                     {
                         // Do not suggest `.clone()` in a `for` loop, we already suggest borrowing.
+                    } else if let UseSpans::FnSelfUse {
+                        kind: CallKind::Normal { .. },
+                        ..
+                    } = move_spans {
+                        // We already suggest cloning for these cases in `explain_captures`.
                     } else {
                         self.suggest_cloning(err, ty, move_span);
                     }
diff --git a/compiler/rustc_borrowck/src/diagnostics/find_all_local_uses.rs b/compiler/rustc_borrowck/src/diagnostics/find_all_local_uses.rs
index 498e9834354..2c4d953f011 100644
--- a/compiler/rustc_borrowck/src/diagnostics/find_all_local_uses.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/find_all_local_uses.rs
@@ -9,7 +9,7 @@ use rustc_middle::mir::{Body, Local, Location};
 /// Find all uses of (including assignments to) a [`Local`].
 ///
 /// Uses `BTreeSet` so output is deterministic.
-pub(super) fn find<'tcx>(body: &Body<'tcx>, local: Local) -> BTreeSet<Location> {
+pub(super) fn find(body: &Body<'_>, local: Local) -> BTreeSet<Location> {
     let mut visitor = AllLocalUsesVisitor { for_local: local, uses: BTreeSet::default() };
     visitor.visit_body(body);
     visitor.uses
diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs
index cbd59005200..63b16aa95a6 100644
--- a/compiler/rustc_borrowck/src/diagnostics/mod.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs
@@ -6,7 +6,7 @@ use rustc_errors::{Applicability, Diagnostic};
 use rustc_hir as hir;
 use rustc_hir::def::{CtorKind, Namespace};
 use rustc_hir::GeneratorKind;
-use rustc_infer::infer::TyCtxtInferExt;
+use rustc_infer::infer::{LateBoundRegionConversionTime, TyCtxtInferExt};
 use rustc_middle::mir::tcx::PlaceTy;
 use rustc_middle::mir::{
     AggregateKind, Constant, FakeReadCause, Field, Local, LocalInfo, LocalKind, Location, Operand,
@@ -18,7 +18,10 @@ use rustc_mir_dataflow::move_paths::{InitLocation, LookupResult};
 use rustc_span::def_id::LocalDefId;
 use rustc_span::{symbol::sym, Span, Symbol, DUMMY_SP};
 use rustc_target::abi::VariantIdx;
-use rustc_trait_selection::traits::type_known_to_meet_bound_modulo_regions;
+use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
+use rustc_trait_selection::traits::{
+    type_known_to_meet_bound_modulo_regions, Obligation, ObligationCause,
+};
 
 use super::borrow_set::BorrowData;
 use super::MirBorrowckCtxt;
@@ -1066,18 +1069,16 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                 }
                 CallKind::Normal { self_arg, desugaring, method_did } => {
                     let self_arg = self_arg.unwrap();
+                    let tcx = self.infcx.tcx;
                     if let Some((CallDesugaringKind::ForLoopIntoIter, _)) = desugaring {
-                        let ty = moved_place.ty(self.body, self.infcx.tcx).ty;
-                        let suggest = match self.infcx.tcx.get_diagnostic_item(sym::IntoIterator) {
+                        let ty = moved_place.ty(self.body, tcx).ty;
+                        let suggest = match tcx.get_diagnostic_item(sym::IntoIterator) {
                             Some(def_id) => {
                                 let infcx = self.infcx.tcx.infer_ctxt().build();
                                 type_known_to_meet_bound_modulo_regions(
                                     &infcx,
                                     self.param_env,
-                                    infcx.tcx.mk_imm_ref(
-                                        infcx.tcx.lifetimes.re_erased,
-                                        infcx.tcx.erase_regions(ty),
-                                    ),
+                                    tcx.mk_imm_ref(tcx.lifetimes.re_erased, tcx.erase_regions(ty)),
                                     def_id,
                                     DUMMY_SP,
                                 )
@@ -1133,8 +1134,44 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                                 place_name, partially_str, loop_message
                             ),
                         );
+                        let infcx = tcx.infer_ctxt().build();
+                        let ty = tcx.erase_regions(moved_place.ty(self.body, tcx).ty);
+                        if let ty::Adt(def, substs) = ty.kind()
+                            && Some(def.did()) == tcx.lang_items().pin_type()
+                            && let ty::Ref(_, _, hir::Mutability::Mut) = substs.type_at(0).kind()
+                            && let self_ty = infcx.replace_bound_vars_with_fresh_vars(
+                                fn_call_span,
+                                LateBoundRegionConversionTime::FnCall,
+                                tcx.fn_sig(method_did).input(0),
+                            )
+                            && infcx.can_eq(self.param_env, ty, self_ty).is_ok()
+                        {
+                            err.span_suggestion_verbose(
+                                fn_call_span.shrink_to_lo(),
+                                "consider reborrowing the `Pin` instead of moving it",
+                                "as_mut().".to_string(),
+                                Applicability::MaybeIncorrect,
+                            );
+                        }
+                        if let Some(clone_trait) = tcx.lang_items().clone_trait()
+                            && let trait_ref = tcx.mk_trait_ref(clone_trait, [ty])
+                            && let o = Obligation::new(
+                                tcx,
+                                ObligationCause::dummy(),
+                                self.param_env,
+                                ty::Binder::dummy(trait_ref),
+                            )
+                            && infcx.predicate_must_hold_modulo_regions(&o)
+                        {
+                            err.span_suggestion_verbose(
+                                fn_call_span.shrink_to_lo(),
+                                "you can `clone` the value and consume it, but this might not be \
+                                 your desired behavior",
+                                "clone().".to_string(),
+                                Applicability::MaybeIncorrect,
+                            );
+                        }
                     }
-                    let tcx = self.infcx.tcx;
                     // Avoid pointing to the same function in multiple different
                     // error messages.
                     if span != DUMMY_SP && self.fn_self_span_reported.insert(self_arg.span) {
diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
index b5a0044e9e8..bcc8afbfd95 100644
--- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
@@ -18,11 +18,11 @@ use rustc_infer::infer::{
 use rustc_middle::hir::place::PlaceBase;
 use rustc_middle::mir::{ConstraintCategory, ReturnConstraint};
 use rustc_middle::ty::subst::InternalSubsts;
-use rustc_middle::ty::Region;
 use rustc_middle::ty::TypeVisitor;
 use rustc_middle::ty::{self, RegionVid, Ty};
+use rustc_middle::ty::{Region, TyCtxt};
 use rustc_span::symbol::{kw, Ident};
-use rustc_span::Span;
+use rustc_span::{Span, DUMMY_SP};
 
 use crate::borrowck_errors;
 use crate::session_diagnostics::{
@@ -70,7 +70,25 @@ impl<'tcx> ConstraintDescription for ConstraintCategory<'tcx> {
 ///
 /// Usually we expect this to either be empty or contain a small number of items, so we can avoid
 /// allocation most of the time.
-pub(crate) type RegionErrors<'tcx> = Vec<RegionErrorKind<'tcx>>;
+pub(crate) struct RegionErrors<'tcx>(Vec<RegionErrorKind<'tcx>>, TyCtxt<'tcx>);
+
+impl<'tcx> RegionErrors<'tcx> {
+    pub fn new(tcx: TyCtxt<'tcx>) -> Self {
+        Self(vec![], tcx)
+    }
+    #[track_caller]
+    pub fn push(&mut self, val: impl Into<RegionErrorKind<'tcx>>) {
+        let val = val.into();
+        self.1.sess.delay_span_bug(DUMMY_SP, "{val:?}");
+        self.0.push(val);
+    }
+    pub fn is_empty(&self) -> bool {
+        self.0.is_empty()
+    }
+    pub fn into_iter(self) -> impl Iterator<Item = RegionErrorKind<'tcx>> {
+        self.0.into_iter()
+    }
+}
 
 #[derive(Clone, Debug)]
 pub(crate) enum RegionErrorKind<'tcx> {
diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs
index d8c22fbe59f..168b798788b 100644
--- a/compiler/rustc_borrowck/src/lib.rs
+++ b/compiler/rustc_borrowck/src/lib.rs
@@ -124,10 +124,7 @@ pub fn provide(providers: &mut Providers) {
     };
 }
 
-fn mir_borrowck<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    def: ty::WithOptConstParam<LocalDefId>,
-) -> &'tcx BorrowCheckResult<'tcx> {
+fn mir_borrowck(tcx: TyCtxt<'_>, def: ty::WithOptConstParam<LocalDefId>) -> &BorrowCheckResult<'_> {
     let (input_body, promoted) = tcx.mir_promoted(def);
     debug!("run query mir_borrowck: {}", tcx.def_path_str(def.did.to_def_id()));
 
diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs
index 0d03346ef0a..308f6e19a73 100644
--- a/compiler/rustc_borrowck/src/region_infer/mod.rs
+++ b/compiler/rustc_borrowck/src/region_infer/mod.rs
@@ -562,7 +562,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         let mir_def_id = body.source.def_id();
         self.propagate_constraints(body);
 
-        let mut errors_buffer = RegionErrors::new();
+        let mut errors_buffer = RegionErrors::new(infcx.tcx);
 
         // If this is a closure, we can propagate unsatisfied
         // `outlives_requirements` to our creator, so create a vector
@@ -1647,26 +1647,29 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         let longer_fr_scc = self.constraint_sccs.scc(longer_fr);
         debug!("check_bound_universal_region: longer_fr_scc={:?}", longer_fr_scc,);
 
-        // If we have some bound universal region `'a`, then the only
-        // elements it can contain is itself -- we don't know anything
-        // else about it!
-        let Some(error_element) = ({
-            self.scc_values.elements_contained_in(longer_fr_scc).find(|element| match element {
-                RegionElement::Location(_) => true,
-                RegionElement::RootUniversalRegion(_) => true,
-                RegionElement::PlaceholderRegion(placeholder1) => placeholder != *placeholder1,
-            })
-        }) else {
-            return;
-        };
-        debug!("check_bound_universal_region: error_element = {:?}", error_element);
+        for error_element in self.scc_values.elements_contained_in(longer_fr_scc) {
+            match error_element {
+                RegionElement::Location(_) | RegionElement::RootUniversalRegion(_) => {}
+                // If we have some bound universal region `'a`, then the only
+                // elements it can contain is itself -- we don't know anything
+                // else about it!
+                RegionElement::PlaceholderRegion(placeholder1) => {
+                    if placeholder == placeholder1 {
+                        continue;
+                    }
+                }
+            }
 
-        // Find the region that introduced this `error_element`.
-        errors_buffer.push(RegionErrorKind::BoundUniversalRegionError {
-            longer_fr,
-            error_element,
-            placeholder,
-        });
+            errors_buffer.push(RegionErrorKind::BoundUniversalRegionError {
+                longer_fr,
+                error_element,
+                placeholder,
+            });
+
+            // Stop after the first error, it gets too noisy otherwise, and does not provide more information.
+            break;
+        }
+        debug!("check_bound_universal_region: all bounds satisfied");
     }
 
     #[instrument(level = "debug", skip(self, infcx, errors_buffer))]
diff --git a/compiler/rustc_borrowck/src/type_check/free_region_relations.rs b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs
index 14cfc3613bf..09cf870bcf3 100644
--- a/compiler/rustc_borrowck/src/type_check/free_region_relations.rs
+++ b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs
@@ -85,7 +85,7 @@ impl UniversalRegionRelations<'_> {
     /// outlives `fr` and (b) is not local.
     ///
     /// (*) If there are multiple competing choices, we return all of them.
-    pub(crate) fn non_local_upper_bounds<'a>(&'a self, fr: RegionVid) -> Vec<RegionVid> {
+    pub(crate) fn non_local_upper_bounds(&self, fr: RegionVid) -> Vec<RegionVid> {
         debug!("non_local_upper_bound(fr={:?})", fr);
         let res = self.non_local_bounds(&self.inverse_outlives, fr);
         assert!(!res.is_empty(), "can't find an upper bound!?");
@@ -148,9 +148,9 @@ impl UniversalRegionRelations<'_> {
     /// Helper for `non_local_upper_bounds` and `non_local_lower_bounds`.
     /// Repeatedly invokes `postdom_parent` until we find something that is not
     /// local. Returns `None` if we never do so.
-    fn non_local_bounds<'a>(
+    fn non_local_bounds(
         &self,
-        relation: &'a TransitiveRelation<RegionVid>,
+        relation: &TransitiveRelation<RegionVid>,
         fr0: RegionVid,
     ) -> Vec<RegionVid> {
         // This method assumes that `fr0` is one of the universally
diff --git a/compiler/rustc_borrowck/src/type_check/input_output.rs b/compiler/rustc_borrowck/src/type_check/input_output.rs
index 62c6f958137..8fa43f8528c 100644
--- a/compiler/rustc_borrowck/src/type_check/input_output.rs
+++ b/compiler/rustc_borrowck/src/type_check/input_output.rs
@@ -37,31 +37,30 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
         // those.
         //
         // e.g., `|x: FxHashMap<_, &'static u32>| ...`
-        let user_provided_sig;
-        if !self.tcx().is_closure(mir_def_id.to_def_id()) {
-            user_provided_sig = None;
+        let user_provided_sig = if !self.tcx().is_closure(mir_def_id.to_def_id()) {
+            None
         } else {
             let typeck_results = self.tcx().typeck(mir_def_id);
-            user_provided_sig =
-                typeck_results.user_provided_sigs.get(&mir_def_id).map(|user_provided_poly_sig| {
-                    // Instantiate the canonicalized variables from
-                    // user-provided signature (e.g., the `_` in the code
-                    // above) with fresh variables.
-                    let poly_sig = self.instantiate_canonical_with_fresh_inference_vars(
-                        body.span,
-                        &user_provided_poly_sig,
-                    );
-
-                    // Replace the bound items in the fn sig with fresh
-                    // variables, so that they represent the view from
-                    // "inside" the closure.
-                    self.infcx.replace_bound_vars_with_fresh_vars(
-                        body.span,
-                        LateBoundRegionConversionTime::FnCall,
-                        poly_sig,
-                    )
-                });
-        }
+
+            typeck_results.user_provided_sigs.get(&mir_def_id).map(|user_provided_poly_sig| {
+                // Instantiate the canonicalized variables from
+                // user-provided signature (e.g., the `_` in the code
+                // above) with fresh variables.
+                let poly_sig = self.instantiate_canonical_with_fresh_inference_vars(
+                    body.span,
+                    &user_provided_poly_sig,
+                );
+
+                // Replace the bound items in the fn sig with fresh
+                // variables, so that they represent the view from
+                // "inside" the closure.
+                self.infcx.replace_bound_vars_with_fresh_vars(
+                    body.span,
+                    LateBoundRegionConversionTime::FnCall,
+                    poly_sig,
+                )
+            })
+        };
 
         debug!(?normalized_input_tys, ?body.local_decls);
 
diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs
index 8d4a720f8ce..247607ff29e 100644
--- a/compiler/rustc_borrowck/src/type_check/mod.rs
+++ b/compiler/rustc_borrowck/src/type_check/mod.rs
@@ -1153,16 +1153,23 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
         category: ConstraintCategory<'tcx>,
     ) -> Fallible<()> {
         let annotated_type = self.user_type_annotations[user_ty.base].inferred_ty;
+        trace!(?annotated_type);
         let mut curr_projected_ty = PlaceTy::from_ty(annotated_type);
 
         let tcx = self.infcx.tcx;
 
         for proj in &user_ty.projs {
+            if let ty::Alias(ty::Opaque, ..) = curr_projected_ty.ty.kind() {
+                // There is nothing that we can compare here if we go through an opaque type.
+                // We're always in its defining scope as we can otherwise not project through
+                // it, so we're constraining it anyways.
+                return Ok(());
+            }
             let projected_ty = curr_projected_ty.projection_ty_core(
                 tcx,
                 self.param_env,
                 proj,
-                |this, field, _| {
+                |this, field, ()| {
                     let ty = this.field_ty(tcx, field);
                     self.normalize(ty, locations)
                 },
@@ -1170,10 +1177,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
             );
             curr_projected_ty = projected_ty;
         }
-        debug!(
-            "user_ty base: {:?} freshened: {:?} projs: {:?} yields: {:?}",
-            user_ty.base, annotated_type, user_ty.projs, curr_projected_ty
-        );
+        trace!(?curr_projected_ty);
 
         let ty = curr_projected_ty.ty;
         self.relate_types(ty, v.xform(ty::Variance::Contravariant), a, locations, category)?;
diff --git a/compiler/rustc_builtin_macros/src/asm.rs b/compiler/rustc_builtin_macros/src/asm.rs
index 900c4427424..925392b500a 100644
--- a/compiler/rustc_builtin_macros/src/asm.rs
+++ b/compiler/rustc_builtin_macros/src/asm.rs
@@ -352,7 +352,7 @@ pub fn parse_asm_args<'a>(
 ///
 /// This function must be called immediately after the option token is parsed.
 /// Otherwise, the suggestion will be incorrect.
-fn err_duplicate_option<'a>(p: &mut Parser<'a>, symbol: Symbol, span: Span) {
+fn err_duplicate_option(p: &mut Parser<'_>, symbol: Symbol, span: Span) {
     let mut err = p
         .sess
         .span_diagnostic
diff --git a/compiler/rustc_builtin_macros/src/proc_macro_harness.rs b/compiler/rustc_builtin_macros/src/proc_macro_harness.rs
index ece660cf6f6..b88de224675 100644
--- a/compiler/rustc_builtin_macros/src/proc_macro_harness.rs
+++ b/compiler/rustc_builtin_macros/src/proc_macro_harness.rs
@@ -262,6 +262,7 @@ impl<'a> Visitor<'a> for CollectProcMacros<'a> {
 //          use proc_macro::bridge::client::ProcMacro;
 //
 //          #[rustc_proc_macro_decls]
+//          #[used]
 //          #[allow(deprecated)]
 //          static DECLS: &[ProcMacro] = &[
 //              ProcMacro::custom_derive($name_trait1, &[], ::$name1);
@@ -364,6 +365,7 @@ fn mk_decls(cx: &mut ExtCtxt<'_>, macros: &[ProcMacro]) -> P<ast::Item> {
         )
         .map(|mut i| {
             i.attrs.push(cx.attr_word(sym::rustc_proc_macro_decls, span));
+            i.attrs.push(cx.attr_word(sym::used, span));
             i.attrs.push(cx.attr_nested_word(sym::allow, sym::deprecated, span));
             i
         });
diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs
index 7a380acf798..e4ac89a7bec 100644
--- a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs
+++ b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs
@@ -644,7 +644,7 @@ fn codegen_regular_intrinsic_call<'tcx>(
             let res = CValue::by_val(res, arg.layout());
             ret.write_cvalue(fx, res);
         }
-        sym::assert_inhabited | sym::assert_zero_valid | sym::assert_uninit_valid => {
+        sym::assert_inhabited | sym::assert_zero_valid | sym::assert_mem_uninitialized_valid => {
             intrinsic_args!(fx, args => (); intrinsic);
 
             let layout = fx.layout_of(substs.type_at(0));
@@ -673,7 +673,9 @@ fn codegen_regular_intrinsic_call<'tcx>(
                 return;
             }
 
-            if intrinsic == sym::assert_uninit_valid && !fx.tcx.permits_uninit_init(layout) {
+            if intrinsic == sym::assert_mem_uninitialized_valid
+                && !fx.tcx.permits_uninit_init(layout)
+            {
                 with_no_trimmed_paths!({
                     crate::base::codegen_panic(
                         fx,
diff --git a/compiler/rustc_codegen_gcc/src/base.rs b/compiler/rustc_codegen_gcc/src/base.rs
index 8f9f6f98faf..d464bd3d12a 100644
--- a/compiler/rustc_codegen_gcc/src/base.rs
+++ b/compiler/rustc_codegen_gcc/src/base.rs
@@ -52,7 +52,7 @@ pub fn linkage_to_gcc(linkage: Linkage) -> FunctionType {
     }
 }
 
-pub fn compile_codegen_unit<'tcx>(tcx: TyCtxt<'tcx>, cgu_name: Symbol, supports_128bit_integers: bool) -> (ModuleCodegen<GccContext>, u64) {
+pub fn compile_codegen_unit(tcx: TyCtxt<'_>, cgu_name: Symbol, supports_128bit_integers: bool) -> (ModuleCodegen<GccContext>, u64) {
     let prof_timer = tcx.prof.generic_activity("codegen_module");
     let start_time = Instant::now();
 
diff --git a/compiler/rustc_codegen_gcc/src/common.rs b/compiler/rustc_codegen_gcc/src/common.rs
index aa1c271c31c..0afc56b4494 100644
--- a/compiler/rustc_codegen_gcc/src/common.rs
+++ b/compiler/rustc_codegen_gcc/src/common.rs
@@ -44,7 +44,7 @@ pub fn bytes_in_context<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, bytes: &[u8]) ->
     context.new_array_constructor(None, typ, &elements)
 }
 
-pub fn type_is_pointer<'gcc>(typ: Type<'gcc>) -> bool {
+pub fn type_is_pointer(typ: Type<'_>) -> bool {
     typ.get_pointee().is_some()
 }
 
diff --git a/compiler/rustc_codegen_gcc/src/lib.rs b/compiler/rustc_codegen_gcc/src/lib.rs
index b9600da5c39..bf1da38312f 100644
--- a/compiler/rustc_codegen_gcc/src/lib.rs
+++ b/compiler/rustc_codegen_gcc/src/lib.rs
@@ -161,7 +161,7 @@ impl ExtraBackendMethods for GccCodegenBackend {
         mods
     }
 
-    fn compile_codegen_unit<'tcx>(&self, tcx: TyCtxt<'tcx>, cgu_name: Symbol) -> (ModuleCodegen<Self::Module>, u64) {
+    fn compile_codegen_unit(&self, tcx: TyCtxt<'_>, cgu_name: Symbol) -> (ModuleCodegen<Self::Module>, u64) {
         base::compile_codegen_unit(tcx, cgu_name, *self.supports_128bit_integers.lock().expect("lock"))
     }
 
diff --git a/compiler/rustc_codegen_llvm/src/attributes.rs b/compiler/rustc_codegen_llvm/src/attributes.rs
index f3bdacf6085..95baa95b021 100644
--- a/compiler/rustc_codegen_llvm/src/attributes.rs
+++ b/compiler/rustc_codegen_llvm/src/attributes.rs
@@ -102,10 +102,10 @@ pub fn uwtable_attr(llcx: &llvm::Context) -> &Attribute {
 
 pub fn frame_pointer_type_attr<'ll>(cx: &CodegenCx<'ll, '_>) -> Option<&'ll Attribute> {
     let mut fp = cx.sess().target.frame_pointer;
+    let opts = &cx.sess().opts;
     // "mcount" function relies on stack pointer.
     // See <https://sourceware.org/binutils/docs/gprof/Implementation.html>.
-    if cx.sess().instrument_mcount() || matches!(cx.sess().opts.cg.force_frame_pointers, Some(true))
-    {
+    if opts.unstable_opts.instrument_mcount || matches!(opts.cg.force_frame_pointers, Some(true)) {
         fp = FramePointer::Always;
     }
     let attr_value = match fp {
@@ -119,7 +119,7 @@ pub fn frame_pointer_type_attr<'ll>(cx: &CodegenCx<'ll, '_>) -> Option<&'ll Attr
 /// Tell LLVM what instrument function to insert.
 #[inline]
 fn instrument_function_attr<'ll>(cx: &CodegenCx<'ll, '_>) -> Option<&'ll Attribute> {
-    if cx.sess().instrument_mcount() {
+    if cx.sess().opts.unstable_opts.instrument_mcount {
         // Similar to `clang -pg` behavior. Handled by the
         // `post-inline-ee-instrument` LLVM pass.
 
@@ -137,6 +137,14 @@ fn instrument_function_attr<'ll>(cx: &CodegenCx<'ll, '_>) -> Option<&'ll Attribu
     }
 }
 
+fn nojumptables_attr<'ll>(cx: &CodegenCx<'ll, '_>) -> Option<&'ll Attribute> {
+    if !cx.sess().opts.unstable_opts.no_jump_tables {
+        return None;
+    }
+
+    Some(llvm::CreateAttrStringValue(cx.llcx, "no-jump-tables", "true"))
+}
+
 fn probestack_attr<'ll>(cx: &CodegenCx<'ll, '_>) -> Option<&'ll Attribute> {
     // Currently stack probes seem somewhat incompatible with the address
     // sanitizer and thread sanitizer. With asan we're already protected from
@@ -293,6 +301,7 @@ pub fn from_fn_attrs<'ll, 'tcx>(
     // FIXME: none of these three functions interact with source level attributes.
     to_add.extend(frame_pointer_type_attr(cx));
     to_add.extend(instrument_function_attr(cx));
+    to_add.extend(nojumptables_attr(cx));
     to_add.extend(probestack_attr(cx));
     to_add.extend(stackprotector_attr(cx));
 
diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs
index 97d0de47b3a..e23c88b62c1 100644
--- a/compiler/rustc_codegen_llvm/src/back/write.rs
+++ b/compiler/rustc_codegen_llvm/src/back/write.rs
@@ -203,7 +203,7 @@ pub fn target_machine_factory(
         sess.opts.unstable_opts.trap_unreachable.unwrap_or(sess.target.trap_unreachable);
     let emit_stack_size_section = sess.opts.unstable_opts.emit_stack_sizes;
 
-    let asm_comments = sess.asm_comments();
+    let asm_comments = sess.opts.unstable_opts.asm_comments;
     let relax_elf_relocations =
         sess.opts.unstable_opts.relax_elf_relocations.unwrap_or(sess.target.relax_elf_relocations);
 
diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs
index f3bff5d5716..d9ccba07a34 100644
--- a/compiler/rustc_codegen_llvm/src/context.rs
+++ b/compiler/rustc_codegen_llvm/src/context.rs
@@ -280,29 +280,35 @@ pub unsafe fn create_module<'ll>(
     }
 
     if let Some(BranchProtection { bti, pac_ret }) = sess.opts.unstable_opts.branch_protection {
+        let behavior = if llvm_version >= (15, 0, 0) {
+            llvm::LLVMModFlagBehavior::Min
+        } else {
+            llvm::LLVMModFlagBehavior::Error
+        };
+
         if sess.target.arch == "aarch64" {
             llvm::LLVMRustAddModuleFlag(
                 llmod,
-                llvm::LLVMModFlagBehavior::Error,
+                behavior,
                 "branch-target-enforcement\0".as_ptr().cast(),
                 bti.into(),
             );
             llvm::LLVMRustAddModuleFlag(
                 llmod,
-                llvm::LLVMModFlagBehavior::Error,
+                behavior,
                 "sign-return-address\0".as_ptr().cast(),
                 pac_ret.is_some().into(),
             );
             let pac_opts = pac_ret.unwrap_or(PacRet { leaf: false, key: PAuthKey::A });
             llvm::LLVMRustAddModuleFlag(
                 llmod,
-                llvm::LLVMModFlagBehavior::Error,
+                behavior,
                 "sign-return-address-all\0".as_ptr().cast(),
                 pac_opts.leaf.into(),
             );
             llvm::LLVMRustAddModuleFlag(
                 llmod,
-                llvm::LLVMModFlagBehavior::Error,
+                behavior,
                 "sign-return-address-with-bkey\0".as_ptr().cast(),
                 u32::from(pac_opts.key == PAuthKey::B),
             );
diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs
index 86580d05d41..393bf30e9f8 100644
--- a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs
+++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs
@@ -30,7 +30,7 @@ use std::ffi::CString;
 /// implementing this Rust version, and though the format documentation is very explicit and
 /// detailed, some undocumented details in Clang's implementation (that may or may not be important)
 /// were also replicated for Rust's Coverage Map.
-pub fn finalize<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>) {
+pub fn finalize(cx: &CodegenCx<'_, '_>) {
     let tcx = cx.tcx;
 
     // Ensure the installed version of LLVM supports at least Coverage Map
@@ -284,7 +284,7 @@ fn save_function_record(
 /// "code coverage dead code cgu" during the partitioning process. This prevents us from generating
 /// code regions for the same function more than once which can lead to linker errors regarding
 /// duplicate symbols.
-fn add_unused_functions<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>) {
+fn add_unused_functions(cx: &CodegenCx<'_, '_>) {
     assert!(cx.codegen_unit.is_code_coverage_dead_code_cgu());
 
     let tcx = cx.tcx;
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
index a9e3dcf4cb3..48e3a812e4f 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
@@ -111,7 +111,7 @@ macro_rules! return_if_di_node_created_in_meantime {
 
 /// Extract size and alignment from a TyAndLayout.
 #[inline]
-fn size_and_align_of<'tcx>(ty_and_layout: TyAndLayout<'tcx>) -> (Size, Align) {
+fn size_and_align_of(ty_and_layout: TyAndLayout<'_>) -> (Size, Align) {
     (ty_and_layout.size, ty_and_layout.align.abi)
 }
 
diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs
index 907517bf6ce..1ce48f82e1c 100644
--- a/compiler/rustc_codegen_llvm/src/intrinsic.rs
+++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs
@@ -567,7 +567,7 @@ fn codegen_msvc_try<'ll>(
         // module.
         //
         // When modifying, make sure that the type_name string exactly matches
-        // the one used in src/libpanic_unwind/seh.rs.
+        // the one used in library/panic_unwind/src/seh.rs.
         let type_info_vtable = bx.declare_global("??_7type_info@@6B@", bx.type_i8p());
         let type_name = bx.const_bytes(b"rust_panic\0");
         let type_info =
diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
index e61dbe8b8fc..8b4861962b2 100644
--- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
@@ -79,6 +79,7 @@ pub enum LLVMModFlagBehavior {
     Append = 5,
     AppendUnique = 6,
     Max = 7,
+    Min = 8,
 }
 
 // Consts for the LLVM CallConv type, pre-cast to usize.
@@ -2389,11 +2390,11 @@ extern "C" {
 
     pub fn LLVMRustSetDataLayoutFromTargetMachine<'a>(M: &'a Module, TM: &'a TargetMachine);
 
-    pub fn LLVMRustBuildOperandBundleDef<'a>(
+    pub fn LLVMRustBuildOperandBundleDef(
         Name: *const c_char,
-        Inputs: *const &'a Value,
+        Inputs: *const &'_ Value,
         NumInputs: c_uint,
-    ) -> &'a mut OperandBundleDef<'a>;
+    ) -> &mut OperandBundleDef<'_>;
     pub fn LLVMRustFreeOperandBundleDef<'a>(Bundle: &'a mut OperandBundleDef<'a>);
 
     pub fn LLVMRustPositionBuilderAtStart<'a>(B: &Builder<'a>, BB: &'a BasicBlock);
diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs
index 2fa602520dc..79b243f73d1 100644
--- a/compiler/rustc_codegen_llvm/src/llvm_util.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs
@@ -81,10 +81,10 @@ unsafe fn configure_llvm(sess: &Session) {
         };
         // Set the llvm "program name" to make usage and invalid argument messages more clear.
         add("rustc -Cllvm-args=\"...\" with", true);
-        if sess.time_llvm_passes() {
+        if sess.opts.unstable_opts.time_llvm_passes {
             add("-time-passes", false);
         }
-        if sess.print_llvm_passes() {
+        if sess.opts.unstable_opts.print_llvm_passes {
             add("-debug-pass=Structure", false);
         }
         if sess.target.generate_arange_section
diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs
index a1c77ec0cfc..edde1537b81 100644
--- a/compiler/rustc_codegen_ssa/src/back/link.rs
+++ b/compiler/rustc_codegen_ssa/src/back/link.rs
@@ -607,21 +607,21 @@ fn link_dwarf_object<'a>(
     }
 
     impl<Relocations> ThorinSession<Relocations> {
-        fn alloc_mmap<'arena>(&'arena self, data: Mmap) -> &'arena Mmap {
+        fn alloc_mmap(&self, data: Mmap) -> &Mmap {
             (*self.arena_mmap.alloc(data)).borrow()
         }
     }
 
     impl<Relocations> thorin::Session<Relocations> for ThorinSession<Relocations> {
-        fn alloc_data<'arena>(&'arena self, data: Vec<u8>) -> &'arena [u8] {
+        fn alloc_data(&self, data: Vec<u8>) -> &[u8] {
             (*self.arena_data.alloc(data)).borrow()
         }
 
-        fn alloc_relocation<'arena>(&'arena self, data: Relocations) -> &'arena Relocations {
+        fn alloc_relocation(&self, data: Relocations) -> &Relocations {
             (*self.arena_relocations.alloc(data)).borrow()
         }
 
-        fn read_input<'arena>(&'arena self, path: &Path) -> std::io::Result<&'arena [u8]> {
+        fn read_input(&self, path: &Path) -> std::io::Result<&[u8]> {
             let file = File::open(&path)?;
             let mmap = (unsafe { Mmap::map(file) })?;
             Ok(self.alloc_mmap(mmap))
diff --git a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs
index 22f534d909a..8cb7d74b90d 100644
--- a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs
+++ b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs
@@ -163,10 +163,10 @@ fn is_reachable_non_generic_provider_extern(tcx: TyCtxt<'_>, def_id: DefId) -> b
     tcx.reachable_non_generics(def_id.krate).contains_key(&def_id)
 }
 
-fn exported_symbols_provider_local<'tcx>(
-    tcx: TyCtxt<'tcx>,
+fn exported_symbols_provider_local(
+    tcx: TyCtxt<'_>,
     cnum: CrateNum,
-) -> &'tcx [(ExportedSymbol<'tcx>, SymbolExportInfo)] {
+) -> &[(ExportedSymbol<'_>, SymbolExportInfo)] {
     assert_eq!(cnum, LOCAL_CRATE);
 
     if !tcx.sess.opts.output_types.should_codegen() {
diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs
index 12fca64968a..1a7de1a184a 100644
--- a/compiler/rustc_codegen_ssa/src/back/write.rs
+++ b/compiler/rustc_codegen_ssa/src/back/write.rs
@@ -1899,7 +1899,7 @@ impl<B: ExtraBackendMethods> OngoingCodegen<B> {
 
         // FIXME: time_llvm_passes support - does this use a global context or
         // something?
-        if sess.codegen_units() == 1 && sess.time_llvm_passes() {
+        if sess.codegen_units() == 1 && sess.opts.unstable_opts.time_llvm_passes {
             self.backend.print_pass_timings()
         }
 
diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs
index 664697e0eda..8b34be38580 100644
--- a/compiler/rustc_codegen_ssa/src/base.rs
+++ b/compiler/rustc_codegen_ssa/src/base.rs
@@ -681,7 +681,7 @@ pub fn codegen_crate<B: ExtraBackendMethods>(
     });
 
     let mut total_codegen_time = Duration::new(0, 0);
-    let start_rss = tcx.sess.time_passes().then(|| get_resident_set_size());
+    let start_rss = tcx.sess.opts.unstable_opts.time_passes.then(|| get_resident_set_size());
 
     // The non-parallel compiler can only translate codegen units to LLVM IR
     // on a single thread, leading to a staircase effect where the N LLVM
@@ -781,7 +781,7 @@ pub fn codegen_crate<B: ExtraBackendMethods>(
 
     // Since the main thread is sometimes blocked during codegen, we keep track
     // -Ztime-passes output manually.
-    if tcx.sess.time_passes() {
+    if tcx.sess.opts.unstable_opts.time_passes {
         let end_rss = get_resident_set_size();
 
         print_time_passes_entry(
diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
index c7f2e1966c1..b0fa7745667 100644
--- a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
+++ b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
@@ -2,6 +2,7 @@ use rustc_ast::{ast, MetaItemKind, NestedMetaItem};
 use rustc_attr::{list_contains_name, InlineAttr, InstructionSetAttr, OptimizeAttr};
 use rustc_errors::struct_span_err;
 use rustc_hir as hir;
+use rustc_hir::def::DefKind;
 use rustc_hir::def_id::{DefId, LocalDefId, LOCAL_CRATE};
 use rustc_hir::{lang_items, weak_lang_items::WEAK_LANG_ITEMS, LangItem};
 use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs};
@@ -60,6 +61,21 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: DefId) -> CodegenFnAttrs {
 
     let supported_target_features = tcx.supported_target_features(LOCAL_CRATE);
 
+    // In some cases, attribute are only valid on functions, but it's the `check_attr`
+    // pass that check that they aren't used anywhere else, rather this module.
+    // In these cases, we bail from performing further checks that are only meaningful for
+    // functions (such as calling `fn_sig`, which ICEs if given a non-function). We also
+    // report a delayed bug, just in case `check_attr` isn't doing its job.
+    let validate_fn_only_attr = |attr_sp| -> bool {
+        let def_kind = tcx.def_kind(did);
+        if let DefKind::Fn | DefKind::AssocFn | DefKind::Variant | DefKind::Ctor(..) = def_kind {
+            true
+        } else {
+            tcx.sess.delay_span_bug(attr_sp, "this attribute can only be applied to functions");
+            false
+        }
+    };
+
     let mut inline_span = None;
     let mut link_ordinal_span = None;
     let mut no_sanitize_span = None;
@@ -197,7 +213,9 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: DefId) -> CodegenFnAttrs {
                 }
             }
         } else if attr.has_name(sym::cmse_nonsecure_entry) {
-            if !matches!(tcx.fn_sig(did).abi(), abi::Abi::C { .. }) {
+            if validate_fn_only_attr(attr.span)
+                && !matches!(tcx.fn_sig(did).abi(), abi::Abi::C { .. })
+            {
                 struct_span_err!(
                     tcx.sess,
                     attr.span,
@@ -214,7 +232,10 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: DefId) -> CodegenFnAttrs {
         } else if attr.has_name(sym::thread_local) {
             codegen_fn_attrs.flags |= CodegenFnAttrFlags::THREAD_LOCAL;
         } else if attr.has_name(sym::track_caller) {
-            if !tcx.is_closure(did.to_def_id()) && tcx.fn_sig(did).abi() != abi::Abi::Rust {
+            if !tcx.is_closure(did.to_def_id())
+                && validate_fn_only_attr(attr.span)
+                && tcx.fn_sig(did).abi() != abi::Abi::Rust
+            {
                 struct_span_err!(tcx.sess, attr.span, E0737, "`#[track_caller]` requires Rust ABI")
                     .emit();
             }
diff --git a/compiler/rustc_codegen_ssa/src/debuginfo/mod.rs b/compiler/rustc_codegen_ssa/src/debuginfo/mod.rs
index 6e3f4f0b8ef..60e9b40e8fb 100644
--- a/compiler/rustc_codegen_ssa/src/debuginfo/mod.rs
+++ b/compiler/rustc_codegen_ssa/src/debuginfo/mod.rs
@@ -10,7 +10,7 @@ pub mod type_names;
 /// NOTE: This is somewhat inconsistent right now: For empty enums and enums with a single
 ///       fieldless variant, we generate DW_TAG_struct_type, although a
 ///       DW_TAG_enumeration_type would be a better fit.
-pub fn wants_c_like_enum_debuginfo<'tcx>(enum_type_and_layout: TyAndLayout<'tcx>) -> bool {
+pub fn wants_c_like_enum_debuginfo(enum_type_and_layout: TyAndLayout<'_>) -> bool {
     match enum_type_and_layout.ty.kind() {
         ty::Adt(adt_def, _) => {
             if !adt_def.is_enum() {
diff --git a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs
index 819c2678d6c..3ae6c531b44 100644
--- a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs
+++ b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs
@@ -509,7 +509,7 @@ pub fn compute_debuginfo_vtable_name<'tcx>(
         visited.clear();
         push_generic_params_internal(tcx, trait_ref.substs, &mut vtable_name, &mut visited);
     } else {
-        vtable_name.push_str("_");
+        vtable_name.push('_');
     }
 
     push_close_angle_bracket(cpp_like_debuginfo, &mut vtable_name);
diff --git a/compiler/rustc_codegen_ssa/src/meth.rs b/compiler/rustc_codegen_ssa/src/meth.rs
index d96ca921f1f..2421acab471 100644
--- a/compiler/rustc_codegen_ssa/src/meth.rs
+++ b/compiler/rustc_codegen_ssa/src/meth.rs
@@ -65,7 +65,7 @@ impl<'a, 'tcx> VirtualIndex {
 
 /// This takes a valid `self` receiver type and extracts the principal trait
 /// ref of the type.
-fn expect_dyn_trait_in_self<'tcx>(ty: Ty<'tcx>) -> ty::PolyExistentialTraitRef<'tcx> {
+fn expect_dyn_trait_in_self(ty: Ty<'_>) -> ty::PolyExistentialTraitRef<'_> {
     for arg in ty.peel_refs().walk() {
         if let GenericArgKind::Type(ty) = arg.unpack() {
             if let ty::Dynamic(data, _, _) = ty.kind() {
diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs
index 3860138018b..978aff511bf 100644
--- a/compiler/rustc_codegen_ssa/src/mir/block.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/block.rs
@@ -637,7 +637,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
         self.set_debug_loc(bx, terminator.source_info);
 
         // Obtain the panic entry point.
-        let (fn_abi, llfn) = common::build_langcall(bx, Some(span), LangItem::PanicNoUnwind);
+        let (fn_abi, llfn) = common::build_langcall(bx, Some(span), LangItem::PanicCannotUnwind);
 
         // Codegen the actual panic invoke/call.
         let merging_succ = helper.do_call(self, bx, fn_abi, llfn, &[], None, None, &[], false);
@@ -663,12 +663,12 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
         enum AssertIntrinsic {
             Inhabited,
             ZeroValid,
-            UninitValid,
+            MemUninitializedValid,
         }
         let panic_intrinsic = intrinsic.and_then(|i| match i {
             sym::assert_inhabited => Some(AssertIntrinsic::Inhabited),
             sym::assert_zero_valid => Some(AssertIntrinsic::ZeroValid),
-            sym::assert_uninit_valid => Some(AssertIntrinsic::UninitValid),
+            sym::assert_mem_uninitialized_valid => Some(AssertIntrinsic::MemUninitializedValid),
             _ => None,
         });
         if let Some(intrinsic) = panic_intrinsic {
@@ -679,7 +679,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
             let do_panic = match intrinsic {
                 Inhabited => layout.abi.is_uninhabited(),
                 ZeroValid => !bx.tcx().permits_zero_init(layout),
-                UninitValid => !bx.tcx().permits_uninit_init(layout),
+                MemUninitializedValid => !bx.tcx().permits_uninit_init(layout),
             };
             Some(if do_panic {
                 let msg_str = with_no_visible_paths!({
@@ -698,11 +698,10 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                     })
                 });
                 let msg = bx.const_str(&msg_str);
-                let location = self.get_caller_location(bx, source_info).immediate();
 
                 // Obtain the panic entry point.
                 let (fn_abi, llfn) =
-                    common::build_langcall(bx, Some(source_info.span), LangItem::Panic);
+                    common::build_langcall(bx, Some(source_info.span), LangItem::PanicNounwind);
 
                 // Codegen the actual panic invoke/call.
                 helper.do_call(
@@ -710,7 +709,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                     bx,
                     fn_abi,
                     llfn,
-                    &[msg.0, msg.1, location],
+                    &[msg.0, msg.1],
                     target.as_ref().map(|bb| (ReturnDest::Nothing, *bb)),
                     cleanup,
                     &[],
@@ -1665,7 +1664,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
             let llpersonality = self.cx.eh_personality();
             bx.cleanup_landing_pad(llpersonality);
 
-            let (fn_abi, fn_ptr) = common::build_langcall(&bx, None, LangItem::PanicNoUnwind);
+            let (fn_abi, fn_ptr) = common::build_langcall(&bx, None, LangItem::PanicCannotUnwind);
             let fn_ty = bx.fn_decl_backend_type(&fn_abi);
 
             let llret = bx.call(fn_ty, Some(&fn_abi), fn_ptr, &[], None);
diff --git a/compiler/rustc_codegen_ssa/src/target_features.rs b/compiler/rustc_codegen_ssa/src/target_features.rs
index 0dabe96b602..da69fc8ecf7 100644
--- a/compiler/rustc_codegen_ssa/src/target_features.rs
+++ b/compiler/rustc_codegen_ssa/src/target_features.rs
@@ -419,7 +419,7 @@ pub fn from_target_feature(
 
 /// Computes the set of target features used in a function for the purposes of
 /// inline assembly.
-fn asm_target_features<'tcx>(tcx: TyCtxt<'tcx>, did: DefId) -> &'tcx FxHashSet<Symbol> {
+fn asm_target_features(tcx: TyCtxt<'_>, did: DefId) -> &FxHashSet<Symbol> {
     let mut target_features = tcx.sess.unstable_target_features.clone();
     if tcx.def_kind(did).has_codegen_attrs() {
         let attrs = tcx.codegen_fn_attrs(did);
diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs
index 9b56757eb39..666fcbd6f80 100644
--- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs
+++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs
@@ -303,7 +303,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
             }
             sym::offset => {
                 let ptr = self.read_pointer(&args[0])?;
-                let offset_count = self.read_scalar(&args[1])?.to_machine_isize(self)?;
+                let offset_count = self.read_machine_isize(&args[1])?;
                 let pointee_ty = substs.type_at(0);
 
                 let offset_ptr = self.ptr_offset_inbounds(ptr, pointee_ty, offset_count)?;
@@ -311,7 +311,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
             }
             sym::arith_offset => {
                 let ptr = self.read_pointer(&args[0])?;
-                let offset_count = self.read_scalar(&args[1])?.to_machine_isize(self)?;
+                let offset_count = self.read_machine_isize(&args[1])?;
                 let pointee_ty = substs.type_at(0);
 
                 let pointee_size = i64::try_from(self.layout_of(pointee_ty)?.size.bytes()).unwrap();
@@ -428,7 +428,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
             sym::transmute => {
                 self.copy_op(&args[0], dest, /*allow_transmute*/ true)?;
             }
-            sym::assert_inhabited | sym::assert_zero_valid | sym::assert_uninit_valid => {
+            sym::assert_inhabited
+            | sym::assert_zero_valid
+            | sym::assert_mem_uninitialized_valid => {
                 let ty = instance.substs.type_at(0);
                 let layout = self.layout_of(ty)?;
 
@@ -460,7 +462,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                     }
                 }
 
-                if intrinsic_name == sym::assert_uninit_valid {
+                if intrinsic_name == sym::assert_mem_uninitialized_valid {
                     let should_panic = !self.tcx.permits_uninit_init(layout);
 
                     if should_panic {
@@ -668,7 +670,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         count: &OpTy<'tcx, <M as Machine<'mir, 'tcx>>::Provenance>,
         nonoverlapping: bool,
     ) -> InterpResult<'tcx> {
-        let count = self.read_scalar(&count)?.to_machine_usize(self)?;
+        let count = self.read_machine_usize(&count)?;
         let layout = self.layout_of(src.layout.ty.builtin_deref(true).unwrap().ty)?;
         let (size, align) = (layout.size, layout.align.abi);
         // `checked_mul` enforces a too small bound (the correct one would probably be machine_isize_max),
@@ -696,7 +698,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
 
         let dst = self.read_pointer(&dst)?;
         let byte = self.read_scalar(&byte)?.to_u8()?;
-        let count = self.read_scalar(&count)?.to_machine_usize(self)?;
+        let count = self.read_machine_usize(&count)?;
 
         // `checked_mul` enforces a too small bound (the correct one would probably be machine_isize_max),
         // but no actual allocation can be big enough for the difference to be noticeable.
diff --git a/compiler/rustc_const_eval/src/interpret/operand.rs b/compiler/rustc_const_eval/src/interpret/operand.rs
index f9e3a2bdc06..fcc6f8ea852 100644
--- a/compiler/rustc_const_eval/src/interpret/operand.rs
+++ b/compiler/rustc_const_eval/src/interpret/operand.rs
@@ -404,6 +404,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         Ok(self.read_immediate(op)?.to_scalar())
     }
 
+    // Pointer-sized reads are fairly common and need target layout access, so we wrap them in
+    // convenience functions.
+
     /// Read a pointer from a place.
     pub fn read_pointer(
         &self,
@@ -411,6 +414,14 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
     ) -> InterpResult<'tcx, Pointer<Option<M::Provenance>>> {
         self.read_scalar(op)?.to_pointer(self)
     }
+    /// Read a pointer-sized unsigned integer from a place.
+    pub fn read_machine_usize(&self, op: &OpTy<'tcx, M::Provenance>) -> InterpResult<'tcx, u64> {
+        self.read_scalar(op)?.to_machine_usize(self)
+    }
+    /// Read a pointer-sized signed integer from a place.
+    pub fn read_machine_isize(&self, op: &OpTy<'tcx, M::Provenance>) -> InterpResult<'tcx, i64> {
+        self.read_scalar(op)?.to_machine_isize(self)
+    }
 
     /// Turn the wide MPlace into a string (must already be dereferenced!)
     pub fn read_str(&self, mplace: &MPlaceTy<'tcx, M::Provenance>) -> InterpResult<'tcx, &str> {
@@ -566,8 +577,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
             ty::ConstKind::Unevaluated(uv) => {
                 let instance = self.resolve(uv.def, uv.substs)?;
                 let cid = GlobalId { instance, promoted: None };
-                self.ctfe_query(span, |tcx| tcx.eval_to_valtree(self.param_env.and(cid)))?
-                    .unwrap_or_else(|| bug!("unable to create ValTree for {uv:?}"))
+                self.ctfe_query(span, |tcx| {
+                    tcx.eval_to_valtree(self.param_env.with_const().and(cid))
+                })?
+                .unwrap_or_else(|| bug!("unable to create ValTree for {uv:?}"))
             }
             ty::ConstKind::Bound(..) | ty::ConstKind::Infer(..) => {
                 span_bug!(self.cur_span(), "unexpected ConstKind in ctfe: {val:?}")
diff --git a/compiler/rustc_const_eval/src/interpret/projection.rs b/compiler/rustc_const_eval/src/interpret/projection.rs
index 2ffd73eef3e..291464ab58a 100644
--- a/compiler/rustc_const_eval/src/interpret/projection.rs
+++ b/compiler/rustc_const_eval/src/interpret/projection.rs
@@ -363,7 +363,7 @@ where
             Index(local) => {
                 let layout = self.layout_of(self.tcx.types.usize)?;
                 let n = self.local_to_op(self.frame(), local, Some(layout))?;
-                let n = self.read_scalar(&n)?.to_machine_usize(self)?;
+                let n = self.read_machine_usize(&n)?;
                 self.place_index(base, n)?
             }
             ConstantIndex { offset, min_length, from_end } => {
@@ -392,7 +392,7 @@ where
             Index(local) => {
                 let layout = self.layout_of(self.tcx.types.usize)?;
                 let n = self.local_to_op(self.frame(), local, Some(layout))?;
-                let n = self.read_scalar(&n)?.to_machine_usize(self)?;
+                let n = self.read_machine_usize(&n)?;
                 self.operand_index(base, n)?
             }
             ConstantIndex { offset, min_length, from_end } => {
diff --git a/compiler/rustc_const_eval/src/interpret/terminator.rs b/compiler/rustc_const_eval/src/interpret/terminator.rs
index 0e7ffcdffc9..550c7a44c41 100644
--- a/compiler/rustc_const_eval/src/interpret/terminator.rs
+++ b/compiler/rustc_const_eval/src/interpret/terminator.rs
@@ -119,11 +119,20 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
             }
 
             Drop { place, target, unwind } => {
+                let frame = self.frame();
+                let ty = place.ty(&frame.body.local_decls, *self.tcx).ty;
+                let ty = self.subst_from_frame_and_normalize_erasing_regions(frame, ty)?;
+                let instance = Instance::resolve_drop_in_place(*self.tcx, ty);
+                if let ty::InstanceDef::DropGlue(_, None) = instance.def {
+                    // This is the branch we enter if and only if the dropped type has no drop glue
+                    // whatsoever. This can happen as a result of monomorphizing a drop of a
+                    // generic. In order to make sure that generic and non-generic code behaves
+                    // roughly the same (and in keeping with Mir semantics) we do nothing here.
+                    self.go_to_block(target);
+                    return Ok(());
+                }
                 let place = self.eval_place(place)?;
-                let ty = place.layout.ty;
                 trace!("TerminatorKind::drop: {:?}, type {}", place, ty);
-
-                let instance = Instance::resolve_drop_in_place(*self.tcx, ty);
                 self.drop_in_place(&place, instance, target, unwind)?;
             }
 
diff --git a/compiler/rustc_const_eval/src/transform/promote_consts.rs b/compiler/rustc_const_eval/src/transform/promote_consts.rs
index 6777fae74f1..04ce701452b 100644
--- a/compiler/rustc_const_eval/src/transform/promote_consts.rs
+++ b/compiler/rustc_const_eval/src/transform/promote_consts.rs
@@ -216,12 +216,6 @@ impl<'tcx> Validator<'_, 'tcx> {
                     return Err(Unpromotable);
                 }
 
-                // We cannot promote things that need dropping, since the promoted value
-                // would not get dropped.
-                if self.qualif_local::<qualifs::NeedsDrop>(place.local) {
-                    return Err(Unpromotable);
-                }
-
                 Ok(())
             }
             _ => bug!(),
@@ -262,13 +256,17 @@ impl<'tcx> Validator<'_, 'tcx> {
                 }
             }
         } else {
-            let span = self.body.local_decls[local].source_info.span;
-            span_bug!(span, "{:?} not promotable, qualif_local shouldn't have been called", local);
+            false
         }
     }
 
     fn validate_local(&mut self, local: Local) -> Result<(), Unpromotable> {
         if let TempState::Defined { location: loc, uses, valid } = self.temps[local] {
+            // We cannot promote things that need dropping, since the promoted value
+            // would not get dropped.
+            if self.qualif_local::<qualifs::NeedsDrop>(local) {
+                return Err(Unpromotable);
+            }
             valid.or_else(|_| {
                 let ok = {
                     let block = &self.body[loc.block];
diff --git a/compiler/rustc_const_eval/src/transform/validate.rs b/compiler/rustc_const_eval/src/transform/validate.rs
index bb897b95b2c..94e1b95a0eb 100644
--- a/compiler/rustc_const_eval/src/transform/validate.rs
+++ b/compiler/rustc_const_eval/src/transform/validate.rs
@@ -9,8 +9,8 @@ use rustc_middle::mir::visit::{PlaceContext, Visitor};
 use rustc_middle::mir::{
     traversal, AggregateKind, BasicBlock, BinOp, Body, BorrowKind, CastKind, CopyNonOverlapping,
     Local, Location, MirPass, MirPhase, NonDivergingIntrinsic, Operand, Place, PlaceElem, PlaceRef,
-    ProjectionElem, RuntimePhase, Rvalue, SourceScope, Statement, StatementKind, Terminator,
-    TerminatorKind, UnOp, START_BLOCK,
+    ProjectionElem, RetagKind, RuntimePhase, Rvalue, SourceScope, Statement, StatementKind,
+    Terminator, TerminatorKind, UnOp, START_BLOCK,
 };
 use rustc_middle::ty::{self, InstanceDef, ParamEnv, Ty, TyCtxt, TypeVisitable};
 use rustc_mir_dataflow::impls::MaybeStorageLive;
@@ -667,10 +667,13 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
                     self.fail(location, "`Deinit`is not allowed until deaggregation");
                 }
             }
-            StatementKind::Retag(_, _) => {
+            StatementKind::Retag(kind, _) => {
                 // FIXME(JakobDegen) The validator should check that `self.mir_phase <
                 // DropsLowered`. However, this causes ICEs with generation of drop shims, which
                 // seem to fail to set their `MirPhase` correctly.
+                if *kind == RetagKind::Raw || *kind == RetagKind::TwoPhase {
+                    self.fail(location, format!("explicit `{:?}` is forbidden", kind));
+                }
             }
             StatementKind::StorageLive(..)
             | StatementKind::StorageDead(..)
diff --git a/compiler/rustc_data_structures/Cargo.toml b/compiler/rustc_data_structures/Cargo.toml
index 5afce15e26b..0366fb0a148 100644
--- a/compiler/rustc_data_structures/Cargo.toml
+++ b/compiler/rustc_data_structures/Cargo.toml
@@ -8,7 +8,7 @@ edition = "2021"
 [dependencies]
 arrayvec = { version = "0.7", default-features = false }
 bitflags = "1.2.1"
-cfg-if = "0.1.2"
+cfg-if = "1.0"
 ena = "0.14"
 indexmap = { version = "1.9.1" }
 jobserver_crate = { version = "0.1.13", package = "jobserver" }
@@ -21,7 +21,11 @@ rustc-hash = "1.1.0"
 rustc_index = { path = "../rustc_index", package = "rustc_index" }
 rustc_macros = { path = "../rustc_macros" }
 rustc_serialize = { path = "../rustc_serialize" }
-smallvec = { version = "1.8.1", features = ["const_generics", "union", "may_dangle"] }
+smallvec = { version = "1.8.1", features = [
+    "const_generics",
+    "union",
+    "may_dangle",
+] }
 stable_deref_trait = "1.0.0"
 stacker = "0.1.15"
 tempfile = "3.2"
diff --git a/compiler/rustc_data_structures/src/profiling.rs b/compiler/rustc_data_structures/src/profiling.rs
index 1d4014f05ac..16296b22489 100644
--- a/compiler/rustc_data_structures/src/profiling.rs
+++ b/compiler/rustc_data_structures/src/profiling.rs
@@ -205,10 +205,7 @@ impl SelfProfilerRef {
     /// VerboseTimingGuard returned from this call is dropped. In addition to recording
     /// a measureme event, "verbose" generic activities also print a timing entry to
     /// stderr if the compiler is invoked with -Ztime-passes.
-    pub fn verbose_generic_activity<'a>(
-        &'a self,
-        event_label: &'static str,
-    ) -> VerboseTimingGuard<'a> {
+    pub fn verbose_generic_activity(&self, event_label: &'static str) -> VerboseTimingGuard<'_> {
         let message =
             if self.print_verbose_generic_activities { Some(event_label.to_owned()) } else { None };
 
@@ -216,11 +213,11 @@ impl SelfProfilerRef {
     }
 
     /// Like `verbose_generic_activity`, but with an extra arg.
-    pub fn verbose_generic_activity_with_arg<'a, A>(
-        &'a self,
+    pub fn verbose_generic_activity_with_arg<A>(
+        &self,
         event_label: &'static str,
         event_arg: A,
-    ) -> VerboseTimingGuard<'a>
+    ) -> VerboseTimingGuard<'_>
     where
         A: Borrow<str> + Into<String>,
     {
diff --git a/compiler/rustc_data_structures/src/stable_hasher.rs b/compiler/rustc_data_structures/src/stable_hasher.rs
index 1a728f82f00..ae4836645fa 100644
--- a/compiler/rustc_data_structures/src/stable_hasher.rs
+++ b/compiler/rustc_data_structures/src/stable_hasher.rs
@@ -223,7 +223,7 @@ pub trait ToStableHashKey<HCX> {
 /// stable across compilation session boundaries. More formally:
 ///
 /// ```txt
-/// Ord::cmp(a1, b1) == Ord:cmp(a2, b2)
+/// Ord::cmp(a1, b1) == Ord::cmp(a2, b2)
 ///    where a2 = decode(encode(a1, context1), context2)
 ///          b2 = decode(encode(b1, context1), context2)
 /// ```
diff --git a/compiler/rustc_data_structures/src/transitive_relation.rs b/compiler/rustc_data_structures/src/transitive_relation.rs
index cf616203842..1ff0d58df14 100644
--- a/compiler/rustc_data_structures/src/transitive_relation.rs
+++ b/compiler/rustc_data_structures/src/transitive_relation.rs
@@ -199,7 +199,7 @@ impl<T: Eq + Hash + Copy> TransitiveRelation<T> {
     /// Viewing the relation as a graph, computes the "mutual
     /// immediate postdominator" of a set of points (if one
     /// exists). See `postdom_upper_bound` for details.
-    pub fn mutual_immediate_postdominator<'a>(&'a self, mut mubs: Vec<T>) -> Option<T> {
+    pub fn mutual_immediate_postdominator(&self, mut mubs: Vec<T>) -> Option<T> {
         loop {
             match mubs.len() {
                 0 => return None,
diff --git a/compiler/rustc_data_structures/src/unord.rs b/compiler/rustc_data_structures/src/unord.rs
index c015f1232cd..14257e4d5c6 100644
--- a/compiler/rustc_data_structures/src/unord.rs
+++ b/compiler/rustc_data_structures/src/unord.rs
@@ -178,7 +178,7 @@ impl<V: Eq + Hash> UnordSet<V> {
     }
 
     #[inline]
-    pub fn items<'a>(&'a self) -> UnordItems<&'a V, impl Iterator<Item = &'a V>> {
+    pub fn items(&self) -> UnordItems<&V, impl Iterator<Item = &V>> {
         UnordItems(self.inner.iter())
     }
 
@@ -255,7 +255,7 @@ impl<K: Eq + Hash, V> UnordMap<K, V> {
     }
 
     #[inline]
-    pub fn items<'a>(&'a self) -> UnordItems<(&'a K, &'a V), impl Iterator<Item = (&'a K, &'a V)>> {
+    pub fn items(&self) -> UnordItems<(&K, &V), impl Iterator<Item = (&K, &V)>> {
         UnordItems(self.inner.iter())
     }
 
@@ -311,7 +311,7 @@ impl<V> UnordBag<V> {
     }
 
     #[inline]
-    pub fn items<'a>(&'a self) -> UnordItems<&'a V, impl Iterator<Item = &'a V>> {
+    pub fn items(&self) -> UnordItems<&V, impl Iterator<Item = &V>> {
         UnordItems(self.inner.iter())
     }
 
diff --git a/compiler/rustc_driver/src/lib.rs b/compiler/rustc_driver/src/lib.rs
index 711eed2b272..31e08c44d29 100644
--- a/compiler/rustc_driver/src/lib.rs
+++ b/compiler/rustc_driver/src/lib.rs
@@ -653,7 +653,7 @@ fn print_crate_info(
     for req in &sess.opts.prints {
         match *req {
             TargetList => {
-                let mut targets = rustc_target::spec::TARGETS.iter().copied().collect::<Vec<_>>();
+                let mut targets = rustc_target::spec::TARGETS.to_vec();
                 targets.sort_unstable();
                 println!("{}", targets.join("\n"));
             }
@@ -1199,10 +1199,13 @@ static DEFAULT_HOOK: LazyLock<Box<dyn Fn(&panic::PanicInfo<'_>) + Sync + Send +
             };
 
             // Invoke the default handler, which prints the actual panic message and optionally a backtrace
-            (*DEFAULT_HOOK)(info);
+            // Don't do this for `ExplicitBug`, which has an unhelpful message and backtrace.
+            if !info.payload().is::<rustc_errors::ExplicitBug>() {
+                (*DEFAULT_HOOK)(info);
 
-            // Separate the output with an empty line
-            eprintln!();
+                // Separate the output with an empty line
+                eprintln!();
+            }
 
             // Print the ICE message
             report_ice(info, BUG_REPORT_URL);
diff --git a/compiler/rustc_error_codes/src/error_codes.rs b/compiler/rustc_error_codes/src/error_codes.rs
index 4e149fc2b99..e6d26240e24 100644
--- a/compiler/rustc_error_codes/src/error_codes.rs
+++ b/compiler/rustc_error_codes/src/error_codes.rs
@@ -244,11 +244,14 @@ E0457: include_str!("./error_codes/E0457.md"),
 E0458: include_str!("./error_codes/E0458.md"),
 E0459: include_str!("./error_codes/E0459.md"),
 E0460: include_str!("./error_codes/E0460.md"),
+E0461: include_str!("./error_codes/E0461.md"),
+E0462: include_str!("./error_codes/E0462.md"),
 E0463: include_str!("./error_codes/E0463.md"),
 E0464: include_str!("./error_codes/E0464.md"),
 E0466: include_str!("./error_codes/E0466.md"),
 E0468: include_str!("./error_codes/E0468.md"),
 E0469: include_str!("./error_codes/E0469.md"),
+E0472: include_str!("./error_codes/E0472.md"),
 E0477: include_str!("./error_codes/E0477.md"),
 E0478: include_str!("./error_codes/E0478.md"),
 E0482: include_str!("./error_codes/E0482.md"),
@@ -593,13 +596,10 @@ E0791: include_str!("./error_codes/E0791.md"),
 //  E0421, // merged into 531
 //  E0427, // merged into 530
 //  E0456, // plugin `..` is not available for triple `..`
-    E0461, // couldn't find crate `..` with expected target triple ..
-    E0462, // found staticlib `..` instead of rlib or dylib
     E0465, // multiple .. candidates for `..` found
 //  E0467, // removed
 //  E0470, // removed
 //  E0471, // constant evaluation error (in pattern)
-    E0472, // llvm_asm! is unsupported on this target
 //  E0473, // dereference of reference outside its lifetime
 //  E0474, // captured variable `..` does not outlive the enclosing closure
 //  E0475, // index of slice outside its lifetime
diff --git a/compiler/rustc_error_codes/src/error_codes/E0461.md b/compiler/rustc_error_codes/src/error_codes/E0461.md
new file mode 100644
index 00000000000..33105c43ccf
--- /dev/null
+++ b/compiler/rustc_error_codes/src/error_codes/E0461.md
@@ -0,0 +1,30 @@
+Couldn't find crate `..` with expected target triple `..`.
+
+Example of erroneous code:
+
+`a.rs`
+```ignore (cannot-link-with-other-tests)
+#![crate_type = "lib"]
+
+fn foo() {}
+```
+
+`main.rs`
+```ignore (cannot-link-with-other-tests)
+extern crate a;
+
+fn main() {
+    a::foo();
+}
+```
+
+`a.rs` is then compiled with `--target powerpc-unknown-linux-gnu` and `b.rs`
+with `--target x86_64-unknown-linux-gnu`. `a.rs` is compiled into a binary
+format incompatible with `b.rs`; PowerPC and x86 are totally different
+architectures. This issue also extends to any difference in target triples, as
+`std` is operating-system specific.
+
+This error can be fixed by:
+ * Using [Cargo](../cargo/index.html), the Rust package manager, automatically
+   fixing this issue.
+ * Recompiling either crate so that they target a consistent target triple.
diff --git a/compiler/rustc_error_codes/src/error_codes/E0462.md b/compiler/rustc_error_codes/src/error_codes/E0462.md
new file mode 100644
index 00000000000..4509cc6fad2
--- /dev/null
+++ b/compiler/rustc_error_codes/src/error_codes/E0462.md
@@ -0,0 +1,32 @@
+Found `staticlib` `..` instead of `rlib` or `dylib`.
+
+Consider the following two files:
+
+`a.rs`
+```ignore (cannot-link-with-other-tests)
+#![crate_type = "staticlib"]
+
+fn foo() {}
+```
+
+`main.rs`
+```ignore (cannot-link-with-other-tests)
+extern crate a;
+
+fn main() {
+    a::foo();
+}
+```
+
+Crate `a` is compiled as a `staticlib`. A `staticlib` is a system-dependant
+library only intended for linking with non-Rust applications (C programs). Note
+that `staticlib`s include all upstream dependencies (`core`, `std`, other user
+dependencies, etc) which makes them significantly larger than `dylib`s:
+prefer `staticlib` for linking with C programs. Learn more about different
+`crate_type`s in [this section of the Reference](../reference/linkage.html).
+
+This error can be fixed by:
+ * Using [Cargo](../cargo/index.html), the Rust package manager, automatically
+   fixing this issue.
+ * Recompiling the crate as a `rlib` or `dylib`; formats suitable for Rust
+   linking.
diff --git a/compiler/rustc_error_codes/src/error_codes/E0472.md b/compiler/rustc_error_codes/src/error_codes/E0472.md
new file mode 100644
index 00000000000..0005cd41911
--- /dev/null
+++ b/compiler/rustc_error_codes/src/error_codes/E0472.md
@@ -0,0 +1,31 @@
+Inline assembly (`asm!`) is not supported on this target.
+
+Example of erroneous code:
+
+```ignore (cannot-change-target)
+// compile-flags: --target sparc64-unknown-linux-gnu
+#![no_std]
+
+use core::arch::asm;
+
+fn main() {
+    unsafe {
+        asm!(""); // error: inline assembly is not supported on this target
+    }
+}
+```
+
+The Rust compiler does not support inline assembly, with the `asm!` macro
+(previously `llvm_asm!`), for all targets. All Tier 1 targets do support this
+macro but support among Tier 2 and 3 targets is not guaranteed (even when they
+have `std` support). Note that this error is related to
+`error[E0658]: inline assembly is not stable yet on this architecture`, but
+distinct in that with `E0472` support is not planned or in progress.
+
+There is no way to easily fix this issue, however:
+ * Consider if you really need inline assembly, is there some other way to
+   achieve your goal (intrinsics, etc)?
+ * Consider writing your assembly externally, linking with it and calling it
+   from Rust.
+ * Consider contributing to <https://github.com/rust-lang/rust> and help
+   integrate support for your target!
diff --git a/compiler/rustc_error_messages/locales/en-US/lint.ftl b/compiler/rustc_error_messages/locales/en-US/lint.ftl
index 7e28f22c0ba..2eb409a5ddd 100644
--- a/compiler/rustc_error_messages/locales/en-US/lint.ftl
+++ b/compiler/rustc_error_messages/locales/en-US/lint.ftl
@@ -350,6 +350,9 @@ lint_builtin_mutable_transmutes =
 
 lint_builtin_unstable_features = unstable feature
 
+lint_ungated_async_fn_track_caller = `#[track_caller]` on async functions is a no-op
+     .label = this function will not propagate the caller location
+
 lint_builtin_unreachable_pub = unreachable `pub` {$what}
     .suggestion = consider restricting its visibility
     .help = or consider exporting it for use by other crates
diff --git a/compiler/rustc_error_messages/locales/en-US/parse.ftl b/compiler/rustc_error_messages/locales/en-US/parse.ftl
index b53550e5fd5..3401978caf5 100644
--- a/compiler/rustc_error_messages/locales/en-US/parse.ftl
+++ b/compiler/rustc_error_messages/locales/en-US/parse.ftl
@@ -365,3 +365,6 @@ parse_invalid_identifier_with_leading_number = expected identifier, found number
 
 parse_maybe_fn_typo_with_impl = you might have meant to write `impl` instead of `fn`
     .suggestion = replace `fn` with `impl` here
+
+parse_expected_fn_path_found_fn_keyword = expected identifier, found keyword `fn`
+    .suggestion = use `Fn` to refer to the trait
diff --git a/compiler/rustc_error_messages/src/lib.rs b/compiler/rustc_error_messages/src/lib.rs
index 25d0e736e59..37a51980a08 100644
--- a/compiler/rustc_error_messages/src/lib.rs
+++ b/compiler/rustc_error_messages/src/lib.rs
@@ -381,7 +381,7 @@ impl<S: Into<String>> From<S> for DiagnosticMessage {
     }
 }
 
-/// A workaround for "good path" ICEs when formatting types in disables lints.
+/// A workaround for "good path" ICEs when formatting types in disabled lints.
 ///
 /// Delays formatting until `.into(): DiagnosticMessage` is used.
 pub struct DelayDm<F>(pub F);
@@ -549,9 +549,7 @@ fn icu_locale_from_unic_langid(lang: LanguageIdentifier) -> Option<icu_locid::Lo
     icu_locid::Locale::try_from_bytes(lang.to_string().as_bytes()).ok()
 }
 
-pub fn fluent_value_from_str_list_sep_by_and<'source>(
-    l: Vec<Cow<'source, str>>,
-) -> FluentValue<'source> {
+pub fn fluent_value_from_str_list_sep_by_and(l: Vec<Cow<'_, str>>) -> FluentValue<'_> {
     // Fluent requires 'static value here for its AnyEq usages.
     #[derive(Clone, PartialEq, Debug)]
     struct FluentStrListSepByAnd(Vec<String>);
diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs
index 518b5ec10f8..b03352d5fec 100644
--- a/compiler/rustc_errors/src/lib.rs
+++ b/compiler/rustc_errors/src/lib.rs
@@ -1212,8 +1212,8 @@ impl HandlerInner {
         self.taught_diagnostics.insert(code.clone())
     }
 
-    fn force_print_diagnostic(&mut self, mut db: Diagnostic) {
-        self.emitter.emit_diagnostic(&mut db);
+    fn force_print_diagnostic(&mut self, db: Diagnostic) {
+        self.emitter.emit_diagnostic(&db);
     }
 
     /// Emit all stashed diagnostics.
diff --git a/compiler/rustc_expand/src/build.rs b/compiler/rustc_expand/src/build.rs
index ef50efb8125..406e1569a6f 100644
--- a/compiler/rustc_expand/src/build.rs
+++ b/compiler/rustc_expand/src/build.rs
@@ -626,7 +626,7 @@ impl<'a> ExtCtxt<'a> {
 
     // Builds `#[name = val]`.
     //
-    // Note: `span` is used for both the identifer and the value.
+    // Note: `span` is used for both the identifier and the value.
     pub fn attr_name_value_str(&self, name: Symbol, val: Symbol, span: Span) -> ast::Attribute {
         let g = &self.sess.parse_sess.attr_id_generator;
         attr::mk_attr_name_value_str(g, ast::AttrStyle::Outer, name, val, span)
diff --git a/compiler/rustc_expand/src/mbe/diagnostics.rs b/compiler/rustc_expand/src/mbe/diagnostics.rs
index 197f056917f..40aa64d9d40 100644
--- a/compiler/rustc_expand/src/mbe/diagnostics.rs
+++ b/compiler/rustc_expand/src/mbe/diagnostics.rs
@@ -43,7 +43,7 @@ pub(super) fn failed_to_match_macro<'cx>(
         return result;
     }
 
-    let Some((token, label, remaining_matcher)) = tracker.best_failure else {
+    let Some(BestFailure { token, msg: label, remaining_matcher, .. }) = tracker.best_failure else {
         return DummyResult::any(sp);
     };
 
@@ -95,11 +95,24 @@ struct CollectTrackerAndEmitter<'a, 'cx, 'matcher> {
     cx: &'a mut ExtCtxt<'cx>,
     remaining_matcher: Option<&'matcher MatcherLoc>,
     /// Which arm's failure should we report? (the one furthest along)
-    best_failure: Option<(Token, &'static str, MatcherLoc)>,
+    best_failure: Option<BestFailure>,
     root_span: Span,
     result: Option<Box<dyn MacResult + 'cx>>,
 }
 
+struct BestFailure {
+    token: Token,
+    position_in_tokenstream: usize,
+    msg: &'static str,
+    remaining_matcher: MatcherLoc,
+}
+
+impl BestFailure {
+    fn is_better_position(&self, position: usize) -> bool {
+        position > self.position_in_tokenstream
+    }
+}
+
 impl<'a, 'cx, 'matcher> Tracker<'matcher> for CollectTrackerAndEmitter<'a, 'cx, 'matcher> {
     fn before_match_loc(&mut self, parser: &TtParser, matcher: &'matcher MatcherLoc) {
         if self.remaining_matcher.is_none()
@@ -119,18 +132,25 @@ impl<'a, 'cx, 'matcher> Tracker<'matcher> for CollectTrackerAndEmitter<'a, 'cx,
                     "should not collect detailed info for successful macro match",
                 );
             }
-            Failure(token, msg) => match self.best_failure {
-                Some((ref best_token, _, _)) if best_token.span.lo() >= token.span.lo() => {}
-                _ => {
-                    self.best_failure = Some((
-                        token.clone(),
+            Failure(token, approx_position, msg) => {
+                debug!(?token, ?msg, "a new failure of an arm");
+
+                if self
+                    .best_failure
+                    .as_ref()
+                    .map_or(true, |failure| failure.is_better_position(*approx_position))
+                {
+                    self.best_failure = Some(BestFailure {
+                        token: token.clone(),
+                        position_in_tokenstream: *approx_position,
                         msg,
-                        self.remaining_matcher
+                        remaining_matcher: self
+                            .remaining_matcher
                             .expect("must have collected matcher already")
                             .clone(),
-                    ))
+                    })
                 }
-            },
+            }
             Error(err_sp, msg) => {
                 let span = err_sp.substitute_dummy(self.root_span);
                 self.cx.struct_span_err(span, msg).emit();
diff --git a/compiler/rustc_expand/src/mbe/macro_parser.rs b/compiler/rustc_expand/src/mbe/macro_parser.rs
index d161868edce..df1c1834c1d 100644
--- a/compiler/rustc_expand/src/mbe/macro_parser.rs
+++ b/compiler/rustc_expand/src/mbe/macro_parser.rs
@@ -310,7 +310,8 @@ pub(crate) enum ParseResult<T> {
     Success(T),
     /// Arm failed to match. If the second parameter is `token::Eof`, it indicates an unexpected
     /// end of macro invocation. Otherwise, it indicates that no rules expected the given token.
-    Failure(Token, &'static str),
+    /// The usize is the approximate position of the token in the input token stream.
+    Failure(Token, usize, &'static str),
     /// Fatal error (malformed macro?). Abort compilation.
     Error(rustc_span::Span, String),
     ErrorReported(ErrorGuaranteed),
@@ -455,6 +456,7 @@ impl TtParser {
         &mut self,
         matcher: &'matcher [MatcherLoc],
         token: &Token,
+        approx_position: usize,
         track: &mut T,
     ) -> Option<NamedParseResult> {
         // Matcher positions that would be valid if the macro invocation was over now. Only
@@ -598,6 +600,7 @@ impl TtParser {
                         token::Eof,
                         if token.span.is_dummy() { token.span } else { token.span.shrink_to_hi() },
                     ),
+                    approx_position,
                     "missing tokens in macro arguments",
                 ),
             })
@@ -627,7 +630,12 @@ impl TtParser {
 
             // Process `cur_mps` until either we have finished the input or we need to get some
             // parsing from the black-box parser done.
-            let res = self.parse_tt_inner(matcher, &parser.token, track);
+            let res = self.parse_tt_inner(
+                matcher,
+                &parser.token,
+                parser.approx_token_stream_pos(),
+                track,
+            );
             if let Some(res) = res {
                 return res;
             }
@@ -642,6 +650,7 @@ impl TtParser {
                     // parser: syntax error.
                     return Failure(
                         parser.token.clone(),
+                        parser.approx_token_stream_pos(),
                         "no rules expected this token in macro call",
                     );
                 }
diff --git a/compiler/rustc_expand/src/mbe/macro_rules.rs b/compiler/rustc_expand/src/mbe/macro_rules.rs
index 320c533a66e..fbb806fe81b 100644
--- a/compiler/rustc_expand/src/mbe/macro_rules.rs
+++ b/compiler/rustc_expand/src/mbe/macro_rules.rs
@@ -326,8 +326,8 @@ pub(super) fn try_match_macro<'matcher, T: Tracker<'matcher>>(
 
                 return Ok((i, named_matches));
             }
-            Failure(_, _) => {
-                trace!("Failed to match arm, trying the next one");
+            Failure(_, reached_position, _) => {
+                trace!(%reached_position, "Failed to match arm, trying the next one");
                 // Try the next arm.
             }
             Error(_, _) => {
@@ -432,7 +432,7 @@ pub fn compile_declarative_macro(
     let argument_map =
         match tt_parser.parse_tt(&mut Cow::Owned(parser), &argument_gram, &mut NoopTracker) {
             Success(m) => m,
-            Failure(token, msg) => {
+            Failure(token, _, msg) => {
                 let s = parse_failure_msg(&token);
                 let sp = token.span.substitute_dummy(def.span);
                 let mut err = sess.parse_sess.span_diagnostic.struct_span_err(sp, &s);
@@ -1166,11 +1166,7 @@ fn check_matcher_core<'tt>(
                                     err.note(&format!(
                                         "{}{} or {}",
                                         msg,
-                                        ts[..ts.len() - 1]
-                                            .iter()
-                                            .copied()
-                                            .collect::<Vec<_>>()
-                                            .join(", "),
+                                        ts[..ts.len() - 1].to_vec().join(", "),
                                         ts[ts.len() - 1],
                                     ));
                                 }
diff --git a/compiler/rustc_expand/src/mbe/quoted.rs b/compiler/rustc_expand/src/mbe/quoted.rs
index ee17d54f629..878284f5928 100644
--- a/compiler/rustc_expand/src/mbe/quoted.rs
+++ b/compiler/rustc_expand/src/mbe/quoted.rs
@@ -356,7 +356,7 @@ fn parse_sep_and_kleene_op(
 // `$$` or a meta-variable is the lhs of a macro but shouldn't.
 //
 // For example, `macro_rules! foo { ( ${length()} ) => {} }`
-fn span_dollar_dollar_or_metavar_in_the_lhs_err<'sess>(sess: &'sess ParseSess, token: &Token) {
+fn span_dollar_dollar_or_metavar_in_the_lhs_err(sess: &ParseSess, token: &Token) {
     sess.span_diagnostic
         .span_err(token.span, &format!("unexpected token: {}", pprust::token_to_string(token)));
     sess.span_diagnostic.span_note_without_error(
diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs
index a616dd70f8e..060306d88be 100644
--- a/compiler/rustc_feature/src/active.rs
+++ b/compiler/rustc_feature/src/active.rs
@@ -160,6 +160,8 @@ declare_features! (
     (active, intrinsics, "1.0.0", None, None),
     /// Allows using `#[lang = ".."]` attribute for linking items to special compiler logic.
     (active, lang_items, "1.0.0", None, None),
+    /// Allows the `multiple_supertrait_upcastable` lint.
+    (active, multiple_supertrait_upcastable, "CURRENT_RUSTC_VERSION", None, None),
     /// Allows using `#[omit_gdb_pretty_printer_section]`.
     (active, omit_gdb_pretty_printer_section, "1.5.0", None, None),
     /// Allows using `#[prelude_import]` on glob `use` items.
diff --git a/compiler/rustc_graphviz/src/lib.rs b/compiler/rustc_graphviz/src/lib.rs
index 1f8268cc17c..434f0a53b78 100644
--- a/compiler/rustc_graphviz/src/lib.rs
+++ b/compiler/rustc_graphviz/src/lib.rs
@@ -164,7 +164,7 @@
 //!     fn node_id(&'a self, n: &Nd) -> dot::Id<'a> {
 //!         dot::Id::new(format!("N{}", n)).unwrap()
 //!     }
-//!     fn node_label<'b>(&'b self, n: &Nd) -> dot::LabelText<'b> {
+//!     fn node_label(&self, n: &Nd) -> dot::LabelText<'_> {
 //!         dot::LabelText::LabelStr(self.nodes[*n].into())
 //!     }
 //!     fn edge_label<'b>(&'b self, _: &Ed) -> dot::LabelText<'b> {
diff --git a/compiler/rustc_hir/src/lang_items.rs b/compiler/rustc_hir/src/lang_items.rs
index 038509031b1..3474fab34f0 100644
--- a/compiler/rustc_hir/src/lang_items.rs
+++ b/compiler/rustc_hir/src/lang_items.rs
@@ -146,7 +146,7 @@ pub fn extract(attrs: &[ast::Attribute]) -> Option<(Symbol, Span)> {
 }
 
 language_item_table! {
-//  Variant name,            Name,                     Method name,                Target                  Generic requirements;
+//  Variant name,            Name,                     Getter method name,         Target                  Generic requirements;
     Sized,                   sym::sized,               sized_trait,                Target::Trait,          GenericRequirement::Exact(0);
     Unsize,                  sym::unsize,              unsize_trait,               Target::Trait,          GenericRequirement::Minimum(1);
     /// Trait injected by `#[derive(PartialEq)]`, (i.e. "Partial EQ").
@@ -232,6 +232,7 @@ language_item_table! {
     // is required to define it somewhere. Additionally, there are restrictions on crates that use
     // a weak lang item, but do not have it defined.
     Panic,                   sym::panic,               panic_fn,                   Target::Fn,             GenericRequirement::Exact(0);
+    PanicNounwind,           sym::panic_nounwind,      panic_nounwind,             Target::Fn,             GenericRequirement::Exact(0);
     PanicFmt,                sym::panic_fmt,           panic_fmt,                  Target::Fn,             GenericRequirement::None;
     PanicDisplay,            sym::panic_display,       panic_display,              Target::Fn,             GenericRequirement::None;
     ConstPanicFmt,           sym::const_panic_fmt,     const_panic_fmt,            Target::Fn,             GenericRequirement::None;
@@ -239,7 +240,7 @@ language_item_table! {
     PanicInfo,               sym::panic_info,          panic_info,                 Target::Struct,         GenericRequirement::None;
     PanicLocation,           sym::panic_location,      panic_location,             Target::Struct,         GenericRequirement::None;
     PanicImpl,               sym::panic_impl,          panic_impl,                 Target::Fn,             GenericRequirement::None;
-    PanicNoUnwind,           sym::panic_no_unwind,     panic_no_unwind,            Target::Fn,             GenericRequirement::Exact(0);
+    PanicCannotUnwind,       sym::panic_cannot_unwind, panic_cannot_unwind,        Target::Fn,             GenericRequirement::Exact(0);
     /// libstd panic entry point. Necessary for const eval to be able to catch it
     BeginPanic,              sym::begin_panic,         begin_panic_fn,             Target::Fn,             GenericRequirement::None;
 
diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs
index c29a3afd7fb..6f0c5d36a5f 100644
--- a/compiler/rustc_hir_analysis/src/astconv/mod.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs
@@ -2626,7 +2626,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                 let e = self
                     .tcx()
                     .sess
-                    .delay_span_bug(path.span, "path with `Res:Err` but no error emitted");
+                    .delay_span_bug(path.span, "path with `Res::Err` but no error emitted");
                 self.set_tainted_by_errors(e);
                 self.tcx().ty_error_with_guaranteed(e)
             }
diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs
index eee0ba2e5ed..28cd18bbb8e 100644
--- a/compiler/rustc_hir_analysis/src/check/check.rs
+++ b/compiler/rustc_hir_analysis/src/check/check.rs
@@ -1,8 +1,8 @@
 use crate::check::intrinsicck::InlineAsmCtxt;
 use crate::errors::LinkageType;
 
-use super::compare_method::check_type_bounds;
-use super::compare_method::{compare_impl_method, compare_ty_impl};
+use super::compare_impl_item::check_type_bounds;
+use super::compare_impl_item::{compare_impl_method, compare_impl_ty};
 use super::*;
 use rustc_attr as attr;
 use rustc_errors::{Applicability, ErrorGuaranteed, MultiSpan};
@@ -162,7 +162,7 @@ fn check_union_fields(tcx: TyCtxt<'_>, span: Span, item_def_id: LocalDefId) -> b
 }
 
 /// Check that a `static` is inhabited.
-fn check_static_inhabited<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) {
+fn check_static_inhabited(tcx: TyCtxt<'_>, def_id: LocalDefId) {
     // Make sure statics are inhabited.
     // Other parts of the compiler assume that there are no uninhabited places. In principle it
     // would be enough to check this for `extern` statics, as statics with an initializer will
@@ -212,7 +212,7 @@ fn check_static_inhabited<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) {
 
 /// Checks that an opaque type does not contain cycles and does not use `Self` or `T::Foo`
 /// projections that would result in "inheriting lifetimes".
-fn check_opaque<'tcx>(tcx: TyCtxt<'tcx>, id: hir::ItemId) {
+fn check_opaque(tcx: TyCtxt<'_>, id: hir::ItemId) {
     let item = tcx.hir().item(id);
     let hir::ItemKind::OpaqueTy(hir::OpaqueTy { origin, .. }) = item.kind else {
         tcx.sess.delay_span_bug(tcx.hir().span(id.hir_id()), "expected opaque item");
@@ -245,8 +245,8 @@ fn check_opaque<'tcx>(tcx: TyCtxt<'tcx>, id: hir::ItemId) {
 /// Checks that an opaque type does not use `Self` or `T::Foo` projections that would result
 /// in "inheriting lifetimes".
 #[instrument(level = "debug", skip(tcx, span))]
-pub(super) fn check_opaque_for_inheriting_lifetimes<'tcx>(
-    tcx: TyCtxt<'tcx>,
+pub(super) fn check_opaque_for_inheriting_lifetimes(
+    tcx: TyCtxt<'_>,
     def_id: LocalDefId,
     span: Span,
 ) {
@@ -468,7 +468,7 @@ fn check_opaque_meets_bounds<'tcx>(
         // Can have different predicates to their defining use
         hir::OpaqueTyOrigin::TyAlias => {
             let outlives_environment = OutlivesEnvironment::new(param_env);
-            infcx.check_region_obligations_and_report_errors(
+            let _ = infcx.check_region_obligations_and_report_errors(
                 defining_use_anchor,
                 &outlives_environment,
             );
@@ -496,7 +496,7 @@ fn is_enum_of_nonnullable_ptr<'tcx>(
     matches!(field.ty(tcx, substs).kind(), ty::FnPtr(..) | ty::Ref(..))
 }
 
-fn check_static_linkage<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) {
+fn check_static_linkage(tcx: TyCtxt<'_>, def_id: LocalDefId) {
     if tcx.codegen_fn_attrs(def_id).import_linkage.is_some() {
         if match tcx.type_of(def_id).kind() {
             ty::RawPtr(_) => false,
@@ -508,7 +508,7 @@ fn check_static_linkage<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) {
     }
 }
 
-fn check_item_type<'tcx>(tcx: TyCtxt<'tcx>, id: hir::ItemId) {
+fn check_item_type(tcx: TyCtxt<'_>, id: hir::ItemId) {
     debug!(
         "check_item_type(it.def_id={:?}, it.name={})",
         id.owner_id,
@@ -774,7 +774,7 @@ fn check_impl_items_against_trait<'tcx>(
         let impl_item_full = tcx.hir().impl_item(impl_item.id);
         match impl_item_full.kind {
             hir::ImplItemKind::Const(..) => {
-                let _ = tcx.compare_assoc_const_impl_item_with_trait_item((
+                let _ = tcx.compare_impl_const((
                     impl_item.id.owner_id.def_id,
                     ty_impl_item.trait_item_def_id.unwrap(),
                 ));
@@ -791,7 +791,7 @@ fn check_impl_items_against_trait<'tcx>(
             }
             hir::ImplItemKind::Type(impl_ty) => {
                 let opt_trait_span = tcx.hir().span_if_local(ty_trait_item.def_id);
-                compare_ty_impl(
+                compare_impl_ty(
                     tcx,
                     &ty_impl_item,
                     impl_ty.span,
@@ -1060,10 +1060,8 @@ pub(super) fn check_transparent<'tcx>(tcx: TyCtxt<'tcx>, adt: ty::AdtDef<'tcx>)
 
     if adt.variants().len() != 1 {
         bad_variant_count(tcx, adt, tcx.def_span(adt.did()), adt.did());
-        if adt.variants().is_empty() {
-            // Don't bother checking the fields. No variants (and thus no fields) exist.
-            return;
-        }
+        // Don't bother checking the fields.
+        return;
     }
 
     // For each field, figure out if it's known to be a ZST and align(1), with "known"
@@ -1160,7 +1158,7 @@ pub(super) fn check_transparent<'tcx>(tcx: TyCtxt<'tcx>, adt: ty::AdtDef<'tcx>)
 }
 
 #[allow(trivial_numeric_casts)]
-fn check_enum<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) {
+fn check_enum(tcx: TyCtxt<'_>, def_id: LocalDefId) {
     let def = tcx.adt_def(def_id);
     def.destructor(tcx); // force the destructor to be evaluated
 
diff --git a/compiler/rustc_hir_analysis/src/check/compare_method.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
index cddd307c13d..a767338ab85 100644
--- a/compiler/rustc_hir_analysis/src/check/compare_method.rs
+++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
@@ -34,7 +34,7 @@ use std::iter;
 /// - `impl_m_span`: span to use for reporting errors
 /// - `trait_m`: the method in the trait
 /// - `impl_trait_ref`: the TraitRef corresponding to the trait implementation
-pub(crate) fn compare_impl_method<'tcx>(
+pub(super) fn compare_impl_method<'tcx>(
     tcx: TyCtxt<'tcx>,
     impl_m: &ty::AssocItem,
     trait_m: &ty::AssocItem,
@@ -71,7 +71,7 @@ pub(crate) fn compare_impl_method<'tcx>(
         return;
     }
 
-    if let Err(_) = compare_predicate_entailment(
+    if let Err(_) = compare_method_predicate_entailment(
         tcx,
         impl_m,
         impl_m_span,
@@ -150,7 +150,7 @@ pub(crate) fn compare_impl_method<'tcx>(
 /// Finally we register each of these predicates as an obligation and check that
 /// they hold.
 #[instrument(level = "debug", skip(tcx, impl_m_span, impl_trait_ref))]
-fn compare_predicate_entailment<'tcx>(
+fn compare_method_predicate_entailment<'tcx>(
     tcx: TyCtxt<'tcx>,
     impl_m: &ty::AssocItem,
     impl_m_span: Span,
@@ -337,7 +337,7 @@ fn compare_predicate_entailment<'tcx>(
     if !errors.is_empty() {
         match check_implied_wf {
             CheckImpliedWfMode::Check => {
-                return compare_predicate_entailment(
+                return compare_method_predicate_entailment(
                     tcx,
                     impl_m,
                     impl_m_span,
@@ -374,7 +374,7 @@ fn compare_predicate_entailment<'tcx>(
         // becomes a hard error (i.e. ideally we'd just call `resolve_regions_and_report_errors`
         match check_implied_wf {
             CheckImpliedWfMode::Check => {
-                return compare_predicate_entailment(
+                return compare_method_predicate_entailment(
                     tcx,
                     impl_m,
                     impl_m_span,
@@ -407,7 +407,7 @@ enum CheckImpliedWfMode {
     /// re-check with `Skip`, and emit a lint if it succeeds.
     Check,
     /// Skips checking implied well-formedness of the impl method, but will emit
-    /// a lint if the `compare_predicate_entailment` succeeded. This means that
+    /// a lint if the `compare_method_predicate_entailment` succeeded. This means that
     /// the reason that we had failed earlier during `Check` was due to the impl
     /// having stronger requirements than the trait.
     Skip,
@@ -441,8 +441,41 @@ fn compare_asyncness<'tcx>(
     Ok(())
 }
 
+/// Given a method def-id in an impl, compare the method signature of the impl
+/// against the trait that it's implementing. In doing so, infer the hidden types
+/// that this method's signature provides to satisfy each return-position `impl Trait`
+/// in the trait signature.
+///
+/// The method is also responsible for making sure that the hidden types for each
+/// RPITIT actually satisfy the bounds of the `impl Trait`, i.e. that if we infer
+/// `impl Trait = Foo`, that `Foo: Trait` holds.
+///
+/// For example, given the sample code:
+///
+/// ```
+/// #![feature(return_position_impl_trait_in_trait)]
+///
+/// use std::ops::Deref;
+///
+/// trait Foo {
+///     fn bar() -> impl Deref<Target = impl Sized>;
+///              // ^- RPITIT #1        ^- RPITIT #2
+/// }
+///
+/// impl Foo for () {
+///     fn bar() -> Box<String> { Box::new(String::new()) }
+/// }
+/// ```
+///
+/// The hidden types for the RPITITs in `bar` would be inferred to:
+///     * `impl Deref` (RPITIT #1) = `Box<String>`
+///     * `impl Sized` (RPITIT #2) = `String`
+///
+/// The relationship between these two types is straightforward in this case, but
+/// may be more tenuously connected via other `impl`s and normalization rules for
+/// cases of more complicated nested RPITITs.
 #[instrument(skip(tcx), level = "debug", ret)]
-pub fn collect_trait_impl_trait_tys<'tcx>(
+pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
     tcx: TyCtxt<'tcx>,
     def_id: DefId,
 ) -> Result<&'tcx FxHashMap<DefId, Ty<'tcx>>, ErrorGuaranteed> {
@@ -550,13 +583,13 @@ pub fn collect_trait_impl_trait_tys<'tcx>(
     // Unify the whole function signature. We need to do this to fully infer
     // the lifetimes of the return type, but do this after unifying just the
     // return types, since we want to avoid duplicating errors from
-    // `compare_predicate_entailment`.
+    // `compare_method_predicate_entailment`.
     match ocx.eq(&cause, param_env, trait_fty, impl_fty) {
         Ok(()) => {}
         Err(terr) => {
-            // This function gets called during `compare_predicate_entailment` when normalizing a
+            // This function gets called during `compare_method_predicate_entailment` when normalizing a
             // signature that contains RPITIT. When the method signatures don't match, we have to
-            // emit an error now because `compare_predicate_entailment` will not report the error
+            // emit an error now because `compare_method_predicate_entailment` will not report the error
             // when normalization fails.
             let emitted = report_trait_method_mismatch(
                 infcx,
@@ -589,7 +622,7 @@ pub fn collect_trait_impl_trait_tys<'tcx>(
     infcx.check_region_obligations_and_report_errors(
         impl_m.def_id.expect_local(),
         &outlives_environment,
-    );
+    )?;
 
     let mut collected_tys = FxHashMap::default();
     for (def_id, (ty, substs)) in collector.types {
@@ -1516,9 +1549,9 @@ fn compare_generic_param_kinds<'tcx>(
     Ok(())
 }
 
-/// Use `tcx.compare_assoc_const_impl_item_with_trait_item` instead
-pub(crate) fn raw_compare_const_impl<'tcx>(
-    tcx: TyCtxt<'tcx>,
+/// Use `tcx.compare_impl_const` instead
+pub(super) fn compare_impl_const_raw(
+    tcx: TyCtxt<'_>,
     (impl_const_item_def, trait_const_item_def): (LocalDefId, DefId),
 ) -> Result<(), ErrorGuaranteed> {
     let impl_const_item = tcx.associated_item(impl_const_item_def);
@@ -1617,13 +1650,13 @@ pub(crate) fn raw_compare_const_impl<'tcx>(
         return Err(infcx.err_ctxt().report_fulfillment_errors(&errors, None));
     }
 
-    // FIXME return `ErrorReported` if region obligations error?
     let outlives_environment = OutlivesEnvironment::new(param_env);
-    infcx.check_region_obligations_and_report_errors(impl_const_item_def, &outlives_environment);
+    infcx.check_region_obligations_and_report_errors(impl_const_item_def, &outlives_environment)?;
+
     Ok(())
 }
 
-pub(crate) fn compare_ty_impl<'tcx>(
+pub(super) fn compare_impl_ty<'tcx>(
     tcx: TyCtxt<'tcx>,
     impl_ty: &ty::AssocItem,
     impl_ty_span: Span,
@@ -1645,7 +1678,7 @@ pub(crate) fn compare_ty_impl<'tcx>(
     })();
 }
 
-/// The equivalent of [compare_predicate_entailment], but for associated types
+/// The equivalent of [compare_method_predicate_entailment], but for associated types
 /// instead of associated functions.
 fn compare_type_predicate_entailment<'tcx>(
     tcx: TyCtxt<'tcx>,
@@ -1730,7 +1763,7 @@ fn compare_type_predicate_entailment<'tcx>(
     infcx.check_region_obligations_and_report_errors(
         impl_ty.def_id.expect_local(),
         &outlives_environment,
-    );
+    )?;
 
     Ok(())
 }
@@ -1749,7 +1782,7 @@ fn compare_type_predicate_entailment<'tcx>(
 /// from the impl could be overridden). We also can't normalize generic
 /// associated types (yet) because they contain bound parameters.
 #[instrument(level = "debug", skip(tcx))]
-pub fn check_type_bounds<'tcx>(
+pub(super) fn check_type_bounds<'tcx>(
     tcx: TyCtxt<'tcx>,
     trait_ty: &ty::AssocItem,
     impl_ty: &ty::AssocItem,
@@ -1944,7 +1977,7 @@ pub fn check_type_bounds<'tcx>(
     infcx.check_region_obligations_and_report_errors(
         impl_ty.def_id.expect_local(),
         &outlives_environment,
-    );
+    )?;
 
     let constraints = infcx.inner.borrow_mut().opaque_type_storage.take_opaque_types();
     for (key, value) in constraints {
diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs
index 69e54b41d4c..598dc2dca5c 100644
--- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs
+++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs
@@ -75,7 +75,7 @@ pub fn intrinsic_operation_unsafety(tcx: TyCtxt<'_>, intrinsic_id: DefId) -> hir
         sym::abort
         | sym::assert_inhabited
         | sym::assert_zero_valid
-        | sym::assert_uninit_valid
+        | sym::assert_mem_uninitialized_valid
         | sym::size_of
         | sym::min_align_of
         | sym::needs_drop
@@ -193,9 +193,9 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
             }
             sym::rustc_peek => (1, vec![param(0)], param(0)),
             sym::caller_location => (0, vec![], tcx.caller_location_ty()),
-            sym::assert_inhabited | sym::assert_zero_valid | sym::assert_uninit_valid => {
-                (1, Vec::new(), tcx.mk_unit())
-            }
+            sym::assert_inhabited
+            | sym::assert_zero_valid
+            | sym::assert_mem_uninitialized_valid => (1, Vec::new(), tcx.mk_unit()),
             sym::forget => (1, vec![param(0)], tcx.mk_unit()),
             sym::transmute => (2, vec![param(0)], param(1)),
             sym::prefetch_read_data
diff --git a/compiler/rustc_hir_analysis/src/check/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs
index 57f0cae12bb..382c3f52945 100644
--- a/compiler/rustc_hir_analysis/src/check/mod.rs
+++ b/compiler/rustc_hir_analysis/src/check/mod.rs
@@ -63,7 +63,7 @@ a type parameter).
 */
 
 mod check;
-mod compare_method;
+mod compare_impl_item;
 pub mod dropck;
 pub mod intrinsic;
 pub mod intrinsicck;
@@ -94,7 +94,7 @@ use std::num::NonZeroU32;
 use crate::require_c_abi_if_c_variadic;
 use crate::util::common::indenter;
 
-use self::compare_method::collect_trait_impl_trait_tys;
+use self::compare_impl_item::collect_return_position_impl_trait_in_trait_tys;
 use self::region::region_scope_tree;
 
 pub fn provide(providers: &mut Providers) {
@@ -103,8 +103,8 @@ pub fn provide(providers: &mut Providers) {
         adt_destructor,
         check_mod_item_types,
         region_scope_tree,
-        collect_trait_impl_trait_tys,
-        compare_assoc_const_impl_item_with_trait_item: compare_method::raw_compare_const_impl,
+        collect_return_position_impl_trait_in_trait_tys,
+        compare_impl_const: compare_impl_item::compare_impl_const_raw,
         ..*providers
     };
 }
@@ -115,10 +115,10 @@ fn adt_destructor(tcx: TyCtxt<'_>, def_id: DefId) -> Option<ty::Destructor> {
 
 /// Given a `DefId` for an opaque type in return position, find its parent item's return
 /// expressions.
-fn get_owner_return_paths<'tcx>(
-    tcx: TyCtxt<'tcx>,
+fn get_owner_return_paths(
+    tcx: TyCtxt<'_>,
     def_id: LocalDefId,
-) -> Option<(LocalDefId, ReturnsVisitor<'tcx>)> {
+) -> Option<(LocalDefId, ReturnsVisitor<'_>)> {
     let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
     let parent_id = tcx.hir().get_parent_item(hir_id).def_id;
     tcx.hir().find_by_def_id(parent_id).and_then(|node| node.body_id()).map(|body_id| {
diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
index 94d333c336e..6cb899f5176 100644
--- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs
+++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
@@ -115,7 +115,7 @@ pub(super) fn enter_wf_checking_ctxt<'tcx, F>(
     let outlives_environment =
         OutlivesEnvironment::with_bounds(param_env, Some(infcx), implied_bounds);
 
-    infcx.check_region_obligations_and_report_errors(body_def_id, &outlives_environment);
+    let _ = infcx.check_region_obligations_and_report_errors(body_def_id, &outlives_environment);
 }
 
 fn check_well_formed(tcx: TyCtxt<'_>, def_id: hir::OwnerId) {
@@ -410,10 +410,7 @@ fn check_gat_where_clauses(tcx: TyCtxt<'_>, associated_items: &[hir::TraitItemRe
                             tcx,
                             param_env,
                             item_hir_id,
-                            tcx.explicit_item_bounds(item_def_id)
-                                .iter()
-                                .copied()
-                                .collect::<Vec<_>>(),
+                            tcx.explicit_item_bounds(item_def_id).to_vec(),
                             &FxIndexSet::default(),
                             gat_def_id.def_id,
                             gat_generics,
@@ -1673,7 +1670,7 @@ fn check_method_receiver<'tcx>(
     }
 }
 
-fn e0307<'tcx>(tcx: TyCtxt<'tcx>, span: Span, receiver_ty: Ty<'_>) {
+fn e0307(tcx: TyCtxt<'_>, span: Span, receiver_ty: Ty<'_>) {
     struct_span_err!(
         tcx.sess.diagnostic(),
         span,
diff --git a/compiler/rustc_hir_analysis/src/coherence/builtin.rs b/compiler/rustc_hir_analysis/src/coherence/builtin.rs
index 193ecdb1678..bfedf63da97 100644
--- a/compiler/rustc_hir_analysis/src/coherence/builtin.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/builtin.rs
@@ -171,7 +171,7 @@ fn visit_implementation_of_copy(tcx: TyCtxt<'_>, impl_did: LocalDefId) {
     }
 }
 
-fn visit_implementation_of_coerce_unsized<'tcx>(tcx: TyCtxt<'tcx>, impl_did: LocalDefId) {
+fn visit_implementation_of_coerce_unsized(tcx: TyCtxt<'_>, impl_did: LocalDefId) {
     debug!("visit_implementation_of_coerce_unsized: impl_did={:?}", impl_did);
 
     // Just compute this for the side-effects, in particular reporting
@@ -181,7 +181,7 @@ fn visit_implementation_of_coerce_unsized<'tcx>(tcx: TyCtxt<'tcx>, impl_did: Loc
     tcx.at(span).coerce_unsized_info(impl_did);
 }
 
-fn visit_implementation_of_dispatch_from_dyn<'tcx>(tcx: TyCtxt<'tcx>, impl_did: LocalDefId) {
+fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: LocalDefId) {
     debug!("visit_implementation_of_dispatch_from_dyn: impl_did={:?}", impl_did);
 
     let impl_hir_id = tcx.hir().local_def_id_to_hir_id(impl_did);
@@ -325,7 +325,7 @@ fn visit_implementation_of_dispatch_from_dyn<'tcx>(tcx: TyCtxt<'tcx>, impl_did:
 
                 // Finally, resolve all regions.
                 let outlives_env = OutlivesEnvironment::new(param_env);
-                infcx.check_region_obligations_and_report_errors(impl_did, &outlives_env);
+                let _ = infcx.check_region_obligations_and_report_errors(impl_did, &outlives_env);
             }
         }
         _ => {
@@ -565,7 +565,7 @@ pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: DefId) -> CoerceUn
 
     // Finally, resolve all regions.
     let outlives_env = OutlivesEnvironment::new(param_env);
-    infcx.check_region_obligations_and_report_errors(impl_did, &outlives_env);
+    let _ = infcx.check_region_obligations_and_report_errors(impl_did, &outlives_env);
 
     CoerceUnsizedInfo { custom_kind: kind }
 }
diff --git a/compiler/rustc_hir_analysis/src/coherence/orphan.rs b/compiler/rustc_hir_analysis/src/coherence/orphan.rs
index cc5114dba5e..c6d4aeefc80 100644
--- a/compiler/rustc_hir_analysis/src/coherence/orphan.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/orphan.rs
@@ -184,11 +184,19 @@ fn emit_orphan_check_error<'tcx>(
                     ty::Adt(def, _) => tcx.mk_adt(*def, ty::List::empty()),
                     _ => ty,
                 };
-                let this = "this".to_string();
-                let (ty, postfix) = match &ty.kind() {
-                    ty::Slice(_) => (this, " because slices are always foreign"),
-                    ty::Array(..) => (this, " because arrays are always foreign"),
-                    ty::Tuple(..) => (this, " because tuples are always foreign"),
+                let msg = |ty: &str, postfix: &str| {
+                    format!("{ty} is not defined in the current crate{postfix}")
+                };
+                let this = |name: &str| msg("this", &format!(" because {name} are always foreign"));
+                let msg = match &ty.kind() {
+                    ty::Slice(_) => this("slices"),
+                    ty::Array(..) => this("arrays"),
+                    ty::Tuple(..) => this("tuples"),
+                    ty::Alias(ty::Opaque, ..) => {
+                        "type alias impl trait is treated as if it were foreign, \
+                        because its hidden type could be from a foreign crate"
+                            .to_string()
+                    }
                     ty::RawPtr(ptr_ty) => {
                         emit_newtype_suggestion_for_raw_ptr(
                             full_impl_span,
@@ -198,12 +206,11 @@ fn emit_orphan_check_error<'tcx>(
                             &mut err,
                         );
 
-                        (format!("`{}`", ty), " because raw pointers are always foreign")
+                        msg(&format!("`{ty}`"), " because raw pointers are always foreign")
                     }
-                    _ => (format!("`{}`", ty), ""),
+                    _ => msg(&format!("`{ty}`"), ""),
                 };
 
-                let msg = format!("{} is not defined in the current crate{}", ty, postfix);
                 if is_target_ty {
                     // Point at `D<A>` in `impl<A, B> for C<B> in D<A>`
                     err.span_label(self_ty_span, &msg);
diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs
index 0c4649cea14..9e46968c408 100644
--- a/compiler/rustc_hir_analysis/src/collect.rs
+++ b/compiler/rustc_hir_analysis/src/collect.rs
@@ -24,6 +24,8 @@ use rustc_hir as hir;
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_hir::intravisit::{self, Visitor};
 use rustc_hir::{GenericParamKind, Node};
+use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
+use rustc_infer::infer::TyCtxtInferExt;
 use rustc_middle::hir::nested_filter;
 use rustc_middle::ty::query::Providers;
 use rustc_middle::ty::util::{Discr, IntTypeExt};
@@ -31,7 +33,9 @@ use rustc_middle::ty::{self, AdtKind, Const, IsSuggestable, ToPredicate, Ty, TyC
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
 use rustc_span::Span;
 use rustc_target::spec::abi;
+use rustc_trait_selection::infer::InferCtxtExt;
 use rustc_trait_selection::traits::error_reporting::suggestions::NextTypeParamName;
+use rustc_trait_selection::traits::ObligationCtxt;
 use std::iter;
 
 mod generics_of;
@@ -839,7 +843,7 @@ fn convert_variant(
     )
 }
 
-fn adt_def<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> ty::AdtDef<'tcx> {
+fn adt_def(tcx: TyCtxt<'_>, def_id: DefId) -> ty::AdtDef<'_> {
     use rustc_hir::*;
 
     let def_id = def_id.expect_local();
@@ -1224,7 +1228,17 @@ fn infer_return_ty_for_fn_sig<'tcx>(
                 // to prevent the user from getting a papercut while trying to use the unique closure
                 // syntax (e.g. `[closure@src/lib.rs:2:5: 2:9]`).
                 diag.help("consider using an `Fn`, `FnMut`, or `FnOnce` trait bound");
-                diag.note("for more information on `Fn` traits and closure types, see https://doc.rust-lang.org/book/ch13-01-closures.html");
+                diag.note(
+                    "for more information on `Fn` traits and closure types, see \
+                     https://doc.rust-lang.org/book/ch13-01-closures.html",
+                );
+            } else if let Some(i_ty) = suggest_impl_iterator(tcx, ret_ty, ty.span, hir_id, def_id) {
+                diag.span_suggestion(
+                    ty.span,
+                    "replace with an appropriate return type",
+                    format!("impl Iterator<Item = {}>", i_ty),
+                    Applicability::MachineApplicable,
+                );
             }
             diag.emit();
 
@@ -1242,6 +1256,51 @@ fn infer_return_ty_for_fn_sig<'tcx>(
     }
 }
 
+fn suggest_impl_iterator<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    ret_ty: Ty<'tcx>,
+    span: Span,
+    hir_id: hir::HirId,
+    def_id: LocalDefId,
+) -> Option<Ty<'tcx>> {
+    let Some(iter_trait) = tcx.get_diagnostic_item(sym::Iterator) else { return None; };
+    let Some(iterator_item) = tcx.get_diagnostic_item(sym::IteratorItem) else { return None; };
+    if !tcx
+        .infer_ctxt()
+        .build()
+        .type_implements_trait(iter_trait, [ret_ty], tcx.param_env(def_id))
+        .must_apply_modulo_regions()
+    {
+        return None;
+    }
+    let infcx = tcx.infer_ctxt().build();
+    let ocx = ObligationCtxt::new_in_snapshot(&infcx);
+    // Find the type of `Iterator::Item`.
+    let origin = TypeVariableOrigin { kind: TypeVariableOriginKind::TypeInference, span };
+    let ty_var = infcx.next_ty_var(origin);
+    let projection = ty::Binder::dummy(ty::PredicateKind::Clause(ty::Clause::Projection(
+        ty::ProjectionPredicate {
+            projection_ty: tcx.mk_alias_ty(iterator_item, tcx.mk_substs([ret_ty.into()].iter())),
+            term: ty_var.into(),
+        },
+    )));
+    // Add `<ret_ty as Iterator>::Item = _` obligation.
+    ocx.register_obligation(crate::traits::Obligation::misc(
+        tcx,
+        span,
+        hir_id,
+        tcx.param_env(def_id),
+        projection,
+    ));
+    if ocx.select_where_possible().is_empty()
+        && let item_ty = infcx.resolve_vars_if_possible(ty_var)
+        && item_ty.is_suggestable(tcx, false)
+    {
+        return Some(item_ty);
+    }
+    None
+}
+
 fn impl_trait_ref(tcx: TyCtxt<'_>, def_id: DefId) -> Option<ty::TraitRef<'_>> {
     let icx = ItemCtxt::new(tcx, def_id);
     let item = tcx.hir().expect_item(def_id.expect_local());
diff --git a/compiler/rustc_hir_analysis/src/collect/lifetimes.rs b/compiler/rustc_hir_analysis/src/collect/lifetimes.rs
index b4ad3467e7d..b63a8ef698d 100644
--- a/compiler/rustc_hir_analysis/src/collect/lifetimes.rs
+++ b/compiler/rustc_hir_analysis/src/collect/lifetimes.rs
@@ -276,7 +276,7 @@ fn resolve_lifetimes(tcx: TyCtxt<'_>, local_def_id: hir::OwnerId) -> ResolveLife
     rl
 }
 
-fn late_region_as_bound_region<'tcx>(tcx: TyCtxt<'tcx>, region: &Region) -> ty::BoundVariableKind {
+fn late_region_as_bound_region(tcx: TyCtxt<'_>, region: &Region) -> ty::BoundVariableKind {
     match region {
         Region::LateBound(_, _, def_id) => {
             let name = tcx.hir().name(tcx.hir().local_def_id_to_hir_id(def_id.expect_local()));
@@ -1018,7 +1018,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
     }
 }
 
-fn object_lifetime_default<'tcx>(tcx: TyCtxt<'tcx>, param_def_id: DefId) -> ObjectLifetimeDefault {
+fn object_lifetime_default(tcx: TyCtxt<'_>, param_def_id: DefId) -> ObjectLifetimeDefault {
     debug_assert_eq!(tcx.def_kind(param_def_id), DefKind::TyParam);
     let param_def_id = param_def_id.expect_local();
     let parent_def_id = tcx.local_parent(param_def_id);
diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
index 79d75231e5d..0943350e2d4 100644
--- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
@@ -318,10 +318,10 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP
     }
 }
 
-fn const_evaluatable_predicates_of<'tcx>(
-    tcx: TyCtxt<'tcx>,
+fn const_evaluatable_predicates_of(
+    tcx: TyCtxt<'_>,
     def_id: LocalDefId,
-) -> FxIndexSet<(ty::Predicate<'tcx>, Span)> {
+) -> FxIndexSet<(ty::Predicate<'_>, Span)> {
     struct ConstCollector<'tcx> {
         tcx: TyCtxt<'tcx>,
         preds: FxIndexSet<(ty::Predicate<'tcx>, Span)>,
diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs
index b678990f94e..4bd55a54831 100644
--- a/compiler/rustc_hir_analysis/src/collect/type_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs
@@ -5,6 +5,7 @@ use rustc_hir::intravisit;
 use rustc_hir::intravisit::Visitor;
 use rustc_hir::{HirId, Node};
 use rustc_middle::hir::nested_filter;
+use rustc_middle::ty::print::with_forced_trimmed_paths;
 use rustc_middle::ty::subst::InternalSubsts;
 use rustc_middle::ty::util::IntTypeExt;
 use rustc_middle::ty::{self, DefIdTree, Ty, TyCtxt, TypeFolder, TypeSuperFoldable, TypeVisitable};
@@ -907,10 +908,10 @@ fn infer_placeholder_type<'a>(
                         Applicability::MachineApplicable,
                     );
                 } else {
-                    err.span_note(
+                    with_forced_trimmed_paths!(err.span_note(
                         tcx.hir().body(body_id).value.span,
-                        &format!("however, the inferred type `{}` cannot be named", ty),
-                    );
+                        &format!("however, the inferred type `{ty}` cannot be named"),
+                    ));
                 }
             }
 
@@ -931,10 +932,10 @@ fn infer_placeholder_type<'a>(
                         Applicability::MaybeIncorrect,
                     );
                 } else {
-                    diag.span_note(
+                    with_forced_trimmed_paths!(diag.span_note(
                         tcx.hir().body(body_id).value.span,
-                        &format!("however, the inferred type `{}` cannot be named", ty),
-                    );
+                        &format!("however, the inferred type `{ty}` cannot be named"),
+                    ));
                 }
             }
 
diff --git a/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs b/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs
index fd8e8ed7ba6..1aae9e0bd20 100644
--- a/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs
+++ b/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs
@@ -81,7 +81,6 @@ use rustc_span::Span;
 use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt;
 use rustc_trait_selection::traits::outlives_bounds::InferCtxtExt as _;
 use rustc_trait_selection::traits::{self, translate_substs, wf, ObligationCtxt};
-use tracing::instrument;
 
 pub(super) fn check_min_specialization(tcx: TyCtxt<'_>, impl_def_id: LocalDefId) {
     if let Some(node) = parent_specialization_node(tcx, impl_def_id) {
@@ -157,11 +156,11 @@ fn check_constness(tcx: TyCtxt<'_>, impl1_def_id: LocalDefId, impl2_node: Node,
 /// ```
 ///
 /// Would return `S1 = [C]` and `S2 = [Vec<C>, C]`.
-fn get_impl_substs<'tcx>(
-    tcx: TyCtxt<'tcx>,
+fn get_impl_substs(
+    tcx: TyCtxt<'_>,
     impl1_def_id: LocalDefId,
     impl2_node: Node,
-) -> Option<(SubstsRef<'tcx>, SubstsRef<'tcx>)> {
+) -> Option<(SubstsRef<'_>, SubstsRef<'_>)> {
     let infcx = &tcx.infer_ctxt().build();
     let ocx = ObligationCtxt::new(infcx);
     let param_env = tcx.param_env(impl1_def_id);
@@ -182,7 +181,7 @@ fn get_impl_substs<'tcx>(
 
     let implied_bounds = infcx.implied_bounds_tys(param_env, impl1_hir_id, assumed_wf_types);
     let outlives_env = OutlivesEnvironment::with_bounds(param_env, Some(infcx), implied_bounds);
-    infcx.check_region_obligations_and_report_errors(impl1_def_id, &outlives_env);
+    let _ = infcx.check_region_obligations_and_report_errors(impl1_def_id, &outlives_env);
     let Ok(impl2_substs) = infcx.fully_resolve(impl2_substs) else {
         let span = tcx.def_span(impl1_def_id);
         tcx.sess.emit_err(SubstsOnOverriddenImpl { span });
diff --git a/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs b/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs
index af8d7e85158..a46f2a94cd2 100644
--- a/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs
+++ b/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs
@@ -13,9 +13,9 @@ use super::utils::*;
 /// `global_inferred_outlives`: this is initially the empty map that
 ///     was generated by walking the items in the crate. This will
 ///     now be filled with inferred predicates.
-pub(super) fn infer_predicates<'tcx>(
-    tcx: TyCtxt<'tcx>,
-) -> FxHashMap<DefId, ty::EarlyBinder<RequiredPredicates<'tcx>>> {
+pub(super) fn infer_predicates(
+    tcx: TyCtxt<'_>,
+) -> FxHashMap<DefId, ty::EarlyBinder<RequiredPredicates<'_>>> {
     debug!("infer_predicates");
 
     let mut explicit_map = ExplicitPredicatesMap::new();
diff --git a/compiler/rustc_hir_typeck/src/callee.rs b/compiler/rustc_hir_typeck/src/callee.rs
index 7a5191b77f1..829913d278d 100644
--- a/compiler/rustc_hir_typeck/src/callee.rs
+++ b/compiler/rustc_hir_typeck/src/callee.rs
@@ -4,7 +4,7 @@ use super::{Expectation, FnCtxt, TupleArgumentsFlag};
 
 use crate::type_error_struct;
 use rustc_ast::util::parser::PREC_POSTFIX;
-use rustc_errors::{struct_span_err, Applicability, Diagnostic, StashKey};
+use rustc_errors::{struct_span_err, Applicability, Diagnostic, ErrorGuaranteed, StashKey};
 use rustc_hir as hir;
 use rustc_hir::def::{self, CtorKind, Namespace, Res};
 use rustc_hir::def_id::DefId;
@@ -241,7 +241,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             });
 
             if let Some(ok) = self.lookup_method_in_trait(
-                call_expr.span,
+                self.misc(call_expr.span),
                 method_name,
                 trait_def_id,
                 adjusted_ty,
@@ -399,6 +399,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             }
             ty::FnPtr(sig) => (sig, None),
             _ => {
+                for arg in arg_exprs {
+                    self.check_expr(arg);
+                }
+
                 if let hir::ExprKind::Path(hir::QPath::Resolved(_, path)) = &callee_expr.kind
                     && let [segment] = path.segments
                     && let Some(mut diag) = self
@@ -424,21 +428,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     }
                 }
 
-                self.report_invalid_callee(call_expr, callee_expr, callee_ty, arg_exprs);
-
-                // This is the "default" function signature, used in case of error.
-                // In that case, we check each argument against "error" in order to
-                // set up all the node type bindings.
-                (
-                    ty::Binder::dummy(self.tcx.mk_fn_sig(
-                        self.err_args(arg_exprs.len()).into_iter(),
-                        self.tcx.ty_error(),
-                        false,
-                        hir::Unsafety::Normal,
-                        abi::Abi::Rust,
-                    )),
-                    None,
-                )
+                let err = self.report_invalid_callee(call_expr, callee_expr, callee_ty, arg_exprs);
+
+                return self.tcx.ty_error_with_guaranteed(err);
             }
         };
 
@@ -498,7 +490,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         expected: Expectation<'tcx>,
     ) -> Option<Ty<'tcx>> {
         if let [callee_expr, rest @ ..] = arg_exprs {
-            let callee_ty = self.check_expr(callee_expr);
+            let callee_ty = self.typeck_results.borrow().expr_ty_adjusted_opt(callee_expr)?;
+
             // First, do a probe with `IsSuggestion(true)` to avoid emitting
             // any strange errors. If it's successful, then we'll do a true
             // method lookup.
@@ -591,7 +584,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         callee_expr: &'tcx hir::Expr<'tcx>,
         callee_ty: Ty<'tcx>,
         arg_exprs: &'tcx [hir::Expr<'tcx>],
-    ) {
+    ) -> ErrorGuaranteed {
         let mut unit_variant = None;
         if let hir::ExprKind::Path(qpath) = &callee_expr.kind
             && let Res::Def(def::DefKind::Ctor(kind, CtorKind::Const), _)
@@ -720,7 +713,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 err.span_label(span, label);
             }
         }
-        err.emit();
+        err.emit()
     }
 
     fn confirm_deferred_closure_call(
diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs
index 8cdd12e4e34..b0cd4a16e98 100644
--- a/compiler/rustc_hir_typeck/src/coercion.rs
+++ b/compiler/rustc_hir_typeck/src/coercion.rs
@@ -118,7 +118,7 @@ fn identity(_: Ty<'_>) -> Vec<Adjustment<'_>> {
     vec![]
 }
 
-fn simple<'tcx>(kind: Adjust<'tcx>) -> impl FnOnce(Ty<'tcx>) -> Vec<Adjustment<'tcx>> {
+fn simple<'tcx>(kind: Adjust<'tcx>) -> impl FnOnce(Ty<'tcx>) -> Vec<Adjustment<'_>> {
     move |target| vec![Adjustment { kind, target }]
 }
 
diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs
index 479aaf2e1a7..1360383a75a 100644
--- a/compiler/rustc_hir_typeck/src/demand.rs
+++ b/compiler/rustc_hir_typeck/src/demand.rs
@@ -1,5 +1,6 @@
 use crate::FnCtxt;
 use rustc_ast::util::parser::PREC_POSTFIX;
+use rustc_errors::MultiSpan;
 use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed};
 use rustc_hir as hir;
 use rustc_hir::def::CtorKind;
@@ -23,7 +24,7 @@ use std::cmp::min;
 use std::iter;
 
 impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
-    pub fn emit_coerce_suggestions(
+    pub fn emit_type_mismatch_suggestions(
         &self,
         err: &mut Diagnostic,
         expr: &hir::Expr<'tcx>,
@@ -36,11 +37,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             return;
         }
 
-        self.annotate_expected_due_to_let_ty(err, expr, error);
+        self.annotate_alternative_method_deref(err, expr, error);
 
         // Use `||` to give these suggestions a precedence
         let _ = self.suggest_missing_parentheses(err, expr)
+            || self.suggest_remove_last_method_call(err, expr, expected)
+            || self.suggest_associated_const(err, expr, expected)
             || self.suggest_deref_ref_or_into(err, expr, expected, expr_ty, expected_ty_expr)
+            || self.suggest_option_to_bool(err, expr, expr_ty, expected)
             || self.suggest_compatible_variants(err, expr, expected, expr_ty)
             || self.suggest_non_zero_new_unwrap(err, expr, expected, expr_ty)
             || self.suggest_calling_boxed_future_when_appropriate(err, expr, expected, expr_ty)
@@ -49,12 +53,28 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             || self.suggest_block_to_brackets_peeling_refs(err, expr, expr_ty, expected)
             || self.suggest_copied_or_cloned(err, expr, expr_ty, expected)
             || self.suggest_into(err, expr, expr_ty, expected)
-            || self.suggest_option_to_bool(err, expr, expr_ty, expected)
             || self.suggest_floating_point_literal(err, expr, expected);
+    }
 
+    pub fn emit_coerce_suggestions(
+        &self,
+        err: &mut Diagnostic,
+        expr: &hir::Expr<'tcx>,
+        expr_ty: Ty<'tcx>,
+        expected: Ty<'tcx>,
+        expected_ty_expr: Option<&'tcx hir::Expr<'tcx>>,
+        error: Option<TypeError<'tcx>>,
+    ) {
+        if expr_ty == expected {
+            return;
+        }
+
+        self.annotate_expected_due_to_let_ty(err, expr, error);
+        self.emit_type_mismatch_suggestions(err, expr, expr_ty, expected, expected_ty_expr, error);
         self.note_type_is_not_clone(err, expected, expr_ty, expr);
         self.note_need_for_fn_pointer(err, expected, expr_ty);
         self.note_internal_mutation_in_method(err, expr, expected, expr_ty);
+        self.check_for_range_as_method_call(err, expr, expr_ty, expected);
     }
 
     /// Requires that the two types unify, and prints an error message if
@@ -300,6 +320,162 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         }
     }
 
+    fn annotate_alternative_method_deref(
+        &self,
+        err: &mut Diagnostic,
+        expr: &hir::Expr<'_>,
+        error: Option<TypeError<'tcx>>,
+    ) {
+        let parent = self.tcx.hir().get_parent_node(expr.hir_id);
+        let Some(TypeError::Sorts(ExpectedFound { expected, .. })) = error else {return;};
+        let Some(hir::Node::Expr(hir::Expr {
+                    kind: hir::ExprKind::Assign(lhs, rhs, _), ..
+                })) = self.tcx.hir().find(parent) else {return; };
+        if rhs.hir_id != expr.hir_id || expected.is_closure() {
+            return;
+        }
+        let hir::ExprKind::Unary(hir::UnOp::Deref, deref) = lhs.kind else { return; };
+        let hir::ExprKind::MethodCall(path, base, args, _) = deref.kind else { return; };
+        let Some(self_ty) = self.typeck_results.borrow().expr_ty_adjusted_opt(base) else { return; };
+
+        let Ok(pick) = self
+            .probe_for_name(
+                probe::Mode::MethodCall,
+                path.ident,
+                probe::IsSuggestion(true),
+                self_ty,
+                deref.hir_id,
+                probe::ProbeScope::TraitsInScope,
+            ) else {
+                return;
+            };
+        let in_scope_methods = self.probe_for_name_many(
+            probe::Mode::MethodCall,
+            path.ident,
+            probe::IsSuggestion(true),
+            self_ty,
+            deref.hir_id,
+            probe::ProbeScope::TraitsInScope,
+        );
+        let other_methods_in_scope: Vec<_> =
+            in_scope_methods.iter().filter(|c| c.item.def_id != pick.item.def_id).collect();
+
+        let all_methods = self.probe_for_name_many(
+            probe::Mode::MethodCall,
+            path.ident,
+            probe::IsSuggestion(true),
+            self_ty,
+            deref.hir_id,
+            probe::ProbeScope::AllTraits,
+        );
+        let suggestions: Vec<_> = all_methods
+            .into_iter()
+            .filter(|c| c.item.def_id != pick.item.def_id)
+            .map(|c| {
+                let m = c.item;
+                let substs = ty::InternalSubsts::for_item(self.tcx, m.def_id, |param, _| {
+                    self.var_for_def(deref.span, param)
+                });
+                vec![
+                    (
+                        deref.span.until(base.span),
+                        format!(
+                            "{}({}",
+                            with_no_trimmed_paths!(
+                                self.tcx.def_path_str_with_substs(m.def_id, substs,)
+                            ),
+                            match self.tcx.fn_sig(m.def_id).input(0).skip_binder().kind() {
+                                ty::Ref(_, _, hir::Mutability::Mut) => "&mut ",
+                                ty::Ref(_, _, _) => "&",
+                                _ => "",
+                            },
+                        ),
+                    ),
+                    match &args[..] {
+                        [] => (base.span.shrink_to_hi().with_hi(deref.span.hi()), ")".to_string()),
+                        [first, ..] => (base.span.between(first.span), ", ".to_string()),
+                    },
+                ]
+            })
+            .collect();
+        if suggestions.is_empty() {
+            return;
+        }
+        let mut path_span: MultiSpan = path.ident.span.into();
+        path_span.push_span_label(
+            path.ident.span,
+            with_no_trimmed_paths!(format!(
+                "refers to `{}`",
+                self.tcx.def_path_str(pick.item.def_id),
+            )),
+        );
+        let container_id = pick.item.container_id(self.tcx);
+        let container = with_no_trimmed_paths!(self.tcx.def_path_str(container_id));
+        for def_id in pick.import_ids {
+            let hir_id = self.tcx.hir().local_def_id_to_hir_id(def_id);
+            path_span.push_span_label(
+                self.tcx.hir().span(hir_id),
+                format!("`{container}` imported here"),
+            );
+        }
+        let tail = with_no_trimmed_paths!(match &other_methods_in_scope[..] {
+            [] => return,
+            [candidate] => format!(
+                "the method of the same name on {} `{}`",
+                match candidate.kind {
+                    probe::CandidateKind::InherentImplCandidate(..) => "the inherent impl for",
+                    _ => "trait",
+                },
+                self.tcx.def_path_str(candidate.item.container_id(self.tcx))
+            ),
+            [.., last] if other_methods_in_scope.len() < 5 => {
+                format!(
+                    "the methods of the same name on {} and `{}`",
+                    other_methods_in_scope[..other_methods_in_scope.len() - 1]
+                        .iter()
+                        .map(|c| format!(
+                            "`{}`",
+                            self.tcx.def_path_str(c.item.container_id(self.tcx))
+                        ))
+                        .collect::<Vec<String>>()
+                        .join(", "),
+                    self.tcx.def_path_str(last.item.container_id(self.tcx))
+                )
+            }
+            _ => format!(
+                "the methods of the same name on {} other traits",
+                other_methods_in_scope.len()
+            ),
+        });
+        err.span_note(
+            path_span,
+            &format!(
+                "the `{}` call is resolved to the method in `{container}`, shadowing {tail}",
+                path.ident,
+            ),
+        );
+        if suggestions.len() > other_methods_in_scope.len() {
+            err.note(&format!(
+                "additionally, there are {} other available methods that aren't in scope",
+                suggestions.len() - other_methods_in_scope.len()
+            ));
+        }
+        err.multipart_suggestions(
+            &format!(
+                "you might have meant to call {}; you can use the fully-qualified path to call {} \
+                 explicitly",
+                if suggestions.len() == 1 {
+                    "the other method"
+                } else {
+                    "one of the other methods"
+                },
+                if suggestions.len() == 1 { "it" } else { "one of them" },
+            ),
+            suggestions,
+            Applicability::MaybeIncorrect,
+        );
+    }
+
     /// If the expected type is an enum (Issue #55250) with any variants whose
     /// sole field is of the found type, suggest such variants. (Issue #42764)
     fn suggest_compatible_variants(
@@ -1432,4 +1608,69 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             _ => false,
         }
     }
+
+    /// Identify when the user has written `foo..bar()` instead of `foo.bar()`.
+    pub fn check_for_range_as_method_call(
+        &self,
+        err: &mut Diagnostic,
+        expr: &hir::Expr<'_>,
+        checked_ty: Ty<'tcx>,
+        expected_ty: Ty<'tcx>,
+    ) {
+        if !hir::is_range_literal(expr) {
+            return;
+        }
+        let hir::ExprKind::Struct(
+            hir::QPath::LangItem(LangItem::Range, ..),
+            [start, end],
+            _,
+        ) = expr.kind else { return; };
+        let parent = self.tcx.hir().get_parent_node(expr.hir_id);
+        if let Some(hir::Node::ExprField(_)) = self.tcx.hir().find(parent) {
+            // Ignore `Foo { field: a..Default::default() }`
+            return;
+        }
+        let mut expr = end.expr;
+        while let hir::ExprKind::MethodCall(_, rcvr, ..) = expr.kind {
+            // Getting to the root receiver and asserting it is a fn call let's us ignore cases in
+            // `src/test/ui/methods/issues/issue-90315.stderr`.
+            expr = rcvr;
+        }
+        let hir::ExprKind::Call(method_name, _) = expr.kind else { return; };
+        let ty::Adt(adt, _) = checked_ty.kind() else { return; };
+        if self.tcx.lang_items().range_struct() != Some(adt.did()) {
+            return;
+        }
+        if let ty::Adt(adt, _) = expected_ty.kind()
+            && self.tcx.lang_items().range_struct() == Some(adt.did())
+        {
+            return;
+        }
+        // Check if start has method named end.
+        let hir::ExprKind::Path(hir::QPath::Resolved(None, p)) = method_name.kind else { return; };
+        let [hir::PathSegment { ident, .. }] = p.segments else { return; };
+        let self_ty = self.typeck_results.borrow().expr_ty(start.expr);
+        let Ok(_pick) = self.probe_for_name(
+            probe::Mode::MethodCall,
+            *ident,
+            probe::IsSuggestion(true),
+            self_ty,
+            expr.hir_id,
+            probe::ProbeScope::AllTraits,
+        ) else { return; };
+        let mut sugg = ".";
+        let mut span = start.expr.span.between(end.expr.span);
+        if span.lo() + BytePos(2) == span.hi() {
+            // There's no space between the start, the range op and the end, suggest removal which
+            // will be more noticeable than the replacement of `..` with `.`.
+            span = span.with_lo(span.lo() + BytePos(1));
+            sugg = "";
+        }
+        err.span_suggestion_verbose(
+            span,
+            "you likely meant to write a method call instead of a range",
+            sugg,
+            Applicability::MachineApplicable,
+        );
+    }
 }
diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs
index edbbb7272ac..ae641b26eee 100644
--- a/compiler/rustc_hir_typeck/src/expr.rs
+++ b/compiler/rustc_hir_typeck/src/expr.rs
@@ -104,16 +104,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         }
 
         if let Some(mut err) = self.demand_suptype_diag(expr.span, expected_ty, ty) {
-            // FIXME(compiler-errors): We probably should fold some of the
-            // `suggest_` functions from  `emit_coerce_suggestions` into here,
-            // since some of those aren't necessarily just coerce suggestions.
-            let _ = self.suggest_deref_ref_or_into(
+            let _ = self.emit_type_mismatch_suggestions(
                 &mut err,
                 expr.peel_drop_temps(),
-                expected_ty,
                 ty,
+                expected_ty,
                 None,
-            ) || self.suggest_option_to_bool(&mut err, expr, ty, expected_ty);
+                None,
+            );
             extend_err(&mut err);
             err.emit();
         }
diff --git a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs
index 03b174c7795..7774ffc9b97 100644
--- a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs
+++ b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs
@@ -756,8 +756,8 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
     /// - When reporting the Place back to the Delegate, ensure that the UpvarId uses the enclosing
     /// closure as the DefId.
     fn walk_captures(&mut self, closure_expr: &hir::Closure<'_>) {
-        fn upvar_is_local_variable<'tcx>(
-            upvars: Option<&'tcx FxIndexMap<hir::HirId, hir::Upvar>>,
+        fn upvar_is_local_variable(
+            upvars: Option<&FxIndexMap<hir::HirId, hir::Upvar>>,
             upvar_id: hir::HirId,
             body_owner_is_closure: bool,
         ) -> bool {
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
index d1e0964112b..d342d96a10f 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
@@ -214,7 +214,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         "cannot use call notation; the first type parameter \
                          for the function trait is neither a tuple nor unit"
                     )
-                    .delay_as_bug();
+                    .emit();
                     (self.err_args(provided_args.len()), None)
                 }
             }
@@ -1307,7 +1307,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         // Type check the initializer.
         if let Some(ref init) = decl.init {
             let init_ty = self.check_decl_initializer(decl.hir_id, decl.pat, &init);
-            self.overwrite_local_ty_if_err(decl.hir_id, decl.pat, decl_ty, init_ty);
+            self.overwrite_local_ty_if_err(decl.hir_id, decl.pat, init_ty);
         }
 
         // Does the expected pattern type originate from an expression and what is the span?
@@ -1322,7 +1322,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         // Type check the pattern. Override if necessary to avoid knock-on errors.
         self.check_pat_top(&decl.pat, decl_ty, ty_span, origin_expr);
         let pat_ty = self.node_ty(decl.pat.hir_id);
-        self.overwrite_local_ty_if_err(decl.hir_id, decl.pat, decl_ty, pat_ty);
+        self.overwrite_local_ty_if_err(decl.hir_id, decl.pat, pat_ty);
 
         if let Some(blk) = decl.els {
             let previous_diverges = self.diverges.get();
@@ -1627,14 +1627,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         &self,
         hir_id: hir::HirId,
         pat: &'tcx hir::Pat<'tcx>,
-        decl_ty: Ty<'tcx>,
         ty: Ty<'tcx>,
     ) {
         if ty.references_error() {
             // Override the types everywhere with `err()` to avoid knock on errors.
-            self.write_ty(hir_id, ty);
-            self.write_ty(pat.hir_id, ty);
-            let local_ty = LocalTy { decl_ty, revealed_ty: ty };
+            let err = self.tcx.ty_error();
+            self.write_ty(hir_id, err);
+            self.write_ty(pat.hir_id, err);
+            let local_ty = LocalTy { decl_ty: err, revealed_ty: err };
             self.locals.borrow_mut().insert(hir_id, local_ty);
             self.locals.borrow_mut().insert(pat.hir_id, local_ty);
         }
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
index c9d179de39f..e38d1bccc10 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
@@ -1,6 +1,7 @@
 use super::FnCtxt;
 
 use crate::errors::{AddReturnTypeSuggestion, ExpectedReturnTypeLabel};
+use crate::method::probe::{IsSuggestion, Mode, ProbeScope};
 use rustc_ast::util::parser::{ExprPrecedence, PREC_POSTFIX};
 use rustc_errors::{Applicability, Diagnostic, MultiSpan};
 use rustc_hir as hir;
@@ -15,10 +16,12 @@ use rustc_infer::traits::{self, StatementAsExpression};
 use rustc_middle::lint::in_external_macro;
 use rustc_middle::ty::{
     self, suggest_constraining_type_params, Binder, DefIdTree, IsSuggestable, ToPredicate, Ty,
+    TypeVisitable,
 };
 use rustc_session::errors::ExprParenthesesNeeded;
-use rustc_span::symbol::sym;
-use rustc_span::Span;
+use rustc_span::source_map::Spanned;
+use rustc_span::symbol::{sym, Ident};
+use rustc_span::{Span, Symbol};
 use rustc_trait_selection::infer::InferCtxtExt;
 use rustc_trait_selection::traits::error_reporting::DefIdOrName;
 use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _;
@@ -327,6 +330,31 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         }
     }
 
+    pub fn suggest_remove_last_method_call(
+        &self,
+        err: &mut Diagnostic,
+        expr: &hir::Expr<'tcx>,
+        expected: Ty<'tcx>,
+    ) -> bool {
+        if let hir::ExprKind::MethodCall(hir::PathSegment { ident: method, .. }, recv_expr, &[], _) = expr.kind &&
+            let Some(recv_ty) = self.typeck_results.borrow().expr_ty_opt(recv_expr) &&
+            self.can_coerce(recv_ty, expected) {
+                let span = if let Some(recv_span) = recv_expr.span.find_ancestor_inside(expr.span) {
+                    expr.span.with_lo(recv_span.hi())
+                } else {
+                    expr.span.with_lo(method.span.lo() - rustc_span::BytePos(1))
+                };
+                err.span_suggestion_verbose(
+                    span,
+                    "try removing the method call",
+                    "",
+                    Applicability::MachineApplicable,
+                );
+                return true;
+            }
+        false
+    }
+
     pub fn suggest_deref_ref_or_into(
         &self,
         err: &mut Diagnostic,
@@ -1232,10 +1260,113 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 );
                 true
             }
+            ExprKind::Lit(Spanned {
+                node: rustc_ast::LitKind::Int(lit, rustc_ast::LitIntType::Unsuffixed),
+                span,
+            }) => {
+                let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) else { return false; };
+                if !(snippet.starts_with("0x") || snippet.starts_with("0X")) {
+                    return false;
+                }
+                if snippet.len() <= 5 || !snippet.is_char_boundary(snippet.len() - 3) {
+                    return false;
+                }
+                let (_, suffix) = snippet.split_at(snippet.len() - 3);
+                let value = match suffix {
+                    "f32" => (lit - 0xf32) / (16 * 16 * 16),
+                    "f64" => (lit - 0xf64) / (16 * 16 * 16),
+                    _ => return false,
+                };
+                err.span_suggestions(
+                    expr.span,
+                    "rewrite this as a decimal floating point literal, or use `as` to turn a hex literal into a float",
+                    [format!("0x{value:X} as {suffix}"), format!("{value}_{suffix}")],
+                    Applicability::MaybeIncorrect,
+                );
+                true
+            }
             _ => false,
         }
     }
 
+    pub(crate) fn suggest_associated_const(
+        &self,
+        err: &mut Diagnostic,
+        expr: &hir::Expr<'_>,
+        expected_ty: Ty<'tcx>,
+    ) -> bool {
+        let Some((DefKind::AssocFn, old_def_id)) = self.typeck_results.borrow().type_dependent_def(expr.hir_id) else {
+            return false;
+        };
+        let old_item_name = self.tcx.item_name(old_def_id);
+        let capitalized_name = Symbol::intern(&old_item_name.as_str().to_uppercase());
+        if old_item_name == capitalized_name {
+            return false;
+        }
+        let (item, segment) = match expr.kind {
+            hir::ExprKind::Path(QPath::Resolved(
+                Some(ty),
+                hir::Path { segments: [segment], .. },
+            ))
+            | hir::ExprKind::Path(QPath::TypeRelative(ty, segment)) => {
+                let self_ty = <dyn AstConv<'_>>::ast_ty_to_ty(self, ty);
+                if let Ok(pick) = self.probe_for_name(
+                    Mode::Path,
+                    Ident::new(capitalized_name, segment.ident.span),
+                    IsSuggestion(true),
+                    self_ty,
+                    expr.hir_id,
+                    ProbeScope::TraitsInScope,
+                ) {
+                    (pick.item, segment)
+                } else {
+                    return false;
+                }
+            }
+            hir::ExprKind::Path(QPath::Resolved(
+                None,
+                hir::Path { segments: [.., segment], .. },
+            )) => {
+                // we resolved through some path that doesn't end in the item name,
+                // better not do a bad suggestion by accident.
+                if old_item_name != segment.ident.name {
+                    return false;
+                }
+                if let Some(item) = self
+                    .tcx
+                    .associated_items(self.tcx.parent(old_def_id))
+                    .filter_by_name_unhygienic(capitalized_name)
+                    .next()
+                {
+                    (*item, segment)
+                } else {
+                    return false;
+                }
+            }
+            _ => return false,
+        };
+        if item.def_id == old_def_id || self.tcx.def_kind(item.def_id) != DefKind::AssocConst {
+            // Same item
+            return false;
+        }
+        let item_ty = self.tcx.type_of(item.def_id);
+        // FIXME(compiler-errors): This check is *so* rudimentary
+        if item_ty.needs_subst() {
+            return false;
+        }
+        if self.can_coerce(item_ty, expected_ty) {
+            err.span_suggestion_verbose(
+                segment.ident.span,
+                format!("try referring to the associated const `{capitalized_name}` instead",),
+                capitalized_name,
+                Applicability::MachineApplicable,
+            );
+            true
+        } else {
+            false
+        }
+    }
+
     fn is_loop(&self, id: hir::HirId) -> bool {
         let node = self.tcx.hir().get(id);
         matches!(node, Node::Expr(Expr { kind: ExprKind::Loop(..), .. }))
diff --git a/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/cfg_build.rs b/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/cfg_build.rs
index fd8ea1ad7bf..16806fdba4f 100644
--- a/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/cfg_build.rs
+++ b/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/cfg_build.rs
@@ -233,6 +233,7 @@ impl<'a, 'tcx> DropRangeVisitor<'a, 'tcx> {
             self.tcx()
                 .sess
                 .delay_span_bug(expr.span, format!("could not resolve infer vars in `{ty}`"));
+            return;
         }
         let ty = self.tcx().erase_regions(ty);
         let m = self.tcx().parent_module(expr.hir_id).to_def_id();
diff --git a/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/mod.rs b/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/mod.rs
index 2f55ea939fc..f7b493bc224 100644
--- a/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/mod.rs
+++ b/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/mod.rs
@@ -79,7 +79,7 @@ pub fn compute_drop_ranges<'a, 'tcx>(
 /// result of `foo`. On the other hand, if `place` points to `x` then `f` will
 /// be called both on the `ExprKind::Path` node that represents the expression
 /// as well as the HirId of the local `x` itself.
-fn for_each_consumable<'tcx>(hir: Map<'tcx>, place: TrackedValue, mut f: impl FnMut(TrackedValue)) {
+fn for_each_consumable(hir: Map<'_>, place: TrackedValue, mut f: impl FnMut(TrackedValue)) {
     f(place);
     let node = hir.find(place.hir_id());
     if let Some(Node::Expr(expr)) = node {
diff --git a/compiler/rustc_hir_typeck/src/generator_interior/mod.rs b/compiler/rustc_hir_typeck/src/generator_interior/mod.rs
index 93f2ceed777..e4ac91befac 100644
--- a/compiler/rustc_hir_typeck/src/generator_interior/mod.rs
+++ b/compiler/rustc_hir_typeck/src/generator_interior/mod.rs
@@ -607,10 +607,7 @@ fn check_must_not_suspend_ty<'tcx>(
         ty::Tuple(fields) => {
             let mut has_emitted = false;
             let comps = match data.expr.map(|e| &e.kind) {
-                Some(hir::ExprKind::Tup(comps)) => {
-                    debug_assert_eq!(comps.len(), fields.len());
-                    Some(comps)
-                }
+                Some(hir::ExprKind::Tup(comps)) if comps.len() == fields.len() => Some(comps),
                 _ => None,
             };
             for (i, ty) in fields.iter().enumerate() {
diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs
index 5b2352cda34..b06927f9662 100644
--- a/compiler/rustc_hir_typeck/src/lib.rs
+++ b/compiler/rustc_hir_typeck/src/lib.rs
@@ -462,8 +462,8 @@ fn fatally_break_rust(sess: &Session) {
     ));
 }
 
-fn has_expected_num_generic_args<'tcx>(
-    tcx: TyCtxt<'tcx>,
+fn has_expected_num_generic_args(
+    tcx: TyCtxt<'_>,
     trait_did: Option<DefId>,
     expected: usize,
 ) -> bool {
diff --git a/compiler/rustc_hir_typeck/src/method/mod.rs b/compiler/rustc_hir_typeck/src/method/mod.rs
index fddb8a458a7..b9b27e8627a 100644
--- a/compiler/rustc_hir_typeck/src/method/mod.rs
+++ b/compiler/rustc_hir_typeck/src/method/mod.rs
@@ -11,7 +11,7 @@ pub use self::suggest::SelfSource;
 pub use self::MethodError::*;
 
 use crate::errors::OpMethodGenericParams;
-use crate::{Expectation, FnCtxt};
+use crate::FnCtxt;
 use rustc_data_structures::sync::Lrc;
 use rustc_errors::{Applicability, Diagnostic};
 use rustc_hir as hir;
@@ -264,7 +264,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
     pub(super) fn obligation_for_method(
         &self,
-        span: Span,
+        cause: ObligationCause<'tcx>,
         trait_def_id: DefId,
         self_ty: Ty<'tcx>,
         opt_input_types: Option<&[Ty<'tcx>]>,
@@ -282,71 +282,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     }
                 }
             }
-            self.var_for_def(span, param)
-        });
-
-        let trait_ref = self.tcx.mk_trait_ref(trait_def_id, substs);
-
-        // Construct an obligation
-        let poly_trait_ref = ty::Binder::dummy(trait_ref);
-        (
-            traits::Obligation::misc(
-                self.tcx,
-                span,
-                self.body_id,
-                self.param_env,
-                poly_trait_ref.without_const(),
-            ),
-            substs,
-        )
-    }
-
-    pub(super) fn obligation_for_op_method(
-        &self,
-        span: Span,
-        trait_def_id: DefId,
-        self_ty: Ty<'tcx>,
-        opt_input_type: Option<Ty<'tcx>>,
-        opt_input_expr: Option<&'tcx hir::Expr<'tcx>>,
-        expected: Expectation<'tcx>,
-    ) -> (traits::Obligation<'tcx, ty::Predicate<'tcx>>, &'tcx ty::List<ty::subst::GenericArg<'tcx>>)
-    {
-        // Construct a trait-reference `self_ty : Trait<input_tys>`
-        let substs = InternalSubsts::for_item(self.tcx, trait_def_id, |param, _| {
-            match param.kind {
-                GenericParamDefKind::Lifetime | GenericParamDefKind::Const { .. } => {}
-                GenericParamDefKind::Type { .. } => {
-                    if param.index == 0 {
-                        return self_ty.into();
-                    } else if let Some(input_type) = opt_input_type {
-                        return input_type.into();
-                    }
-                }
-            }
-            self.var_for_def(span, param)
+            self.var_for_def(cause.span, param)
         });
 
         let trait_ref = self.tcx.mk_trait_ref(trait_def_id, substs);
 
         // Construct an obligation
         let poly_trait_ref = ty::Binder::dummy(trait_ref);
-        let output_ty = expected.only_has_type(self).and_then(|ty| (!ty.needs_infer()).then(|| ty));
-
         (
             traits::Obligation::new(
                 self.tcx,
-                traits::ObligationCause::new(
-                    span,
-                    self.body_id,
-                    traits::BinOp {
-                        rhs_span: opt_input_expr.map(|expr| expr.span),
-                        is_lit: opt_input_expr
-                            .map_or(false, |expr| matches!(expr.kind, hir::ExprKind::Lit(_))),
-                        output_ty,
-                    },
-                ),
+                cause,
                 self.param_env,
-                poly_trait_ref,
+                poly_trait_ref.without_const(),
             ),
             substs,
         )
@@ -357,55 +305,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     /// In particular, it doesn't really do any probing: it simply constructs
     /// an obligation for a particular trait with the given self type and checks
     /// whether that trait is implemented.
-    #[instrument(level = "debug", skip(self, span))]
+    #[instrument(level = "debug", skip(self))]
     pub(super) fn lookup_method_in_trait(
         &self,
-        span: Span,
+        cause: ObligationCause<'tcx>,
         m_name: Ident,
         trait_def_id: DefId,
         self_ty: Ty<'tcx>,
         opt_input_types: Option<&[Ty<'tcx>]>,
     ) -> Option<InferOk<'tcx, MethodCallee<'tcx>>> {
         let (obligation, substs) =
-            self.obligation_for_method(span, trait_def_id, self_ty, opt_input_types);
-        self.construct_obligation_for_trait(
-            span,
-            m_name,
-            trait_def_id,
-            obligation,
-            substs,
-            None,
-            false,
-        )
-    }
-
-    pub(super) fn lookup_op_method_in_trait(
-        &self,
-        span: Span,
-        m_name: Ident,
-        trait_def_id: DefId,
-        self_ty: Ty<'tcx>,
-        opt_input_type: Option<Ty<'tcx>>,
-        opt_input_expr: Option<&'tcx hir::Expr<'tcx>>,
-        expected: Expectation<'tcx>,
-    ) -> Option<InferOk<'tcx, MethodCallee<'tcx>>> {
-        let (obligation, substs) = self.obligation_for_op_method(
-            span,
-            trait_def_id,
-            self_ty,
-            opt_input_type,
-            opt_input_expr,
-            expected,
-        );
-        self.construct_obligation_for_trait(
-            span,
-            m_name,
-            trait_def_id,
-            obligation,
-            substs,
-            opt_input_expr,
-            true,
-        )
+            self.obligation_for_method(cause, trait_def_id, self_ty, opt_input_types);
+        self.construct_obligation_for_trait(m_name, trait_def_id, obligation, substs)
     }
 
     // FIXME(#18741): it seems likely that we can consolidate some of this
@@ -413,13 +324,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     // of this method is basically the same as confirmation.
     fn construct_obligation_for_trait(
         &self,
-        span: Span,
         m_name: Ident,
         trait_def_id: DefId,
         obligation: traits::PredicateObligation<'tcx>,
         substs: &'tcx ty::List<ty::subst::GenericArg<'tcx>>,
-        opt_input_expr: Option<&'tcx hir::Expr<'tcx>>,
-        is_op: bool,
     ) -> Option<InferOk<'tcx, MethodCallee<'tcx>>> {
         debug!(?obligation);
 
@@ -435,7 +343,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         let tcx = self.tcx;
         let Some(method_item) = self.associated_value(trait_def_id, m_name) else {
             tcx.sess.delay_span_bug(
-                span,
+                obligation.cause.span,
                 "operator trait does not have corresponding operator method",
             );
             return None;
@@ -461,24 +369,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         // with bound regions.
         let fn_sig = tcx.bound_fn_sig(def_id);
         let fn_sig = fn_sig.subst(self.tcx, substs);
-        let fn_sig = self.replace_bound_vars_with_fresh_vars(span, infer::FnCall, fn_sig);
-
-        let cause = if is_op {
-            ObligationCause::new(
-                span,
-                self.body_id,
-                traits::BinOp {
-                    rhs_span: opt_input_expr.map(|expr| expr.span),
-                    is_lit: opt_input_expr
-                        .map_or(false, |expr| matches!(expr.kind, hir::ExprKind::Lit(_))),
-                    output_ty: None,
-                },
-            )
-        } else {
-            traits::ObligationCause::misc(span, self.body_id)
-        };
+        let fn_sig =
+            self.replace_bound_vars_with_fresh_vars(obligation.cause.span, infer::FnCall, fn_sig);
 
-        let InferOk { value, obligations: o } = self.at(&cause, self.param_env).normalize(fn_sig);
+        let InferOk { value, obligations: o } =
+            self.at(&obligation.cause, self.param_env).normalize(fn_sig);
         let fn_sig = {
             obligations.extend(o);
             value
@@ -494,7 +389,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         // any late-bound regions appearing in its bounds.
         let bounds = self.tcx.predicates_of(def_id).instantiate(self.tcx, substs);
 
-        let InferOk { value, obligations: o } = self.at(&cause, self.param_env).normalize(bounds);
+        let InferOk { value, obligations: o } =
+            self.at(&obligation.cause, self.param_env).normalize(bounds);
         let bounds = {
             obligations.extend(o);
             value
@@ -502,7 +398,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
         assert!(!bounds.has_escaping_bound_vars());
 
-        let predicates_cause = cause.clone();
+        let predicates_cause = obligation.cause.clone();
         obligations.extend(traits::predicates_for_generics(
             move |_, _| predicates_cause.clone(),
             self.param_env,
@@ -517,7 +413,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         );
         obligations.push(traits::Obligation::new(
             tcx,
-            cause,
+            obligation.cause,
             self.param_env,
             ty::Binder::dummy(ty::PredicateKind::WellFormed(method_ty.into())),
         ));
diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs
index b9e7830bf07..1afaae0e020 100644
--- a/compiler/rustc_hir_typeck/src/method/probe.rs
+++ b/compiler/rustc_hir_typeck/src/method/probe.rs
@@ -97,7 +97,7 @@ impl<'a, 'tcx> Deref for ProbeContext<'a, 'tcx> {
 }
 
 #[derive(Debug, Clone)]
-struct Candidate<'tcx> {
+pub(crate) struct Candidate<'tcx> {
     // Candidates are (I'm not quite sure, but they are mostly) basically
     // some metadata on top of a `ty::AssocItem` (without substs).
     //
@@ -131,13 +131,13 @@ struct Candidate<'tcx> {
     // if `T: Sized`.
     xform_self_ty: Ty<'tcx>,
     xform_ret_ty: Option<Ty<'tcx>>,
-    item: ty::AssocItem,
-    kind: CandidateKind<'tcx>,
-    import_ids: SmallVec<[LocalDefId; 1]>,
+    pub(crate) item: ty::AssocItem,
+    pub(crate) kind: CandidateKind<'tcx>,
+    pub(crate) import_ids: SmallVec<[LocalDefId; 1]>,
 }
 
 #[derive(Debug, Clone)]
-enum CandidateKind<'tcx> {
+pub(crate) enum CandidateKind<'tcx> {
     InherentImplCandidate(
         SubstsRef<'tcx>,
         // Normalize obligations
@@ -322,6 +322,36 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         )
     }
 
+    #[instrument(level = "debug", skip(self))]
+    pub(crate) fn probe_for_name_many(
+        &self,
+        mode: Mode,
+        item_name: Ident,
+        is_suggestion: IsSuggestion,
+        self_ty: Ty<'tcx>,
+        scope_expr_id: hir::HirId,
+        scope: ProbeScope,
+    ) -> Vec<Candidate<'tcx>> {
+        self.probe_op(
+            item_name.span,
+            mode,
+            Some(item_name),
+            None,
+            is_suggestion,
+            self_ty,
+            scope_expr_id,
+            scope,
+            |probe_cx| {
+                Ok(probe_cx
+                    .inherent_candidates
+                    .into_iter()
+                    .chain(probe_cx.extension_candidates)
+                    .collect())
+            },
+        )
+        .unwrap()
+    }
+
     fn probe_op<OP, R>(
         &'a self,
         span: Span,
@@ -943,6 +973,9 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
             });
         } else {
             debug_assert!(self.tcx.is_trait(trait_def_id));
+            if self.tcx.trait_is_auto(trait_def_id) {
+                return;
+            }
             for item in self.impl_or_trait_item(trait_def_id) {
                 // Check whether `trait_def_id` defines a method with suitable name.
                 if !self.has_applicable_self(&item) {
diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs
index 7c5a9a333fe..aa689295178 100644
--- a/compiler/rustc_hir_typeck/src/method/suggest.rs
+++ b/compiler/rustc_hir_typeck/src/method/suggest.rs
@@ -2306,6 +2306,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         _ => false,
                     }
                 }) && (type_is_local || info.def_id.is_local())
+                    && !self.tcx.trait_is_auto(info.def_id)
                     && self
                         .associated_value(info.def_id, item_name)
                         .filter(|item| {
diff --git a/compiler/rustc_hir_typeck/src/op.rs b/compiler/rustc_hir_typeck/src/op.rs
index b12d84af4ad..34140f3e1fe 100644
--- a/compiler/rustc_hir_typeck/src/op.rs
+++ b/compiler/rustc_hir_typeck/src/op.rs
@@ -12,14 +12,16 @@ use rustc_middle::ty::adjustment::{
     Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability,
 };
 use rustc_middle::ty::print::with_no_trimmed_paths;
-use rustc_middle::ty::{self, DefIdTree, Ty, TyCtxt, TypeFolder, TypeSuperFoldable, TypeVisitable};
+use rustc_middle::ty::{
+    self, DefIdTree, IsSuggestable, Ty, TyCtxt, TypeFolder, TypeSuperFoldable, TypeVisitable,
+};
 use rustc_session::errors::ExprParenthesesNeeded;
 use rustc_span::source_map::Spanned;
 use rustc_span::symbol::{sym, Ident};
 use rustc_span::Span;
 use rustc_trait_selection::infer::InferCtxtExt;
 use rustc_trait_selection::traits::error_reporting::suggestions::TypeErrCtxtExt as _;
-use rustc_trait_selection::traits::FulfillmentError;
+use rustc_trait_selection::traits::{self, FulfillmentError};
 use rustc_type_ir::sty::TyKind::*;
 
 impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
@@ -48,8 +50,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 if self
                     .lookup_op_method(
                         lhs_deref_ty,
-                        Some(rhs_ty),
-                        Some(rhs),
+                        Some((rhs, rhs_ty)),
                         Op::Binary(op, IsAssign::Yes),
                         expected,
                     )
@@ -60,8 +61,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     if self
                         .lookup_op_method(
                             lhs_ty,
-                            Some(rhs_ty),
-                            Some(rhs),
+                            Some((rhs, rhs_ty)),
                             Op::Binary(op, IsAssign::Yes),
                             expected,
                         )
@@ -248,8 +248,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
         let result = self.lookup_op_method(
             lhs_ty,
-            Some(rhs_ty_var),
-            Some(rhs_expr),
+            Some((rhs_expr, rhs_ty_var)),
             Op::Binary(op, is_assign),
             expected,
         );
@@ -382,8 +381,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     if self
                         .lookup_op_method(
                             lhs_deref_ty,
-                            Some(rhs_ty),
-                            Some(rhs_expr),
+                            Some((rhs_expr, rhs_ty)),
                             Op::Binary(op, is_assign),
                             expected,
                         )
@@ -410,8 +408,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 let is_compatible = |lhs_ty, rhs_ty| {
                     self.lookup_op_method(
                         lhs_ty,
-                        Some(rhs_ty),
-                        Some(rhs_expr),
+                        Some((rhs_expr, rhs_ty)),
                         Op::Binary(op, is_assign),
                         expected,
                     )
@@ -471,8 +468,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         let errors = self
                             .lookup_op_method(
                                 lhs_ty,
-                                Some(rhs_ty),
-                                Some(rhs_expr),
+                                Some((rhs_expr, rhs_ty)),
                                 Op::Binary(op, is_assign),
                                 expected,
                             )
@@ -492,6 +488,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                                             if let Some(output_def_id) = output_def_id
                                                 && let Some(trait_def_id) = trait_def_id
                                                 && self.tcx.parent(output_def_id) == trait_def_id
+                                                && output_ty.is_suggestable(self.tcx, false)
                                             {
                                                 Some(("Output", *output_ty))
                                             } else {
@@ -625,7 +622,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         expected: Expectation<'tcx>,
     ) -> Ty<'tcx> {
         assert!(op.is_by_value());
-        match self.lookup_op_method(operand_ty, None, None, Op::Unary(op, ex.span), expected) {
+        match self.lookup_op_method(operand_ty, None, Op::Unary(op, ex.span), expected) {
             Ok(method) => {
                 self.write_method_call(ex.hir_id, method);
                 method.sig.output()
@@ -712,8 +709,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     fn lookup_op_method(
         &self,
         lhs_ty: Ty<'tcx>,
-        other_ty: Option<Ty<'tcx>>,
-        other_ty_expr: Option<&'tcx hir::Expr<'tcx>>,
+        opt_rhs: Option<(&'tcx hir::Expr<'tcx>, Ty<'tcx>)>,
         op: Op,
         expected: Expectation<'tcx>,
     ) -> Result<MethodCallee<'tcx>, Vec<FulfillmentError<'tcx>>> {
@@ -742,20 +738,27 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 Op::Unary(..) => 0,
             },
         ) {
+            self.tcx
+                .sess
+                .delay_span_bug(span, "operator didn't have the right number of generic args");
             return Err(vec![]);
         }
 
         let opname = Ident::with_dummy_span(opname);
+        let input_types =
+            opt_rhs.as_ref().map(|(_, ty)| std::slice::from_ref(ty)).unwrap_or_default();
+        let cause = self.cause(
+            span,
+            traits::BinOp {
+                rhs_span: opt_rhs.map(|(expr, _)| expr.span),
+                is_lit: opt_rhs
+                    .map_or(false, |(expr, _)| matches!(expr.kind, hir::ExprKind::Lit(_))),
+                output_ty: expected.only_has_type(self),
+            },
+        );
+
         let method = trait_did.and_then(|trait_did| {
-            self.lookup_op_method_in_trait(
-                span,
-                opname,
-                trait_did,
-                lhs_ty,
-                other_ty,
-                other_ty_expr,
-                expected,
-            )
+            self.lookup_method_in_trait(cause.clone(), opname, trait_did, lhs_ty, Some(input_types))
         });
 
         match (method, trait_did) {
@@ -766,14 +769,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             }
             (None, None) => Err(vec![]),
             (None, Some(trait_did)) => {
-                let (obligation, _) = self.obligation_for_op_method(
-                    span,
-                    trait_did,
-                    lhs_ty,
-                    other_ty,
-                    other_ty_expr,
-                    expected,
-                );
+                let (obligation, _) =
+                    self.obligation_for_method(cause, trait_did, lhs_ty, Some(input_types));
                 Err(rustc_trait_selection::traits::fully_solve_obligation(self, obligation))
             }
         }
@@ -904,7 +901,7 @@ enum Op {
 }
 
 /// Dereferences a single level of immutable referencing.
-fn deref_ty_if_possible<'tcx>(ty: Ty<'tcx>) -> Ty<'tcx> {
+fn deref_ty_if_possible(ty: Ty<'_>) -> Ty<'_> {
     match ty.kind() {
         ty::Ref(_, ty, hir::Mutability::Not) => *ty,
         _ => ty,
diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs
index d3e88b1b80a..0021fdd7f61 100644
--- a/compiler/rustc_hir_typeck/src/pat.rs
+++ b/compiler/rustc_hir_typeck/src/pat.rs
@@ -1013,7 +1013,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         let (res, opt_ty, segments) =
             self.resolve_ty_and_res_fully_qualified_call(qpath, pat.hir_id, pat.span);
         if res == Res::Err {
-            let e = tcx.sess.delay_span_bug(pat.span, "`Res:Err` but no error emitted");
+            let e = tcx.sess.delay_span_bug(pat.span, "`Res::Err` but no error emitted");
             self.set_tainted_by_errors(e);
             on_error(e);
             return tcx.ty_error_with_guaranteed(e);
diff --git a/compiler/rustc_hir_typeck/src/place_op.rs b/compiler/rustc_hir_typeck/src/place_op.rs
index 952ea14887f..a0f048fc09b 100644
--- a/compiler/rustc_hir_typeck/src/place_op.rs
+++ b/compiler/rustc_hir_typeck/src/place_op.rs
@@ -225,7 +225,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
         imm_tr.and_then(|trait_did| {
             self.lookup_method_in_trait(
-                span,
+                self.misc(span),
                 Ident::with_dummy_span(imm_op),
                 trait_did,
                 base_ty,
@@ -264,7 +264,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
         mut_tr.and_then(|trait_did| {
             self.lookup_method_in_trait(
-                span,
+                self.misc(span),
                 Ident::with_dummy_span(mut_op),
                 trait_did,
                 base_ty,
diff --git a/compiler/rustc_hir_typeck/src/upvar.rs b/compiler/rustc_hir_typeck/src/upvar.rs
index 0f46972019e..a9347991e7f 100644
--- a/compiler/rustc_hir_typeck/src/upvar.rs
+++ b/compiler/rustc_hir_typeck/src/upvar.rs
@@ -1675,7 +1675,7 @@ fn apply_capture_kind_on_capture_ty<'tcx>(
 }
 
 /// Returns the Span of where the value with the provided HirId would be dropped
-fn drop_location_span<'tcx>(tcx: TyCtxt<'tcx>, hir_id: hir::HirId) -> Span {
+fn drop_location_span(tcx: TyCtxt<'_>, hir_id: hir::HirId) -> Span {
     let owner_id = tcx.hir().get_enclosing_scope(hir_id).unwrap();
 
     let owner_node = tcx.hir().get(owner_id);
@@ -1843,10 +1843,10 @@ fn restrict_precision_for_drop_types<'a, 'tcx>(
 /// - No projections are applied to raw pointers, since these require unsafe blocks. We capture
 ///   them completely.
 /// - No projections are applied on top of Union ADTs, since these require unsafe blocks.
-fn restrict_precision_for_unsafe<'tcx>(
-    mut place: Place<'tcx>,
+fn restrict_precision_for_unsafe(
+    mut place: Place<'_>,
     mut curr_mode: ty::UpvarCapture,
-) -> (Place<'tcx>, ty::UpvarCapture) {
+) -> (Place<'_>, ty::UpvarCapture) {
     if place.base_ty.is_unsafe_ptr() {
         truncate_place_to_len_and_update_capture_kind(&mut place, &mut curr_mode, 0);
     }
@@ -1876,10 +1876,10 @@ fn restrict_precision_for_unsafe<'tcx>(
 /// - No Index projections are captured, since arrays are captured completely.
 /// - No unsafe block is required to capture `place`
 /// Returns the truncated place and updated capture mode.
-fn restrict_capture_precision<'tcx>(
-    place: Place<'tcx>,
+fn restrict_capture_precision(
+    place: Place<'_>,
     curr_mode: ty::UpvarCapture,
-) -> (Place<'tcx>, ty::UpvarCapture) {
+) -> (Place<'_>, ty::UpvarCapture) {
     let (mut place, mut curr_mode) = restrict_precision_for_unsafe(place, curr_mode);
 
     if place.projections.is_empty() {
@@ -1904,10 +1904,10 @@ fn restrict_capture_precision<'tcx>(
 }
 
 /// Truncate deref of any reference.
-fn adjust_for_move_closure<'tcx>(
-    mut place: Place<'tcx>,
+fn adjust_for_move_closure(
+    mut place: Place<'_>,
     mut kind: ty::UpvarCapture,
-) -> (Place<'tcx>, ty::UpvarCapture) {
+) -> (Place<'_>, ty::UpvarCapture) {
     let first_deref = place.projections.iter().position(|proj| proj.kind == ProjectionKind::Deref);
 
     if let Some(idx) = first_deref {
@@ -1919,10 +1919,10 @@ fn adjust_for_move_closure<'tcx>(
 
 /// Adjust closure capture just that if taking ownership of data, only move data
 /// from enclosing stack frame.
-fn adjust_for_non_move_closure<'tcx>(
-    mut place: Place<'tcx>,
+fn adjust_for_non_move_closure(
+    mut place: Place<'_>,
     mut kind: ty::UpvarCapture,
-) -> (Place<'tcx>, ty::UpvarCapture) {
+) -> (Place<'_>, ty::UpvarCapture) {
     let contains_deref =
         place.projections.iter().position(|proj| proj.kind == ProjectionKind::Deref);
 
@@ -2225,10 +2225,10 @@ fn determine_place_ancestry_relation<'tcx>(
 ///     // it is constrained to `'a`
 /// }
 /// ```
-fn truncate_capture_for_optimization<'tcx>(
-    mut place: Place<'tcx>,
+fn truncate_capture_for_optimization(
+    mut place: Place<'_>,
     mut curr_mode: ty::UpvarCapture,
-) -> (Place<'tcx>, ty::UpvarCapture) {
+) -> (Place<'_>, ty::UpvarCapture) {
     let is_shared_ref = |ty: Ty<'_>| matches!(ty.kind(), ty::Ref(.., hir::Mutability::Not));
 
     // Find the right-most deref (if any). All the projections that come after this
diff --git a/compiler/rustc_incremental/src/assert_dep_graph.rs b/compiler/rustc_incremental/src/assert_dep_graph.rs
index b4bf9f4bcc7..67b4d6d6959 100644
--- a/compiler/rustc_incremental/src/assert_dep_graph.rs
+++ b/compiler/rustc_incremental/src/assert_dep_graph.rs
@@ -432,10 +432,7 @@ fn walk_between<'q>(
     }
 }
 
-fn filter_edges<'q>(
-    query: &'q DepGraphQuery,
-    nodes: &FxHashSet<DepKind>,
-) -> Vec<(DepKind, DepKind)> {
+fn filter_edges(query: &DepGraphQuery, nodes: &FxHashSet<DepKind>) -> Vec<(DepKind, DepKind)> {
     let uniq: FxHashSet<_> = query
         .edges()
         .into_iter()
diff --git a/compiler/rustc_infer/src/infer/canonical/query_response.rs b/compiler/rustc_infer/src/infer/canonical/query_response.rs
index 996b1c40e3f..a722613e331 100644
--- a/compiler/rustc_infer/src/infer/canonical/query_response.rs
+++ b/compiler/rustc_infer/src/infer/canonical/query_response.rs
@@ -151,7 +151,11 @@ impl<'tcx> InferCtxt<'tcx> {
         })
     }
 
-    fn take_opaque_types_for_query_response(&self) -> Vec<(Ty<'tcx>, Ty<'tcx>)> {
+    /// FIXME: This method should only be used for canonical queries and therefore be private.
+    ///
+    /// As the new solver does canonicalization slightly differently, this is also used there
+    /// for now. This should hopefully change fairly soon.
+    pub fn take_opaque_types_for_query_response(&self) -> Vec<(Ty<'tcx>, Ty<'tcx>)> {
         self.inner
             .borrow_mut()
             .opaque_type_storage
diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
index 269fc95420a..7222eb77682 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
@@ -729,7 +729,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                             format!("this and all prior arms are found to be of type `{}`", t),
                         );
                     }
-                    let outer_error_span = if any_multiline_arm {
+                    let outer = if any_multiline_arm || !source_map.is_multiline(cause.span) {
                         // Cover just `match` and the scrutinee expression, not
                         // the entire match body, to reduce diagram noise.
                         cause.span.shrink_to_lo().to(scrut_span)
@@ -737,7 +737,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                         cause.span
                     };
                     let msg = "`match` arms have incompatible types";
-                    err.span_label(outer_error_span, msg);
+                    err.span_label(outer, msg);
                     self.suggest_remove_semi_or_return_binding(
                         err,
                         prior_arm_block_id,
@@ -1836,7 +1836,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
 
         // In some (most?) cases cause.body_id points to actual body, but in some cases
         // it's an actual definition. According to the comments (e.g. in
-        // rustc_hir_analysis/check/compare_method.rs:compare_predicate_entailment) the latter
+        // rustc_hir_analysis/check/compare_impl_item.rs:compare_predicate_entailment) the latter
         // is relied upon by some other code. This might (or might not) need cleanup.
         let body_owner_def_id =
             self.tcx.hir().opt_local_def_id(cause.body_id).unwrap_or_else(|| {
@@ -2199,10 +2199,10 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
             );
         }
 
-        fn binding_suggestion<'tcx, S: fmt::Display>(
+        fn binding_suggestion<S: fmt::Display>(
             err: &mut Diagnostic,
             type_param_span: Option<(Span, bool)>,
-            bound_kind: GenericKind<'tcx>,
+            bound_kind: GenericKind<'_>,
             sub: S,
             add_lt_sugg: Option<(Span, String)>,
         ) {
diff --git a/compiler/rustc_infer/src/infer/error_reporting/note_region.rs b/compiler/rustc_infer/src/infer/error_reporting/note_region.rs
deleted file mode 100644
index 41b115f3377..00000000000
--- a/compiler/rustc_infer/src/infer/error_reporting/note_region.rs
+++ /dev/null
@@ -1,427 +0,0 @@
-use crate::errors::RegionOriginNote;
-use crate::infer::error_reporting::{note_and_explain_region, TypeErrCtxt};
-use crate::infer::{self, SubregionOrigin};
-use rustc_errors::{
-    fluent, struct_span_err, AddToDiagnostic, Diagnostic, DiagnosticBuilder, ErrorGuaranteed,
-};
-use rustc_middle::traits::ObligationCauseCode;
-use rustc_middle::ty::error::TypeError;
-use rustc_middle::ty::{self, Region};
-
-use super::ObligationCauseAsDiagArg;
-
-impl<'tcx> TypeErrCtxt<'_, 'tcx> {
-    pub(super) fn note_region_origin(&self, err: &mut Diagnostic, origin: &SubregionOrigin<'tcx>) {
-        match *origin {
-            infer::Subtype(ref trace) => RegionOriginNote::WithRequirement {
-                span: trace.cause.span,
-                requirement: ObligationCauseAsDiagArg(trace.cause.clone()),
-                expected_found: self.values_str(trace.values),
-            }
-            .add_to_diagnostic(err),
-            infer::Reborrow(span) => {
-                RegionOriginNote::Plain { span, msg: fluent::infer_reborrow }.add_to_diagnostic(err)
-            }
-            infer::ReborrowUpvar(span, ref upvar_id) => {
-                let var_name = self.tcx.hir().name(upvar_id.var_path.hir_id);
-                RegionOriginNote::WithName {
-                    span,
-                    msg: fluent::infer_reborrow,
-                    name: &var_name.to_string(),
-                    continues: false,
-                }
-                .add_to_diagnostic(err);
-            }
-            infer::RelateObjectBound(span) => {
-                RegionOriginNote::Plain { span, msg: fluent::infer_relate_object_bound }
-                    .add_to_diagnostic(err);
-            }
-            infer::DataBorrowed(ty, span) => {
-                RegionOriginNote::WithName {
-                    span,
-                    msg: fluent::infer_data_borrowed,
-                    name: &self.ty_to_string(ty),
-                    continues: false,
-                }
-                .add_to_diagnostic(err);
-            }
-            infer::ReferenceOutlivesReferent(ty, span) => {
-                RegionOriginNote::WithName {
-                    span,
-                    msg: fluent::infer_reference_outlives_referent,
-                    name: &self.ty_to_string(ty),
-                    continues: false,
-                }
-                .add_to_diagnostic(err);
-            }
-            infer::RelateParamBound(span, ty, opt_span) => {
-                RegionOriginNote::WithName {
-                    span,
-                    msg: fluent::infer_relate_param_bound,
-                    name: &self.ty_to_string(ty),
-                    continues: opt_span.is_some(),
-                }
-                .add_to_diagnostic(err);
-                if let Some(span) = opt_span {
-                    RegionOriginNote::Plain { span, msg: fluent::infer_relate_param_bound_2 }
-                        .add_to_diagnostic(err);
-                }
-            }
-            infer::RelateRegionParamBound(span) => {
-                RegionOriginNote::Plain { span, msg: fluent::infer_relate_region_param_bound }
-                    .add_to_diagnostic(err);
-            }
-            infer::CompareImplItemObligation { span, .. } => {
-                RegionOriginNote::Plain { span, msg: fluent::infer_compare_impl_item_obligation }
-                    .add_to_diagnostic(err);
-            }
-            infer::CheckAssociatedTypeBounds { ref parent, .. } => {
-                self.note_region_origin(err, &parent);
-            }
-            infer::AscribeUserTypeProvePredicate(span) => {
-                RegionOriginNote::Plain {
-                    span,
-                    msg: fluent::infer_ascribe_user_type_prove_predicate,
-                }
-                .add_to_diagnostic(err);
-            }
-        }
-    }
-
-    pub(super) fn report_concrete_failure(
-        &self,
-        origin: SubregionOrigin<'tcx>,
-        sub: Region<'tcx>,
-        sup: Region<'tcx>,
-    ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
-        match origin {
-            infer::Subtype(box trace) => {
-                let terr = TypeError::RegionsDoesNotOutlive(sup, sub);
-                let mut err = self.report_and_explain_type_error(trace, terr);
-                match (*sub, *sup) {
-                    (ty::RePlaceholder(_), ty::RePlaceholder(_)) => {}
-                    (ty::RePlaceholder(_), _) => {
-                        note_and_explain_region(
-                            self.tcx,
-                            &mut err,
-                            "",
-                            sup,
-                            " doesn't meet the lifetime requirements",
-                            None,
-                        );
-                    }
-                    (_, ty::RePlaceholder(_)) => {
-                        note_and_explain_region(
-                            self.tcx,
-                            &mut err,
-                            "the required lifetime does not necessarily outlive ",
-                            sub,
-                            "",
-                            None,
-                        );
-                    }
-                    _ => {
-                        note_and_explain_region(self.tcx, &mut err, "", sup, "...", None);
-                        note_and_explain_region(
-                            self.tcx,
-                            &mut err,
-                            "...does not necessarily outlive ",
-                            sub,
-                            "",
-                            None,
-                        );
-                    }
-                }
-                err
-            }
-            infer::Reborrow(span) => {
-                let mut err = struct_span_err!(
-                    self.tcx.sess,
-                    span,
-                    E0312,
-                    "lifetime of reference outlives lifetime of borrowed content..."
-                );
-                note_and_explain_region(
-                    self.tcx,
-                    &mut err,
-                    "...the reference is valid for ",
-                    sub,
-                    "...",
-                    None,
-                );
-                note_and_explain_region(
-                    self.tcx,
-                    &mut err,
-                    "...but the borrowed content is only valid for ",
-                    sup,
-                    "",
-                    None,
-                );
-                err
-            }
-            infer::ReborrowUpvar(span, ref upvar_id) => {
-                let var_name = self.tcx.hir().name(upvar_id.var_path.hir_id);
-                let mut err = struct_span_err!(
-                    self.tcx.sess,
-                    span,
-                    E0313,
-                    "lifetime of borrowed pointer outlives lifetime of captured variable `{}`...",
-                    var_name
-                );
-                note_and_explain_region(
-                    self.tcx,
-                    &mut err,
-                    "...the borrowed pointer is valid for ",
-                    sub,
-                    "...",
-                    None,
-                );
-                note_and_explain_region(
-                    self.tcx,
-                    &mut err,
-                    &format!("...but `{}` is only valid for ", var_name),
-                    sup,
-                    "",
-                    None,
-                );
-                err
-            }
-            infer::RelateObjectBound(span) => {
-                let mut err = struct_span_err!(
-                    self.tcx.sess,
-                    span,
-                    E0476,
-                    "lifetime of the source pointer does not outlive lifetime bound of the \
-                     object type"
-                );
-                note_and_explain_region(
-                    self.tcx,
-                    &mut err,
-                    "object type is valid for ",
-                    sub,
-                    "",
-                    None,
-                );
-                note_and_explain_region(
-                    self.tcx,
-                    &mut err,
-                    "source pointer is only valid for ",
-                    sup,
-                    "",
-                    None,
-                );
-                err
-            }
-            infer::RelateParamBound(span, ty, opt_span) => {
-                let mut err = struct_span_err!(
-                    self.tcx.sess,
-                    span,
-                    E0477,
-                    "the type `{}` does not fulfill the required lifetime",
-                    self.ty_to_string(ty)
-                );
-                match *sub {
-                    ty::ReStatic => note_and_explain_region(
-                        self.tcx,
-                        &mut err,
-                        "type must satisfy ",
-                        sub,
-                        if opt_span.is_some() { " as required by this binding" } else { "" },
-                        opt_span,
-                    ),
-                    _ => note_and_explain_region(
-                        self.tcx,
-                        &mut err,
-                        "type must outlive ",
-                        sub,
-                        if opt_span.is_some() { " as required by this binding" } else { "" },
-                        opt_span,
-                    ),
-                }
-                err
-            }
-            infer::RelateRegionParamBound(span) => {
-                let mut err =
-                    struct_span_err!(self.tcx.sess, span, E0478, "lifetime bound not satisfied");
-                note_and_explain_region(
-                    self.tcx,
-                    &mut err,
-                    "lifetime parameter instantiated with ",
-                    sup,
-                    "",
-                    None,
-                );
-                note_and_explain_region(
-                    self.tcx,
-                    &mut err,
-                    "but lifetime parameter must outlive ",
-                    sub,
-                    "",
-                    None,
-                );
-                err
-            }
-            infer::DataBorrowed(ty, span) => {
-                let mut err = struct_span_err!(
-                    self.tcx.sess,
-                    span,
-                    E0490,
-                    "a value of type `{}` is borrowed for too long",
-                    self.ty_to_string(ty)
-                );
-                note_and_explain_region(
-                    self.tcx,
-                    &mut err,
-                    "the type is valid for ",
-                    sub,
-                    "",
-                    None,
-                );
-                note_and_explain_region(
-                    self.tcx,
-                    &mut err,
-                    "but the borrow lasts for ",
-                    sup,
-                    "",
-                    None,
-                );
-                err
-            }
-            infer::ReferenceOutlivesReferent(ty, span) => {
-                let mut err = struct_span_err!(
-                    self.tcx.sess,
-                    span,
-                    E0491,
-                    "in type `{}`, reference has a longer lifetime than the data it references",
-                    self.ty_to_string(ty)
-                );
-                note_and_explain_region(
-                    self.tcx,
-                    &mut err,
-                    "the pointer is valid for ",
-                    sub,
-                    "",
-                    None,
-                );
-                note_and_explain_region(
-                    self.tcx,
-                    &mut err,
-                    "but the referenced data is only valid for ",
-                    sup,
-                    "",
-                    None,
-                );
-                err
-            }
-            infer::CompareImplItemObligation { span, impl_item_def_id, trait_item_def_id } => self
-                .report_extra_impl_obligation(
-                    span,
-                    impl_item_def_id,
-                    trait_item_def_id,
-                    &format!("`{}: {}`", sup, sub),
-                ),
-            infer::CheckAssociatedTypeBounds { impl_item_def_id, trait_item_def_id, parent } => {
-                let mut err = self.report_concrete_failure(*parent, sub, sup);
-
-                let trait_item_span = self.tcx.def_span(trait_item_def_id);
-                let item_name = self.tcx.item_name(impl_item_def_id.to_def_id());
-                err.span_label(
-                    trait_item_span,
-                    format!("definition of `{}` from trait", item_name),
-                );
-
-                let trait_predicates = self.tcx.explicit_predicates_of(trait_item_def_id);
-                let impl_predicates = self.tcx.explicit_predicates_of(impl_item_def_id);
-
-                let impl_predicates: rustc_data_structures::fx::FxHashSet<_> =
-                    impl_predicates.predicates.into_iter().map(|(pred, _)| pred).collect();
-                let clauses: Vec<_> = trait_predicates
-                    .predicates
-                    .into_iter()
-                    .filter(|&(pred, _)| !impl_predicates.contains(pred))
-                    .map(|(pred, _)| format!("{}", pred))
-                    .collect();
-
-                if !clauses.is_empty() {
-                    let generics = self.tcx.hir().get_generics(impl_item_def_id).unwrap();
-                    let where_clause_span = generics.tail_span_for_predicate_suggestion();
-
-                    let suggestion = format!(
-                        "{} {}",
-                        generics.add_where_or_trailing_comma(),
-                        clauses.join(", "),
-                    );
-                    err.span_suggestion(
-                        where_clause_span,
-                        &format!(
-                            "try copying {} from the trait",
-                            if clauses.len() > 1 { "these clauses" } else { "this clause" }
-                        ),
-                        suggestion,
-                        rustc_errors::Applicability::MaybeIncorrect,
-                    );
-                }
-
-                err
-            }
-            infer::AscribeUserTypeProvePredicate(span) => {
-                let mut err =
-                    struct_span_err!(self.tcx.sess, span, E0478, "lifetime bound not satisfied");
-                note_and_explain_region(
-                    self.tcx,
-                    &mut err,
-                    "lifetime instantiated with ",
-                    sup,
-                    "",
-                    None,
-                );
-                note_and_explain_region(
-                    self.tcx,
-                    &mut err,
-                    "but lifetime must outlive ",
-                    sub,
-                    "",
-                    None,
-                );
-                err
-            }
-        }
-    }
-
-    pub(super) fn report_placeholder_failure(
-        &self,
-        placeholder_origin: SubregionOrigin<'tcx>,
-        sub: Region<'tcx>,
-        sup: Region<'tcx>,
-    ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
-        // I can't think how to do better than this right now. -nikomatsakis
-        debug!(?placeholder_origin, ?sub, ?sup, "report_placeholder_failure");
-        match placeholder_origin {
-            infer::Subtype(box ref trace)
-                if matches!(
-                    &trace.cause.code().peel_derives(),
-                    ObligationCauseCode::BindingObligation(..)
-                        | ObligationCauseCode::ExprBindingObligation(..)
-                ) =>
-            {
-                // Hack to get around the borrow checker because trace.cause has an `Rc`.
-                if let ObligationCauseCode::BindingObligation(_, span)
-                | ObligationCauseCode::ExprBindingObligation(_, span, ..) =
-                    &trace.cause.code().peel_derives()
-                {
-                    let span = *span;
-                    let mut err = self.report_concrete_failure(placeholder_origin, sub, sup);
-                    err.span_note(span, "the lifetime requirement is introduced here");
-                    err
-                } else {
-                    unreachable!()
-                }
-            }
-            infer::Subtype(box trace) => {
-                let terr = TypeError::RegionsPlaceholderMismatch;
-                return self.report_and_explain_type_error(trace, terr);
-            }
-            _ => return self.report_concrete_failure(placeholder_origin, sub, sup),
-        }
-    }
-}
diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs
index a9ef91db059..b17a465eb38 100644
--- a/compiler/rustc_infer/src/infer/mod.rs
+++ b/compiler/rustc_infer/src/infer/mod.rs
@@ -1693,7 +1693,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
         &self,
         generic_param_scope: LocalDefId,
         outlives_env: &OutlivesEnvironment<'tcx>,
-    ) -> Option<ErrorGuaranteed> {
+    ) -> Result<(), ErrorGuaranteed> {
         let errors = self.resolve_regions(outlives_env);
 
         if let None = self.tainted_by_errors() {
@@ -1705,9 +1705,14 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
             self.report_region_errors(generic_param_scope, &errors);
         }
 
-        (!errors.is_empty()).then(|| {
-            self.tcx.sess.delay_span_bug(rustc_span::DUMMY_SP, "error should have been emitted")
-        })
+        if errors.is_empty() {
+            Ok(())
+        } else {
+            Err(self
+                .tcx
+                .sess
+                .delay_span_bug(rustc_span::DUMMY_SP, "error should have been emitted"))
+        }
     }
 
     // [Note-Type-error-reporting]
diff --git a/compiler/rustc_infer/src/infer/note.rs b/compiler/rustc_infer/src/infer/note.rs
deleted file mode 100644
index 2ccbd164faa..00000000000
--- a/compiler/rustc_infer/src/infer/note.rs
+++ /dev/null
@@ -1,203 +0,0 @@
-impl<'tcx> TypeErrCtxt<'_, 'tcx> {
-    fn note_error_origin(
-        &self,
-        err: &mut Diagnostic,
-        cause: &ObligationCause<'tcx>,
-        exp_found: Option<ty::error::ExpectedFound<Ty<'tcx>>>,
-        terr: TypeError<'tcx>,
-    ) {
-        match *cause.code() {
-            ObligationCauseCode::Pattern { origin_expr: true, span: Some(span), root_ty } => {
-                let ty = self.resolve_vars_if_possible(root_ty);
-                if !matches!(ty.kind(), ty::Infer(ty::InferTy::TyVar(_) | ty::InferTy::FreshTy(_)))
-                {
-                    // don't show type `_`
-                    if span.desugaring_kind() == Some(DesugaringKind::ForLoop)
-                        && let ty::Adt(def, substs) = ty.kind()
-                        && Some(def.did()) == self.tcx.get_diagnostic_item(sym::Option)
-                    {
-                        err.span_label(span, format!("this is an iterator with items of type `{}`", substs.type_at(0)));
-                    } else {
-                    err.span_label(span, format!("this expression has type `{}`", ty));
-                }
-                }
-                if let Some(ty::error::ExpectedFound { found, .. }) = exp_found
-                    && ty.is_box() && ty.boxed_ty() == found
-                    && let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span)
-                {
-                    err.span_suggestion(
-                        span,
-                        "consider dereferencing the boxed value",
-                        format!("*{}", snippet),
-                        Applicability::MachineApplicable,
-                    );
-                }
-            }
-            ObligationCauseCode::Pattern { origin_expr: false, span: Some(span), .. } => {
-                err.span_label(span, "expected due to this");
-            }
-            ObligationCauseCode::MatchExpressionArm(box MatchExpressionArmCause {
-                arm_block_id,
-                arm_span,
-                arm_ty,
-                prior_arm_block_id,
-                prior_arm_span,
-                prior_arm_ty,
-                source,
-                ref prior_arms,
-                scrut_hir_id,
-                opt_suggest_box_span,
-                scrut_span,
-                ..
-            }) => match source {
-                hir::MatchSource::TryDesugar => {
-                    if let Some(ty::error::ExpectedFound { expected, .. }) = exp_found {
-                        let scrut_expr = self.tcx.hir().expect_expr(scrut_hir_id);
-                        let scrut_ty = if let hir::ExprKind::Call(_, args) = &scrut_expr.kind {
-                            let arg_expr = args.first().expect("try desugaring call w/out arg");
-                            self.typeck_results.as_ref().and_then(|typeck_results| {
-                                typeck_results.expr_ty_opt(arg_expr)
-                            })
-                        } else {
-                            bug!("try desugaring w/out call expr as scrutinee");
-                        };
-
-                        match scrut_ty {
-                            Some(ty) if expected == ty => {
-                                let source_map = self.tcx.sess.source_map();
-                                err.span_suggestion(
-                                    source_map.end_point(cause.span),
-                                    "try removing this `?`",
-                                    "",
-                                    Applicability::MachineApplicable,
-                                );
-                            }
-                            _ => {}
-                        }
-                    }
-                }
-                _ => {
-                    // `prior_arm_ty` can be `!`, `expected` will have better info when present.
-                    let t = self.resolve_vars_if_possible(match exp_found {
-                        Some(ty::error::ExpectedFound { expected, .. }) => expected,
-                        _ => prior_arm_ty,
-                    });
-                    let source_map = self.tcx.sess.source_map();
-                    let mut any_multiline_arm = source_map.is_multiline(arm_span);
-                    if prior_arms.len() <= 4 {
-                        for sp in prior_arms {
-                            any_multiline_arm |= source_map.is_multiline(*sp);
-                            err.span_label(*sp, format!("this is found to be of type `{}`", t));
-                        }
-                    } else if let Some(sp) = prior_arms.last() {
-                        any_multiline_arm |= source_map.is_multiline(*sp);
-                        err.span_label(
-                            *sp,
-                            format!("this and all prior arms are found to be of type `{}`", t),
-                        );
-                    }
-                    let outer_error_span = if any_multiline_arm {
-                        // Cover just `match` and the scrutinee expression, not
-                        // the entire match body, to reduce diagram noise.
-                        cause.span.shrink_to_lo().to(scrut_span)
-                    } else {
-                        cause.span
-                    };
-                    let msg = "`match` arms have incompatible types";
-                    err.span_label(outer_error_span, msg);
-                    self.suggest_remove_semi_or_return_binding(
-                        err,
-                        prior_arm_block_id,
-                        prior_arm_ty,
-                        prior_arm_span,
-                        arm_block_id,
-                        arm_ty,
-                        arm_span,
-                    );
-                    if let Some(ret_sp) = opt_suggest_box_span {
-                        // Get return type span and point to it.
-                        self.suggest_boxing_for_return_impl_trait(
-                            err,
-                            ret_sp,
-                            prior_arms.iter().chain(std::iter::once(&arm_span)).map(|s| *s),
-                        );
-                    }
-                }
-            },
-            ObligationCauseCode::IfExpression(box IfExpressionCause {
-                then_id,
-                else_id,
-                then_ty,
-                else_ty,
-                outer_span,
-                opt_suggest_box_span,
-            }) => {
-                let then_span = self.find_block_span_from_hir_id(then_id);
-                let else_span = self.find_block_span_from_hir_id(else_id);
-                err.span_label(then_span, "expected because of this");
-                if let Some(sp) = outer_span {
-                    err.span_label(sp, "`if` and `else` have incompatible types");
-                }
-                self.suggest_remove_semi_or_return_binding(
-                    err,
-                    Some(then_id),
-                    then_ty,
-                    then_span,
-                    Some(else_id),
-                    else_ty,
-                    else_span,
-                );
-                if let Some(ret_sp) = opt_suggest_box_span {
-                    self.suggest_boxing_for_return_impl_trait(
-                        err,
-                        ret_sp,
-                        [then_span, else_span].into_iter(),
-                    );
-                }
-            }
-            ObligationCauseCode::LetElse => {
-                err.help("try adding a diverging expression, such as `return` or `panic!(..)`");
-                err.help("...or use `match` instead of `let...else`");
-            }
-            _ => {
-                if let ObligationCauseCode::BindingObligation(_, span)
-                | ObligationCauseCode::ExprBindingObligation(_, span, ..)
-                = cause.code().peel_derives()
-                    && let TypeError::RegionsPlaceholderMismatch = terr
-                {
-                    err.span_note( * span,
-                    "the lifetime requirement is introduced here");
-                }
-            }
-        }
-    }
-}
-
-impl<'tcx> InferCtxt<'tcx> {
-    /// Given a [`hir::Block`], get the span of its last expression or
-    /// statement, peeling off any inner blocks.
-    pub fn find_block_span(&self, block: &'tcx hir::Block<'tcx>) -> Span {
-        let block = block.innermost_block();
-        if let Some(expr) = &block.expr {
-            expr.span
-        } else if let Some(stmt) = block.stmts.last() {
-            // possibly incorrect trailing `;` in the else arm
-            stmt.span
-        } else {
-            // empty block; point at its entirety
-            block.span
-        }
-    }
-
-    /// Given a [`hir::HirId`] for a block, get the span of its last expression
-    /// or statement, peeling off any inner blocks.
-    pub fn find_block_span_from_hir_id(&self, hir_id: hir::HirId) -> Span {
-        match self.tcx.hir().get(hir_id) {
-            hir::Node::Block(blk) => self.find_block_span(blk),
-            // The parser was in a weird state if either of these happen, but
-            // it's better not to panic.
-            hir::Node::Expr(e) => e.span,
-            _ => rustc_span::DUMMY_SP,
-        }
-    }
-}
diff --git a/compiler/rustc_infer/src/infer/outlives/obligations.rs b/compiler/rustc_infer/src/infer/outlives/obligations.rs
index 47bd1564f08..f71c39dc0d2 100644
--- a/compiler/rustc_infer/src/infer/outlives/obligations.rs
+++ b/compiler/rustc_infer/src/infer/outlives/obligations.rs
@@ -178,7 +178,7 @@ impl<'tcx> InferCtxt<'tcx> {
         &self,
         generic_param_scope: LocalDefId,
         outlives_env: &OutlivesEnvironment<'tcx>,
-    ) -> Option<ErrorGuaranteed> {
+    ) -> Result<(), ErrorGuaranteed> {
         self.process_registered_region_obligations(
             outlives_env.region_bound_pairs(),
             outlives_env.param_env,
diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs
index e903cb86dd2..ff2196d5857 100644
--- a/compiler/rustc_interface/src/tests.rs
+++ b/compiler/rustc_interface/src/tests.rs
@@ -754,6 +754,7 @@ fn test_unstable_options_tracking_hash() {
     tracked!(move_size_limit, Some(4096));
     tracked!(mutable_noalias, Some(true));
     tracked!(no_generate_arange_section, true);
+    tracked!(no_jump_tables, true);
     tracked!(no_link, true);
     tracked!(no_profiler_runtime, true);
     tracked!(no_unique_section_names, true);
diff --git a/compiler/rustc_lexer/src/lib.rs b/compiler/rustc_lexer/src/lib.rs
index 50d6d5b9bab..4c65fca29b8 100644
--- a/compiler/rustc_lexer/src/lib.rs
+++ b/compiler/rustc_lexer/src/lib.rs
@@ -851,7 +851,7 @@ impl Cursor<'_> {
     }
 
     // Eats the identifier. Note: succeeds on `_`, which isn't a valid
-    // identifer.
+    // identifier.
     fn eat_identifier(&mut self) {
         if !is_id_start(self.first()) {
             return;
diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs
index cd19e65b6fc..cdb901b7f86 100644
--- a/compiler/rustc_lint/src/builtin.rs
+++ b/compiler/rustc_lint/src/builtin.rs
@@ -25,6 +25,7 @@ use crate::{
     types::{transparent_newtype_field, CItemKind},
     EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext,
 };
+use hir::IsAsync;
 use rustc_ast::attr;
 use rustc_ast::tokenstream::{TokenStream, TokenTree};
 use rustc_ast::visit::{FnCtxt, FnKind};
@@ -40,7 +41,10 @@ use rustc_feature::{deprecated_attributes, AttributeGate, BuiltinAttribute, Gate
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::{DefId, LocalDefId, LocalDefIdSet, CRATE_DEF_ID};
-use rustc_hir::{ForeignItemKind, GenericParamKind, HirId, Node, PatKind, PredicateOrigin};
+use rustc_hir::intravisit::FnKind as HirFnKind;
+use rustc_hir::{
+    Body, FnDecl, ForeignItemKind, GenericParamKind, HirId, Node, PatKind, PredicateOrigin,
+};
 use rustc_index::vec::Idx;
 use rustc_middle::lint::in_external_macro;
 use rustc_middle::ty::layout::{LayoutError, LayoutOf};
@@ -1371,6 +1375,72 @@ impl<'tcx> LateLintPass<'tcx> for UnstableFeatures {
 }
 
 declare_lint! {
+    /// The `ungated_async_fn_track_caller` lint warns when the
+    /// `#[track_caller]` attribute is used on an async function, method, or
+    /// closure, without enabling the corresponding unstable feature flag.
+    ///
+    /// ### Example
+    ///
+    /// ```rust
+    /// #[track_caller]
+    /// async fn foo() {}
+    /// ```
+    ///
+    /// {{produces}}
+    ///
+    /// ### Explanation
+    ///
+    /// The attribute must be used in conjunction with the
+    /// [`closure_track_caller` feature flag]. Otherwise, the `#[track_caller]`
+    /// annotation will function as as no-op.
+    ///
+    /// [`closure_track_caller` feature flag]: https://doc.rust-lang.org/beta/unstable-book/language-features/closure-track-caller.html
+    UNGATED_ASYNC_FN_TRACK_CALLER,
+    Warn,
+    "enabling track_caller on an async fn is a no-op unless the closure_track_caller feature is enabled"
+}
+
+declare_lint_pass!(
+    /// Explains corresponding feature flag must be enabled for the `#[track_caller] attribute to
+    /// do anything
+    UngatedAsyncFnTrackCaller => [UNGATED_ASYNC_FN_TRACK_CALLER]
+);
+
+impl<'tcx> LateLintPass<'tcx> for UngatedAsyncFnTrackCaller {
+    fn check_fn(
+        &mut self,
+        cx: &LateContext<'_>,
+        fn_kind: HirFnKind<'_>,
+        _: &'tcx FnDecl<'_>,
+        _: &'tcx Body<'_>,
+        span: Span,
+        hir_id: HirId,
+    ) {
+        if fn_kind.asyncness() == IsAsync::Async
+            && !cx.tcx.features().closure_track_caller
+            && let attrs = cx.tcx.hir().attrs(hir_id)
+            // Now, check if the function has the `#[track_caller]` attribute
+            && let Some(attr) = attrs.iter().find(|attr| attr.has_name(sym::track_caller))
+            {
+                cx.struct_span_lint(
+                    UNGATED_ASYNC_FN_TRACK_CALLER,
+                    attr.span,
+                    fluent::lint_ungated_async_fn_track_caller,
+                    |lint| {
+                        lint.span_label(span, fluent::label);
+                        rustc_session::parse::add_feature_diagnostics(
+                            lint,
+                            &cx.tcx.sess.parse_sess,
+                            sym::closure_track_caller,
+                        );
+                        lint
+                    },
+                );
+            }
+    }
+}
+
+declare_lint! {
     /// The `unreachable_pub` lint triggers for `pub` items not reachable from
     /// the crate root.
     ///
@@ -2114,6 +2184,7 @@ impl ExplicitOutlivesRequirements {
         tcx: TyCtxt<'tcx>,
         bounds: &hir::GenericBounds<'_>,
         inferred_outlives: &[ty::Region<'tcx>],
+        predicate_span: Span,
     ) -> Vec<(usize, Span)> {
         use rustc_middle::middle::resolve_lifetime::Region;
 
@@ -2121,23 +2192,28 @@ impl ExplicitOutlivesRequirements {
             .iter()
             .enumerate()
             .filter_map(|(i, bound)| {
-                if let hir::GenericBound::Outlives(lifetime) = bound {
-                    let is_inferred = match tcx.named_region(lifetime.hir_id) {
-                        Some(Region::EarlyBound(def_id)) => inferred_outlives.iter().any(|r| {
-                            if let ty::ReEarlyBound(ebr) = **r {
-                                ebr.def_id == def_id
-                            } else {
-                                false
-                            }
-                        }),
-                        _ => false,
-                    };
-                    is_inferred.then_some((i, bound.span()))
-                } else {
-                    None
+                let hir::GenericBound::Outlives(lifetime) = bound else {
+                    return None;
+                };
+
+                let is_inferred = match tcx.named_region(lifetime.hir_id) {
+                    Some(Region::EarlyBound(def_id)) => inferred_outlives
+                        .iter()
+                        .any(|r| matches!(**r, ty::ReEarlyBound(ebr) if { ebr.def_id == def_id })),
+                    _ => false,
+                };
+
+                if !is_inferred {
+                    return None;
                 }
+
+                let span = bound.span().find_ancestor_inside(predicate_span)?;
+                if in_external_macro(tcx.sess, span) {
+                    return None;
+                }
+
+                Some((i, span))
             })
-            .filter(|(_, span)| !in_external_macro(tcx.sess, *span))
             .collect()
     }
 
@@ -2203,9 +2279,9 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitOutlivesRequirements {
         use rustc_middle::middle::resolve_lifetime::Region;
 
         let def_id = item.owner_id.def_id;
-        if let hir::ItemKind::Struct(_, ref hir_generics)
-        | hir::ItemKind::Enum(_, ref hir_generics)
-        | hir::ItemKind::Union(_, ref hir_generics) = item.kind
+        if let hir::ItemKind::Struct(_, hir_generics)
+        | hir::ItemKind::Enum(_, hir_generics)
+        | hir::ItemKind::Union(_, hir_generics) = item.kind
         {
             let inferred_outlives = cx.tcx.inferred_outlives_of(def_id);
             if inferred_outlives.is_empty() {
@@ -2220,53 +2296,58 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitOutlivesRequirements {
             let mut dropped_predicate_count = 0;
             let num_predicates = hir_generics.predicates.len();
             for (i, where_predicate) in hir_generics.predicates.iter().enumerate() {
-                let (relevant_lifetimes, bounds, span, in_where_clause) = match where_predicate {
-                    hir::WherePredicate::RegionPredicate(predicate) => {
-                        if let Some(Region::EarlyBound(region_def_id)) =
-                            cx.tcx.named_region(predicate.lifetime.hir_id)
-                        {
-                            (
-                                Self::lifetimes_outliving_lifetime(
-                                    inferred_outlives,
-                                    region_def_id,
-                                ),
-                                &predicate.bounds,
-                                predicate.span,
-                                predicate.in_where_clause,
-                            )
-                        } else {
-                            continue;
-                        }
-                    }
-                    hir::WherePredicate::BoundPredicate(predicate) => {
-                        // FIXME we can also infer bounds on associated types,
-                        // and should check for them here.
-                        match predicate.bounded_ty.kind {
-                            hir::TyKind::Path(hir::QPath::Resolved(None, ref path)) => {
-                                let Res::Def(DefKind::TyParam, def_id) = path.res else {
-                                    continue
-                                };
-                                let index = ty_generics.param_def_id_to_index[&def_id];
+                let (relevant_lifetimes, bounds, predicate_span, in_where_clause) =
+                    match where_predicate {
+                        hir::WherePredicate::RegionPredicate(predicate) => {
+                            if let Some(Region::EarlyBound(region_def_id)) =
+                                cx.tcx.named_region(predicate.lifetime.hir_id)
+                            {
                                 (
-                                    Self::lifetimes_outliving_type(inferred_outlives, index),
+                                    Self::lifetimes_outliving_lifetime(
+                                        inferred_outlives,
+                                        region_def_id,
+                                    ),
                                     &predicate.bounds,
                                     predicate.span,
-                                    predicate.origin == PredicateOrigin::WhereClause,
+                                    predicate.in_where_clause,
                                 )
-                            }
-                            _ => {
+                            } else {
                                 continue;
                             }
                         }
-                    }
-                    _ => continue,
-                };
+                        hir::WherePredicate::BoundPredicate(predicate) => {
+                            // FIXME we can also infer bounds on associated types,
+                            // and should check for them here.
+                            match predicate.bounded_ty.kind {
+                                hir::TyKind::Path(hir::QPath::Resolved(None, path)) => {
+                                    let Res::Def(DefKind::TyParam, def_id) = path.res else {
+                                    continue;
+                                };
+                                    let index = ty_generics.param_def_id_to_index[&def_id];
+                                    (
+                                        Self::lifetimes_outliving_type(inferred_outlives, index),
+                                        &predicate.bounds,
+                                        predicate.span,
+                                        predicate.origin == PredicateOrigin::WhereClause,
+                                    )
+                                }
+                                _ => {
+                                    continue;
+                                }
+                            }
+                        }
+                        _ => continue,
+                    };
                 if relevant_lifetimes.is_empty() {
                     continue;
                 }
 
-                let bound_spans =
-                    self.collect_outlives_bound_spans(cx.tcx, bounds, &relevant_lifetimes);
+                let bound_spans = self.collect_outlives_bound_spans(
+                    cx.tcx,
+                    bounds,
+                    &relevant_lifetimes,
+                    predicate_span,
+                );
                 bound_count += bound_spans.len();
 
                 let drop_predicate = bound_spans.len() == bounds.len();
@@ -2275,15 +2356,15 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitOutlivesRequirements {
                 }
 
                 if drop_predicate && !in_where_clause {
-                    lint_spans.push(span);
+                    lint_spans.push(predicate_span);
                 } else if drop_predicate && i + 1 < num_predicates {
                     // If all the bounds on a predicate were inferable and there are
                     // further predicates, we want to eat the trailing comma.
                     let next_predicate_span = hir_generics.predicates[i + 1].span();
-                    where_lint_spans.push(span.to(next_predicate_span.shrink_to_lo()));
+                    where_lint_spans.push(predicate_span.to(next_predicate_span.shrink_to_lo()));
                 } else {
                     where_lint_spans.extend(self.consolidate_outlives_bound_spans(
-                        span.shrink_to_lo(),
+                        predicate_span.shrink_to_lo(),
                         bounds,
                         bound_spans,
                     ));
@@ -2304,12 +2385,26 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitOutlivesRequirements {
                     } else {
                         hir_generics.span.shrink_to_hi().to(where_span)
                     };
-                lint_spans.push(full_where_span);
+
+                // Due to macro expansions, the `full_where_span` might not actually contain all predicates.
+                if where_lint_spans.iter().all(|&sp| full_where_span.contains(sp)) {
+                    lint_spans.push(full_where_span);
+                } else {
+                    lint_spans.extend(where_lint_spans);
+                }
             } else {
                 lint_spans.extend(where_lint_spans);
             }
 
             if !lint_spans.is_empty() {
+                // Do not automatically delete outlives requirements from macros.
+                let applicability = if lint_spans.iter().all(|sp| sp.can_be_used_for_suggestions())
+                {
+                    Applicability::MachineApplicable
+                } else {
+                    Applicability::MaybeIncorrect
+                };
+
                 cx.struct_span_lint(
                     EXPLICIT_OUTLIVES_REQUIREMENTS,
                     lint_spans.clone(),
@@ -2317,11 +2412,8 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitOutlivesRequirements {
                     |lint| {
                         lint.set_arg("count", bound_count).multipart_suggestion(
                             fluent::suggestion,
-                            lint_spans
-                                .into_iter()
-                                .map(|span| (span, String::new()))
-                                .collect::<Vec<_>>(),
-                            Applicability::MachineApplicable,
+                            lint_spans.into_iter().map(|span| (span, String::new())).collect(),
+                            applicability,
                         )
                     },
                 );
diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs
index 0417f375588..a16bb7f1a5f 100644
--- a/compiler/rustc_lint/src/context.rs
+++ b/compiler/rustc_lint/src/context.rs
@@ -355,14 +355,12 @@ impl LintStore {
                     sub: RequestedLevel { level, lint_name },
                 });
             }
-            CheckLintNameResult::Tool(result) => {
-                if let Err((Some(_), new_name)) = result {
-                    sess.emit_warning(CheckNameDeprecated {
-                        lint_name: lint_name.clone(),
-                        new_name,
-                        sub: RequestedLevel { level, lint_name },
-                    });
-                }
+            CheckLintNameResult::Tool(Err((Some(_), new_name))) => {
+                sess.emit_warning(CheckNameDeprecated {
+                    lint_name: lint_name.clone(),
+                    new_name,
+                    sub: RequestedLevel { level, lint_name },
+                });
             }
             CheckLintNameResult::NoTool => {
                 sess.emit_err(CheckNameUnknownTool {
@@ -483,7 +481,16 @@ impl LintStore {
             return CheckLintNameResult::NoLint(Some(Symbol::intern(&name_lower)));
         }
         // ...if not, search for lints with a similar name
-        let groups = self.lint_groups.keys().copied().map(Symbol::intern);
+        // Note: find_best_match_for_name depends on the sort order of its input vector.
+        // To ensure deterministic output, sort elements of the lint_groups hash map.
+        // Also, never suggest deprecated lint groups.
+        let mut groups: Vec<_> = self
+            .lint_groups
+            .iter()
+            .filter_map(|(k, LintGroup { depr, .. })| if depr.is_none() { Some(k) } else { None })
+            .collect();
+        groups.sort();
+        let groups = groups.iter().map(|k| Symbol::intern(k));
         let lints = self.lints.iter().map(|l| Symbol::intern(&l.name_lower()));
         let names: Vec<Symbol> = groups.chain(lints).collect();
         let suggestion = find_best_match_for_name(&names, Symbol::intern(&name_lower), None);
diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs
index 11022eb80ea..44ee4172675 100644
--- a/compiler/rustc_lint/src/lib.rs
+++ b/compiler/rustc_lint/src/lib.rs
@@ -61,6 +61,7 @@ mod late;
 mod let_underscore;
 mod levels;
 mod methods;
+mod multiple_supertrait_upcastable;
 mod non_ascii_idents;
 mod non_fmt_panic;
 mod nonstandard_style;
@@ -95,6 +96,7 @@ use hidden_unicode_codepoints::*;
 use internal::*;
 use let_underscore::*;
 use methods::*;
+use multiple_supertrait_upcastable::*;
 use non_ascii_idents::*;
 use non_fmt_panic::NonPanicFmt;
 use nonstandard_style::*;
@@ -219,6 +221,7 @@ late_lint_methods!(
             // May Depend on constants elsewhere
             UnusedBrokenConst: UnusedBrokenConst,
             UnstableFeatures: UnstableFeatures,
+            UngatedAsyncFnTrackCaller: UngatedAsyncFnTrackCaller,
             ArrayIntoIter: ArrayIntoIter::default(),
             DropTraitConstraints: DropTraitConstraints,
             TemporaryCStringAsPtr: TemporaryCStringAsPtr,
@@ -228,6 +231,7 @@ late_lint_methods!(
             InvalidAtomicOrdering: InvalidAtomicOrdering,
             NamedAsmLabels: NamedAsmLabels,
             OpaqueHiddenInferredBound: OpaqueHiddenInferredBound,
+            MultipleSupertraitUpcastable: MultipleSupertraitUpcastable,
         ]
     ]
 );
diff --git a/compiler/rustc_lint/src/multiple_supertrait_upcastable.rs b/compiler/rustc_lint/src/multiple_supertrait_upcastable.rs
new file mode 100644
index 00000000000..5861b826b1c
--- /dev/null
+++ b/compiler/rustc_lint/src/multiple_supertrait_upcastable.rs
@@ -0,0 +1,63 @@
+use crate::{LateContext, LateLintPass, LintContext};
+
+use rustc_errors::DelayDm;
+use rustc_hir as hir;
+use rustc_span::sym;
+
+declare_lint! {
+    /// The `multiple_supertrait_upcastable` lint detects when an object-safe trait has multiple
+    /// supertraits.
+    ///
+    /// ### Example
+    ///
+    /// ```rust
+    /// trait A {}
+    /// trait B {}
+    ///
+    /// #[warn(multiple_supertrait_upcastable)]
+    /// trait C: A + B {}
+    /// ```
+    ///
+    /// {{produces}}
+    ///
+    /// ### Explanation
+    ///
+    /// To support upcasting with multiple supertraits, we need to store multiple vtables and this
+    /// can result in extra space overhead, even if no code actually uses upcasting.
+    /// This lint allows users to identify when such scenarios occur and to decide whether the
+    /// additional overhead is justified.
+    pub MULTIPLE_SUPERTRAIT_UPCASTABLE,
+    Allow,
+    "detect when an object-safe trait has multiple supertraits",
+    @feature_gate = sym::multiple_supertrait_upcastable;
+}
+
+declare_lint_pass!(MultipleSupertraitUpcastable => [MULTIPLE_SUPERTRAIT_UPCASTABLE]);
+
+impl<'tcx> LateLintPass<'tcx> for MultipleSupertraitUpcastable {
+    fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'tcx>) {
+        let def_id = item.owner_id.to_def_id();
+        if let hir::ItemKind::Trait(_, _, _, _, _) = item.kind
+            && cx.tcx.is_object_safe(def_id)
+        {
+            let direct_super_traits_iter = cx.tcx
+                    .super_predicates_of(def_id)
+                    .predicates
+                    .into_iter()
+                    .filter_map(|(pred, _)| pred.to_opt_poly_trait_pred());
+            if direct_super_traits_iter.count() > 1 {
+                cx.struct_span_lint(
+                    MULTIPLE_SUPERTRAIT_UPCASTABLE,
+                    cx.tcx.def_span(def_id),
+                    DelayDm(|| {
+                        format!(
+                            "`{}` is object-safe and has multiple supertraits",
+                            item.ident,
+                        )
+                    }),
+                    |diag| diag,
+                );
+            }
+        }
+    }
+}
diff --git a/compiler/rustc_lint/src/non_fmt_panic.rs b/compiler/rustc_lint/src/non_fmt_panic.rs
index c1820ac4d1e..8dccfe0046c 100644
--- a/compiler/rustc_lint/src/non_fmt_panic.rs
+++ b/compiler/rustc_lint/src/non_fmt_panic.rs
@@ -304,7 +304,7 @@ fn check_panic_str<'tcx>(
 
 /// Given the span of `some_macro!(args);`, gives the span of `(` and `)`,
 /// and the type of (opening) delimiter used.
-fn find_delimiters<'tcx>(cx: &LateContext<'tcx>, span: Span) -> Option<(Span, Span, char)> {
+fn find_delimiters(cx: &LateContext<'_>, span: Span) -> Option<(Span, Span, char)> {
     let snippet = cx.sess().parse_sess.source_map().span_to_snippet(span).ok()?;
     let (open, open_ch) = snippet.char_indices().find(|&(_, c)| "([{".contains(c))?;
     let close = snippet.rfind(|c| ")]}".contains(c))?;
diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs
index 3b8df61a0ea..a7a5234049f 100644
--- a/compiler/rustc_lint/src/unused.rs
+++ b/compiler/rustc_lint/src/unused.rs
@@ -1142,6 +1142,7 @@ impl UnusedDelimLint for UnusedBraces {
                             && !cx.sess().source_map().is_multiline(value.span)
                             && value.attrs.is_empty()
                             && !value.span.from_expansion()
+                            && !inner.span.from_expansion()
                         {
                             self.emit_unused_delims_expr(cx, value, ctx, left_pos, right_pos)
                         }
diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs
index f7a4103f4d5..28317d6cea0 100644
--- a/compiler/rustc_lint_defs/src/builtin.rs
+++ b/compiler/rustc_lint_defs/src/builtin.rs
@@ -1405,7 +1405,7 @@ declare_lint! {
     /// struct S;
     ///
     /// impl S {
-    ///     fn late<'a, 'b>(self, _: &'a u8, _: &'b u8) {}
+    ///     fn late(self, _: &u8, _: &u8) {}
     /// }
     ///
     /// fn main() {
@@ -3581,7 +3581,7 @@ declare_lint! {
     /// fn main() {
     ///     let x: String = "3".try_into().unwrap();
     ///     //                  ^^^^^^^^
-    ///     // This call to try_into matches both Foo:try_into and TryInto::try_into as
+    ///     // This call to try_into matches both Foo::try_into and TryInto::try_into as
     ///     // `TryInto` has been added to the Rust prelude in 2021 edition.
     ///     println!("{x}");
     /// }
diff --git a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs
index 446aebe4f83..767db367322 100644
--- a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs
+++ b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs
@@ -29,7 +29,7 @@ impl SubdiagnosticDeriveBuilder {
         Self { diag, f }
     }
 
-    pub(crate) fn into_tokens<'a>(self, mut structure: Structure<'a>) -> TokenStream {
+    pub(crate) fn into_tokens(self, mut structure: Structure<'_>) -> TokenStream {
         let implementation = {
             let ast = structure.ast();
             let span = ast.span().unwrap();
diff --git a/compiler/rustc_macros/src/diagnostics/utils.rs b/compiler/rustc_macros/src/diagnostics/utils.rs
index da90233523c..4ff9c777ad8 100644
--- a/compiler/rustc_macros/src/diagnostics/utils.rs
+++ b/compiler/rustc_macros/src/diagnostics/utils.rs
@@ -385,7 +385,7 @@ impl quote::ToTokens for Applicability {
 
 /// Build the mapping of field names to fields. This allows attributes to peek values from
 /// other fields.
-pub(super) fn build_field_mapping<'v>(variant: &VariantInfo<'v>) -> HashMap<String, TokenStream> {
+pub(super) fn build_field_mapping(variant: &VariantInfo<'_>) -> HashMap<String, TokenStream> {
     let mut fields_map = FieldMap::new();
     for binding in variant.bindings() {
         if let Some(ident) = &binding.ast().ident {
diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs
index 9ce3ff98ba9..b34dc0df1e2 100644
--- a/compiler/rustc_metadata/src/creader.rs
+++ b/compiler/rustc_metadata/src/creader.rs
@@ -520,8 +520,8 @@ impl<'a> CrateLoader<'a> {
         }))
     }
 
-    fn resolve_crate<'b>(
-        &'b mut self,
+    fn resolve_crate(
+        &mut self,
         name: Symbol,
         span: Span,
         dep_kind: CrateDepKind,
diff --git a/compiler/rustc_metadata/src/locator.rs b/compiler/rustc_metadata/src/locator.rs
index 15546092e41..dda5f4bac42 100644
--- a/compiler/rustc_metadata/src/locator.rs
+++ b/compiler/rustc_metadata/src/locator.rs
@@ -1011,11 +1011,7 @@ impl CrateError {
                 sess.emit_err(SymbolConflictsOthers { span, crate_name: root_name });
             }
             CrateError::StableCrateIdCollision(crate_name0, crate_name1) => {
-                sess.emit_err(StableCrateIdCollision {
-                    span,
-                    crate_name0: crate_name0,
-                    crate_name1: crate_name1,
-                });
+                sess.emit_err(StableCrateIdCollision { span, crate_name0, crate_name1 });
             }
             CrateError::DlOpen(s) | CrateError::DlSym(s) => {
                 sess.emit_err(DlError { span, err: s });
@@ -1074,7 +1070,7 @@ impl CrateError {
                     }
                     sess.emit_err(NoCrateWithTriple {
                         span,
-                        crate_name: crate_name,
+                        crate_name,
                         locator_triple: locator.triple.triple(),
                         add_info,
                         found_crates,
diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs
index 4370d4bd758..99d8225a4c3 100644
--- a/compiler/rustc_metadata/src/rmeta/decoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/decoder.rs
@@ -78,10 +78,6 @@ pub(crate) struct CrateMetadata {
     blob: MetadataBlob,
 
     // --- Some data pre-decoded from the metadata blob, usually for performance ---
-    /// NOTE(eddyb) we pass `'static` to a `'tcx` parameter because this
-    /// lifetime is only used behind `LazyValue`, `LazyArray`, or `LazyTable`, and therefore acts like a
-    /// universal (`for<'tcx>`), that is paired up with whichever `TyCtxt`
-    /// is being used to decode those values.
     root: CrateRoot,
     /// Trait impl data.
     /// FIXME: Used only from queries and can use query cache,
@@ -688,10 +684,10 @@ impl MetadataBlob {
     pub(crate) fn get_root(&self) -> CrateRoot {
         let slice = &self.blob()[..];
         let offset = METADATA_HEADER.len();
-        let pos = (((slice[offset + 0] as u32) << 24)
-            | ((slice[offset + 1] as u32) << 16)
-            | ((slice[offset + 2] as u32) << 8)
-            | ((slice[offset + 3] as u32) << 0)) as usize;
+
+        let pos_bytes = slice[offset..][..4].try_into().unwrap();
+        let pos = u32::from_be_bytes(pos_bytes) as usize;
+
         LazyValue::<CrateRoot>::from_position(NonZeroUsize::new(pos).unwrap()).decode(self)
     }
 
@@ -702,16 +698,14 @@ impl MetadataBlob {
         writeln!(out, "hash {} stable_crate_id {:?}", root.hash, root.stable_crate_id)?;
         writeln!(out, "proc_macro {:?}", root.proc_macro_data.is_some())?;
         writeln!(out, "=External Dependencies=")?;
+
         for (i, dep) in root.crate_deps.decode(self).enumerate() {
+            let CrateDep { name, extra_filename, hash, host_hash, kind } = dep;
+            let number = i + 1;
+
             writeln!(
                 out,
-                "{} {}{} hash {} host_hash {:?} kind {:?}",
-                i + 1,
-                dep.name,
-                dep.extra_filename,
-                dep.hash,
-                dep.host_hash,
-                dep.kind
+                "{number} {name}{extra_filename} hash {hash} host_hash {host_hash:?} kind {kind:?}"
             )?;
         }
         write!(out, "\n")?;
diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
index 9d0ccfeb168..e167bbf57e6 100644
--- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
+++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
@@ -223,7 +223,7 @@ provide! { tcx, def_id, other, cdata,
     generator_kind => { table }
     trait_def => { table }
     deduced_param_attrs => { table }
-    collect_trait_impl_trait_tys => {
+    collect_return_position_impl_trait_in_trait_tys => {
         Ok(cdata
             .root
             .tables
diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs
index 4af423f2a22..214a5842233 100644
--- a/compiler/rustc_metadata/src/rmeta/encoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/encoder.rs
@@ -76,7 +76,7 @@ pub(super) struct EncodeContext<'a, 'tcx> {
     symbol_table: FxHashMap<Symbol, usize>,
 }
 
-/// If the current crate is a proc-macro, returns early with `Lazy:empty()`.
+/// If the current crate is a proc-macro, returns early with `LazyArray::empty()`.
 /// This is useful for skipping the encoding of things that aren't needed
 /// for proc-macro crates.
 macro_rules! empty_proc_macro {
@@ -713,7 +713,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
         let computed_total_bytes: usize = stats.iter().map(|(_, size)| size).sum();
         assert_eq!(total_bytes, computed_total_bytes);
 
-        if tcx.sess.meta_stats() {
+        if tcx.sess.opts.unstable_opts.meta_stats {
             self.opaque.flush();
 
             // Rewind and re-read all the metadata to count the zero bytes we wrote.
@@ -1093,7 +1093,7 @@ fn should_encode_const(def_kind: DefKind) -> bool {
     }
 }
 
-fn should_encode_trait_impl_trait_tys<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> bool {
+fn should_encode_trait_impl_trait_tys(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
     if tcx.def_kind(def_id) != DefKind::AssocFn {
         return false;
     }
@@ -1197,7 +1197,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
                 record!(self.tables.params_in_repr[def_id] <- params_in_repr);
             }
             if should_encode_trait_impl_trait_tys(tcx, def_id)
-                && let Ok(table) = self.tcx.collect_trait_impl_trait_tys(def_id)
+                && let Ok(table) = self.tcx.collect_return_position_impl_trait_in_trait_tys(def_id)
             {
                 record!(self.tables.trait_impl_trait_tys[def_id] <- table);
             }
@@ -1564,7 +1564,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
                 let trait_ref = self.tcx.impl_trait_ref(def_id);
                 if let Some(trait_ref) = trait_ref {
                     let trait_def = self.tcx.trait_def(trait_ref.def_id);
-                    if let Some(mut an) = trait_def.ancestors(self.tcx, def_id).ok() {
+                    if let Ok(mut an) = trait_def.ancestors(self.tcx, def_id) {
                         if let Some(specialization_graph::Node::Impl(parent)) = an.nth(1) {
                             self.tables.impl_parent.set(def_id.index, parent.into());
                         }
diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs
index 6b60577c902..26a41f633ff 100644
--- a/compiler/rustc_metadata/src/rmeta/mod.rs
+++ b/compiler/rustc_metadata/src/rmeta/mod.rs
@@ -416,11 +416,6 @@ struct VariantData {
     is_non_exhaustive: bool,
 }
 
-#[derive(TyEncodable, TyDecodable)]
-struct GeneratorData<'tcx> {
-    layout: mir::GeneratorLayout<'tcx>,
-}
-
 // Tags used for encoding Spans:
 const TAG_VALID_SPAN_LOCAL: u8 = 0;
 const TAG_VALID_SPAN_FOREIGN: u8 = 1;
diff --git a/compiler/rustc_middle/Cargo.toml b/compiler/rustc_middle/Cargo.toml
index cf1ab47de86..543bd56a20c 100644
--- a/compiler/rustc_middle/Cargo.toml
+++ b/compiler/rustc_middle/Cargo.toml
@@ -18,6 +18,8 @@ rustc_ast = { path = "../rustc_ast" }
 rustc_attr = { path = "../rustc_attr" }
 rustc_data_structures = { path = "../rustc_data_structures" }
 rustc_errors = { path = "../rustc_errors" }
+# Used for intra-doc links
+rustc_error_messages = { path = "../rustc_error_messages" }
 rustc_feature = { path = "../rustc_feature" }
 rustc_graphviz = { path = "../rustc_graphviz" }
 rustc_hir = { path = "../rustc_hir" }
diff --git a/compiler/rustc_middle/src/dep_graph/dep_node.rs b/compiler/rustc_middle/src/dep_graph/dep_node.rs
index 6b556826918..865bb70afb5 100644
--- a/compiler/rustc_middle/src/dep_graph/dep_node.rs
+++ b/compiler/rustc_middle/src/dep_graph/dep_node.rs
@@ -175,7 +175,7 @@ impl DepNodeExt for DepNode {
     /// DepNode. Condition (2) might not be fulfilled if a DepNode
     /// refers to something from the previous compilation session that
     /// has been removed.
-    fn extract_def_id<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Option<DefId> {
+    fn extract_def_id(&self, tcx: TyCtxt<'_>) -> Option<DefId> {
         if tcx.fingerprint_style(self.kind) == FingerprintStyle::DefPathHash {
             Some(tcx.def_path_hash_to_def_id(DefPathHash(self.hash.into()), &mut || {
                 panic!("Failed to extract DefId: {:?} {}", self.kind, self.hash)
diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs
index 0450abed51b..99e692ccb58 100644
--- a/compiler/rustc_middle/src/hir/map/mod.rs
+++ b/compiler/rustc_middle/src/hir/map/mod.rs
@@ -18,7 +18,7 @@ use rustc_span::Span;
 use rustc_target::spec::abi::Abi;
 
 #[inline]
-pub fn associated_body<'hir>(node: Node<'hir>) -> Option<BodyId> {
+pub fn associated_body(node: Node<'_>) -> Option<BodyId> {
     match node {
         Node::Item(Item {
             kind: ItemKind::Const(_, body) | ItemKind::Static(.., body) | ItemKind::Fn(.., body),
@@ -41,7 +41,7 @@ pub fn associated_body<'hir>(node: Node<'hir>) -> Option<BodyId> {
     }
 }
 
-fn is_body_owner<'hir>(node: Node<'hir>, hir_id: HirId) -> bool {
+fn is_body_owner(node: Node<'_>, hir_id: HirId) -> bool {
     match associated_body(node) {
         Some(b) => b.hir_id == hir_id,
         None => false,
@@ -170,6 +170,7 @@ impl<'hir> Map<'hir> {
     }
 
     #[inline]
+    #[track_caller]
     pub fn local_def_id(self, hir_id: HirId) -> LocalDefId {
         self.opt_local_def_id(hir_id).unwrap_or_else(|| {
             bug!(
@@ -310,6 +311,7 @@ impl<'hir> Map<'hir> {
         }
     }
 
+    #[track_caller]
     pub fn get_parent_node(self, hir_id: HirId) -> HirId {
         self.find_parent_node(hir_id)
             .unwrap_or_else(|| bug!("No parent for node {:?}", self.node_to_string(hir_id)))
@@ -334,12 +336,14 @@ impl<'hir> Map<'hir> {
     }
 
     /// Retrieves the `Node` corresponding to `id`, panicking if it cannot be found.
+    #[track_caller]
     pub fn get(self, id: HirId) -> Node<'hir> {
         self.find(id).unwrap_or_else(|| bug!("couldn't find hir id {} in the HIR map", id))
     }
 
     /// Retrieves the `Node` corresponding to `id`, panicking if it cannot be found.
     #[inline]
+    #[track_caller]
     pub fn get_by_def_id(self, id: LocalDefId) -> Node<'hir> {
         self.find_by_def_id(id).unwrap_or_else(|| bug!("couldn't find {:?} in the HIR map", id))
     }
@@ -377,6 +381,7 @@ impl<'hir> Map<'hir> {
         self.tcx.hir_owner_nodes(id.hir_id.owner).unwrap().bodies[&id.hir_id.local_id]
     }
 
+    #[track_caller]
     pub fn fn_decl_by_hir_id(self, hir_id: HirId) -> Option<&'hir FnDecl<'hir>> {
         if let Some(node) = self.find(hir_id) {
             node.fn_decl()
@@ -385,6 +390,7 @@ impl<'hir> Map<'hir> {
         }
     }
 
+    #[track_caller]
     pub fn fn_sig_by_hir_id(self, hir_id: HirId) -> Option<&'hir FnSig<'hir>> {
         if let Some(node) = self.find(hir_id) {
             node.fn_sig()
@@ -393,6 +399,7 @@ impl<'hir> Map<'hir> {
         }
     }
 
+    #[track_caller]
     pub fn enclosing_body_owner(self, hir_id: HirId) -> LocalDefId {
         for (_, node) in self.parent_iter(hir_id) {
             if let Some(body) = associated_body(node) {
@@ -408,7 +415,7 @@ impl<'hir> Map<'hir> {
     /// item (possibly associated), a closure, or a `hir::AnonConst`.
     pub fn body_owner(self, BodyId { hir_id }: BodyId) -> HirId {
         let parent = self.get_parent_node(hir_id);
-        assert!(self.find(parent).map_or(false, |n| is_body_owner(n, hir_id)));
+        assert!(self.find(parent).map_or(false, |n| is_body_owner(n, hir_id)), "{hir_id:?}");
         parent
     }
 
@@ -419,10 +426,11 @@ impl<'hir> Map<'hir> {
     /// Given a `LocalDefId`, returns the `BodyId` associated with it,
     /// if the node is a body owner, otherwise returns `None`.
     pub fn maybe_body_owned_by(self, id: LocalDefId) -> Option<BodyId> {
-        self.get_if_local(id.to_def_id()).map(associated_body).flatten()
+        self.find_by_def_id(id).and_then(associated_body)
     }
 
     /// Given a body owner's id, returns the `BodyId` associated with it.
+    #[track_caller]
     pub fn body_owned_by(self, id: LocalDefId) -> BodyId {
         self.maybe_body_owned_by(id).unwrap_or_else(|| {
             let hir_id = self.local_def_id_to_hir_id(id);
@@ -696,12 +704,10 @@ impl<'hir> Map<'hir> {
     pub fn get_return_block(self, id: HirId) -> Option<HirId> {
         let mut iter = self.parent_iter(id).peekable();
         let mut ignore_tail = false;
-        if let Some(node) = self.find(id) {
-            if let Node::Expr(Expr { kind: ExprKind::Ret(_), .. }) = node {
-                // When dealing with `return` statements, we don't care about climbing only tail
-                // expressions.
-                ignore_tail = true;
-            }
+        if let Some(Node::Expr(Expr { kind: ExprKind::Ret(_), .. })) = self.find(id) {
+            // When dealing with `return` statements, we don't care about climbing only tail
+            // expressions.
+            ignore_tail = true;
         }
         while let Some((hir_id, node)) = iter.next() {
             if let (Some((_, next_node)), false) = (iter.peek(), ignore_tail) {
diff --git a/compiler/rustc_middle/src/hir/mod.rs b/compiler/rustc_middle/src/hir/mod.rs
index 3f6e29ad611..a633201e3d9 100644
--- a/compiler/rustc_middle/src/hir/mod.rs
+++ b/compiler/rustc_middle/src/hir/mod.rs
@@ -160,9 +160,13 @@ pub fn provide(providers: &mut Providers) {
         } else if let Node::TraitItem(&TraitItem {
             kind: TraitItemKind::Fn(_, TraitFn::Required(idents)),
             ..
+        })
+        | Node::ForeignItem(&ForeignItem {
+            kind: ForeignItemKind::Fn(_, idents, _),
+            ..
         }) = hir.get(hir_id)
         {
-            tcx.arena.alloc_slice(idents)
+            idents
         } else {
             span_bug!(hir.span(hir_id), "fn_arg_names: unexpected item {:?}", id);
         }
diff --git a/compiler/rustc_middle/src/infer/canonical.rs b/compiler/rustc_middle/src/infer/canonical.rs
index 0331d764b38..0b32f67a81e 100644
--- a/compiler/rustc_middle/src/infer/canonical.rs
+++ b/compiler/rustc_middle/src/infer/canonical.rs
@@ -300,6 +300,16 @@ impl<'tcx, V> Canonical<'tcx, V> {
         let Canonical { max_universe, variables, value } = self;
         Canonical { max_universe, variables, value: map_op(value) }
     }
+
+    /// Allows you to map the `value` of a canonical while keeping the same set of
+    /// bound variables.
+    ///
+    /// **WARNING:** This function is very easy to mis-use, hence the name! See
+    /// the comment of [Canonical::unchecked_map] for more details.
+    pub fn unchecked_rebind<W>(self, value: W) -> Canonical<'tcx, W> {
+        let Canonical { max_universe, variables, value: _ } = self;
+        Canonical { max_universe, variables, value }
+    }
 }
 
 pub type QueryOutlivesConstraint<'tcx> = (
diff --git a/compiler/rustc_middle/src/middle/stability.rs b/compiler/rustc_middle/src/middle/stability.rs
index 61bc089e431..0836f236e24 100644
--- a/compiler/rustc_middle/src/middle/stability.rs
+++ b/compiler/rustc_middle/src/middle/stability.rs
@@ -223,8 +223,8 @@ pub fn deprecation_message_and_lint(
     )
 }
 
-pub fn early_report_deprecation<'a>(
-    lint_buffer: &'a mut LintBuffer,
+pub fn early_report_deprecation(
+    lint_buffer: &mut LintBuffer,
     message: &str,
     suggestion: Option<Symbol>,
     lint: &'static Lint,
diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs
index ffdf61d4244..a89e6566d56 100644
--- a/compiler/rustc_middle/src/mir/mod.rs
+++ b/compiler/rustc_middle/src/mir/mod.rs
@@ -1767,9 +1767,9 @@ impl SourceScope {
     /// Finds the original HirId this MIR item came from.
     /// This is necessary after MIR optimizations, as otherwise we get a HirId
     /// from the function that was inlined instead of the function call site.
-    pub fn lint_root<'tcx>(
+    pub fn lint_root(
         self,
-        source_scopes: &IndexVec<SourceScope, SourceScopeData<'tcx>>,
+        source_scopes: &IndexVec<SourceScope, SourceScopeData<'_>>,
     ) -> Option<HirId> {
         let mut data = &source_scopes[self];
         // FIXME(oli-obk): we should be able to just walk the `inlined_parent_scope`, but it
@@ -2894,7 +2894,7 @@ fn pretty_print_const_value<'tcx>(
                 if let Some(contents) = tcx.try_destructure_mir_constant(
                     ty::ParamEnv::reveal_all().and(ConstantKind::Val(ct, ty)),
                 ) {
-                    let fields = contents.fields.iter().copied().collect::<Vec<_>>();
+                    let fields = contents.fields.to_vec();
                     match *ty.kind() {
                         ty::Array(..) => {
                             fmt.write_str("[")?;
diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs
index 1ebfdbbd6ef..40289af257f 100644
--- a/compiler/rustc_middle/src/mir/pretty.rs
+++ b/compiler/rustc_middle/src/mir/pretty.rs
@@ -88,7 +88,7 @@ pub fn dump_mir<'tcx, F>(
     dump_matched_mir_node(tcx, pass_num, pass_name, disambiguator, body, extra_data);
 }
 
-pub fn dump_enabled<'tcx>(tcx: TyCtxt<'tcx>, pass_name: &str, def_id: DefId) -> bool {
+pub fn dump_enabled(tcx: TyCtxt<'_>, pass_name: &str, def_id: DefId) -> bool {
     let Some(ref filters) = tcx.sess.opts.unstable_opts.dump_mir else {
         return false;
     };
@@ -421,7 +421,7 @@ impl<'tcx> ExtraComments<'tcx> {
     }
 }
 
-fn use_verbose<'tcx>(ty: Ty<'tcx>, fn_def: bool) -> bool {
+fn use_verbose(ty: Ty<'_>, fn_def: bool) -> bool {
     match *ty.kind() {
         ty::Int(_) | ty::Uint(_) | ty::Bool | ty::Char | ty::Float(_) => false,
         // Unit type
diff --git a/compiler/rustc_middle/src/mir/spanview.rs b/compiler/rustc_middle/src/mir/spanview.rs
index 4e06d91012c..887ee571575 100644
--- a/compiler/rustc_middle/src/mir/spanview.rs
+++ b/compiler/rustc_middle/src/mir/spanview.rs
@@ -230,7 +230,7 @@ where
 }
 
 /// Format a string showing the start line and column, and end line and column within a file.
-pub fn source_range_no_file<'tcx>(tcx: TyCtxt<'tcx>, span: Span) -> String {
+pub fn source_range_no_file(tcx: TyCtxt<'_>, span: Span) -> String {
     let source_map = tcx.sess.source_map();
     let start = source_map.lookup_char_pos(span.lo());
     let end = source_map.lookup_char_pos(span.hi());
@@ -322,7 +322,7 @@ fn block_span_viewable<'tcx>(
     Some(SpanViewable { bb, span, id, tooltip })
 }
 
-fn compute_block_span<'tcx>(data: &BasicBlockData<'tcx>, body_span: Span) -> Span {
+fn compute_block_span(data: &BasicBlockData<'_>, body_span: Span) -> Span {
     let mut span = data.terminator().source_info.span;
     for statement_span in data.statements.iter().map(|statement| statement.source_info.span) {
         // Only combine Spans from the root context, and within the function's body_span.
@@ -522,12 +522,7 @@ where
 }
 
 #[inline(always)]
-fn write_coverage_gap<'tcx, W>(
-    tcx: TyCtxt<'tcx>,
-    lo: BytePos,
-    hi: BytePos,
-    w: &mut W,
-) -> io::Result<()>
+fn write_coverage_gap<W>(tcx: TyCtxt<'_>, lo: BytePos, hi: BytePos, w: &mut W) -> io::Result<()>
 where
     W: Write,
 {
@@ -582,8 +577,8 @@ where
     Ok(())
 }
 
-fn make_html_snippet<'tcx>(
-    tcx: TyCtxt<'tcx>,
+fn make_html_snippet(
+    tcx: TyCtxt<'_>,
     span: Span,
     some_viewable: Option<&SpanViewable>,
 ) -> Option<String> {
@@ -664,7 +659,7 @@ fn trim_span_hi(span: Span, to_pos: BytePos) -> Span {
     if to_pos >= span.hi() { span } else { span.with_hi(cmp::max(span.lo(), to_pos)) }
 }
 
-fn fn_span<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> Span {
+fn fn_span(tcx: TyCtxt<'_>, def_id: DefId) -> Span {
     let fn_decl_span = tcx.def_span(def_id);
     if let Some(body_span) = hir_body(tcx, def_id).map(|hir_body| hir_body.value.span) {
         if fn_decl_span.eq_ctxt(body_span) { fn_decl_span.to(body_span) } else { body_span }
@@ -673,7 +668,7 @@ fn fn_span<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> Span {
     }
 }
 
-fn hir_body<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> Option<&'tcx rustc_hir::Body<'tcx>> {
+fn hir_body(tcx: TyCtxt<'_>, def_id: DefId) -> Option<&rustc_hir::Body<'_>> {
     let hir_node = tcx.hir().get_if_local(def_id).expect("expected DefId is local");
     hir::map::associated_body(hir_node).map(|fn_body_id| tcx.hir().body(fn_body_id))
 }
diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs
index 99e59c770d7..6b4489026d3 100644
--- a/compiler/rustc_middle/src/mir/syntax.rs
+++ b/compiler/rustc_middle/src/mir/syntax.rs
@@ -320,8 +320,10 @@ pub enum StatementKind<'tcx> {
     /// <https://internals.rust-lang.org/t/stacked-borrows-an-aliasing-model-for-rust/8153/> for
     /// more details.
     ///
-    /// For code that is not specific to stacked borrows, you should consider retags to read
-    /// and modify the place in an opaque way.
+    /// For code that is not specific to stacked borrows, you should consider retags to read and
+    /// modify the place in an opaque way.
+    ///
+    /// Only `RetagKind::Default` and `RetagKind::FnEntry` are permitted.
     Retag(RetagKind, Box<Place<'tcx>>),
 
     /// Encodes a user's type ascription. These need to be preserved
@@ -562,14 +564,13 @@ pub enum TerminatorKind<'tcx> {
     Unreachable,
 
     /// The behavior of this statement differs significantly before and after drop elaboration.
-    /// After drop elaboration, `Drop` executes the drop glue for the specified place, after which
-    /// it continues execution/unwinds at the given basic blocks. It is possible that executing drop
-    /// glue is special - this would be part of Rust's memory model. (**FIXME**: due we have an
-    /// issue tracking if drop glue has any interesting semantics in addition to those of a function
-    /// call?)
-    ///
-    /// `Drop` before drop elaboration is a *conditional* execution of the drop glue. Specifically, the
-    /// `Drop` will be executed if...
+    ///
+    /// After drop elaboration: `Drop` terminators are a complete nop for types that have no drop
+    /// glue. For other types, `Drop` terminators behave exactly like a call to
+    /// `core::mem::drop_in_place` with a pointer to the given place.
+    ///
+    /// `Drop` before drop elaboration is a *conditional* execution of the drop glue. Specifically,
+    /// the `Drop` will be executed if...
     ///
     /// **Needs clarification**: End of that sentence. This in effect should document the exact
     /// behavior of drop elaboration. The following sounds vaguely right, but I'm not quite sure:
diff --git a/compiler/rustc_middle/src/mir/tcx.rs b/compiler/rustc_middle/src/mir/tcx.rs
index 8d2a8f33d6a..599f0b9d3fa 100644
--- a/compiler/rustc_middle/src/mir/tcx.rs
+++ b/compiler/rustc_middle/src/mir/tcx.rs
@@ -32,8 +32,9 @@ impl<'tcx> PlaceTy<'tcx> {
     /// not carry a `Ty` for `T`.)
     ///
     /// Note that the resulting type has not been normalized.
+    #[instrument(level = "debug", skip(tcx), ret)]
     pub fn field_ty(self, tcx: TyCtxt<'tcx>, f: Field) -> Ty<'tcx> {
-        let answer = match self.ty.kind() {
+        match self.ty.kind() {
             ty::Adt(adt_def, substs) => {
                 let variant_def = match self.variant_index {
                     None => adt_def.non_enum_variant(),
@@ -47,9 +48,7 @@ impl<'tcx> PlaceTy<'tcx> {
             }
             ty::Tuple(tys) => tys[f.index()],
             _ => bug!("extracting field of non-tuple non-adt: {:?}", self),
-        };
-        debug!("field_ty self: {:?} f: {:?} yields: {:?}", self, f, answer);
-        answer
+        }
     }
 
     /// Convenience wrapper around `projection_ty_core` for
diff --git a/compiler/rustc_middle/src/mir/terminator.rs b/compiler/rustc_middle/src/mir/terminator.rs
index 013a1bccd3b..438f36373ca 100644
--- a/compiler/rustc_middle/src/mir/terminator.rs
+++ b/compiler/rustc_middle/src/mir/terminator.rs
@@ -1,4 +1,4 @@
-use smallvec::{smallvec, SmallVec};
+use smallvec::SmallVec;
 
 use super::{BasicBlock, InlineAsmOperand, Operand, SourceInfo, TerminatorKind};
 use rustc_ast::InlineAsmTemplatePiece;
diff --git a/compiler/rustc_middle/src/mir/traversal.rs b/compiler/rustc_middle/src/mir/traversal.rs
index 55b2c592795..0b461d1ce41 100644
--- a/compiler/rustc_middle/src/mir/traversal.rs
+++ b/compiler/rustc_middle/src/mir/traversal.rs
@@ -302,7 +302,7 @@ pub fn reachable<'a, 'tcx>(
 }
 
 /// Returns a `BitSet` containing all basic blocks reachable from the `START_BLOCK`.
-pub fn reachable_as_bitset<'tcx>(body: &Body<'tcx>) -> BitSet<BasicBlock> {
+pub fn reachable_as_bitset(body: &Body<'_>) -> BitSet<BasicBlock> {
     let mut iter = preorder(body);
     (&mut iter).for_each(drop);
     iter.visited
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index ab512804330..37db2274f67 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -169,7 +169,7 @@ rustc_queries! {
         separate_provide_extern
     }
 
-    query collect_trait_impl_trait_tys(key: DefId)
+    query collect_return_position_impl_trait_in_trait_tys(key: DefId)
         -> Result<&'tcx FxHashMap<DefId, Ty<'tcx>>, ErrorGuaranteed>
     {
         desc { "comparing an impl and trait method signature, inferring any hidden `impl Trait` types in the process" }
@@ -2117,7 +2117,7 @@ rustc_queries! {
         desc { "checking to see if `{}` permits being left zeroed", key.ty }
     }
 
-    query compare_assoc_const_impl_item_with_trait_item(
+    query compare_impl_const(
         key: (LocalDefId, DefId)
     ) -> Result<(), ErrorGuaranteed> {
         desc { |tcx| "checking assoc const `{}` has the same type as trait item", tcx.def_path_str(key.0.to_def_id()) }
diff --git a/compiler/rustc_middle/src/traits/chalk.rs b/compiler/rustc_middle/src/traits/chalk.rs
index 6d4af8bea62..dd75b0d9ebc 100644
--- a/compiler/rustc_middle/src/traits/chalk.rs
+++ b/compiler/rustc_middle/src/traits/chalk.rs
@@ -210,7 +210,7 @@ impl<'tcx> chalk_ir::interner::Interner for RustInterner<'tcx> {
         Box::new(chalk_ir::TyData { kind: ty, flags: flags })
     }
 
-    fn ty_data<'a>(self, ty: &'a Self::InternedType) -> &'a chalk_ir::TyData<Self> {
+    fn ty_data(self, ty: &Self::InternedType) -> &chalk_ir::TyData<Self> {
         ty
     }
 
@@ -218,10 +218,7 @@ impl<'tcx> chalk_ir::interner::Interner for RustInterner<'tcx> {
         Box::new(lifetime)
     }
 
-    fn lifetime_data<'a>(
-        self,
-        lifetime: &'a Self::InternedLifetime,
-    ) -> &'a chalk_ir::LifetimeData<Self> {
+    fn lifetime_data(self, lifetime: &Self::InternedLifetime) -> &chalk_ir::LifetimeData<Self> {
         &lifetime
     }
 
@@ -229,7 +226,7 @@ impl<'tcx> chalk_ir::interner::Interner for RustInterner<'tcx> {
         Box::new(constant)
     }
 
-    fn const_data<'a>(self, constant: &'a Self::InternedConst) -> &'a chalk_ir::ConstData<Self> {
+    fn const_data(self, constant: &Self::InternedConst) -> &chalk_ir::ConstData<Self> {
         &constant
     }
 
@@ -246,10 +243,7 @@ impl<'tcx> chalk_ir::interner::Interner for RustInterner<'tcx> {
         Box::new(data)
     }
 
-    fn generic_arg_data<'a>(
-        self,
-        data: &'a Self::InternedGenericArg,
-    ) -> &'a chalk_ir::GenericArgData<Self> {
+    fn generic_arg_data(self, data: &Self::InternedGenericArg) -> &chalk_ir::GenericArgData<Self> {
         &data
     }
 
@@ -257,7 +251,7 @@ impl<'tcx> chalk_ir::interner::Interner for RustInterner<'tcx> {
         Box::new(goal)
     }
 
-    fn goal_data<'a>(self, goal: &'a Self::InternedGoal) -> &'a chalk_ir::GoalData<Self> {
+    fn goal_data(self, goal: &Self::InternedGoal) -> &chalk_ir::GoalData<Self> {
         &goal
     }
 
@@ -268,7 +262,7 @@ impl<'tcx> chalk_ir::interner::Interner for RustInterner<'tcx> {
         data.into_iter().collect::<Result<Vec<_>, _>>()
     }
 
-    fn goals_data<'a>(self, goals: &'a Self::InternedGoals) -> &'a [chalk_ir::Goal<Self>] {
+    fn goals_data(self, goals: &Self::InternedGoals) -> &[chalk_ir::Goal<Self>] {
         goals
     }
 
@@ -279,10 +273,10 @@ impl<'tcx> chalk_ir::interner::Interner for RustInterner<'tcx> {
         data.into_iter().collect::<Result<Vec<_>, _>>()
     }
 
-    fn substitution_data<'a>(
+    fn substitution_data(
         self,
-        substitution: &'a Self::InternedSubstitution,
-    ) -> &'a [chalk_ir::GenericArg<Self>] {
+        substitution: &Self::InternedSubstitution,
+    ) -> &[chalk_ir::GenericArg<Self>] {
         substitution
     }
 
@@ -293,10 +287,10 @@ impl<'tcx> chalk_ir::interner::Interner for RustInterner<'tcx> {
         Box::new(data)
     }
 
-    fn program_clause_data<'a>(
+    fn program_clause_data(
         self,
-        clause: &'a Self::InternedProgramClause,
-    ) -> &'a chalk_ir::ProgramClauseData<Self> {
+        clause: &Self::InternedProgramClause,
+    ) -> &chalk_ir::ProgramClauseData<Self> {
         &clause
     }
 
@@ -307,10 +301,10 @@ impl<'tcx> chalk_ir::interner::Interner for RustInterner<'tcx> {
         data.into_iter().collect::<Result<Vec<_>, _>>()
     }
 
-    fn program_clauses_data<'a>(
+    fn program_clauses_data(
         self,
-        clauses: &'a Self::InternedProgramClauses,
-    ) -> &'a [chalk_ir::ProgramClause<Self>] {
+        clauses: &Self::InternedProgramClauses,
+    ) -> &[chalk_ir::ProgramClause<Self>] {
         clauses
     }
 
@@ -321,10 +315,10 @@ impl<'tcx> chalk_ir::interner::Interner for RustInterner<'tcx> {
         data.into_iter().collect::<Result<Vec<_>, _>>()
     }
 
-    fn quantified_where_clauses_data<'a>(
+    fn quantified_where_clauses_data(
         self,
-        clauses: &'a Self::InternedQuantifiedWhereClauses,
-    ) -> &'a [chalk_ir::QuantifiedWhereClause<Self>] {
+        clauses: &Self::InternedQuantifiedWhereClauses,
+    ) -> &[chalk_ir::QuantifiedWhereClause<Self>] {
         clauses
     }
 
@@ -335,10 +329,10 @@ impl<'tcx> chalk_ir::interner::Interner for RustInterner<'tcx> {
         data.into_iter().collect::<Result<Vec<_>, _>>()
     }
 
-    fn variable_kinds_data<'a>(
+    fn variable_kinds_data(
         self,
-        parameter_kinds: &'a Self::InternedVariableKinds,
-    ) -> &'a [chalk_ir::VariableKind<Self>] {
+        parameter_kinds: &Self::InternedVariableKinds,
+    ) -> &[chalk_ir::VariableKind<Self>] {
         parameter_kinds
     }
 
@@ -349,10 +343,10 @@ impl<'tcx> chalk_ir::interner::Interner for RustInterner<'tcx> {
         data.into_iter().collect::<Result<Vec<_>, _>>()
     }
 
-    fn canonical_var_kinds_data<'a>(
+    fn canonical_var_kinds_data(
         self,
-        canonical_var_kinds: &'a Self::InternedCanonicalVarKinds,
-    ) -> &'a [chalk_ir::CanonicalVarKind<Self>] {
+        canonical_var_kinds: &Self::InternedCanonicalVarKinds,
+    ) -> &[chalk_ir::CanonicalVarKind<Self>] {
         canonical_var_kinds
     }
 
@@ -363,10 +357,10 @@ impl<'tcx> chalk_ir::interner::Interner for RustInterner<'tcx> {
         data.into_iter().collect::<Result<Vec<_>, _>>()
     }
 
-    fn constraints_data<'a>(
+    fn constraints_data(
         self,
-        constraints: &'a Self::InternedConstraints,
-    ) -> &'a [chalk_ir::InEnvironment<chalk_ir::Constraint<Self>>] {
+        constraints: &Self::InternedConstraints,
+    ) -> &[chalk_ir::InEnvironment<chalk_ir::Constraint<Self>>] {
         constraints
     }
 
@@ -377,10 +371,7 @@ impl<'tcx> chalk_ir::interner::Interner for RustInterner<'tcx> {
         data.into_iter().collect::<Result<Vec<_>, _>>()
     }
 
-    fn variances_data<'a>(
-        self,
-        variances: &'a Self::InternedVariances,
-    ) -> &'a [chalk_ir::Variance] {
+    fn variances_data(self, variances: &Self::InternedVariances) -> &[chalk_ir::Variance] {
         variances
     }
 }
diff --git a/compiler/rustc_middle/src/traits/query.rs b/compiler/rustc_middle/src/traits/query.rs
index 7380c62a669..6a149be3137 100644
--- a/compiler/rustc_middle/src/traits/query.rs
+++ b/compiler/rustc_middle/src/traits/query.rs
@@ -96,7 +96,7 @@ pub type CanonicalTypeOpProvePredicateGoal<'tcx> =
 pub type CanonicalTypeOpNormalizeGoal<'tcx, T> =
     Canonical<'tcx, ty::ParamEnvAnd<'tcx, type_op::Normalize<T>>>;
 
-#[derive(Copy, Clone, Debug, HashStable)]
+#[derive(Copy, Clone, Debug, HashStable, PartialEq, Eq)]
 pub struct NoSolution;
 
 pub type Fallible<T> = Result<T, NoSolution>;
diff --git a/compiler/rustc_middle/src/traits/specialization_graph.rs b/compiler/rustc_middle/src/traits/specialization_graph.rs
index cccedc9ec6e..aad5b2fbe07 100644
--- a/compiler/rustc_middle/src/traits/specialization_graph.rs
+++ b/compiler/rustc_middle/src/traits/specialization_graph.rs
@@ -60,7 +60,7 @@ pub enum OverlapMode {
 }
 
 impl OverlapMode {
-    pub fn get<'tcx>(tcx: TyCtxt<'tcx>, trait_id: DefId) -> OverlapMode {
+    pub fn get(tcx: TyCtxt<'_>, trait_id: DefId) -> OverlapMode {
         let with_negative_coherence = tcx.features().with_negative_coherence;
         let strict_coherence = tcx.has_attr(trait_id, sym::rustc_strict_coherence);
 
@@ -180,6 +180,7 @@ impl Iterator for Ancestors<'_> {
 }
 
 /// Information about the most specialized definition of an associated item.
+#[derive(Debug)]
 pub struct LeafDef {
     /// The associated item described by this `LeafDef`.
     pub item: ty::AssocItem,
@@ -253,11 +254,11 @@ impl<'tcx> Ancestors<'tcx> {
 ///
 /// Returns `Err` if an error was reported while building the specialization
 /// graph.
-pub fn ancestors<'tcx>(
-    tcx: TyCtxt<'tcx>,
+pub fn ancestors(
+    tcx: TyCtxt<'_>,
     trait_def_id: DefId,
     start_from_impl: DefId,
-) -> Result<Ancestors<'tcx>, ErrorGuaranteed> {
+) -> Result<Ancestors<'_>, ErrorGuaranteed> {
     let specialization_graph = tcx.specialization_graph_of(trait_def_id);
 
     if let Some(reported) = specialization_graph.has_errored {
diff --git a/compiler/rustc_middle/src/ty/closure.rs b/compiler/rustc_middle/src/ty/closure.rs
index d00553cbad1..6ade8935fc8 100644
--- a/compiler/rustc_middle/src/ty/closure.rs
+++ b/compiler/rustc_middle/src/ty/closure.rs
@@ -238,10 +238,7 @@ impl<'tcx> CapturedPlace<'tcx> {
     }
 }
 
-fn symbols_for_closure_captures<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    def_id: (LocalDefId, LocalDefId),
-) -> Vec<Symbol> {
+fn symbols_for_closure_captures(tcx: TyCtxt<'_>, def_id: (LocalDefId, LocalDefId)) -> Vec<Symbol> {
     let typeck_results = tcx.typeck(def_id.0);
     let captures = typeck_results.closure_min_captures_flattened(def_id.1);
     captures.into_iter().map(|captured_place| captured_place.to_symbol(tcx)).collect()
diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs
index e5abc38046c..152a7e9d43f 100644
--- a/compiler/rustc_middle/src/ty/consts.rs
+++ b/compiler/rustc_middle/src/ty/consts.rs
@@ -239,7 +239,7 @@ impl<'tcx> Const<'tcx> {
     }
 }
 
-pub fn const_param_default<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> Const<'tcx> {
+pub fn const_param_default(tcx: TyCtxt<'_>, def_id: DefId) -> Const<'_> {
     let default_def_id = match tcx.hir().get_by_def_id(def_id.expect_local()) {
         hir::Node::GenericParam(hir::GenericParam {
             kind: hir::GenericParamKind::Const { default: Some(ac), .. },
diff --git a/compiler/rustc_middle/src/ty/consts/int.rs b/compiler/rustc_middle/src/ty/consts/int.rs
index 2a8a4d59888..48958e0d9e9 100644
--- a/compiler/rustc_middle/src/ty/consts/int.rs
+++ b/compiler/rustc_middle/src/ty/consts/int.rs
@@ -232,7 +232,7 @@ impl ScalarInt {
     }
 
     #[inline]
-    pub fn try_to_machine_usize<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Result<u64, Size> {
+    pub fn try_to_machine_usize(&self, tcx: TyCtxt<'_>) -> Result<u64, Size> {
         Ok(self.to_bits(tcx.data_layout.pointer_size)? as u64)
     }
 
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index 8f4d56c65b9..5de414077a2 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -1518,7 +1518,7 @@ impl<'tcx, T: 'tcx + ?Sized> IntoPointer for InternedInSet<'tcx, T> {
 
 #[allow(rustc::usage_of_ty_tykind)]
 impl<'tcx, T> Borrow<T> for InternedInSet<'tcx, WithCachedTypeInfo<T>> {
-    fn borrow<'a>(&'a self) -> &'a T {
+    fn borrow(&self) -> &T {
         &self.0.internee
     }
 }
@@ -1541,7 +1541,7 @@ impl<'tcx, T: Hash> Hash for InternedInSet<'tcx, WithCachedTypeInfo<T>> {
 }
 
 impl<'tcx, T> Borrow<[T]> for InternedInSet<'tcx, List<T>> {
-    fn borrow<'a>(&'a self) -> &'a [T] {
+    fn borrow(&self) -> &[T] {
         &self.0[..]
     }
 }
diff --git a/compiler/rustc_middle/src/ty/flags.rs b/compiler/rustc_middle/src/ty/flags.rs
index 042b89bc4b0..8306d670a65 100644
--- a/compiler/rustc_middle/src/ty/flags.rs
+++ b/compiler/rustc_middle/src/ty/flags.rs
@@ -22,7 +22,7 @@ impl FlagComputation {
         result
     }
 
-    pub fn for_predicate<'tcx>(binder: ty::Binder<'tcx, ty::PredicateKind<'_>>) -> FlagComputation {
+    pub fn for_predicate(binder: ty::Binder<'_, ty::PredicateKind<'_>>) -> FlagComputation {
         let mut result = FlagComputation::new();
         result.add_predicate(binder);
         result
diff --git a/compiler/rustc_middle/src/ty/generics.rs b/compiler/rustc_middle/src/ty/generics.rs
index 2e70ac256a7..705adecd3b9 100644
--- a/compiler/rustc_middle/src/ty/generics.rs
+++ b/compiler/rustc_middle/src/ty/generics.rs
@@ -70,14 +70,6 @@ impl GenericParamDef {
         }
     }
 
-    pub fn has_default(&self) -> bool {
-        match self.kind {
-            GenericParamDefKind::Type { has_default, .. }
-            | GenericParamDefKind::Const { has_default } => has_default,
-            GenericParamDefKind::Lifetime => false,
-        }
-    }
-
     pub fn is_anonymous_lifetime(&self) -> bool {
         match self.kind {
             GenericParamDefKind::Lifetime => {
diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs
index 7f66b993646..9e0ca44d098 100644
--- a/compiler/rustc_middle/src/ty/layout.rs
+++ b/compiler/rustc_middle/src/ty/layout.rs
@@ -993,7 +993,7 @@ where
 /// might (from a foreign exception or similar).
 #[inline]
 #[tracing::instrument(level = "debug", skip(tcx))]
-pub fn fn_can_unwind<'tcx>(tcx: TyCtxt<'tcx>, fn_def_id: Option<DefId>, abi: SpecAbi) -> bool {
+pub fn fn_can_unwind(tcx: TyCtxt<'_>, fn_def_id: Option<DefId>, abi: SpecAbi) -> bool {
     if let Some(did) = fn_def_id {
         // Special attribute for functions which can't unwind.
         if tcx.codegen_fn_attrs(did).flags.contains(CodegenFnAttrFlags::NEVER_UNWIND) {
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index a8e1253e670..f01d74539a1 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -535,6 +535,17 @@ impl<'tcx> Predicate<'tcx> {
         self
     }
 
+    #[instrument(level = "debug", skip(tcx), ret)]
+    pub fn is_coinductive(self, tcx: TyCtxt<'tcx>) -> bool {
+        match self.kind().skip_binder() {
+            ty::PredicateKind::Clause(ty::Clause::Trait(data)) => {
+                tcx.trait_is_coinductive(data.def_id())
+            }
+            ty::PredicateKind::WellFormed(_) => true,
+            _ => false,
+        }
+    }
+
     /// Whether this projection can be soundly normalized.
     ///
     /// Wf predicates must not be normalized, as normalization
@@ -1018,6 +1029,24 @@ pub struct ProjectionPredicate<'tcx> {
     pub term: Term<'tcx>,
 }
 
+impl<'tcx> ProjectionPredicate<'tcx> {
+    pub fn self_ty(self) -> Ty<'tcx> {
+        self.projection_ty.self_ty()
+    }
+
+    pub fn with_self_ty(self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> ProjectionPredicate<'tcx> {
+        Self { projection_ty: self.projection_ty.with_self_ty(tcx, self_ty), ..self }
+    }
+
+    pub fn trait_def_id(self, tcx: TyCtxt<'tcx>) -> DefId {
+        self.projection_ty.trait_def_id(tcx)
+    }
+
+    pub fn def_id(self) -> DefId {
+        self.projection_ty.def_id
+    }
+}
+
 pub type PolyProjectionPredicate<'tcx> = Binder<'tcx, ProjectionPredicate<'tcx>>;
 
 impl<'tcx> PolyProjectionPredicate<'tcx> {
@@ -1054,18 +1083,6 @@ impl<'tcx> PolyProjectionPredicate<'tcx> {
     }
 }
 
-impl<'tcx> ProjectionPredicate<'tcx> {
-    pub fn with_self_ty(self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> Self {
-        Self {
-            projection_ty: tcx.mk_alias_ty(
-                self.projection_ty.def_id,
-                [self_ty.into()].into_iter().chain(self.projection_ty.substs.iter().skip(1)),
-            ),
-            ..self
-        }
-    }
-}
-
 pub trait ToPolyTraitRef<'tcx> {
     fn to_poly_trait_ref(&self) -> PolyTraitRef<'tcx>;
 }
diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs
index a1d53506707..c49e75d68ad 100644
--- a/compiler/rustc_middle/src/ty/print/pretty.rs
+++ b/compiler/rustc_middle/src/ty/print/pretty.rs
@@ -2883,13 +2883,19 @@ fn for_each_def(tcx: TyCtxt<'_>, mut collect_fn: impl for<'b> FnMut(&'b Ident, N
 /// `std::vec::Vec` to just `Vec`, as long as there is no other `Vec` importable anywhere.
 ///
 /// The implementation uses similar import discovery logic to that of 'use' suggestions.
+///
+/// See also [`DelayDm`](rustc_error_messages::DelayDm) and [`with_no_trimmed_paths`].
 fn trimmed_def_paths(tcx: TyCtxt<'_>, (): ()) -> FxHashMap<DefId, Symbol> {
     let mut map: FxHashMap<DefId, Symbol> = FxHashMap::default();
 
     if let TrimmedDefPaths::GoodPath = tcx.sess.opts.trimmed_def_paths {
+        // Trimming paths is expensive and not optimized, since we expect it to only be used for error reporting.
+        //
         // For good paths causing this bug, the `rustc_middle::ty::print::with_no_trimmed_paths`
         // wrapper can be used to suppress this query, in exchange for full paths being formatted.
-        tcx.sess.delay_good_path_bug("trimmed_def_paths constructed");
+        tcx.sess.delay_good_path_bug(
+            "trimmed_def_paths constructed but no error emitted; use `DelayDm` for lints or `with_no_trimmed_paths` for debugging",
+        );
     }
 
     let unique_symbols_rev: &mut FxHashMap<(Namespace, Symbol), Option<DefId>> =
diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs
index e13b68c83b5..f7e4c821569 100644
--- a/compiler/rustc_middle/src/ty/sty.rs
+++ b/compiler/rustc_middle/src/ty/sty.rs
@@ -1169,7 +1169,7 @@ pub struct AliasTy<'tcx> {
 }
 
 impl<'tcx> AliasTy<'tcx> {
-    pub fn trait_def_id(&self, tcx: TyCtxt<'tcx>) -> DefId {
+    pub fn trait_def_id(self, tcx: TyCtxt<'tcx>) -> DefId {
         match tcx.def_kind(self.def_id) {
             DefKind::AssocTy | DefKind::AssocConst => tcx.parent(self.def_id),
             DefKind::ImplTraitPlaceholder => {
@@ -1183,7 +1183,7 @@ impl<'tcx> AliasTy<'tcx> {
     /// For example, if this is a projection of `<T as StreamingIterator>::Item<'a>`,
     /// then this function would return a `T: Iterator` trait reference and `['a]` as the own substs
     pub fn trait_ref_and_own_substs(
-        &self,
+        self,
         tcx: TyCtxt<'tcx>,
     ) -> (ty::TraitRef<'tcx>, &'tcx [ty::GenericArg<'tcx>]) {
         debug_assert!(matches!(tcx.def_kind(self.def_id), DefKind::AssocTy | DefKind::AssocConst));
@@ -1202,14 +1202,18 @@ impl<'tcx> AliasTy<'tcx> {
     /// WARNING: This will drop the substs for generic associated types
     /// consider calling [Self::trait_ref_and_own_substs] to get those
     /// as well.
-    pub fn trait_ref(&self, tcx: TyCtxt<'tcx>) -> ty::TraitRef<'tcx> {
+    pub fn trait_ref(self, tcx: TyCtxt<'tcx>) -> ty::TraitRef<'tcx> {
         let def_id = self.trait_def_id(tcx);
         tcx.mk_trait_ref(def_id, self.substs.truncate_to(tcx, tcx.generics_of(def_id)))
     }
 
-    pub fn self_ty(&self) -> Ty<'tcx> {
+    pub fn self_ty(self) -> Ty<'tcx> {
         self.substs.type_at(0)
     }
+
+    pub fn with_self_ty(self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> Self {
+        tcx.mk_alias_ty(self.def_id, [self_ty.into()].into_iter().chain(self.substs.iter().skip(1)))
+    }
 }
 
 #[derive(Copy, Clone, Debug, TypeFoldable, TypeVisitable, Lift)]
diff --git a/compiler/rustc_middle/src/ty/subst.rs b/compiler/rustc_middle/src/ty/subst.rs
index a04b15f8cf1..0c33e5bda1a 100644
--- a/compiler/rustc_middle/src/ty/subst.rs
+++ b/compiler/rustc_middle/src/ty/subst.rs
@@ -348,7 +348,7 @@ impl<'tcx> InternalSubsts<'tcx> {
         substs.reserve(defs.params.len());
         for param in &defs.params {
             let kind = mk_kind(param, substs);
-            assert_eq!(param.index as usize, substs.len());
+            assert_eq!(param.index as usize, substs.len(), "{substs:#?}, {defs:#?}");
             substs.push(kind);
         }
     }
@@ -400,6 +400,7 @@ impl<'tcx> InternalSubsts<'tcx> {
     }
 
     #[inline]
+    #[track_caller]
     pub fn type_at(&self, i: usize) -> Ty<'tcx> {
         if let GenericArgKind::Type(ty) = self[i].unpack() {
             ty
@@ -409,6 +410,7 @@ impl<'tcx> InternalSubsts<'tcx> {
     }
 
     #[inline]
+    #[track_caller]
     pub fn region_at(&self, i: usize) -> ty::Region<'tcx> {
         if let GenericArgKind::Lifetime(lt) = self[i].unpack() {
             lt
@@ -418,6 +420,7 @@ impl<'tcx> InternalSubsts<'tcx> {
     }
 
     #[inline]
+    #[track_caller]
     pub fn const_at(&self, i: usize) -> ty::Const<'tcx> {
         if let GenericArgKind::Const(ct) = self[i].unpack() {
             ct
@@ -427,6 +430,7 @@ impl<'tcx> InternalSubsts<'tcx> {
     }
 
     #[inline]
+    #[track_caller]
     pub fn type_for_def(&self, def: &ty::GenericParamDef) -> GenericArg<'tcx> {
         self.type_at(def.index as usize).into()
     }
@@ -573,6 +577,10 @@ impl<T> EarlyBinder<T> {
     pub fn rebind<U>(&self, value: U) -> EarlyBinder<U> {
         EarlyBinder(value)
     }
+
+    pub fn skip_binder(self) -> T {
+        self.0
+    }
 }
 
 impl<T> EarlyBinder<Option<T>> {
diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs
index 5d0af1d4ead..cc53659f827 100644
--- a/compiler/rustc_middle/src/ty/util.rs
+++ b/compiler/rustc_middle/src/ty/util.rs
@@ -641,11 +641,11 @@ impl<'tcx> TyCtxt<'tcx> {
         ty::EarlyBinder(self.type_of(def_id))
     }
 
-    pub fn bound_trait_impl_trait_tys(
+    pub fn bound_return_position_impl_trait_in_trait_tys(
         self,
         def_id: DefId,
     ) -> ty::EarlyBinder<Result<&'tcx FxHashMap<DefId, Ty<'tcx>>, ErrorGuaranteed>> {
-        ty::EarlyBinder(self.collect_trait_impl_trait_tys(def_id))
+        ty::EarlyBinder(self.collect_return_position_impl_trait_in_trait_tys(def_id))
     }
 
     pub fn bound_fn_sig(self, def_id: DefId) -> ty::EarlyBinder<ty::PolyFnSig<'tcx>> {
@@ -1248,7 +1248,7 @@ pub fn needs_drop_components<'tcx>(
     }
 }
 
-pub fn is_trivially_const_drop<'tcx>(ty: Ty<'tcx>) -> bool {
+pub fn is_trivially_const_drop(ty: Ty<'_>) -> bool {
     match *ty.kind() {
         ty::Bool
         | ty::Char
diff --git a/compiler/rustc_middle/src/ty/visit.rs b/compiler/rustc_middle/src/ty/visit.rs
index b302572f3ca..d5553f84f75 100644
--- a/compiler/rustc_middle/src/ty/visit.rs
+++ b/compiler/rustc_middle/src/ty/visit.rs
@@ -88,9 +88,11 @@ pub trait TypeVisitable<'tcx>: fmt::Debug + Clone {
         self.has_vars_bound_at_or_above(ty::INNERMOST)
     }
 
-    #[instrument(level = "trace", ret)]
     fn has_type_flags(&self, flags: TypeFlags) -> bool {
-        self.visit_with(&mut HasTypeFlagsVisitor { flags }).break_value() == Some(FoundFlags)
+        let res =
+            self.visit_with(&mut HasTypeFlagsVisitor { flags }).break_value() == Some(FoundFlags);
+        trace!(?self, ?flags, ?res, "has_type_flags");
+        res
     }
     fn has_projections(&self) -> bool {
         self.has_type_flags(TypeFlags::HAS_PROJECTION)
@@ -560,10 +562,8 @@ impl<'tcx> TypeVisitor<'tcx> for HasTypeFlagsVisitor {
     type BreakTy = FoundFlags;
 
     #[inline]
-    #[instrument(skip(self), level = "trace", ret)]
     fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
         let flags = t.flags();
-        trace!(t.flags=?t.flags());
         if flags.intersects(self.flags) {
             ControlFlow::Break(FoundFlags)
         } else {
@@ -572,10 +572,8 @@ impl<'tcx> TypeVisitor<'tcx> for HasTypeFlagsVisitor {
     }
 
     #[inline]
-    #[instrument(skip(self), level = "trace", ret)]
     fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
         let flags = r.type_flags();
-        trace!(r.flags=?flags);
         if flags.intersects(self.flags) {
             ControlFlow::Break(FoundFlags)
         } else {
@@ -584,7 +582,6 @@ impl<'tcx> TypeVisitor<'tcx> for HasTypeFlagsVisitor {
     }
 
     #[inline]
-    #[instrument(level = "trace", ret)]
     fn visit_const(&mut self, c: ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> {
         let flags = FlagComputation::for_const(c);
         trace!(r.flags=?flags);
@@ -596,14 +593,7 @@ impl<'tcx> TypeVisitor<'tcx> for HasTypeFlagsVisitor {
     }
 
     #[inline]
-    #[instrument(level = "trace", ret)]
     fn visit_predicate(&mut self, predicate: ty::Predicate<'tcx>) -> ControlFlow<Self::BreakTy> {
-        debug!(
-            "HasTypeFlagsVisitor: predicate={:?} predicate.flags={:?} self.flags={:?}",
-            predicate,
-            predicate.flags(),
-            self.flags
-        );
         if predicate.flags().intersects(self.flags) {
             ControlFlow::Break(FoundFlags)
         } else {
diff --git a/compiler/rustc_middle/src/ty/walk.rs b/compiler/rustc_middle/src/ty/walk.rs
index 34dbb6e9f68..708a5e4d059 100644
--- a/compiler/rustc_middle/src/ty/walk.rs
+++ b/compiler/rustc_middle/src/ty/walk.rs
@@ -4,7 +4,7 @@
 use crate::ty::subst::{GenericArg, GenericArgKind};
 use crate::ty::{self, Ty};
 use rustc_data_structures::sso::SsoHashSet;
-use smallvec::{self, SmallVec};
+use smallvec::SmallVec;
 
 // 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/values.rs b/compiler/rustc_middle/src/values.rs
index 70b98e59a8b..c242be57031 100644
--- a/compiler/rustc_middle/src/values.rs
+++ b/compiler/rustc_middle/src/values.rs
@@ -1,3 +1,4 @@
+use crate::dep_graph::DepKind;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::{pluralize, struct_span_err, Applicability, MultiSpan};
 use rustc_hir as hir;
@@ -11,16 +12,16 @@ use rustc_span::Span;
 
 use std::fmt::Write;
 
-impl<'tcx> Value<TyCtxt<'tcx>> for Ty<'_> {
-    fn from_cycle_error(tcx: TyCtxt<'tcx>, _: &[QueryInfo]) -> Self {
+impl<'tcx> Value<TyCtxt<'tcx>, DepKind> for Ty<'_> {
+    fn from_cycle_error(tcx: TyCtxt<'tcx>, _: &[QueryInfo<DepKind>]) -> Self {
         // SAFETY: This is never called when `Self` is not `Ty<'tcx>`.
         // FIXME: Represent the above fact in the trait system somehow.
         unsafe { std::mem::transmute::<Ty<'tcx>, Ty<'_>>(tcx.ty_error()) }
     }
 }
 
-impl<'tcx> Value<TyCtxt<'tcx>> for ty::SymbolName<'_> {
-    fn from_cycle_error(tcx: TyCtxt<'tcx>, _: &[QueryInfo]) -> Self {
+impl<'tcx> Value<TyCtxt<'tcx>, DepKind> for ty::SymbolName<'_> {
+    fn from_cycle_error(tcx: TyCtxt<'tcx>, _: &[QueryInfo<DepKind>]) -> Self {
         // SAFETY: This is never called when `Self` is not `SymbolName<'tcx>`.
         // FIXME: Represent the above fact in the trait system somehow.
         unsafe {
@@ -31,12 +32,12 @@ impl<'tcx> Value<TyCtxt<'tcx>> for ty::SymbolName<'_> {
     }
 }
 
-impl<'tcx> Value<TyCtxt<'tcx>> for ty::Binder<'_, ty::FnSig<'_>> {
-    fn from_cycle_error(tcx: TyCtxt<'tcx>, stack: &[QueryInfo]) -> Self {
+impl<'tcx> Value<TyCtxt<'tcx>, DepKind> for ty::Binder<'_, ty::FnSig<'_>> {
+    fn from_cycle_error(tcx: TyCtxt<'tcx>, stack: &[QueryInfo<DepKind>]) -> Self {
         let err = tcx.ty_error();
 
         let arity = if let Some(frame) = stack.get(0)
-            && frame.query.name == "fn_sig"
+            && frame.query.dep_kind == DepKind::fn_sig
             && let Some(def_id) = frame.query.def_id
             && let Some(node) = tcx.hir().get_if_local(def_id)
             && let Some(sig) = node.fn_sig()
@@ -61,12 +62,12 @@ impl<'tcx> Value<TyCtxt<'tcx>> for ty::Binder<'_, ty::FnSig<'_>> {
     }
 }
 
-impl<'tcx> Value<TyCtxt<'tcx>> for Representability {
-    fn from_cycle_error(tcx: TyCtxt<'tcx>, cycle: &[QueryInfo]) -> Self {
+impl<'tcx> Value<TyCtxt<'tcx>, DepKind> for Representability {
+    fn from_cycle_error(tcx: TyCtxt<'tcx>, cycle: &[QueryInfo<DepKind>]) -> Self {
         let mut item_and_field_ids = Vec::new();
         let mut representable_ids = FxHashSet::default();
         for info in cycle {
-            if info.query.name == "representability"
+            if info.query.dep_kind == DepKind::representability
                 && let Some(field_id) = info.query.def_id
                 && let Some(field_id) = field_id.as_local()
                 && let Some(DefKind::Field) = info.query.def_kind
@@ -80,7 +81,7 @@ impl<'tcx> Value<TyCtxt<'tcx>> for Representability {
             }
         }
         for info in cycle {
-            if info.query.name == "representability_adt_ty"
+            if info.query.dep_kind == DepKind::representability_adt_ty
                 && let Some(def_id) = info.query.ty_adt_id
                 && let Some(def_id) = def_id.as_local()
                 && !item_and_field_ids.iter().any(|&(id, _)| id == def_id)
diff --git a/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs b/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs
index 7c39a93a8eb..dca4906c07d 100644
--- a/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs
+++ b/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs
@@ -15,9 +15,6 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> {
             @call("mir_retag", args) => {
                 Ok(StatementKind::Retag(RetagKind::Default, Box::new(self.parse_place(args[0])?)))
             },
-            @call("mir_retag_raw", args) => {
-                Ok(StatementKind::Retag(RetagKind::Raw, Box::new(self.parse_place(args[0])?)))
-            },
             @call("mir_set_discriminant", args) => {
                 let place = self.parse_place(args[0])?;
                 let var = self.parse_integer_literal(args[1])? as u32;
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 3b7ed818dc9..1d96893c7a3 100644
--- a/compiler/rustc_mir_build/src/build/expr/as_constant.rs
+++ b/compiler/rustc_mir_build/src/build/expr/as_constant.rs
@@ -66,14 +66,14 @@ pub fn as_constant_inner<'tcx>(
 
             let literal = ConstantKind::Val(ConstValue::Scalar(Scalar::Int(lit)), ty);
 
-            Constant { span, user_ty: user_ty, literal }
+            Constant { span, user_ty, literal }
         }
         ExprKind::ZstLiteral { ref user_ty } => {
             let user_ty = user_ty.as_ref().map(push_cuta).flatten();
 
             let literal = ConstantKind::Val(ConstValue::ZeroSized, ty);
 
-            Constant { span, user_ty: user_ty, literal }
+            Constant { span, user_ty, literal }
         }
         ExprKind::NamedConst { def_id, substs, ref user_ty } => {
             let user_ty = user_ty.as_ref().map(push_cuta).flatten();
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 c8610af7038..dbcb0132c9f 100644
--- a/compiler/rustc_mir_build/src/build/expr/as_operand.rs
+++ b/compiler/rustc_mir_build/src/build/expr/as_operand.rs
@@ -72,7 +72,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
     /// will actually provide a pointer to the interior of the box, and not move the `dyn Debug`
     /// value to the stack.
     ///
-    /// See #68034 for more details.
+    /// See #68304 for more details.
     pub(crate) fn as_local_call_operand(
         &mut self,
         block: BasicBlock,
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 edd52728626..e22fa6365dc 100644
--- a/compiler/rustc_mir_build/src/build/expr/as_place.rs
+++ b/compiler/rustc_mir_build/src/build/expr/as_place.rs
@@ -81,8 +81,8 @@ pub(in crate::build) struct PlaceBuilder<'tcx> {
 /// ProjectionElems `Downcast`, `ConstantIndex`, `Index`, or `Subslice` because those will never be
 /// part of a path that is captured by a closure. We stop applying projections once we see the first
 /// projection that isn't captured by a closure.
-fn convert_to_hir_projections_and_truncate_for_capture<'tcx>(
-    mir_projections: &[PlaceElem<'tcx>],
+fn convert_to_hir_projections_and_truncate_for_capture(
+    mir_projections: &[PlaceElem<'_>],
 ) -> Vec<HirProjectionKind> {
     let mut hir_projections = Vec::new();
     let mut variant = None;
diff --git a/compiler/rustc_mir_build/src/build/matches/mod.rs b/compiler/rustc_mir_build/src/build/matches/mod.rs
index 7edcd46a34f..f90aba80bf3 100644
--- a/compiler/rustc_mir_build/src/build/matches/mod.rs
+++ b/compiler/rustc_mir_build/src/build/matches/mod.rs
@@ -2210,7 +2210,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             BindingMode::ByValue => ty::BindingMode::BindByValue(mutability),
             BindingMode::ByRef(_) => ty::BindingMode::BindByReference(mutability),
         };
-        let local = LocalDecl::<'tcx> {
+        let local = LocalDecl {
             mutability,
             ty: var_ty,
             user_ty: if user_ty.is_empty() { None } else { Some(Box::new(user_ty)) },
diff --git a/compiler/rustc_mir_build/src/build/mod.rs b/compiler/rustc_mir_build/src/build/mod.rs
index c785dfb500f..9daf68a15f4 100644
--- a/compiler/rustc_mir_build/src/build/mod.rs
+++ b/compiler/rustc_mir_build/src/build/mod.rs
@@ -28,10 +28,10 @@ use rustc_target::spec::abi::Abi;
 
 use super::lints;
 
-pub(crate) fn mir_built<'tcx>(
-    tcx: TyCtxt<'tcx>,
+pub(crate) fn mir_built(
+    tcx: TyCtxt<'_>,
     def: ty::WithOptConstParam<LocalDefId>,
-) -> &'tcx rustc_data_structures::steal::Steal<Body<'tcx>> {
+) -> &rustc_data_structures::steal::Steal<Body<'_>> {
     if let Some(def) = def.try_upgrade(tcx) {
         return tcx.mir_built(def);
     }
@@ -625,12 +625,12 @@ fn construct_const<'a, 'tcx>(
 ///
 /// This is required because we may still want to run MIR passes on an item
 /// with type errors, but normal MIR construction can't handle that in general.
-fn construct_error<'tcx>(
-    tcx: TyCtxt<'tcx>,
+fn construct_error(
+    tcx: TyCtxt<'_>,
     def: LocalDefId,
     body_owner_kind: hir::BodyOwnerKind,
     err: ErrorGuaranteed,
-) -> Body<'tcx> {
+) -> Body<'_> {
     let span = tcx.def_span(def);
     let hir_id = tcx.hir().local_def_id_to_hir_id(def);
     let generator_kind = tcx.generator_kind(def);
diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs
index 99e96ff77ce..3c311729a52 100644
--- a/compiler/rustc_mir_build/src/check_unsafety.rs
+++ b/compiler/rustc_mir_build/src/check_unsafety.rs
@@ -703,7 +703,7 @@ impl UnsafeOpKind {
     }
 }
 
-pub fn check_unsafety<'tcx>(tcx: TyCtxt<'tcx>, def: ty::WithOptConstParam<LocalDefId>) {
+pub fn check_unsafety(tcx: TyCtxt<'_>, def: ty::WithOptConstParam<LocalDefId>) {
     // THIR unsafeck is gated under `-Z thir-unsafeck`
     if !tcx.sess.opts.unstable_opts.thir_unsafeck {
         return;
@@ -749,7 +749,7 @@ pub fn check_unsafety<'tcx>(tcx: TyCtxt<'tcx>, def: ty::WithOptConstParam<LocalD
     visitor.visit_expr(&thir[expr]);
 }
 
-pub(crate) fn thir_check_unsafety<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) {
+pub(crate) fn thir_check_unsafety(tcx: TyCtxt<'_>, def_id: LocalDefId) {
     if let Some(def) = ty::WithOptConstParam::try_lookup(def_id, tcx) {
         tcx.thir_check_unsafety_for_const_arg(def)
     } else {
@@ -757,8 +757,8 @@ pub(crate) fn thir_check_unsafety<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) {
     }
 }
 
-pub(crate) fn thir_check_unsafety_for_const_arg<'tcx>(
-    tcx: TyCtxt<'tcx>,
+pub(crate) fn thir_check_unsafety_for_const_arg(
+    tcx: TyCtxt<'_>,
     (did, param_did): (LocalDefId, DefId),
 ) {
     check_unsafety(tcx, ty::WithOptConstParam { did, const_param_did: Some(param_did) })
diff --git a/compiler/rustc_mir_build/src/thir/cx/mod.rs b/compiler/rustc_mir_build/src/thir/cx/mod.rs
index b5c4b7b137d..a355e1bdab5 100644
--- a/compiler/rustc_mir_build/src/thir/cx/mod.rs
+++ b/compiler/rustc_mir_build/src/thir/cx/mod.rs
@@ -18,10 +18,10 @@ use rustc_middle::thir::*;
 use rustc_middle::ty::{self, RvalueScopes, TyCtxt};
 use rustc_span::Span;
 
-pub(crate) fn thir_body<'tcx>(
-    tcx: TyCtxt<'tcx>,
+pub(crate) fn thir_body(
+    tcx: TyCtxt<'_>,
     owner_def: ty::WithOptConstParam<LocalDefId>,
-) -> Result<(&'tcx Steal<Thir<'tcx>>, ExprId), ErrorGuaranteed> {
+) -> Result<(&Steal<Thir<'_>>, ExprId), ErrorGuaranteed> {
     let hir = tcx.hir();
     let body = hir.body(hir.body_owned_by(owner_def.did));
     let mut cx = Cx::new(tcx, owner_def);
@@ -52,10 +52,7 @@ pub(crate) fn thir_body<'tcx>(
     Ok((tcx.alloc_steal_thir(cx.thir), expr))
 }
 
-pub(crate) fn thir_tree<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    owner_def: ty::WithOptConstParam<LocalDefId>,
-) -> String {
+pub(crate) fn thir_tree(tcx: TyCtxt<'_>, owner_def: ty::WithOptConstParam<LocalDefId>) -> String {
     match thir_body(tcx, owner_def) {
         Ok((thir, _)) => format!("{:#?}", thir.steal()),
         Err(_) => "error".into(),
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 7e1f708b0d6..6470efab2e9 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
@@ -70,7 +70,7 @@ mod fallback_to_const_ref {
     /// hoops to get a reference to the value.
     pub(super) struct FallbackToConstRef(());
 
-    pub(super) fn fallback_to_const_ref<'tcx>(c2p: &super::ConstToPat<'tcx>) -> FallbackToConstRef {
+    pub(super) fn fallback_to_const_ref(c2p: &super::ConstToPat<'_>) -> FallbackToConstRef {
         assert!(c2p.behind_reference.get());
         FallbackToConstRef(())
     }
diff --git a/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs
index 18e9c69c487..a95349d7670 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs
@@ -404,7 +404,7 @@ impl SplitIntRange {
     }
 
     /// Iterate over the contained ranges.
-    fn iter<'a>(&'a self) -> impl Iterator<Item = IntRange> + Captures<'a> {
+    fn iter(&self) -> impl Iterator<Item = IntRange> + Captures<'_> {
         use IntBorder::*;
 
         let self_range = Self::to_borders(self.range.clone());
@@ -612,7 +612,7 @@ impl SplitVarLenSlice {
     }
 
     /// Iterate over the partition of this slice.
-    fn iter<'a>(&'a self) -> impl Iterator<Item = Slice> + Captures<'a> {
+    fn iter(&self) -> impl Iterator<Item = Slice> + Captures<'_> {
         let smaller_lengths = match self.array_len {
             // The only admissible fixed-length slice is one of the array size. Whether `max_slice`
             // is fixed-length or variable-length, it will be the only relevant slice to output
diff --git a/compiler/rustc_mir_dataflow/src/impls/liveness.rs b/compiler/rustc_mir_dataflow/src/impls/liveness.rs
index 3e08a8799ef..923dc16c11b 100644
--- a/compiler/rustc_mir_dataflow/src/impls/liveness.rs
+++ b/compiler/rustc_mir_dataflow/src/impls/liveness.rs
@@ -149,7 +149,7 @@ enum DefUse {
 }
 
 impl DefUse {
-    fn apply<'tcx>(trans: &mut impl GenKill<Local>, place: Place<'tcx>, context: PlaceContext) {
+    fn apply(trans: &mut impl GenKill<Local>, place: Place<'_>, context: PlaceContext) {
         match DefUse::for_place(place, context) {
             Some(DefUse::Def) => trans.kill(place.local),
             Some(DefUse::Use) => trans.gen(place.local),
@@ -157,7 +157,7 @@ impl DefUse {
         }
     }
 
-    fn for_place<'tcx>(place: Place<'tcx>, context: PlaceContext) -> Option<DefUse> {
+    fn for_place(place: Place<'_>, context: PlaceContext) -> Option<DefUse> {
         match context {
             PlaceContext::NonUse(_) => None,
 
diff --git a/compiler/rustc_mir_dataflow/src/value_analysis.rs b/compiler/rustc_mir_dataflow/src/value_analysis.rs
index 7df01142264..fe5ee4011ab 100644
--- a/compiler/rustc_mir_dataflow/src/value_analysis.rs
+++ b/compiler/rustc_mir_dataflow/src/value_analysis.rs
@@ -823,7 +823,7 @@ fn iter_fields<'tcx>(
 }
 
 /// Returns all locals with projections that have their reference or address taken.
-fn excluded_locals<'tcx>(body: &Body<'tcx>) -> IndexVec<Local, bool> {
+fn excluded_locals(body: &Body<'_>) -> IndexVec<Local, bool> {
     struct Collector {
         result: IndexVec<Local, bool>,
     }
diff --git a/compiler/rustc_mir_transform/src/check_unsafety.rs b/compiler/rustc_mir_transform/src/check_unsafety.rs
index 9c22b5df73c..adf6ae4c727 100644
--- a/compiler/rustc_mir_transform/src/check_unsafety.rs
+++ b/compiler/rustc_mir_transform/src/check_unsafety.rs
@@ -490,10 +490,10 @@ fn check_unused_unsafe(
     unused_unsafes
 }
 
-fn unsafety_check_result<'tcx>(
-    tcx: TyCtxt<'tcx>,
+fn unsafety_check_result(
+    tcx: TyCtxt<'_>,
     def: ty::WithOptConstParam<LocalDefId>,
-) -> &'tcx UnsafetyCheckResult {
+) -> &UnsafetyCheckResult {
     debug!("unsafety_violations({:?})", def);
 
     // N.B., this borrow is valid because all the consumers of
diff --git a/compiler/rustc_mir_transform/src/coverage/mod.rs b/compiler/rustc_mir_transform/src/coverage/mod.rs
index 60481014488..1468afc6456 100644
--- a/compiler/rustc_mir_transform/src/coverage/mod.rs
+++ b/compiler/rustc_mir_transform/src/coverage/mod.rs
@@ -533,10 +533,10 @@ fn make_code_region(
     }
 }
 
-fn fn_sig_and_body<'tcx>(
-    tcx: TyCtxt<'tcx>,
+fn fn_sig_and_body(
+    tcx: TyCtxt<'_>,
     def_id: DefId,
-) -> (Option<&'tcx rustc_hir::FnSig<'tcx>>, &'tcx rustc_hir::Body<'tcx>) {
+) -> (Option<&rustc_hir::FnSig<'_>>, &rustc_hir::Body<'_>) {
     // FIXME(#79625): Consider improving MIR to provide the information needed, to avoid going back
     // to HIR for it.
     let hir_node = tcx.hir().get_if_local(def_id).expect("expected DefId is local");
diff --git a/compiler/rustc_mir_transform/src/coverage/query.rs b/compiler/rustc_mir_transform/src/coverage/query.rs
index dc1e68b253e..3bd7f31b45d 100644
--- a/compiler/rustc_mir_transform/src/coverage/query.rs
+++ b/compiler/rustc_mir_transform/src/coverage/query.rs
@@ -136,7 +136,7 @@ fn coverageinfo<'tcx>(tcx: TyCtxt<'tcx>, instance_def: ty::InstanceDef<'tcx>) ->
     coverage_visitor.info
 }
 
-fn covered_code_regions<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> Vec<&'tcx CodeRegion> {
+fn covered_code_regions(tcx: TyCtxt<'_>, def_id: DefId) -> Vec<&CodeRegion> {
     let body = mir_body(tcx, def_id);
     body.basic_blocks
         .iter()
@@ -163,7 +163,7 @@ fn is_inlined(body: &Body<'_>, statement: &Statement<'_>) -> bool {
 /// This function ensures we obtain the correct MIR for the given item irrespective of
 /// whether that means const mir or runtime mir. For `const fn` this opts for runtime
 /// mir.
-fn mir_body<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> &'tcx mir::Body<'tcx> {
+fn mir_body(tcx: TyCtxt<'_>, def_id: DefId) -> &mir::Body<'_> {
     let id = ty::WithOptConstParam::unknown(def_id);
     let def = ty::InstanceDef::Item(id);
     tcx.instance_mir(def)
diff --git a/compiler/rustc_mir_transform/src/coverage/tests.rs b/compiler/rustc_mir_transform/src/coverage/tests.rs
index eba6a2b34e4..fa7f22303a8 100644
--- a/compiler/rustc_mir_transform/src/coverage/tests.rs
+++ b/compiler/rustc_mir_transform/src/coverage/tests.rs
@@ -169,7 +169,7 @@ impl<'tcx> MockBlocks<'tcx> {
     }
 }
 
-fn debug_basic_blocks<'tcx>(mir_body: &Body<'tcx>) -> String {
+fn debug_basic_blocks(mir_body: &Body<'_>) -> String {
     format!(
         "{:?}",
         mir_body
diff --git a/compiler/rustc_mir_transform/src/deduce_param_attrs.rs b/compiler/rustc_mir_transform/src/deduce_param_attrs.rs
index 92f1fff6beb..ddab7bbb2e3 100644
--- a/compiler/rustc_mir_transform/src/deduce_param_attrs.rs
+++ b/compiler/rustc_mir_transform/src/deduce_param_attrs.rs
@@ -129,7 +129,7 @@ impl<'tcx> Visitor<'tcx> for DeduceReadOnly {
 }
 
 /// Returns true if values of a given type will never be passed indirectly, regardless of ABI.
-fn type_will_always_be_passed_directly<'tcx>(ty: Ty<'tcx>) -> bool {
+fn type_will_always_be_passed_directly(ty: Ty<'_>) -> bool {
     matches!(
         ty.kind(),
         ty::Bool
diff --git a/compiler/rustc_mir_transform/src/dest_prop.rs b/compiler/rustc_mir_transform/src/dest_prop.rs
index 74d8337653f..08e296a8371 100644
--- a/compiler/rustc_mir_transform/src/dest_prop.rs
+++ b/compiler/rustc_mir_transform/src/dest_prop.rs
@@ -658,7 +658,7 @@ impl WriteInfo {
         }
     }
 
-    fn add_place<'tcx>(&mut self, place: Place<'tcx>) {
+    fn add_place(&mut self, place: Place<'_>) {
         self.writes.push(place.local);
     }
 
diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs
index aba5a8580f1..ae79c2290f6 100644
--- a/compiler/rustc_mir_transform/src/lib.rs
+++ b/compiler/rustc_mir_transform/src/lib.rs
@@ -266,10 +266,7 @@ fn mir_const_qualif(tcx: TyCtxt<'_>, def: ty::WithOptConstParam<LocalDefId>) ->
 /// Make MIR ready for const evaluation. This is run on all MIR, not just on consts!
 /// FIXME(oli-obk): it's unclear whether we still need this phase (and its corresponding query).
 /// We used to have this for pre-miri MIR based const eval.
-fn mir_const<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    def: ty::WithOptConstParam<LocalDefId>,
-) -> &'tcx Steal<Body<'tcx>> {
+fn mir_const(tcx: TyCtxt<'_>, def: ty::WithOptConstParam<LocalDefId>) -> &Steal<Body<'_>> {
     if let Some(def) = def.try_upgrade(tcx) {
         return tcx.mir_const(def);
     }
@@ -308,10 +305,10 @@ fn mir_const<'tcx>(
 }
 
 /// Compute the main MIR body and the list of MIR bodies of the promoteds.
-fn mir_promoted<'tcx>(
-    tcx: TyCtxt<'tcx>,
+fn mir_promoted(
+    tcx: TyCtxt<'_>,
     def: ty::WithOptConstParam<LocalDefId>,
-) -> (&'tcx Steal<Body<'tcx>>, &'tcx Steal<IndexVec<Promoted, Body<'tcx>>>) {
+) -> (&Steal<Body<'_>>, &Steal<IndexVec<Promoted, Body<'_>>>) {
     if let Some(def) = def.try_upgrade(tcx) {
         return tcx.mir_promoted(def);
     }
@@ -350,7 +347,7 @@ fn mir_promoted<'tcx>(
 }
 
 /// Compute the MIR that is used during CTFE (and thus has no optimizations run on it)
-fn mir_for_ctfe<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> &'tcx Body<'tcx> {
+fn mir_for_ctfe(tcx: TyCtxt<'_>, def_id: DefId) -> &Body<'_> {
     let did = def_id.expect_local();
     if let Some(def) = ty::WithOptConstParam::try_lookup(did, tcx) {
         tcx.mir_for_ctfe_of_const_arg(def)
@@ -364,10 +361,7 @@ fn mir_for_ctfe<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> &'tcx Body<'tcx> {
 /// we'd get cycle errors with `mir_for_ctfe`, because typeck would need to typeck
 /// the const parameter while type checking the main body, which in turn would try
 /// to type check the main body again.
-fn mir_for_ctfe_of_const_arg<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    (did, param_did): (LocalDefId, DefId),
-) -> &'tcx Body<'tcx> {
+fn mir_for_ctfe_of_const_arg(tcx: TyCtxt<'_>, (did, param_did): (LocalDefId, DefId)) -> &Body<'_> {
     tcx.arena.alloc(inner_mir_for_ctfe(
         tcx,
         ty::WithOptConstParam { did, const_param_did: Some(param_did) },
@@ -424,10 +418,10 @@ fn inner_mir_for_ctfe(tcx: TyCtxt<'_>, def: ty::WithOptConstParam<LocalDefId>) -
 /// Obtain just the main MIR (no promoteds) and run some cleanups on it. This also runs
 /// mir borrowck *before* doing so in order to ensure that borrowck can be run and doesn't
 /// end up missing the source MIR due to stealing happening.
-fn mir_drops_elaborated_and_const_checked<'tcx>(
-    tcx: TyCtxt<'tcx>,
+fn mir_drops_elaborated_and_const_checked(
+    tcx: TyCtxt<'_>,
     def: ty::WithOptConstParam<LocalDefId>,
-) -> &'tcx Steal<Body<'tcx>> {
+) -> &Steal<Body<'_>> {
     if let Some(def) = def.try_upgrade(tcx) {
         return tcx.mir_drops_elaborated_and_const_checked(def);
     }
@@ -597,7 +591,7 @@ fn run_optimization_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
 }
 
 /// Optimize the MIR and prepare it for codegen.
-fn optimized_mir<'tcx>(tcx: TyCtxt<'tcx>, did: DefId) -> &'tcx Body<'tcx> {
+fn optimized_mir(tcx: TyCtxt<'_>, did: DefId) -> &Body<'_> {
     let did = did.expect_local();
     assert_eq!(ty::WithOptConstParam::try_lookup(did, tcx), None);
     tcx.arena.alloc(inner_optimized_mir(tcx, did))
@@ -634,10 +628,10 @@ fn inner_optimized_mir(tcx: TyCtxt<'_>, did: LocalDefId) -> Body<'_> {
 
 /// Fetch all the promoteds of an item and prepare their MIR bodies to be ready for
 /// constant evaluation once all substitutions become known.
-fn promoted_mir<'tcx>(
-    tcx: TyCtxt<'tcx>,
+fn promoted_mir(
+    tcx: TyCtxt<'_>,
     def: ty::WithOptConstParam<LocalDefId>,
-) -> &'tcx IndexVec<Promoted, Body<'tcx>> {
+) -> &IndexVec<Promoted, Body<'_>> {
     if tcx.is_constructor(def.did.to_def_id()) {
         return tcx.arena.alloc(IndexVec::new());
     }
diff --git a/compiler/rustc_mir_transform/src/shim.rs b/compiler/rustc_mir_transform/src/shim.rs
index f8b55c86287..dace540fa29 100644
--- a/compiler/rustc_mir_transform/src/shim.rs
+++ b/compiler/rustc_mir_transform/src/shim.rs
@@ -174,9 +174,36 @@ fn build_drop_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, ty: Option<Ty<'tcx>>)
     let mut body =
         new_body(source, blocks, local_decls_for_sig(&sig, span), sig.inputs().len(), span);
 
+    // The first argument (index 0), but add 1 for the return value.
+    let mut dropee_ptr = Place::from(Local::new(1 + 0));
+    if tcx.sess.opts.unstable_opts.mir_emit_retag {
+        // We want to treat the function argument as if it was passed by `&mut`. As such, we
+        // generate
+        // ```
+        // temp = &mut *arg;
+        // Retag(temp, FnEntry)
+        // ```
+        // It's important that we do this first, before anything that depends on `dropee_ptr`
+        // has been put into the body.
+        let reborrow = Rvalue::Ref(
+            tcx.lifetimes.re_erased,
+            BorrowKind::Mut { allow_two_phase_borrow: false },
+            tcx.mk_place_deref(dropee_ptr),
+        );
+        let ref_ty = reborrow.ty(body.local_decls(), tcx);
+        dropee_ptr = body.local_decls.push(LocalDecl::new(ref_ty, span)).into();
+        let new_statements = [
+            StatementKind::Assign(Box::new((dropee_ptr, reborrow))),
+            StatementKind::Retag(RetagKind::FnEntry, Box::new(dropee_ptr)),
+        ];
+        for s in new_statements {
+            body.basic_blocks_mut()[START_BLOCK]
+                .statements
+                .push(Statement { source_info, kind: s });
+        }
+    }
+
     if ty.is_some() {
-        // The first argument (index 0), but add 1 for the return value.
-        let dropee_ptr = Place::from(Local::new(1 + 0));
         let patch = {
             let param_env = tcx.param_env_reveal_all_normalized(def_id);
             let mut elaborator =
diff --git a/compiler/rustc_mir_transform/src/simplify_try.rs b/compiler/rustc_mir_transform/src/simplify_try.rs
index baeb620ef24..e4f3ace9a93 100644
--- a/compiler/rustc_mir_transform/src/simplify_try.rs
+++ b/compiler/rustc_mir_transform/src/simplify_try.rs
@@ -532,7 +532,7 @@ struct VarField<'tcx> {
 }
 
 /// Match on `((_LOCAL as Variant).FIELD: TY)`.
-fn match_variant_field_place<'tcx>(place: Place<'tcx>) -> Option<(Local, VarField<'tcx>)> {
+fn match_variant_field_place(place: Place<'_>) -> Option<(Local, VarField<'_>)> {
     match place.as_ref() {
         PlaceRef {
             local,
diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs
index deeeb9af4eb..59cc500a99d 100644
--- a/compiler/rustc_monomorphize/src/collector.rs
+++ b/compiler/rustc_monomorphize/src/collector.rs
@@ -843,7 +843,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> {
             mir::TerminatorKind::Abort { .. } => {
                 let instance = Instance::mono(
                     tcx,
-                    tcx.require_lang_item(LangItem::PanicNoUnwind, Some(source)),
+                    tcx.require_lang_item(LangItem::PanicCannotUnwind, Some(source)),
                 );
                 if should_codegen_locally(tcx, &instance) {
                     self.output.push(create_fn_mono_item(tcx, instance, source));
diff --git a/compiler/rustc_monomorphize/src/partitioning/mod.rs b/compiler/rustc_monomorphize/src/partitioning/mod.rs
index 38e1d98e44e..4f25fc71314 100644
--- a/compiler/rustc_monomorphize/src/partitioning/mod.rs
+++ b/compiler/rustc_monomorphize/src/partitioning/mod.rs
@@ -305,7 +305,7 @@ where
                 );
             }
 
-            let _ = writeln!(s, "");
+            let _ = writeln!(s);
         }
 
         std::mem::take(s)
@@ -345,10 +345,7 @@ where
     }
 }
 
-fn collect_and_partition_mono_items<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    (): (),
-) -> (&'tcx DefIdSet, &'tcx [CodegenUnit<'tcx>]) {
+fn collect_and_partition_mono_items(tcx: TyCtxt<'_>, (): ()) -> (&DefIdSet, &[CodegenUnit<'_>]) {
     let collection_mode = match tcx.sess.opts.unstable_opts.print_mono_items {
         Some(ref s) => {
             let mode_string = s.to_lowercase();
@@ -541,7 +538,7 @@ fn dump_mono_items_stats<'tcx>(
     Ok(())
 }
 
-fn codegened_and_inlined_items<'tcx>(tcx: TyCtxt<'tcx>, (): ()) -> &'tcx DefIdSet {
+fn codegened_and_inlined_items(tcx: TyCtxt<'_>, (): ()) -> &DefIdSet {
     let (items, cgus) = tcx.collect_and_partition_mono_items(());
     let mut visited = DefIdSet::default();
     let mut result = items.clone();
diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs
index 18a0bee9c2e..574591529f3 100644
--- a/compiler/rustc_parse/src/errors.rs
+++ b/compiler/rustc_parse/src/errors.rs
@@ -1229,3 +1229,11 @@ pub(crate) struct FnTypoWithImpl {
     #[suggestion(applicability = "maybe-incorrect", code = "impl", style = "verbose")]
     pub fn_span: Span,
 }
+
+#[derive(Diagnostic)]
+#[diag(parse_expected_fn_path_found_fn_keyword)]
+pub(crate) struct ExpectedFnPathFoundFnKeyword {
+    #[primary_span]
+    #[suggestion(applicability = "machine-applicable", code = "Fn", style = "verbose")]
+    pub fn_token_span: Span,
+}
diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs
index 0191ab730c8..61fe379c3e9 100644
--- a/compiler/rustc_parse/src/parser/diagnostics.rs
+++ b/compiler/rustc_parse/src/parser/diagnostics.rs
@@ -41,7 +41,6 @@ use rustc_span::{Span, SpanSnippetError, 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) -> Param {
diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs
index c0ed450b985..6a115088eca 100644
--- a/compiler/rustc_parse/src/parser/expr.rs
+++ b/compiler/rustc_parse/src/parser/expr.rs
@@ -182,7 +182,7 @@ impl<'a> Parser<'a> {
                 LhsExpr::AttributesParsed(attrs) => Some(attrs),
                 _ => None,
             };
-            if [token::DotDot, token::DotDotDot, token::DotDotEq].contains(&self.token.kind) {
+            if self.token.is_range_separator() {
                 return self.parse_prefix_range_expr(attrs);
             } else {
                 self.parse_prefix_expr(attrs)?
@@ -514,7 +514,7 @@ impl<'a> Parser<'a> {
         }
 
         debug_assert!(
-            [token::DotDot, token::DotDotDot, token::DotDotEq].contains(&self.token.kind),
+            self.token.is_range_separator(),
             "parse_prefix_range_expr: token {:?} is not DotDot/DotDotEq",
             self.token
         );
@@ -899,7 +899,11 @@ impl<'a> Parser<'a> {
         let has_lifetime = self.token.is_lifetime() && self.look_ahead(1, |t| t != &token::Colon);
         let lifetime = has_lifetime.then(|| self.expect_lifetime()); // For recovery, see below.
         let (borrow_kind, mutbl) = self.parse_borrow_modifiers(lo);
-        let expr = self.parse_prefix_expr(None);
+        let expr = if self.token.is_range_separator() {
+            self.parse_prefix_range_expr(None)
+        } else {
+            self.parse_prefix_expr(None)
+        };
         let (hi, expr) = self.interpolated_or_expr_span(expr)?;
         let span = lo.to(hi);
         if let Some(lt) = lifetime {
diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs
index 7c2d01509de..e1ced2eb965 100644
--- a/compiler/rustc_parse/src/parser/item.rs
+++ b/compiler/rustc_parse/src/parser/item.rs
@@ -24,7 +24,6 @@ use rustc_span::symbol::{kw, sym, Ident, Symbol};
 use rustc_span::DUMMY_SP;
 use std::mem;
 use 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.
@@ -2465,7 +2464,6 @@ impl<'a> Parser<'a> {
             };
             let (pat, ty) = if is_name_required || this.is_named_param() {
                 debug!("parse_param_general parse_pat (is_name_required:{})", is_name_required);
-
                 let (pat, colon) = this.parse_fn_param_pat_colon()?;
                 if !colon {
                     let mut err = this.unexpected::<()>().unwrap_err();
diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs
index 40b88788caa..919e71bd115 100644
--- a/compiler/rustc_parse/src/parser/mod.rs
+++ b/compiler/rustc_parse/src/parser/mod.rs
@@ -1499,6 +1499,10 @@ impl<'a> Parser<'a> {
     pub fn clear_expected_tokens(&mut self) {
         self.expected_tokens.clear();
     }
+
+    pub fn approx_token_stream_pos(&self) -> usize {
+        self.token_cursor.num_next_calls
+    }
 }
 
 pub(crate) fn make_unclosed_delims_error(
diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs
index a1981e11477..0b057f2f577 100644
--- a/compiler/rustc_parse/src/parser/pat.rs
+++ b/compiler/rustc_parse/src/parser/pat.rs
@@ -491,17 +491,6 @@ impl<'a> Parser<'a> {
 
         if let PatKind::Ident(_, _, sub @ None) = &mut rhs.kind {
             // The user inverted the order, so help them fix that.
-            let mut applicability = Applicability::MachineApplicable;
-            // FIXME(bindings_after_at): Remove this code when stabilizing the feature.
-            lhs.walk(&mut |p| match p.kind {
-                // `check_match` is unhappy if the subpattern has a binding anywhere.
-                PatKind::Ident(..) => {
-                    applicability = Applicability::MaybeIncorrect;
-                    false // Short-circuit.
-                }
-                _ => true,
-            });
-
             let lhs_span = lhs.span;
             // Move the LHS into the RHS as a subpattern.
             // The RHS is now the full pattern.
@@ -510,7 +499,12 @@ impl<'a> Parser<'a> {
             self.struct_span_err(sp, "pattern on wrong side of `@`")
                 .span_label(lhs_span, "pattern on the left, should be on the right")
                 .span_label(rhs.span, "binding on the right, should be on the left")
-                .span_suggestion(sp, "switch the order", pprust::pat_to_string(&rhs), applicability)
+                .span_suggestion(
+                    sp,
+                    "switch the order",
+                    pprust::pat_to_string(&rhs),
+                    Applicability::MachineApplicable,
+                )
                 .emit();
         } else {
             // The special case above doesn't apply so we may have e.g. `A(x) @ B(y)`.
diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs
index b7206b57642..8661e9ca16b 100644
--- a/compiler/rustc_parse/src/parser/ty.rs
+++ b/compiler/rustc_parse/src/parser/ty.rs
@@ -1,8 +1,9 @@
 use super::{Parser, PathStyle, TokenType};
 
-use crate::errors::{FnPtrWithGenerics, FnPtrWithGenericsSugg};
+use crate::errors::{ExpectedFnPathFoundFnKeyword, FnPtrWithGenerics, FnPtrWithGenericsSugg};
 use crate::{maybe_recover_from_interpolated_ty_qpath, maybe_whole};
 
+use ast::DUMMY_NODE_ID;
 use rustc_ast::ptr::P;
 use rustc_ast::token::{self, Delimiter, Token, TokenKind};
 use rustc_ast::util::case::Case;
@@ -12,7 +13,9 @@ use rustc_ast::{
 };
 use rustc_errors::{pluralize, struct_span_err, Applicability, PResult};
 use rustc_span::source_map::Span;
-use rustc_span::symbol::{kw, sym};
+use rustc_span::symbol::{kw, sym, Ident};
+use rustc_span::Symbol;
+use thin_vec::thin_vec;
 
 /// Any `?` or `~const` modifiers that appear at the start of a bound.
 struct BoundModifiers {
@@ -613,6 +616,25 @@ impl<'a> Parser<'a> {
     /// Parses an `impl B0 + ... + Bn` type.
     fn parse_impl_ty(&mut self, impl_dyn_multi: &mut bool) -> PResult<'a, TyKind> {
         // Always parse bounds greedily for better error recovery.
+        if self.token.is_lifetime() {
+            self.look_ahead(1, |t| {
+                if let token::Ident(symname, _) = t.kind {
+                    // parse pattern with "'a Sized" we're supposed to give suggestion like
+                    // "'a + Sized"
+                    self.struct_span_err(
+                        self.token.span,
+                        &format!("expected `+` between lifetime and {}", symname),
+                    )
+                    .span_suggestion_verbose(
+                        self.token.span.shrink_to_hi(),
+                        "add `+`",
+                        " +",
+                        Applicability::MaybeIncorrect,
+                    )
+                    .emit();
+                }
+            })
+        }
         let bounds = self.parse_generic_bounds(None)?;
         *impl_dyn_multi = bounds.len() > 1 || self.prev_token.kind == TokenKind::BinOp(token::Plus);
         Ok(TyKind::ImplTrait(ast::DUMMY_NODE_ID, bounds))
@@ -912,7 +934,14 @@ impl<'a> Parser<'a> {
         modifiers: BoundModifiers,
     ) -> PResult<'a, GenericBound> {
         let lifetime_defs = self.parse_late_bound_lifetime_defs()?;
-        let path = self.parse_path(PathStyle::Type)?;
+        let path = if self.token.is_keyword(kw::Fn)
+            && self.look_ahead(1, |tok| tok.kind == TokenKind::OpenDelim(Delimiter::Parenthesis))
+            && let Some(path) = self.recover_path_from_fn()
+        {
+            path
+        } else {
+            self.parse_path(PathStyle::Type)?
+        };
         if has_parens {
             if self.token.is_like_plus() {
                 // Someone has written something like `&dyn (Trait + Other)`. The correct code
@@ -941,6 +970,38 @@ impl<'a> Parser<'a> {
         Ok(GenericBound::Trait(poly_trait, modifier))
     }
 
+    // recovers a `Fn(..)` parenthesized-style path from `fn(..)`
+    fn recover_path_from_fn(&mut self) -> Option<ast::Path> {
+        let fn_token_span = self.token.span;
+        self.bump();
+        let args_lo = self.token.span;
+        let snapshot = self.create_snapshot_for_diagnostic();
+        match self.parse_fn_decl(|_| false, AllowPlus::No, RecoverReturnSign::OnlyFatArrow) {
+            Ok(decl) => {
+                self.sess.emit_err(ExpectedFnPathFoundFnKeyword { fn_token_span });
+                Some(ast::Path {
+                    span: fn_token_span.to(self.prev_token.span),
+                    segments: thin_vec![ast::PathSegment {
+                        ident: Ident::new(Symbol::intern("Fn"), fn_token_span),
+                        id: DUMMY_NODE_ID,
+                        args: Some(P(ast::GenericArgs::Parenthesized(ast::ParenthesizedArgs {
+                            span: args_lo.to(self.prev_token.span),
+                            inputs: decl.inputs.iter().map(|a| a.ty.clone()).collect(),
+                            inputs_span: args_lo.until(decl.output.span()),
+                            output: decl.output.clone(),
+                        }))),
+                    }],
+                    tokens: None,
+                })
+            }
+            Err(diag) => {
+                diag.cancel();
+                self.restore_snapshot(snapshot);
+                None
+            }
+        }
+    }
+
     /// Optionally parses `for<$generic_params>`.
     pub(super) fn parse_late_bound_lifetime_defs(&mut self) -> PResult<'a, Vec<GenericParam>> {
         if self.eat_keyword(kw::For) {
diff --git a/compiler/rustc_parse_format/src/lib.rs b/compiler/rustc_parse_format/src/lib.rs
index 9cbe04c1288..ab0463045fa 100644
--- a/compiler/rustc_parse_format/src/lib.rs
+++ b/compiler/rustc_parse_format/src/lib.rs
@@ -38,6 +38,24 @@ impl InnerSpan {
     }
 }
 
+/// The location and before/after width of a character whose width has changed from its source code
+/// representation
+#[derive(Copy, Clone, PartialEq, Eq)]
+pub struct InnerWidthMapping {
+    /// Index of the character in the source
+    pub position: usize,
+    /// The inner width in characters
+    pub before: usize,
+    /// The transformed width in characters
+    pub after: usize,
+}
+
+impl InnerWidthMapping {
+    pub fn new(position: usize, before: usize, after: usize) -> InnerWidthMapping {
+        InnerWidthMapping { position, before, after }
+    }
+}
+
 /// The type of format string that we are parsing.
 #[derive(Copy, Clone, Debug, Eq, PartialEq)]
 pub enum ParseMode {
@@ -200,8 +218,8 @@ pub struct Parser<'a> {
     style: Option<usize>,
     /// Start and end byte offset of every successfully parsed argument
     pub arg_places: Vec<InnerSpan>,
-    /// Characters that need to be shifted
-    skips: Vec<usize>,
+    /// Characters whose length has been changed from their in-code representation
+    width_map: Vec<InnerWidthMapping>,
     /// Span of the last opening brace seen, used for error reporting
     last_opening_brace: Option<InnerSpan>,
     /// Whether the source string is comes from `println!` as opposed to `format!` or `print!`
@@ -224,7 +242,7 @@ impl<'a> Iterator for Parser<'a> {
                 '{' => {
                     let curr_last_brace = self.last_opening_brace;
                     let byte_pos = self.to_span_index(pos);
-                    let lbrace_end = self.to_span_index(pos + 1);
+                    let lbrace_end = InnerOffset(byte_pos.0 + self.to_span_width(pos));
                     self.last_opening_brace = Some(byte_pos.to(lbrace_end));
                     self.cur.next();
                     if self.consume('{') {
@@ -233,12 +251,15 @@ impl<'a> Iterator for Parser<'a> {
                         Some(String(self.string(pos + 1)))
                     } else {
                         let arg = self.argument(lbrace_end);
-                        if let Some(rbrace_byte_idx) = self.must_consume('}') {
-                            let lbrace_inner_offset = self.to_span_index(pos);
-                            let rbrace_inner_offset = self.to_span_index(rbrace_byte_idx);
+                        if let Some(rbrace_pos) = self.must_consume('}') {
                             if self.is_literal {
+                                let lbrace_byte_pos = self.to_span_index(pos);
+                                let rbrace_byte_pos = self.to_span_index(rbrace_pos);
+
+                                let width = self.to_span_width(rbrace_pos);
+
                                 self.arg_places.push(
-                                    lbrace_inner_offset.to(InnerOffset(rbrace_inner_offset.0 + 1)),
+                                    lbrace_byte_pos.to(InnerOffset(rbrace_byte_pos.0 + width)),
                                 );
                             }
                         } else {
@@ -285,7 +306,7 @@ impl<'a> Parser<'a> {
         append_newline: bool,
         mode: ParseMode,
     ) -> Parser<'a> {
-        let (skips, is_literal) = find_skips_from_snippet(snippet, style);
+        let (width_map, is_literal) = find_width_map_from_snippet(snippet, style);
         Parser {
             mode,
             input: s,
@@ -294,7 +315,7 @@ impl<'a> Parser<'a> {
             curarg: 0,
             style,
             arg_places: vec![],
-            skips,
+            width_map,
             last_opening_brace: None,
             append_newline,
             is_literal,
@@ -367,21 +388,34 @@ impl<'a> Parser<'a> {
         None
     }
 
+    fn remap_pos(&self, mut pos: usize) -> InnerOffset {
+        for width in &self.width_map {
+            if pos > width.position {
+                pos += width.before - width.after;
+            } else if pos == width.position && width.after == 0 {
+                pos += width.before;
+            } else {
+                break;
+            }
+        }
+
+        InnerOffset(pos)
+    }
+
     fn to_span_index(&self, pos: usize) -> InnerOffset {
-        let mut pos = pos;
         // This handles the raw string case, the raw argument is the number of #
         // in r###"..."### (we need to add one because of the `r`).
         let raw = self.style.map_or(0, |raw| raw + 1);
-        for skip in &self.skips {
-            if pos > *skip {
-                pos += 1;
-            } else if pos == *skip && raw == 0 {
-                pos += 1;
-            } else {
-                break;
-            }
+        let pos = self.remap_pos(pos);
+        InnerOffset(raw + pos.0 + 1)
+    }
+
+    fn to_span_width(&self, pos: usize) -> usize {
+        let pos = self.remap_pos(pos);
+        match self.width_map.iter().find(|w| w.position == pos.0) {
+            Some(w) => w.before,
+            None => 1,
         }
-        InnerOffset(raw + pos + 1)
     }
 
     fn span(&self, start_pos: usize, end_pos: usize) -> InnerSpan {
@@ -809,10 +843,10 @@ impl<'a> Parser<'a> {
 /// Finds the indices of all characters that have been processed and differ between the actual
 /// written code (code snippet) and the `InternedString` that gets processed in the `Parser`
 /// in order to properly synthesise the intra-string `Span`s for error diagnostics.
-fn find_skips_from_snippet(
+fn find_width_map_from_snippet(
     snippet: Option<string::String>,
     str_style: Option<usize>,
-) -> (Vec<usize>, bool) {
+) -> (Vec<InnerWidthMapping>, bool) {
     let snippet = match snippet {
         Some(ref s) if s.starts_with('"') || s.starts_with("r\"") || s.starts_with("r#") => s,
         _ => return (vec![], false),
@@ -825,43 +859,39 @@ fn find_skips_from_snippet(
     let snippet = &snippet[1..snippet.len() - 1];
 
     let mut s = snippet.char_indices();
-    let mut skips = vec![];
+    let mut width_mappings = vec![];
     while let Some((pos, c)) = s.next() {
         match (c, s.clone().next()) {
             // skip whitespace and empty lines ending in '\\'
-            ('\\', Some((next_pos, '\n'))) => {
-                skips.push(pos);
-                skips.push(next_pos);
+            ('\\', Some((_, '\n'))) => {
                 let _ = s.next();
+                let mut width = 2;
 
-                while let Some((pos, c)) = s.clone().next() {
+                while let Some((_, c)) = s.clone().next() {
                     if matches!(c, ' ' | '\n' | '\t') {
-                        skips.push(pos);
+                        width += 1;
                         let _ = s.next();
                     } else {
                         break;
                     }
                 }
+
+                width_mappings.push(InnerWidthMapping::new(pos, width, 0));
             }
-            ('\\', Some((next_pos, 'n' | 't' | 'r' | '0' | '\\' | '\'' | '\"'))) => {
-                skips.push(next_pos);
+            ('\\', Some((_, 'n' | 't' | 'r' | '0' | '\\' | '\'' | '\"'))) => {
+                width_mappings.push(InnerWidthMapping::new(pos, 2, 1));
                 let _ = s.next();
             }
             ('\\', Some((_, 'x'))) => {
-                for _ in 0..3 {
-                    // consume `\xAB` literal
-                    if let Some((pos, _)) = s.next() {
-                        skips.push(pos);
-                    } else {
-                        break;
-                    }
-                }
+                // consume `\xAB` literal
+                s.nth(2);
+                width_mappings.push(InnerWidthMapping::new(pos, 4, 1));
             }
             ('\\', Some((_, 'u'))) => {
-                if let Some((pos, _)) = s.next() {
-                    skips.push(pos);
-                }
-                if let Some((next_pos, next_c)) = s.next() {
+                let mut width = 2;
+                let _ = s.next();
+
+                if let Some((_, next_c)) = s.next() {
                     if next_c == '{' {
                         // consume up to 6 hexanumeric chars
                         let digits_len =
@@ -881,19 +911,18 @@ fn find_skips_from_snippet(
                         let required_skips = digits_len.saturating_sub(len_utf8.saturating_sub(1));
 
                         // skip '{' and '}' also
-                        for pos in (next_pos..).take(required_skips + 2) {
-                            skips.push(pos)
-                        }
+                        width += required_skips + 2;
 
                         s.nth(digits_len);
                     } else if next_c.is_digit(16) {
-                        skips.push(next_pos);
+                        width += 1;
+
                         // We suggest adding `{` and `}` when appropriate, accept it here as if
                         // it were correct
                         let mut i = 0; // consume up to 6 hexanumeric chars
-                        while let (Some((next_pos, c)), _) = (s.next(), i < 6) {
+                        while let (Some((_, c)), _) = (s.next(), i < 6) {
                             if c.is_digit(16) {
-                                skips.push(next_pos);
+                                width += 1;
                             } else {
                                 break;
                             }
@@ -901,11 +930,13 @@ fn find_skips_from_snippet(
                         }
                     }
                 }
+
+                width_mappings.push(InnerWidthMapping::new(pos, width, 1));
             }
             _ => {}
         }
     }
-    (skips, true)
+    (width_mappings, true)
 }
 
 // Assert a reasonable size for `Piece`
diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs
index 2e2874dbccb..c59c06ac31e 100644
--- a/compiler/rustc_passes/src/check_attr.rs
+++ b/compiler/rustc_passes/src/check_attr.rs
@@ -1090,9 +1090,7 @@ impl CheckAttrVisitor<'_> {
                                     errors::DocTestUnknownInclude {
                                         path,
                                         value: value.to_string(),
-                                        inner: (attr.style == AttrStyle::Inner)
-                                            .then_some("!")
-                                            .unwrap_or(""),
+                                        inner: if attr.style == AttrStyle::Inner { "!" } else { "" },
                                         sugg: (attr.meta().unwrap().span, applicability),
                                     }
                                 );
diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs
index f5556738bff..edb0e4367f2 100644
--- a/compiler/rustc_passes/src/dead.rs
+++ b/compiler/rustc_passes/src/dead.rs
@@ -571,7 +571,7 @@ fn check_item<'tcx>(
     }
 }
 
-fn check_trait_item<'tcx>(tcx: TyCtxt<'tcx>, worklist: &mut Vec<LocalDefId>, id: hir::TraitItemId) {
+fn check_trait_item(tcx: TyCtxt<'_>, worklist: &mut Vec<LocalDefId>, id: hir::TraitItemId) {
     use hir::TraitItemKind::{Const, Fn};
     if matches!(tcx.def_kind(id.owner_id), DefKind::AssocConst | DefKind::AssocFn) {
         let trait_item = tcx.hir().trait_item(id);
@@ -583,11 +583,7 @@ fn check_trait_item<'tcx>(tcx: TyCtxt<'tcx>, worklist: &mut Vec<LocalDefId>, id:
     }
 }
 
-fn check_foreign_item<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    worklist: &mut Vec<LocalDefId>,
-    id: hir::ForeignItemId,
-) {
+fn check_foreign_item(tcx: TyCtxt<'_>, worklist: &mut Vec<LocalDefId>, id: hir::ForeignItemId) {
     if matches!(tcx.def_kind(id.owner_id), DefKind::Static(_) | DefKind::Fn)
         && has_allow_dead_code_or_lang_attr(tcx, id.hir_id())
     {
@@ -595,8 +591,8 @@ fn check_foreign_item<'tcx>(
     }
 }
 
-fn create_and_seed_worklist<'tcx>(
-    tcx: TyCtxt<'tcx>,
+fn create_and_seed_worklist(
+    tcx: TyCtxt<'_>,
 ) -> (Vec<LocalDefId>, FxHashMap<LocalDefId, LocalDefId>) {
     let effective_visibilities = &tcx.effective_visibilities(());
     // see `MarkSymbolVisitor::struct_constructors`
@@ -626,8 +622,8 @@ fn create_and_seed_worklist<'tcx>(
     (worklist, struct_constructors)
 }
 
-fn live_symbols_and_ignored_derived_traits<'tcx>(
-    tcx: TyCtxt<'tcx>,
+fn live_symbols_and_ignored_derived_traits(
+    tcx: TyCtxt<'_>,
     (): (),
 ) -> (FxHashSet<LocalDefId>, FxHashMap<LocalDefId, Vec<(DefId, DefId)>>) {
     let (worklist, struct_constructors) = create_and_seed_worklist(tcx);
diff --git a/compiler/rustc_passes/src/debugger_visualizer.rs b/compiler/rustc_passes/src/debugger_visualizer.rs
index 253b0a88e48..aeacbaa67cb 100644
--- a/compiler/rustc_passes/src/debugger_visualizer.rs
+++ b/compiler/rustc_passes/src/debugger_visualizer.rs
@@ -15,8 +15,8 @@ use std::sync::Arc;
 
 use crate::errors::DebugVisualizerUnreadable;
 
-fn check_for_debugger_visualizer<'tcx>(
-    tcx: TyCtxt<'tcx>,
+fn check_for_debugger_visualizer(
+    tcx: TyCtxt<'_>,
     hir_id: HirId,
     debugger_visualizers: &mut FxHashSet<DebuggerVisualizerFile>,
 ) {
@@ -69,7 +69,7 @@ fn check_for_debugger_visualizer<'tcx>(
 }
 
 /// Traverses and collects the debugger visualizers for a specific crate.
-fn debugger_visualizers<'tcx>(tcx: TyCtxt<'tcx>, cnum: CrateNum) -> Vec<DebuggerVisualizerFile> {
+fn debugger_visualizers(tcx: TyCtxt<'_>, cnum: CrateNum) -> Vec<DebuggerVisualizerFile> {
     assert_eq!(cnum, LOCAL_CRATE);
 
     // Initialize the collector.
diff --git a/compiler/rustc_passes/src/diagnostic_items.rs b/compiler/rustc_passes/src/diagnostic_items.rs
index a72056e00b1..10ffa87efe3 100644
--- a/compiler/rustc_passes/src/diagnostic_items.rs
+++ b/compiler/rustc_passes/src/diagnostic_items.rs
@@ -18,11 +18,7 @@ use rustc_span::symbol::{kw::Empty, sym, Symbol};
 
 use crate::errors::{DuplicateDiagnosticItem, DuplicateDiagnosticItemInCrate};
 
-fn observe_item<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    diagnostic_items: &mut DiagnosticItems,
-    def_id: LocalDefId,
-) {
+fn observe_item(tcx: TyCtxt<'_>, diagnostic_items: &mut DiagnosticItems, def_id: LocalDefId) {
     let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
     let attrs = tcx.hir().attrs(hir_id);
     if let Some(name) = extract(attrs) {
@@ -63,7 +59,7 @@ fn extract(attrs: &[ast::Attribute]) -> Option<Symbol> {
 }
 
 /// Traverse and collect the diagnostic items in the current
-fn diagnostic_items<'tcx>(tcx: TyCtxt<'tcx>, cnum: CrateNum) -> DiagnosticItems {
+fn diagnostic_items(tcx: TyCtxt<'_>, cnum: CrateNum) -> DiagnosticItems {
     assert_eq!(cnum, LOCAL_CRATE);
 
     // Initialize the collector.
@@ -92,7 +88,7 @@ fn diagnostic_items<'tcx>(tcx: TyCtxt<'tcx>, cnum: CrateNum) -> DiagnosticItems
 }
 
 /// Traverse and collect all the diagnostic items in all crates.
-fn all_diagnostic_items<'tcx>(tcx: TyCtxt<'tcx>, (): ()) -> DiagnosticItems {
+fn all_diagnostic_items(tcx: TyCtxt<'_>, (): ()) -> DiagnosticItems {
     // Initialize the collector.
     let mut items = DiagnosticItems::default();
 
diff --git a/compiler/rustc_passes/src/layout_test.rs b/compiler/rustc_passes/src/layout_test.rs
index 5322baee747..827d86780aa 100644
--- a/compiler/rustc_passes/src/layout_test.rs
+++ b/compiler/rustc_passes/src/layout_test.rs
@@ -26,7 +26,7 @@ pub fn test_layout(tcx: TyCtxt<'_>) {
     }
 }
 
-fn dump_layout_of<'tcx>(tcx: TyCtxt<'tcx>, item_def_id: LocalDefId, attr: &Attribute) {
+fn dump_layout_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId, attr: &Attribute) {
     let tcx = tcx;
     let param_env = tcx.param_env(item_def_id);
     let ty = tcx.type_of(item_def_id);
diff --git a/compiler/rustc_passes/src/reachable.rs b/compiler/rustc_passes/src/reachable.rs
index e7c3c712852..ad095220386 100644
--- a/compiler/rustc_passes/src/reachable.rs
+++ b/compiler/rustc_passes/src/reachable.rs
@@ -347,7 +347,7 @@ fn check_item<'tcx>(
     }
 }
 
-fn has_custom_linkage<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> bool {
+fn has_custom_linkage(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
     // Anything which has custom linkage gets thrown on the worklist no
     // matter where it is in the crate, along with "special std symbols"
     // which are currently akin to allocator symbols.
@@ -364,7 +364,7 @@ fn has_custom_linkage<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> bool {
         || codegen_attrs.flags.contains(CodegenFnAttrFlags::USED_LINKER)
 }
 
-fn reachable_set<'tcx>(tcx: TyCtxt<'tcx>, (): ()) -> FxHashSet<LocalDefId> {
+fn reachable_set(tcx: TyCtxt<'_>, (): ()) -> FxHashSet<LocalDefId> {
     let effective_visibilities = &tcx.effective_visibilities(());
 
     let any_library =
diff --git a/compiler/rustc_passes/src/stability.rs b/compiler/rustc_passes/src/stability.rs
index da715523474..96f7236de5c 100644
--- a/compiler/rustc_passes/src/stability.rs
+++ b/compiler/rustc_passes/src/stability.rs
@@ -853,7 +853,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'tcx> {
 /// Check whether a path is a `use` item that has been marked as unstable.
 ///
 /// See issue #94972 for details on why this is a special case
-fn is_unstable_reexport<'tcx>(tcx: TyCtxt<'tcx>, id: hir::HirId) -> bool {
+fn is_unstable_reexport(tcx: TyCtxt<'_>, id: hir::HirId) -> bool {
     // Get the LocalDefId so we can lookup the item to check the kind.
     let Some(def_id) = tcx.hir().opt_local_def_id(id) else { return false; };
 
diff --git a/compiler/rustc_passes/src/weak_lang_items.rs b/compiler/rustc_passes/src/weak_lang_items.rs
index f0815fcd8db..fc6372cf99e 100644
--- a/compiler/rustc_passes/src/weak_lang_items.rs
+++ b/compiler/rustc_passes/src/weak_lang_items.rs
@@ -11,7 +11,7 @@ use crate::errors::{MissingLangItem, MissingPanicHandler, UnknownExternLangItem}
 
 /// Checks the crate for usage of weak lang items, returning a vector of all the
 /// language items required by this crate, but not defined yet.
-pub fn check_crate<'tcx>(tcx: TyCtxt<'tcx>, items: &mut lang_items::LanguageItems) {
+pub fn check_crate(tcx: TyCtxt<'_>, items: &mut lang_items::LanguageItems) {
     // These are never called by user code, they're generated by the compiler.
     // They will never implicitly be added to the `missing` array unless we do
     // so here.
@@ -40,7 +40,7 @@ pub fn check_crate<'tcx>(tcx: TyCtxt<'tcx>, items: &mut lang_items::LanguageItem
     verify(tcx, items);
 }
 
-fn verify<'tcx>(tcx: TyCtxt<'tcx>, items: &lang_items::LanguageItems) {
+fn verify(tcx: TyCtxt<'_>, items: &lang_items::LanguageItems) {
     // We only need to check for the presence of weak lang items if we're
     // emitting something that's not an rlib.
     let needs_check = tcx.sess.crate_types().iter().any(|kind| match *kind {
diff --git a/compiler/rustc_query_impl/src/on_disk_cache.rs b/compiler/rustc_query_impl/src/on_disk_cache.rs
index c4e605c1852..2bcfdab03c8 100644
--- a/compiler/rustc_query_impl/src/on_disk_cache.rs
+++ b/compiler/rustc_query_impl/src/on_disk_cache.rs
@@ -227,7 +227,7 @@ impl<'sess> rustc_middle::ty::OnDiskCache<'sess> for OnDiskCache<'sess> {
         *self.serialized_data.write() = None;
     }
 
-    fn serialize<'tcx>(&self, tcx: TyCtxt<'tcx>, encoder: FileEncoder) -> FileEncodeResult {
+    fn serialize(&self, tcx: TyCtxt<'_>, encoder: FileEncoder) -> FileEncodeResult {
         // Serializing the `DepGraph` should not modify it.
         tcx.dep_graph.with_ignore(|| {
             // Allocate `SourceFileIndex`es.
diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs
index 8d5d84c5db4..9ffcc5672cc 100644
--- a/compiler/rustc_query_impl/src/plumbing.rs
+++ b/compiler/rustc_query_impl/src/plumbing.rs
@@ -66,7 +66,7 @@ impl QueryContext for QueryCtxt<'_> {
         tls::with_related_context(**self, |icx| icx.query)
     }
 
-    fn try_collect_active_jobs(&self) -> Option<QueryMap> {
+    fn try_collect_active_jobs(&self) -> Option<QueryMap<DepKind>> {
         self.queries.try_collect_active_jobs(**self)
     }
 
@@ -195,7 +195,7 @@ impl<'tcx> QueryCtxt<'tcx> {
 
 #[derive(Clone, Copy)]
 pub(crate) struct QueryStruct<'tcx> {
-    pub try_collect_active_jobs: fn(QueryCtxt<'tcx>, &mut QueryMap) -> Option<()>,
+    pub try_collect_active_jobs: fn(QueryCtxt<'tcx>, &mut QueryMap<DepKind>) -> Option<()>,
     pub alloc_self_profile_query_strings: fn(TyCtxt<'tcx>, &mut QueryKeyStringCache),
     pub encode_query_results:
         Option<fn(QueryCtxt<'tcx>, &mut CacheEncoder<'_, 'tcx>, &mut EncodedDepNodeIndex)>,
@@ -313,7 +313,7 @@ pub(crate) fn create_query_frame<
     key: K,
     kind: DepKind,
     name: &'static str,
-) -> QueryStackFrame {
+) -> QueryStackFrame<DepKind> {
     // Disable visible paths printing for performance reasons.
     // Showing visible path instead of any path is not that important in production.
     let description = ty::print::with_no_visible_paths!(
@@ -346,7 +346,7 @@ pub(crate) fn create_query_frame<
     };
     let ty_adt_id = key.ty_adt_id();
 
-    QueryStackFrame::new(name, description, span, def_id, def_kind, ty_adt_id, hash)
+    QueryStackFrame::new(description, span, def_id, def_kind, kind, ty_adt_id, hash)
 }
 
 fn try_load_from_on_disk_cache<'tcx, Q>(tcx: TyCtxt<'tcx>, dep_node: DepNode)
@@ -378,7 +378,7 @@ fn force_from_dep_node<'tcx, Q>(tcx: TyCtxt<'tcx>, dep_node: DepNode) -> bool
 where
     Q: QueryConfig<QueryCtxt<'tcx>>,
     Q::Key: DepNodeParams<TyCtxt<'tcx>>,
-    Q::Value: Value<TyCtxt<'tcx>>,
+    Q::Value: Value<TyCtxt<'tcx>, DepKind>,
 {
     // We must avoid ever having to call `force_from_dep_node()` for a
     // `DepNode::codegen_unit`:
@@ -402,7 +402,7 @@ where
         #[cfg(debug_assertions)]
         let _guard = tracing::span!(tracing::Level::TRACE, stringify!($name), ?key).entered();
         let tcx = QueryCtxt::from_tcx(tcx);
-        force_query::<Q, _>(tcx, key, dep_node);
+        force_query::<Q, _, DepKind>(tcx, key, dep_node);
         true
     } else {
         false
@@ -480,7 +480,7 @@ macro_rules! define_queries {
             type Cache = query_storage::$name<'tcx>;
 
             #[inline(always)]
-            fn query_state<'a>(tcx: QueryCtxt<'tcx>) -> &'a QueryState<Self::Key>
+            fn query_state<'a>(tcx: QueryCtxt<'tcx>) -> &'a QueryState<Self::Key, crate::dep_graph::DepKind>
                 where QueryCtxt<'tcx>: 'a
             {
                 &tcx.queries.$name
@@ -587,9 +587,10 @@ macro_rules! define_queries {
             use $crate::plumbing::{QueryStruct, QueryCtxt};
             use $crate::profiling_support::QueryKeyStringCache;
             use rustc_query_system::query::QueryMap;
+            use rustc_middle::dep_graph::DepKind;
 
             pub(super) const fn dummy_query_struct<'tcx>() -> QueryStruct<'tcx> {
-                fn noop_try_collect_active_jobs(_: QueryCtxt<'_>, _: &mut QueryMap) -> Option<()> {
+                fn noop_try_collect_active_jobs(_: QueryCtxt<'_>, _: &mut QueryMap<DepKind>) -> Option<()> {
                     None
                 }
                 fn noop_alloc_self_profile_query_strings(_: TyCtxt<'_>, _: &mut QueryKeyStringCache) {}
@@ -675,7 +676,8 @@ macro_rules! define_queries_struct {
             $(
                 $(#[$attr])*
                 $name: QueryState<
-                    <queries::$name<'tcx> as QueryConfig<QueryCtxt<'tcx>>>::Key
+                    <queries::$name<'tcx> as QueryConfig<QueryCtxt<'tcx>>>::Key,
+                    rustc_middle::dep_graph::DepKind,
                 >,
             )*
         }
@@ -684,7 +686,7 @@ macro_rules! define_queries_struct {
             pub(crate) fn try_collect_active_jobs(
                 &'tcx self,
                 tcx: TyCtxt<'tcx>,
-            ) -> Option<QueryMap> {
+            ) -> Option<QueryMap<rustc_middle::dep_graph::DepKind>> {
                 let tcx = QueryCtxt { tcx, queries: self };
                 let mut jobs = QueryMap::default();
 
@@ -718,7 +720,7 @@ macro_rules! define_queries_struct {
                 mode: QueryMode,
             ) -> Option<query_stored::$name<'tcx>> {
                 let qcx = QueryCtxt { tcx, queries: self };
-                get_query::<queries::$name<'tcx>, _>(qcx, span, key, mode)
+                get_query::<queries::$name<'tcx>, _, rustc_middle::dep_graph::DepKind>(qcx, span, key, mode)
             })*
         }
     };
diff --git a/compiler/rustc_query_impl/src/profiling_support.rs b/compiler/rustc_query_impl/src/profiling_support.rs
index 81114f2cd82..5f54bab9c31 100644
--- a/compiler/rustc_query_impl/src/profiling_support.rs
+++ b/compiler/rustc_query_impl/src/profiling_support.rs
@@ -278,7 +278,7 @@ pub(crate) fn alloc_self_profile_query_strings_for_query_cache<'tcx, C>(
 /// If we are recording only summary data, the ids will point to
 /// just the query names. If we are recording query keys too, we
 /// allocate the corresponding strings here.
-pub fn alloc_self_profile_query_strings<'tcx>(tcx: TyCtxt<'tcx>) {
+pub fn alloc_self_profile_query_strings(tcx: TyCtxt<'_>) {
     if !tcx.prof.enabled() {
         return;
     }
diff --git a/compiler/rustc_query_system/src/query/config.rs b/compiler/rustc_query_system/src/query/config.rs
index 7d1b62ab102..24c960765df 100644
--- a/compiler/rustc_query_system/src/query/config.rs
+++ b/compiler/rustc_query_system/src/query/config.rs
@@ -21,7 +21,7 @@ pub trait QueryConfig<Qcx: QueryContext> {
     type Cache: QueryCache<Key = Self::Key, Stored = Self::Stored, Value = Self::Value>;
 
     // Don't use this method to access query results, instead use the methods on TyCtxt
-    fn query_state<'a>(tcx: Qcx) -> &'a QueryState<Self::Key>
+    fn query_state<'a>(tcx: Qcx) -> &'a QueryState<Self::Key, Qcx::DepKind>
     where
         Qcx: 'a;
 
diff --git a/compiler/rustc_query_system/src/query/job.rs b/compiler/rustc_query_system/src/query/job.rs
index 701bbde6ad2..a5a2f0093ce 100644
--- a/compiler/rustc_query_system/src/query/job.rs
+++ b/compiler/rustc_query_system/src/query/job.rs
@@ -1,6 +1,8 @@
+use crate::dep_graph::DepKind;
 use crate::error::CycleStack;
 use crate::query::plumbing::CycleError;
 use crate::query::{QueryContext, QueryStackFrame};
+use core::marker::PhantomData;
 
 use rustc_data_structures::fx::FxHashMap;
 use rustc_errors::{
@@ -28,48 +30,48 @@ use {
 
 /// Represents a span and a query key.
 #[derive(Clone, Debug)]
-pub struct QueryInfo {
+pub struct QueryInfo<D: DepKind> {
     /// The span corresponding to the reason for which this query was required.
     pub span: Span,
-    pub query: QueryStackFrame,
+    pub query: QueryStackFrame<D>,
 }
 
-pub type QueryMap = FxHashMap<QueryJobId, QueryJobInfo>;
+pub type QueryMap<D> = FxHashMap<QueryJobId, QueryJobInfo<D>>;
 
 /// A value uniquely identifying an active query job.
 #[derive(Copy, Clone, Eq, PartialEq, Hash)]
 pub struct QueryJobId(pub NonZeroU64);
 
 impl QueryJobId {
-    fn query(self, map: &QueryMap) -> QueryStackFrame {
+    fn query<D: DepKind>(self, map: &QueryMap<D>) -> QueryStackFrame<D> {
         map.get(&self).unwrap().query.clone()
     }
 
     #[cfg(parallel_compiler)]
-    fn span(self, map: &QueryMap) -> Span {
+    fn span<D: DepKind>(self, map: &QueryMap<D>) -> Span {
         map.get(&self).unwrap().job.span
     }
 
     #[cfg(parallel_compiler)]
-    fn parent(self, map: &QueryMap) -> Option<QueryJobId> {
+    fn parent<D: DepKind>(self, map: &QueryMap<D>) -> Option<QueryJobId> {
         map.get(&self).unwrap().job.parent
     }
 
     #[cfg(parallel_compiler)]
-    fn latch<'a>(self, map: &'a QueryMap) -> Option<&'a QueryLatch> {
+    fn latch<D: DepKind>(self, map: &QueryMap<D>) -> Option<&QueryLatch<D>> {
         map.get(&self).unwrap().job.latch.as_ref()
     }
 }
 
 #[derive(Clone)]
-pub struct QueryJobInfo {
-    pub query: QueryStackFrame,
-    pub job: QueryJob,
+pub struct QueryJobInfo<D: DepKind> {
+    pub query: QueryStackFrame<D>,
+    pub job: QueryJob<D>,
 }
 
 /// Represents an active query job.
 #[derive(Clone)]
-pub struct QueryJob {
+pub struct QueryJob<D: DepKind> {
     pub id: QueryJobId,
 
     /// The span corresponding to the reason for which this query was required.
@@ -80,10 +82,11 @@ pub struct QueryJob {
 
     /// The latch that is used to wait on this job.
     #[cfg(parallel_compiler)]
-    latch: Option<QueryLatch>,
+    latch: Option<QueryLatch<D>>,
+    spooky: core::marker::PhantomData<D>,
 }
 
-impl QueryJob {
+impl<D: DepKind> QueryJob<D> {
     /// Creates a new query job.
     #[inline]
     pub fn new(id: QueryJobId, span: Span, parent: Option<QueryJobId>) -> Self {
@@ -93,11 +96,12 @@ impl QueryJob {
             parent,
             #[cfg(parallel_compiler)]
             latch: None,
+            spooky: PhantomData,
         }
     }
 
     #[cfg(parallel_compiler)]
-    pub(super) fn latch(&mut self) -> QueryLatch {
+    pub(super) fn latch(&mut self) -> QueryLatch<D> {
         if self.latch.is_none() {
             self.latch = Some(QueryLatch::new());
         }
@@ -123,12 +127,12 @@ impl QueryJobId {
     #[cold]
     #[inline(never)]
     #[cfg(not(parallel_compiler))]
-    pub(super) fn find_cycle_in_stack(
+    pub(super) fn find_cycle_in_stack<D: DepKind>(
         &self,
-        query_map: QueryMap,
+        query_map: QueryMap<D>,
         current_job: &Option<QueryJobId>,
         span: Span,
-    ) -> CycleError {
+    ) -> CycleError<D> {
         // Find the waitee amongst `current_job` parents
         let mut cycle = Vec::new();
         let mut current_job = Option::clone(current_job);
@@ -162,14 +166,18 @@ impl QueryJobId {
 
     #[cold]
     #[inline(never)]
-    pub fn try_find_layout_root(&self, query_map: QueryMap) -> Option<(QueryJobInfo, usize)> {
+    pub fn try_find_layout_root<D: DepKind>(
+        &self,
+        query_map: QueryMap<D>,
+    ) -> Option<(QueryJobInfo<D>, usize)> {
         let mut last_layout = None;
         let mut current_id = Some(*self);
         let mut depth = 0;
 
         while let Some(id) = current_id {
             let info = query_map.get(&id).unwrap();
-            if info.query.name == "layout_of" {
+            // FIXME: This string comparison should probably not be done.
+            if format!("{:?}", info.query.dep_kind) == "layout_of" {
                 depth += 1;
                 last_layout = Some((info.clone(), depth));
             }
@@ -180,15 +188,15 @@ impl QueryJobId {
 }
 
 #[cfg(parallel_compiler)]
-struct QueryWaiter {
+struct QueryWaiter<D: DepKind> {
     query: Option<QueryJobId>,
     condvar: Condvar,
     span: Span,
-    cycle: Lock<Option<CycleError>>,
+    cycle: Lock<Option<CycleError<D>>>,
 }
 
 #[cfg(parallel_compiler)]
-impl QueryWaiter {
+impl<D: DepKind> QueryWaiter<D> {
     fn notify(&self, registry: &rayon_core::Registry) {
         rayon_core::mark_unblocked(registry);
         self.condvar.notify_one();
@@ -196,19 +204,19 @@ impl QueryWaiter {
 }
 
 #[cfg(parallel_compiler)]
-struct QueryLatchInfo {
+struct QueryLatchInfo<D: DepKind> {
     complete: bool,
-    waiters: Vec<Lrc<QueryWaiter>>,
+    waiters: Vec<Lrc<QueryWaiter<D>>>,
 }
 
 #[cfg(parallel_compiler)]
 #[derive(Clone)]
-pub(super) struct QueryLatch {
-    info: Lrc<Mutex<QueryLatchInfo>>,
+pub(super) struct QueryLatch<D: DepKind> {
+    info: Lrc<Mutex<QueryLatchInfo<D>>>,
 }
 
 #[cfg(parallel_compiler)]
-impl QueryLatch {
+impl<D: DepKind> QueryLatch<D> {
     fn new() -> Self {
         QueryLatch {
             info: Lrc::new(Mutex::new(QueryLatchInfo { complete: false, waiters: Vec::new() })),
@@ -216,7 +224,11 @@ impl QueryLatch {
     }
 
     /// Awaits for the query job to complete.
-    pub(super) fn wait_on(&self, query: Option<QueryJobId>, span: Span) -> Result<(), CycleError> {
+    pub(super) fn wait_on(
+        &self,
+        query: Option<QueryJobId>,
+        span: Span,
+    ) -> Result<(), CycleError<D>> {
         let waiter =
             Lrc::new(QueryWaiter { query, span, cycle: Lock::new(None), condvar: Condvar::new() });
         self.wait_on_inner(&waiter);
@@ -231,7 +243,7 @@ impl QueryLatch {
     }
 
     /// Awaits the caller on this latch by blocking the current thread.
-    fn wait_on_inner(&self, waiter: &Lrc<QueryWaiter>) {
+    fn wait_on_inner(&self, waiter: &Lrc<QueryWaiter<D>>) {
         let mut info = self.info.lock();
         if !info.complete {
             // We push the waiter on to the `waiters` list. It can be accessed inside
@@ -265,7 +277,7 @@ impl QueryLatch {
 
     /// Removes a single waiter from the list of waiters.
     /// This is used to break query cycles.
-    fn extract_waiter(&self, waiter: usize) -> Lrc<QueryWaiter> {
+    fn extract_waiter(&self, waiter: usize) -> Lrc<QueryWaiter<D>> {
         let mut info = self.info.lock();
         debug_assert!(!info.complete);
         // Remove the waiter from the list of waiters
@@ -287,9 +299,14 @@ type Waiter = (QueryJobId, usize);
 /// required information to resume the waiter.
 /// If all `visit` calls returns None, this function also returns None.
 #[cfg(parallel_compiler)]
-fn visit_waiters<F>(query_map: &QueryMap, query: QueryJobId, mut visit: F) -> Option<Option<Waiter>>
+fn visit_waiters<F, D>(
+    query_map: &QueryMap<D>,
+    query: QueryJobId,
+    mut visit: F,
+) -> Option<Option<Waiter>>
 where
     F: FnMut(Span, QueryJobId) -> Option<Option<Waiter>>,
+    D: DepKind,
 {
     // Visit the parent query which is a non-resumable waiter since it's on the same stack
     if let Some(parent) = query.parent(query_map) {
@@ -318,8 +335,8 @@ where
 /// If a cycle is detected, this initial value is replaced with the span causing
 /// the cycle.
 #[cfg(parallel_compiler)]
-fn cycle_check(
-    query_map: &QueryMap,
+fn cycle_check<D: DepKind>(
+    query_map: &QueryMap<D>,
     query: QueryJobId,
     span: Span,
     stack: &mut Vec<(Span, QueryJobId)>,
@@ -359,8 +376,8 @@ fn cycle_check(
 /// from `query` without going through any of the queries in `visited`.
 /// This is achieved with a depth first search.
 #[cfg(parallel_compiler)]
-fn connected_to_root(
-    query_map: &QueryMap,
+fn connected_to_root<D: DepKind>(
+    query_map: &QueryMap<D>,
     query: QueryJobId,
     visited: &mut FxHashSet<QueryJobId>,
 ) -> bool {
@@ -382,9 +399,10 @@ fn connected_to_root(
 
 // Deterministically pick an query from a list
 #[cfg(parallel_compiler)]
-fn pick_query<'a, T, F>(query_map: &QueryMap, queries: &'a [T], f: F) -> &'a T
+fn pick_query<'a, T, F, D>(query_map: &QueryMap<D>, queries: &'a [T], f: F) -> &'a T
 where
     F: Fn(&T) -> (Span, QueryJobId),
+    D: DepKind,
 {
     // Deterministically pick an entry point
     // FIXME: Sort this instead
@@ -408,10 +426,10 @@ where
 /// If a cycle was not found, the starting query is removed from `jobs` and
 /// the function returns false.
 #[cfg(parallel_compiler)]
-fn remove_cycle(
-    query_map: &QueryMap,
+fn remove_cycle<D: DepKind>(
+    query_map: &QueryMap<D>,
     jobs: &mut Vec<QueryJobId>,
-    wakelist: &mut Vec<Lrc<QueryWaiter>>,
+    wakelist: &mut Vec<Lrc<QueryWaiter<D>>>,
 ) -> bool {
     let mut visited = FxHashSet::default();
     let mut stack = Vec::new();
@@ -513,7 +531,7 @@ fn remove_cycle(
 /// There may be multiple cycles involved in a deadlock, so this searches
 /// all active queries for cycles before finally resuming all the waiters at once.
 #[cfg(parallel_compiler)]
-pub fn deadlock(query_map: QueryMap, registry: &rayon_core::Registry) {
+pub fn deadlock<D: DepKind>(query_map: QueryMap<D>, registry: &rayon_core::Registry) {
     let on_panic = OnDrop(|| {
         eprintln!("deadlock handler panicked, aborting process");
         process::abort();
@@ -549,9 +567,9 @@ pub fn deadlock(query_map: QueryMap, registry: &rayon_core::Registry) {
 
 #[inline(never)]
 #[cold]
-pub(crate) fn report_cycle<'a>(
+pub(crate) fn report_cycle<'a, D: DepKind>(
     sess: &'a Session,
-    CycleError { usage, cycle: stack }: &CycleError,
+    CycleError { usage, cycle: stack }: &CycleError<D>,
 ) -> DiagnosticBuilder<'a, ErrorGuaranteed> {
     assert!(!stack.is_empty());
 
@@ -617,7 +635,7 @@ pub fn print_query_stack<Qcx: QueryContext>(
         };
         let mut diag = Diagnostic::new(
             Level::FailureNote,
-            &format!("#{} [{}] {}", i, query_info.query.name, query_info.query.description),
+            &format!("#{} [{:?}] {}", i, query_info.query.dep_kind, query_info.query.description),
         );
         diag.span = query_info.job.span.into();
         handler.force_print_diagnostic(diag);
diff --git a/compiler/rustc_query_system/src/query/mod.rs b/compiler/rustc_query_system/src/query/mod.rs
index 7f3dc50d234..ce9179ea832 100644
--- a/compiler/rustc_query_system/src/query/mod.rs
+++ b/compiler/rustc_query_system/src/query/mod.rs
@@ -14,6 +14,7 @@ pub use self::caches::{
 mod config;
 pub use self::config::{QueryConfig, QueryVTable};
 
+use crate::dep_graph::DepKind;
 use crate::dep_graph::{DepNodeIndex, HasDepContext, SerializedDepNodeIndex};
 use rustc_data_structures::sync::Lock;
 use rustc_errors::Diagnostic;
@@ -26,37 +27,37 @@ use thin_vec::ThinVec;
 ///
 /// This is mostly used in case of cycles for error reporting.
 #[derive(Clone, Debug)]
-pub struct QueryStackFrame {
-    pub name: &'static str,
+pub struct QueryStackFrame<D: DepKind> {
     pub description: String,
     span: Option<Span>,
     pub def_id: Option<DefId>,
     pub def_kind: Option<DefKind>,
     pub ty_adt_id: Option<DefId>,
+    pub dep_kind: D,
     /// This hash is used to deterministically pick
     /// a query to remove cycles in the parallel compiler.
     #[cfg(parallel_compiler)]
     hash: u64,
 }
 
-impl QueryStackFrame {
+impl<D: DepKind> QueryStackFrame<D> {
     #[inline]
     pub fn new(
-        name: &'static str,
         description: String,
         span: Option<Span>,
         def_id: Option<DefId>,
         def_kind: Option<DefKind>,
+        dep_kind: D,
         ty_adt_id: Option<DefId>,
         _hash: impl FnOnce() -> u64,
     ) -> Self {
         Self {
-            name,
             description,
             span,
             def_id,
             def_kind,
             ty_adt_id,
+            dep_kind,
             #[cfg(parallel_compiler)]
             hash: _hash(),
         }
@@ -104,7 +105,7 @@ pub trait QueryContext: HasDepContext {
     /// Get the query information from the TLS context.
     fn current_query_job(&self) -> Option<QueryJobId>;
 
-    fn try_collect_active_jobs(&self) -> Option<QueryMap>;
+    fn try_collect_active_jobs(&self) -> Option<QueryMap<Self::DepKind>>;
 
     /// Load side effects associated to the node in the previous session.
     fn load_side_effects(&self, prev_dep_node_index: SerializedDepNodeIndex) -> QuerySideEffects;
diff --git a/compiler/rustc_query_system/src/query/plumbing.rs b/compiler/rustc_query_system/src/query/plumbing.rs
index 848fa67e3df..53844dab9db 100644
--- a/compiler/rustc_query_system/src/query/plumbing.rs
+++ b/compiler/rustc_query_system/src/query/plumbing.rs
@@ -2,7 +2,7 @@
 //! generate the actual methods on tcx which find and execute the provider,
 //! manage the caches, and so forth.
 
-use crate::dep_graph::{DepContext, DepNode, DepNodeIndex, DepNodeParams};
+use crate::dep_graph::{DepContext, DepKind, DepNode, DepNodeIndex, DepNodeParams};
 use crate::ich::StableHashingContext;
 use crate::query::caches::QueryCache;
 use crate::query::config::QueryVTable;
@@ -31,26 +31,27 @@ use thin_vec::ThinVec;
 
 use super::QueryConfig;
 
-pub struct QueryState<K> {
+pub struct QueryState<K, D: DepKind> {
     #[cfg(parallel_compiler)]
-    active: Sharded<FxHashMap<K, QueryResult>>,
+    active: Sharded<FxHashMap<K, QueryResult<D>>>,
     #[cfg(not(parallel_compiler))]
-    active: Lock<FxHashMap<K, QueryResult>>,
+    active: Lock<FxHashMap<K, QueryResult<D>>>,
 }
 
 /// Indicates the state of a query for a given key in a query map.
-enum QueryResult {
+enum QueryResult<D: DepKind> {
     /// An already executing query. The query job can be used to await for its completion.
-    Started(QueryJob),
+    Started(QueryJob<D>),
 
     /// The query panicked. Queries trying to wait on this will raise a fatal error which will
     /// silently panic.
     Poisoned,
 }
 
-impl<K> QueryState<K>
+impl<K, D> QueryState<K, D>
 where
     K: Eq + Hash + Clone + Debug,
+    D: DepKind,
 {
     pub fn all_inactive(&self) -> bool {
         #[cfg(parallel_compiler)]
@@ -67,8 +68,8 @@ where
     pub fn try_collect_active_jobs<Qcx: Copy>(
         &self,
         qcx: Qcx,
-        make_query: fn(Qcx, K) -> QueryStackFrame,
-        jobs: &mut QueryMap,
+        make_query: fn(Qcx, K) -> QueryStackFrame<D>,
+        jobs: &mut QueryMap<D>,
     ) -> Option<()> {
         #[cfg(parallel_compiler)]
         {
@@ -102,34 +103,34 @@ where
     }
 }
 
-impl<K> Default for QueryState<K> {
-    fn default() -> QueryState<K> {
+impl<K, D: DepKind> Default for QueryState<K, D> {
+    fn default() -> QueryState<K, D> {
         QueryState { active: Default::default() }
     }
 }
 
 /// A type representing the responsibility to execute the job in the `job` field.
 /// This will poison the relevant query if dropped.
-struct JobOwner<'tcx, K>
+struct JobOwner<'tcx, K, D: DepKind>
 where
     K: Eq + Hash + Clone,
 {
-    state: &'tcx QueryState<K>,
+    state: &'tcx QueryState<K, D>,
     key: K,
     id: QueryJobId,
 }
 
 #[cold]
 #[inline(never)]
-fn mk_cycle<Qcx, V, R>(
+fn mk_cycle<Qcx, V, R, D: DepKind>(
     qcx: Qcx,
-    cycle_error: CycleError,
+    cycle_error: CycleError<D>,
     handler: HandleCycleError,
     cache: &dyn crate::query::QueryStorage<Value = V, Stored = R>,
 ) -> R
 where
-    Qcx: QueryContext,
-    V: std::fmt::Debug + Value<Qcx::DepContext>,
+    Qcx: QueryContext + crate::query::HasDepContext<DepKind = D>,
+    V: std::fmt::Debug + Value<Qcx::DepContext, Qcx::DepKind>,
     R: Clone,
 {
     let error = report_cycle(qcx.dep_context().sess(), &cycle_error);
@@ -139,13 +140,13 @@ where
 
 fn handle_cycle_error<Tcx, V>(
     tcx: Tcx,
-    cycle_error: &CycleError,
+    cycle_error: &CycleError<Tcx::DepKind>,
     mut error: DiagnosticBuilder<'_, ErrorGuaranteed>,
     handler: HandleCycleError,
 ) -> V
 where
     Tcx: DepContext,
-    V: Value<Tcx>,
+    V: Value<Tcx, Tcx::DepKind>,
 {
     use HandleCycleError::*;
     match handler {
@@ -165,7 +166,7 @@ where
     }
 }
 
-impl<'tcx, K> JobOwner<'tcx, K>
+impl<'tcx, K, D: DepKind> JobOwner<'tcx, K, D>
 where
     K: Eq + Hash + Clone,
 {
@@ -180,12 +181,12 @@ where
     #[inline(always)]
     fn try_start<'b, Qcx>(
         qcx: &'b Qcx,
-        state: &'b QueryState<K>,
+        state: &'b QueryState<K, Qcx::DepKind>,
         span: Span,
         key: K,
-    ) -> TryGetJob<'b, K>
+    ) -> TryGetJob<'b, K, D>
     where
-        Qcx: QueryContext,
+        Qcx: QueryContext + crate::query::HasDepContext<DepKind = D>,
     {
         #[cfg(parallel_compiler)]
         let mut state_lock = state.active.get_shard_by_value(&key).lock();
@@ -280,9 +281,10 @@ where
     }
 }
 
-impl<'tcx, K> Drop for JobOwner<'tcx, K>
+impl<'tcx, K, D> Drop for JobOwner<'tcx, K, D>
 where
     K: Eq + Hash + Clone,
+    D: DepKind,
 {
     #[inline(never)]
     #[cold]
@@ -308,19 +310,20 @@ where
 }
 
 #[derive(Clone)]
-pub(crate) struct CycleError {
+pub(crate) struct CycleError<D: DepKind> {
     /// The query and related span that uses the cycle.
-    pub usage: Option<(Span, QueryStackFrame)>,
-    pub cycle: Vec<QueryInfo>,
+    pub usage: Option<(Span, QueryStackFrame<D>)>,
+    pub cycle: Vec<QueryInfo<D>>,
 }
 
 /// The result of `try_start`.
-enum TryGetJob<'tcx, K>
+enum TryGetJob<'tcx, K, D>
 where
     K: Eq + Hash + Clone,
+    D: DepKind,
 {
     /// The query is not yet started. Contains a guard to the cache eventually used to start it.
-    NotYetStarted(JobOwner<'tcx, K>),
+    NotYetStarted(JobOwner<'tcx, K, D>),
 
     /// The query was already completed.
     /// Returns the result of the query and its dep-node index
@@ -329,7 +332,7 @@ where
     JobCompleted(TimingGuard<'tcx>),
 
     /// Trying to execute the query resulted in a cycle.
-    Cycle(CycleError),
+    Cycle(CycleError<D>),
 }
 
 /// Checks if the query is already computed and in the cache.
@@ -337,9 +340,9 @@ where
 /// which will be used if the query is not in the cache and we need
 /// to compute it.
 #[inline]
-pub fn try_get_cached<'a, Tcx, C, R, OnHit>(
+pub fn try_get_cached<Tcx, C, R, OnHit>(
     tcx: Tcx,
-    cache: &'a C,
+    cache: &C,
     key: &C::Key,
     // `on_hit` can be called while holding a lock to the query cache
     on_hit: OnHit,
@@ -360,7 +363,7 @@ where
 
 fn try_execute_query<Qcx, C>(
     qcx: Qcx,
-    state: &QueryState<C::Key>,
+    state: &QueryState<C::Key, Qcx::DepKind>,
     cache: &C,
     span: Span,
     key: C::Key,
@@ -370,11 +373,11 @@ fn try_execute_query<Qcx, C>(
 where
     C: QueryCache,
     C::Key: Clone + DepNodeParams<Qcx::DepContext>,
-    C::Value: Value<Qcx::DepContext>,
+    C::Value: Value<Qcx::DepContext, Qcx::DepKind>,
     C::Stored: Debug + std::borrow::Borrow<C::Value>,
     Qcx: QueryContext,
 {
-    match JobOwner::<'_, C::Key>::try_start(&qcx, state, span, key.clone()) {
+    match JobOwner::<'_, C::Key, Qcx::DepKind>::try_start(&qcx, state, span, key.clone()) {
         TryGetJob::NotYetStarted(job) => {
             let (result, dep_node_index) = execute_job(qcx, key.clone(), dep_node, query, job.id);
             if query.feedable {
@@ -739,11 +742,12 @@ pub enum QueryMode {
     Ensure,
 }
 
-pub fn get_query<Q, Qcx>(qcx: Qcx, span: Span, key: Q::Key, mode: QueryMode) -> Option<Q::Stored>
+pub fn get_query<Q, Qcx, D>(qcx: Qcx, span: Span, key: Q::Key, mode: QueryMode) -> Option<Q::Stored>
 where
+    D: DepKind,
     Q: QueryConfig<Qcx>,
     Q::Key: DepNodeParams<Qcx::DepContext>,
-    Q::Value: Value<Qcx::DepContext>,
+    Q::Value: Value<Qcx::DepContext, D>,
     Qcx: QueryContext,
 {
     let query = Q::make_vtable(qcx, &key);
@@ -772,11 +776,12 @@ where
     Some(result)
 }
 
-pub fn force_query<Q, Qcx>(qcx: Qcx, key: Q::Key, dep_node: DepNode<Qcx::DepKind>)
+pub fn force_query<Q, Qcx, D>(qcx: Qcx, key: Q::Key, dep_node: DepNode<Qcx::DepKind>)
 where
+    D: DepKind,
     Q: QueryConfig<Qcx>,
     Q::Key: DepNodeParams<Qcx::DepContext>,
-    Q::Value: Value<Qcx::DepContext>,
+    Q::Value: Value<Qcx::DepContext, D>,
     Qcx: QueryContext,
 {
     // We may be concurrently trying both execute and force a query.
diff --git a/compiler/rustc_query_system/src/values.rs b/compiler/rustc_query_system/src/values.rs
index 214656abed4..b6e2cfa3dca 100644
--- a/compiler/rustc_query_system/src/values.rs
+++ b/compiler/rustc_query_system/src/values.rs
@@ -1,12 +1,12 @@
-use crate::dep_graph::DepContext;
+use crate::dep_graph::{DepContext, DepKind};
 use crate::query::QueryInfo;
 
-pub trait Value<Tcx: DepContext>: Sized {
-    fn from_cycle_error(tcx: Tcx, cycle: &[QueryInfo]) -> Self;
+pub trait Value<Tcx: DepContext, D: DepKind>: Sized {
+    fn from_cycle_error(tcx: Tcx, cycle: &[QueryInfo<D>]) -> Self;
 }
 
-impl<Tcx: DepContext, T> Value<Tcx> for T {
-    default fn from_cycle_error(tcx: Tcx, _: &[QueryInfo]) -> T {
+impl<Tcx: DepContext, T, D: DepKind> Value<Tcx, D> for T {
+    default fn from_cycle_error(tcx: Tcx, _: &[QueryInfo<D>]) -> T {
         tcx.sess().abort_if_errors();
         // Ideally we would use `bug!` here. But bug! is only defined in rustc_middle, and it's
         // non-trivial to define it earlier.
diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs
index 5b7a00101e9..49e069f58c9 100644
--- a/compiler/rustc_resolve/src/late.rs
+++ b/compiler/rustc_resolve/src/late.rs
@@ -16,7 +16,7 @@ use rustc_ast::ptr::P;
 use rustc_ast::visit::{self, AssocCtxt, BoundKind, FnCtxt, FnKind, Visitor};
 use rustc_ast::*;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap};
-use rustc_errors::{DiagnosticArgValue, DiagnosticId, IntoDiagnosticArg};
+use rustc_errors::{Applicability, DiagnosticArgValue, DiagnosticId, IntoDiagnosticArg};
 use rustc_hir::def::Namespace::{self, *};
 use rustc_hir::def::{self, CtorKind, DefKind, LifetimeRes, PartialRes, PerNS};
 use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID, LOCAL_CRATE};
@@ -536,6 +536,9 @@ struct DiagnosticMetadata<'ast> {
     in_assignment: Option<&'ast Expr>,
     is_assign_rhs: bool,
 
+    /// Used to detect possible `.` -> `..` typo when calling methods.
+    in_range: Option<(&'ast Expr, &'ast Expr)>,
+
     /// If we are currently in a trait object definition. Used to point at the bounds when
     /// encountering a struct or enum.
     current_trait_object: Option<&'ast [ast::GenericBound]>,
@@ -3320,6 +3323,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
         );
     }
 
+    #[instrument(level = "debug", skip(self))]
     fn smart_resolve_path_fragment(
         &mut self,
         qself: &Option<P<QSelf>>,
@@ -3327,10 +3331,6 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
         source: PathSource<'ast>,
         finalize: Finalize,
     ) -> PartialRes {
-        debug!(
-            "smart_resolve_path_fragment(qself={:?}, path={:?}, finalize={:?})",
-            qself, path, finalize,
-        );
         let ns = source.namespace();
 
         let Finalize { node_id, path_span, .. } = finalize;
@@ -3341,8 +3341,28 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
 
                 let def_id = this.parent_scope.module.nearest_parent_mod();
                 let instead = res.is_some();
-                let suggestion =
-                    if res.is_none() { this.report_missing_type_error(path) } else { None };
+                let suggestion = if let Some((start, end)) = this.diagnostic_metadata.in_range
+                    && path[0].ident.span.lo() == end.span.lo()
+                {
+                    let mut sugg = ".";
+                    let mut span = start.span.between(end.span);
+                    if span.lo() + BytePos(2) == span.hi() {
+                        // There's no space between the start, the range op and the end, suggest
+                        // removal which will look better.
+                        span = span.with_lo(span.lo() + BytePos(1));
+                        sugg = "";
+                    }
+                    Some((
+                        span,
+                        "you might have meant to write `.` instead of `..`",
+                        sugg.to_string(),
+                        Applicability::MaybeIncorrect,
+                    ))
+                } else if res.is_none() {
+                    this.report_missing_type_error(path)
+                } else {
+                    None
+                };
 
                 this.r.use_injections.push(UseError {
                     err,
@@ -4005,6 +4025,12 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
                 self.visit_expr(rhs);
                 self.diagnostic_metadata.is_assign_rhs = false;
             }
+            ExprKind::Range(Some(ref start), Some(ref end), RangeLimits::HalfOpen) => {
+                self.diagnostic_metadata.in_range = Some((start, end));
+                self.resolve_expr(start, Some(expr));
+                self.resolve_expr(end, Some(expr));
+                self.diagnostic_metadata.in_range = None;
+            }
             _ => {
                 visit::walk_expr(self, expr);
             }
diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs
index 4861ee746aa..2182b736937 100644
--- a/compiler/rustc_resolve/src/lib.rs
+++ b/compiler/rustc_resolve/src/lib.rs
@@ -1686,6 +1686,24 @@ impl<'a> Resolver<'a> {
             .or_insert_with(|| self.arenas.alloc_name_resolution())
     }
 
+    /// Test if AmbiguityError ambi is any identical to any one inside ambiguity_errors
+    fn matches_previous_ambiguity_error(&mut self, ambi: &AmbiguityError<'_>) -> bool {
+        for ambiguity_error in &self.ambiguity_errors {
+            // if the span location and ident as well as its span are the same
+            if ambiguity_error.kind == ambi.kind
+                && ambiguity_error.ident == ambi.ident
+                && ambiguity_error.ident.span == ambi.ident.span
+                && ambiguity_error.b1.span == ambi.b1.span
+                && ambiguity_error.b2.span == ambi.b2.span
+                && ambiguity_error.misc1 == ambi.misc1
+                && ambiguity_error.misc2 == ambi.misc2
+            {
+                return true;
+            }
+        }
+        false
+    }
+
     fn record_use(
         &mut self,
         ident: Ident,
@@ -1693,14 +1711,18 @@ impl<'a> Resolver<'a> {
         is_lexical_scope: bool,
     ) {
         if let Some((b2, kind)) = used_binding.ambiguity {
-            self.ambiguity_errors.push(AmbiguityError {
+            let ambiguity_error = AmbiguityError {
                 kind,
                 ident,
                 b1: used_binding,
                 b2,
                 misc1: AmbiguityErrorMisc::None,
                 misc2: AmbiguityErrorMisc::None,
-            });
+            };
+            if !self.matches_previous_ambiguity_error(&ambiguity_error) {
+                // avoid dumplicated span information to be emitt out
+                self.ambiguity_errors.push(ambiguity_error);
+            }
         }
         if let NameBindingKind::Import { import, binding, ref used } = used_binding.kind {
             // Avoid marking `extern crate` items that refer to a name from extern prelude,
diff --git a/compiler/rustc_save_analysis/src/lib.rs b/compiler/rustc_save_analysis/src/lib.rs
index 6c310abf10a..6afd5fe5a7f 100644
--- a/compiler/rustc_save_analysis/src/lib.rs
+++ b/compiler/rustc_save_analysis/src/lib.rs
@@ -957,10 +957,10 @@ impl SaveHandler for CallbackHandler<'_> {
     }
 }
 
-pub fn process_crate<'l, 'tcx, H: SaveHandler>(
-    tcx: TyCtxt<'tcx>,
+pub fn process_crate<H: SaveHandler>(
+    tcx: TyCtxt<'_>,
     cratename: Symbol,
-    input: &'l Input,
+    input: &Input,
     config: Option<Config>,
     mut handler: H,
 ) {
diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs
index 9e130287104..ae01efebacc 100644
--- a/compiler/rustc_session/src/options.rs
+++ b/compiler/rustc_session/src/options.rs
@@ -1214,7 +1214,6 @@ options! {
         "only allow the listed language features to be enabled in code (space separated)"),
     always_encode_mir: bool = (false, parse_bool, [TRACKED],
         "encode MIR of all functions into the crate metadata (default: no)"),
-    #[rustc_lint_opt_deny_field_access("use `Session::asm_comments` instead of this field")]
     asm_comments: bool = (false, parse_bool, [TRACKED],
         "generate comments into the assembly (may change behavior) (default: no)"),
     assert_incr_state: Option<String> = (None, parse_opt_string, [UNTRACKED],
@@ -1363,7 +1362,6 @@ options! {
         `=except-unused-generics`
         `=except-unused-functions`
         `=off` (default)"),
-    #[rustc_lint_opt_deny_field_access("use `Session::instrument_mcount` instead of this field")]
     instrument_mcount: bool = (false, parse_bool, [TRACKED],
         "insert function instrument code for mcount-based tracing (default: no)"),
     keep_hygiene_data: bool = (false, parse_bool, [UNTRACKED],
@@ -1392,7 +1390,6 @@ options! {
     merge_functions: Option<MergeFunctions> = (None, parse_merge_functions, [TRACKED],
         "control the operation of the MergeFunctions LLVM pass, taking \
         the same values as the target option of the same name"),
-    #[rustc_lint_opt_deny_field_access("use `Session::meta_stats` instead of this field")]
     meta_stats: bool = (false, parse_bool, [UNTRACKED],
         "gather metadata statistics (default: no)"),
     mir_emit_retag: bool = (false, parse_bool, [TRACKED],
@@ -1421,6 +1418,8 @@ options! {
         "run all passes except codegen; no output"),
     no_generate_arange_section: bool = (false, parse_no_flag, [TRACKED],
         "omit DWARF address ranges that give faster lookups"),
+    no_jump_tables: bool = (false, parse_no_flag, [TRACKED],
+        "disable the jump tables and lookup tables that can be generated from a switch case lowering"),
     no_leak_check: bool = (false, parse_no_flag, [UNTRACKED],
         "disable the 'leak check' for subtyping; unsound, but useful for tests"),
     no_link: bool = (false, parse_no_flag, [TRACKED],
@@ -1467,7 +1466,6 @@ options! {
         See #77382 and #74551."),
     print_fuel: Option<String> = (None, parse_opt_string, [TRACKED],
         "make rustc print the total optimization fuel used by a crate"),
-    #[rustc_lint_opt_deny_field_access("use `Session::print_llvm_passes` instead of this field")]
     print_llvm_passes: bool = (false, parse_bool, [UNTRACKED],
         "print the LLVM optimization passes being run (default: no)"),
     print_mono_items: Option<String> = (None, parse_opt_string, [UNTRACKED],
@@ -1581,10 +1579,8 @@ options! {
     #[rustc_lint_opt_deny_field_access("use `Session::threads` instead of this field")]
     threads: usize = (1, parse_threads, [UNTRACKED],
         "use a thread pool with N threads"),
-    #[rustc_lint_opt_deny_field_access("use `Session::time_llvm_passes` instead of this field")]
     time_llvm_passes: bool = (false, parse_bool, [UNTRACKED],
         "measure time of each LLVM pass (default: no)"),
-    #[rustc_lint_opt_deny_field_access("use `Session::time_passes` instead of this field")]
     time_passes: bool = (false, parse_bool, [UNTRACKED],
         "measure time of each rustc pass (default: no)"),
     #[rustc_lint_opt_deny_field_access("use `Session::tls_model` instead of this field")]
diff --git a/compiler/rustc_session/src/parse.rs b/compiler/rustc_session/src/parse.rs
index f9f4f2979c4..2aa8ca9e4a9 100644
--- a/compiler/rustc_session/src/parse.rs
+++ b/compiler/rustc_session/src/parse.rs
@@ -122,7 +122,7 @@ pub fn feature_err_issue<'a>(
 /// Construct a future incompatibility diagnostic for a feature gate.
 ///
 /// This diagnostic is only a warning and *does not cause compilation to fail*.
-pub fn feature_warn<'a>(sess: &'a ParseSess, feature: Symbol, span: Span, explain: &str) {
+pub fn feature_warn(sess: &ParseSess, feature: Symbol, span: Span, explain: &str) {
     feature_warn_issue(sess, feature, span, GateIssue::Language, explain);
 }
 
@@ -134,8 +134,8 @@ pub fn feature_warn<'a>(sess: &'a ParseSess, feature: Symbol, span: Span, explai
 /// Almost always, you want to use this for a language feature. If so, prefer `feature_warn`.
 #[allow(rustc::diagnostic_outside_of_impl)]
 #[allow(rustc::untranslatable_diagnostic)]
-pub fn feature_warn_issue<'a>(
-    sess: &'a ParseSess,
+pub fn feature_warn_issue(
+    sess: &ParseSess,
     feature: Symbol,
     span: Span,
     issue: GateIssue,
@@ -160,7 +160,7 @@ pub fn feature_warn_issue<'a>(
 }
 
 /// Adds the diagnostics for a feature to an existing error.
-pub fn add_feature_diagnostics<'a>(err: &mut Diagnostic, sess: &'a ParseSess, feature: Symbol) {
+pub fn add_feature_diagnostics(err: &mut Diagnostic, sess: &ParseSess, feature: Symbol) {
     add_feature_diagnostics_for_issue(err, sess, feature, GateIssue::Language);
 }
 
@@ -169,9 +169,9 @@ pub fn add_feature_diagnostics<'a>(err: &mut Diagnostic, sess: &'a ParseSess, fe
 /// This variant allows you to control whether it is a library or language feature.
 /// Almost always, you want to use this for a language feature. If so, prefer
 /// `add_feature_diagnostics`.
-pub fn add_feature_diagnostics_for_issue<'a>(
+pub fn add_feature_diagnostics_for_issue(
     err: &mut Diagnostic,
-    sess: &'a ParseSess,
+    sess: &ParseSess,
     feature: Symbol,
     issue: GateIssue,
 ) {
diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs
index 01a9b100088..4a3d29414d6 100644
--- a/compiler/rustc_session/src/session.rs
+++ b/compiler/rustc_session/src/session.rs
@@ -976,34 +976,10 @@ impl Session {
         self.opts.unstable_opts.verbose
     }
 
-    pub fn instrument_mcount(&self) -> bool {
-        self.opts.unstable_opts.instrument_mcount
-    }
-
-    pub fn time_passes(&self) -> bool {
-        self.opts.unstable_opts.time_passes
-    }
-
-    pub fn time_llvm_passes(&self) -> bool {
-        self.opts.unstable_opts.time_llvm_passes
-    }
-
-    pub fn meta_stats(&self) -> bool {
-        self.opts.unstable_opts.meta_stats
-    }
-
-    pub fn asm_comments(&self) -> bool {
-        self.opts.unstable_opts.asm_comments
-    }
-
     pub fn verify_llvm_ir(&self) -> bool {
         self.opts.unstable_opts.verify_llvm_ir || option_env!("RUSTC_VERIFY_LLVM_IR").is_some()
     }
 
-    pub fn print_llvm_passes(&self) -> bool {
-        self.opts.unstable_opts.print_llvm_passes
-    }
-
     pub fn binary_dep_depinfo(&self) -> bool {
         self.opts.unstable_opts.binary_dep_depinfo
     }
diff --git a/compiler/rustc_session/src/utils.rs b/compiler/rustc_session/src/utils.rs
index e65b6891e32..b996d36a318 100644
--- a/compiler/rustc_session/src/utils.rs
+++ b/compiler/rustc_session/src/utils.rs
@@ -3,7 +3,7 @@ use rustc_data_structures::profiling::VerboseTimingGuard;
 use std::path::{Path, PathBuf};
 
 impl Session {
-    pub fn timer<'a>(&'a self, what: &'static str) -> VerboseTimingGuard<'a> {
+    pub fn timer(&self, what: &'static str) -> VerboseTimingGuard<'_> {
         self.prof.verbose_generic_activity(what)
     }
     pub fn time<R>(&self, what: &'static str, f: impl FnOnce() -> R) -> R {
diff --git a/compiler/rustc_span/Cargo.toml b/compiler/rustc_span/Cargo.toml
index 48a2ab0f904..5ce2577b63c 100644
--- a/compiler/rustc_span/Cargo.toml
+++ b/compiler/rustc_span/Cargo.toml
@@ -13,7 +13,7 @@ rustc_index = { path = "../rustc_index" }
 rustc_arena = { path = "../rustc_arena" }
 scoped-tls = "1.0"
 unicode-width = "0.1.4"
-cfg-if = "0.1.2"
+cfg-if = "1.0"
 tracing = "0.1"
 sha1 = { package = "sha-1", version = "0.10.0" }
 sha2 = "0.10.1"
diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs
index 2181c090027..bee4b0a2332 100644
--- a/compiler/rustc_span/src/lib.rs
+++ b/compiler/rustc_span/src/lib.rs
@@ -796,6 +796,9 @@ impl Span {
 
     /// Returns a `Span` that would enclose both `self` and `end`.
     ///
+    /// Note that this can also be used to extend the span "backwards":
+    /// `start.to(end)` and `end.to(start)` return the same `Span`.
+    ///
     /// ```text
     ///     ____             ___
     ///     self lorem ipsum end
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index f23959b6e47..c450c4da9a8 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -213,6 +213,7 @@ symbols! {
         Is,
         ItemContext,
         Iterator,
+        IteratorItem,
         Layout,
         Left,
         LinkedList,
@@ -376,9 +377,9 @@ symbols! {
         assert_eq_macro,
         assert_inhabited,
         assert_macro,
+        assert_mem_uninitialized_valid,
         assert_ne_macro,
         assert_receiver_is_total_eq,
-        assert_uninit_valid,
         assert_zero_valid,
         asserting,
         associated_const_equality,
@@ -943,6 +944,7 @@ symbols! {
         mul,
         mul_assign,
         mul_with_overflow,
+        multiple_supertrait_upcastable,
         must_not_suspend,
         must_use,
         naked,
@@ -1041,6 +1043,7 @@ symbols! {
         panic_2021,
         panic_abort,
         panic_bounds_check,
+        panic_cannot_unwind,
         panic_display,
         panic_fmt,
         panic_handler,
@@ -1048,7 +1051,7 @@ symbols! {
         panic_implementation,
         panic_info,
         panic_location,
-        panic_no_unwind,
+        panic_nounwind,
         panic_runtime,
         panic_str,
         panic_unwind,
diff --git a/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs b/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs
index 0845b1b6b09..493e31a688f 100644
--- a/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs
+++ b/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs
@@ -338,7 +338,7 @@ fn encode_substs<'tcx>(
 }
 
 /// Encodes a ty:Ty name, including its crate and path disambiguators and names.
-fn encode_ty_name<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> String {
+fn encode_ty_name(tcx: TyCtxt<'_>, def_id: DefId) -> String {
     // Encode <name> for use in u<length><name>[I<element-type1..element-typeN>E], where
     // <element-type> is <subst>, using v0's <path> without v0's extended form of paths:
     //
diff --git a/compiler/rustc_target/src/abi/call/loongarch.rs b/compiler/rustc_target/src/abi/call/loongarch.rs
index d29b479de5d..4a2d39cc700 100644
--- a/compiler/rustc_target/src/abi/call/loongarch.rs
+++ b/compiler/rustc_target/src/abi/call/loongarch.rs
@@ -19,7 +19,7 @@ enum FloatConv {
 #[derive(Copy, Clone)]
 struct CannotUseFpConv;
 
-fn is_loongarch_aggregate<'a, Ty>(arg: &ArgAbi<'a, Ty>) -> bool {
+fn is_loongarch_aggregate<Ty>(arg: &ArgAbi<'_, Ty>) -> bool {
     match arg.layout.abi {
         Abi::Vector { .. } => true,
         _ => arg.layout.is_aggregate(),
@@ -290,7 +290,7 @@ fn classify_arg<'a, Ty, C>(
     }
 }
 
-fn extend_integer_width<'a, Ty>(arg: &mut ArgAbi<'a, Ty>, xlen: u64) {
+fn extend_integer_width<Ty>(arg: &mut ArgAbi<'_, Ty>, xlen: u64) {
     if let Abi::Scalar(scalar) = arg.layout.abi {
         if let abi::Int(i, _) = scalar.primitive() {
             // 32-bit integers are always sign-extended
diff --git a/compiler/rustc_target/src/abi/call/riscv.rs b/compiler/rustc_target/src/abi/call/riscv.rs
index 1cb360f834e..34280d38e34 100644
--- a/compiler/rustc_target/src/abi/call/riscv.rs
+++ b/compiler/rustc_target/src/abi/call/riscv.rs
@@ -25,7 +25,7 @@ enum FloatConv {
 #[derive(Copy, Clone)]
 struct CannotUseFpConv;
 
-fn is_riscv_aggregate<'a, Ty>(arg: &ArgAbi<'a, Ty>) -> bool {
+fn is_riscv_aggregate<Ty>(arg: &ArgAbi<'_, Ty>) -> bool {
     match arg.layout.abi {
         Abi::Vector { .. } => true,
         _ => arg.layout.is_aggregate(),
@@ -296,7 +296,7 @@ fn classify_arg<'a, Ty, C>(
     }
 }
 
-fn extend_integer_width<'a, Ty>(arg: &mut ArgAbi<'a, Ty>, xlen: u64) {
+fn extend_integer_width<Ty>(arg: &mut ArgAbi<'_, Ty>, xlen: u64) {
     if let Abi::Scalar(scalar) = arg.layout.abi {
         if let abi::Int(i, _) = scalar.primitive() {
             // 32-bit integers are always sign-extended
diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs
index be994eda14c..4512db49403 100644
--- a/compiler/rustc_target/src/spec/mod.rs
+++ b/compiler/rustc_target/src/spec/mod.rs
@@ -1319,7 +1319,7 @@ pub struct Target {
 }
 
 impl Target {
-    pub fn parse_data_layout<'a>(&'a self) -> Result<TargetDataLayout, TargetDataLayoutErrors<'a>> {
+    pub fn parse_data_layout(&self) -> Result<TargetDataLayout, TargetDataLayoutErrors<'_>> {
         let mut dl = TargetDataLayout::parse_from_llvm_datalayout_string(&self.data_layout)?;
 
         // Perform consistency checks against the Target information.
@@ -2291,7 +2291,7 @@ impl Target {
                     } else {
                         return Some(Err(format!(
                             "'{}' is not a valid value for lld-flavor. \
-                             Use 'darwin', 'gnu', 'link' or 'wasm.",
+                             Use 'darwin', 'gnu', 'link' or 'wasm'.",
                             s)))
                     }
                     Some(Ok(()))
diff --git a/compiler/rustc_trait_selection/src/lib.rs b/compiler/rustc_trait_selection/src/lib.rs
index 975ff31a607..a30d1df4ede 100644
--- a/compiler/rustc_trait_selection/src/lib.rs
+++ b/compiler/rustc_trait_selection/src/lib.rs
@@ -19,6 +19,7 @@
 #![feature(let_chains)]
 #![feature(if_let_guard)]
 #![feature(never_type)]
+#![feature(result_option_inspect)]
 #![feature(type_alias_impl_trait)]
 #![recursion_limit = "512"] // For rustdoc
 
@@ -37,4 +38,5 @@ extern crate smallvec;
 pub mod autoderef;
 pub mod errors;
 pub mod infer;
+pub mod solve;
 pub mod traits;
diff --git a/compiler/rustc_trait_selection/src/solve/assembly.rs b/compiler/rustc_trait_selection/src/solve/assembly.rs
new file mode 100644
index 00000000000..e9ddad11ff2
--- /dev/null
+++ b/compiler/rustc_trait_selection/src/solve/assembly.rs
@@ -0,0 +1,150 @@
+//! Code shared by trait and projection goals for candidate assembly.
+
+use super::infcx_ext::InferCtxtExt;
+use super::{
+    fixme_instantiate_canonical_query_response, CanonicalGoal, CanonicalResponse, Certainty,
+    EvalCtxt, Goal,
+};
+use rustc_hir::def_id::DefId;
+use rustc_infer::infer::TyCtxtInferExt;
+use rustc_infer::infer::{
+    canonical::{CanonicalVarValues, OriginalQueryValues},
+    InferCtxt,
+};
+use rustc_infer::traits::query::NoSolution;
+use rustc_middle::ty::TypeFoldable;
+use rustc_middle::ty::{self, Ty, TyCtxt};
+use rustc_span::DUMMY_SP;
+use std::fmt::Debug;
+
+/// A candidate is a possible way to prove a goal.
+///
+/// It consists of both the `source`, which describes how that goal would be proven,
+/// and the `result` when using the given `source`.
+///
+/// For the list of possible candidates, please look at the documentation of
+/// [super::trait_goals::CandidateSource] and [super::project_goals::CandidateSource].
+#[derive(Debug, Clone)]
+pub(super) struct Candidate<'tcx, G: GoalKind<'tcx>> {
+    pub(super) source: G::CandidateSource,
+    pub(super) result: CanonicalResponse<'tcx>,
+}
+
+pub(super) trait GoalKind<'tcx>: TypeFoldable<'tcx> + Copy {
+    type CandidateSource: Debug + Copy;
+
+    fn self_ty(self) -> Ty<'tcx>;
+
+    fn with_self_ty(self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> Self;
+
+    fn trait_def_id(self, tcx: TyCtxt<'tcx>) -> DefId;
+
+    fn consider_impl_candidate(
+        acx: &mut AssemblyCtxt<'_, 'tcx, Self>,
+        goal: Goal<'tcx, Self>,
+        impl_def_id: DefId,
+    );
+}
+
+/// An abstraction which correctly deals with the canonical results for candidates.
+///
+/// It also deduplicates the behavior between trait and projection predicates.
+pub(super) struct AssemblyCtxt<'a, 'tcx, G: GoalKind<'tcx>> {
+    pub(super) cx: &'a mut EvalCtxt<'tcx>,
+    pub(super) infcx: &'a InferCtxt<'tcx>,
+    var_values: CanonicalVarValues<'tcx>,
+    candidates: Vec<Candidate<'tcx, G>>,
+}
+
+impl<'a, 'tcx, G: GoalKind<'tcx>> AssemblyCtxt<'a, 'tcx, G> {
+    pub(super) fn assemble_and_evaluate_candidates(
+        cx: &'a mut EvalCtxt<'tcx>,
+        goal: CanonicalGoal<'tcx, G>,
+    ) -> Vec<Candidate<'tcx, G>> {
+        let (ref infcx, goal, var_values) =
+            cx.tcx.infer_ctxt().build_with_canonical(DUMMY_SP, &goal);
+        let mut acx = AssemblyCtxt { cx, infcx, var_values, candidates: Vec::new() };
+
+        acx.assemble_candidates_after_normalizing_self_ty(goal);
+
+        acx.assemble_impl_candidates(goal);
+
+        acx.candidates
+    }
+
+    pub(super) fn try_insert_candidate(
+        &mut self,
+        source: G::CandidateSource,
+        certainty: Certainty,
+    ) {
+        match self.infcx.make_canonical_response(self.var_values.clone(), certainty) {
+            Ok(result) => self.candidates.push(Candidate { source, result }),
+            Err(NoSolution) => debug!(?source, ?certainty, "failed leakcheck"),
+        }
+    }
+
+    /// If the self type of a goal is a projection, computing the relevant candidates is difficult.
+    ///
+    /// To deal with this, we first try to normalize the self type and add the candidates for the normalized
+    /// self type to the list of candidates in case that succeeds. Note that we can't just eagerly return in
+    /// this case as projections as self types add `
+    fn assemble_candidates_after_normalizing_self_ty(&mut self, goal: Goal<'tcx, G>) {
+        let tcx = self.cx.tcx;
+        // FIXME: We also have to normalize opaque types, not sure where to best fit that in.
+        let &ty::Alias(ty::Projection, projection_ty) = goal.predicate.self_ty().kind() else {
+            return
+        };
+        self.infcx.probe(|_| {
+            let normalized_ty = self.infcx.next_ty_infer();
+            let normalizes_to_goal = goal.with(
+                tcx,
+                ty::Binder::dummy(ty::ProjectionPredicate {
+                    projection_ty,
+                    term: normalized_ty.into(),
+                }),
+            );
+            let normalization_certainty =
+                match self.cx.evaluate_goal(&self.infcx, normalizes_to_goal) {
+                    Ok((_, certainty)) => certainty,
+                    Err(NoSolution) => return,
+                };
+
+            // NOTE: Alternatively we could call `evaluate_goal` here and only have a `Normalized` candidate.
+            // This doesn't work as long as we use `CandidateSource` in both winnowing and to resolve associated items.
+            let goal = goal.with(tcx, goal.predicate.with_self_ty(tcx, normalized_ty));
+            let mut orig_values = OriginalQueryValues::default();
+            let goal = self.infcx.canonicalize_query(goal, &mut orig_values);
+            let normalized_candidates =
+                AssemblyCtxt::assemble_and_evaluate_candidates(self.cx, goal);
+
+            // Map each candidate from being canonical wrt the current inference context to being
+            // canonical wrt the caller.
+            for Candidate { source, result } in normalized_candidates {
+                self.infcx.probe(|_| {
+                    let candidate_certainty = fixme_instantiate_canonical_query_response(
+                        &self.infcx,
+                        &orig_values,
+                        result,
+                    );
+
+                    // FIXME: This is a bit scary if the `normalizes_to_goal` overflows.
+                    //
+                    // If we have an ambiguous candidate it hides that normalization
+                    // caused an overflow which may cause issues.
+                    self.try_insert_candidate(
+                        source,
+                        normalization_certainty.unify_and(candidate_certainty),
+                    )
+                })
+            }
+        })
+    }
+
+    fn assemble_impl_candidates(&mut self, goal: Goal<'tcx, G>) {
+        self.cx.tcx.for_each_relevant_impl(
+            goal.predicate.trait_def_id(self.cx.tcx),
+            goal.predicate.self_ty(),
+            |impl_def_id| G::consider_impl_candidate(self, goal, impl_def_id),
+        );
+    }
+}
diff --git a/compiler/rustc_trait_selection/src/solve/cache.rs b/compiler/rustc_trait_selection/src/solve/cache.rs
new file mode 100644
index 00000000000..993b7989066
--- /dev/null
+++ b/compiler/rustc_trait_selection/src/solve/cache.rs
@@ -0,0 +1,257 @@
+//! This module both handles the global cache which stores "finished" goals,
+//! and the provisional cache which contains partially computed goals.
+//!
+//! The provisional cache is necessary when dealing with coinductive cycles.
+//!
+//! For more information about the provisional cache and coinduction in general,
+//! check out the relevant section of the rustc-dev-guide.
+//!
+//! FIXME(@lcnr): Write that section, feel free to ping me if you need help here
+//! before then or if I still haven't done that before January 2023.
+use super::overflow::OverflowData;
+use super::CanonicalGoal;
+use super::{EvalCtxt, QueryResult};
+
+use rustc_data_structures::fx::FxHashMap;
+use rustc_middle::ty::TyCtxt;
+use std::{cmp::Ordering, collections::hash_map::Entry};
+
+#[derive(Debug, Clone)]
+struct ProvisionalEntry<'tcx> {
+    // In case we have a coinductive cycle, this is the
+    // the currently least restrictive result of this goal.
+    response: QueryResult<'tcx>,
+    // The lowest element on the stack on which this result
+    // relies on. Starts out as just being the depth at which
+    // we've proven this obligation, but gets lowered to the
+    // depth of another goal if we rely on it in a cycle.
+    depth: usize,
+}
+
+struct StackElem<'tcx> {
+    goal: CanonicalGoal<'tcx>,
+    has_been_used: bool,
+}
+
+/// The cache used for goals which are currently in progress or which depend
+/// on in progress results.
+///
+/// Once we're done with a goal we can store it in the global trait solver
+/// cache of the `TyCtxt`. For goals which we're currently proving, or which
+/// have only been proven via a coinductive cycle using a goal still on our stack
+/// we have to use this separate data structure.
+///
+/// The current data structure is not perfect, so there may still be room for
+/// improvement here. We have the following requirements:
+///
+/// ## Is there is a provisional entry for the given goal:
+///
+/// ```ignore (for syntax highlighting)
+/// self.entries.get(goal)
+/// ```
+///
+/// ## Get all goals on the stack involved in a cycle:
+///
+/// ```ignore (for syntax highlighting)
+/// let entry = self.entries.get(goal).unwrap();
+/// let involved_goals = self.stack.iter().skip(entry.depth);
+/// ```
+///
+/// ## Capping the depth of all entries
+///
+/// Needed whenever we encounter a cycle. The current implementation always
+/// iterates over all entries instead of only the ones with a larger depth.
+/// Changing this may result in notable performance improvements.
+///
+/// ```ignore (for syntax highlighting)
+/// let cycle_depth = self.entries.get(goal).unwrap().depth;
+/// for e in &mut self.entries {
+///     e.depth = e.depth.min(cycle_depth);
+/// }
+/// ```
+///
+/// ## Checking whether we have to rerun the current goal
+///
+/// A goal has to be rerun if its provisional result was used in a cycle
+/// and that result is different from its final result. We update
+/// [StackElem::has_been_used] for the deepest stack element involved in a cycle.
+///
+/// ## Moving all finished goals into the global cache
+///
+/// If `stack_elem.has_been_used` is true, iterate over all entries, moving the ones
+/// with equal depth. If not, simply move this single entry.
+pub(super) struct ProvisionalCache<'tcx> {
+    stack: Vec<StackElem<'tcx>>,
+    entries: FxHashMap<CanonicalGoal<'tcx>, ProvisionalEntry<'tcx>>,
+}
+
+impl<'tcx> ProvisionalCache<'tcx> {
+    pub(super) fn empty() -> ProvisionalCache<'tcx> {
+        ProvisionalCache { stack: Vec::new(), entries: Default::default() }
+    }
+
+    pub(super) fn current_depth(&self) -> usize {
+        self.stack.len()
+    }
+}
+
+impl<'tcx> EvalCtxt<'tcx> {
+    /// Tries putting the new goal on the stack, returning an error if it is already cached.
+    ///
+    /// This correctly updates the provisional cache if there is a cycle.
+    pub(super) fn try_push_stack(
+        &mut self,
+        goal: CanonicalGoal<'tcx>,
+    ) -> Result<(), QueryResult<'tcx>> {
+        // FIXME: start by checking the global cache
+
+        // Look at the provisional cache to check for cycles.
+        let cache = &mut self.provisional_cache;
+        match cache.entries.entry(goal) {
+            // No entry, simply push this goal on the stack after dealing with overflow.
+            Entry::Vacant(v) => {
+                if self.overflow_data.has_overflow(cache.stack.len()) {
+                    return Err(self.deal_with_overflow());
+                }
+
+                v.insert(ProvisionalEntry {
+                    response: fixme_response_yes_no_constraints(),
+                    depth: cache.stack.len(),
+                });
+                cache.stack.push(StackElem { goal, has_been_used: false });
+                Ok(())
+            }
+            // We have a nested goal which relies on a goal `root` deeper in the stack.
+            //
+            // We first store that we may have to rerun `evaluate_goal` for `root` in case the
+            // provisional response is not equal to the final response. We also update the depth
+            // of all goals which recursively depend on our current goal to depend on `root`
+            // instead.
+            //
+            // Finally we can return either the provisional response for that goal if we have a
+            // coinductive cycle or an ambiguous result if the cycle is inductive.
+            Entry::Occupied(entry) => {
+                // FIXME: `ProvisionalEntry` should be `Copy`.
+                let entry = entry.get().clone();
+                cache.stack[entry.depth].has_been_used = true;
+                for provisional_entry in cache.entries.values_mut() {
+                    provisional_entry.depth = provisional_entry.depth.min(entry.depth);
+                }
+
+                // NOTE: The goals on the stack aren't the only goals involved in this cycle.
+                // We can also depend on goals which aren't part of the stack but coinductively
+                // depend on the stack themselves. We already checked whether all the goals
+                // between these goals and their root on the stack. This means that as long as
+                // each goal in a cycle is checked for coinductivity by itself simply checking
+                // the stack is enough.
+                if cache.stack[entry.depth..]
+                    .iter()
+                    .all(|g| g.goal.value.predicate.is_coinductive(self.tcx))
+                {
+                    Err(entry.response)
+                } else {
+                    Err(fixme_response_maybe_no_constraints())
+                }
+            }
+        }
+    }
+
+    /// We cannot simply store the result of [EvalCtxt::compute_goal] as we have to deal with
+    /// coinductive cycles.
+    ///
+    /// When we encounter a coinductive cycle, we have to prove the final result of that cycle
+    /// while we are still computing that result. Because of this we continously recompute the
+    /// cycle until the result of the previous iteration is equal to the final result, at which
+    /// point we are done.
+    ///
+    /// This function returns `true` if we were able to finalize the goal and `false` if it has
+    /// updated the provisional cache and we have to recompute the current goal.
+    ///
+    /// FIXME: Refer to the rustc-dev-guide entry once it exists.
+    pub(super) fn try_finalize_goal(
+        &mut self,
+        actual_goal: CanonicalGoal<'tcx>,
+        response: QueryResult<'tcx>,
+    ) -> bool {
+        let cache = &mut self.provisional_cache;
+        let StackElem { goal, has_been_used } = cache.stack.pop().unwrap();
+        assert_eq!(goal, actual_goal);
+
+        let provisional_entry = cache.entries.get_mut(&goal).unwrap();
+        // Check whether the current stack entry is the root of a cycle.
+        //
+        // If so, we either move all participants of that cycle to the global cache
+        // or, in case the provisional response used in the cycle is not equal to the
+        // final response, have to recompute the goal after updating the provisional
+        // response to the final response of this iteration.
+        if has_been_used {
+            if provisional_entry.response == response {
+                // We simply drop all entries according to an immutable condition, so
+                // query instability is not a concern here.
+                #[allow(rustc::potential_query_instability)]
+                cache.entries.retain(|goal, entry| match entry.depth.cmp(&cache.stack.len()) {
+                    Ordering::Less => true,
+                    Ordering::Equal => {
+                        Self::try_move_finished_goal_to_global_cache(
+                            self.tcx,
+                            &mut self.overflow_data,
+                            &cache.stack,
+                            // FIXME: these should be `Copy` :(
+                            goal.clone(),
+                            entry.response.clone(),
+                        );
+                        false
+                    }
+                    Ordering::Greater => bug!("entry with greater depth than the current leaf"),
+                });
+
+                true
+            } else {
+                provisional_entry.response = response;
+                cache.stack.push(StackElem { goal, has_been_used: false });
+                false
+            }
+        } else {
+            Self::try_move_finished_goal_to_global_cache(
+                self.tcx,
+                &mut self.overflow_data,
+                &cache.stack,
+                goal,
+                response,
+            );
+            cache.entries.remove(&goal);
+            true
+        }
+    }
+
+    fn try_move_finished_goal_to_global_cache(
+        tcx: TyCtxt<'tcx>,
+        overflow_data: &mut OverflowData,
+        stack: &[StackElem<'tcx>],
+        goal: CanonicalGoal<'tcx>,
+        response: QueryResult<'tcx>,
+    ) {
+        // We move goals to the global cache if we either did not hit an overflow or if it's
+        // the root goal as that will now always hit the same overflow limit.
+        //
+        // NOTE: We cannot move any non-root goals to the global cache even if their final result
+        // isn't impacted by the overflow as that goal still has unstable query dependencies
+        // because it didn't go its full depth.
+        //
+        // FIXME(@lcnr): We could still cache subtrees which are not impacted by overflow though.
+        // Tracking that info correctly isn't trivial, so I haven't implemented it for now.
+        let should_cache_globally = !overflow_data.did_overflow() || stack.is_empty();
+        if should_cache_globally {
+            // FIXME: move the provisional entry to the global cache.
+            let _ = (tcx, goal, response);
+        }
+    }
+}
+
+fn fixme_response_yes_no_constraints<'tcx>() -> QueryResult<'tcx> {
+    unimplemented!()
+}
+
+fn fixme_response_maybe_no_constraints<'tcx>() -> QueryResult<'tcx> {
+    unimplemented!()
+}
diff --git a/compiler/rustc_trait_selection/src/solve/fulfill.rs b/compiler/rustc_trait_selection/src/solve/fulfill.rs
new file mode 100644
index 00000000000..80115d78d88
--- /dev/null
+++ b/compiler/rustc_trait_selection/src/solve/fulfill.rs
@@ -0,0 +1,92 @@
+use std::mem;
+
+use rustc_data_structures::fx::FxHashMap;
+use rustc_infer::{
+    infer::InferCtxt,
+    traits::{query::NoSolution, FulfillmentError, PredicateObligation, TraitEngine},
+};
+use rustc_middle::ty;
+
+use super::{Certainty, EvalCtxt};
+
+/// A trait engine using the new trait solver.
+///
+/// This is mostly identical to how `evaluate_all` works inside of the
+/// solver, except that the requirements are slightly different.
+///
+/// Unlike `evaluate_all` it is possible to add new obligations later on
+/// and we also have to track diagnostics information by using `Obligation`
+/// instead of `Goal`.
+///
+/// It is also likely that we want to use slightly different datastructures
+/// here as this will have to deal with far more root goals than `evaluate_all`.
+pub struct FulfillmentCtxt<'tcx> {
+    obligations: Vec<PredicateObligation<'tcx>>,
+}
+
+impl<'tcx> FulfillmentCtxt<'tcx> {
+    pub fn new() -> FulfillmentCtxt<'tcx> {
+        FulfillmentCtxt { obligations: Vec::new() }
+    }
+}
+
+impl<'tcx> TraitEngine<'tcx> for FulfillmentCtxt<'tcx> {
+    fn register_predicate_obligation(
+        &mut self,
+        _infcx: &InferCtxt<'tcx>,
+        obligation: PredicateObligation<'tcx>,
+    ) {
+        self.obligations.push(obligation);
+    }
+
+    fn select_all_or_error(&mut self, infcx: &InferCtxt<'tcx>) -> Vec<FulfillmentError<'tcx>> {
+        let errors = self.select_where_possible(infcx);
+        if !errors.is_empty() {
+            return errors;
+        }
+
+        if self.obligations.is_empty() {
+            Vec::new()
+        } else {
+            unimplemented!("ambiguous obligations")
+        }
+    }
+
+    fn select_where_possible(&mut self, infcx: &InferCtxt<'tcx>) -> Vec<FulfillmentError<'tcx>> {
+        let errors = Vec::new();
+        for i in 0.. {
+            if !infcx.tcx.recursion_limit().value_within_limit(i) {
+                unimplemented!("overflow")
+            }
+
+            let mut has_changed = false;
+            for o in mem::take(&mut self.obligations) {
+                let mut cx = EvalCtxt::new(infcx.tcx);
+                let (changed, certainty) = match cx.evaluate_goal(infcx, o.clone().into()) {
+                    Ok(result) => result,
+                    Err(NoSolution) => unimplemented!("error"),
+                };
+
+                has_changed |= changed;
+                match certainty {
+                    Certainty::Yes => {}
+                    Certainty::Maybe(_) => self.obligations.push(o),
+                }
+            }
+
+            if !has_changed {
+                break;
+            }
+        }
+
+        errors
+    }
+
+    fn pending_obligations(&self) -> Vec<PredicateObligation<'tcx>> {
+        self.obligations.clone()
+    }
+
+    fn relationships(&mut self) -> &mut FxHashMap<ty::TyVid, ty::FoundRelationships> {
+        unimplemented!("Should be moved out of `TraitEngine`")
+    }
+}
diff --git a/compiler/rustc_trait_selection/src/solve/infcx_ext.rs b/compiler/rustc_trait_selection/src/solve/infcx_ext.rs
new file mode 100644
index 00000000000..436f4eea662
--- /dev/null
+++ b/compiler/rustc_trait_selection/src/solve/infcx_ext.rs
@@ -0,0 +1,55 @@
+use rustc_infer::infer::canonical::CanonicalVarValues;
+use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
+use rustc_infer::infer::InferCtxt;
+use rustc_infer::traits::query::NoSolution;
+use rustc_middle::ty::Ty;
+use rustc_span::DUMMY_SP;
+
+use crate::solve::ExternalConstraints;
+
+use super::{Certainty, QueryResult, Response};
+
+/// Methods used inside of the canonical queries of the solver.
+pub(super) trait InferCtxtExt<'tcx> {
+    fn next_ty_infer(&self) -> Ty<'tcx>;
+
+    fn make_canonical_response(
+        &self,
+        var_values: CanonicalVarValues<'tcx>,
+        certainty: Certainty,
+    ) -> QueryResult<'tcx>;
+}
+
+impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
+    fn next_ty_infer(&self) -> Ty<'tcx> {
+        self.next_ty_var(TypeVariableOrigin {
+            kind: TypeVariableOriginKind::MiscVariable,
+            span: DUMMY_SP,
+        })
+    }
+
+    fn make_canonical_response(
+        &self,
+        var_values: CanonicalVarValues<'tcx>,
+        certainty: Certainty,
+    ) -> QueryResult<'tcx> {
+        let external_constraints = take_external_constraints(self)?;
+
+        Ok(self.canonicalize_response(Response { var_values, external_constraints, certainty }))
+    }
+}
+
+#[instrument(level = "debug", skip(infcx), ret)]
+fn take_external_constraints<'tcx>(
+    infcx: &InferCtxt<'tcx>,
+) -> Result<ExternalConstraints<'tcx>, NoSolution> {
+    let region_obligations = infcx.take_registered_region_obligations();
+    let opaque_types = infcx.take_opaque_types_for_query_response();
+    Ok(ExternalConstraints {
+        // FIXME: Now that's definitely wrong :)
+        //
+        // Should also do the leak check here I think
+        regions: drop(region_obligations),
+        opaque_types,
+    })
+}
diff --git a/compiler/rustc_trait_selection/src/solve/mod.rs b/compiler/rustc_trait_selection/src/solve/mod.rs
new file mode 100644
index 00000000000..7f5e3208f4e
--- /dev/null
+++ b/compiler/rustc_trait_selection/src/solve/mod.rs
@@ -0,0 +1,309 @@
+//! The new trait solver, currently still WIP.
+//!
+//! As a user of the trait system, you can use `TyCtxt::evaluate_goal` to
+//! interact with this solver.
+//!
+//! For a high-level overview of how this solver works, check out the relevant
+//! section of the rustc-dev-guide.
+//!
+//! FIXME(@lcnr): Write that section. If you read this before then ask me
+//! about it on zulip.
+
+// FIXME: Instead of using `infcx.canonicalize_query` we have to add a new routine which
+// preserves universes and creates a unique var (in the highest universe) for each
+// appearance of a region.
+
+// FIXME: `CanonicalVarValues` should be interned and `Copy`.
+
+// FIXME: uses of `infcx.at` need to enable deferred projection equality once that's implemented.
+
+use std::mem;
+
+use rustc_infer::infer::canonical::OriginalQueryValues;
+use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
+use rustc_infer::traits::query::NoSolution;
+use rustc_infer::traits::Obligation;
+use rustc_middle::infer::canonical::{Canonical, CanonicalVarValues};
+use rustc_middle::ty::{self, Ty, TyCtxt};
+use rustc_middle::ty::{RegionOutlivesPredicate, ToPredicate, TypeOutlivesPredicate};
+use rustc_span::DUMMY_SP;
+
+use self::infcx_ext::InferCtxtExt;
+
+mod assembly;
+mod cache;
+mod fulfill;
+mod infcx_ext;
+mod overflow;
+mod project_goals;
+mod trait_goals;
+
+pub use fulfill::FulfillmentCtxt;
+
+/// A goal is a statement, i.e. `predicate`, we want to prove
+/// given some assumptions, i.e. `param_env`.
+///
+/// Most of the time the `param_env` contains the `where`-bounds of the function
+/// we're currently typechecking while the `predicate` is some trait bound.
+#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash, TypeFoldable, TypeVisitable)]
+pub struct Goal<'tcx, P> {
+    param_env: ty::ParamEnv<'tcx>,
+    predicate: P,
+}
+
+impl<'tcx, P> Goal<'tcx, P> {
+    pub fn new(
+        tcx: TyCtxt<'tcx>,
+        param_env: ty::ParamEnv<'tcx>,
+        predicate: impl ToPredicate<'tcx, P>,
+    ) -> Goal<'tcx, P> {
+        Goal { param_env, predicate: predicate.to_predicate(tcx) }
+    }
+
+    /// Updates the goal to one with a different `predicate` but the same `param_env`.
+    fn with<Q>(self, tcx: TyCtxt<'tcx>, predicate: impl ToPredicate<'tcx, Q>) -> Goal<'tcx, Q> {
+        Goal { param_env: self.param_env, predicate: predicate.to_predicate(tcx) }
+    }
+}
+
+impl<'tcx, P> From<Obligation<'tcx, P>> for Goal<'tcx, P> {
+    fn from(obligation: Obligation<'tcx, P>) -> Goal<'tcx, P> {
+        Goal { param_env: obligation.param_env, predicate: obligation.predicate }
+    }
+}
+
+#[derive(Debug, PartialEq, Eq, Clone, Hash, TypeFoldable, TypeVisitable)]
+pub struct Response<'tcx> {
+    pub var_values: CanonicalVarValues<'tcx>,
+    /// Additional constraints returned by this query.
+    pub external_constraints: ExternalConstraints<'tcx>,
+    pub certainty: Certainty,
+}
+
+#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash, TypeFoldable, TypeVisitable)]
+pub enum Certainty {
+    Yes,
+    Maybe(MaybeCause),
+}
+
+impl Certainty {
+    /// When proving multiple goals using **AND**, e.g. nested obligations for an impl,
+    /// use this function to unify the certainty of these goals
+    pub fn unify_and(self, other: Certainty) -> Certainty {
+        match (self, other) {
+            (Certainty::Yes, Certainty::Yes) => Certainty::Yes,
+            (Certainty::Yes, Certainty::Maybe(_)) => other,
+            (Certainty::Maybe(_), Certainty::Yes) => self,
+            (Certainty::Maybe(MaybeCause::Overflow), Certainty::Maybe(MaybeCause::Overflow)) => {
+                Certainty::Maybe(MaybeCause::Overflow)
+            }
+            // If at least one of the goals is ambiguous, hide the overflow as the ambiguous goal
+            // may still result in failure.
+            (Certainty::Maybe(MaybeCause::Ambiguity), Certainty::Maybe(_))
+            | (Certainty::Maybe(_), Certainty::Maybe(MaybeCause::Ambiguity)) => {
+                Certainty::Maybe(MaybeCause::Ambiguity)
+            }
+        }
+    }
+}
+
+/// Why we failed to evaluate a goal.
+#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash, TypeFoldable, TypeVisitable)]
+pub enum MaybeCause {
+    /// We failed due to ambiguity. This ambiguity can either
+    /// be a true ambiguity, i.e. there are multiple different answers,
+    /// or we hit a case where we just don't bother, e.g. `?x: Trait` goals.
+    Ambiguity,
+    /// We gave up due to an overflow, most often by hitting the recursion limit.
+    Overflow,
+}
+
+/// Additional constraints returned on success.
+#[derive(Debug, PartialEq, Eq, Clone, Hash, TypeFoldable, TypeVisitable)]
+pub struct ExternalConstraints<'tcx> {
+    // FIXME: implement this.
+    regions: (),
+    opaque_types: Vec<(Ty<'tcx>, Ty<'tcx>)>,
+}
+
+type CanonicalGoal<'tcx, T = ty::Predicate<'tcx>> = Canonical<'tcx, Goal<'tcx, T>>;
+type CanonicalResponse<'tcx> = Canonical<'tcx, Response<'tcx>>;
+/// The result of evaluating a canonical query.
+///
+/// FIXME: We use a different type than the existing canonical queries. This is because
+/// we need to add a `Certainty` for `overflow` and may want to restructure this code without
+/// having to worry about changes to currently used code. Once we've made progress on this
+/// solver, merge the two responses again.
+pub type QueryResult<'tcx> = Result<CanonicalResponse<'tcx>, NoSolution>;
+
+pub trait TyCtxtExt<'tcx> {
+    fn evaluate_goal(self, goal: CanonicalGoal<'tcx>) -> QueryResult<'tcx>;
+}
+
+impl<'tcx> TyCtxtExt<'tcx> for TyCtxt<'tcx> {
+    fn evaluate_goal(self, goal: CanonicalGoal<'tcx>) -> QueryResult<'tcx> {
+        let mut cx = EvalCtxt::new(self);
+        cx.evaluate_canonical_goal(goal)
+    }
+}
+
+struct EvalCtxt<'tcx> {
+    tcx: TyCtxt<'tcx>,
+
+    provisional_cache: cache::ProvisionalCache<'tcx>,
+    overflow_data: overflow::OverflowData,
+}
+
+impl<'tcx> EvalCtxt<'tcx> {
+    fn new(tcx: TyCtxt<'tcx>) -> EvalCtxt<'tcx> {
+        EvalCtxt {
+            tcx,
+            provisional_cache: cache::ProvisionalCache::empty(),
+            overflow_data: overflow::OverflowData::new(tcx),
+        }
+    }
+
+    /// Recursively evaluates `goal`, returning whether any inference vars have
+    /// been constrained and the certainty of the result.
+    fn evaluate_goal(
+        &mut self,
+        infcx: &InferCtxt<'tcx>,
+        goal: Goal<'tcx, ty::Predicate<'tcx>>,
+    ) -> Result<(bool, Certainty), NoSolution> {
+        let mut orig_values = OriginalQueryValues::default();
+        let canonical_goal = infcx.canonicalize_query(goal, &mut orig_values);
+        let canonical_response = self.evaluate_canonical_goal(canonical_goal)?;
+        Ok((
+            true, // FIXME: check whether `var_values` are an identity substitution.
+            fixme_instantiate_canonical_query_response(infcx, &orig_values, canonical_response),
+        ))
+    }
+
+    fn evaluate_canonical_goal(&mut self, goal: CanonicalGoal<'tcx>) -> QueryResult<'tcx> {
+        match self.try_push_stack(goal) {
+            Ok(()) => {}
+            // Our goal is already on the stack, eager return.
+            Err(response) => return response,
+        }
+
+        // We may have to repeatedly recompute the goal in case of coinductive cycles,
+        // check out the `cache` module for more information.
+        //
+        // FIXME: Similar to `evaluate_all`, this has to check for overflow.
+        loop {
+            let result = self.compute_goal(goal);
+
+            // FIXME: `Response` should be `Copy`
+            if self.try_finalize_goal(goal, result.clone()) {
+                return result;
+            }
+        }
+    }
+
+    fn compute_goal(&mut self, canonical_goal: CanonicalGoal<'tcx>) -> QueryResult<'tcx> {
+        // WARNING: We're looking at a canonical value without instantiating it here.
+        //
+        // We have to be incredibly careful to not change the order of bound variables or
+        // remove any. As we go from `Goal<'tcx, Predicate>` to `Goal` with the variants
+        // of `PredicateKind` this is the case and it is and faster than instantiating and
+        // recanonicalizing.
+        let Goal { param_env, predicate } = canonical_goal.value;
+        if let Some(kind) = predicate.kind().no_bound_vars() {
+            match kind {
+                ty::PredicateKind::Clause(ty::Clause::Trait(predicate)) => self.compute_trait_goal(
+                    canonical_goal.unchecked_rebind(Goal { param_env, predicate }),
+                ),
+                ty::PredicateKind::Clause(ty::Clause::Projection(predicate)) => self
+                    .compute_projection_goal(
+                        canonical_goal.unchecked_rebind(Goal { param_env, predicate }),
+                    ),
+                ty::PredicateKind::Clause(ty::Clause::TypeOutlives(predicate)) => self
+                    .compute_type_outlives_goal(
+                        canonical_goal.unchecked_rebind(Goal { param_env, predicate }),
+                    ),
+                ty::PredicateKind::Clause(ty::Clause::RegionOutlives(predicate)) => self
+                    .compute_region_outlives_goal(
+                        canonical_goal.unchecked_rebind(Goal { param_env, predicate }),
+                    ),
+                // FIXME: implement these predicates :)
+                ty::PredicateKind::WellFormed(_)
+                | ty::PredicateKind::ObjectSafe(_)
+                | ty::PredicateKind::ClosureKind(_, _, _)
+                | ty::PredicateKind::Subtype(_)
+                | ty::PredicateKind::Coerce(_)
+                | ty::PredicateKind::ConstEvaluatable(_)
+                | ty::PredicateKind::ConstEquate(_, _)
+                | ty::PredicateKind::TypeWellFormedFromEnv(_)
+                | ty::PredicateKind::Ambiguous => unimplemented!(),
+            }
+        } else {
+            let (infcx, goal, var_values) =
+                self.tcx.infer_ctxt().build_with_canonical(DUMMY_SP, &canonical_goal);
+            let kind = infcx.replace_bound_vars_with_placeholders(goal.predicate.kind());
+            let goal = goal.with(self.tcx, ty::Binder::dummy(kind));
+            let (_, certainty) = self.evaluate_goal(&infcx, goal)?;
+            infcx.make_canonical_response(var_values, certainty)
+        }
+    }
+
+    fn compute_type_outlives_goal(
+        &mut self,
+        _goal: CanonicalGoal<'tcx, TypeOutlivesPredicate<'tcx>>,
+    ) -> QueryResult<'tcx> {
+        todo!()
+    }
+
+    fn compute_region_outlives_goal(
+        &mut self,
+        _goal: CanonicalGoal<'tcx, RegionOutlivesPredicate<'tcx>>,
+    ) -> QueryResult<'tcx> {
+        todo!()
+    }
+}
+
+impl<'tcx> EvalCtxt<'tcx> {
+    fn evaluate_all(
+        &mut self,
+        infcx: &InferCtxt<'tcx>,
+        mut goals: Vec<Goal<'tcx, ty::Predicate<'tcx>>>,
+    ) -> Result<Certainty, NoSolution> {
+        let mut new_goals = Vec::new();
+        self.repeat_while_none(|this| {
+            let mut has_changed = Err(Certainty::Yes);
+            for goal in goals.drain(..) {
+                let (changed, certainty) = match this.evaluate_goal(infcx, goal) {
+                    Ok(result) => result,
+                    Err(NoSolution) => return Some(Err(NoSolution)),
+                };
+
+                if changed {
+                    has_changed = Ok(());
+                }
+
+                match certainty {
+                    Certainty::Yes => {}
+                    Certainty::Maybe(_) => {
+                        new_goals.push(goal);
+                        has_changed = has_changed.map_err(|c| c.unify_and(certainty));
+                    }
+                }
+            }
+
+            match has_changed {
+                Ok(()) => {
+                    mem::swap(&mut new_goals, &mut goals);
+                    None
+                }
+                Err(certainty) => Some(Ok(certainty)),
+            }
+        })
+    }
+}
+
+fn fixme_instantiate_canonical_query_response<'tcx>(
+    _: &InferCtxt<'tcx>,
+    _: &OriginalQueryValues<'tcx>,
+    _: CanonicalResponse<'tcx>,
+) -> Certainty {
+    unimplemented!()
+}
diff --git a/compiler/rustc_trait_selection/src/solve/overflow.rs b/compiler/rustc_trait_selection/src/solve/overflow.rs
new file mode 100644
index 00000000000..8d73a83aec9
--- /dev/null
+++ b/compiler/rustc_trait_selection/src/solve/overflow.rs
@@ -0,0 +1,80 @@
+use rustc_infer::traits::query::NoSolution;
+use rustc_middle::ty::TyCtxt;
+use rustc_session::Limit;
+
+use super::{Certainty, EvalCtxt, MaybeCause, QueryResult};
+
+/// When detecting a solver overflow, we return ambiguity. Overflow can be
+/// *hidden* by either a fatal error in an **AND** or a trivial success in an **OR**.
+///
+/// This is in issue in case of exponential blowup, e.g. if each goal on the stack
+/// has multiple nested (overflowing) candidates. To deal with this, we reduce the limit
+/// used by the solver when hitting the default limit for the first time.
+///
+/// FIXME: Get tests where always using the `default_limit` results in a hang and refer
+/// to them here. We can also improve the overflow strategy if necessary.
+pub(super) struct OverflowData {
+    default_limit: Limit,
+    current_limit: Limit,
+    /// When proving an **AND** we have to repeatedly iterate over the yet unproven goals.
+    ///
+    /// Because of this each iteration also increases the depth in addition to the stack
+    /// depth.
+    additional_depth: usize,
+}
+
+impl OverflowData {
+    pub(super) fn new(tcx: TyCtxt<'_>) -> OverflowData {
+        let default_limit = tcx.recursion_limit();
+        OverflowData { default_limit, current_limit: default_limit, additional_depth: 0 }
+    }
+
+    #[inline]
+    pub(super) fn did_overflow(&self) -> bool {
+        self.default_limit.0 != self.current_limit.0
+    }
+
+    #[inline]
+    pub(super) fn has_overflow(&self, depth: usize) -> bool {
+        self.current_limit.value_within_limit(depth + self.additional_depth)
+    }
+
+    /// Updating the current limit when hitting overflow.
+    fn deal_with_overflow(&mut self) {
+        // When first hitting overflow we reduce the overflow limit
+        // for all future goals to prevent hangs if there's an exponental
+        // blowup.
+        self.current_limit.0 = self.default_limit.0 / 8;
+    }
+}
+
+impl<'tcx> EvalCtxt<'tcx> {
+    pub(super) fn deal_with_overflow(&mut self) -> QueryResult<'tcx> {
+        self.overflow_data.deal_with_overflow();
+        fixme_response_overflow_no_constraints()
+    }
+
+    /// A `while`-loop which tracks overflow.
+    pub(super) fn repeat_while_none(
+        &mut self,
+        mut loop_body: impl FnMut(&mut Self) -> Option<Result<Certainty, NoSolution>>,
+    ) -> Result<Certainty, NoSolution> {
+        let start_depth = self.overflow_data.additional_depth;
+        let depth = self.provisional_cache.current_depth();
+        while !self.overflow_data.has_overflow(depth) {
+            if let Some(result) = loop_body(self) {
+                self.overflow_data.additional_depth = start_depth;
+                return result;
+            }
+
+            self.overflow_data.additional_depth += 1;
+        }
+        self.overflow_data.additional_depth = start_depth;
+        self.overflow_data.deal_with_overflow();
+        Ok(Certainty::Maybe(MaybeCause::Overflow))
+    }
+}
+
+fn fixme_response_overflow_no_constraints<'tcx>() -> QueryResult<'tcx> {
+    unimplemented!()
+}
diff --git a/compiler/rustc_trait_selection/src/solve/project_goals.rs b/compiler/rustc_trait_selection/src/solve/project_goals.rs
new file mode 100644
index 00000000000..b50f42c4d94
--- /dev/null
+++ b/compiler/rustc_trait_selection/src/solve/project_goals.rs
@@ -0,0 +1,244 @@
+use crate::traits::{specialization_graph, translate_substs};
+
+use super::assembly::{self, AssemblyCtxt};
+use super::{CanonicalGoal, EvalCtxt, Goal, QueryResult};
+use rustc_errors::ErrorGuaranteed;
+use rustc_hir::def::DefKind;
+use rustc_hir::def_id::DefId;
+use rustc_infer::infer::{InferCtxt, InferOk};
+use rustc_infer::traits::query::NoSolution;
+use rustc_infer::traits::specialization_graph::LeafDef;
+use rustc_infer::traits::{ObligationCause, Reveal};
+use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams};
+use rustc_middle::ty::ProjectionPredicate;
+use rustc_middle::ty::TypeVisitable;
+use rustc_middle::ty::{self, Ty, TyCtxt};
+use rustc_span::DUMMY_SP;
+use std::iter;
+
+#[allow(dead_code)] // FIXME: implement and use all variants.
+#[derive(Debug, Clone, Copy)]
+pub(super) enum CandidateSource {
+    Impl(DefId),
+    ParamEnv(usize),
+    Builtin,
+}
+
+type Candidate<'tcx> = assembly::Candidate<'tcx, ProjectionPredicate<'tcx>>;
+
+impl<'tcx> EvalCtxt<'tcx> {
+    pub(super) fn compute_projection_goal(
+        &mut self,
+        goal: CanonicalGoal<'tcx, ProjectionPredicate<'tcx>>,
+    ) -> QueryResult<'tcx> {
+        let candidates = AssemblyCtxt::assemble_and_evaluate_candidates(self, goal);
+        self.merge_project_candidates(candidates)
+    }
+
+    fn merge_project_candidates(
+        &mut self,
+        mut candidates: Vec<Candidate<'tcx>>,
+    ) -> QueryResult<'tcx> {
+        match candidates.len() {
+            0 => return Err(NoSolution),
+            1 => return Ok(candidates.pop().unwrap().result),
+            _ => {}
+        }
+
+        if candidates.len() > 1 {
+            let mut i = 0;
+            'outer: while i < candidates.len() {
+                for j in (0..candidates.len()).filter(|&j| i != j) {
+                    if self.project_candidate_should_be_dropped_in_favor_of(
+                        &candidates[i],
+                        &candidates[j],
+                    ) {
+                        debug!(candidate = ?candidates[i], "Dropping candidate #{}/{}", i, candidates.len());
+                        candidates.swap_remove(i);
+                        continue 'outer;
+                    }
+                }
+
+                debug!(candidate = ?candidates[i], "Retaining candidate #{}/{}", i, candidates.len());
+                // If there are *STILL* multiple candidates, give up
+                // and report ambiguity.
+                i += 1;
+                if i > 1 {
+                    debug!("multiple matches, ambig");
+                    // FIXME: return overflow if all candidates overflow, otherwise return ambiguity.
+                    unimplemented!();
+                }
+            }
+        }
+
+        Ok(candidates.pop().unwrap().result)
+    }
+
+    fn project_candidate_should_be_dropped_in_favor_of(
+        &self,
+        candidate: &Candidate<'tcx>,
+        other: &Candidate<'tcx>,
+    ) -> bool {
+        // FIXME: implement this
+        match (candidate.source, other.source) {
+            (CandidateSource::Impl(_), _)
+            | (CandidateSource::ParamEnv(_), _)
+            | (CandidateSource::Builtin, _) => unimplemented!(),
+        }
+    }
+}
+
+impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> {
+    type CandidateSource = CandidateSource;
+
+    fn self_ty(self) -> Ty<'tcx> {
+        self.self_ty()
+    }
+
+    fn with_self_ty(self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> Self {
+        self.with_self_ty(tcx, self_ty)
+    }
+
+    fn trait_def_id(self, tcx: TyCtxt<'tcx>) -> DefId {
+        self.trait_def_id(tcx)
+    }
+
+    fn consider_impl_candidate(
+        acx: &mut AssemblyCtxt<'_, 'tcx, ProjectionPredicate<'tcx>>,
+        goal: Goal<'tcx, ProjectionPredicate<'tcx>>,
+        impl_def_id: DefId,
+    ) {
+        let tcx = acx.cx.tcx;
+        let goal_trait_ref = goal.predicate.projection_ty.trait_ref(tcx);
+        let impl_trait_ref = tcx.bound_impl_trait_ref(impl_def_id).unwrap();
+        let drcx = DeepRejectCtxt { treat_obligation_params: TreatParams::AsPlaceholder };
+        if iter::zip(goal_trait_ref.substs, impl_trait_ref.skip_binder().substs)
+            .any(|(goal, imp)| !drcx.generic_args_may_unify(goal, imp))
+        {
+            return;
+        }
+
+        acx.infcx.probe(|_| {
+            let impl_substs = acx.infcx.fresh_substs_for_item(DUMMY_SP, impl_def_id);
+            let impl_trait_ref = impl_trait_ref.subst(tcx, impl_substs);
+
+            let Ok(InferOk { obligations, .. }) = acx
+                .infcx
+                .at(&ObligationCause::dummy(), goal.param_env)
+                .define_opaque_types(false)
+                .eq(goal_trait_ref, impl_trait_ref)
+                .map_err(|e| debug!("failed to equate trait refs: {e:?}"))
+            else {
+                return
+            };
+
+            let nested_goals = obligations.into_iter().map(|o| o.into()).collect();
+            let Ok(trait_ref_certainty) = acx.cx.evaluate_all(acx.infcx, nested_goals) else { return };
+
+            let Some(assoc_def) = fetch_eligible_assoc_item_def(
+                acx.infcx,
+                goal.param_env,
+                goal_trait_ref,
+                goal.predicate.def_id(),
+                impl_def_id
+            ) else {
+                return
+            };
+
+            if !assoc_def.item.defaultness(tcx).has_value() {
+                tcx.sess.delay_span_bug(
+                    tcx.def_span(assoc_def.item.def_id),
+                    "missing value for assoc item in impl",
+                );
+            }
+
+            // Getting the right substitutions here is complex, e.g. given:
+            // - a goal `<Vec<u32> as Trait<i32>>::Assoc<u64>`
+            // - the applicable impl `impl<T> Trait<i32> for Vec<T>`
+            // - and the impl which defines `Assoc` being `impl<T, U> Trait<U> for Vec<T>`
+            //
+            // We first rebase the goal substs onto the impl, going from `[Vec<u32>, i32, u64]`
+            // to `[u32, u64]`.
+            //
+            // And then map these substs to the substs of the defining impl of `Assoc`, going
+            // from `[u32, u64]` to `[u32, i32, u64]`.
+            let impl_substs_with_gat = goal.predicate.projection_ty.substs.rebase_onto(
+                tcx,
+                goal_trait_ref.def_id,
+                impl_trait_ref.substs,
+            );
+            let substs = translate_substs(
+                acx.infcx,
+                goal.param_env,
+                impl_def_id,
+                impl_substs_with_gat,
+                assoc_def.defining_node,
+            );
+
+            // Finally we construct the actual value of the associated type.
+            let is_const = matches!(tcx.def_kind(assoc_def.item.def_id), DefKind::AssocConst);
+            let ty = tcx.bound_type_of(assoc_def.item.def_id);
+            let term: ty::EarlyBinder<ty::Term<'tcx>> = if is_const {
+                let identity_substs = ty::InternalSubsts::identity_for_item(tcx, assoc_def.item.def_id);
+                let did = ty::WithOptConstParam::unknown(assoc_def.item.def_id);
+                let kind =
+                    ty::ConstKind::Unevaluated(ty::UnevaluatedConst::new(did, identity_substs));
+                ty.map_bound(|ty| tcx.mk_const(kind, ty).into())
+            } else {
+                ty.map_bound(|ty| ty.into())
+            };
+
+            let Ok(InferOk { obligations, .. }) = acx
+                .infcx
+                .at(&ObligationCause::dummy(), goal.param_env)
+                .define_opaque_types(false)
+                .eq(goal.predicate.term,  term.subst(tcx, substs))
+                .map_err(|e| debug!("failed to equate trait refs: {e:?}"))
+            else {
+                return
+            };
+
+            let nested_goals = obligations.into_iter().map(|o| o.into()).collect();
+            let Ok(rhs_certainty) = acx.cx.evaluate_all(acx.infcx, nested_goals) else { return };
+
+            let certainty = trait_ref_certainty.unify_and(rhs_certainty);
+            acx.try_insert_candidate(CandidateSource::Impl(impl_def_id), certainty);
+        })
+    }
+}
+
+/// This behavior is also implemented in `rustc_ty_utils` and in the old `project` code.
+///
+/// FIXME: We should merge these 3 implementations as it's likely that they otherwise
+/// diverge.
+#[instrument(level = "debug", skip(infcx, param_env), ret)]
+fn fetch_eligible_assoc_item_def<'tcx>(
+    infcx: &InferCtxt<'tcx>,
+    param_env: ty::ParamEnv<'tcx>,
+    goal_trait_ref: ty::TraitRef<'tcx>,
+    trait_assoc_def_id: DefId,
+    impl_def_id: DefId,
+) -> Option<LeafDef> {
+    let node_item = specialization_graph::assoc_def(infcx.tcx, impl_def_id, trait_assoc_def_id)
+        .map_err(|ErrorGuaranteed { .. }| ())
+        .ok()?;
+
+    let eligible = if node_item.is_final() {
+        // Non-specializable items are always projectable.
+        true
+    } else {
+        // Only reveal a specializable default if we're past type-checking
+        // and the obligation is monomorphic, otherwise passes such as
+        // transmute checking and polymorphic MIR optimizations could
+        // get a result which isn't correct for all monomorphizations.
+        if param_env.reveal() == Reveal::All {
+            let poly_trait_ref = infcx.resolve_vars_if_possible(goal_trait_ref);
+            !poly_trait_ref.still_further_specializable()
+        } else {
+            debug!(?node_item.item.def_id, "not eligible due to default");
+            false
+        }
+    };
+
+    if eligible { Some(node_item) } else { None }
+}
diff --git a/compiler/rustc_trait_selection/src/solve/trait_goals.rs b/compiler/rustc_trait_selection/src/solve/trait_goals.rs
new file mode 100644
index 00000000000..10b45a77dab
--- /dev/null
+++ b/compiler/rustc_trait_selection/src/solve/trait_goals.rs
@@ -0,0 +1,180 @@
+//! Dealing with trait goals, i.e. `T: Trait<'a, U>`.
+
+use std::iter;
+
+use super::assembly::{self, AssemblyCtxt};
+use super::{CanonicalGoal, EvalCtxt, Goal, QueryResult};
+use rustc_hir::def_id::DefId;
+use rustc_infer::infer::InferOk;
+use rustc_infer::traits::query::NoSolution;
+use rustc_infer::traits::ObligationCause;
+use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams};
+use rustc_middle::ty::TraitPredicate;
+use rustc_middle::ty::{self, Ty, TyCtxt};
+use rustc_span::DUMMY_SP;
+
+#[allow(dead_code)] // FIXME: implement and use all variants.
+#[derive(Debug, Clone, Copy)]
+pub(super) enum CandidateSource {
+    /// Some user-defined impl with the given `DefId`.
+    Impl(DefId),
+    /// The n-th caller bound in the `param_env` of our goal.
+    ///
+    /// This is pretty much always a bound from the `where`-clauses of the
+    /// currently checked item.
+    ParamEnv(usize),
+    /// A bound on the `self_ty` in case it is a projection or an opaque type.
+    ///
+    /// # Examples
+    ///
+    /// ```ignore (for syntax highlighting)
+    /// trait Trait {
+    ///     type Assoc: OtherTrait;
+    /// }
+    /// ```
+    ///
+    /// We know that `<Whatever as Trait>::Assoc: OtherTrait` holds by looking at
+    /// the bounds on `Trait::Assoc`.
+    AliasBound(usize),
+    /// A builtin implementation for some specific traits, used in cases
+    /// where we cannot rely an ordinary library implementations.
+    ///
+    /// The most notable examples are `Sized`, `Copy` and `Clone`. This is also
+    /// used for the `DiscriminantKind` and `Pointee` trait, both of which have
+    /// an associated type.
+    Builtin,
+    /// An automatic impl for an auto trait, e.g. `Send`. These impls recursively look
+    /// at the constituent types of the `self_ty` to check whether the auto trait
+    /// is implemented for those.
+    AutoImpl,
+}
+
+type Candidate<'tcx> = assembly::Candidate<'tcx, TraitPredicate<'tcx>>;
+
+impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
+    type CandidateSource = CandidateSource;
+
+    fn self_ty(self) -> Ty<'tcx> {
+        self.self_ty()
+    }
+
+    fn with_self_ty(self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> Self {
+        self.with_self_ty(tcx, self_ty)
+    }
+
+    fn trait_def_id(self, _: TyCtxt<'tcx>) -> DefId {
+        self.def_id()
+    }
+
+    fn consider_impl_candidate(
+        acx: &mut AssemblyCtxt<'_, 'tcx, Self>,
+        goal: Goal<'tcx, TraitPredicate<'tcx>>,
+        impl_def_id: DefId,
+    ) {
+        let impl_trait_ref = acx.cx.tcx.bound_impl_trait_ref(impl_def_id).unwrap();
+        let drcx = DeepRejectCtxt { treat_obligation_params: TreatParams::AsPlaceholder };
+        if iter::zip(goal.predicate.trait_ref.substs, impl_trait_ref.skip_binder().substs)
+            .any(|(goal, imp)| !drcx.generic_args_may_unify(goal, imp))
+        {
+            return;
+        }
+
+        acx.infcx.probe(|_| {
+            let impl_substs = acx.infcx.fresh_substs_for_item(DUMMY_SP, impl_def_id);
+            let impl_trait_ref = impl_trait_ref.subst(acx.cx.tcx, impl_substs);
+
+            let Ok(InferOk { obligations, .. }) = acx
+                .infcx
+                .at(&ObligationCause::dummy(), goal.param_env)
+                .define_opaque_types(false)
+                .eq(goal.predicate.trait_ref, impl_trait_ref)
+                .map_err(|e| debug!("failed to equate trait refs: {e:?}"))
+            else {
+                return
+            };
+
+            let nested_goals = obligations.into_iter().map(|o| o.into()).collect();
+
+            let Ok(certainty) = acx.cx.evaluate_all(acx.infcx, nested_goals) else { return };
+            acx.try_insert_candidate(CandidateSource::Impl(impl_def_id), certainty);
+        })
+    }
+}
+
+impl<'tcx> EvalCtxt<'tcx> {
+    pub(super) fn compute_trait_goal(
+        &mut self,
+        goal: CanonicalGoal<'tcx, TraitPredicate<'tcx>>,
+    ) -> QueryResult<'tcx> {
+        let candidates = AssemblyCtxt::assemble_and_evaluate_candidates(self, goal);
+        self.merge_trait_candidates_discard_reservation_impls(candidates)
+    }
+
+    #[instrument(level = "debug", skip(self), ret)]
+    pub(super) fn merge_trait_candidates_discard_reservation_impls(
+        &mut self,
+        mut candidates: Vec<Candidate<'tcx>>,
+    ) -> QueryResult<'tcx> {
+        match candidates.len() {
+            0 => return Err(NoSolution),
+            1 => return Ok(self.discard_reservation_impl(candidates.pop().unwrap()).result),
+            _ => {}
+        }
+
+        if candidates.len() > 1 {
+            let mut i = 0;
+            'outer: while i < candidates.len() {
+                for j in (0..candidates.len()).filter(|&j| i != j) {
+                    if self.trait_candidate_should_be_dropped_in_favor_of(
+                        &candidates[i],
+                        &candidates[j],
+                    ) {
+                        debug!(candidate = ?candidates[i], "Dropping candidate #{}/{}", i, candidates.len());
+                        candidates.swap_remove(i);
+                        continue 'outer;
+                    }
+                }
+
+                debug!(candidate = ?candidates[i], "Retaining candidate #{}/{}", i, candidates.len());
+                // If there are *STILL* multiple candidates, give up
+                // and report ambiguity.
+                i += 1;
+                if i > 1 {
+                    debug!("multiple matches, ambig");
+                    // FIXME: return overflow if all candidates overflow, otherwise return ambiguity.
+                    unimplemented!();
+                }
+            }
+        }
+
+        Ok(self.discard_reservation_impl(candidates.pop().unwrap()).result)
+    }
+
+    fn trait_candidate_should_be_dropped_in_favor_of(
+        &self,
+        candidate: &Candidate<'tcx>,
+        other: &Candidate<'tcx>,
+    ) -> bool {
+        // FIXME: implement this
+        match (candidate.source, other.source) {
+            (CandidateSource::Impl(_), _)
+            | (CandidateSource::ParamEnv(_), _)
+            | (CandidateSource::AliasBound(_), _)
+            | (CandidateSource::Builtin, _)
+            | (CandidateSource::AutoImpl, _) => unimplemented!(),
+        }
+    }
+
+    fn discard_reservation_impl(&self, candidate: Candidate<'tcx>) -> Candidate<'tcx> {
+        if let CandidateSource::Impl(def_id) = candidate.source {
+            if let ty::ImplPolarity::Reservation = self.tcx.impl_polarity(def_id) {
+                debug!("Selected reservation impl");
+                // FIXME: reduce candidate to ambiguous
+                // FIXME: replace `var_values` with identity, yeet external constraints.
+                unimplemented!()
+            }
+        }
+
+        candidate
+    }
+}
diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs
index 7c569621cfe..26757965c95 100644
--- a/compiler/rustc_trait_selection/src/traits/coherence.rs
+++ b/compiler/rustc_trait_selection/src/traits/coherence.rs
@@ -66,13 +66,13 @@ pub fn add_placeholder_note(err: &mut Diagnostic) {
 /// with a suitably-freshened `ImplHeader` with those types
 /// substituted. Otherwise, returns `None`.
 #[instrument(skip(tcx, skip_leak_check), level = "debug")]
-pub fn overlapping_impls<'tcx>(
-    tcx: TyCtxt<'tcx>,
+pub fn overlapping_impls(
+    tcx: TyCtxt<'_>,
     impl1_def_id: DefId,
     impl2_def_id: DefId,
     skip_leak_check: SkipLeakCheck,
     overlap_mode: OverlapMode,
-) -> Option<OverlapResult<'tcx>> {
+) -> Option<OverlapResult<'_>> {
     // Before doing expensive operations like entering an inference context, do
     // a quick check via fast_reject to tell if the impl headers could possibly
     // unify.
@@ -283,7 +283,7 @@ fn implicit_negative<'cx, 'tcx>(
 
 /// Given impl1 and impl2 check if both impls are never satisfied by a common type (including
 /// where-clauses) If so, return true, they are disjoint and false otherwise.
-fn negative_impl<'tcx>(tcx: TyCtxt<'tcx>, impl1_def_id: DefId, impl2_def_id: DefId) -> bool {
+fn negative_impl(tcx: TyCtxt<'_>, impl1_def_id: DefId, impl2_def_id: DefId) -> bool {
     debug!("negative_impl(impl1_def_id={:?}, impl2_def_id={:?})", impl1_def_id, impl2_def_id);
 
     // Create an infcx, taking the predicates of impl1 as assumptions:
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/method_chain.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/method_chain.rs
index cb373d65772..27c207528c7 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/method_chain.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/method_chain.rs
@@ -14,21 +14,27 @@ impl<'a, 'tcx> TypeRelation<'tcx> for CollectAllMismatches<'a, 'tcx> {
     fn tag(&self) -> &'static str {
         "CollectAllMismatches"
     }
+
     fn tcx(&self) -> TyCtxt<'tcx> {
         self.infcx.tcx
     }
+
     fn intercrate(&self) -> bool {
         false
     }
+
     fn param_env(&self) -> ty::ParamEnv<'tcx> {
         self.param_env
     }
+
     fn a_is_expected(&self) -> bool {
         true
-    } // irrelevant
+    }
+
     fn mark_ambiguous(&mut self) {
         bug!()
     }
+
     fn relate_with_variance<T: Relate<'tcx>>(
         &mut self,
         _: ty::Variance,
@@ -38,6 +44,7 @@ impl<'a, 'tcx> TypeRelation<'tcx> for CollectAllMismatches<'a, 'tcx> {
     ) -> RelateResult<'tcx, T> {
         self.relate(a, b)
     }
+
     fn regions(
         &mut self,
         a: ty::Region<'tcx>,
@@ -45,15 +52,20 @@ impl<'a, 'tcx> TypeRelation<'tcx> for CollectAllMismatches<'a, 'tcx> {
     ) -> RelateResult<'tcx, ty::Region<'tcx>> {
         Ok(a)
     }
+
     fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
-        if a == b || matches!(a.kind(), ty::Infer(_)) || matches!(b.kind(), ty::Infer(_)) {
-            return Ok(a);
-        }
-        relate::super_relate_tys(self, a, b).or_else(|e| {
-            self.errors.push(e);
-            Ok(a)
+        self.infcx.probe(|_| {
+            if a.is_ty_infer() || b.is_ty_infer() {
+                Ok(a)
+            } else {
+                self.infcx.super_combine_tys(self, a, b).or_else(|e| {
+                    self.errors.push(e);
+                    Ok(a)
+                })
+            }
         })
     }
+
     fn consts(
         &mut self,
         a: ty::Const<'tcx>,
@@ -64,6 +76,7 @@ impl<'a, 'tcx> TypeRelation<'tcx> for CollectAllMismatches<'a, 'tcx> {
         }
         relate::super_relate_consts(self, a, b) // could do something similar here for constants!
     }
+
     fn binders<T: Relate<'tcx>>(
         &mut self,
         a: ty::Binder<'tcx, T>,
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
index 036e8f6d47b..472086eca8f 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
@@ -335,7 +335,7 @@ pub trait TypeErrCtxtExt<'tcx> {
         err: &mut Diagnostic,
         trait_pred: ty::PolyTraitPredicate<'tcx>,
     );
-    fn function_argument_obligation(
+    fn note_function_argument_obligation(
         &self,
         arg_hir_id: HirId,
         err: &mut Diagnostic,
@@ -1291,29 +1291,25 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
 
         if let ObligationCauseCode::AwaitableExpr(hir_id) = obligation.cause.code().peel_derives() {
             let hir = self.tcx.hir();
-            if let Some(node) = hir_id.and_then(|hir_id| hir.find(hir_id)) {
-                if let hir::Node::Expr(expr) = node {
-                    // FIXME: use `obligation.predicate.kind()...trait_ref.self_ty()` to see if we have `()`
-                    // and if not maybe suggest doing something else? If we kept the expression around we
-                    // could also check if it is an fn call (very likely) and suggest changing *that*, if
-                    // it is from the local crate.
-                    err.span_suggestion(
-                        span,
-                        "remove the `.await`",
-                        "",
-                        Applicability::MachineApplicable,
-                    );
-                    // FIXME: account for associated `async fn`s.
-                    if let hir::Expr { span, kind: hir::ExprKind::Call(base, _), .. } = expr {
-                        if let ty::PredicateKind::Clause(ty::Clause::Trait(pred)) =
-                            obligation.predicate.kind().skip_binder()
-                        {
-                            err.span_label(
-                                *span,
-                                &format!("this call returns `{}`", pred.self_ty()),
-                            );
-                        }
-                        if let Some(typeck_results) = &self.typeck_results
+            if let Some(hir::Node::Expr(expr)) = hir_id.and_then(|hir_id| hir.find(hir_id)) {
+                // FIXME: use `obligation.predicate.kind()...trait_ref.self_ty()` to see if we have `()`
+                // and if not maybe suggest doing something else? If we kept the expression around we
+                // could also check if it is an fn call (very likely) and suggest changing *that*, if
+                // it is from the local crate.
+                err.span_suggestion(
+                    span,
+                    "remove the `.await`",
+                    "",
+                    Applicability::MachineApplicable,
+                );
+                // FIXME: account for associated `async fn`s.
+                if let hir::Expr { span, kind: hir::ExprKind::Call(base, _), .. } = expr {
+                    if let ty::PredicateKind::Clause(ty::Clause::Trait(pred)) =
+                        obligation.predicate.kind().skip_binder()
+                    {
+                        err.span_label(*span, &format!("this call returns `{}`", pred.self_ty()));
+                    }
+                    if let Some(typeck_results) = &self.typeck_results
                             && let ty = typeck_results.expr_ty_adjusted(base)
                             && let ty::FnDef(def_id, _substs) = ty.kind()
                             && let Some(hir::Node::Item(hir::Item { ident, span, vis_span, .. })) =
@@ -1339,7 +1335,6 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                                 );
                             }
                         }
-                    }
                 }
             }
         }
@@ -2909,7 +2904,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                 ref parent_code,
                 ..
             } => {
-                self.function_argument_obligation(
+                self.note_function_argument_obligation(
                     arg_hir_id,
                     err,
                     parent_code,
@@ -3141,23 +3136,20 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
             );
         }
     }
-    fn function_argument_obligation(
+    fn note_function_argument_obligation(
         &self,
         arg_hir_id: HirId,
         err: &mut Diagnostic,
         parent_code: &ObligationCauseCode<'tcx>,
         param_env: ty::ParamEnv<'tcx>,
-        predicate: ty::Predicate<'tcx>,
+        failed_pred: ty::Predicate<'tcx>,
         call_hir_id: HirId,
     ) {
         let tcx = self.tcx;
         let hir = tcx.hir();
-        if let Some(Node::Expr(expr)) = hir.find(arg_hir_id) {
-            let parent_id = hir.get_parent_item(arg_hir_id);
-            let typeck_results: &TypeckResults<'tcx> = match &self.typeck_results {
-                Some(t) if t.hir_owner == parent_id => t,
-                _ => self.tcx.typeck(parent_id.def_id),
-            };
+        if let Some(Node::Expr(expr)) = hir.find(arg_hir_id)
+            && let Some(typeck_results) = &self.typeck_results
+        {
             if let hir::Expr { kind: hir::ExprKind::Block(..), .. } = expr {
                 let expr = expr.peel_blocks();
                 let ty = typeck_results.expr_ty_adjusted_opt(expr).unwrap_or(tcx.ty_error());
@@ -3182,37 +3174,29 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
             let mut type_diffs = vec![];
 
             if let ObligationCauseCode::ExprBindingObligation(def_id, _, _, idx) = parent_code.deref()
-                && let predicates = self.tcx.predicates_of(def_id).instantiate_identity(self.tcx)
-                && let Some(pred) = predicates.predicates.get(*idx)
+                && let Some(node_substs) = typeck_results.node_substs_opt(call_hir_id)
+                && let where_clauses = self.tcx.predicates_of(def_id).instantiate(self.tcx, node_substs)
+                && let Some(where_pred) = where_clauses.predicates.get(*idx)
             {
-                if let Ok(trait_pred) = pred.kind().try_map_bound(|pred| match pred {
-                    ty::PredicateKind::Clause(ty::Clause::Trait(trait_pred)) => Ok(trait_pred),
-                    _ => Err(()),
-                })
-                    && let Ok(trait_predicate) = predicate.kind().try_map_bound(|pred| match pred {
-                        ty::PredicateKind::Clause(ty::Clause::Trait(trait_pred)) => Ok(trait_pred),
-                        _ => Err(()),
-                    })
+                if let Some(where_pred) = where_pred.to_opt_poly_trait_pred()
+                    && let Some(failed_pred) = failed_pred.to_opt_poly_trait_pred()
                 {
                     let mut c = CollectAllMismatches {
                         infcx: self.infcx,
                         param_env,
                         errors: vec![],
                     };
-                    if let Ok(_) = c.relate(trait_pred, trait_predicate) {
+                    if let Ok(_) = c.relate(where_pred, failed_pred) {
                         type_diffs = c.errors;
                     }
-                } else if let ty::PredicateKind::Clause(
-                    ty::Clause::Projection(proj)
-                ) = pred.kind().skip_binder()
-                    && let ty::PredicateKind::Clause(
-                        ty::Clause::Projection(projection)
-                    ) = predicate.kind().skip_binder()
+                } else if let Some(where_pred) = where_pred.to_opt_poly_projection_pred()
+                    && let Some(failed_pred) = failed_pred.to_opt_poly_projection_pred()
+                    && let Some(found) = failed_pred.skip_binder().term.ty()
                 {
                     type_diffs = vec![
                         Sorts(ty::error::ExpectedFound {
-                            expected: self.tcx.mk_ty(ty::Alias(ty::Projection, proj.projection_ty)),
-                            found: projection.term.ty().unwrap(),
+                            expected: self.tcx.mk_ty(ty::Alias(ty::Projection, where_pred.skip_binder().projection_ty)),
+                            found,
                         }),
                     ];
                 }
@@ -3227,9 +3211,9 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                 // If the expression we're calling on is a binding, we want to point at the
                 // `let` when talking about the type. Otherwise we'll point at every part
                 // of the method chain with the type.
-                self.point_at_chain(binding_expr, typeck_results, type_diffs, param_env, err);
+                self.point_at_chain(binding_expr, &typeck_results, type_diffs, param_env, err);
             } else {
-                self.point_at_chain(expr, typeck_results, type_diffs, param_env, err);
+                self.point_at_chain(expr, &typeck_results, type_diffs, param_env, err);
             }
         }
         let call_node = hir.find(call_hir_id);
@@ -3483,7 +3467,7 @@ fn hint_missing_borrow<'tcx>(
 
     let arg_spans = fn_decl.inputs.iter().map(|ty| ty.span);
 
-    fn get_deref_type_and_refs<'tcx>(mut ty: Ty<'tcx>) -> (Ty<'tcx>, usize) {
+    fn get_deref_type_and_refs(mut ty: Ty<'_>) -> (Ty<'_>, usize) {
         let mut refs = 0;
 
         while let ty::Ref(_, new_ty, _) = ty.kind() {
diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs
index 2566d793d78..c30531fa906 100644
--- a/compiler/rustc_trait_selection/src/traits/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/mod.rs
@@ -484,10 +484,7 @@ fn subst_and_check_impossible_predicates<'tcx>(
 ///
 /// This only considers predicates that reference the impl's generics, and not
 /// those that reference the method's generics.
-fn is_impossible_method<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    (impl_def_id, trait_item_def_id): (DefId, DefId),
-) -> bool {
+fn is_impossible_method(tcx: TyCtxt<'_>, (impl_def_id, trait_item_def_id): (DefId, DefId)) -> bool {
     struct ReferencesOnlyParentGenerics<'tcx> {
         tcx: TyCtxt<'tcx>,
         generics: &'tcx ty::Generics,
diff --git a/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs b/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs
index e1092a788e3..f2c5f730b31 100644
--- a/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs
+++ b/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs
@@ -34,7 +34,7 @@ impl<'a, 'tcx: 'a> InferCtxtExt<'a, 'tcx> for InferCtxt<'tcx> {
     /// argument types are well-formed. This may imply certain relationships
     /// between generic parameters. For example:
     /// ```
-    /// fn foo<'a,T>(x: &'a T) {}
+    /// fn foo<T>(x: &T) {}
     /// ```
     /// can only be called with a `'a` and `T` such that `&'a T` is WF.
     /// For `&'a T` to be WF, `T: 'a` must hold. So we can assume `T: 'a`.
diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs
index 84d7244c1db..f7614997585 100644
--- a/compiler/rustc_trait_selection/src/traits/project.rs
+++ b/compiler/rustc_trait_selection/src/traits/project.rs
@@ -25,7 +25,6 @@ use rustc_data_structures::sso::SsoHashSet;
 use rustc_data_structures::stack::ensure_sufficient_stack;
 use rustc_errors::ErrorGuaranteed;
 use rustc_hir::def::DefKind;
-use rustc_hir::def_id::DefId;
 use rustc_hir::lang_items::LangItem;
 use rustc_infer::infer::at::At;
 use rustc_infer::infer::resolve::OpportunisticRegionResolver;
@@ -1553,7 +1552,7 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
                 // NOTE: This should be kept in sync with the similar code in
                 // `rustc_ty_utils::instance::resolve_associated_item()`.
                 let node_item =
-                    assoc_def(selcx, impl_data.impl_def_id, obligation.predicate.def_id)
+                    specialization_graph::assoc_def(selcx.tcx(), impl_data.impl_def_id, obligation.predicate.def_id)
                         .map_err(|ErrorGuaranteed { .. }| ())?;
 
                 if node_item.is_final() {
@@ -2113,7 +2112,7 @@ fn confirm_impl_candidate<'cx, 'tcx>(
     let trait_def_id = tcx.trait_id_of_impl(impl_def_id).unwrap();
 
     let param_env = obligation.param_env;
-    let Ok(assoc_ty) = assoc_def(selcx, impl_def_id, assoc_item_id) else {
+    let Ok(assoc_ty) = specialization_graph::assoc_def(tcx, impl_def_id, assoc_item_id) else {
         return Progress { term: tcx.ty_error().into(), obligations: nested };
     };
 
@@ -2210,7 +2209,7 @@ fn confirm_impl_trait_in_trait_candidate<'tcx>(
     let mut obligations = data.nested;
 
     let trait_fn_def_id = tcx.impl_trait_in_trait_parent(obligation.predicate.def_id);
-    let Ok(leaf_def) = assoc_def(selcx, data.impl_def_id, trait_fn_def_id) else {
+    let Ok(leaf_def) = specialization_graph::assoc_def(tcx, data.impl_def_id, trait_fn_def_id) else {
         return Progress { term: tcx.ty_error().into(), obligations };
     };
     if !leaf_def.item.defaultness(tcx).has_value() {
@@ -2285,7 +2284,7 @@ fn confirm_impl_trait_in_trait_candidate<'tcx>(
         obligation.param_env,
         cause.clone(),
         obligation.recursion_depth + 1,
-        tcx.bound_trait_impl_trait_tys(impl_fn_def_id)
+        tcx.bound_return_position_impl_trait_in_trait_tys(impl_fn_def_id)
             .map_bound(|tys| {
                 tys.map_or_else(|_| tcx.ty_error(), |tys| tys[&obligation.predicate.def_id])
             })
@@ -2347,58 +2346,6 @@ fn assoc_ty_own_obligations<'cx, 'tcx>(
     }
 }
 
-/// Locate the definition of an associated type in the specialization hierarchy,
-/// starting from the given impl.
-///
-/// Based on the "projection mode", this lookup may in fact only examine the
-/// topmost impl. See the comments for `Reveal` for more details.
-fn assoc_def(
-    selcx: &SelectionContext<'_, '_>,
-    impl_def_id: DefId,
-    assoc_def_id: DefId,
-) -> Result<specialization_graph::LeafDef, ErrorGuaranteed> {
-    let tcx = selcx.tcx();
-    let trait_def_id = tcx.impl_trait_ref(impl_def_id).unwrap().def_id;
-    let trait_def = tcx.trait_def(trait_def_id);
-
-    // This function may be called while we are still building the
-    // specialization graph that is queried below (via TraitDef::ancestors()),
-    // so, in order to avoid unnecessary infinite recursion, we manually look
-    // for the associated item at the given impl.
-    // If there is no such item in that impl, this function will fail with a
-    // cycle error if the specialization graph is currently being built.
-    if let Some(&impl_item_id) = tcx.impl_item_implementor_ids(impl_def_id).get(&assoc_def_id) {
-        let item = tcx.associated_item(impl_item_id);
-        let impl_node = specialization_graph::Node::Impl(impl_def_id);
-        return Ok(specialization_graph::LeafDef {
-            item: *item,
-            defining_node: impl_node,
-            finalizing_node: if item.defaultness(tcx).is_default() {
-                None
-            } else {
-                Some(impl_node)
-            },
-        });
-    }
-
-    let ancestors = trait_def.ancestors(tcx, impl_def_id)?;
-    if let Some(assoc_item) = ancestors.leaf_def(tcx, assoc_def_id) {
-        Ok(assoc_item)
-    } else {
-        // This is saying that neither the trait nor
-        // the impl contain a definition for this
-        // associated type.  Normally this situation
-        // could only arise through a compiler bug --
-        // if the user wrote a bad item name, it
-        // should have failed in astconv.
-        bug!(
-            "No associated type `{}` for {}",
-            tcx.item_name(assoc_def_id),
-            tcx.def_path_str(impl_def_id)
-        )
-    }
-}
-
 pub(crate) trait ProjectionCacheKeyExt<'cx, 'tcx>: Sized {
     fn from_poly_projection_predicate(
         selcx: &mut SelectionContext<'cx, 'tcx>,
diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs
index 792933096b1..81e8f9e914c 100644
--- a/compiler/rustc_trait_selection/src/traits/select/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs
@@ -1171,19 +1171,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
     where
         I: Iterator<Item = ty::Predicate<'tcx>>,
     {
-        cycle.all(|predicate| self.coinductive_predicate(predicate))
-    }
-
-    fn coinductive_predicate(&self, predicate: ty::Predicate<'tcx>) -> bool {
-        let result = match predicate.kind().skip_binder() {
-            ty::PredicateKind::Clause(ty::Clause::Trait(ref data)) => {
-                self.tcx().trait_is_coinductive(data.def_id())
-            }
-            ty::PredicateKind::WellFormed(_) => true,
-            _ => false,
-        };
-        debug!(?predicate, ?result, "coinductive_predicate");
-        result
+        cycle.all(|predicate| predicate.is_coinductive(self.tcx()))
     }
 
     /// Further evaluates `candidate` to decide whether all type parameters match and whether nested
diff --git a/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs b/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs
index 4546c953393..02b06677740 100644
--- a/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs
+++ b/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs
@@ -1,6 +1,7 @@
 use super::OverlapError;
 
 use crate::traits;
+use rustc_errors::ErrorGuaranteed;
 use rustc_hir::def_id::DefId;
 use rustc_middle::ty::fast_reject::{self, SimplifiedType, TreatParams};
 use rustc_middle::ty::{self, TyCtxt, TypeVisitable};
@@ -379,3 +380,51 @@ impl<'tcx> GraphExt<'tcx> for Graph {
         self.children.entry(parent).or_default().insert_blindly(tcx, child);
     }
 }
+
+/// Locate the definition of an associated type in the specialization hierarchy,
+/// starting from the given impl.
+pub(crate) fn assoc_def(
+    tcx: TyCtxt<'_>,
+    impl_def_id: DefId,
+    assoc_def_id: DefId,
+) -> Result<LeafDef, ErrorGuaranteed> {
+    let trait_def_id = tcx.impl_trait_ref(impl_def_id).unwrap().def_id;
+    let trait_def = tcx.trait_def(trait_def_id);
+
+    // This function may be called while we are still building the
+    // specialization graph that is queried below (via TraitDef::ancestors()),
+    // so, in order to avoid unnecessary infinite recursion, we manually look
+    // for the associated item at the given impl.
+    // If there is no such item in that impl, this function will fail with a
+    // cycle error if the specialization graph is currently being built.
+    if let Some(&impl_item_id) = tcx.impl_item_implementor_ids(impl_def_id).get(&assoc_def_id) {
+        let &item = tcx.associated_item(impl_item_id);
+        let impl_node = Node::Impl(impl_def_id);
+        return Ok(LeafDef {
+            item,
+            defining_node: impl_node,
+            finalizing_node: if item.defaultness(tcx).is_default() {
+                None
+            } else {
+                Some(impl_node)
+            },
+        });
+    }
+
+    let ancestors = trait_def.ancestors(tcx, impl_def_id)?;
+    if let Some(assoc_item) = ancestors.leaf_def(tcx, assoc_def_id) {
+        Ok(assoc_item)
+    } else {
+        // This is saying that neither the trait nor
+        // the impl contain a definition for this
+        // associated type.  Normally this situation
+        // could only arise through a compiler bug --
+        // if the user wrote a bad item name, it
+        // should have failed in astconv.
+        bug!(
+            "No associated type `{}` for {}",
+            tcx.item_name(assoc_def_id),
+            tcx.def_path_str(impl_def_id)
+        )
+    }
+}
diff --git a/compiler/rustc_trait_selection/src/traits/util.rs b/compiler/rustc_trait_selection/src/traits/util.rs
index f3ca6a6c779..b5df583e3f4 100644
--- a/compiler/rustc_trait_selection/src/traits/util.rs
+++ b/compiler/rustc_trait_selection/src/traits/util.rs
@@ -1,6 +1,5 @@
 use rustc_errors::Diagnostic;
 use rustc_span::Span;
-use smallvec::smallvec;
 use smallvec::SmallVec;
 
 use rustc_data_structures::fx::FxHashSet;
diff --git a/compiler/rustc_trait_selection/src/traits/vtable.rs b/compiler/rustc_trait_selection/src/traits/vtable.rs
index 41ce6cdf789..5ec9c2a24cd 100644
--- a/compiler/rustc_trait_selection/src/traits/vtable.rs
+++ b/compiler/rustc_trait_selection/src/traits/vtable.rs
@@ -191,7 +191,7 @@ fn dump_vtable_entries<'tcx>(
     });
 }
 
-fn own_existential_vtable_entries<'tcx>(tcx: TyCtxt<'tcx>, trait_def_id: DefId) -> &'tcx [DefId] {
+fn own_existential_vtable_entries(tcx: TyCtxt<'_>, trait_def_id: DefId) -> &[DefId] {
     let trait_methods = tcx
         .associated_items(trait_def_id)
         .in_definition_order()
diff --git a/compiler/rustc_traits/src/chalk/db.rs b/compiler/rustc_traits/src/chalk/db.rs
index bc4a52c5040..f288eb11258 100644
--- a/compiler/rustc_traits/src/chalk/db.rs
+++ b/compiler/rustc_traits/src/chalk/db.rs
@@ -719,7 +719,7 @@ impl<'tcx> chalk_ir::UnificationDatabase<RustInterner<'tcx>> for RustIrDatabase<
 /// var bound at index `0`. For types, we use a `BoundVar` index equal to
 /// the type parameter index. For regions, we use the `BoundRegionKind::BrNamed`
 /// variant (which has a `DefId`).
-fn bound_vars_for_item<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> SubstsRef<'tcx> {
+fn bound_vars_for_item(tcx: TyCtxt<'_>, def_id: DefId) -> SubstsRef<'_> {
     InternalSubsts::for_item(tcx, def_id, |param, substs| match param.kind {
         ty::GenericParamDefKind::Type { .. } => tcx
             .mk_ty(ty::Bound(
diff --git a/compiler/rustc_traits/src/normalize_erasing_regions.rs b/compiler/rustc_traits/src/normalize_erasing_regions.rs
index 44fd8bfb31f..6e6bc62a040 100644
--- a/compiler/rustc_traits/src/normalize_erasing_regions.rs
+++ b/compiler/rustc_traits/src/normalize_erasing_regions.rs
@@ -54,7 +54,7 @@ fn try_normalize_after_erasing_regions<'tcx, T: TypeFoldable<'tcx> + PartialEq +
     }
 }
 
-fn not_outlives_predicate<'tcx>(p: ty::Predicate<'tcx>) -> bool {
+fn not_outlives_predicate(p: ty::Predicate<'_>) -> bool {
     match p.kind().skip_binder() {
         ty::PredicateKind::Clause(ty::Clause::RegionOutlives(..))
         | ty::PredicateKind::Clause(ty::Clause::TypeOutlives(..)) => false,
diff --git a/compiler/rustc_ty_utils/src/consts.rs b/compiler/rustc_ty_utils/src/consts.rs
index f8ff31f971b..a9b4e1420ea 100644
--- a/compiler/rustc_ty_utils/src/consts.rs
+++ b/compiler/rustc_ty_utils/src/consts.rs
@@ -267,8 +267,8 @@ struct IsThirPolymorphic<'a, 'tcx> {
     thir: &'a thir::Thir<'tcx>,
 }
 
-fn error<'tcx>(
-    tcx: TyCtxt<'tcx>,
+fn error(
+    tcx: TyCtxt<'_>,
     sub: GenericConstantTooComplexSub,
     root_span: Span,
 ) -> Result<!, ErrorGuaranteed> {
@@ -281,8 +281,8 @@ fn error<'tcx>(
     Err(reported)
 }
 
-fn maybe_supported_error<'tcx>(
-    tcx: TyCtxt<'tcx>,
+fn maybe_supported_error(
+    tcx: TyCtxt<'_>,
     sub: GenericConstantTooComplexSub,
     root_span: Span,
 ) -> Result<!, ErrorGuaranteed> {
@@ -349,10 +349,10 @@ impl<'a, 'tcx> visit::Visitor<'a, 'tcx> for IsThirPolymorphic<'a, 'tcx> {
 }
 
 /// Builds an abstract const, do not use this directly, but use `AbstractConst::new` instead.
-pub fn thir_abstract_const<'tcx>(
-    tcx: TyCtxt<'tcx>,
+pub fn thir_abstract_const(
+    tcx: TyCtxt<'_>,
     def: ty::WithOptConstParam<LocalDefId>,
-) -> Result<Option<ty::Const<'tcx>>, ErrorGuaranteed> {
+) -> Result<Option<ty::Const<'_>>, ErrorGuaranteed> {
     if tcx.features().generic_const_exprs {
         match tcx.def_kind(def.did) {
             // FIXME(generic_const_exprs): We currently only do this for anonymous constants,
diff --git a/compiler/rustc_ty_utils/src/implied_bounds.rs b/compiler/rustc_ty_utils/src/implied_bounds.rs
index f0d8c240ea5..b7a24a22c53 100644
--- a/compiler/rustc_ty_utils/src/implied_bounds.rs
+++ b/compiler/rustc_ty_utils/src/implied_bounds.rs
@@ -6,7 +6,7 @@ pub fn provide(providers: &mut ty::query::Providers) {
     *providers = ty::query::Providers { assumed_wf_types, ..*providers };
 }
 
-fn assumed_wf_types<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> &'tcx ty::List<Ty<'tcx>> {
+fn assumed_wf_types(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::List<Ty<'_>> {
     match tcx.def_kind(def_id) {
         DefKind::Fn => {
             let sig = tcx.fn_sig(def_id);
diff --git a/compiler/rustc_ty_utils/src/instance.rs b/compiler/rustc_ty_utils/src/instance.rs
index 2da98d33429..8d46ba320fc 100644
--- a/compiler/rustc_ty_utils/src/instance.rs
+++ b/compiler/rustc_ty_utils/src/instance.rs
@@ -194,7 +194,7 @@ fn resolve_associated_item<'tcx>(
                 && trait_item_id != leaf_def.item.def_id
                 && let Some(leaf_def_item) = leaf_def.item.def_id.as_local()
             {
-                tcx.compare_assoc_const_impl_item_with_trait_item((
+                tcx.compare_impl_const((
                     leaf_def_item,
                     trait_item_id,
                 ))?;
diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs
index c761a4dbe45..c8c6acaa453 100644
--- a/compiler/rustc_ty_utils/src/layout.rs
+++ b/compiler/rustc_ty_utils/src/layout.rs
@@ -489,8 +489,8 @@ enum SavedLocalEligibility {
 // of any variant.
 
 /// Compute the eligibility and assignment of each local.
-fn generator_saved_local_eligibility<'tcx>(
-    info: &GeneratorLayout<'tcx>,
+fn generator_saved_local_eligibility(
+    info: &GeneratorLayout<'_>,
 ) -> (BitSet<GeneratorSavedLocal>, IndexVec<GeneratorSavedLocal, SavedLocalEligibility>) {
     use SavedLocalEligibility::*;
 
diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs
index 5279fc69a31..e2d10f550c3 100644
--- a/compiler/rustc_ty_utils/src/ty.rs
+++ b/compiler/rustc_ty_utils/src/ty.rs
@@ -225,10 +225,7 @@ fn param_env(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamEnv<'_> {
 /// that are assumed to be well-formed (because they come from the environment).
 ///
 /// Used only in chalk mode.
-fn well_formed_types_in_env<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    def_id: DefId,
-) -> &'tcx ty::List<Predicate<'tcx>> {
+fn well_formed_types_in_env(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::List<Predicate<'_>> {
     use rustc_hir::{ForeignItemKind, ImplItemKind, ItemKind, Node, TraitItemKind};
     use rustc_middle::ty::subst::GenericArgKind;
 
diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs
index b154688fb08..b5fe8d72f7d 100644
--- a/library/alloc/src/boxed.rs
+++ b/library/alloc/src/boxed.rs
@@ -954,7 +954,7 @@ impl<T: ?Sized> Box<T> {
     /// [`Layout`]: crate::Layout
     #[stable(feature = "box_raw", since = "1.4.0")]
     #[inline]
-    #[must_use = "call `drop(from_raw(ptr))` if you intend to drop the `Box`"]
+    #[must_use = "call `drop(Box::from_raw(ptr))` if you intend to drop the `Box`"]
     pub unsafe fn from_raw(raw: *mut T) -> Self {
         unsafe { Self::from_raw_in(raw, Global) }
     }
diff --git a/library/alloc/src/collections/binary_heap/tests.rs b/library/alloc/src/collections/binary_heap/tests.rs
index 5a05215aeed..fe08e0e10e8 100644
--- a/library/alloc/src/collections/binary_heap/tests.rs
+++ b/library/alloc/src/collections/binary_heap/tests.rs
@@ -1,8 +1,8 @@
 use super::*;
 use crate::boxed::Box;
+use crate::testing::crash_test::{CrashTestDummy, Panic};
 use std::iter::TrustedLen;
 use std::panic::{catch_unwind, AssertUnwindSafe};
-use std::sync::atomic::{AtomicU32, Ordering};
 
 #[test]
 fn test_iterator() {
@@ -291,33 +291,83 @@ fn test_drain_sorted() {
 
 #[test]
 fn test_drain_sorted_leak() {
-    static DROPS: AtomicU32 = AtomicU32::new(0);
-
-    #[derive(Clone, PartialEq, Eq, PartialOrd, Ord)]
-    struct D(u32, bool);
-
-    impl Drop for D {
-        fn drop(&mut self) {
-            DROPS.fetch_add(1, Ordering::SeqCst);
-
-            if self.1 {
-                panic!("panic in `drop`");
-            }
-        }
-    }
-
+    let d0 = CrashTestDummy::new(0);
+    let d1 = CrashTestDummy::new(1);
+    let d2 = CrashTestDummy::new(2);
+    let d3 = CrashTestDummy::new(3);
+    let d4 = CrashTestDummy::new(4);
+    let d5 = CrashTestDummy::new(5);
     let mut q = BinaryHeap::from(vec![
-        D(0, false),
-        D(1, false),
-        D(2, false),
-        D(3, true),
-        D(4, false),
-        D(5, false),
+        d0.spawn(Panic::Never),
+        d1.spawn(Panic::Never),
+        d2.spawn(Panic::Never),
+        d3.spawn(Panic::InDrop),
+        d4.spawn(Panic::Never),
+        d5.spawn(Panic::Never),
     ]);
 
-    catch_unwind(AssertUnwindSafe(|| drop(q.drain_sorted()))).ok();
+    catch_unwind(AssertUnwindSafe(|| drop(q.drain_sorted()))).unwrap_err();
+
+    assert_eq!(d0.dropped(), 1);
+    assert_eq!(d1.dropped(), 1);
+    assert_eq!(d2.dropped(), 1);
+    assert_eq!(d3.dropped(), 1);
+    assert_eq!(d4.dropped(), 1);
+    assert_eq!(d5.dropped(), 1);
+    assert!(q.is_empty());
+}
 
-    assert_eq!(DROPS.load(Ordering::SeqCst), 6);
+#[test]
+fn test_drain_forget() {
+    let a = CrashTestDummy::new(0);
+    let b = CrashTestDummy::new(1);
+    let c = CrashTestDummy::new(2);
+    let mut q =
+        BinaryHeap::from(vec![a.spawn(Panic::Never), b.spawn(Panic::Never), c.spawn(Panic::Never)]);
+
+    catch_unwind(AssertUnwindSafe(|| {
+        let mut it = q.drain();
+        it.next();
+        mem::forget(it);
+    }))
+    .unwrap();
+    // Behaviour after leaking is explicitly unspecified and order is arbitrary,
+    // so it's fine if these start failing, but probably worth knowing.
+    assert!(q.is_empty());
+    assert_eq!(a.dropped() + b.dropped() + c.dropped(), 1);
+    assert_eq!(a.dropped(), 0);
+    assert_eq!(b.dropped(), 0);
+    assert_eq!(c.dropped(), 1);
+    drop(q);
+    assert_eq!(a.dropped(), 0);
+    assert_eq!(b.dropped(), 0);
+    assert_eq!(c.dropped(), 1);
+}
+
+#[test]
+fn test_drain_sorted_forget() {
+    let a = CrashTestDummy::new(0);
+    let b = CrashTestDummy::new(1);
+    let c = CrashTestDummy::new(2);
+    let mut q =
+        BinaryHeap::from(vec![a.spawn(Panic::Never), b.spawn(Panic::Never), c.spawn(Panic::Never)]);
+
+    catch_unwind(AssertUnwindSafe(|| {
+        let mut it = q.drain_sorted();
+        it.next();
+        mem::forget(it);
+    }))
+    .unwrap();
+    // Behaviour after leaking is explicitly unspecified,
+    // so it's fine if these start failing, but probably worth knowing.
+    assert_eq!(q.len(), 2);
+    assert_eq!(a.dropped(), 0);
+    assert_eq!(b.dropped(), 0);
+    assert_eq!(c.dropped(), 1);
+    drop(q);
+    assert_eq!(a.dropped(), 1);
+    assert_eq!(b.dropped(), 1);
+    assert_eq!(c.dropped(), 1);
 }
 
 #[test]
diff --git a/library/alloc/src/collections/btree/map/tests.rs b/library/alloc/src/collections/btree/map/tests.rs
index 4c372b1d60a..700b1463bfd 100644
--- a/library/alloc/src/collections/btree/map/tests.rs
+++ b/library/alloc/src/collections/btree/map/tests.rs
@@ -1,12 +1,12 @@
-use super::super::testing::crash_test::{CrashTestDummy, Panic};
-use super::super::testing::ord_chaos::{Cyclic3, Governed, Governor};
-use super::super::testing::rng::DeterministicRng;
 use super::Entry::{Occupied, Vacant};
 use super::*;
 use crate::boxed::Box;
 use crate::fmt::Debug;
 use crate::rc::Rc;
 use crate::string::{String, ToString};
+use crate::testing::crash_test::{CrashTestDummy, Panic};
+use crate::testing::ord_chaos::{Cyclic3, Governed, Governor};
+use crate::testing::rng::DeterministicRng;
 use crate::vec::Vec;
 use std::cmp::Ordering;
 use std::convert::TryFrom;
diff --git a/library/alloc/src/collections/btree/mod.rs b/library/alloc/src/collections/btree/mod.rs
index 9d43ac5c5be..7552f2fc04c 100644
--- a/library/alloc/src/collections/btree/mod.rs
+++ b/library/alloc/src/collections/btree/mod.rs
@@ -21,6 +21,3 @@ trait Recover<Q: ?Sized> {
     fn take(&mut self, key: &Q) -> Option<Self::Key>;
     fn replace(&mut self, key: Self::Key) -> Option<Self::Key>;
 }
-
-#[cfg(test)]
-mod testing;
diff --git a/library/alloc/src/collections/btree/set/tests.rs b/library/alloc/src/collections/btree/set/tests.rs
index 502d3e1d126..7b8d41a6031 100644
--- a/library/alloc/src/collections/btree/set/tests.rs
+++ b/library/alloc/src/collections/btree/set/tests.rs
@@ -1,6 +1,6 @@
-use super::super::testing::crash_test::{CrashTestDummy, Panic};
-use super::super::testing::rng::DeterministicRng;
 use super::*;
+use crate::testing::crash_test::{CrashTestDummy, Panic};
+use crate::testing::rng::DeterministicRng;
 use crate::vec::Vec;
 use std::cmp::Ordering;
 use std::hash::{Hash, Hasher};
diff --git a/library/alloc/src/collections/linked_list/tests.rs b/library/alloc/src/collections/linked_list/tests.rs
index f8fbfa1bfbc..5d5af22bb29 100644
--- a/library/alloc/src/collections/linked_list/tests.rs
+++ b/library/alloc/src/collections/linked_list/tests.rs
@@ -1,4 +1,5 @@
 use super::*;
+use crate::testing::crash_test::{CrashTestDummy, Panic};
 use crate::vec::Vec;
 
 use std::panic::{catch_unwind, AssertUnwindSafe};
@@ -984,35 +985,34 @@ fn drain_filter_complex() {
 
 #[test]
 fn drain_filter_drop_panic_leak() {
-    static mut DROPS: i32 = 0;
-
-    struct D(bool);
-
-    impl Drop for D {
-        fn drop(&mut self) {
-            unsafe {
-                DROPS += 1;
-            }
-
-            if self.0 {
-                panic!("panic in `drop`");
-            }
-        }
-    }
-
+    let d0 = CrashTestDummy::new(0);
+    let d1 = CrashTestDummy::new(1);
+    let d2 = CrashTestDummy::new(2);
+    let d3 = CrashTestDummy::new(3);
+    let d4 = CrashTestDummy::new(4);
+    let d5 = CrashTestDummy::new(5);
+    let d6 = CrashTestDummy::new(6);
+    let d7 = CrashTestDummy::new(7);
     let mut q = LinkedList::new();
-    q.push_back(D(false));
-    q.push_back(D(false));
-    q.push_back(D(false));
-    q.push_back(D(false));
-    q.push_back(D(false));
-    q.push_front(D(false));
-    q.push_front(D(true));
-    q.push_front(D(false));
-
-    catch_unwind(AssertUnwindSafe(|| drop(q.drain_filter(|_| true)))).ok();
-
-    assert_eq!(unsafe { DROPS }, 8);
+    q.push_back(d3.spawn(Panic::Never));
+    q.push_back(d4.spawn(Panic::Never));
+    q.push_back(d5.spawn(Panic::Never));
+    q.push_back(d6.spawn(Panic::Never));
+    q.push_back(d7.spawn(Panic::Never));
+    q.push_front(d2.spawn(Panic::Never));
+    q.push_front(d1.spawn(Panic::InDrop));
+    q.push_front(d0.spawn(Panic::Never));
+
+    catch_unwind(AssertUnwindSafe(|| drop(q.drain_filter(|_| true)))).unwrap_err();
+
+    assert_eq!(d0.dropped(), 1);
+    assert_eq!(d1.dropped(), 1);
+    assert_eq!(d2.dropped(), 1);
+    assert_eq!(d3.dropped(), 1);
+    assert_eq!(d4.dropped(), 1);
+    assert_eq!(d5.dropped(), 1);
+    assert_eq!(d6.dropped(), 1);
+    assert_eq!(d7.dropped(), 1);
     assert!(q.is_empty());
 }
 
diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs
index 96960d43f58..fb1664ba7a2 100644
--- a/library/alloc/src/lib.rs
+++ b/library/alloc/src/lib.rs
@@ -87,6 +87,7 @@
 #![warn(missing_debug_implementations)]
 #![warn(missing_docs)]
 #![allow(explicit_outlives_requirements)]
+#![cfg_attr(not(bootstrap), warn(multiple_supertrait_upcastable))]
 //
 // Library features:
 #![feature(alloc_layout_extra)]
@@ -190,6 +191,7 @@
 #![feature(unsized_fn_params)]
 #![feature(c_unwind)]
 #![feature(with_negative_coherence)]
+#![cfg_attr(not(bootstrap), feature(multiple_supertrait_upcastable))]
 //
 // Rustdoc features:
 #![feature(doc_cfg)]
@@ -206,6 +208,8 @@
 extern crate std;
 #[cfg(test)]
 extern crate test;
+#[cfg(test)]
+mod testing;
 
 // Module with internal macros used by other modules (needs to be included before other modules).
 #[macro_use]
diff --git a/library/alloc/src/collections/btree/testing/crash_test.rs b/library/alloc/src/testing/crash_test.rs
index bcf5f5f7251..bcf5f5f7251 100644
--- a/library/alloc/src/collections/btree/testing/crash_test.rs
+++ b/library/alloc/src/testing/crash_test.rs
diff --git a/library/alloc/src/collections/btree/testing/mod.rs b/library/alloc/src/testing/mod.rs
index 7a094f8a595..7a094f8a595 100644
--- a/library/alloc/src/collections/btree/testing/mod.rs
+++ b/library/alloc/src/testing/mod.rs
diff --git a/library/alloc/src/collections/btree/testing/ord_chaos.rs b/library/alloc/src/testing/ord_chaos.rs
index 96ce7c15790..96ce7c15790 100644
--- a/library/alloc/src/collections/btree/testing/ord_chaos.rs
+++ b/library/alloc/src/testing/ord_chaos.rs
diff --git a/library/alloc/src/collections/btree/testing/rng.rs b/library/alloc/src/testing/rng.rs
index ecf543bee03..ecf543bee03 100644
--- a/library/alloc/src/collections/btree/testing/rng.rs
+++ b/library/alloc/src/testing/rng.rs
diff --git a/library/alloc/src/vec/into_iter.rs b/library/alloc/src/vec/into_iter.rs
index 6bcde6d899c..b207b3210f1 100644
--- a/library/alloc/src/vec/into_iter.rs
+++ b/library/alloc/src/vec/into_iter.rs
@@ -40,7 +40,9 @@ pub struct IntoIter<
     // to avoid dropping the allocator twice we need to wrap it into ManuallyDrop
     pub(super) alloc: ManuallyDrop<A>,
     pub(super) ptr: *const T,
-    pub(super) end: *const T,
+    pub(super) end: *const T, // If T is a ZST, this is actually ptr+len.  This encoding is picked so that
+                              // ptr == end is a quick test for the Iterator being empty, that works
+                              // for both ZST and non-ZST.
 }
 
 #[stable(feature = "vec_intoiter_debug", since = "1.13.0")]
@@ -132,7 +134,9 @@ impl<T, A: Allocator> IntoIter<T, A> {
 
     /// Forgets to Drop the remaining elements while still allowing the backing allocation to be freed.
     pub(crate) fn forget_remaining_elements(&mut self) {
-        self.ptr = self.end;
+        // For th ZST case, it is crucial that we mutate `end` here, not `ptr`.
+        // `ptr` must stay aligned, while `end` may be unaligned.
+        self.end = self.ptr;
     }
 
     #[cfg(not(no_global_oom_handling))]
@@ -184,10 +188,9 @@ impl<T, A: Allocator> Iterator for IntoIter<T, A> {
         if self.ptr == self.end {
             None
         } else if T::IS_ZST {
-            // purposefully don't use 'ptr.offset' because for
-            // vectors with 0-size elements this would return the
-            // same pointer.
-            self.ptr = self.ptr.wrapping_byte_add(1);
+            // `ptr` has to stay where it is to remain aligned, so we reduce the length by 1 by
+            // reducing the `end`.
+            self.end = self.end.wrapping_byte_sub(1);
 
             // Make up a value of this ZST.
             Some(unsafe { mem::zeroed() })
@@ -214,10 +217,8 @@ impl<T, A: Allocator> Iterator for IntoIter<T, A> {
         let step_size = self.len().min(n);
         let to_drop = ptr::slice_from_raw_parts_mut(self.ptr as *mut T, step_size);
         if T::IS_ZST {
-            // SAFETY: due to unchecked casts of unsigned amounts to signed offsets the wraparound
-            // effectively results in unsigned pointers representing positions 0..usize::MAX,
-            // which is valid for ZSTs.
-            self.ptr = self.ptr.wrapping_byte_add(step_size);
+            // See `next` for why we sub `end` here.
+            self.end = self.end.wrapping_byte_sub(step_size);
         } else {
             // SAFETY: the min() above ensures that step_size is in bounds
             self.ptr = unsafe { self.ptr.add(step_size) };
@@ -250,7 +251,7 @@ impl<T, A: Allocator> Iterator for IntoIter<T, A> {
                 return Err(unsafe { array::IntoIter::new_unchecked(raw_ary, 0..len) });
             }
 
-            self.ptr = self.ptr.wrapping_byte_add(N);
+            self.end = self.end.wrapping_byte_sub(N);
             // Safety: ditto
             return Ok(unsafe { raw_ary.transpose().assume_init() });
         }
diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs
index ba34ab6800f..1028bb981b9 100644
--- a/library/alloc/src/vec/mod.rs
+++ b/library/alloc/src/vec/mod.rs
@@ -166,7 +166,7 @@ mod spec_extend;
 /// vec[0] = 7;
 /// assert_eq!(vec[0], 7);
 ///
-/// vec.extend([1, 2, 3].iter().copied());
+/// vec.extend([1, 2, 3]);
 ///
 /// for x in &vec {
 ///     println!("{x}");
diff --git a/library/alloc/tests/vec.rs b/library/alloc/tests/vec.rs
index 7ebed0d5ca6..87adcead8f6 100644
--- a/library/alloc/tests/vec.rs
+++ b/library/alloc/tests/vec.rs
@@ -7,7 +7,9 @@ use std::borrow::Cow;
 use std::cell::Cell;
 use std::collections::TryReserveErrorKind::*;
 use std::fmt::Debug;
+use std::hint;
 use std::iter::InPlaceIterable;
+use std::mem;
 use std::mem::{size_of, swap};
 use std::ops::Bound::*;
 use std::panic::{catch_unwind, AssertUnwindSafe};
@@ -1107,8 +1109,31 @@ fn test_into_iter_drop_allocator() {
 
 #[test]
 fn test_into_iter_zst() {
-    for _ in vec![[0u64; 0]].into_iter() {}
-    for _ in vec![[0u64; 0]; 5].into_iter().rev() {}
+    #[derive(Debug, Clone)]
+    struct AlignedZstWithDrop([u64; 0]);
+    impl Drop for AlignedZstWithDrop {
+        fn drop(&mut self) {
+            let addr = self as *mut _ as usize;
+            assert!(hint::black_box(addr) % mem::align_of::<u64>() == 0);
+        }
+    }
+
+    const C: AlignedZstWithDrop = AlignedZstWithDrop([0u64; 0]);
+
+    for _ in vec![C].into_iter() {}
+    for _ in vec![C; 5].into_iter().rev() {}
+
+    let mut it = vec![C, C].into_iter();
+    it.advance_by(1).unwrap();
+    drop(it);
+
+    let mut it = vec![C, C].into_iter();
+    it.next_chunk::<1>().unwrap();
+    drop(it);
+
+    let mut it = vec![C, C].into_iter();
+    it.next_chunk::<4>().unwrap_err();
+    drop(it);
 }
 
 #[test]
diff --git a/library/core/src/any.rs b/library/core/src/any.rs
index 1a379ecc11c..9ca4947ed8f 100644
--- a/library/core/src/any.rs
+++ b/library/core/src/any.rs
@@ -148,7 +148,7 @@
 //! ```
 //!
 //! In this example, if the concrete type of `obj` in `use_my_trait` is `SomeConcreteType`, then
-//! the `get_context_ref` call will return a reference to `obj.some_string` with type `&String`.
+//! the `get_context_by_ref` call will return a reference to `obj.some_string` with type `&String`.
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs
index b4e173ce03d..77f1ffaacff 100644
--- a/library/core/src/cell.rs
+++ b/library/core/src/cell.rs
@@ -807,7 +807,8 @@ impl<T> RefCell<T> {
     ///
     /// # Panics
     ///
-    /// Panics if the value in either `RefCell` is currently borrowed.
+    /// Panics if the value in either `RefCell` is currently borrowed, or
+    /// if `self` and `other` point to the same `RefCell`.
     ///
     /// # Examples
     ///
@@ -1193,7 +1194,7 @@ impl<T: Default> Default for RefCell<T> {
 impl<T: ?Sized + PartialEq> PartialEq for RefCell<T> {
     /// # Panics
     ///
-    /// Panics if the value in either `RefCell` is currently borrowed.
+    /// Panics if the value in either `RefCell` is currently mutably borrowed.
     #[inline]
     fn eq(&self, other: &RefCell<T>) -> bool {
         *self.borrow() == *other.borrow()
@@ -1207,7 +1208,7 @@ impl<T: ?Sized + Eq> Eq for RefCell<T> {}
 impl<T: ?Sized + PartialOrd> PartialOrd for RefCell<T> {
     /// # Panics
     ///
-    /// Panics if the value in either `RefCell` is currently borrowed.
+    /// Panics if the value in either `RefCell` is currently mutably borrowed.
     #[inline]
     fn partial_cmp(&self, other: &RefCell<T>) -> Option<Ordering> {
         self.borrow().partial_cmp(&*other.borrow())
@@ -1215,7 +1216,7 @@ impl<T: ?Sized + PartialOrd> PartialOrd for RefCell<T> {
 
     /// # Panics
     ///
-    /// Panics if the value in either `RefCell` is currently borrowed.
+    /// Panics if the value in either `RefCell` is currently mutably borrowed.
     #[inline]
     fn lt(&self, other: &RefCell<T>) -> bool {
         *self.borrow() < *other.borrow()
@@ -1223,7 +1224,7 @@ impl<T: ?Sized + PartialOrd> PartialOrd for RefCell<T> {
 
     /// # Panics
     ///
-    /// Panics if the value in either `RefCell` is currently borrowed.
+    /// Panics if the value in either `RefCell` is currently mutably borrowed.
     #[inline]
     fn le(&self, other: &RefCell<T>) -> bool {
         *self.borrow() <= *other.borrow()
@@ -1231,7 +1232,7 @@ impl<T: ?Sized + PartialOrd> PartialOrd for RefCell<T> {
 
     /// # Panics
     ///
-    /// Panics if the value in either `RefCell` is currently borrowed.
+    /// Panics if the value in either `RefCell` is currently mutably borrowed.
     #[inline]
     fn gt(&self, other: &RefCell<T>) -> bool {
         *self.borrow() > *other.borrow()
@@ -1239,7 +1240,7 @@ impl<T: ?Sized + PartialOrd> PartialOrd for RefCell<T> {
 
     /// # Panics
     ///
-    /// Panics if the value in either `RefCell` is currently borrowed.
+    /// Panics if the value in either `RefCell` is currently mutably borrowed.
     #[inline]
     fn ge(&self, other: &RefCell<T>) -> bool {
         *self.borrow() >= *other.borrow()
@@ -1250,7 +1251,7 @@ impl<T: ?Sized + PartialOrd> PartialOrd for RefCell<T> {
 impl<T: ?Sized + Ord> Ord for RefCell<T> {
     /// # Panics
     ///
-    /// Panics if the value in either `RefCell` is currently borrowed.
+    /// Panics if the value in either `RefCell` is currently mutably borrowed.
     #[inline]
     fn cmp(&self, other: &RefCell<T>) -> Ordering {
         self.borrow().cmp(&*other.borrow())
@@ -1783,7 +1784,7 @@ impl<T: ?Sized + fmt::Display> fmt::Display for RefMut<'_, T> {
 /// until the reference expires. As a special exception, given an `&T`, any part of it that is
 /// inside an `UnsafeCell<_>` may be deallocated during the lifetime of the reference, after the
 /// last time the reference is used (dereferenced or reborrowed). Since you cannot deallocate a part
-/// of what a reference points to, this means the memory an `&T` points to can be deallocted only if
+/// of what a reference points to, this means the memory an `&T` points to can be deallocated only if
 /// *every part of it* (including padding) is inside an `UnsafeCell`.
 ///
 ///     However, whenever a `&UnsafeCell<T>` is constructed or dereferenced, it must still point to
diff --git a/library/core/src/cell/lazy.rs b/library/core/src/cell/lazy.rs
index b355d94ce49..19f80daef1d 100644
--- a/library/core/src/cell/lazy.rs
+++ b/library/core/src/cell/lazy.rs
@@ -35,7 +35,7 @@ pub struct LazyCell<T, F = fn() -> T> {
     init: Cell<Option<F>>,
 }
 
-impl<T, F> LazyCell<T, F> {
+impl<T, F: FnOnce() -> T> LazyCell<T, F> {
     /// Creates a new lazy value with the given initializing function.
     ///
     /// # Examples
@@ -55,9 +55,7 @@ impl<T, F> LazyCell<T, F> {
     pub const fn new(init: F) -> LazyCell<T, F> {
         LazyCell { cell: OnceCell::new(), init: Cell::new(Some(init)) }
     }
-}
 
-impl<T, F: FnOnce() -> T> LazyCell<T, F> {
     /// Forces the evaluation of this lazy value and returns a reference to
     /// the result.
     ///
diff --git a/library/core/src/char/decode.rs b/library/core/src/char/decode.rs
index 11f1c30f6d5..eeb08803040 100644
--- a/library/core/src/char/decode.rs
+++ b/library/core/src/char/decode.rs
@@ -67,7 +67,7 @@ impl<I: Iterator<Item = u16>> Iterator for DecodeUtf16<I> {
             }
 
             // all ok, so lets decode it.
-            let c = (((u - 0xD800) as u32) << 10 | (u2 - 0xDC00) as u32) + 0x1_0000;
+            let c = (((u & 0x3ff) as u32) << 10 | (u2 & 0x3ff) as u32) + 0x1_0000;
             // SAFETY: we checked that it's a legal unicode value
             Some(Ok(unsafe { from_u32_unchecked(c) }))
         }
diff --git a/library/core/src/const_closure.rs b/library/core/src/const_closure.rs
index 151c8e6d898..920c31233c1 100644
--- a/library/core/src/const_closure.rs
+++ b/library/core/src/const_closure.rs
@@ -51,7 +51,7 @@ macro_rules! impl_fn_mut_tuple {
         impl<'a, $($var,)* ClosureArguments, Function, ClosureReturnValue> const
             FnOnce<ClosureArguments> for ConstFnMutClosure<($(&'a mut $var),*), Function>
         where
-            Function: ~const Fn(($(&mut $var),*), ClosureArguments) -> ClosureReturnValue+ ~const Destruct,
+            Function: ~const Fn(($(&mut $var),*), ClosureArguments) -> ClosureReturnValue + ~const Destruct,
         {
             type Output = ClosureReturnValue;
 
@@ -64,7 +64,7 @@ macro_rules! impl_fn_mut_tuple {
         impl<'a, $($var,)* ClosureArguments, Function, ClosureReturnValue> const
             FnMut<ClosureArguments> for ConstFnMutClosure<($(&'a mut $var),*), Function>
         where
-            Function: ~const Fn(($(&mut $var),*), ClosureArguments)-> ClosureReturnValue,
+            Function: ~const Fn(($(&mut $var),*), ClosureArguments)-> ClosureReturnValue + ~const Destruct,
         {
             extern "rust-call" fn call_mut(&mut self, args: ClosureArguments) -> Self::Output {
                 #[allow(non_snake_case)]
diff --git a/library/core/src/convert/num.rs b/library/core/src/convert/num.rs
index 9c0d7e9a1e8..45e2f711c6c 100644
--- a/library/core/src/convert/num.rs
+++ b/library/core/src/convert/num.rs
@@ -168,6 +168,26 @@ impl_from! { u32, f64, #[stable(feature = "lossless_float_conv", since = "1.6.0"
 // Float -> Float
 impl_from! { f32, f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")] }
 
+// bool -> Float
+#[stable(feature = "float_from_bool", since = "CURRENT_RUSTC_VERSION")]
+#[rustc_const_unstable(feature = "const_num_from_num", issue = "87852")]
+impl const From<bool> for f32 {
+    /// Converts `bool` to `f32` losslessly.
+    #[inline]
+    fn from(small: bool) -> Self {
+        small as u8 as Self
+    }
+}
+#[stable(feature = "float_from_bool", since = "CURRENT_RUSTC_VERSION")]
+#[rustc_const_unstable(feature = "const_num_from_num", issue = "87852")]
+impl const From<bool> for f64 {
+    /// Converts `bool` to `f64` losslessly.
+    #[inline]
+    fn from(small: bool) -> Self {
+        small as u8 as Self
+    }
+}
+
 // no possible bounds violation
 macro_rules! try_from_unbounded {
     ($source:ty, $($target:ty),*) => {$(
diff --git a/library/core/src/error.rs b/library/core/src/error.rs
index 7152300abcb..d2fac23ff18 100644
--- a/library/core/src/error.rs
+++ b/library/core/src/error.rs
@@ -28,6 +28,7 @@ use crate::fmt::{Debug, Display};
 #[stable(feature = "rust1", since = "1.0.0")]
 #[cfg_attr(not(test), rustc_diagnostic_item = "Error")]
 #[rustc_has_incoherent_inherent_impls]
+#[cfg_attr(not(bootstrap), allow(multiple_supertrait_upcastable))]
 pub trait Error: Debug + Display {
     /// The lower-level source of this error, if any.
     ///
diff --git a/library/core/src/hash/mod.rs b/library/core/src/hash/mod.rs
index c755afa39eb..71a0d1825ef 100644
--- a/library/core/src/hash/mod.rs
+++ b/library/core/src/hash/mod.rs
@@ -199,7 +199,7 @@ pub trait Hash {
     /// println!("Hash is {:x}!", hasher.finish());
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
-    fn hash<H: Hasher>(&self, state: &mut H);
+    fn hash<H: ~const Hasher>(&self, state: &mut H);
 
     /// Feeds a slice of this type into the given [`Hasher`].
     ///
@@ -980,7 +980,7 @@ mod impls {
     #[rustc_const_unstable(feature = "const_hash", issue = "104061")]
     impl<T: ?Sized + ~const Hash> const Hash for &mut T {
         #[inline]
-        fn hash<H: Hasher>(&self, state: &mut H) {
+        fn hash<H: ~const Hasher>(&self, state: &mut H) {
             (**self).hash(state);
         }
     }
diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs
index 7ed7d767f2f..6eeaef5ab01 100644
--- a/library/core/src/intrinsics.rs
+++ b/library/core/src/intrinsics.rs
@@ -959,13 +959,13 @@ extern "rust-intrinsic" {
     #[rustc_safe_intrinsic]
     pub fn assert_zero_valid<T>();
 
-    /// A guard for unsafe functions that cannot ever be executed if `T` has invalid
-    /// bit patterns: This will statically either panic, or do nothing.
+    /// A guard for `std::mem::uninitialized`. This will statically either panic, or do nothing.
     ///
     /// This intrinsic does not have a stable counterpart.
     #[rustc_const_unstable(feature = "const_assert_type2", issue = "none")]
     #[rustc_safe_intrinsic]
-    pub fn assert_uninit_valid<T>();
+    #[cfg(not(bootstrap))]
+    pub fn assert_mem_uninitialized_valid<T>();
 
     /// Gets a reference to a static `Location` indicating where it was called.
     ///
@@ -2281,7 +2281,7 @@ macro_rules! assert_unsafe_precondition {
             fn runtime$(<$($tt)*>)?($($i:$ty),*) {
                 if !$e {
                     // don't unwind to reduce impact on code size
-                    ::core::panicking::panic_str_nounwind(
+                    ::core::panicking::panic_nounwind(
                         concat!("unsafe precondition(s) violated: ", $name)
                     );
                 }
diff --git a/library/core/src/intrinsics/mir.rs b/library/core/src/intrinsics/mir.rs
index e08a15571fc..9e7099ddfd1 100644
--- a/library/core/src/intrinsics/mir.rs
+++ b/library/core/src/intrinsics/mir.rs
@@ -259,7 +259,6 @@ define!("mir_drop", fn Drop<T>(place: T, goto: BasicBlock));
 define!("mir_drop_and_replace", fn DropAndReplace<T>(place: T, value: T, goto: BasicBlock));
 define!("mir_call", fn Call<T>(place: T, goto: BasicBlock, call: T));
 define!("mir_retag", fn Retag<T>(place: T));
-define!("mir_retag_raw", fn RetagRaw<T>(place: T));
 define!("mir_move", fn Move<T>(place: T) -> T);
 define!("mir_static", fn Static<T>(s: T) -> &'static T);
 define!("mir_static_mut", fn StaticMut<T>(s: T) -> *mut T);
diff --git a/library/core/src/iter/sources/empty.rs b/library/core/src/iter/sources/empty.rs
index 98734c527f2..617dfd12383 100644
--- a/library/core/src/iter/sources/empty.rs
+++ b/library/core/src/iter/sources/empty.rs
@@ -22,17 +22,12 @@ pub const fn empty<T>() -> Empty<T> {
     Empty(marker::PhantomData)
 }
 
-// Newtype for use in `PhantomData` to avoid
-// > error: const-stable function cannot use `#[feature(const_fn_fn_ptr_basics)]`
-// in `const fn empty<T>()` above.
-struct FnReturning<T>(fn() -> T);
-
 /// An iterator that yields nothing.
 ///
 /// This `struct` is created by the [`empty()`] function. See its documentation for more.
 #[must_use = "iterators are lazy and do nothing unless consumed"]
 #[stable(feature = "iter_empty", since = "1.2.0")]
-pub struct Empty<T>(marker::PhantomData<FnReturning<T>>);
+pub struct Empty<T>(marker::PhantomData<fn() -> T>);
 
 #[stable(feature = "core_impl_debug", since = "1.9.0")]
 impl<T> fmt::Debug for Empty<T> {
diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs
index bac836292f8..b4863bb2589 100644
--- a/library/core/src/iter/traits/iterator.rs
+++ b/library/core/src/iter/traits/iterator.rs
@@ -66,6 +66,7 @@ fn _assert_is_object_safe(_: &dyn Iterator<Item = ()>) {}
 #[must_use = "iterators are lazy and do nothing unless consumed"]
 pub trait Iterator {
     /// The type of the elements being iterated over.
+    #[rustc_diagnostic_item = "IteratorItem"]
     #[stable(feature = "rust1", since = "1.0.0")]
     type Item;
 
@@ -803,7 +804,7 @@ pub trait Iterator {
     /// (0..5).map(|x| x * 2 + 1)
     ///       .for_each(move |x| tx.send(x).unwrap());
     ///
-    /// let v: Vec<_> =  rx.iter().collect();
+    /// let v: Vec<_> = rx.iter().collect();
     /// assert_eq!(v, vec![1, 3, 5, 7, 9]);
     /// ```
     ///
diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs
index 1823fd30062..825c8541f0d 100644
--- a/library/core/src/lib.rs
+++ b/library/core/src/lib.rs
@@ -95,6 +95,7 @@
 #![warn(missing_docs)]
 #![allow(explicit_outlives_requirements)]
 #![allow(incomplete_features)]
+#![cfg_attr(not(bootstrap), warn(multiple_supertrait_upcastable))]
 //
 // Library features:
 #![feature(const_align_offset)]
@@ -231,6 +232,7 @@
 #![feature(unsized_fn_params)]
 #![feature(asm_const)]
 #![feature(const_transmute_copy)]
+#![cfg_attr(not(bootstrap), feature(multiple_supertrait_upcastable))]
 //
 // Target features:
 #![feature(arm_target_feature)]
diff --git a/library/core/src/mem/mod.rs b/library/core/src/mem/mod.rs
index 383bdc7b6e2..5e01ccc07d8 100644
--- a/library/core/src/mem/mod.rs
+++ b/library/core/src/mem/mod.rs
@@ -682,7 +682,8 @@ pub unsafe fn zeroed<T>() -> T {
 pub unsafe fn uninitialized<T>() -> T {
     // SAFETY: the caller must guarantee that an uninitialized value is valid for `T`.
     unsafe {
-        intrinsics::assert_uninit_valid::<T>();
+        #[cfg(not(bootstrap))] // If the compiler hits this itself then it deserves the UB.
+        intrinsics::assert_mem_uninitialized_valid::<T>();
         let mut val = MaybeUninit::<T>::uninit();
 
         // Fill memory with 0x01, as an imperfect mitigation for old code that uses this function on
diff --git a/library/core/src/ops/index.rs b/library/core/src/ops/index.rs
index 5e3dc48b6ca..228efb0bc0a 100644
--- a/library/core/src/ops/index.rs
+++ b/library/core/src/ops/index.rs
@@ -165,7 +165,7 @@ see chapter in The Book <https://doc.rust-lang.org/book/ch08-02-strings.html#ind
 #[doc(alias = "]")]
 #[doc(alias = "[]")]
 #[const_trait]
-pub trait IndexMut<Idx: ?Sized>: Index<Idx> {
+pub trait IndexMut<Idx: ?Sized>: ~const Index<Idx> {
     /// Performs the mutable indexing (`container[index]`) operation.
     ///
     /// # Panics
diff --git a/library/core/src/panicking.rs b/library/core/src/panicking.rs
index a704a00faaa..9fce78d076b 100644
--- a/library/core/src/panicking.rs
+++ b/library/core/src/panicking.rs
@@ -64,12 +64,13 @@ pub const fn panic_fmt(fmt: fmt::Arguments<'_>) -> ! {
     unsafe { panic_impl(&pi) }
 }
 
-/// Like panic_fmt, but without unwinding and track_caller to reduce the impact on codesize.
-/// Also just works on `str`, as a `fmt::Arguments` needs more space to be passed.
+/// Like `panic`, but without unwinding and track_caller to reduce the impact on codesize.
+/// (No `fmt` variant as a `fmt::Arguments` needs more space to be passed.)
 #[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)]
 #[cfg_attr(feature = "panic_immediate_abort", inline)]
+#[cfg_attr(not(bootstrap), lang = "panic_nounwind")] // needed by codegen for non-unwinding panics
 #[rustc_nounwind]
-pub fn panic_str_nounwind(msg: &'static str) -> ! {
+pub fn panic_nounwind(msg: &'static str) -> ! {
     if cfg!(feature = "panic_immediate_abort") {
         super::intrinsics::abort()
     }
@@ -153,10 +154,11 @@ fn panic_bounds_check(index: usize, len: usize) -> ! {
 /// any extra arguments (including those synthesized by track_caller).
 #[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)]
 #[cfg_attr(feature = "panic_immediate_abort", inline)]
-#[lang = "panic_no_unwind"] // needed by codegen for panic in nounwind function
+#[cfg_attr(bootstrap, lang = "panic_no_unwind")] // needed by codegen for panic in nounwind function
+#[cfg_attr(not(bootstrap), lang = "panic_cannot_unwind")] // needed by codegen for panic in nounwind function
 #[rustc_nounwind]
-fn panic_no_unwind() -> ! {
-    panic_str_nounwind("panic in a function that cannot unwind")
+fn panic_cannot_unwind() -> ! {
+    panic_nounwind("panic in a function that cannot unwind")
 }
 
 /// This function is used instead of panic_fmt in const eval.
diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs
index 48b2e88da28..5f30029eaa0 100644
--- a/library/core/src/ptr/mod.rs
+++ b/library/core/src/ptr/mod.rs
@@ -516,6 +516,27 @@ pub const fn null<T: ?Sized + Thin>() -> *const T {
     from_raw_parts(invalid(0), ())
 }
 
+/// Creates a null mutable raw pointer.
+///
+/// # Examples
+///
+/// ```
+/// use std::ptr;
+///
+/// let p: *mut i32 = ptr::null_mut();
+/// assert!(p.is_null());
+/// ```
+#[inline(always)]
+#[must_use]
+#[stable(feature = "rust1", since = "1.0.0")]
+#[rustc_promotable]
+#[rustc_const_stable(feature = "const_ptr_null", since = "1.24.0")]
+#[rustc_allow_const_fn_unstable(ptr_metadata)]
+#[rustc_diagnostic_item = "ptr_null_mut"]
+pub const fn null_mut<T: ?Sized + Thin>() -> *mut T {
+    from_raw_parts_mut(invalid_mut(0), ())
+}
+
 /// Creates an invalid pointer with the given address.
 ///
 /// This is different from `addr as *const T`, which creates a pointer that picks up a previously
@@ -663,25 +684,26 @@ where
     addr as *mut T
 }
 
-/// Creates a null mutable raw pointer.
+/// Convert a reference to a raw pointer.
 ///
-/// # Examples
-///
-/// ```
-/// use std::ptr;
+/// This is equivalent to `r as *const T`, but is a bit safer since it will never silently change
+/// type or mutability, in particular if the code is refactored.
+#[inline(always)]
+#[must_use]
+#[unstable(feature = "ptr_from_ref", issue = "106116")]
+pub fn from_ref<T: ?Sized>(r: &T) -> *const T {
+    r
+}
+
+/// Convert a mutable reference to a raw pointer.
 ///
-/// let p: *mut i32 = ptr::null_mut();
-/// assert!(p.is_null());
-/// ```
+/// This is equivalent to `r as *mut T`, but is a bit safer since it will never silently change
+/// type or mutability, in particular if the code is refactored.
 #[inline(always)]
 #[must_use]
-#[stable(feature = "rust1", since = "1.0.0")]
-#[rustc_promotable]
-#[rustc_const_stable(feature = "const_ptr_null", since = "1.24.0")]
-#[rustc_allow_const_fn_unstable(ptr_metadata)]
-#[rustc_diagnostic_item = "ptr_null_mut"]
-pub const fn null_mut<T: ?Sized + Thin>() -> *mut T {
-    from_raw_parts_mut(invalid_mut(0), ())
+#[unstable(feature = "ptr_from_ref", issue = "106116")]
+pub fn from_mut<T: ?Sized>(r: &mut T) -> *mut T {
+    r
 }
 
 /// Forms a raw slice from a pointer and a length.
diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs
index 2c469f61854..2995cf0c644 100644
--- a/library/core/src/slice/mod.rs
+++ b/library/core/src/slice/mod.rs
@@ -893,7 +893,7 @@ impl<T> [T] {
     #[stable(feature = "chunks_exact", since = "1.31.0")]
     #[inline]
     pub fn chunks_exact(&self, chunk_size: usize) -> ChunksExact<'_, T> {
-        assert_ne!(chunk_size, 0);
+        assert_ne!(chunk_size, 0, "chunks cannot have a size of zero");
         ChunksExact::new(self, chunk_size)
     }
 
@@ -935,7 +935,7 @@ impl<T> [T] {
     #[stable(feature = "chunks_exact", since = "1.31.0")]
     #[inline]
     pub fn chunks_exact_mut(&mut self, chunk_size: usize) -> ChunksExactMut<'_, T> {
-        assert_ne!(chunk_size, 0);
+        assert_ne!(chunk_size, 0, "chunks cannot have a size of zero");
         ChunksExactMut::new(self, chunk_size)
     }
 
@@ -1017,7 +1017,7 @@ impl<T> [T] {
     #[inline]
     #[must_use]
     pub fn as_chunks<const N: usize>(&self) -> (&[[T; N]], &[T]) {
-        assert_ne!(N, 0);
+        assert_ne!(N, 0, "chunks cannot have a size of zero");
         let len = self.len() / N;
         let (multiple_of_n, remainder) = self.split_at(len * N);
         // SAFETY: We already panicked for zero, and ensured by construction
@@ -1048,7 +1048,7 @@ impl<T> [T] {
     #[inline]
     #[must_use]
     pub fn as_rchunks<const N: usize>(&self) -> (&[T], &[[T; N]]) {
-        assert_ne!(N, 0);
+        assert_ne!(N, 0, "chunks cannot have a size of zero");
         let len = self.len() / N;
         let (remainder, multiple_of_n) = self.split_at(self.len() - len * N);
         // SAFETY: We already panicked for zero, and ensured by construction
@@ -1087,7 +1087,7 @@ impl<T> [T] {
     #[unstable(feature = "array_chunks", issue = "74985")]
     #[inline]
     pub fn array_chunks<const N: usize>(&self) -> ArrayChunks<'_, T, N> {
-        assert_ne!(N, 0);
+        assert_ne!(N, 0, "chunks cannot have a size of zero");
         ArrayChunks::new(self)
     }
 
@@ -1166,7 +1166,7 @@ impl<T> [T] {
     #[inline]
     #[must_use]
     pub fn as_chunks_mut<const N: usize>(&mut self) -> (&mut [[T; N]], &mut [T]) {
-        assert_ne!(N, 0);
+        assert_ne!(N, 0, "chunks cannot have a size of zero");
         let len = self.len() / N;
         let (multiple_of_n, remainder) = self.split_at_mut(len * N);
         // SAFETY: We already panicked for zero, and ensured by construction
@@ -1203,7 +1203,7 @@ impl<T> [T] {
     #[inline]
     #[must_use]
     pub fn as_rchunks_mut<const N: usize>(&mut self) -> (&mut [T], &mut [[T; N]]) {
-        assert_ne!(N, 0);
+        assert_ne!(N, 0, "chunks cannot have a size of zero");
         let len = self.len() / N;
         let (remainder, multiple_of_n) = self.split_at_mut(self.len() - len * N);
         // SAFETY: We already panicked for zero, and ensured by construction
@@ -1244,7 +1244,7 @@ impl<T> [T] {
     #[unstable(feature = "array_chunks", issue = "74985")]
     #[inline]
     pub fn array_chunks_mut<const N: usize>(&mut self) -> ArrayChunksMut<'_, T, N> {
-        assert_ne!(N, 0);
+        assert_ne!(N, 0, "chunks cannot have a size of zero");
         ArrayChunksMut::new(self)
     }
 
@@ -1276,7 +1276,7 @@ impl<T> [T] {
     #[unstable(feature = "array_windows", issue = "75027")]
     #[inline]
     pub fn array_windows<const N: usize>(&self) -> ArrayWindows<'_, T, N> {
-        assert_ne!(N, 0);
+        assert_ne!(N, 0, "windows cannot have a size of zero");
         ArrayWindows::new(self)
     }
 
diff --git a/library/core/src/str/mod.rs b/library/core/src/str/mod.rs
index 45fd2caae52..863ded5e5ec 100644
--- a/library/core/src/str/mod.rs
+++ b/library/core/src/str/mod.rs
@@ -970,8 +970,10 @@ impl str {
 
     /// An iterator over the lines of a string, as string slices.
     ///
-    /// Lines are ended with either a newline (`\n`) or a carriage return with
-    /// a line feed (`\r\n`).
+    /// Lines are split at line endings that are either newlines (`\n`) or
+    /// sequences of a carriage return followed by a line feed (`\r\n`).
+    ///
+    /// Line terminators are not included in the lines returned by the iterator.
     ///
     /// The final line ending is optional. A string that ends with a final line
     /// ending will return the same lines as an otherwise identical string
diff --git a/library/core/src/task/wake.rs b/library/core/src/task/wake.rs
index 0cff972df3a..1b7578376b4 100644
--- a/library/core/src/task/wake.rs
+++ b/library/core/src/task/wake.rs
@@ -104,7 +104,7 @@ pub struct RawWakerVTable {
     /// pointer.
     wake_by_ref: unsafe fn(*const ()),
 
-    /// This function gets called when a [`RawWaker`] gets dropped.
+    /// This function gets called when a [`Waker`] gets dropped.
     ///
     /// The implementation of this function must make sure to release any
     /// resources that are associated with this instance of a [`RawWaker`] and
@@ -151,7 +151,7 @@ impl RawWakerVTable {
     ///
     /// # `drop`
     ///
-    /// This function gets called when a [`RawWaker`] gets dropped.
+    /// This function gets called when a [`Waker`] gets dropped.
     ///
     /// The implementation of this function must make sure to release any
     /// resources that are associated with this instance of a [`RawWaker`] and
diff --git a/library/core/tests/char.rs b/library/core/tests/char.rs
index 8542e5c70d4..ac0b2ca168b 100644
--- a/library/core/tests/char.rs
+++ b/library/core/tests/char.rs
@@ -306,6 +306,10 @@ fn test_decode_utf16() {
     }
     check(&[0xD800, 0x41, 0x42], &[Err(0xD800), Ok('A'), Ok('B')]);
     check(&[0xD800, 0], &[Err(0xD800), Ok('\0')]);
+    check(&[0xD800], &[Err(0xD800)]);
+    check(&[0xD840, 0xDC00], &[Ok('\u{20000}')]);
+    check(&[0xD840, 0xD840, 0xDC00], &[Err(0xD840), Ok('\u{20000}')]);
+    check(&[0xDC00, 0xD840], &[Err(0xDC00), Err(0xD840)]);
 }
 
 #[test]
diff --git a/library/core/tests/lazy.rs b/library/core/tests/lazy.rs
index 70fcc6d2d4b..c7c3c479b71 100644
--- a/library/core/tests/lazy.rs
+++ b/library/core/tests/lazy.rs
@@ -106,6 +106,12 @@ fn lazy_new() {
     assert_eq!(called.get(), 1);
 }
 
+// Check that we can infer `T` from closure's type.
+#[test]
+fn lazy_type_inference() {
+    let _ = LazyCell::new(|| ());
+}
+
 #[test]
 fn aliasing_in_get() {
     let x = OnceCell::new();
diff --git a/library/std/src/io/stdio.rs b/library/std/src/io/stdio.rs
index 1141a957d87..14bfef4c7aa 100644
--- a/library/std/src/io/stdio.rs
+++ b/library/std/src/io/stdio.rs
@@ -10,9 +10,8 @@ use crate::fmt;
 use crate::fs::File;
 use crate::io::{self, BufReader, IoSlice, IoSliceMut, LineWriter, Lines};
 use crate::sync::atomic::{AtomicBool, Ordering};
-use crate::sync::{Arc, Mutex, MutexGuard, OnceLock};
+use crate::sync::{Arc, Mutex, MutexGuard, OnceLock, ReentrantMutex, ReentrantMutexGuard};
 use crate::sys::stdio;
-use crate::sys_common::remutex::{ReentrantMutex, ReentrantMutexGuard};
 
 type LocalStream = Arc<Mutex<Vec<u8>>>;
 
diff --git a/library/std/src/panic.rs b/library/std/src/panic.rs
index c4f022de021..9fa8f5702a8 100644
--- a/library/std/src/panic.rs
+++ b/library/std/src/panic.rs
@@ -114,6 +114,9 @@ where
 /// aborting the process as well. This function *only* catches unwinding panics,
 /// not those that abort the process.
 ///
+/// Note that if a custom panic hook has been set, it will be invoked before
+/// the panic is caught, before unwinding.
+///
 /// Also note that unwinding into Rust code with a foreign exception (e.g.
 /// an exception thrown from C++ code) is undefined behavior.
 ///
diff --git a/library/std/src/process.rs b/library/std/src/process.rs
index 17aff342c15..c1da395bfc5 100644
--- a/library/std/src/process.rs
+++ b/library/std/src/process.rs
@@ -1038,6 +1038,15 @@ impl fmt::Debug for Command {
     /// Format the program and arguments of a Command for display. Any
     /// non-utf8 data is lossily converted using the utf8 replacement
     /// character.
+    ///
+    /// The default format approximates a shell invocation of the program along with its
+    /// arguments. It does not include most of the other command properties. The output is not guaranteed to work
+    /// (e.g. due to lack of shell-escaping or differences in path resolution)
+    /// On some platforms you can use [the alternate syntax] to show more fields.
+    ///
+    /// Note that the debug implementation is platform-specific.
+    ///
+    /// [the alternate syntax]: fmt#sign0
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         self.inner.fmt(f)
     }
diff --git a/library/std/src/process/tests.rs b/library/std/src/process/tests.rs
index 955ad68916c..b4f6cc2daba 100644
--- a/library/std/src/process/tests.rs
+++ b/library/std/src/process/tests.rs
@@ -417,6 +417,100 @@ fn env_empty() {
     assert!(p.is_ok());
 }
 
+#[test]
+#[cfg(not(windows))]
+#[cfg_attr(any(target_os = "emscripten", target_env = "sgx"), ignore)]
+fn main() {
+    const PIDFD: &'static str =
+        if cfg!(target_os = "linux") { "    create_pidfd: false,\n" } else { "" };
+
+    let mut command = Command::new("some-boring-name");
+
+    assert_eq!(format!("{command:?}"), format!(r#""some-boring-name""#));
+
+    assert_eq!(
+        format!("{command:#?}"),
+        format!(
+            r#"Command {{
+    program: "some-boring-name",
+    args: [
+        "some-boring-name",
+    ],
+{PIDFD}}}"#
+        )
+    );
+
+    command.args(&["1", "2", "3"]);
+
+    assert_eq!(format!("{command:?}"), format!(r#""some-boring-name" "1" "2" "3""#));
+
+    assert_eq!(
+        format!("{command:#?}"),
+        format!(
+            r#"Command {{
+    program: "some-boring-name",
+    args: [
+        "some-boring-name",
+        "1",
+        "2",
+        "3",
+    ],
+{PIDFD}}}"#
+        )
+    );
+
+    crate::os::unix::process::CommandExt::arg0(&mut command, "exciting-name");
+
+    assert_eq!(
+        format!("{command:?}"),
+        format!(r#"["some-boring-name"] "exciting-name" "1" "2" "3""#)
+    );
+
+    assert_eq!(
+        format!("{command:#?}"),
+        format!(
+            r#"Command {{
+    program: "some-boring-name",
+    args: [
+        "exciting-name",
+        "1",
+        "2",
+        "3",
+    ],
+{PIDFD}}}"#
+        )
+    );
+
+    let mut command_with_env_and_cwd = Command::new("boring-name");
+    command_with_env_and_cwd.current_dir("/some/path").env("FOO", "bar");
+    assert_eq!(
+        format!("{command_with_env_and_cwd:?}"),
+        r#"cd "/some/path" && FOO="bar" "boring-name""#
+    );
+    assert_eq!(
+        format!("{command_with_env_and_cwd:#?}"),
+        format!(
+            r#"Command {{
+    program: "boring-name",
+    args: [
+        "boring-name",
+    ],
+    env: CommandEnv {{
+        clear: false,
+        vars: {{
+            "FOO": Some(
+                "bar",
+            ),
+        }},
+    }},
+    cwd: Some(
+        "/some/path",
+    ),
+{PIDFD}}}"#
+        )
+    );
+}
+
 // See issue #91991
 #[test]
 #[cfg(windows)]
diff --git a/library/std/src/sync/lazy_lock.rs b/library/std/src/sync/lazy_lock.rs
index c8d3289ca4a..bf5a716fa03 100644
--- a/library/std/src/sync/lazy_lock.rs
+++ b/library/std/src/sync/lazy_lock.rs
@@ -46,17 +46,14 @@ pub struct LazyLock<T, F = fn() -> T> {
     cell: OnceLock<T>,
     init: Cell<Option<F>>,
 }
-
-impl<T, F> LazyLock<T, F> {
+impl<T, F: FnOnce() -> T> LazyLock<T, F> {
     /// Creates a new lazy value with the given initializing
     /// function.
     #[unstable(feature = "once_cell", issue = "74465")]
     pub const fn new(f: F) -> LazyLock<T, F> {
         LazyLock { cell: OnceLock::new(), init: Cell::new(Some(f)) }
     }
-}
 
-impl<T, F: FnOnce() -> T> LazyLock<T, F> {
     /// Forces the evaluation of this lazy value and
     /// returns a reference to result. This is equivalent
     /// to the `Deref` impl, but is explicit.
diff --git a/library/std/src/sync/lazy_lock/tests.rs b/library/std/src/sync/lazy_lock/tests.rs
index f11b66bfca5..a5d4e25c596 100644
--- a/library/std/src/sync/lazy_lock/tests.rs
+++ b/library/std/src/sync/lazy_lock/tests.rs
@@ -136,6 +136,12 @@ fn sync_lazy_poisoning() {
     }
 }
 
+// Check that we can infer `T` from closure's type.
+#[test]
+fn lazy_type_inference() {
+    let _ = LazyCell::new(|| ());
+}
+
 #[test]
 fn is_sync_send() {
     fn assert_traits<T: Send + Sync>() {}
diff --git a/library/std/src/sync/mod.rs b/library/std/src/sync/mod.rs
index 4fee8d3e92f..ba20bab87a4 100644
--- a/library/std/src/sync/mod.rs
+++ b/library/std/src/sync/mod.rs
@@ -177,6 +177,8 @@ pub use self::lazy_lock::LazyLock;
 #[unstable(feature = "once_cell", issue = "74465")]
 pub use self::once_lock::OnceLock;
 
+pub(crate) use self::remutex::{ReentrantMutex, ReentrantMutexGuard};
+
 pub mod mpsc;
 
 mod barrier;
@@ -187,4 +189,5 @@ mod mutex;
 mod once;
 mod once_lock;
 mod poison;
+mod remutex;
 mod rwlock;
diff --git a/library/std/src/sync/mpmc/utils.rs b/library/std/src/sync/mpmc/utils.rs
index d0904b4b94c..e030c55ce8f 100644
--- a/library/std/src/sync/mpmc/utils.rs
+++ b/library/std/src/sync/mpmc/utils.rs
@@ -136,7 +136,7 @@ impl Backoff {
         }
     }
 
-    /// Returns `true` if exponential backoff has completed and blocking the thread is advised.
+    /// Returns `true` if quadratic backoff has completed and blocking the thread is advised.
     #[inline]
     pub fn is_completed(&self) -> bool {
         self.step.get() > YIELD_LIMIT
diff --git a/library/std/src/sys_common/remutex.rs b/library/std/src/sync/remutex.rs
index 4c054da6471..4c054da6471 100644
--- a/library/std/src/sys_common/remutex.rs
+++ b/library/std/src/sync/remutex.rs
diff --git a/library/std/src/sys_common/remutex/tests.rs b/library/std/src/sync/remutex/tests.rs
index 8e97ce11c34..fc553081d42 100644
--- a/library/std/src/sys_common/remutex/tests.rs
+++ b/library/std/src/sync/remutex/tests.rs
@@ -1,6 +1,6 @@
+use super::{ReentrantMutex, ReentrantMutexGuard};
 use crate::cell::RefCell;
 use crate::sync::Arc;
-use crate::sys_common::remutex::{ReentrantMutex, ReentrantMutexGuard};
 use crate::thread;
 
 #[test]
diff --git a/library/std/src/sys/unix/fs.rs b/library/std/src/sys/unix/fs.rs
index d5f50d77911..aea0c26ee8b 100644
--- a/library/std/src/sys/unix/fs.rs
+++ b/library/std/src/sys/unix/fs.rs
@@ -1754,11 +1754,11 @@ mod remove_dir_impl {
     use crate::sys::{cvt, cvt_r};
 
     #[cfg(not(any(
-        target_os = "linux",
+        all(target_os = "linux", target_env = "gnu"),
         all(target_os = "macos", not(target_arch = "aarch64"))
     )))]
     use libc::{fdopendir, openat, unlinkat};
-    #[cfg(target_os = "linux")]
+    #[cfg(all(target_os = "linux", target_env = "gnu"))]
     use libc::{fdopendir, openat64 as openat, unlinkat};
     #[cfg(all(target_os = "macos", not(target_arch = "aarch64")))]
     use macos_weak::{fdopendir, openat, unlinkat};
diff --git a/library/std/src/sys/unix/kernel_copy.rs b/library/std/src/sys/unix/kernel_copy.rs
index 6fa85e859c0..0f7107122b7 100644
--- a/library/std/src/sys/unix/kernel_copy.rs
+++ b/library/std/src/sys/unix/kernel_copy.rs
@@ -61,9 +61,9 @@ use crate::ptr;
 use crate::sync::atomic::{AtomicBool, AtomicU8, Ordering};
 use crate::sys::cvt;
 use crate::sys::weak::syscall;
-#[cfg(not(target_os = "linux"))]
+#[cfg(not(all(target_os = "linux", target_env = "gnu")))]
 use libc::sendfile as sendfile64;
-#[cfg(target_os = "linux")]
+#[cfg(all(target_os = "linux", target_env = "gnu"))]
 use libc::sendfile64;
 use libc::{EBADF, EINVAL, ENOSYS, EOPNOTSUPP, EOVERFLOW, EPERM, EXDEV};
 
diff --git a/library/std/src/sys/unix/mod.rs b/library/std/src/sys/unix/mod.rs
index 3d60941e84e..83a43b6ee26 100644
--- a/library/std/src/sys/unix/mod.rs
+++ b/library/std/src/sys/unix/mod.rs
@@ -95,9 +95,9 @@ pub unsafe fn init(argc: isize, argv: *const *const u8, sigpipe: u8) {
         )))]
         'poll: {
             use crate::sys::os::errno;
-            #[cfg(not(target_os = "linux"))]
+            #[cfg(not(all(target_os = "linux", target_env = "gnu")))]
             use libc::open as open64;
-            #[cfg(target_os = "linux")]
+            #[cfg(all(target_os = "linux", target_env = "gnu"))]
             use libc::open64;
             let pfds: &mut [_] = &mut [
                 libc::pollfd { fd: 0, events: 0, revents: 0 },
@@ -143,9 +143,9 @@ pub unsafe fn init(argc: isize, argv: *const *const u8, sigpipe: u8) {
         )))]
         {
             use crate::sys::os::errno;
-            #[cfg(not(target_os = "linux"))]
+            #[cfg(not(all(target_os = "linux", target_env = "gnu")))]
             use libc::open as open64;
-            #[cfg(target_os = "linux")]
+            #[cfg(all(target_os = "linux", target_env = "gnu"))]
             use libc::open64;
             for fd in 0..3 {
                 if libc::fcntl(fd, libc::F_GETFD) == -1 && errno() == libc::EBADF {
diff --git a/library/std/src/sys/unix/process/process_common.rs b/library/std/src/sys/unix/process/process_common.rs
index 848adca78c0..afd03d79c0b 100644
--- a/library/std/src/sys/unix/process/process_common.rs
+++ b/library/std/src/sys/unix/process/process_common.rs
@@ -144,6 +144,7 @@ pub enum ChildStdio {
     Null,
 }
 
+#[derive(Debug)]
 pub enum Stdio {
     Inherit,
     Null,
@@ -510,16 +511,68 @@ impl ChildStdio {
 }
 
 impl fmt::Debug for Command {
+    // show all attributes but `self.closures` which does not implement `Debug`
+    // and `self.argv` which is not useful for debugging
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        if self.program != self.args[0] {
-            write!(f, "[{:?}] ", self.program)?;
-        }
-        write!(f, "{:?}", self.args[0])?;
+        if f.alternate() {
+            let mut debug_command = f.debug_struct("Command");
+            debug_command.field("program", &self.program).field("args", &self.args);
+            if !self.env.is_unchanged() {
+                debug_command.field("env", &self.env);
+            }
+
+            if self.cwd.is_some() {
+                debug_command.field("cwd", &self.cwd);
+            }
+            if self.uid.is_some() {
+                debug_command.field("uid", &self.uid);
+            }
+            if self.gid.is_some() {
+                debug_command.field("gid", &self.gid);
+            }
+
+            if self.groups.is_some() {
+                debug_command.field("groups", &self.groups);
+            }
+
+            if self.stdin.is_some() {
+                debug_command.field("stdin", &self.stdin);
+            }
+            if self.stdout.is_some() {
+                debug_command.field("stdout", &self.stdout);
+            }
+            if self.stderr.is_some() {
+                debug_command.field("stderr", &self.stderr);
+            }
+            if self.pgroup.is_some() {
+                debug_command.field("pgroup", &self.pgroup);
+            }
+
+            #[cfg(target_os = "linux")]
+            {
+                debug_command.field("create_pidfd", &self.create_pidfd);
+            }
 
-        for arg in &self.args[1..] {
-            write!(f, " {:?}", arg)?;
+            debug_command.finish()
+        } else {
+            if let Some(ref cwd) = self.cwd {
+                write!(f, "cd {cwd:?} && ")?;
+            }
+            for (key, value_opt) in self.get_envs() {
+                if let Some(value) = value_opt {
+                    write!(f, "{}={value:?} ", key.to_string_lossy())?;
+                }
+            }
+            if self.program != self.args[0] {
+                write!(f, "[{:?}] ", self.program)?;
+            }
+            write!(f, "{:?}", self.args[0])?;
+
+            for arg in &self.args[1..] {
+                write!(f, " {:?}", arg)?;
+            }
+            Ok(())
         }
-        Ok(())
     }
 }
 
diff --git a/library/std/src/sys/unix/stack_overflow.rs b/library/std/src/sys/unix/stack_overflow.rs
index 957e086798f..b59d4ba26af 100644
--- a/library/std/src/sys/unix/stack_overflow.rs
+++ b/library/std/src/sys/unix/stack_overflow.rs
@@ -45,9 +45,9 @@ mod imp {
     use crate::thread;
 
     use libc::MAP_FAILED;
-    #[cfg(not(target_os = "linux"))]
+    #[cfg(not(all(target_os = "linux", target_env = "gnu")))]
     use libc::{mmap as mmap64, munmap};
-    #[cfg(target_os = "linux")]
+    #[cfg(all(target_os = "linux", target_env = "gnu"))]
     use libc::{mmap64, munmap};
     use libc::{sigaction, sighandler_t, SA_ONSTACK, SA_SIGINFO, SIGBUS, SIG_DFL};
     use libc::{sigaltstack, SIGSTKSZ, SS_DISABLE};
diff --git a/library/std/src/sys/unix/thread.rs b/library/std/src/sys/unix/thread.rs
index d454a2a717c..b251949bda2 100644
--- a/library/std/src/sys/unix/thread.rs
+++ b/library/std/src/sys/unix/thread.rs
@@ -505,7 +505,7 @@ mod cgroups {
                     let limit = raw_quota.next()?;
                     let period = raw_quota.next()?;
                     match (limit.parse::<usize>(), period.parse::<usize>()) {
-                        (Ok(limit), Ok(period)) => {
+                        (Ok(limit), Ok(period)) if period > 0 => {
                             quota = quota.min(limit / period);
                         }
                         _ => {}
@@ -565,7 +565,7 @@ mod cgroups {
                 let period = parse_file("cpu.cfs_period_us");
 
                 match (limit, period) {
-                    (Some(limit), Some(period)) => quota = quota.min(limit / period),
+                    (Some(limit), Some(period)) if period > 0 => quota = quota.min(limit / period),
                     _ => {}
                 }
 
@@ -653,9 +653,9 @@ pub mod guard {
 ))]
 #[cfg_attr(test, allow(dead_code))]
 pub mod guard {
-    #[cfg(not(target_os = "linux"))]
+    #[cfg(not(all(target_os = "linux", target_env = "gnu")))]
     use libc::{mmap as mmap64, mprotect};
-    #[cfg(target_os = "linux")]
+    #[cfg(all(target_os = "linux", target_env = "gnu"))]
     use libc::{mmap64, mprotect};
     use libc::{MAP_ANON, MAP_FAILED, MAP_FIXED, MAP_PRIVATE, PROT_NONE, PROT_READ, PROT_WRITE};
 
diff --git a/library/std/src/sys/unix/thread_parker/pthread.rs b/library/std/src/sys/unix/thread_parker/pthread.rs
index c400c771567..510168a010f 100644
--- a/library/std/src/sys/unix/thread_parker/pthread.rs
+++ b/library/std/src/sys/unix/thread_parker/pthread.rs
@@ -44,7 +44,8 @@ unsafe fn wait_timeout(
         target_os = "macos",
         target_os = "ios",
         target_os = "watchos",
-        target_os = "espidf"
+        target_os = "espidf",
+        target_os = "horizon",
     ))]
     let (now, dur) = {
         use crate::cmp::min;
@@ -70,7 +71,8 @@ unsafe fn wait_timeout(
         target_os = "macos",
         target_os = "ios",
         target_os = "watchos",
-        target_os = "espidf"
+        target_os = "espidf",
+        target_os = "horizon",
     )))]
     let (now, dur) = {
         use crate::sys::time::Timespec;
diff --git a/library/std/src/sys_common/mod.rs b/library/std/src/sys_common/mod.rs
index b1987aa0f62..73da1ce066c 100644
--- a/library/std/src/sys_common/mod.rs
+++ b/library/std/src/sys_common/mod.rs
@@ -27,7 +27,6 @@ pub mod lazy_box;
 pub mod memchr;
 pub mod once;
 pub mod process;
-pub mod remutex;
 pub mod thread;
 pub mod thread_info;
 pub mod thread_local_dtor;
diff --git a/library/std/src/sys_common/process.rs b/library/std/src/sys_common/process.rs
index ae11412067b..18883048dae 100644
--- a/library/std/src/sys_common/process.rs
+++ b/library/std/src/sys_common/process.rs
@@ -4,12 +4,13 @@
 use crate::collections::BTreeMap;
 use crate::env;
 use crate::ffi::{OsStr, OsString};
+use crate::fmt;
 use crate::io;
 use crate::sys::pipe::read2;
 use crate::sys::process::{EnvKey, ExitStatus, Process, StdioPipes};
 
 // Stores a set of changes to an environment
-#[derive(Clone, Debug)]
+#[derive(Clone)]
 pub struct CommandEnv {
     clear: bool,
     saw_path: bool,
@@ -22,6 +23,14 @@ impl Default for CommandEnv {
     }
 }
 
+impl fmt::Debug for CommandEnv {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        let mut debug_command_env = f.debug_struct("CommandEnv");
+        debug_command_env.field("clear", &self.clear).field("vars", &self.vars);
+        debug_command_env.finish()
+    }
+}
+
 impl CommandEnv {
     // Capture the current environment with these changes applied
     pub fn capture(&self) -> BTreeMap<EnvKey, OsString> {
diff --git a/library/std/src/sys_common/thread_local_key.rs b/library/std/src/sys_common/thread_local_key.rs
index 747579f1781..2672a2a75b0 100644
--- a/library/std/src/sys_common/thread_local_key.rs
+++ b/library/std/src/sys_common/thread_local_key.rs
@@ -117,10 +117,14 @@ pub struct Key {
 /// This value specifies no destructor by default.
 pub const INIT: StaticKey = StaticKey::new(None);
 
+// Define a sentinel value that is unlikely to be returned
+// as a TLS key (but it may be returned).
+const KEY_SENTVAL: usize = 0;
+
 impl StaticKey {
     #[rustc_const_unstable(feature = "thread_local_internals", issue = "none")]
     pub const fn new(dtor: Option<unsafe extern "C" fn(*mut u8)>) -> StaticKey {
-        StaticKey { key: atomic::AtomicUsize::new(0), dtor }
+        StaticKey { key: atomic::AtomicUsize::new(KEY_SENTVAL), dtor }
     }
 
     /// Gets the value associated with this TLS key
@@ -144,31 +148,36 @@ impl StaticKey {
     #[inline]
     unsafe fn key(&self) -> imp::Key {
         match self.key.load(Ordering::Relaxed) {
-            0 => self.lazy_init() as imp::Key,
+            KEY_SENTVAL => self.lazy_init() as imp::Key,
             n => n as imp::Key,
         }
     }
 
     unsafe fn lazy_init(&self) -> usize {
-        // POSIX allows the key created here to be 0, but the compare_exchange
-        // below relies on using 0 as a sentinel value to check who won the
+        // POSIX allows the key created here to be KEY_SENTVAL, but the compare_exchange
+        // below relies on using KEY_SENTVAL as a sentinel value to check who won the
         // race to set the shared TLS key. As far as I know, there is no
         // guaranteed value that cannot be returned as a posix_key_create key,
         // so there is no value we can initialize the inner key with to
         // prove that it has not yet been set. As such, we'll continue using a
-        // value of 0, but with some gyrations to make sure we have a non-0
+        // value of KEY_SENTVAL, but with some gyrations to make sure we have a non-KEY_SENTVAL
         // value returned from the creation routine.
         // FIXME: this is clearly a hack, and should be cleaned up.
         let key1 = imp::create(self.dtor);
-        let key = if key1 != 0 {
+        let key = if key1 as usize != KEY_SENTVAL {
             key1
         } else {
             let key2 = imp::create(self.dtor);
             imp::destroy(key1);
             key2
         };
-        rtassert!(key != 0);
-        match self.key.compare_exchange(0, key as usize, Ordering::SeqCst, Ordering::SeqCst) {
+        rtassert!(key as usize != KEY_SENTVAL);
+        match self.key.compare_exchange(
+            KEY_SENTVAL,
+            key as usize,
+            Ordering::SeqCst,
+            Ordering::SeqCst,
+        ) {
             // The CAS succeeded, so we've created the actual key
             Ok(_) => key as usize,
             // If someone beat us to the punch, use their key instead
diff --git a/src/bootstrap/CHANGELOG.md b/src/bootstrap/CHANGELOG.md
index 64b74ecc9de..4105fa5ec96 100644
--- a/src/bootstrap/CHANGELOG.md
+++ b/src/bootstrap/CHANGELOG.md
@@ -15,6 +15,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
 - Several unsupported `./configure` options have been removed: `optimize`, `parallel-compiler`. These can still be enabled with `--set`, although it isn't recommended.
 - `remote-test-server`'s `verbose` argument has been removed in favor of the `--verbose` flag
 - `remote-test-server`'s `remote` argument has been removed in favor of the `--bind` flag. Use `--bind 0.0.0.0:12345` to replicate the behavior of the `remote` argument.
+- `x.py fmt` now formats only files modified between the merge-base of HEAD and the last commit in the master branch of the rust-lang repository and the current working directory. To restore old behaviour, use `x.py fmt .`. The check mode is not affected by this change. [#105702](https://github.com/rust-lang/rust/pull/105702)
 
 ### Non-breaking changes
 
diff --git a/src/bootstrap/Cargo.toml b/src/bootstrap/Cargo.toml
index ccc7ec1fce9..fafe82a9c12 100644
--- a/src/bootstrap/Cargo.toml
+++ b/src/bootstrap/Cargo.toml
@@ -29,11 +29,6 @@ name = "sccache-plus-cl"
 path = "bin/sccache-plus-cl.rs"
 test = false
 
-[[bin]]
-name = "llvm-config-wrapper"
-path = "bin/llvm-config-wrapper.rs"
-test = false
-
 [dependencies]
 cmake = "0.1.38"
 fd-lock = "3.0.8"
diff --git a/src/bootstrap/README.md b/src/bootstrap/README.md
index 985727bddc5..79c2eb31cda 100644
--- a/src/bootstrap/README.md
+++ b/src/bootstrap/README.md
@@ -80,18 +80,12 @@ The script accepts commands, flags, and arguments to determine what to do:
 
 ## Configuring rustbuild
 
-There are currently two methods for configuring the rustbuild build system.
-
-First, rustbuild offers a TOML-based configuration system with a `config.toml`
+rustbuild offers a TOML-based configuration system with a `config.toml`
 file. An example of this configuration can be found at `config.toml.example`,
 and the configuration file can also be passed as `--config path/to/config.toml`
 if the build system is being invoked manually (via the python script).
 
-Next, the `./configure` options serialized in `config.mk` will be
-parsed and read. That is, if any `./configure` options are passed, they'll be
-handled naturally. `./configure` should almost never be used for local
-installations, and is primarily useful for CI. Prefer to customize behavior
-using `config.toml`.
+You can generate a config.toml using `./configure` options if you want to automate creating the file without having to edit it.
 
 Finally, rustbuild makes use of the [cc-rs crate] which has [its own
 method][env-vars] of configuring C compilers and C flags via environment
diff --git a/src/bootstrap/bin/llvm-config-wrapper.rs b/src/bootstrap/bin/llvm-config-wrapper.rs
deleted file mode 100644
index 89984bb55df..00000000000
--- a/src/bootstrap/bin/llvm-config-wrapper.rs
+++ /dev/null
@@ -1,24 +0,0 @@
-// The sheer existence of this file is an awful hack. See the comments in
-// `src/bootstrap/native.rs` for why this is needed when compiling LLD.
-
-use std::env;
-use std::io::{self, Write};
-use std::process::{self, Command, Stdio};
-
-fn main() {
-    let real_llvm_config = env::var_os("LLVM_CONFIG_REAL").unwrap();
-    let mut cmd = Command::new(real_llvm_config);
-    cmd.args(env::args().skip(1)).stderr(Stdio::piped());
-    let output = cmd.output().expect("failed to spawn llvm-config");
-    let mut stdout = String::from_utf8_lossy(&output.stdout);
-
-    if let Ok(to_replace) = env::var("LLVM_CONFIG_SHIM_REPLACE") {
-        if let Ok(replace_with) = env::var("LLVM_CONFIG_SHIM_REPLACE_WITH") {
-            stdout = stdout.replace(&to_replace, &replace_with).into();
-        }
-    }
-
-    print!("{}", stdout.replace("\\", "/"));
-    io::stdout().flush().unwrap();
-    process::exit(output.status.code().unwrap_or(1));
-}
diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs
index 1d37d68c1d4..707e4169002 100644
--- a/src/bootstrap/builder.rs
+++ b/src/bootstrap/builder.rs
@@ -13,7 +13,6 @@ use std::time::{Duration, Instant};
 
 use crate::cache::{Cache, Interned, INTERNER};
 use crate::config::{SplitDebuginfo, TargetSelection};
-use crate::dist;
 use crate::doc;
 use crate::flags::{Color, Subcommand};
 use crate::install;
@@ -25,6 +24,7 @@ use crate::tool::{self, SourceType};
 use crate::util::{self, add_dylib_path, add_link_lib_path, exe, libdir, output, t};
 use crate::EXTRA_CHECK_CFGS;
 use crate::{check, compile, Crate};
+use crate::{clean, dist};
 use crate::{Build, CLang, DocTests, GitRepo, Mode};
 
 pub use crate::Compiler;
@@ -96,6 +96,17 @@ impl RunConfig<'_> {
     pub fn build_triple(&self) -> TargetSelection {
         self.builder.build.build
     }
+
+    /// Return a `-p=x -p=y` string suitable for passing to a cargo invocation.
+    pub fn cargo_crates_in_set(&self) -> Interned<Vec<String>> {
+        let mut crates = Vec::new();
+        for krate in &self.paths {
+            let path = krate.assert_single_path();
+            let crate_name = self.builder.crate_paths[&path.path];
+            crates.push(format!("-p={crate_name}"));
+        }
+        INTERNER.intern_list(crates)
+    }
 }
 
 struct StepDescription {
@@ -702,6 +713,7 @@ impl<'a> Builder<'a> {
                 doc::RustdocBook,
                 doc::RustByExample,
                 doc::RustcBook,
+                doc::Cargo,
                 doc::CargoBook,
                 doc::Clippy,
                 doc::ClippyBook,
@@ -763,8 +775,9 @@ impl<'a> Builder<'a> {
                 run::GenerateCopyright,
             ),
             Kind::Setup => describe!(setup::Profile),
-            // These commands either don't use paths, or they're special-cased in Build::build()
-            Kind::Clean | Kind::Format => vec![],
+            Kind::Clean => describe!(clean::CleanAll, clean::Rustc, clean::Std),
+            // special-cased in Build::build()
+            Kind::Format => vec![],
         }
     }
 
@@ -826,14 +839,12 @@ impl<'a> Builder<'a> {
             Subcommand::Dist { ref paths } => (Kind::Dist, &paths[..]),
             Subcommand::Install { ref paths } => (Kind::Install, &paths[..]),
             Subcommand::Run { ref paths, .. } => (Kind::Run, &paths[..]),
+            Subcommand::Clean { ref paths, .. } => (Kind::Clean, &paths[..]),
             Subcommand::Format { .. } => (Kind::Format, &[][..]),
             Subcommand::Setup { profile: ref path } => (
                 Kind::Setup,
                 path.as_ref().map_or([].as_slice(), |path| std::slice::from_ref(path)),
             ),
-            Subcommand::Clean { .. } => {
-                panic!()
-            }
         };
 
         Self::new_internal(build, kind, paths.to_owned())
@@ -1068,7 +1079,7 @@ impl<'a> Builder<'a> {
     /// check build or dry-run, where there's no need to build all of LLVM.
     fn llvm_config(&self, target: TargetSelection) -> Option<PathBuf> {
         if self.config.llvm_enabled() && self.kind != Kind::Check && !self.config.dry_run() {
-            let llvm_config = self.ensure(native::Llvm { target });
+            let native::LlvmResult { llvm_config, .. } = self.ensure(native::Llvm { target });
             if llvm_config.is_file() {
                 return Some(llvm_config);
             }
@@ -1076,6 +1087,62 @@ impl<'a> Builder<'a> {
         None
     }
 
+    /// Like `cargo`, but only passes flags that are valid for all commands.
+    pub fn bare_cargo(
+        &self,
+        compiler: Compiler,
+        mode: Mode,
+        target: TargetSelection,
+        cmd: &str,
+    ) -> Command {
+        let mut cargo = Command::new(&self.initial_cargo);
+        // Run cargo from the source root so it can find .cargo/config.
+        // This matters when using vendoring and the working directory is outside the repository.
+        cargo.current_dir(&self.src);
+
+        let out_dir = self.stage_out(compiler, mode);
+        cargo.env("CARGO_TARGET_DIR", &out_dir).arg(cmd);
+
+        // Found with `rg "init_env_logger\("`. If anyone uses `init_env_logger`
+        // from out of tree it shouldn't matter, since x.py is only used for
+        // building in-tree.
+        let color_logs = ["RUSTDOC_LOG_COLOR", "RUSTC_LOG_COLOR", "RUST_LOG_COLOR"];
+        match self.build.config.color {
+            Color::Always => {
+                cargo.arg("--color=always");
+                for log in &color_logs {
+                    cargo.env(log, "always");
+                }
+            }
+            Color::Never => {
+                cargo.arg("--color=never");
+                for log in &color_logs {
+                    cargo.env(log, "never");
+                }
+            }
+            Color::Auto => {} // nothing to do
+        }
+
+        if cmd != "install" {
+            cargo.arg("--target").arg(target.rustc_target_arg());
+        } else {
+            assert_eq!(target, compiler.host);
+        }
+
+        if self.config.rust_optimize {
+            // FIXME: cargo bench/install do not accept `--release`
+            if cmd != "bench" && cmd != "install" {
+                cargo.arg("--release");
+            }
+        }
+
+        // Remove make-related flags to ensure Cargo can correctly set things up
+        cargo.env_remove("MAKEFLAGS");
+        cargo.env_remove("MFLAGS");
+
+        cargo
+    }
+
     /// Prepares an invocation of `cargo` to be run.
     ///
     /// This will create a `Command` that represents a pending execution of
@@ -1091,11 +1158,8 @@ impl<'a> Builder<'a> {
         target: TargetSelection,
         cmd: &str,
     ) -> Cargo {
-        let mut cargo = Command::new(&self.initial_cargo);
+        let mut cargo = self.bare_cargo(compiler, mode, target, cmd);
         let out_dir = self.stage_out(compiler, mode);
-        // Run cargo from the source root so it can find .cargo/config.
-        // This matters when using vendoring and the working directory is outside the repository.
-        cargo.current_dir(&self.src);
 
         // Codegen backends are not yet tracked by -Zbinary-dep-depinfo,
         // so we need to explicitly clear out if they've been updated.
@@ -1120,8 +1184,6 @@ impl<'a> Builder<'a> {
             self.clear_if_dirty(&my_out, &rustdoc);
         }
 
-        cargo.env("CARGO_TARGET_DIR", &out_dir).arg(cmd);
-
         let profile_var = |name: &str| {
             let profile = if self.config.rust_optimize { "RELEASE" } else { "DEV" };
             format!("CARGO_PROFILE_{}_{}", profile, name)
@@ -1134,32 +1196,6 @@ impl<'a> Builder<'a> {
             cargo.env("REAL_LIBRARY_PATH", e);
         }
 
-        // Found with `rg "init_env_logger\("`. If anyone uses `init_env_logger`
-        // from out of tree it shouldn't matter, since x.py is only used for
-        // building in-tree.
-        let color_logs = ["RUSTDOC_LOG_COLOR", "RUSTC_LOG_COLOR", "RUST_LOG_COLOR"];
-        match self.build.config.color {
-            Color::Always => {
-                cargo.arg("--color=always");
-                for log in &color_logs {
-                    cargo.env(log, "always");
-                }
-            }
-            Color::Never => {
-                cargo.arg("--color=never");
-                for log in &color_logs {
-                    cargo.env(log, "never");
-                }
-            }
-            Color::Auto => {} // nothing to do
-        }
-
-        if cmd != "install" {
-            cargo.arg("--target").arg(target.rustc_target_arg());
-        } else {
-            assert_eq!(target, compiler.host);
-        }
-
         // Set a flag for `check`/`clippy`/`fix`, so that certain build
         // scripts can do less work (i.e. not building/requiring LLVM).
         if cmd == "check" || cmd == "clippy" || cmd == "fix" {
@@ -1340,9 +1376,6 @@ impl<'a> Builder<'a> {
         }
 
         cargo.arg("-j").arg(self.jobs().to_string());
-        // Remove make-related flags to ensure Cargo can correctly set things up
-        cargo.env_remove("MAKEFLAGS");
-        cargo.env_remove("MFLAGS");
 
         // FIXME: Temporary fix for https://github.com/rust-lang/cargo/issues/3005
         // Force cargo to output binaries with disambiguating hashes in the name
@@ -1826,13 +1859,6 @@ impl<'a> Builder<'a> {
             }
         }
 
-        if self.config.rust_optimize {
-            // FIXME: cargo bench/install do not accept `--release`
-            if cmd != "bench" && cmd != "install" {
-                cargo.arg("--release");
-            }
-        }
-
         if self.config.locked_deps {
             cargo.arg("--locked");
         }
@@ -1863,7 +1889,10 @@ impl<'a> Builder<'a> {
             };
 
             if let Some(limit) = limit {
-                rustflags.arg(&format!("-Cllvm-args=-import-instr-limit={}", limit));
+                if stage == 0 || self.config.default_codegen_backend().unwrap_or_default() == "llvm"
+                {
+                    rustflags.arg(&format!("-Cllvm-args=-import-instr-limit={}", limit));
+                }
             }
         }
 
diff --git a/src/bootstrap/clean.rs b/src/bootstrap/clean.rs
index 069f3d6acf1..8e363ee1290 100644
--- a/src/bootstrap/clean.rs
+++ b/src/bootstrap/clean.rs
@@ -9,10 +9,83 @@ use std::fs;
 use std::io::{self, ErrorKind};
 use std::path::Path;
 
+use crate::builder::{Builder, RunConfig, ShouldRun, Step};
+use crate::cache::Interned;
+use crate::config::TargetSelection;
 use crate::util::t;
-use crate::Build;
+use crate::{Build, Mode, Subcommand};
 
-pub fn clean(build: &Build, all: bool) {
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
+pub struct CleanAll {}
+
+impl Step for CleanAll {
+    const DEFAULT: bool = true;
+    type Output = ();
+
+    fn make_run(run: RunConfig<'_>) {
+        run.builder.ensure(CleanAll {})
+    }
+
+    fn run(self, builder: &Builder<'_>) -> Self::Output {
+        let Subcommand::Clean { all, .. } = builder.config.cmd else { unreachable!("wrong subcommand?") };
+        clean_default(builder.build, all)
+    }
+
+    fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
+        run.never() // handled by DEFAULT
+    }
+}
+
+macro_rules! clean_crate_tree {
+    ( $( $name:ident, $mode:path, $root_crate:literal);+ $(;)? ) => { $(
+        #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
+        pub struct $name {
+            target: TargetSelection,
+            crates: Interned<Vec<String>>,
+        }
+
+        impl Step for $name {
+            type Output = ();
+
+            fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
+                let crates = run.builder.in_tree_crates($root_crate, None);
+                run.crates(crates)
+            }
+
+            fn make_run(run: RunConfig<'_>) {
+                let builder = run.builder;
+                if builder.top_stage != 0 {
+                    panic!("non-stage-0 clean not supported for individual crates");
+                }
+                builder.ensure(Self { crates: run.cargo_crates_in_set(), target: run.target });
+            }
+
+            fn run(self, builder: &Builder<'_>) -> Self::Output {
+                let compiler = builder.compiler(0, self.target);
+                let mut cargo = builder.bare_cargo(compiler, $mode, self.target, "clean");
+                for krate in &*self.crates {
+                    cargo.arg(krate);
+                }
+
+                builder.info(&format!(
+                    "Cleaning stage{} {} artifacts ({} -> {})",
+                    compiler.stage, stringify!($name).to_lowercase(), &compiler.host, self.target
+                ));
+
+                // NOTE: doesn't use `run_cargo` because we don't want to save a stamp file,
+                // and doesn't use `stream_cargo` to avoid passing `--message-format` which `clean` doesn't accept.
+                builder.run(&mut cargo);
+            }
+        }
+    )+ }
+}
+
+clean_crate_tree! {
+    Rustc, Mode::Rustc, "rustc-main";
+    Std, Mode::Std, "test";
+}
+
+fn clean_default(build: &Build, all: bool) {
     rm_rf("tmp".as_ref());
 
     if all {
@@ -21,6 +94,7 @@ pub fn clean(build: &Build, all: bool) {
         rm_rf(&build.out.join("tmp"));
         rm_rf(&build.out.join("dist"));
         rm_rf(&build.out.join("bootstrap"));
+        rm_rf(&build.out.join("rustfmt.stamp"));
 
         for host in &build.hosts {
             let entries = match build.out.join(host.triple).read_dir() {
diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs
index 0deed3f990d..427e1a3863e 100644
--- a/src/bootstrap/compile.rs
+++ b/src/bootstrap/compile.rs
@@ -46,17 +46,6 @@ impl Std {
     }
 }
 
-/// Return a `-p=x -p=y` string suitable for passing to a cargo invocation.
-fn build_crates_in_set(run: &RunConfig<'_>) -> Interned<Vec<String>> {
-    let mut crates = Vec::new();
-    for krate in &run.paths {
-        let path = krate.assert_single_path();
-        let crate_name = run.builder.crate_paths[&path.path];
-        crates.push(format!("-p={crate_name}"));
-    }
-    INTERNER.intern_list(crates)
-}
-
 impl Step for Std {
     type Output = ();
     const DEFAULT: bool = true;
@@ -76,7 +65,7 @@ impl Step for Std {
         // Build all crates anyway, as if they hadn't passed the other args.
         let has_library =
             run.paths.iter().any(|set| set.assert_single_path().path.ends_with("library"));
-        let crates = if has_library { Default::default() } else { build_crates_in_set(&run) };
+        let crates = if has_library { Default::default() } else { run.cargo_crates_in_set() };
         run.builder.ensure(Std {
             compiler: run.builder.compiler(run.builder.top_stage, run.build_triple()),
             target: run.target,
@@ -321,8 +310,15 @@ pub fn std_cargo(builder: &Builder<'_>, target: TargetSelection, stage: u32, car
         ""
     };
 
+    let mut features = String::new();
+
+    // Cranelift doesn't support `asm`.
+    if stage != 0 && builder.config.default_codegen_backend().unwrap_or_default() == "cranelift" {
+        features += " compiler-builtins-no-asm";
+    }
+
     if builder.no_std(target) == Some(true) {
-        let mut features = "compiler-builtins-mem".to_string();
+        features += " compiler-builtins-mem";
         if !target.starts_with("bpf") {
             features.push_str(compiler_builtins_c_feature);
         }
@@ -335,7 +331,7 @@ pub fn std_cargo(builder: &Builder<'_>, target: TargetSelection, stage: u32, car
             .arg("--features")
             .arg(features);
     } else {
-        let mut features = builder.std_features(target);
+        features += &builder.std_features(target);
         features.push_str(compiler_builtins_c_feature);
 
         cargo
@@ -596,7 +592,7 @@ impl Step for Rustc {
     }
 
     fn make_run(run: RunConfig<'_>) {
-        let crates = build_crates_in_set(&run);
+        let crates = run.cargo_crates_in_set();
         run.builder.ensure(Rustc {
             compiler: run.builder.compiler(run.builder.top_stage, run.build_triple()),
             target: run.target,
@@ -754,7 +750,7 @@ pub fn rustc_cargo_env(builder: &Builder<'_>, cargo: &mut Cargo, target: TargetS
         .env("CFG_RELEASE_CHANNEL", &builder.config.channel)
         .env("CFG_VERSION", builder.rust_version());
 
-    if let Some(backend) = builder.config.rust_codegen_backends.get(0) {
+    if let Some(backend) = builder.config.default_codegen_backend() {
         cargo.env("CFG_DEFAULT_CODEGEN_BACKEND", backend);
     }
 
@@ -805,7 +801,7 @@ pub fn rustc_cargo_env(builder: &Builder<'_>, cargo: &mut Cargo, target: TargetS
         if builder.is_rust_llvm(target) {
             cargo.env("LLVM_RUSTLLVM", "1");
         }
-        let llvm_config = builder.ensure(native::Llvm { target });
+        let native::LlvmResult { llvm_config, .. } = builder.ensure(native::Llvm { target });
         cargo.env("LLVM_CONFIG", &llvm_config);
         if let Some(s) = target_config.and_then(|c| c.llvm_config.as_ref()) {
             cargo.env("CFG_LLVM_ROOT", s);
@@ -1341,9 +1337,10 @@ impl Step for Assemble {
         }
 
         if builder.config.rust_codegen_backends.contains(&INTERNER.intern_str("llvm")) {
-            let llvm_config_bin = builder.ensure(native::Llvm { target: target_compiler.host });
+            let native::LlvmResult { llvm_config, .. } =
+                builder.ensure(native::Llvm { target: target_compiler.host });
             if !builder.config.dry_run() {
-                let llvm_bin_dir = output(Command::new(llvm_config_bin).arg("--bindir"));
+                let llvm_bin_dir = output(Command::new(llvm_config).arg("--bindir"));
                 let llvm_bin_dir = Path::new(llvm_bin_dir.trim());
 
                 // Since we've already built the LLVM tools, install them to the sysroot.
diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs
index 2906616ffad..b41d60d51a8 100644
--- a/src/bootstrap/config.rs
+++ b/src/bootstrap/config.rs
@@ -49,10 +49,7 @@ pub enum DryRun {
 
 /// Global configuration for the entire build and/or bootstrap.
 ///
-/// This structure is derived from a combination of both `config.toml` and
-/// `config.mk`. As of the time of this writing it's unlikely that `config.toml`
-/// is used all that much, so this is primarily filled out by `config.mk` which
-/// is generated from `./configure`.
+/// This structure is parsed from `config.toml`, and some of the fields are inferred from `git` or build-time parameters.
 ///
 /// Note that this structure is not decoded directly into, but rather it is
 /// filled out from the decoded forms of the structs below. For documentation
@@ -1611,6 +1608,10 @@ impl Config {
         self.submodules.unwrap_or(rust_info.is_managed_git_subrepository())
     }
 
+    pub fn default_codegen_backend(&self) -> Option<Interned<String>> {
+        self.rust_codegen_backends.get(0).cloned()
+    }
+
     /// Returns the commit to download, or `None` if we shouldn't download CI artifacts.
     fn download_ci_rustc_commit(&self, download_rustc: Option<StringOrBool>) -> Option<String> {
         // If `download-rustc` is not set, default to rebuilding.
diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs
index 3cb0eccd324..340aa78ebf9 100644
--- a/src/bootstrap/dist.rs
+++ b/src/bootstrap/dist.rs
@@ -24,6 +24,7 @@ use crate::channel;
 use crate::compile;
 use crate::config::TargetSelection;
 use crate::doc::DocumentationFormat;
+use crate::native;
 use crate::tarball::{GeneratedTarball, OverlayKind, Tarball};
 use crate::tool::{self, Tool};
 use crate::util::{exe, is_dylib, output, t, timeit};
@@ -1927,7 +1928,9 @@ fn maybe_install_llvm(builder: &Builder<'_>, target: TargetSelection, dst_libdir
             builder.install(&llvm_dylib_path, dst_libdir, 0o644);
         }
         !builder.config.dry_run()
-    } else if let Ok(llvm_config) = crate::native::prebuilt_llvm_config(builder, target) {
+    } else if let Ok(native::LlvmResult { llvm_config, .. }) =
+        native::prebuilt_llvm_config(builder, target)
+    {
         let mut cmd = Command::new(llvm_config);
         cmd.arg("--libfiles");
         builder.verbose(&format!("running {:?}", cmd));
@@ -2137,7 +2140,7 @@ impl Step for Bootstrap {
         let tarball = Tarball::new(builder, "bootstrap", &target.triple);
 
         let bootstrap_outdir = &builder.bootstrap_out;
-        for file in &["bootstrap", "llvm-config-wrapper", "rustc", "rustdoc", "sccache-plus-cl"] {
+        for file in &["bootstrap", "rustc", "rustdoc", "sccache-plus-cl"] {
             tarball.add_file(bootstrap_outdir.join(exe(file, target)), "bootstrap/bin", 0o755);
         }
 
diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs
index 2c6fd1e1d4d..5838049aa5c 100644
--- a/src/bootstrap/doc.rs
+++ b/src/bootstrap/doc.rs
@@ -729,7 +729,7 @@ impl Step for Rustc {
 }
 
 macro_rules! tool_doc {
-    ($tool: ident, $should_run: literal, $path: literal, [$($krate: literal),+ $(,)?] $(,)?) => {
+    ($tool: ident, $should_run: literal, $path: literal, $(rustc_tool = $rustc_tool:literal, )? $(in_tree = $in_tree:literal, )? [$($krate: literal),+ $(,)?] $(,)?) => {
         #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
         pub struct $tool {
             target: TargetSelection,
@@ -763,13 +763,24 @@ macro_rules! tool_doc {
                 let out = builder.compiler_doc_out(target);
                 t!(fs::create_dir_all(&out));
 
-                // Build rustc docs so that we generate relative links.
-                builder.ensure(Rustc { stage, target });
-                // Rustdoc needs the rustc sysroot available to build.
-                // FIXME: is there a way to only ensure `check::Rustc` here? Last time I tried it failed
-                // with strange errors, but only on a full bors test ...
                 let compiler = builder.compiler(stage, builder.config.build);
-                builder.ensure(compile::Rustc::new(compiler, target));
+                builder.ensure(compile::Std::new(compiler, target));
+
+                if true $(&& $rustc_tool)? {
+                    // Build rustc docs so that we generate relative links.
+                    builder.ensure(Rustc { stage, target });
+
+                    // Rustdoc needs the rustc sysroot available to build.
+                    // FIXME: is there a way to only ensure `check::Rustc` here? Last time I tried it failed
+                    // with strange errors, but only on a full bors test ...
+                    builder.ensure(compile::Rustc::new(compiler, target));
+                }
+
+                let source_type = if true $(&& $in_tree)? {
+                    SourceType::InTree
+                } else {
+                    SourceType::Submodule
+                };
 
                 builder.info(
                     &format!(
@@ -781,9 +792,15 @@ macro_rules! tool_doc {
                 );
 
                 // Symlink compiler docs to the output directory of rustdoc documentation.
-                let out_dir = builder.stage_out(compiler, Mode::ToolRustc).join(target.triple).join("doc");
-                t!(fs::create_dir_all(&out_dir));
-                t!(symlink_dir_force(&builder.config, &out, &out_dir));
+                let out_dirs = [
+                    builder.stage_out(compiler, Mode::ToolRustc).join(target.triple).join("doc"),
+                    // Cargo uses a different directory for proc macros.
+                    builder.stage_out(compiler, Mode::ToolRustc).join("doc"),
+                ];
+                for out_dir in out_dirs {
+                    t!(fs::create_dir_all(&out_dir));
+                    t!(symlink_dir_force(&builder.config, &out, &out_dir));
+                }
 
                 // Build cargo command.
                 let mut cargo = prepare_tool_cargo(
@@ -793,7 +810,7 @@ macro_rules! tool_doc {
                     target,
                     "doc",
                     $path,
-                    SourceType::InTree,
+                    source_type,
                     &[],
                 );
 
@@ -824,6 +841,30 @@ tool_doc!(
 );
 tool_doc!(Clippy, "clippy", "src/tools/clippy", ["clippy_utils"]);
 tool_doc!(Miri, "miri", "src/tools/miri", ["miri"]);
+tool_doc!(
+    Cargo,
+    "cargo",
+    "src/tools/cargo",
+    rustc_tool = false,
+    in_tree = false,
+    [
+        "cargo",
+        "cargo-platform",
+        "cargo-util",
+        "crates-io",
+        "cargo-test-macro",
+        "cargo-test-support",
+        "cargo-credential",
+        "cargo-credential-1password",
+        "mdman",
+        // FIXME: this trips a license check in tidy.
+        // "resolver-tests",
+        // FIXME: we should probably document these, but they're different per-platform so we can't use `tool_doc`.
+        // "cargo-credential-gnome-secret",
+        // "cargo-credential-macos-keychain",
+        // "cargo-credential-wincred",
+    ]
+);
 
 #[derive(Ord, PartialOrd, Debug, Copy, Clone, Hash, PartialEq, Eq)]
 pub struct ErrorIndex {
diff --git a/src/bootstrap/flags.rs b/src/bootstrap/flags.rs
index 851cb5ecf4c..3be7ad4075e 100644
--- a/src/bootstrap/flags.rs
+++ b/src/bootstrap/flags.rs
@@ -130,6 +130,7 @@ pub enum Subcommand {
         test_args: Vec<String>,
     },
     Clean {
+        paths: Vec<PathBuf>,
         all: bool,
     },
     Dist {
@@ -351,7 +352,17 @@ To learn more about a subcommand, run `./x.py <subcommand> -h`",
 
         // fn usage()
         let usage = |exit_code: i32, opts: &Options, verbose: bool, subcommand_help: &str| -> ! {
-            let config = Config::parse(&["setup".to_string()]);
+            // We have an unfortunate situation here: some Steps use `builder.in_tree_crates` to determine their paths.
+            // To determine those crates, we need to run `cargo metadata`, which means we need all submodules to be checked out.
+            // That takes a while to run, so only do it when paths were explicitly requested, not on all CLI errors.
+            // `Build::new` won't load submodules for the `setup` command.
+            let cmd = if verbose {
+                println!("note: updating submodules before printing available paths");
+                "build"
+            } else {
+                "setup"
+            };
+            let config = Config::parse(&[cmd.to_string()]);
             let build = Build::new(config);
             let paths = Builder::get_help(&build, subcommand);
 
@@ -601,14 +612,7 @@ Arguments:
                 open: matches.opt_present("open"),
                 json: matches.opt_present("json"),
             },
-            Kind::Clean => {
-                if !paths.is_empty() {
-                    println!("\nclean does not take a path argument\n");
-                    usage(1, &opts, verbose, &subcommand_help);
-                }
-
-                Subcommand::Clean { all: matches.opt_present("all") }
-            }
+            Kind::Clean => Subcommand::Clean { all: matches.opt_present("all"), paths },
             Kind::Format => Subcommand::Format { check: matches.opt_present("check"), paths },
             Kind::Dist => Subcommand::Dist { paths },
             Kind::Install => Subcommand::Install { paths },
diff --git a/src/bootstrap/format.rs b/src/bootstrap/format.rs
index b2f6afead79..b49322e3c02 100644
--- a/src/bootstrap/format.rs
+++ b/src/bootstrap/format.rs
@@ -1,7 +1,7 @@
 //! Runs rustfmt on the repository.
 
 use crate::builder::Builder;
-use crate::util::{output, t};
+use crate::util::{output, program_out_of_date, t};
 use ignore::WalkBuilder;
 use std::collections::VecDeque;
 use std::path::{Path, PathBuf};
@@ -44,6 +44,90 @@ fn rustfmt(src: &Path, rustfmt: &Path, paths: &[PathBuf], check: bool) -> impl F
     }
 }
 
+fn get_rustfmt_version(build: &Builder<'_>) -> Option<(String, PathBuf)> {
+    let stamp_file = build.out.join("rustfmt.stamp");
+
+    let mut cmd = Command::new(match build.initial_rustfmt() {
+        Some(p) => p,
+        None => return None,
+    });
+    cmd.arg("--version");
+    let output = match cmd.output() {
+        Ok(status) => status,
+        Err(_) => return None,
+    };
+    if !output.status.success() {
+        return None;
+    }
+    Some((String::from_utf8(output.stdout).unwrap(), stamp_file))
+}
+
+/// Return whether the format cache can be reused.
+fn verify_rustfmt_version(build: &Builder<'_>) -> bool {
+    let Some((version, stamp_file)) = get_rustfmt_version(build) else {return false;};
+    !program_out_of_date(&stamp_file, &version)
+}
+
+/// Updates the last rustfmt version used
+fn update_rustfmt_version(build: &Builder<'_>) {
+    let Some((version, stamp_file)) = get_rustfmt_version(build) else {return;};
+    t!(std::fs::write(stamp_file, version))
+}
+
+/// Returns the files modified between the `merge-base` of HEAD and
+/// rust-lang/master and what is now on the disk.
+///
+/// Returns `None` if all files should be formatted.
+fn get_modified_files(build: &Builder<'_>) -> Option<Vec<String>> {
+    let Ok(remote) = get_rust_lang_rust_remote() else {return None;};
+    if !verify_rustfmt_version(build) {
+        return None;
+    }
+    Some(
+        output(
+            build
+                .config
+                .git()
+                .arg("diff-index")
+                .arg("--name-only")
+                .arg("--merge-base")
+                .arg(&format!("{remote}/master")),
+        )
+        .lines()
+        .map(|s| s.trim().to_owned())
+        .collect(),
+    )
+}
+
+/// Finds the remote for rust-lang/rust.
+/// For example for these remotes it will return `upstream`.
+/// ```text
+/// origin  https://github.com/Nilstrieb/rust.git (fetch)
+/// origin  https://github.com/Nilstrieb/rust.git (push)
+/// upstream        https://github.com/rust-lang/rust (fetch)
+/// upstream        https://github.com/rust-lang/rust (push)
+/// ```
+fn get_rust_lang_rust_remote() -> Result<String, String> {
+    let mut git = Command::new("git");
+    git.args(["config", "--local", "--get-regex", "remote\\..*\\.url"]);
+
+    let output = git.output().map_err(|err| format!("{err:?}"))?;
+    if !output.status.success() {
+        return Err("failed to execute git config command".to_owned());
+    }
+
+    let stdout = String::from_utf8(output.stdout).map_err(|err| format!("{err:?}"))?;
+
+    let rust_lang_remote = stdout
+        .lines()
+        .find(|remote| remote.contains("rust-lang"))
+        .ok_or_else(|| "rust-lang/rust remote not found".to_owned())?;
+
+    let remote_name =
+        rust_lang_remote.split('.').nth(1).ok_or_else(|| "remote name not found".to_owned())?;
+    Ok(remote_name.into())
+}
+
 #[derive(serde::Deserialize)]
 struct RustfmtConfig {
     ignore: Vec<String>,
@@ -110,6 +194,14 @@ pub fn format(build: &Builder<'_>, check: bool, paths: &[PathBuf]) {
                 // preventing the latter from being formatted.
                 ignore_fmt.add(&format!("!/{}", untracked_path)).expect(&untracked_path);
             }
+            if !check && paths.is_empty() {
+                if let Some(files) = get_modified_files(build) {
+                    for file in files {
+                        println!("formatting modified file {file}");
+                        ignore_fmt.add(&format!("/{file}")).expect(&file);
+                    }
+                }
+            }
         } else {
             println!("Not in git tree. Skipping git-aware format checks");
         }
@@ -187,4 +279,7 @@ pub fn format(build: &Builder<'_>, check: bool, paths: &[PathBuf]) {
     drop(tx);
 
     thread.join().unwrap();
+    if !check {
+        update_rustfmt_version(build);
+    }
 }
diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs
index 47fb4a38d05..5ea41d10bc8 100644
--- a/src/bootstrap/lib.rs
+++ b/src/bootstrap/lib.rs
@@ -202,6 +202,7 @@ const EXTRA_CHECK_CFGS: &[(Option<Mode>, &'static str, Option<&[&'static str]>)]
     (None, "bootstrap", None),
     (Some(Mode::Rustc), "parallel_compiler", None),
     (Some(Mode::ToolRustc), "parallel_compiler", None),
+    (Some(Mode::ToolRustc), "emulate_second_only_system", None),
     (Some(Mode::Codegen), "parallel_compiler", None),
     (Some(Mode::Std), "stdarch_intel_sde", None),
     (Some(Mode::Std), "no_fp_fmt_parse", None),
@@ -726,10 +727,6 @@ impl Build {
             return format::format(&builder::Builder::new(&self), *check, &paths);
         }
 
-        if let Subcommand::Clean { all } = self.config.cmd {
-            return clean::clean(self, all);
-        }
-
         // Download rustfmt early so that it can be used in rust-analyzer configs.
         let _ = &builder::Builder::new(&self).initial_rustfmt();
 
@@ -795,7 +792,7 @@ impl Build {
     /// Gets the space-separated set of activated features for the standard
     /// library.
     fn std_features(&self, target: TargetSelection) -> String {
-        let mut features = "panic-unwind".to_string();
+        let mut features = " panic-unwind".to_string();
 
         match self.config.llvm_libunwind(target) {
             LlvmLibunwind::InTree => features.push_str(" llvm-libunwind"),
@@ -1399,7 +1396,10 @@ impl Build {
         let mut list = vec![INTERNER.intern_str(root)];
         let mut visited = HashSet::new();
         while let Some(krate) = list.pop() {
-            let krate = &self.crates[&krate];
+            let krate = self
+                .crates
+                .get(&krate)
+                .unwrap_or_else(|| panic!("metadata missing for {krate}: {:?}", self.crates));
             ret.push(krate);
             for dep in &krate.deps {
                 if !self.crates.contains_key(dep) {
diff --git a/src/bootstrap/mk/Makefile.in b/src/bootstrap/mk/Makefile.in
index 9a08a7be0f5..5b2aba9aa2d 100644
--- a/src/bootstrap/mk/Makefile.in
+++ b/src/bootstrap/mk/Makefile.in
@@ -57,11 +57,6 @@ tidy:
 prepare:
 	$(Q)$(BOOTSTRAP) build --stage 2 nonexistent/path/to/trigger/cargo/metadata
 
-check-stage2-T-arm-linux-androideabi-H-x86_64-unknown-linux-gnu:
-	$(Q)$(BOOTSTRAP) test --stage 2 --target arm-linux-androideabi
-check-stage2-T-x86_64-unknown-linux-musl-H-x86_64-unknown-linux-gnu:
-	$(Q)$(BOOTSTRAP) test --stage 2 --target x86_64-unknown-linux-musl
-
 TESTS_IN_2 := \
 	src/test/ui \
 	src/tools/linkchecker
diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs
index f6c453ebe10..4e503dfe864 100644
--- a/src/bootstrap/native.rs
+++ b/src/bootstrap/native.rs
@@ -24,9 +24,18 @@ use crate::util::get_clang_cl_resource_dir;
 use crate::util::{self, exe, output, t, up_to_date};
 use crate::{CLang, GitRepo};
 
+#[derive(Clone)]
+pub struct LlvmResult {
+    /// Path to llvm-config binary.
+    /// NB: This is always the host llvm-config!
+    pub llvm_config: PathBuf,
+    /// Path to LLVM cmake directory for the target.
+    pub llvm_cmake_dir: PathBuf,
+}
+
 pub struct Meta {
     stamp: HashStamp,
-    build_llvm_config: PathBuf,
+    res: LlvmResult,
     out_dir: PathBuf,
     root: String,
 }
@@ -64,7 +73,7 @@ impl LdFlags {
 pub fn prebuilt_llvm_config(
     builder: &Builder<'_>,
     target: TargetSelection,
-) -> Result<PathBuf, Meta> {
+) -> Result<LlvmResult, Meta> {
     builder.config.maybe_download_ci_llvm();
 
     // If we're using a custom LLVM bail out here, but we can only use a
@@ -72,7 +81,14 @@ pub fn prebuilt_llvm_config(
     if let Some(config) = builder.config.target_config.get(&target) {
         if let Some(ref s) = config.llvm_config {
             check_llvm_version(builder, s);
-            return Ok(s.to_path_buf());
+            let llvm_config = s.to_path_buf();
+            let mut llvm_cmake_dir = llvm_config.clone();
+            llvm_cmake_dir.pop();
+            llvm_cmake_dir.pop();
+            llvm_cmake_dir.push("lib");
+            llvm_cmake_dir.push("cmake");
+            llvm_cmake_dir.push("llvm");
+            return Ok(LlvmResult { llvm_config, llvm_cmake_dir });
         }
     }
 
@@ -84,8 +100,9 @@ pub fn prebuilt_llvm_config(
         llvm_config_ret_dir.push("build");
     }
     llvm_config_ret_dir.push("bin");
-
     let build_llvm_config = llvm_config_ret_dir.join(exe("llvm-config", builder.config.build));
+    let llvm_cmake_dir = out_dir.join("lib/cmake/llvm");
+    let res = LlvmResult { llvm_config: build_llvm_config, llvm_cmake_dir };
 
     let stamp = out_dir.join("llvm-finished-building");
     let stamp = HashStamp::new(stamp, builder.in_tree_llvm_info.sha());
@@ -96,7 +113,7 @@ pub fn prebuilt_llvm_config(
                 Using a potentially stale build of LLVM; \
                 This may not behave well.",
         );
-        return Ok(build_llvm_config);
+        return Ok(res);
     }
 
     if stamp.is_done() {
@@ -110,10 +127,10 @@ pub fn prebuilt_llvm_config(
                 stamp.path.display()
             ));
         }
-        return Ok(build_llvm_config);
+        return Ok(res);
     }
 
-    Err(Meta { stamp, build_llvm_config, out_dir, root: root.into() })
+    Err(Meta { stamp, res, out_dir, root: root.into() })
 }
 
 /// This retrieves the LLVM sha we *want* to use, according to git history.
@@ -223,7 +240,7 @@ pub struct Llvm {
 }
 
 impl Step for Llvm {
-    type Output = PathBuf; // path to llvm-config
+    type Output = LlvmResult;
 
     const ONLY_HOSTS: bool = true;
 
@@ -236,7 +253,7 @@ impl Step for Llvm {
     }
 
     /// Compile LLVM for `target`.
-    fn run(self, builder: &Builder<'_>) -> PathBuf {
+    fn run(self, builder: &Builder<'_>) -> LlvmResult {
         let target = self.target;
         let target_native = if self.target.starts_with("riscv") {
             // RISC-V target triples in Rust is not named the same as C compiler target triples.
@@ -252,11 +269,10 @@ impl Step for Llvm {
             target.to_string()
         };
 
-        let Meta { stamp, build_llvm_config, out_dir, root } =
-            match prebuilt_llvm_config(builder, target) {
-                Ok(p) => return p,
-                Err(m) => m,
-            };
+        let Meta { stamp, res, out_dir, root } = match prebuilt_llvm_config(builder, target) {
+            Ok(p) => return p,
+            Err(m) => m,
+        };
 
         builder.update_submodule(&Path::new("src").join("llvm-project"));
         if builder.llvm_link_shared() && target.contains("windows") {
@@ -430,7 +446,8 @@ impl Step for Llvm {
 
         // https://llvm.org/docs/HowToCrossCompileLLVM.html
         if target != builder.config.build {
-            let llvm_config = builder.ensure(Llvm { target: builder.config.build });
+            let LlvmResult { llvm_config, .. } =
+                builder.ensure(Llvm { target: builder.config.build });
             if !builder.config.dry_run() {
                 let llvm_bindir = output(Command::new(&llvm_config).arg("--bindir"));
                 let host_bin = Path::new(llvm_bindir.trim());
@@ -480,7 +497,7 @@ impl Step for Llvm {
         //        tools and libs on all platforms.
 
         if builder.config.dry_run() {
-            return build_llvm_config;
+            return res;
         }
 
         cfg.build();
@@ -490,7 +507,7 @@ impl Step for Llvm {
         // for a versioned path like libLLVM-14.dylib. Manually create a symbolic
         // link to make llvm-config happy.
         if builder.llvm_link_shared() && target.contains("apple-darwin") {
-            let mut cmd = Command::new(&build_llvm_config);
+            let mut cmd = Command::new(&res.llvm_config);
             let version = output(cmd.arg("--version"));
             let major = version.split('.').next().unwrap();
             let lib_name = match llvm_version_suffix {
@@ -509,18 +526,18 @@ impl Step for Llvm {
         // LLVM after a configuration change, so to rebuild it the build files have to be removed,
         // which will also remove these modified files.
         if builder.config.llvm_bolt_profile_generate {
-            instrument_with_bolt_inplace(&get_built_llvm_lib_path(&build_llvm_config));
+            instrument_with_bolt_inplace(&get_built_llvm_lib_path(&res.llvm_config));
         }
         if let Some(path) = &builder.config.llvm_bolt_profile_use {
             optimize_library_with_bolt_inplace(
-                &get_built_llvm_lib_path(&build_llvm_config),
+                &get_built_llvm_lib_path(&res.llvm_config),
                 &Path::new(path),
             );
         }
 
         t!(stamp.write());
 
-        build_llvm_config
+        res
     }
 }
 
@@ -600,6 +617,9 @@ fn configure_cmake(
             if target.starts_with("aarch64") {
                 // macOS uses a different name for building arm64
                 cfg.define("CMAKE_OSX_ARCHITECTURES", "arm64");
+            } else if target.starts_with("i686") {
+                // macOS uses a different name for building i386
+                cfg.define("CMAKE_OSX_ARCHITECTURES", "i386");
             } else {
                 cfg.define("CMAKE_OSX_ARCHITECTURES", target.triple.split('-').next().unwrap());
             }
@@ -803,7 +823,8 @@ impl Step for Lld {
         }
         let target = self.target;
 
-        let llvm_config = builder.ensure(Llvm { target: self.target });
+        let LlvmResult { llvm_config, llvm_cmake_dir } =
+            builder.ensure(Llvm { target: self.target });
 
         let out_dir = builder.lld_out(target);
         let done_stamp = out_dir.join("lld-finished-building");
@@ -834,22 +855,6 @@ impl Step for Lld {
         configure_cmake(builder, target, &mut cfg, true, ldflags);
         configure_llvm(builder, target, &mut cfg);
 
-        // This is an awful, awful hack. Discovered when we migrated to using
-        // clang-cl to compile LLVM/LLD it turns out that LLD, when built out of
-        // tree, will execute `llvm-config --cmakedir` and then tell CMake about
-        // that directory for later processing. Unfortunately if this path has
-        // forward slashes in it (which it basically always does on Windows)
-        // then CMake will hit a syntax error later on as... something isn't
-        // escaped it seems?
-        //
-        // Instead of attempting to fix this problem in upstream CMake and/or
-        // LLVM/LLD we just hack around it here. This thin wrapper will take the
-        // output from llvm-config and replace all instances of `\` with `/` to
-        // ensure we don't hit the same bugs with escaping. It means that you
-        // can't build on a system where your paths require `\` on Windows, but
-        // there's probably a lot of reasons you can't do that other than this.
-        let llvm_config_shim = env::current_exe().unwrap().with_file_name("llvm-config-wrapper");
-
         // Re-use the same flags as llvm to control the level of debug information
         // generated for lld.
         let profile = match (builder.config.llvm_optimize, builder.config.llvm_release_debuginfo) {
@@ -860,36 +865,17 @@ impl Step for Lld {
 
         cfg.out_dir(&out_dir)
             .profile(profile)
-            .env("LLVM_CONFIG_REAL", &llvm_config)
-            .define("LLVM_CONFIG_PATH", llvm_config_shim)
+            .define("LLVM_CMAKE_DIR", llvm_cmake_dir)
             .define("LLVM_INCLUDE_TESTS", "OFF");
 
-        // While we're using this horrible workaround to shim the execution of
-        // llvm-config, let's just pile on more. I can't seem to figure out how
-        // to build LLD as a standalone project and also cross-compile it at the
-        // same time. It wants a natively executable `llvm-config` to learn
-        // about LLVM, but then it learns about all the host configuration of
-        // LLVM and tries to link to host LLVM libraries.
-        //
-        // To work around that we tell our shim to replace anything with the
-        // build target with the actual target instead. This'll break parts of
-        // LLD though which try to execute host tools, such as llvm-tblgen, so
-        // we specifically tell it where to find those. This is likely super
-        // brittle and will break over time. If anyone knows better how to
-        // cross-compile LLD it would be much appreciated to fix this!
         if target != builder.config.build {
-            cfg.env("LLVM_CONFIG_SHIM_REPLACE", &builder.config.build.triple)
-                .env("LLVM_CONFIG_SHIM_REPLACE_WITH", &target.triple)
-                .define(
-                    "LLVM_TABLEGEN_EXE",
-                    llvm_config.with_file_name("llvm-tblgen").with_extension(EXE_EXTENSION),
-                );
+            // Use the host llvm-tblgen binary.
+            cfg.define(
+                "LLVM_TABLEGEN_EXE",
+                llvm_config.with_file_name("llvm-tblgen").with_extension(EXE_EXTENSION),
+            );
         }
 
-        // Explicitly set C++ standard, because upstream doesn't do so
-        // for standalone builds.
-        cfg.define("CMAKE_CXX_STANDARD", "14");
-
         cfg.build();
 
         t!(File::create(&done_stamp));
@@ -991,7 +977,7 @@ impl Step for Sanitizers {
             return runtimes;
         }
 
-        let llvm_config = builder.ensure(Llvm { target: builder.config.build });
+        let LlvmResult { llvm_config, .. } = builder.ensure(Llvm { target: builder.config.build });
         if builder.config.dry_run() {
             return runtimes;
         }
diff --git a/src/bootstrap/setup.rs b/src/bootstrap/setup.rs
index 57426ce3d51..cd360cbef96 100644
--- a/src/bootstrap/setup.rs
+++ b/src/bootstrap/setup.rs
@@ -96,6 +96,10 @@ impl Step for Profile {
     }
 
     fn make_run(run: RunConfig<'_>) {
+        if run.builder.config.dry_run() {
+            return;
+        }
+
         // for Profile, `run.paths` will have 1 and only 1 element
         // this is because we only accept at most 1 path from user input.
         // If user calls `x.py setup` without arguments, the interactive TUI
diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs
index 39cedfdac5f..0d9c22e210f 100644
--- a/src/bootstrap/test.rs
+++ b/src/bootstrap/test.rs
@@ -1575,7 +1575,8 @@ note: if you're sure you want to do this, please open an issue as to why. In the
         let mut llvm_components_passed = false;
         let mut copts_passed = false;
         if builder.config.llvm_enabled() {
-            let llvm_config = builder.ensure(native::Llvm { target: builder.config.build });
+            let native::LlvmResult { llvm_config, .. } =
+                builder.ensure(native::Llvm { target: builder.config.build });
             if !builder.config.dry_run() {
                 let llvm_version = output(Command::new(&llvm_config).arg("--version"));
                 let llvm_components = output(Command::new(&llvm_config).arg("--components"));
diff --git a/src/ci/docker/host-x86_64/mingw-check-tidy/Dockerfile b/src/ci/docker/host-x86_64/mingw-check-tidy/Dockerfile
new file mode 100644
index 00000000000..78fee152eb9
--- /dev/null
+++ b/src/ci/docker/host-x86_64/mingw-check-tidy/Dockerfile
@@ -0,0 +1,36 @@
+FROM ubuntu:18.04
+# FIXME: when bumping the version, remove the Python 3.6-specific changes in
+# the reuse-requirements.in file, regenerate reuse-requirements.txt and remove
+# this comment.
+
+RUN apt-get update && apt-get install -y --no-install-recommends \
+  g++ \
+  make \
+  ninja-build \
+  file \
+  curl \
+  ca-certificates \
+  python3 \
+  python3-pip \
+  python3-pkg-resources \
+  git \
+  cmake \
+  sudo \
+  gdb \
+  xz-utils \
+  libssl-dev \
+  pkg-config \
+  mingw-w64 \
+  && rm -rf /var/lib/apt/lists/*
+
+COPY scripts/sccache.sh /scripts/
+RUN sh /scripts/sccache.sh
+
+COPY host-x86_64/mingw-check/reuse-requirements.txt /tmp/
+RUN pip3 install --no-deps --no-cache-dir --require-hashes -r /tmp/reuse-requirements.txt
+
+COPY host-x86_64/mingw-check/validate-toolstate.sh /scripts/
+COPY host-x86_64/mingw-check/validate-error-codes.sh /scripts/
+
+ENV RUN_CHECK_WITH_PARALLEL_QUERIES 1
+ENV SCRIPT python3 ../x.py test --stage 0 src/tools/tidy
diff --git a/src/ci/docker/host-x86_64/mingw-check/Dockerfile b/src/ci/docker/host-x86_64/mingw-check/Dockerfile
index 9e2568af13f..adf6bb4b377 100644
--- a/src/ci/docker/host-x86_64/mingw-check/Dockerfile
+++ b/src/ci/docker/host-x86_64/mingw-check/Dockerfile
@@ -40,7 +40,6 @@ COPY host-x86_64/mingw-check/validate-error-codes.sh /scripts/
 
 ENV RUN_CHECK_WITH_PARALLEL_QUERIES 1
 ENV SCRIPT python3 ../x.py --stage 2 test src/tools/expand-yaml-anchors && \
-           python3 ../x.py test --stage 0 src/tools/tidy && \
            python3 ../x.py check --target=i686-pc-windows-gnu --host=i686-pc-windows-gnu --all-targets && \
            python3 ../x.py build --stage 0 src/tools/build-manifest && \
            python3 ../x.py test --stage 0 src/tools/compiletest && \
diff --git a/src/ci/github-actions/ci.yml b/src/ci/github-actions/ci.yml
index d1ba46ad30d..d33396dcc80 100644
--- a/src/ci/github-actions/ci.yml
+++ b/src/ci/github-actions/ci.yml
@@ -287,19 +287,27 @@ jobs:
     env:
       <<: [*shared-ci-variables, *public-variables]
     if: github.event_name == 'pull_request'
+    continue-on-error: ${{ matrix.tidy }}
     strategy:
       matrix:
         include:
           - name: mingw-check
             <<: *job-linux-xl
+            tidy: false
+
+          - name: mingw-check-tidy
+            <<: *job-linux-xl
+            tidy: true
 
           - name: x86_64-gnu-llvm-13
             <<: *job-linux-xl
+            tidy: false
 
           - name: x86_64-gnu-tools
+            <<: *job-linux-xl
+            tidy: false
             env:
               CI_ONLY_WHEN_SUBMODULES_CHANGED: 1
-            <<: *job-linux-xl
 
   auto:
     permissions:
diff --git a/src/ci/run.sh b/src/ci/run.sh
index f05bb81d4a1..b6430027750 100755
--- a/src/ci/run.sh
+++ b/src/ci/run.sh
@@ -45,14 +45,6 @@ fi
 ci_dir=`cd $(dirname $0) && pwd`
 source "$ci_dir/shared.sh"
 
-if command -v python > /dev/null; then
-    PYTHON="python"
-elif command -v python3 > /dev/null; then
-    PYTHON="python3"
-else
-    PYTHON="python2"
-fi
-
 if ! isCI || isCiBranch auto || isCiBranch beta || isCiBranch try || isCiBranch try-perf; then
     RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --set build.print-step-timings --enable-verbose-tests"
     RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --set build.metrics"
@@ -201,7 +193,7 @@ if [ "$RUN_CHECK_WITH_PARALLEL_QUERIES" != "" ]; then
     mv metrics.json build
   fi
 
-  CARGO_INCREMENTAL=0 $PYTHON ../x.py check
+  CARGO_INCREMENTAL=0 ../x check
 fi
 
 sccache --show-stats || true
diff --git a/src/doc/rustdoc/src/write-documentation/the-doc-attribute.md b/src/doc/rustdoc/src/write-documentation/the-doc-attribute.md
index e3b08648999..8ecf05f0e12 100644
--- a/src/doc/rustdoc/src/write-documentation/the-doc-attribute.md
+++ b/src/doc/rustdoc/src/write-documentation/the-doc-attribute.md
@@ -9,11 +9,11 @@ are the same:
 
 ```rust,no_run
 /// This is a doc comment.
-#[doc = " This is a doc comment."]
+#[doc = r" This is a doc comment."]
 # fn f() {}
 ```
 
-(Note the leading space in the attribute version.)
+(Note the leading space and the raw string literal in the attribute version.)
 
 In most cases, `///` is easier to use than `#[doc]`. One case where the latter is easier is
 when generating documentation in macros; the `collapse-docs` pass will combine multiple
diff --git a/src/etc/pre-push.sh b/src/etc/pre-push.sh
index be7de3ebaf5..2a3086338b4 100755
--- a/src/etc/pre-push.sh
+++ b/src/etc/pre-push.sh
@@ -10,16 +10,8 @@ set -Eeuo pipefail
 # https://github.com/rust-lang/rust/issues/77620#issuecomment-705144570
 unset GIT_DIR
 ROOT_DIR="$(git rev-parse --show-toplevel)"
-COMMAND="$ROOT_DIR/x.py test tidy"
 
-if [[ "$OSTYPE" == "msys" || "$OSTYPE" == "win32" ]]; then
-  COMMAND="python $COMMAND"
-elif ! command -v python &> /dev/null; then
-  COMMAND="python3 $COMMAND"
-fi
-
-echo "Running pre-push script '$COMMAND'"
+echo "Running pre-push script $ROOT_DIR/x test tidy"
 
 cd "$ROOT_DIR"
-
-$COMMAND
+./x test tidy
diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs
index 39e2a902226..5ad24bf2681 100644
--- a/src/librustdoc/html/format.rs
+++ b/src/librustdoc/html/format.rs
@@ -1655,10 +1655,10 @@ impl clean::types::Term {
         &'a self,
         cx: &'a Context<'tcx>,
     ) -> impl fmt::Display + 'a + Captures<'tcx> {
-        match self {
-            clean::types::Term::Type(ty) => ty.print(cx),
-            _ => todo!(),
-        }
+        display_fn(move |f| match self {
+            clean::types::Term::Type(ty) => fmt::Display::fmt(&ty.print(cx), f),
+            clean::types::Term::Constant(ct) => fmt::Display::fmt(&ct.print(cx.tcx()), f),
+        })
     }
 }
 
diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs
index 146e5010e4e..8bccf68029a 100644
--- a/src/librustdoc/html/render/mod.rs
+++ b/src/librustdoc/html/render/mod.rs
@@ -3005,8 +3005,7 @@ fn render_call_locations(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Ite
                   </summary>\
                   <div class=\"hide-more\">Hide additional examples</div>\
                   <div class=\"more-scraped-examples\">\
-                    <div class=\"toggle-line\"><div class=\"toggle-line-inner\"></div></div>\
-                    <div class=\"more-scraped-examples-inner\">"
+                    <div class=\"toggle-line\"><div class=\"toggle-line-inner\"></div></div>"
         );
 
         // Only generate inline code for MAX_FULL_EXAMPLES number of examples. Otherwise we could
@@ -3030,7 +3029,7 @@ fn render_call_locations(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Ite
             write!(w, "</ul></div>");
         }
 
-        write!(w, "</div></div></details>");
+        write!(w, "</div></details>");
     }
 
     write!(w, "</div>");
diff --git a/src/librustdoc/html/render/write_shared.rs b/src/librustdoc/html/render/write_shared.rs
index 94d8a9feca6..eaf149a4300 100644
--- a/src/librustdoc/html/render/write_shared.rs
+++ b/src/librustdoc/html/render/write_shared.rs
@@ -137,7 +137,7 @@ pub(super) fn write_shared(
         Ok((ret, krates))
     }
 
-    /// Read a file and return all lines that match the <code>"{crate}":{data},\</code> format,
+    /// Read a file and return all lines that match the <code>"{crate}":{data},\ </code> format,
     /// and return a tuple `(Vec<DataString>, Vec<CrateNameString>)`.
     ///
     /// This forms the payload of files that look like this:
diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css
index 11e34a3fc7d..2a41d3579e1 100644
--- a/src/librustdoc/html/static/css/rustdoc.css
+++ b/src/librustdoc/html/static/css/rustdoc.css
@@ -347,6 +347,9 @@ pre {
 .source .content pre {
 	padding: 20px;
 }
+.rustdoc.source .example-wrap > pre.src-line-numbers  {
+	padding: 20px 0 20px 4px;
+}
 
 img {
 	max-width: 100%;
@@ -361,6 +364,10 @@ img {
 	line-height: 0;
 }
 
+.sub-logo-container {
+	margin-right: 32px;
+}
+
 .sub-logo-container > img {
 	height: 60px;
 	width: 60px;
@@ -371,10 +378,6 @@ img {
 	filter: var(--rust-logo-filter);
 }
 
-.sidebar, .mobile-topbar, .sidebar-menu-toggle {
-	background-color: var(--sidebar-background-color);
-}
-
 .sidebar {
 	font-size: 0.875rem;
 	flex: 0 0 200px;
@@ -393,7 +396,8 @@ img {
 	overflow-y: hidden;
 }
 
-.source .sidebar, #src-sidebar-toggle, #source-sidebar {
+.sidebar, .mobile-topbar, .sidebar-menu-toggle,
+#src-sidebar-toggle, #source-sidebar {
 	background-color: var(--sidebar-background-color);
 }
 
@@ -519,10 +523,6 @@ ul.block, .block li {
 	display: none;
 }
 
-.source .content pre.rust {
-	padding-left: 0;
-}
-
 .rustdoc .example-wrap {
 	display: flex;
 	position: relative;
@@ -543,29 +543,28 @@ ul.block, .block li {
 .rustdoc .example-wrap > pre.example-line-numbers,
 .rustdoc .example-wrap > pre.src-line-numbers {
 	flex-grow: 0;
+	min-width: fit-content; /* prevent collapsing into nothing in truncated scraped examples */
 	overflow: initial;
 	text-align: right;
 	-webkit-user-select: none;
 	-moz-user-select: none;
 	-ms-user-select: none;
 	user-select: none;
+	padding: 14px 8px;
+	color: var(--src-line-numbers-span-color);
 }
 
-.example-line-numbers {
-	border: 1px solid;
-	padding: 13px 8px;
-	border-top-left-radius: 5px;
-	border-bottom-left-radius: 5px;
-	border-color: var(--example-line-numbers-border-color);
+.rustdoc .example-wrap > pre.src-line-numbers {
+	padding: 14px 0;
 }
-
 .src-line-numbers a, .src-line-numbers span {
 	color: var(--src-line-numbers-span-color);
+	padding: 0 8px;
 }
 .src-line-numbers :target {
 	background-color: transparent;
 	border-right: none;
-	padding-right: 0;
+	padding: 0 8px;
 }
 .src-line-numbers .line-highlighted {
 	background-color: var(--src-line-number-highlighted-background-color);
@@ -578,8 +577,6 @@ ul.block, .block li {
 .docblock-short {
 	overflow-wrap: break-word;
 	overflow-wrap: anywhere;
-	overflow: hidden;
-	text-overflow: ellipsis;
 }
 /* Wrap non-pre code blocks (`text`) but not (```text```). */
 .docblock :not(pre) > code,
@@ -675,9 +672,6 @@ nav.sub {
 .source nav.sub {
 	margin: 0 0 15px 0;
 }
-.source .search-form {
-	margin-left: 32px;
-}
 
 a {
 	text-decoration: none;
@@ -689,14 +683,10 @@ a {
 	position: relative;
 }
 
-.small-section-header:hover > .anchor {
+.small-section-header:hover > .anchor, .impl:hover > .anchor,
+.trait-impl:hover > .anchor, .variant:hover > .anchor {
 	display: initial;
 }
-
-.impl:hover > .anchor, .trait-impl:hover > .anchor, .variant:hover > .anchor {
-	display: inline-block;
-	position: absolute;
-}
 .anchor {
 	display: none;
 	position: absolute;
@@ -1264,14 +1254,14 @@ a.test-arrow:hover {
 	margin-right: auto;
 }
 
-#titles {
+#search-tabs {
 	display: flex;
 	flex-direction: row;
 	gap: 1px;
 	margin-bottom: 4px;
 }
 
-#titles > button {
+#search-tabs button {
 	text-align: center;
 	font-size: 1.125rem;
 	border: 0;
@@ -1281,9 +1271,9 @@ a.test-arrow:hover {
 	color: inherit;
 }
 
-#titles > button > div.count {
-	display: inline-block;
+#search-tabs .count {
 	font-size: 1rem;
+	color: var(--search-tab-title-count-color);
 }
 
 #src-sidebar-toggle {
@@ -1708,7 +1698,7 @@ in storage.js
 		display: none !important;
 	}
 
-	#titles > button > div.count {
+	#search-tabs .count {
 		display: block;
 	}
 
@@ -1841,13 +1831,6 @@ in storage.js
 		height: 35px;
 		width: 35px;
 	}
-
-	#src-sidebar-toggle {
-		top: 10px;
-	}
-	.source-sidebar-expanded #src-sidebar-toggle {
-		top: unset;
-	}
 }
 
 .variant,
@@ -1963,15 +1946,6 @@ in storage.js
 	bottom: 0;
 }
 
-.scraped-example .code-wrapper .src-line-numbers {
-	padding: 14px 0;
-}
-
-.scraped-example .code-wrapper .src-line-numbers a,
-.scraped-example .code-wrapper .src-line-numbers span {
-	padding: 0 14px;
-}
-
 .scraped-example .code-wrapper .example-wrap {
 	width: 100%;
 	overflow-y: hidden;
@@ -1994,20 +1968,15 @@ in storage.js
 }
 
 .more-scraped-examples {
-	margin-left: 5px;
-	display: flex;
-	flex-direction: row;
-}
-
-.more-scraped-examples-inner {
-	/* 20px is width of toggle-line + toggle-line-inner */
-	width: calc(100% - 20px);
+	margin-left: 25px;
+	position: relative;
 }
 
 .toggle-line {
-	align-self: stretch;
-	margin-right: 10px;
-	margin-top: 5px;
+	position: absolute;
+	top: 5px;
+	bottom: 0;
+	right: calc(100% + 10px);
 	padding: 0 4px;
 	cursor: pointer;
 }
@@ -2015,6 +1984,11 @@ in storage.js
 .toggle-line-inner {
 	min-width: 2px;
 	height: 100%;
+	background: var(--scrape-example-toggle-line-background);
+}
+
+.toggle-line:hover .toggle-line-inner {
+	background: var(--scrape-example-toggle-line-hover-background);
 }
 
 .more-scraped-examples .scraped-example, .example-links {
diff --git a/src/librustdoc/html/static/css/themes/ayu.css b/src/librustdoc/html/static/css/themes/ayu.css
index de0dfcd4690..7d7bdfb92ce 100644
--- a/src/librustdoc/html/static/css/themes/ayu.css
+++ b/src/librustdoc/html/static/css/themes/ayu.css
@@ -45,6 +45,7 @@ Original by Dempfi (https://github.com/dempfi/ayu)
 	--search-color: #fff;
 	--search-results-alias-color: #c5c5c5;
 	--search-results-grey-color: #999;
+	--search-tab-title-count-color: #888;
 	--stab-background-color: #314559;
 	--stab-code-color: #e6e1cf;
 	--code-highlight-kw-color: #ff7733;
@@ -61,7 +62,6 @@ Original by Dempfi (https://github.com/dempfi/ayu)
 	--code-highlight-question-mark-color: #ff9011;
 	--code-highlight-comment-color: #788797;
 	--code-highlight-doc-comment-color: #a1ac88;
-	--example-line-numbers-border-color: none;
 	--src-line-numbers-span-color: #5c6773;
 	--src-line-number-highlighted-background-color: rgba(255, 236, 164, 0.06);
 	--test-arrow-color: #788797;
@@ -89,6 +89,8 @@ Original by Dempfi (https://github.com/dempfi/ayu)
 	--source-sidebar-background-hover: #14191f;
 	--table-alt-row-background-color: #191f26;
 	--codeblock-link-background: #333;
+	--scrape-example-toggle-line-background: #999;
+	--scrape-example-toggle-line-hover-background: #c5c5c5;
 }
 
 h1, h2, h3, h4 {
@@ -131,7 +133,7 @@ pre, .rustdoc.source .example-wrap {
 
 .src-line-numbers .line-highlighted {
 	color: #708090;
-	padding-right: 4px;
+	padding-right: 7px;
 	border-right: 1px solid #ffb44c;
 }
 
@@ -160,36 +162,28 @@ pre, .rustdoc.source .example-wrap {
 	color: #788797;
 }
 
-#titles > button.selected {
+#search-tabs > button.selected {
 	background-color: #141920 !important;
 	border-bottom: 1px solid #ffb44c !important;
 	border-top: none;
 }
 
-#titles > button:not(.selected) {
+#search-tabs > button:not(.selected) {
 	background-color: transparent !important;
 	border: none;
 }
 
-#titles > button:hover {
+#search-tabs > button:hover {
 	border-bottom: 1px solid rgba(242, 151, 24, 0.3);
 }
 
-#titles > button > div.count {
-	color: #888;
-}
-
 /* rules that this theme does not need to set, here to satisfy the rule checker */
 /* note that a lot of these are partially set in some way (meaning they are set
 individually rather than as a group) */
 /* FIXME: these rules should be at the bottom of the file but currently must be
 above the `@media (max-width: 700px)` rules due to a bug in the css checker */
 /* see https://github.com/rust-lang/rust/pull/71237#issuecomment-618170143 */
-pre.rust .lifetime {}
-pre.rust .kw {}
-#titles > button:hover, #titles > button.selected {}
-pre.rust .self, pre.rust .bool-val, pre.rust .prelude-val, pre.rust .attribute {}
-pre.rust .kw-2, pre.rust .prelude-ty {}
+#search-tabs > button:hover, #search-tabs > button.selected {}
 
 #settings-menu > a img {
 	filter: invert(100);
@@ -218,15 +212,9 @@ pre.rust .kw-2, pre.rust .prelude-ty {}
 .scraped-example .example-wrap .rust span.highlight.focus {
 	background: rgb(124, 75, 15);
 }
-.scraped-example:not(.expanded) .code-wrapper:before {
+.scraped-example:not(.expanded) .code-wrapper::before {
 	background: linear-gradient(to bottom, rgba(15, 20, 25, 1), rgba(15, 20, 25, 0));
 }
-.scraped-example:not(.expanded) .code-wrapper:after {
+.scraped-example:not(.expanded) .code-wrapper::after {
 	background: linear-gradient(to top, rgba(15, 20, 25, 1), rgba(15, 20, 25, 0));
 }
-.toggle-line-inner {
-	background: #999;
-}
-.toggle-line:hover .toggle-line-inner {
-	background: #c5c5c5;
-}
diff --git a/src/librustdoc/html/static/css/themes/dark.css b/src/librustdoc/html/static/css/themes/dark.css
index dd7fc689253..6dd15d2e1bb 100644
--- a/src/librustdoc/html/static/css/themes/dark.css
+++ b/src/librustdoc/html/static/css/themes/dark.css
@@ -40,6 +40,7 @@
 	--search-color: #111;
 	--search-results-alias-color: #fff;
 	--search-results-grey-color: #ccc;
+	--search-tab-title-count-color: #888;
 	--stab-background-color: #314559;
 	--stab-code-color: #e6e1cf;
 	--code-highlight-kw-color: #ab8ac1;
@@ -56,7 +57,6 @@
 	--code-highlight-question-mark-color: #ff9011;
 	--code-highlight-comment-color: #8d8d8b;
 	--code-highlight-doc-comment-color: #8ca375;
-	--example-line-numbers-border-color: #4a4949;
 	--src-line-numbers-span-color: #3b91e2;
 	--src-line-number-highlighted-background-color: #0a042f;
 	--test-arrow-color: #dedede;
@@ -84,22 +84,20 @@
 	--source-sidebar-background-hover: #444;
 	--table-alt-row-background-color: #2A2A2A;
 	--codeblock-link-background: #333;
+	--scrape-example-toggle-line-background: #999;
+	--scrape-example-toggle-line-hover-background: #c5c5c5;
 }
 
-#titles > button:not(.selected) {
+#search-tabs > button:not(.selected) {
 	background-color: #252525;
 	border-top-color: #252525;
 }
 
-#titles > button:hover, #titles > button.selected {
+#search-tabs > button:hover, #search-tabs > button.selected {
 	border-top-color: #0089ff;
 	background-color: #353535;
 }
 
-#titles > button > div.count {
-	color: #888;
-}
-
 .scraped-example-list .scrape-help {
 	border-color: #aaa;
 	color: #eee;
@@ -114,15 +112,9 @@
 .scraped-example .example-wrap .rust span.highlight.focus {
 	background: rgb(124, 75, 15);
 }
-.scraped-example:not(.expanded) .code-wrapper:before {
+.scraped-example:not(.expanded) .code-wrapper::before {
 	background: linear-gradient(to bottom, rgba(53, 53, 53, 1), rgba(53, 53, 53, 0));
 }
-.scraped-example:not(.expanded) .code-wrapper:after {
+.scraped-example:not(.expanded) .code-wrapper::after {
 	background: linear-gradient(to top, rgba(53, 53, 53, 1), rgba(53, 53, 53, 0));
 }
-.toggle-line-inner {
-	background: #999;
-}
-.toggle-line:hover .toggle-line-inner {
-	background: #c5c5c5;
-}
diff --git a/src/librustdoc/html/static/css/themes/light.css b/src/librustdoc/html/static/css/themes/light.css
index b69d8a1cff9..804e20d0d44 100644
--- a/src/librustdoc/html/static/css/themes/light.css
+++ b/src/librustdoc/html/static/css/themes/light.css
@@ -40,6 +40,7 @@
 	--search-color: #000;
 	--search-results-alias-color: #000;
 	--search-results-grey-color: #999;
+	--search-tab-title-count-color: #888;
 	--stab-background-color: #fff5d6;
 	--stab-code-color: #000;
 	--code-highlight-kw-color: #8959a8;
@@ -56,7 +57,6 @@
 	--code-highlight-question-mark-color: #ff9011;
 	--code-highlight-comment-color: #8e908c;
 	--code-highlight-doc-comment-color: #4d4d4c;
-	--example-line-numbers-border-color: #c7c7c7;
 	--src-line-numbers-span-color: #c67e2d;
 	--src-line-number-highlighted-background-color: #fdffd3;
 	--test-arrow-color: #f5f5f5;
@@ -81,22 +81,20 @@
 	--source-sidebar-background-hover: #e0e0e0;
 	--table-alt-row-background-color: #F5F5F5;
 	--codeblock-link-background: #eee;
+	--scrape-example-toggle-line-background: #ccc;
+	--scrape-example-toggle-line-hover-background: #999;
 }
 
-#titles > button:not(.selected) {
+#search-tabs > button:not(.selected) {
 	background-color: #e6e6e6;
 	border-top-color: #e6e6e6;
 }
 
-#titles > button:hover, #titles > button.selected {
+#search-tabs > button:hover, #search-tabs > button.selected {
 	background-color: #ffffff;
 	border-top-color: #0089ff;
 }
 
-#titles > button > div.count {
-	color: #888;
-}
-
 .scraped-example-list .scrape-help {
 	border-color: #555;
 	color: #333;
@@ -111,15 +109,9 @@
 .scraped-example .example-wrap .rust span.highlight.focus {
 	background: #f6fdb0;
 }
-.scraped-example:not(.expanded) .code-wrapper:before {
+.scraped-example:not(.expanded) .code-wrapper::before {
 	background: linear-gradient(to bottom, rgba(255, 255, 255, 1), rgba(255, 255, 255, 0));
 }
-.scraped-example:not(.expanded) .code-wrapper:after {
+.scraped-example:not(.expanded) .code-wrapper::after {
 	background: linear-gradient(to top, rgba(255, 255, 255, 1), rgba(255, 255, 255, 0));
 }
-.toggle-line-inner {
-	background: #ccc;
-}
-.toggle-line:hover .toggle-line-inner {
-	background: #999;
-}
diff --git a/src/librustdoc/html/static/js/main.js b/src/librustdoc/html/static/js/main.js
index 3f97e4e2e39..60e4e749224 100644
--- a/src/librustdoc/html/static/js/main.js
+++ b/src/librustdoc/html/static/js/main.js
@@ -813,16 +813,14 @@ function loadCss(cssUrl) {
         hideSidebar();
     });
 
-    onEachLazy(document.getElementsByTagName("a"), el => {
+    onEachLazy(document.querySelectorAll("a[href^='#']"), el => {
         // For clicks on internal links (<A> tags with a hash property), we expand the section we're
         // jumping to *before* jumping there. We can't do this in onHashChange, because it changes
         // the height of the document so we wind up scrolled to the wrong place.
-        if (el.hash) {
-            el.addEventListener("click", () => {
-                expandSection(el.hash.slice(1));
-                hideSidebar();
-            });
-        }
+        el.addEventListener("click", () => {
+            expandSection(el.hash.slice(1));
+            hideSidebar();
+        });
     });
 
     onEachLazy(document.querySelectorAll(".rustdoc-toggle > summary:not(.hideme)"), el => {
diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js
index 23ae4e97082..1b8822b0b2b 100644
--- a/src/librustdoc/html/static/js/search.js
+++ b/src/librustdoc/html/static/js/search.js
@@ -49,7 +49,7 @@ function printTab(nb) {
     let iter = 0;
     let foundCurrentTab = false;
     let foundCurrentResultSet = false;
-    onEachLazy(document.getElementById("titles").childNodes, elem => {
+    onEachLazy(document.getElementById("search-tabs").childNodes, elem => {
         if (nb === iter) {
             addClass(elem, "selected");
             foundCurrentTab = true;
@@ -1490,7 +1490,7 @@ function initSearch(rawSearchIndex) {
     function focusSearchResult() {
         const target = searchState.focusedByTab[searchState.currentTab] ||
             document.querySelectorAll(".search-results.active a").item(0) ||
-            document.querySelectorAll("#titles > button").item(searchState.currentTab);
+            document.querySelectorAll("#search-tabs button").item(searchState.currentTab);
         searchState.focusedByTab[searchState.currentTab] = null;
         if (target) {
             target.focus();
@@ -1645,9 +1645,9 @@ function initSearch(rawSearchIndex) {
     function makeTabHeader(tabNb, text, nbElems) {
         if (searchState.currentTab === tabNb) {
             return "<button class=\"selected\">" + text +
-                   " <div class=\"count\">(" + nbElems + ")</div></button>";
+                   " <span class=\"count\">(" + nbElems + ")</span></button>";
         }
-        return "<button>" + text + " <div class=\"count\">(" + nbElems + ")</div></button>";
+        return "<button>" + text + " <span class=\"count\">(" + nbElems + ")</span></button>";
     }
 
     /**
@@ -1712,12 +1712,12 @@ function initSearch(rawSearchIndex) {
         let output = `<h1 class="search-results-title">Results${crates}</h1>`;
         if (results.query.error !== null) {
             output += `<h3>Query parser error: "${results.query.error}".</h3>`;
-            output += "<div id=\"titles\">" +
+            output += "<div id=\"search-tabs\">" +
                 makeTabHeader(0, "In Names", ret_others[1]) +
                 "</div>";
             currentTab = 0;
         } else if (results.query.foundElems <= 1 && results.query.returned.length === 0) {
-            output += "<div id=\"titles\">" +
+            output += "<div id=\"search-tabs\">" +
                 makeTabHeader(0, "In Names", ret_others[1]) +
                 makeTabHeader(1, "In Parameters", ret_in_args[1]) +
                 makeTabHeader(2, "In Return Types", ret_returned[1]) +
@@ -1727,7 +1727,7 @@ function initSearch(rawSearchIndex) {
                 results.query.elems.length === 0 ? "In Function Return Types" :
                 results.query.returned.length === 0 ? "In Function Parameters" :
                 "In Function Signatures";
-            output += "<div id=\"titles\">" +
+            output += "<div id=\"search-tabs\">" +
                 makeTabHeader(0, signatureTabTitle, ret_others[1]) +
                 "</div>";
             currentTab = 0;
@@ -1747,7 +1747,7 @@ function initSearch(rawSearchIndex) {
         search.appendChild(resultsElem);
         // Reset focused elements.
         searchState.showResults(search);
-        const elems = document.getElementById("titles").childNodes;
+        const elems = document.getElementById("search-tabs").childNodes;
         searchState.focusedByTab = [];
         let i = 0;
         for (const elem of elems) {
diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs
index 22068ebe041..310a01194ea 100644
--- a/src/librustdoc/visit_ast.rs
+++ b/src/librustdoc/visit_ast.rs
@@ -5,8 +5,10 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::DefId;
+use rustc_hir::intravisit::{walk_item, Visitor};
 use rustc_hir::Node;
 use rustc_hir::CRATE_HIR_ID;
+use rustc_middle::hir::nested_filter;
 use rustc_middle::ty::TyCtxt;
 use rustc_span::def_id::{CRATE_DEF_ID, LOCAL_CRATE};
 use rustc_span::symbol::{kw, sym, Symbol};
@@ -57,9 +59,6 @@ pub(crate) fn inherits_doc_hidden(tcx: TyCtxt<'_>, mut node: hir::HirId) -> bool
     false
 }
 
-// Also, is there some reason that this doesn't use the 'visit'
-// framework from syntax?.
-
 pub(crate) struct RustdocVisitor<'a, 'tcx> {
     cx: &'a mut core::DocContext<'tcx>,
     view_item_stack: FxHashSet<hir::HirId>,
@@ -67,6 +66,7 @@ pub(crate) struct RustdocVisitor<'a, 'tcx> {
     /// Are the current module and all of its parents public?
     inside_public_path: bool,
     exact_paths: FxHashMap<DefId, Vec<Symbol>>,
+    modules: Vec<Module<'tcx>>,
 }
 
 impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
@@ -74,12 +74,19 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
         // If the root is re-exported, terminate all recursion.
         let mut stack = FxHashSet::default();
         stack.insert(hir::CRATE_HIR_ID);
+        let om = Module::new(
+            cx.tcx.crate_name(LOCAL_CRATE),
+            hir::CRATE_HIR_ID,
+            cx.tcx.hir().root_module().spans.inner_span,
+        );
+
         RustdocVisitor {
             cx,
             view_item_stack: stack,
             inlining: false,
             inside_public_path: true,
             exact_paths: FxHashMap::default(),
+            modules: vec![om],
         }
     }
 
@@ -89,12 +96,10 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
     }
 
     pub(crate) fn visit(mut self) -> Module<'tcx> {
-        let mut top_level_module = self.visit_mod_contents(
-            hir::CRATE_HIR_ID,
-            self.cx.tcx.hir().root_module(),
-            self.cx.tcx.crate_name(LOCAL_CRATE),
-            None,
-        );
+        let root_module = self.cx.tcx.hir().root_module();
+        self.visit_mod_contents(CRATE_HIR_ID, root_module);
+
+        let mut top_level_module = self.modules.pop().unwrap();
 
         // `#[macro_export] macro_rules!` items are reexported at the top level of the
         // crate, regardless of where they're defined. We want to document the
@@ -109,15 +114,13 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
         // macro in the same module.
         let mut inserted = FxHashSet::default();
         for export in self.cx.tcx.module_reexports(CRATE_DEF_ID).unwrap_or(&[]) {
-            if let Res::Def(DefKind::Macro(_), def_id) = export.res {
-                if let Some(local_def_id) = def_id.as_local() {
-                    if self.cx.tcx.has_attr(def_id, sym::macro_export) {
-                        if inserted.insert(def_id) {
-                            let item = self.cx.tcx.hir().expect_item(local_def_id);
-                            top_level_module.items.push((item, None, None));
-                        }
-                    }
-                }
+            if let Res::Def(DefKind::Macro(_), def_id) = export.res &&
+                let Some(local_def_id) = def_id.as_local() &&
+                self.cx.tcx.has_attr(def_id, sym::macro_export) &&
+                inserted.insert(def_id)
+            {
+                    let item = self.cx.tcx.hir().expect_item(local_def_id);
+                    top_level_module.items.push((item, None, None));
             }
         }
 
@@ -151,24 +154,23 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
         top_level_module
     }
 
-    fn visit_mod_contents(
-        &mut self,
-        id: hir::HirId,
-        m: &'tcx hir::Mod<'tcx>,
-        name: Symbol,
-        parent_id: Option<hir::HirId>,
-    ) -> Module<'tcx> {
-        let mut om = Module::new(name, id, m.spans.inner_span);
+    /// This method will go through the given module items in two passes:
+    /// 1. The items which are not glob imports/reexports.
+    /// 2. The glob imports/reexports.
+    fn visit_mod_contents(&mut self, id: hir::HirId, m: &'tcx hir::Mod<'tcx>) {
+        debug!("Going through module {:?}", m);
         let def_id = self.cx.tcx.hir().local_def_id(id).to_def_id();
         // Keep track of if there were any private modules in the path.
         let orig_inside_public_path = self.inside_public_path;
         self.inside_public_path &= self.cx.tcx.visibility(def_id).is_public();
+
+        // Reimplementation of `walk_mod` because we need to do it in two passes (explanations in
+        // the second loop):
         for &i in m.item_ids {
             let item = self.cx.tcx.hir().item(i);
-            if matches!(item.kind, hir::ItemKind::Use(_, hir::UseKind::Glob)) {
-                continue;
+            if !matches!(item.kind, hir::ItemKind::Use(_, hir::UseKind::Glob)) {
+                self.visit_item(item);
             }
-            self.visit_item(item, None, &mut om, parent_id);
         }
         for &i in m.item_ids {
             let item = self.cx.tcx.hir().item(i);
@@ -176,11 +178,10 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
             // Later passes in rustdoc will de-duplicate by name and kind, so if glob-
             // imported items appear last, then they'll be the ones that get discarded.
             if matches!(item.kind, hir::ItemKind::Use(_, hir::UseKind::Glob)) {
-                self.visit_item(item, None, &mut om, parent_id);
+                self.visit_item(item);
             }
         }
         self.inside_public_path = orig_inside_public_path;
-        om
     }
 
     /// Tries to resolve the target of a `pub use` statement and inlines the
@@ -198,7 +199,6 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
         res: Res,
         renamed: Option<Symbol>,
         glob: bool,
-        om: &mut Module<'tcx>,
         please_inline: bool,
     ) -> bool {
         debug!("maybe_inline_local res: {:?}", res);
@@ -249,20 +249,20 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
                 let prev = mem::replace(&mut self.inlining, true);
                 for &i in m.item_ids {
                     let i = self.cx.tcx.hir().item(i);
-                    self.visit_item(i, None, om, Some(id));
+                    self.visit_item_inner(i, None, Some(id));
                 }
                 self.inlining = prev;
                 true
             }
             Node::Item(it) if !glob => {
                 let prev = mem::replace(&mut self.inlining, true);
-                self.visit_item(it, renamed, om, Some(id));
+                self.visit_item_inner(it, renamed, Some(id));
                 self.inlining = prev;
                 true
             }
             Node::ForeignItem(it) if !glob => {
                 let prev = mem::replace(&mut self.inlining, true);
-                self.visit_foreign_item(it, renamed, om);
+                self.visit_foreign_item_inner(it, renamed);
                 self.inlining = prev;
                 true
             }
@@ -272,13 +272,22 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
         ret
     }
 
-    fn visit_item(
+    #[inline]
+    fn add_to_current_mod(
         &mut self,
         item: &'tcx hir::Item<'_>,
         renamed: Option<Symbol>,
-        om: &mut Module<'tcx>,
         parent_id: Option<hir::HirId>,
     ) {
+        self.modules.last_mut().unwrap().items.push((item, renamed, parent_id))
+    }
+
+    fn visit_item_inner(
+        &mut self,
+        item: &'tcx hir::Item<'_>,
+        renamed: Option<Symbol>,
+        parent_id: Option<hir::HirId>,
+    ) -> bool {
         debug!("visiting item {:?}", item);
         let name = renamed.unwrap_or(item.ident.name);
 
@@ -293,7 +302,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
             hir::ItemKind::ForeignMod { items, .. } => {
                 for item in items {
                     let item = self.cx.tcx.hir().foreign_item(item.id);
-                    self.visit_foreign_item(item, None, om);
+                    self.visit_foreign_item_inner(item, None);
                 }
             }
             // If we're inlining, skip private items or item reexported as "_".
@@ -326,14 +335,13 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
                             res,
                             ident,
                             is_glob,
-                            om,
                             please_inline,
                         ) {
                             continue;
                         }
                     }
 
-                    om.items.push((item, renamed, parent_id))
+                    self.add_to_current_mod(item, renamed, parent_id);
                 }
             }
             hir::ItemKind::Macro(ref macro_def, _) => {
@@ -353,11 +361,11 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
                 let nonexported = !self.cx.tcx.has_attr(def_id, sym::macro_export);
 
                 if is_macro_2_0 || nonexported || self.inlining {
-                    om.items.push((item, renamed, None));
+                    self.add_to_current_mod(item, renamed, None);
                 }
             }
             hir::ItemKind::Mod(ref m) => {
-                om.mods.push(self.visit_mod_contents(item.hir_id(), m, name, parent_id));
+                self.enter_mod(item.hir_id(), m, name);
             }
             hir::ItemKind::Fn(..)
             | hir::ItemKind::ExternCrate(..)
@@ -368,33 +376,92 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
             | hir::ItemKind::OpaqueTy(..)
             | hir::ItemKind::Static(..)
             | hir::ItemKind::Trait(..)
-            | hir::ItemKind::TraitAlias(..) => om.items.push((item, renamed, parent_id)),
+            | hir::ItemKind::TraitAlias(..) => {
+                self.add_to_current_mod(item, renamed, parent_id);
+            }
             hir::ItemKind::Const(..) => {
                 // Underscore constants do not correspond to a nameable item and
                 // so are never useful in documentation.
                 if name != kw::Underscore {
-                    om.items.push((item, renamed, parent_id));
+                    self.add_to_current_mod(item, renamed, parent_id);
                 }
             }
             hir::ItemKind::Impl(impl_) => {
                 // Don't duplicate impls when inlining or if it's implementing a trait, we'll pick
                 // them up regardless of where they're located.
                 if !self.inlining && impl_.of_trait.is_none() {
-                    om.items.push((item, None, None));
+                    self.add_to_current_mod(item, None, None);
                 }
             }
         }
+        true
     }
 
-    fn visit_foreign_item(
+    fn visit_foreign_item_inner(
         &mut self,
         item: &'tcx hir::ForeignItem<'_>,
         renamed: Option<Symbol>,
-        om: &mut Module<'tcx>,
     ) {
         // If inlining we only want to include public functions.
         if !self.inlining || self.cx.tcx.visibility(item.owner_id).is_public() {
-            om.foreigns.push((item, renamed));
+            self.modules.last_mut().unwrap().foreigns.push((item, renamed));
         }
     }
+
+    /// This method will create a new module and push it onto the "modules stack" then call
+    /// `visit_mod_contents`. Once done, it'll remove it from the "modules stack" and instead
+    /// add into into the list of modules of the current module.
+    fn enter_mod(&mut self, id: hir::HirId, m: &'tcx hir::Mod<'tcx>, name: Symbol) {
+        self.modules.push(Module::new(name, id, m.spans.inner_span));
+
+        self.visit_mod_contents(id, m);
+
+        let last = self.modules.pop().unwrap();
+        self.modules.last_mut().unwrap().mods.push(last);
+    }
+}
+
+// We need to implement this visitor so it'll go everywhere and retrieve items we're interested in
+// such as impl blocks in const blocks.
+impl<'a, 'tcx> Visitor<'tcx> for RustdocVisitor<'a, 'tcx> {
+    type NestedFilter = nested_filter::All;
+
+    fn nested_visit_map(&mut self) -> Self::Map {
+        self.cx.tcx.hir()
+    }
+
+    fn visit_item(&mut self, i: &'tcx hir::Item<'tcx>) {
+        let parent_id = if self.modules.len() > 1 {
+            Some(self.modules[self.modules.len() - 2].id)
+        } else {
+            None
+        };
+        if self.visit_item_inner(i, None, parent_id) {
+            walk_item(self, i);
+        }
+    }
+
+    fn visit_mod(&mut self, _: &hir::Mod<'tcx>, _: Span, _: hir::HirId) {
+        // Handled in `visit_item_inner`
+    }
+
+    fn visit_use(&mut self, _: &hir::UsePath<'tcx>, _: hir::HirId) {
+        // Handled in `visit_item_inner`
+    }
+
+    fn visit_path(&mut self, _: &hir::Path<'tcx>, _: hir::HirId) {
+        // Handled in `visit_item_inner`
+    }
+
+    fn visit_label(&mut self, _: &rustc_ast::Label) {
+        // Unneeded.
+    }
+
+    fn visit_infer(&mut self, _: &hir::InferArg) {
+        // Unneeded.
+    }
+
+    fn visit_lifetime(&mut self, _: &hir::Lifetime) {
+        // Unneeded.
+    }
 }
diff --git a/src/test/assembly/x86_64-no-jump-tables.rs b/src/test/assembly/x86_64-no-jump-tables.rs
new file mode 100644
index 00000000000..007c3591a4a
--- /dev/null
+++ b/src/test/assembly/x86_64-no-jump-tables.rs
@@ -0,0 +1,34 @@
+// Test that jump tables are (not) emitted when the `-Zno-jump-tables`
+// flag is (not) set.
+
+// revisions: unset set
+// assembly-output: emit-asm
+// compile-flags: -O
+// [set] compile-flags: -Zno-jump-tables
+// only-x86_64
+
+#![crate_type = "lib"]
+
+extern "C" {
+    fn bar1();
+    fn bar2();
+    fn bar3();
+    fn bar4();
+    fn bar5();
+    fn bar6();
+}
+
+// CHECK-LABEL: foo:
+#[no_mangle]
+pub unsafe fn foo(x: i32) {
+    // unset: LJTI0_0
+    // set-NOT: LJTI0_0
+    match x {
+        1 => bar1(),
+        2 => bar2(),
+        3 => bar3(),
+        4 => bar4(),
+        5 => bar5(),
+        _ => bar6(),
+    }
+}
diff --git a/src/test/codegen/comparison-operators-newtype.rs b/src/test/codegen/comparison-operators-newtype.rs
new file mode 100644
index 00000000000..5cf6c3ac0a2
--- /dev/null
+++ b/src/test/codegen/comparison-operators-newtype.rs
@@ -0,0 +1,49 @@
+// The `derive(PartialOrd)` for a newtype doesn't override `lt`/`le`/`gt`/`ge`.
+// This double-checks that the `Option<Ordering>` intermediate values used
+// in the operators for such a type all optimize away.
+
+// compile-flags: -C opt-level=1
+// min-llvm-version: 15.0
+
+#![crate_type = "lib"]
+
+use std::cmp::Ordering;
+
+#[derive(PartialOrd, PartialEq)]
+pub struct Foo(u16);
+
+// CHECK-LABEL: @check_lt
+// CHECK-SAME: (i16 %[[A:.+]], i16 %[[B:.+]])
+#[no_mangle]
+pub fn check_lt(a: Foo, b: Foo) -> bool {
+    // CHECK: %[[R:.+]] = icmp ult i16 %[[A]], %[[B]]
+    // CHECK-NEXT: ret i1 %[[R]]
+    a < b
+}
+
+// CHECK-LABEL: @check_le
+// CHECK-SAME: (i16 %[[A:.+]], i16 %[[B:.+]])
+#[no_mangle]
+pub fn check_le(a: Foo, b: Foo) -> bool {
+    // CHECK: %[[R:.+]] = icmp ule i16 %[[A]], %[[B]]
+    // CHECK-NEXT: ret i1 %[[R]]
+    a <= b
+}
+
+// CHECK-LABEL: @check_gt
+// CHECK-SAME: (i16 %[[A:.+]], i16 %[[B:.+]])
+#[no_mangle]
+pub fn check_gt(a: Foo, b: Foo) -> bool {
+    // CHECK: %[[R:.+]] = icmp ugt i16 %[[A]], %[[B]]
+    // CHECK-NEXT: ret i1 %[[R]]
+    a > b
+}
+
+// CHECK-LABEL: @check_ge
+// CHECK-SAME: (i16 %[[A:.+]], i16 %[[B:.+]])
+#[no_mangle]
+pub fn check_ge(a: Foo, b: Foo) -> bool {
+    // CHECK: %[[R:.+]] = icmp uge i16 %[[A]], %[[B]]
+    // CHECK-NEXT: ret i1 %[[R]]
+    a >= b
+}
diff --git a/src/test/codegen/no-jump-tables.rs b/src/test/codegen/no-jump-tables.rs
new file mode 100644
index 00000000000..8e2cb47566e
--- /dev/null
+++ b/src/test/codegen/no-jump-tables.rs
@@ -0,0 +1,22 @@
+// Test that the `no-jump-tables` function attribute are (not) emitted when
+// the `-Zno-jump-tables` flag is (not) set.
+
+// revisions: unset set
+// needs-llvm-components: x86
+// compile-flags: --target x86_64-unknown-linux-gnu
+// [set] compile-flags: -Zno-jump-tables
+
+#![crate_type = "lib"]
+#![feature(no_core, lang_items)]
+#![no_core]
+
+#[lang = "sized"]
+trait Sized {}
+
+#[no_mangle]
+pub fn foo() {
+    // CHECK: @foo() unnamed_addr #0
+
+    // unset-NOT: attributes #0 = { {{.*}}"no-jump-tables"="true"{{.*}} }
+    // set: attributes #0 = { {{.*}}"no-jump-tables"="true"{{.*}} }
+}
diff --git a/src/test/codegen/sanitizer-kcfi-emit-kcfi-operand-bundle-itanium-cxx-abi.rs b/src/test/codegen/sanitizer-kcfi-emit-kcfi-operand-bundle-itanium-cxx-abi.rs
index 0afd9727517..8e0d02550ee 100644
--- a/src/test/codegen/sanitizer-kcfi-emit-kcfi-operand-bundle-itanium-cxx-abi.rs
+++ b/src/test/codegen/sanitizer-kcfi-emit-kcfi-operand-bundle-itanium-cxx-abi.rs
@@ -20,24 +20,21 @@ impl Copy for i32 {}
 
 pub fn foo(f: fn(i32) -> i32, arg: i32) -> i32 {
     // CHECK-LABEL: define{{.*}}foo
-    // FIXME(rcvalle): Change <unknown kind #36> to !kcfi_type when Rust is updated to LLVM 16
-    // CHECK-SAME: {{.*}}!<unknown kind #36> ![[TYPE1:[0-9]+]]
+    // CHECK-SAME: {{.*}}!{{<unknown kind #36>|kcfi_type}} ![[TYPE1:[0-9]+]]
     // CHECK: call i32 %f(i32 %arg){{.*}}[ "kcfi"(i32 -1666898348) ]
     f(arg)
 }
 
 pub fn bar(f: fn(i32, i32) -> i32, arg1: i32, arg2: i32) -> i32 {
     // CHECK-LABEL: define{{.*}}bar
-    // FIXME(rcvalle): Change <unknown kind #36> to !kcfi_type when Rust is updated to LLVM 16
-    // CHECK-SAME: {{.*}}!<unknown kind #36> ![[TYPE2:[0-9]+]]
+    // CHECK-SAME: {{.*}}!{{<unknown kind #36>|kcfi_type}} ![[TYPE2:[0-9]+]]
     // CHECK: call i32 %f(i32 %arg1, i32 %arg2){{.*}}[ "kcfi"(i32 -1789026986) ]
     f(arg1, arg2)
 }
 
 pub fn baz(f: fn(i32, i32, i32) -> i32, arg1: i32, arg2: i32, arg3: i32) -> i32 {
     // CHECK-LABEL: define{{.*}}baz
-    // FIXME(rcvalle): Change <unknown kind #36> to !kcfi_type when Rust is updated to LLVM 16
-    // CHECK-SAME: {{.*}}!<unknown kind #36> ![[TYPE3:[0-9]+]]
+    // CHECK-SAME: {{.*}}!{{<unknown kind #36>|kcfi_type}} ![[TYPE3:[0-9]+]]
     // CHECK: call i32 %f(i32 %arg1, i32 %arg2, i32 %arg3){{.*}}[ "kcfi"(i32 1248878270) ]
     f(arg1, arg2, arg3)
 }
diff --git a/src/test/codegen/unwind-abis/c-unwind-abi-panic-abort.rs b/src/test/codegen/unwind-abis/c-unwind-abi-panic-abort.rs
index 8447bbeb1ed..ea5bae18e23 100644
--- a/src/test/codegen/unwind-abis/c-unwind-abi-panic-abort.rs
+++ b/src/test/codegen/unwind-abis/c-unwind-abi-panic-abort.rs
@@ -9,7 +9,8 @@
 // CHECK: @rust_item_that_can_unwind() unnamed_addr [[ATTR0:#[0-9]+]]
 #[no_mangle]
 pub unsafe extern "C-unwind" fn rust_item_that_can_unwind() {
-    // CHECK: call void @_ZN4core9panicking15panic_no_unwind
+    // Handle both legacy and v0 symbol mangling.
+    // CHECK: call void @{{.*core9panicking19panic_cannot_unwind}}
     may_unwind();
 }
 
diff --git a/src/test/codegen/unwind-and-panic-abort.rs b/src/test/codegen/unwind-and-panic-abort.rs
index f238741e599..e43e73b96b9 100644
--- a/src/test/codegen/unwind-and-panic-abort.rs
+++ b/src/test/codegen/unwind-and-panic-abort.rs
@@ -9,7 +9,8 @@ extern "C-unwind" {
 
 // CHECK: Function Attrs:{{.*}}nounwind
 // CHECK-NEXT: define{{.*}}void @foo
-// CHECK: call void @_ZN4core9panicking15panic_no_unwind
+// Handle both legacy and v0 symbol mangling.
+// CHECK: call void @{{.*core9panicking19panic_cannot_unwind}}
 #[no_mangle]
 pub unsafe extern "C" fn foo() {
     bar();
diff --git a/src/test/codegen/vec-shrink-panik.rs b/src/test/codegen/vec-shrink-panik.rs
index 18409014bde..aa6589dc35b 100644
--- a/src/test/codegen/vec-shrink-panik.rs
+++ b/src/test/codegen/vec-shrink-panik.rs
@@ -18,11 +18,11 @@ pub fn shrink_to_fit(vec: &mut Vec<u32>) {
 pub fn issue71861(vec: Vec<u32>) -> Box<[u32]> {
     // CHECK-NOT: panic
 
-    // Call to panic_no_unwind in case of double-panic is expected,
+    // Call to panic_cannot_unwind in case of double-panic is expected,
     // but other panics are not.
     // CHECK: cleanup
-    // CHECK-NEXT: ; call core::panicking::panic_no_unwind
-    // CHECK-NEXT: panic_no_unwind
+    // CHECK-NEXT: ; call core::panicking::panic_cannot_unwind
+    // CHECK-NEXT: panic_cannot_unwind
 
     // CHECK-NOT: panic
     vec.into_boxed_slice()
@@ -33,15 +33,15 @@ pub fn issue71861(vec: Vec<u32>) -> Box<[u32]> {
 pub fn issue75636<'a>(iter: &[&'a str]) -> Box<[&'a str]> {
     // CHECK-NOT: panic
 
-    // Call to panic_no_unwind in case of double-panic is expected,
+    // Call to panic_cannot_unwind in case of double-panic is expected,
     // but other panics are not.
     // CHECK: cleanup
-    // CHECK-NEXT: ; call core::panicking::panic_no_unwind
-    // CHECK-NEXT: panic_no_unwind
+    // CHECK-NEXT: ; call core::panicking::panic_cannot_unwind
+    // CHECK-NEXT: panic_cannot_unwind
 
     // CHECK-NOT: panic
     iter.iter().copied().collect()
 }
 
-// CHECK: ; core::panicking::panic_no_unwind
-// CHECK: declare void @{{.*}}panic_no_unwind
+// CHECK: ; core::panicking::panic_cannot_unwind
+// CHECK: declare void @{{.*}}panic_cannot_unwind
diff --git a/src/test/mir-opt/building/custom/references.immut_ref.built.after.mir b/src/test/mir-opt/building/custom/references.immut_ref.built.after.mir
index 4d38d45c0f4..f5ee1126235 100644
--- a/src/test/mir-opt/building/custom/references.immut_ref.built.after.mir
+++ b/src/test/mir-opt/building/custom/references.immut_ref.built.after.mir
@@ -6,9 +6,8 @@ fn immut_ref(_1: &i32) -> &i32 {
 
     bb0: {
         _2 = &raw const (*_1);           // scope 0 at $DIR/references.rs:+5:13: +5:29
-        Retag([raw] _2);                 // scope 0 at $DIR/references.rs:+6:13: +6:24
-        _0 = &(*_2);                     // scope 0 at $DIR/references.rs:+7:13: +7:23
-        Retag(_0);                       // scope 0 at $DIR/references.rs:+8:13: +8:23
-        return;                          // scope 0 at $DIR/references.rs:+9:13: +9:21
+        _0 = &(*_2);                     // scope 0 at $DIR/references.rs:+6:13: +6:23
+        Retag(_0);                       // scope 0 at $DIR/references.rs:+7:13: +7:23
+        return;                          // scope 0 at $DIR/references.rs:+8:13: +8:21
     }
 }
diff --git a/src/test/mir-opt/building/custom/references.mut_ref.built.after.mir b/src/test/mir-opt/building/custom/references.mut_ref.built.after.mir
index 01bc8a9cd35..8e2ffc33b1a 100644
--- a/src/test/mir-opt/building/custom/references.mut_ref.built.after.mir
+++ b/src/test/mir-opt/building/custom/references.mut_ref.built.after.mir
@@ -6,9 +6,8 @@ fn mut_ref(_1: &mut i32) -> &mut i32 {
 
     bb0: {
         _2 = &raw mut (*_1);             // scope 0 at $DIR/references.rs:+5:13: +5:33
-        Retag([raw] _2);                 // scope 0 at $DIR/references.rs:+6:13: +6:24
-        _0 = &mut (*_2);                 // scope 0 at $DIR/references.rs:+7:13: +7:26
-        Retag(_0);                       // scope 0 at $DIR/references.rs:+8:13: +8:23
-        return;                          // scope 0 at $DIR/references.rs:+9:13: +9:21
+        _0 = &mut (*_2);                 // scope 0 at $DIR/references.rs:+6:13: +6:26
+        Retag(_0);                       // scope 0 at $DIR/references.rs:+7:13: +7:23
+        return;                          // scope 0 at $DIR/references.rs:+8:13: +8:21
     }
 }
diff --git a/src/test/mir-opt/building/custom/references.rs b/src/test/mir-opt/building/custom/references.rs
index c93f6ec624b..a1c896de04c 100644
--- a/src/test/mir-opt/building/custom/references.rs
+++ b/src/test/mir-opt/building/custom/references.rs
@@ -12,7 +12,6 @@ pub fn mut_ref(x: &mut i32) -> &mut i32 {
 
         {
             t = addr_of_mut!(*x);
-            RetagRaw(t);
             RET = &mut *t;
             Retag(RET);
             Return()
@@ -28,7 +27,6 @@ pub fn immut_ref(x: &i32) -> &i32 {
 
         {
             t = addr_of!(*x);
-            RetagRaw(t);
             RET = & *t;
             Retag(RET);
             Return()
diff --git a/src/test/mir-opt/retag.core.ptr-drop_in_place.Test.SimplifyCfg-make_shim.after.mir b/src/test/mir-opt/retag.core.ptr-drop_in_place.Test.SimplifyCfg-make_shim.after.mir
index 14f297e948b..f495f147be3 100644
--- a/src/test/mir-opt/retag.core.ptr-drop_in_place.Test.SimplifyCfg-make_shim.after.mir
+++ b/src/test/mir-opt/retag.core.ptr-drop_in_place.Test.SimplifyCfg-make_shim.after.mir
@@ -3,11 +3,14 @@
 fn std::ptr::drop_in_place(_1: *mut Test) -> () {
     let mut _0: ();                      // return place in scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
     let mut _2: &mut Test;               // in scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
-    let mut _3: ();                      // in scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
+    let mut _3: &mut Test;               // in scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
+    let mut _4: ();                      // in scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
 
     bb0: {
         _2 = &mut (*_1);                 // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
-        _3 = <Test as Drop>::drop(move _2) -> bb1; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
+        Retag([fn entry] _2);            // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
+        _3 = &mut (*_2);                 // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
+        _4 = <Test as Drop>::drop(move _3) -> bb1; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
                                          // mir::Constant
                                          // + span: $SRC_DIR/core/src/ptr/mod.rs:LL:COL
                                          // + literal: Const { ty: for<'a> fn(&'a mut Test) {<Test as Drop>::drop}, val: Value(<ZST>) }
diff --git a/src/test/rustdoc-gui/basic-code.goml b/src/test/rustdoc-gui/basic-code.goml
index f4ba5a12845..108cf8abcb5 100644
--- a/src/test/rustdoc-gui/basic-code.goml
+++ b/src/test/rustdoc-gui/basic-code.goml
@@ -1,3 +1,4 @@
 goto: "file://" + |DOC_PATH| + "/test_docs/index.html"
 click: ".srclink"
+wait-for: ".src-line-numbers"
 assert-count: (".src-line-numbers", 1)
diff --git a/src/test/rustdoc-gui/cursor.goml b/src/test/rustdoc-gui/cursor.goml
index cb6716a76f5..59b1397970b 100644
--- a/src/test/rustdoc-gui/cursor.goml
+++ b/src/test/rustdoc-gui/cursor.goml
@@ -12,8 +12,8 @@ write: (".search-input", "Foo")
 // To be SURE that the search will be run.
 press-key: 'Enter'
 // Waiting for the search results to appear...
-wait-for: "#titles"
-assert-css: ("#titles > button", {"cursor": "pointer"})
+wait-for: "#search-tabs"
+assert-css: ("#search-tabs > button", {"cursor": "pointer"})
 
 // mobile sidebar toggle button
 size: (500, 700)
diff --git a/src/test/rustdoc-gui/docblock-code-block-line-number.goml b/src/test/rustdoc-gui/docblock-code-block-line-number.goml
index b094c483876..a3ed008719c 100644
--- a/src/test/rustdoc-gui/docblock-code-block-line-number.goml
+++ b/src/test/rustdoc-gui/docblock-code-block-line-number.goml
@@ -1,23 +1,53 @@
 // Checks that the setting "line numbers" is working as expected.
 goto: "file://" + |DOC_PATH| + "/test_docs/fn.foo.html"
 
+// Otherwise, we can't check text color
+show-text: true
+
 // We check that without this setting, there is no line number displayed.
 assert-false: "pre.example-line-numbers"
 
-// We now set the setting to show the line numbers on code examples.
-local-storage: {"rustdoc-line-numbers": "true" }
-// We reload to make the line numbers appear.
-reload:
-
-// We wait for them to be added into the DOM by the JS...
-wait-for: "pre.example-line-numbers"
-// If the test didn't fail, it means that it was found!
 // Let's now check some CSS properties...
-assert-css: ("pre.example-line-numbers", {
-    "margin": "0px",
-    "padding": "13px 8px",
-    "text-align": "right",
+define-function: (
+    "check-colors",
+    (theme, color),
+    [
+        // We now set the setting to show the line numbers on code examples.
+        ("local-storage", {
+            "rustdoc-theme": |theme|,
+            "rustdoc-use-system-theme": "false",
+            "rustdoc-line-numbers": "true"
+        }),
+        // We reload to make the line numbers appear and change theme.
+        ("reload"),
+        // We wait for them to be added into the DOM by the JS...
+        ("wait-for", "pre.example-line-numbers"),
+        // If the test didn't fail, it means that it was found!
+        ("assert-css", (
+            "pre.example-line-numbers",
+            {
+                "color": |color|,
+                "margin": "0px",
+                "padding": "14px 8px",
+                "text-align": "right",
+            },
+            ALL,
+        )),
+    ],
+)
+call-function: ("check-colors", {
+    "theme": "ayu",
+    "color": "rgb(92, 103, 115)",
 })
+call-function: ("check-colors", {
+    "theme": "dark",
+    "color": "rgb(59, 145, 226)",
+})
+call-function: ("check-colors", {
+    "theme": "light",
+    "color": "rgb(198, 126, 45)",
+})
+
 // The first code block has two lines so let's check its `<pre>` elements lists both of them.
 assert-text: ("pre.example-line-numbers", "1\n2")
 
diff --git a/src/test/rustdoc-gui/links-color.goml b/src/test/rustdoc-gui/links-color.goml
index 839629ad982..9402c09eb69 100644
--- a/src/test/rustdoc-gui/links-color.goml
+++ b/src/test/rustdoc-gui/links-color.goml
@@ -4,82 +4,95 @@ goto: "file://" + |DOC_PATH| + "/test_docs/index.html"
 // This is needed so that the text color is computed.
 show-text: true
 
-// Ayu theme
-local-storage: {
-    "rustdoc-theme": "ayu",
-    "rustdoc-use-system-theme": "false",
-}
-reload:
-
-assert-css: (".item-table .mod", {"color": "rgb(57, 175, 215)"}, ALL)
-assert-css: (".item-table .macro", {"color": "rgb(163, 122, 204)"}, ALL)
-assert-css: (".item-table .struct", {"color": "rgb(255, 160, 165)"}, ALL)
-assert-css: (".item-table .enum", {"color": "rgb(255, 160, 165)"}, ALL)
-assert-css: (".item-table .trait", {"color": "rgb(57, 175, 215)"}, ALL)
-assert-css: (".item-table .fn", {"color": "rgb(253, 214, 135)"}, ALL)
-assert-css: (".item-table .type", {"color": "rgb(255, 160, 165)"}, ALL)
-assert-css: (".item-table .union", {"color": "rgb(255, 160, 165)"}, ALL)
-assert-css: (".item-table .keyword", {"color": "rgb(57, 175, 215)"}, ALL)
-
-assert-css: (
-    ".sidebar-elems a:not(.current)",
-    {"color": "rgb(83, 177, 219)", "background-color": "rgba(0, 0, 0, 0)", "font-weight": "400"},
-    ALL,
-)
-assert-css: (
-    ".sidebar-elems a.current",
-    {"color": "rgb(255, 180, 76)", "background-color": "rgba(0, 0, 0, 0)", "font-weight": "500"},
-    ALL,
+define-function: (
+    "check-colors",
+    (theme, mod, macro, struct, enum, trait, fn, type, union, keyword,
+     sidebar, sidebar_current, sidebar_current_background),
+    [
+        ("local-storage", {
+            "rustdoc-theme": |theme|,
+            "rustdoc-use-system-theme": "false",
+        }),
+        ("reload"),
+        // Checking results colors.
+        ("assert-css", (".item-table .mod", {"color": |mod|}, ALL)),
+        ("assert-css", (".item-table .macro", {"color": |macro|}, ALL)),
+        ("assert-css", (".item-table .struct", {"color": |struct|}, ALL)),
+        ("assert-css", (".item-table .enum", {"color": |enum|}, ALL)),
+        ("assert-css", (".item-table .trait", {"color": |trait|}, ALL)),
+        ("assert-css", (".item-table .fn", {"color": |fn|}, ALL)),
+        ("assert-css", (".item-table .type", {"color": |type|}, ALL)),
+        ("assert-css", (".item-table .union", {"color": |union|}, ALL)),
+        ("assert-css", (".item-table .keyword", {"color": |keyword|}, ALL)),
+        // Checking sidebar elements.
+        ("assert-css", (
+            ".sidebar-elems a:not(.current)",
+            {"color": |sidebar|, "background-color": "rgba(0, 0, 0, 0)", "font-weight": "400"},
+            ALL,
+        )),
+        ("assert-css", (
+            ".sidebar-elems a.current",
+            {
+                "color": |sidebar_current|,
+                "background-color": |sidebar_current_background|,
+                "font-weight": "500",
+            },
+            ALL,
+        )),
+    ],
 )
 
-
-// Dark theme
-local-storage: {"rustdoc-theme": "dark"}
-reload:
-
-assert-css: (".item-table .mod", {"color": "rgb(210, 153, 29)"}, ALL)
-assert-css: (".item-table .macro", {"color": "rgb(9, 189, 0)"}, ALL)
-assert-css: (".item-table .struct", {"color": "rgb(45, 191, 184)"}, ALL)
-assert-css: (".item-table .enum", {"color": "rgb(45, 191, 184)"}, ALL)
-assert-css: (".item-table .trait", {"color": "rgb(183, 140, 242)"}, ALL)
-assert-css: (".item-table .fn", {"color": "rgb(43, 171, 99)"}, ALL)
-assert-css: (".item-table .type", {"color": "rgb(45, 191, 184)"}, ALL)
-assert-css: (".item-table .union", {"color": "rgb(45, 191, 184)"}, ALL)
-assert-css: (".item-table .keyword", {"color": "rgb(210, 153, 29)"}, ALL)
-
-assert-css: (
-    ".sidebar-elems a:not(.current)",
-    {"color": "rgb(253, 191, 53)", "background-color": "rgba(0, 0, 0, 0)", "font-weight": "400"},
-    ALL,
+call-function: (
+    "check-colors",
+    {
+        "theme": "ayu",
+        "mod": "rgb(57, 175, 215)",
+        "macro": "rgb(163, 122, 204)",
+        "struct": "rgb(255, 160, 165)",
+        "enum": "rgb(255, 160, 165)",
+        "trait": "rgb(57, 175, 215)",
+        "fn": "rgb(253, 214, 135)",
+        "type": "rgb(255, 160, 165)",
+        "union": "rgb(255, 160, 165)",
+        "keyword": "rgb(57, 175, 215)",
+        "sidebar": "rgb(83, 177, 219)",
+        "sidebar_current": "rgb(255, 180, 76)",
+        "sidebar_current_background": "rgba(0, 0, 0, 0)",
+    },
 )
-assert-css: (
-    ".sidebar-elems a.current",
-    {"color": "rgb(253, 191, 53)", "background-color": "rgb(68, 68, 68)", "font-weight": "500"},
-    ALL,
-)
-
-
-// Light theme
-local-storage: {"rustdoc-theme": "light"}
-reload:
-
-assert-css: (".item-table .mod", {"color": "rgb(56, 115, 173)"}, ALL)
-assert-css: (".item-table .macro", {"color": "rgb(6, 128, 0)"}, ALL)
-assert-css: (".item-table .struct", {"color": "rgb(173, 55, 138)"}, ALL)
-assert-css: (".item-table .enum", {"color": "rgb(173, 55, 138)"}, ALL)
-assert-css: (".item-table .trait", {"color": "rgb(110, 79, 201)"}, ALL)
-assert-css: (".item-table .fn", {"color": "rgb(173, 124, 55)"}, ALL)
-assert-css: (".item-table .type", {"color": "rgb(173, 55, 138)"}, ALL)
-assert-css: (".item-table .union", {"color": "rgb(173, 55, 138)"}, ALL)
-assert-css: (".item-table .keyword", {"color": "rgb(56, 115, 173)"}, ALL)
-
-assert-css: (
-    ".sidebar-elems a:not(.current)",
-    {"color": "rgb(53, 109, 164)", "background-color": "rgba(0, 0, 0, 0)", "font-weight": "400"},
-    ALL,
+call-function: (
+    "check-colors",
+    {
+        "theme": "dark",
+        "mod": "rgb(210, 153, 29)",
+        "macro": "rgb(9, 189, 0)",
+        "struct": "rgb(45, 191, 184)",
+        "enum": "rgb(45, 191, 184)",
+        "trait": "rgb(183, 140, 242)",
+        "fn": "rgb(43, 171, 99)",
+        "type": "rgb(45, 191, 184)",
+        "union": "rgb(45, 191, 184)",
+        "keyword": "rgb(210, 153, 29)",
+        "sidebar": "rgb(253, 191, 53)",
+        "sidebar_current": "rgb(253, 191, 53)",
+        "sidebar_current_background": "rgb(68, 68, 68)",
+    },
 )
-assert-css: (
-    ".sidebar-elems a.current",
-    {"color": "rgb(53, 109, 164)", "background-color": "rgb(255, 255, 255)", "font-weight": "500"},
-    ALL,
+call-function: (
+    "check-colors",
+    {
+        "theme": "light",
+        "mod": "rgb(56, 115, 173)",
+        "macro": "rgb(6, 128, 0)",
+        "struct": "rgb(173, 55, 138)",
+        "enum": "rgb(173, 55, 138)",
+        "trait": "rgb(110, 79, 201)",
+        "fn": "rgb(173, 124, 55)",
+        "type": "rgb(173, 55, 138)",
+        "union": "rgb(173, 55, 138)",
+        "keyword": "rgb(56, 115, 173)",
+        "sidebar": "rgb(53, 109, 164)",
+        "sidebar_current": "rgb(53, 109, 164)",
+        "sidebar_current_background": "rgb(255, 255, 255)",
+    },
 )
diff --git a/src/test/rustdoc-gui/scrape-examples-layout.goml b/src/test/rustdoc-gui/scrape-examples-layout.goml
new file mode 100644
index 00000000000..fde9a0ab0bc
--- /dev/null
+++ b/src/test/rustdoc-gui/scrape-examples-layout.goml
@@ -0,0 +1,35 @@
+// Check that the line number column has the correct layout.
+goto: "file://" + |DOC_PATH| + "/scrape_examples/fn.test_many.html"
+
+// Check that it's not zero.
+assert-property-false: (
+    ".more-scraped-examples .scraped-example .code-wrapper .src-line-numbers",
+    {"clientWidth": "0"}
+)
+
+// Check that examples with very long lines have the same width as ones that don't.
+store-property: (
+    clientWidth,
+    ".more-scraped-examples .scraped-example:nth-child(2) .code-wrapper .src-line-numbers",
+    "clientWidth"
+)
+
+assert-property: (
+    ".more-scraped-examples .scraped-example:nth-child(3) .code-wrapper .src-line-numbers",
+    {"clientWidth": |clientWidth|}
+)
+
+assert-property: (
+    ".more-scraped-examples .scraped-example:nth-child(4) .code-wrapper .src-line-numbers",
+    {"clientWidth": |clientWidth|}
+)
+
+assert-property: (
+    ".more-scraped-examples .scraped-example:nth-child(5) .code-wrapper .src-line-numbers",
+    {"clientWidth": |clientWidth|}
+)
+
+assert-property: (
+    ".more-scraped-examples .scraped-example:nth-child(6) .code-wrapper .src-line-numbers",
+    {"clientWidth": |clientWidth|}
+)
diff --git a/src/test/rustdoc-gui/scrape-examples-toggle.goml b/src/test/rustdoc-gui/scrape-examples-toggle.goml
index ee720afb788..8c84fbc0c30 100644
--- a/src/test/rustdoc-gui/scrape-examples-toggle.goml
+++ b/src/test/rustdoc-gui/scrape-examples-toggle.goml
@@ -1,9 +1,46 @@
+// This tests checks that the "scraped examples" toggle is working as expected.
 goto: "file://" + |DOC_PATH| + "/scrape_examples/fn.test_many.html"
 
-// Clicking "More examples..." will open additional examples
-assert-attribute-false: (".more-examples-toggle", {"open": ""})
-click: ".more-examples-toggle"
-assert-attribute: (".more-examples-toggle", {"open": ""})
+// Checking the color of the toggle line.
+show-text: true
+define-function: (
+    "check-color",
+    (theme, toggle_line_color, toggle_line_hover_color),
+    [
+        ("local-storage", {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}),
+        ("reload"),
+
+        // Clicking "More examples..." will open additional examples
+        ("assert-attribute-false", (".more-examples-toggle", {"open": ""})),
+        ("click", ".more-examples-toggle"),
+        ("assert-attribute", (".more-examples-toggle", {"open": ""})),
+
+        ("assert-css", (".toggle-line-inner", {"background-color": |toggle_line_color|}, ALL)),
+        ("move-cursor-to", ".toggle-line"),
+        ("assert-css", (
+            ".toggle-line:hover .toggle-line-inner",
+            {"background-color": |toggle_line_hover_color|},
+        )),
+        // Moving cursor away from the toggle line to prevent disrupting next test.
+        ("move-cursor-to", ".search-input"),
+    ],
+)
+
+call-function: ("check-color", {
+    "theme": "ayu",
+    "toggle_line_color": "rgb(153, 153, 153)",
+    "toggle_line_hover_color": "rgb(197, 197, 197)",
+})
+call-function: ("check-color", {
+    "theme": "dark",
+    "toggle_line_color": "rgb(153, 153, 153)",
+    "toggle_line_hover_color": "rgb(197, 197, 197)",
+})
+call-function: ("check-color", {
+    "theme": "light",
+    "toggle_line_color": "rgb(204, 204, 204)",
+    "toggle_line_hover_color": "rgb(153, 153, 153)",
+})
 
 // Toggling all docs will close additional examples
 click: "#toggle-all-docs"
diff --git a/src/test/rustdoc-gui/search-filter.goml b/src/test/rustdoc-gui/search-filter.goml
index e0228694eec..e556da0c54e 100644
--- a/src/test/rustdoc-gui/search-filter.goml
+++ b/src/test/rustdoc-gui/search-filter.goml
@@ -5,7 +5,7 @@ write: (".search-input", "test")
 // To be SURE that the search will be run.
 press-key: 'Enter'
 // Waiting for the search results to appear...
-wait-for: "#titles"
+wait-for: "#search-tabs"
 assert-text: ("#results .externcrate", "test_docs")
 
 wait-for: "#crate-search"
@@ -17,7 +17,7 @@ press-key: "ArrowDown"
 press-key: "ArrowDown"
 press-key: "Enter"
 // Waiting for the search results to appear...
-wait-for: "#titles"
+wait-for: "#search-tabs"
 assert-document-property: ({"URL": "&filter-crate="}, CONTAINS)
 // We check that there is no more "test_docs" appearing.
 assert-false: "#results .externcrate"
@@ -41,7 +41,7 @@ press-key: "ArrowUp"
 press-key: "ArrowUp"
 press-key: "Enter"
 // Waiting for the search results to appear...
-wait-for: "#titles"
+wait-for: "#search-tabs"
 assert-property: ("#crate-search", {"value": "all crates"})
 
 // Checking that the URL parameter is taken into account for crate filtering.
diff --git a/src/test/rustdoc-gui/search-keyboard.goml b/src/test/rustdoc-gui/search-keyboard.goml
index be642fc4997..ed975664c66 100644
--- a/src/test/rustdoc-gui/search-keyboard.goml
+++ b/src/test/rustdoc-gui/search-keyboard.goml
@@ -5,7 +5,7 @@ write: (".search-input", "Foo")
 // To be SURE that the search will be run.
 press-key: 'Enter'
 // Waiting for the search results to appear...
-wait-for: "#titles"
+wait-for: "#search-tabs"
 
 // Now use the keyboard commands to switch to the third result.
 press-key: "ArrowDown"
diff --git a/src/test/rustdoc-gui/search-result-color.goml b/src/test/rustdoc-gui/search-result-color.goml
index dde43b1c980..3c5fe9b74b7 100644
--- a/src/test/rustdoc-gui/search-result-color.goml
+++ b/src/test/rustdoc-gui/search-result-color.goml
@@ -65,7 +65,12 @@ local-storage: {
 reload:
 
 // Waiting for the search results to appear...
-wait-for: "#titles"
+wait-for: "#search-tabs"
+assert-css: (
+    "#search-tabs > button > .count",
+    {"color": "rgb(136, 136, 136)"},
+    ALL,
+)
 assert-css: (
     "//*[@class='desc'][text()='Just a normal struct.']",
     {"color": "rgb(197, 197, 197)"},
@@ -177,7 +182,12 @@ local-storage: {
 reload:
 
 // Waiting for the search results to appear...
-wait-for: "#titles"
+wait-for: "#search-tabs"
+assert-css: (
+    "#search-tabs > button > .count",
+    {"color": "rgb(136, 136, 136)"},
+    ALL,
+)
 assert-css: (
     "//*[@class='desc'][text()='Just a normal struct.']",
     {"color": "rgb(221, 221, 221)"},
@@ -274,7 +284,12 @@ local-storage: {"rustdoc-theme": "light", "rustdoc-use-system-theme": "false"}
 reload:
 
 // Waiting for the search results to appear...
-wait-for: "#titles"
+wait-for: "#search-tabs"
+assert-css: (
+    "#search-tabs > button > .count",
+    {"color": "rgb(136, 136, 136)"},
+    ALL,
+)
 assert-css: (
     "//*[@class='desc'][text()='Just a normal struct.']",
     {"color": "rgb(0, 0, 0)"},
@@ -381,7 +396,7 @@ define-function: (
         // To be SURE that the search will be run.
         ("press-key", 'Enter'),
         // Waiting for the search results to appear...
-        ("wait-for", "#titles"),
+        ("wait-for", "#search-tabs"),
         // Checking that the colors for the alias element are the ones expected.
         ("assert-css", (".result-name > .alias", {"color": |alias|})),
         ("assert-css", (".result-name > .alias > .grey", {"color": |grey|})),
diff --git a/src/test/rustdoc-gui/search-result-description.goml b/src/test/rustdoc-gui/search-result-description.goml
index 53a335b6335..9fa2108045d 100644
--- a/src/test/rustdoc-gui/search-result-description.goml
+++ b/src/test/rustdoc-gui/search-result-description.goml
@@ -1,5 +1,5 @@
 // This test is to ensure that the codeblocks are correctly rendered in the search results.
 goto: "file://" + |DOC_PATH| + "/test_docs/index.html?search=some_more_function"
 // Waiting for the search results to appear...
-wait-for: "#titles"
+wait-for: "#search-tabs"
 assert-text: (".search-results .desc code", "format!")
diff --git a/src/test/rustdoc-gui/search-result-go-to-first.goml b/src/test/rustdoc-gui/search-result-go-to-first.goml
index eeddf5ef6e8..994fd87c996 100644
--- a/src/test/rustdoc-gui/search-result-go-to-first.goml
+++ b/src/test/rustdoc-gui/search-result-go-to-first.goml
@@ -8,7 +8,7 @@ assert-text-false: (".fqn", "Struct test_docs::Foo")
 // We now check that we land on the search result page if "go_to_first" isn't set.
 goto: "file://" + |DOC_PATH| + "/test_docs/index.html?search=struct%3AFoo"
 // Waiting for the search results to appear...
-wait-for: "#titles"
+wait-for: "#search-tabs"
 assert-text-false: (".fqn", "Struct test_docs::Foo")
 // Ensure that the search results are displayed, not the "normal" content.
 assert-css: ("#main-content", {"display": "none"})
diff --git a/src/test/rustdoc-gui/search-result-keyword.goml b/src/test/rustdoc-gui/search-result-keyword.goml
index 66e63155a4e..8c3577d9fd3 100644
--- a/src/test/rustdoc-gui/search-result-keyword.goml
+++ b/src/test/rustdoc-gui/search-result-keyword.goml
@@ -4,7 +4,7 @@ write: (".search-input", "CookieMonster")
 // To be SURE that the search will be run.
 press-key: 'Enter'
 // Waiting for the search results to appear...
-wait-for: "#titles"
+wait-for: "#search-tabs"
 // Note: The two next assert commands could be merged as one but readability would be
 // less good.
 //
diff --git a/src/test/rustdoc-gui/search-tab-change-title-fn-sig.goml b/src/test/rustdoc-gui/search-tab-change-title-fn-sig.goml
index a19dc6a8b40..1433dc4d7e5 100644
--- a/src/test/rustdoc-gui/search-tab-change-title-fn-sig.goml
+++ b/src/test/rustdoc-gui/search-tab-change-title-fn-sig.goml
@@ -5,21 +5,21 @@ write: (".search-input", "Foo")
 // To be SURE that the search will be run.
 press-key: 'Enter'
 // Waiting for the search results to appear...
-wait-for: "#titles"
-assert-attribute: ("#titles > button:nth-of-type(1)", {"class": "selected"})
-assert-text: ("#titles > button:nth-of-type(1)", "In Names", STARTS_WITH)
+wait-for: "#search-tabs"
+assert-attribute: ("#search-tabs > button:nth-of-type(1)", {"class": "selected"})
+assert-text: ("#search-tabs > button:nth-of-type(1)", "In Names", STARTS_WITH)
 assert: "input.search-input:focus"
 // Use left-right keys
 press-key: "ArrowDown"
 assert: "#results > .search-results.active > a:nth-of-type(1):focus"
 press-key: "ArrowRight"
-wait-for-attribute: ("#titles > button:nth-of-type(2)", {"class": "selected"})
+wait-for-attribute: ("#search-tabs > button:nth-of-type(2)", {"class": "selected"})
 press-key: "ArrowRight"
-wait-for-attribute: ("#titles > button:nth-of-type(3)", {"class": "selected"})
+wait-for-attribute: ("#search-tabs > button:nth-of-type(3)", {"class": "selected"})
 press-key: "ArrowRight"
-wait-for-attribute: ("#titles > button:nth-of-type(1)", {"class": "selected"})
+wait-for-attribute: ("#search-tabs > button:nth-of-type(1)", {"class": "selected"})
 press-key: "ArrowLeft"
-wait-for-attribute: ("#titles > button:nth-of-type(3)", {"class": "selected"})
+wait-for-attribute: ("#search-tabs > button:nth-of-type(3)", {"class": "selected"})
 
 // Now try search-by-return
 goto: "file://" + |DOC_PATH| + "/test_docs/index.html"
@@ -27,21 +27,21 @@ write: (".search-input", "-> String")
 // To be SURE that the search will be run.
 press-key: 'Enter'
 // Waiting for the search results to appear...
-wait-for: "#titles"
-assert-attribute: ("#titles > button:nth-of-type(1)", {"class": "selected"})
-assert-text: ("#titles > button:nth-of-type(1)", "In Function Return Types", STARTS_WITH)
+wait-for: "#search-tabs"
+assert-attribute: ("#search-tabs > button:nth-of-type(1)", {"class": "selected"})
+assert-text: ("#search-tabs > button:nth-of-type(1)", "In Function Return Types", STARTS_WITH)
 assert: "input.search-input:focus"
 // Use left-right keys
 press-key: "ArrowDown"
 assert: "#results > .search-results.active > a:nth-of-type(1):focus"
 press-key: "ArrowRight"
-wait-for-attribute: ("#titles > button:nth-of-type(1)", {"class": "selected"})
+wait-for-attribute: ("#search-tabs > button:nth-of-type(1)", {"class": "selected"})
 press-key: "ArrowRight"
-wait-for-attribute: ("#titles > button:nth-of-type(1)", {"class": "selected"})
+wait-for-attribute: ("#search-tabs > button:nth-of-type(1)", {"class": "selected"})
 press-key: "ArrowRight"
-wait-for-attribute: ("#titles > button:nth-of-type(1)", {"class": "selected"})
+wait-for-attribute: ("#search-tabs > button:nth-of-type(1)", {"class": "selected"})
 press-key: "ArrowLeft"
-wait-for-attribute: ("#titles > button:nth-of-type(1)", {"class": "selected"})
+wait-for-attribute: ("#search-tabs > button:nth-of-type(1)", {"class": "selected"})
 
 // Try with a search-by-return with no results
 goto: "file://" + |DOC_PATH| + "/test_docs/index.html"
@@ -49,9 +49,9 @@ write: (".search-input", "-> Something")
 // To be SURE that the search will be run.
 press-key: 'Enter'
 // Waiting for the search results to appear...
-wait-for: "#titles"
-assert-attribute: ("#titles > button:nth-of-type(1)", {"class": "selected"})
-assert-text: ("#titles > button:nth-of-type(1)", "In Function Return Types", STARTS_WITH)
+wait-for: "#search-tabs"
+assert-attribute: ("#search-tabs > button:nth-of-type(1)", {"class": "selected"})
+assert-text: ("#search-tabs > button:nth-of-type(1)", "In Function Return Types", STARTS_WITH)
 
 // Try with a search-by-parameter
 goto: "file://" + |DOC_PATH| + "/test_docs/index.html"
@@ -59,9 +59,9 @@ write: (".search-input", "usize pattern")
 // To be SURE that the search will be run.
 press-key: 'Enter'
 // Waiting for the search results to appear...
-wait-for: "#titles"
-assert-attribute: ("#titles > button:nth-of-type(1)", {"class": "selected"})
-assert-text: ("#titles > button:nth-of-type(1)", "In Function Parameters", STARTS_WITH)
+wait-for: "#search-tabs"
+assert-attribute: ("#search-tabs > button:nth-of-type(1)", {"class": "selected"})
+assert-text: ("#search-tabs > button:nth-of-type(1)", "In Function Parameters", STARTS_WITH)
 
 // Try with a search-by-parameter-and-return
 goto: "file://" + |DOC_PATH| + "/test_docs/index.html"
@@ -69,6 +69,6 @@ write: (".search-input", "pattern -> str")
 // To be SURE that the search will be run.
 press-key: 'Enter'
 // Waiting for the search results to appear...
-wait-for: "#titles"
-assert-attribute: ("#titles > button:nth-of-type(1)", {"class": "selected"})
-assert-text: ("#titles > button:nth-of-type(1)", "In Function Signatures", STARTS_WITH)
+wait-for: "#search-tabs"
+assert-attribute: ("#search-tabs > button:nth-of-type(1)", {"class": "selected"})
+assert-text: ("#search-tabs > button:nth-of-type(1)", "In Function Signatures", STARTS_WITH)
diff --git a/src/test/rustdoc-gui/search-tab.goml b/src/test/rustdoc-gui/search-tab.goml
new file mode 100644
index 00000000000..c2634a04c8a
--- /dev/null
+++ b/src/test/rustdoc-gui/search-tab.goml
@@ -0,0 +1,76 @@
+// Checking the colors of the search tab headers.
+goto: "file://" + |DOC_PATH| + "/test_docs/fn.foo.html?search=something"
+show-text: true
+
+define-function: (
+    "check-colors",
+    (theme, background, background_selected, background_hover, border_bottom,
+     border_bottom_selected, border_bottom_hover, border_top, border_top_selected,
+     border_top_hover),
+    [
+        // Setting the theme.
+        ("local-storage", {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}),
+        ("reload"),
+
+        // These two commands are used to be sure the search will be run.
+        ("focus", ".search-input"),
+        ("press-key", "Enter"),
+
+        ("wait-for", "#search-tabs"),
+        ("assert-css", ("#search-tabs > button:not(.selected)", {
+            "background-color": |background|,
+            "border-bottom": |border_bottom|,
+            "border-top": |border_top|,
+        })),
+        ("assert-css", ("#search-tabs > button.selected", {
+            "background-color": |background_selected|,
+            "border-bottom": |border_bottom_selected|,
+            "border-top": |border_top_selected|,
+        })),
+        ("move-cursor-to", "#search-tabs > button:not(.selected)"),
+        ("assert-css", ("#search-tabs > button:not(.selected):hover", {
+            "background-color": |background_hover|,
+            "border-bottom": |border_bottom_hover|,
+            "border-top": |border_top_hover|,
+        })),
+        // To prevent disrupting next run of this function.
+        ("move-cursor-to", ".search-input"),
+    ],
+)
+
+call-function: ("check-colors", {
+    "theme": "ayu",
+    "background": "rgba(0, 0, 0, 0)",
+    "background_selected": "rgb(20, 25, 32)",
+    "background_hover": "rgba(0, 0, 0, 0)",
+    "border_bottom": "0px none rgb(197, 197, 197)",
+    "border_bottom_selected": "1px solid rgb(255, 180, 76)",
+    "border_bottom_hover": "1px solid rgba(242, 151, 24, 0.3)",
+    "border_top": "0px none rgb(197, 197, 197)",
+    "border_top_selected": "0px none rgb(197, 197, 197)",
+    "border_top_hover": "0px none rgb(197, 197, 197)",
+})
+call-function: ("check-colors", {
+    "theme": "dark",
+    "background": "rgb(37, 37, 37)",
+    "background_selected": "rgb(53, 53, 53)",
+    "background_hover": "rgb(53, 53, 53)",
+    "border_bottom": "0px none rgb(221, 221, 221)",
+    "border_bottom_selected": "0px none rgb(221, 221, 221)",
+    "border_bottom_hover": "0px none rgb(221, 221, 221)",
+    "border_top": "2px solid rgb(37, 37, 37)",
+    "border_top_selected": "2px solid rgb(0, 137, 255)",
+    "border_top_hover": "2px solid rgb(0, 137, 255)",
+})
+call-function: ("check-colors", {
+    "theme": "light",
+    "background": "rgb(230, 230, 230)",
+    "background_selected": "rgb(255, 255, 255)",
+    "background_hover": "rgb(255, 255, 255)",
+    "border_bottom": "0px none rgb(0, 0, 0)",
+    "border_bottom_selected": "0px none rgb(0, 0, 0)",
+    "border_bottom_hover": "0px none rgb(0, 0, 0)",
+    "border_top": "2px solid rgb(230, 230, 230)",
+    "border_top_selected": "2px solid rgb(0, 137, 255)",
+    "border_top_hover": "2px solid rgb(0, 137, 255)",
+})
diff --git a/src/test/rustdoc-gui/sidebar-source-code.goml b/src/test/rustdoc-gui/sidebar-source-code.goml
index 36e4d555b8e..d5f57ed6102 100644
--- a/src/test/rustdoc-gui/sidebar-source-code.goml
+++ b/src/test/rustdoc-gui/sidebar-source-code.goml
@@ -1,7 +1,52 @@
 // The goal of this test is to ensure that the sidebar is working as expected in the source
 // code pages.
 goto: "file://" + |DOC_PATH| + "/src/test_docs/lib.rs.html"
-// First: desktop mode.
+show-text: true
+
+// First, check the sidebar colors.
+define-function: (
+    "check-colors",
+    (theme, color, background_color),
+    [
+        ("local-storage", {
+            "rustdoc-theme": |theme|,
+            "rustdoc-use-system-theme": "false",
+        }),
+        ("reload"),
+        // Checking results colors.
+        ("assert-css", (".source .sidebar", {
+        	"color": |color|,
+        	"background-color": |background_color|
+        }, ALL)),
+    ],
+)
+
+call-function: (
+	"check-colors",
+	{
+		"theme": "ayu",
+		"color": "rgb(197, 197, 197)",
+		"background_color": "rgb(20, 25, 31)",
+	}
+)
+call-function: (
+	"check-colors",
+	{
+		"theme": "dark",
+		"color": "rgb(221, 221, 221)",
+		"background_color": "rgb(80, 80, 80)",
+	}
+)
+call-function: (
+	"check-colors",
+	{
+		"theme": "light",
+		"color": "rgb(0, 0, 0)",
+		"background_color": "rgb(245, 245, 245)",
+	}
+)
+
+// Next, desktop mode layout.
 size: (1100, 800)
 // We check that the sidebar isn't expanded and has the expected width.
 assert-css: ("nav.sidebar", {"width": "50px"})
diff --git a/src/test/rustdoc-gui/sidebar.goml b/src/test/rustdoc-gui/sidebar.goml
index 5058630f469..bfd7567a224 100644
--- a/src/test/rustdoc-gui/sidebar.goml
+++ b/src/test/rustdoc-gui/sidebar.goml
@@ -2,6 +2,50 @@
 goto: "file://" + |DOC_PATH| + "/test_docs/index.html"
 assert-property: (".sidebar", {"clientWidth": "200"})
 show-text: true
+
+// First, check the sidebar colors.
+define-function: (
+    "check-colors",
+    (theme, color, background_color),
+    [
+        ("local-storage", {
+            "rustdoc-theme": |theme|,
+            "rustdoc-use-system-theme": "false",
+        }),
+        ("reload"),
+        // Checking results colors.
+        ("assert-css", (".sidebar", {
+        	"color": |color|,
+        	"background-color": |background_color|
+        }, ALL)),
+    ],
+)
+
+call-function: (
+	"check-colors",
+	{
+		"theme": "ayu",
+		"color": "rgb(197, 197, 197)",
+		"background_color": "rgb(20, 25, 31)",
+	}
+)
+call-function: (
+	"check-colors",
+	{
+		"theme": "dark",
+		"color": "rgb(221, 221, 221)",
+		"background_color": "rgb(80, 80, 80)",
+	}
+)
+call-function: (
+	"check-colors",
+	{
+		"theme": "light",
+		"color": "rgb(0, 0, 0)",
+		"background_color": "rgb(245, 245, 245)",
+	}
+)
+
 local-storage: {"rustdoc-theme": "light"}
 // We reload the page so the local storage settings are being used.
 reload:
diff --git a/src/test/rustdoc-gui/source-code-page.goml b/src/test/rustdoc-gui/source-code-page.goml
index 25da74e5173..8a33e713191 100644
--- a/src/test/rustdoc-gui/source-code-page.goml
+++ b/src/test/rustdoc-gui/source-code-page.goml
@@ -89,9 +89,9 @@ assert-css: (".src-line-numbers", {"text-align": "right"})
 // do anything (and certainly not add a `#NaN` to the URL!).
 goto: "file://" + |DOC_PATH| + "/src/test_docs/lib.rs.html"
 // We use this assert-position to know where we will click.
-assert-position: ("//*[@id='1']", {"x": 104, "y": 112})
+assert-position: ("//*[@id='1']", {"x": 88, "y": 112})
 // We click on the left of the "1" anchor but still in the "src-line-number" `<pre>`.
-click: (103, 103)
+click: (87, 103)
 assert-document-property: ({"URL": "/lib.rs.html"}, ENDS_WITH)
 
 // Checking the source code sidebar.
diff --git a/src/test/rustdoc-gui/src/scrape_examples/examples/check-many-1.rs b/src/test/rustdoc-gui/src/scrape_examples/examples/check-many-1.rs
index 1d1bc5002aa..81a48ac50c8 100644
--- a/src/test/rustdoc-gui/src/scrape_examples/examples/check-many-1.rs
+++ b/src/test/rustdoc-gui/src/scrape_examples/examples/check-many-1.rs
@@ -1,3 +1,13 @@
 fn main() {
+    // all examples have same line count
+    scrape_examples::test_many();
+    scrape_examples::test_many();
+    scrape_examples::test_many();
+    scrape_examples::test_many();
+    scrape_examples::test_many();
+    scrape_examples::test_many();
+    scrape_examples::test_many();
+    scrape_examples::test_many();
+    scrape_examples::test_many();
     scrape_examples::test_many();
 }
diff --git a/src/test/rustdoc-gui/src/scrape_examples/examples/check-many-2.rs b/src/test/rustdoc-gui/src/scrape_examples/examples/check-many-2.rs
index 1d1bc5002aa..c9fdf68d3be 100644
--- a/src/test/rustdoc-gui/src/scrape_examples/examples/check-many-2.rs
+++ b/src/test/rustdoc-gui/src/scrape_examples/examples/check-many-2.rs
@@ -1,3 +1,13 @@
 fn main() {
-    scrape_examples::test_many();
+    // ignore-tidy-linelength
+    scrape_examples::test_many(); /* Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. */
+    scrape_examples::test_many(); /* Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. */
+    scrape_examples::test_many(); /* Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. */
+    scrape_examples::test_many(); /* Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. */
+    scrape_examples::test_many(); /* Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. */
+    scrape_examples::test_many(); /* Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. */
+    scrape_examples::test_many(); /* Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. */
+    scrape_examples::test_many(); /* Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. */
+    scrape_examples::test_many(); /* Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. */
+    scrape_examples::test_many(); /* Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. */
 }
diff --git a/src/test/rustdoc-gui/src/scrape_examples/examples/check-many-3.rs b/src/test/rustdoc-gui/src/scrape_examples/examples/check-many-3.rs
index 1d1bc5002aa..c9fdf68d3be 100644
--- a/src/test/rustdoc-gui/src/scrape_examples/examples/check-many-3.rs
+++ b/src/test/rustdoc-gui/src/scrape_examples/examples/check-many-3.rs
@@ -1,3 +1,13 @@
 fn main() {
-    scrape_examples::test_many();
+    // ignore-tidy-linelength
+    scrape_examples::test_many(); /* Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. */
+    scrape_examples::test_many(); /* Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. */
+    scrape_examples::test_many(); /* Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. */
+    scrape_examples::test_many(); /* Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. */
+    scrape_examples::test_many(); /* Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. */
+    scrape_examples::test_many(); /* Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. */
+    scrape_examples::test_many(); /* Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. */
+    scrape_examples::test_many(); /* Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. */
+    scrape_examples::test_many(); /* Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. */
+    scrape_examples::test_many(); /* Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. */
 }
diff --git a/src/test/rustdoc-gui/src/scrape_examples/examples/check-many-4.rs b/src/test/rustdoc-gui/src/scrape_examples/examples/check-many-4.rs
index 1d1bc5002aa..81a48ac50c8 100644
--- a/src/test/rustdoc-gui/src/scrape_examples/examples/check-many-4.rs
+++ b/src/test/rustdoc-gui/src/scrape_examples/examples/check-many-4.rs
@@ -1,3 +1,13 @@
 fn main() {
+    // all examples have same line count
+    scrape_examples::test_many();
+    scrape_examples::test_many();
+    scrape_examples::test_many();
+    scrape_examples::test_many();
+    scrape_examples::test_many();
+    scrape_examples::test_many();
+    scrape_examples::test_many();
+    scrape_examples::test_many();
+    scrape_examples::test_many();
     scrape_examples::test_many();
 }
diff --git a/src/test/rustdoc-gui/src/scrape_examples/examples/check-many-5.rs b/src/test/rustdoc-gui/src/scrape_examples/examples/check-many-5.rs
index 1d1bc5002aa..81a48ac50c8 100644
--- a/src/test/rustdoc-gui/src/scrape_examples/examples/check-many-5.rs
+++ b/src/test/rustdoc-gui/src/scrape_examples/examples/check-many-5.rs
@@ -1,3 +1,13 @@
 fn main() {
+    // all examples have same line count
+    scrape_examples::test_many();
+    scrape_examples::test_many();
+    scrape_examples::test_many();
+    scrape_examples::test_many();
+    scrape_examples::test_many();
+    scrape_examples::test_many();
+    scrape_examples::test_many();
+    scrape_examples::test_many();
+    scrape_examples::test_many();
     scrape_examples::test_many();
 }
diff --git a/src/test/rustdoc-gui/src/scrape_examples/examples/check-many-6.rs b/src/test/rustdoc-gui/src/scrape_examples/examples/check-many-6.rs
index 1d1bc5002aa..81a48ac50c8 100644
--- a/src/test/rustdoc-gui/src/scrape_examples/examples/check-many-6.rs
+++ b/src/test/rustdoc-gui/src/scrape_examples/examples/check-many-6.rs
@@ -1,3 +1,13 @@
 fn main() {
+    // all examples have same line count
+    scrape_examples::test_many();
+    scrape_examples::test_many();
+    scrape_examples::test_many();
+    scrape_examples::test_many();
+    scrape_examples::test_many();
+    scrape_examples::test_many();
+    scrape_examples::test_many();
+    scrape_examples::test_many();
+    scrape_examples::test_many();
     scrape_examples::test_many();
 }
diff --git a/src/test/rustdoc-gui/src/scrape_examples/examples/check-many-7.rs b/src/test/rustdoc-gui/src/scrape_examples/examples/check-many-7.rs
index 1d1bc5002aa..81a48ac50c8 100644
--- a/src/test/rustdoc-gui/src/scrape_examples/examples/check-many-7.rs
+++ b/src/test/rustdoc-gui/src/scrape_examples/examples/check-many-7.rs
@@ -1,3 +1,13 @@
 fn main() {
+    // all examples have same line count
+    scrape_examples::test_many();
+    scrape_examples::test_many();
+    scrape_examples::test_many();
+    scrape_examples::test_many();
+    scrape_examples::test_many();
+    scrape_examples::test_many();
+    scrape_examples::test_many();
+    scrape_examples::test_many();
+    scrape_examples::test_many();
     scrape_examples::test_many();
 }
diff --git a/src/test/rustdoc-ui/infinite-recursive-type-impl-trait-return.rs b/src/test/rustdoc-ui/infinite-recursive-type-impl-trait-return.rs
index 4b1e04234c8..939da186fbc 100644
--- a/src/test/rustdoc-ui/infinite-recursive-type-impl-trait-return.rs
+++ b/src/test/rustdoc-ui/infinite-recursive-type-impl-trait-return.rs
@@ -1,12 +1,10 @@
-// check-pass
 // normalize-stderr-test: "`.*`" -> "`DEF_ID`"
 // normalize-stdout-test: "`.*`" -> "`DEF_ID`"
 // edition:2018
 
 pub async fn f() -> impl std::fmt::Debug {
-    // rustdoc doesn't care that this is infinitely sized
     #[derive(Debug)]
-    enum E {
+    enum E { //~ ERROR
         This(E),
         Unit,
     }
diff --git a/src/test/rustdoc-ui/infinite-recursive-type-impl-trait-return.stderr b/src/test/rustdoc-ui/infinite-recursive-type-impl-trait-return.stderr
new file mode 100644
index 00000000000..aff7402bc91
--- /dev/null
+++ b/src/test/rustdoc-ui/infinite-recursive-type-impl-trait-return.stderr
@@ -0,0 +1,16 @@
+error[E0072]: recursive type `DEF_ID` has infinite size
+  --> $DIR/infinite-recursive-type-impl-trait-return.rs:7:5
+   |
+LL |     enum E {
+   |     ^^^^^^
+LL |         This(E),
+   |              - recursive without indirection
+   |
+help: insert some indirection (e.g., a `DEF_ID`) to break the cycle
+   |
+LL |         This(Box<E>),
+   |              ++++ +
+
+error: aborting due to previous error
+
+For more information about this error, try `DEF_ID`.
diff --git a/src/test/rustdoc-ui/infinite-recursive-type-impl-trait.rs b/src/test/rustdoc-ui/infinite-recursive-type-impl-trait.rs
index ac79582fb3f..ac517257498 100644
--- a/src/test/rustdoc-ui/infinite-recursive-type-impl-trait.rs
+++ b/src/test/rustdoc-ui/infinite-recursive-type-impl-trait.rs
@@ -1,8 +1,5 @@
-// check-pass
-
 fn f() -> impl Sized {
-    // rustdoc doesn't care that this is infinitely sized
-    enum E {
+    enum E { //~ ERROR
         V(E),
     }
     unimplemented!()
diff --git a/src/test/rustdoc-ui/infinite-recursive-type-impl-trait.stderr b/src/test/rustdoc-ui/infinite-recursive-type-impl-trait.stderr
new file mode 100644
index 00000000000..a61577bd14a
--- /dev/null
+++ b/src/test/rustdoc-ui/infinite-recursive-type-impl-trait.stderr
@@ -0,0 +1,16 @@
+error[E0072]: recursive type `f::E` has infinite size
+  --> $DIR/infinite-recursive-type-impl-trait.rs:2:5
+   |
+LL |     enum E {
+   |     ^^^^^^
+LL |         V(E),
+   |           - recursive without indirection
+   |
+help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle
+   |
+LL |         V(Box<E>),
+   |           ++++ +
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0072`.
diff --git a/src/test/rustdoc-ui/z-help.stdout b/src/test/rustdoc-ui/z-help.stdout
index 3537e669608..53677b18377 100644
--- a/src/test/rustdoc-ui/z-help.stdout
+++ b/src/test/rustdoc-ui/z-help.stdout
@@ -92,6 +92,7 @@
     -Z                             no-analysis=val -- parse and expand the source, but run no analysis
     -Z                              no-codegen=val -- run all passes except codegen; no output
     -Z              no-generate-arange-section=val -- omit DWARF address ranges that give faster lookups
+    -Z                          no-jump-tables=val -- disable the jump tables and lookup tables that can be generated from a switch case lowering
     -Z                           no-leak-check=val -- disable the 'leak check' for subtyping; unsound, but useful for tests
     -Z                                 no-link=val -- compile without linking
     -Z                        no-parallel-llvm=val -- run LLVM in non-parallel mode (while keeping codegen-units and ThinLTO)
diff --git a/src/test/rustdoc/impl-in-const-block.rs b/src/test/rustdoc/impl-in-const-block.rs
new file mode 100644
index 00000000000..b44e7135246
--- /dev/null
+++ b/src/test/rustdoc/impl-in-const-block.rs
@@ -0,0 +1,43 @@
+// Regression test for #83026.
+// The goal of this test is to ensure that impl blocks inside
+// const expressions are documented as well.
+
+#![crate_name = "foo"]
+
+// @has 'foo/struct.A.html'
+// @has - '//*[@id="method.new"]/*[@class="code-header"]' 'pub fn new() -> A'
+// @has - '//*[@id="method.bar"]/*[@class="code-header"]' 'pub fn bar(&self)'
+// @has - '//*[@id="method.woo"]/*[@class="code-header"]' 'pub fn woo(&self)'
+// @has - '//*[@id="method.yoo"]/*[@class="code-header"]' 'pub fn yoo()'
+// @has - '//*[@id="method.yuu"]/*[@class="code-header"]' 'pub fn yuu()'
+pub struct A;
+
+const _: () = {
+    impl A {
+        const FOO: () = {
+            impl A {
+                pub fn woo(&self) {}
+            }
+        };
+
+        pub fn new() -> A {
+            A
+        }
+    }
+};
+pub const X: () = {
+    impl A {
+        pub fn bar(&self) {}
+    }
+};
+
+fn foo() {
+    impl A {
+        pub fn yoo() {}
+    }
+    const _: () = {
+        impl A {
+            pub fn yuu() {}
+        }
+    };
+}
diff --git a/src/test/rustdoc/issue-105952.rs b/src/test/rustdoc/issue-105952.rs
new file mode 100644
index 00000000000..e3f1df0063d
--- /dev/null
+++ b/src/test/rustdoc/issue-105952.rs
@@ -0,0 +1,14 @@
+#![crate_name = "foo"]
+
+#![feature(associated_const_equality)]
+pub enum ParseMode {
+    Raw,
+}
+pub trait Parse {
+    const PARSE_MODE: ParseMode;
+}
+pub trait RenderRaw {}
+
+// @hasraw foo/trait.RenderRaw.html 'impl'
+// @hasraw foo/trait.RenderRaw.html 'ParseMode::Raw'
+impl<T: Parse<PARSE_MODE = { ParseMode::Raw }>> RenderRaw for T {}
diff --git a/src/test/ui/argument-suggestions/extern-fn-arg-names.rs b/src/test/ui/argument-suggestions/extern-fn-arg-names.rs
new file mode 100644
index 00000000000..6c925a3d653
--- /dev/null
+++ b/src/test/ui/argument-suggestions/extern-fn-arg-names.rs
@@ -0,0 +1,9 @@
+extern "Rust" {
+    fn dstfn(src: i32, dst: err);
+    //~^ ERROR cannot find type `err` in this scope
+}
+
+fn main() {
+    dstfn(1);
+    //~^ ERROR this function takes 2 arguments but 1 argument was supplied
+}
diff --git a/src/test/ui/argument-suggestions/extern-fn-arg-names.stderr b/src/test/ui/argument-suggestions/extern-fn-arg-names.stderr
new file mode 100644
index 00000000000..f6bc84c1203
--- /dev/null
+++ b/src/test/ui/argument-suggestions/extern-fn-arg-names.stderr
@@ -0,0 +1,26 @@
+error[E0412]: cannot find type `err` in this scope
+  --> $DIR/extern-fn-arg-names.rs:2:29
+   |
+LL |     fn dstfn(src: i32, dst: err);
+   |                             ^^^ not found in this scope
+
+error[E0061]: this function takes 2 arguments but 1 argument was supplied
+  --> $DIR/extern-fn-arg-names.rs:7:5
+   |
+LL |     dstfn(1);
+   |     ^^^^^--- an argument is missing
+   |
+note: function defined here
+  --> $DIR/extern-fn-arg-names.rs:2:8
+   |
+LL |     fn dstfn(src: i32, dst: err);
+   |        ^^^^^
+help: provide the argument
+   |
+LL |     dstfn(1, /* dst */);
+   |          ~~~~~~~~~~~~~~
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0061, E0412.
+For more information about an error, try `rustc --explain E0061`.
diff --git a/src/test/ui/asm/bad-arch.mirunsafeck.stderr b/src/test/ui/asm/bad-arch.mirunsafeck.stderr
index 4aa27180758..d7af296152f 100644
--- a/src/test/ui/asm/bad-arch.mirunsafeck.stderr
+++ b/src/test/ui/asm/bad-arch.mirunsafeck.stderr
@@ -14,3 +14,4 @@ LL | global_asm!("");
 
 error: aborting due to 2 previous errors
 
+For more information about this error, try `rustc --explain E0472`.
diff --git a/src/test/ui/asm/bad-arch.thirunsafeck.stderr b/src/test/ui/asm/bad-arch.thirunsafeck.stderr
index 4aa27180758..d7af296152f 100644
--- a/src/test/ui/asm/bad-arch.thirunsafeck.stderr
+++ b/src/test/ui/asm/bad-arch.thirunsafeck.stderr
@@ -14,3 +14,4 @@ LL | global_asm!("");
 
 error: aborting due to 2 previous errors
 
+For more information about this error, try `rustc --explain E0472`.
diff --git a/src/test/ui/async-await/async-is-unwindsafe.rs b/src/test/ui/async-await/async-is-unwindsafe.rs
new file mode 100644
index 00000000000..56ed2847292
--- /dev/null
+++ b/src/test/ui/async-await/async-is-unwindsafe.rs
@@ -0,0 +1,30 @@
+// edition:2018
+
+fn is_unwindsafe(_: impl std::panic::UnwindSafe) {}
+
+fn main() {
+    // A normal future created by an async block takes a `&mut Context<'_>` argument.
+    // That should not leak through to the whole async block.
+    is_unwindsafe(async {
+        async {}.await; // this needs an inner await point
+    });
+
+    is_unwindsafe(async {
+        //~^ ERROR the type `&mut Context<'_>` may not be safely transferred across an unwind boundary
+        use std::ptr::null;
+        use std::task::{Context, RawWaker, RawWakerVTable, Waker};
+        let waker = unsafe {
+            Waker::from_raw(RawWaker::new(
+                null(),
+                &RawWakerVTable::new(|_| todo!(), |_| todo!(), |_| todo!(), |_| todo!()),
+            ))
+        };
+        let mut cx = Context::from_waker(&waker);
+        let cx_ref = &mut cx;
+
+        async {}.await; // this needs an inner await point
+
+        // in this case, `&mut Context<'_>` is *truly* alive across an await point
+        drop(cx_ref);
+    });
+}
diff --git a/src/test/ui/async-await/async-is-unwindsafe.stderr b/src/test/ui/async-await/async-is-unwindsafe.stderr
new file mode 100644
index 00000000000..d6404b30e74
--- /dev/null
+++ b/src/test/ui/async-await/async-is-unwindsafe.stderr
@@ -0,0 +1,38 @@
+error[E0277]: the type `&mut Context<'_>` may not be safely transferred across an unwind boundary
+  --> $DIR/async-is-unwindsafe.rs:12:19
+   |
+LL |       is_unwindsafe(async {
+   |  ___________________^
+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: 29:6]`
+   |
+   = help: within `[async block@$DIR/async-is-unwindsafe.rs:12:19: 29:6]`, the trait `UnwindSafe` is not implemented for `&mut Context<'_>`
+   = note: `UnwindSafe` is implemented for `&std::task::Context<'_>`, but not for `&mut std::task::Context<'_>`
+note: future does not implement `UnwindSafe` as this value is used across an await
+  --> $DIR/async-is-unwindsafe.rs:25:17
+   |
+LL |         let cx_ref = &mut cx;
+   |             ------ has type `&mut Context<'_>` which does not implement `UnwindSafe`
+LL |
+LL |         async {}.await; // this needs an inner await point
+   |                 ^^^^^^ await occurs here, with `cx_ref` maybe used later
+...
+LL |     });
+   |     - `cx_ref` is later dropped here
+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 previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/async-await/track-caller/async-closure-gate.rs b/src/test/ui/async-await/track-caller/async-closure-gate.rs
index 9593fdb1908..d9d55685599 100644
--- a/src/test/ui/async-await/track-caller/async-closure-gate.rs
+++ b/src/test/ui/async-await/track-caller/async-closure-gate.rs
@@ -5,6 +5,5 @@
 fn main() {
     let _ = #[track_caller] async || {
         //~^ ERROR `#[track_caller]` on closures is currently unstable [E0658]
-        //~| ERROR `#[track_caller]` on closures is currently unstable [E0658]
     };
 }
diff --git a/src/test/ui/async-await/track-caller/async-closure-gate.stderr b/src/test/ui/async-await/track-caller/async-closure-gate.stderr
index be3d110eccd..498f1b43b9b 100644
--- a/src/test/ui/async-await/track-caller/async-closure-gate.stderr
+++ b/src/test/ui/async-await/track-caller/async-closure-gate.stderr
@@ -7,19 +7,6 @@ LL |     let _ = #[track_caller] async || {
    = note: see issue #87417 <https://github.com/rust-lang/rust/issues/87417> for more information
    = help: add `#![feature(closure_track_caller)]` to the crate attributes to enable
 
-error[E0658]: `#[track_caller]` on closures is currently unstable
-  --> $DIR/async-closure-gate.rs:6:38
-   |
-LL |       let _ = #[track_caller] async || {
-   |  ______________________________________^
-LL | |
-LL | |
-LL | |     };
-   | |_____^
-   |
-   = note: see issue #87417 <https://github.com/rust-lang/rust/issues/87417> for more information
-   = help: add `#![feature(closure_track_caller)]` to the crate attributes to enable
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
 For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/async-await/track-caller/panic-track-caller.nofeat.stderr b/src/test/ui/async-await/track-caller/panic-track-caller.nofeat.stderr
new file mode 100644
index 00000000000..51ea225f4cb
--- /dev/null
+++ b/src/test/ui/async-await/track-caller/panic-track-caller.nofeat.stderr
@@ -0,0 +1,29 @@
+warning: `#[track_caller]` on async functions is a no-op
+  --> $DIR/panic-track-caller.rs:50:1
+   |
+LL |   #[track_caller]
+   |   ^^^^^^^^^^^^^^^
+LL | / async fn bar_track_caller() {
+LL | |     panic!()
+LL | | }
+   | |_- this function will not propagate the caller location
+   |
+   = note: see issue #87417 <https://github.com/rust-lang/rust/issues/87417> for more information
+   = help: add `#![feature(closure_track_caller)]` to the crate attributes to enable
+   = note: `#[warn(ungated_async_fn_track_caller)]` on by default
+
+warning: `#[track_caller]` on async functions is a no-op
+  --> $DIR/panic-track-caller.rs:62:5
+   |
+LL |       #[track_caller]
+   |       ^^^^^^^^^^^^^^^
+LL | /     async fn bar_assoc() {
+LL | |         panic!();
+LL | |     }
+   | |_____- this function will not propagate the caller location
+   |
+   = note: see issue #87417 <https://github.com/rust-lang/rust/issues/87417> for more information
+   = help: add `#![feature(closure_track_caller)]` to the crate attributes to enable
+
+warning: 2 warnings emitted
+
diff --git a/src/test/ui/async-await/track-caller/panic-track-caller.rs b/src/test/ui/async-await/track-caller/panic-track-caller.rs
index 066cf97628f..f45243b0ea6 100644
--- a/src/test/ui/async-await/track-caller/panic-track-caller.rs
+++ b/src/test/ui/async-await/track-caller/panic-track-caller.rs
@@ -1,7 +1,9 @@
 // run-pass
 // edition:2021
+// revisions: feat nofeat
 // needs-unwind
-#![feature(closure_track_caller, async_closure, stmt_expr_attributes)]
+#![feature(async_closure, stmt_expr_attributes)]
+#![cfg_attr(feat, feature(closure_track_caller))]
 
 use std::future::Future;
 use std::panic;
@@ -45,7 +47,7 @@ async fn foo() {
     bar().await
 }
 
-#[track_caller]
+#[track_caller] //[nofeat]~ WARN `#[track_caller]` on async functions is a no-op
 async fn bar_track_caller() {
     panic!()
 }
@@ -57,7 +59,7 @@ async fn foo_track_caller() {
 struct Foo;
 
 impl Foo {
-    #[track_caller]
+    #[track_caller] //[nofeat]~ WARN `#[track_caller]` on async functions is a no-op
     async fn bar_assoc() {
         panic!();
     }
@@ -67,6 +69,9 @@ async fn foo_assoc() {
     Foo::bar_assoc().await
 }
 
+// Since compilation is expected to fail for this fn when using
+// `nofeat`, we test that separately in `async-closure-gate.rs`
+#[cfg(feat)]
 async fn foo_closure() {
     let c = #[track_caller] async || {
         panic!();
@@ -91,8 +96,18 @@ fn panicked_at(f: impl FnOnce() + panic::UnwindSafe) -> u32 {
 }
 
 fn main() {
-    assert_eq!(panicked_at(|| block_on(foo())), 41);
-    assert_eq!(panicked_at(|| block_on(foo_track_caller())), 54);
-    assert_eq!(panicked_at(|| block_on(foo_assoc())), 67);
-    assert_eq!(panicked_at(|| block_on(foo_closure())), 74);
+    assert_eq!(panicked_at(|| block_on(foo())), 43);
+
+    #[cfg(feat)]
+    assert_eq!(panicked_at(|| block_on(foo_track_caller())), 56);
+    #[cfg(nofeat)]
+    assert_eq!(panicked_at(|| block_on(foo_track_caller())), 52);
+
+    #[cfg(feat)]
+    assert_eq!(panicked_at(|| block_on(foo_assoc())), 69);
+    #[cfg(nofeat)]
+    assert_eq!(panicked_at(|| block_on(foo_assoc())), 64);
+
+    #[cfg(feat)]
+    assert_eq!(panicked_at(|| block_on(foo_closure())), 79);
 }
diff --git a/src/test/ui/attributes/issue-105594-invalid-attr-validation.rs b/src/test/ui/attributes/issue-105594-invalid-attr-validation.rs
new file mode 100644
index 00000000000..6c68e6b046f
--- /dev/null
+++ b/src/test/ui/attributes/issue-105594-invalid-attr-validation.rs
@@ -0,0 +1,13 @@
+// This checks that the attribute validation ICE in issue #105594 doesn't
+// recur.
+//
+// ignore-thumbv8m.base
+#![feature(cmse_nonsecure_entry)]
+
+fn main() {}
+
+#[track_caller] //~ ERROR attribute should be applied to a function
+static _A: () = ();
+
+#[cmse_nonsecure_entry] //~ ERROR attribute should be applied to a function
+static _B: () = (); //~| ERROR #[cmse_nonsecure_entry]` is only valid for targets
diff --git a/src/test/ui/attributes/issue-105594-invalid-attr-validation.stderr b/src/test/ui/attributes/issue-105594-invalid-attr-validation.stderr
new file mode 100644
index 00000000000..c6b2d6e7813
--- /dev/null
+++ b/src/test/ui/attributes/issue-105594-invalid-attr-validation.stderr
@@ -0,0 +1,26 @@
+error[E0739]: attribute should be applied to a function definition
+  --> $DIR/issue-105594-invalid-attr-validation.rs:9:1
+   |
+LL | #[track_caller]
+   | ^^^^^^^^^^^^^^^
+LL | static _A: () = ();
+   | ------------------- not a function definition
+
+error: attribute should be applied to a function definition
+  --> $DIR/issue-105594-invalid-attr-validation.rs:12:1
+   |
+LL | #[cmse_nonsecure_entry]
+   | ^^^^^^^^^^^^^^^^^^^^^^^
+LL | static _B: () = ();
+   | ------------------- not a function definition
+
+error[E0775]: `#[cmse_nonsecure_entry]` is only valid for targets with the TrustZone-M extension
+  --> $DIR/issue-105594-invalid-attr-validation.rs:12:1
+   |
+LL | #[cmse_nonsecure_entry]
+   | ^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 3 previous errors
+
+Some errors have detailed explanations: E0739, E0775.
+For more information about an error, try `rustc --explain E0739`.
diff --git a/src/test/ui/z-crate-attr.rs b/src/test/ui/attributes/z-crate-attr.rs
index 1021774fc5f..1021774fc5f 100644
--- a/src/test/ui/z-crate-attr.rs
+++ b/src/test/ui/attributes/z-crate-attr.rs
diff --git a/src/test/ui/borrowck/borrowck-move-out-of-overloaded-auto-deref.stderr b/src/test/ui/borrowck/borrowck-move-out-of-overloaded-auto-deref.stderr
index ecf5382e863..87135f0bb43 100644
--- a/src/test/ui/borrowck/borrowck-move-out-of-overloaded-auto-deref.stderr
+++ b/src/test/ui/borrowck/borrowck-move-out-of-overloaded-auto-deref.stderr
@@ -9,6 +9,10 @@ LL |     let _x = Rc::new(vec![1, 2]).into_iter();
    |
 note: `into_iter` takes ownership of the receiver `self`, which moves value
   --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
+help: you can `clone` the value and consume it, but this might not be your desired behavior
+   |
+LL |     let _x = Rc::new(vec![1, 2]).clone().into_iter();
+   |                                  ++++++++
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/borrowck/unboxed-closures-move-upvar-from-non-once-ref-closure.fixed b/src/test/ui/borrowck/unboxed-closures-move-upvar-from-non-once-ref-closure.fixed
new file mode 100644
index 00000000000..b0c5376105b
--- /dev/null
+++ b/src/test/ui/borrowck/unboxed-closures-move-upvar-from-non-once-ref-closure.fixed
@@ -0,0 +1,15 @@
+// run-rustfix
+// Test that a by-ref `FnMut` closure gets an error when it tries to
+// consume a value.
+
+fn call<F>(f: F) where F : Fn() {
+    f();
+}
+
+fn main() {
+    let y = vec![format!("World")];
+    call(|| {
+        y.clone().into_iter();
+        //~^ ERROR cannot move out of `y`, a captured variable in an `Fn` closure
+    });
+}
diff --git a/src/test/ui/borrowck/unboxed-closures-move-upvar-from-non-once-ref-closure.rs b/src/test/ui/borrowck/unboxed-closures-move-upvar-from-non-once-ref-closure.rs
index d54b09c5da9..4666b8a3373 100644
--- a/src/test/ui/borrowck/unboxed-closures-move-upvar-from-non-once-ref-closure.rs
+++ b/src/test/ui/borrowck/unboxed-closures-move-upvar-from-non-once-ref-closure.rs
@@ -1,3 +1,4 @@
+// run-rustfix
 // Test that a by-ref `FnMut` closure gets an error when it tries to
 // consume a value.
 
diff --git a/src/test/ui/borrowck/unboxed-closures-move-upvar-from-non-once-ref-closure.stderr b/src/test/ui/borrowck/unboxed-closures-move-upvar-from-non-once-ref-closure.stderr
index b1367c65218..f033d53bf8e 100644
--- a/src/test/ui/borrowck/unboxed-closures-move-upvar-from-non-once-ref-closure.stderr
+++ b/src/test/ui/borrowck/unboxed-closures-move-upvar-from-non-once-ref-closure.stderr
@@ -1,5 +1,5 @@
 error[E0507]: cannot move out of `y`, a captured variable in an `Fn` closure
-  --> $DIR/unboxed-closures-move-upvar-from-non-once-ref-closure.rs:11:9
+  --> $DIR/unboxed-closures-move-upvar-from-non-once-ref-closure.rs:12:9
    |
 LL |     let y = vec![format!("World")];
    |         - captured outer variable
@@ -12,6 +12,10 @@ LL |         y.into_iter();
    |
 note: `into_iter` takes ownership of the receiver `self`, which moves `y`
   --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
+help: you can `clone` the value and consume it, but this might not be your desired behavior
+   |
+LL |         y.clone().into_iter();
+   |           ++++++++
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/codemap_tests/tab_3.stderr b/src/test/ui/codemap_tests/tab_3.stderr
index e0e369124a4..17bea2f366f 100644
--- a/src/test/ui/codemap_tests/tab_3.stderr
+++ b/src/test/ui/codemap_tests/tab_3.stderr
@@ -12,10 +12,10 @@ LL |         println!("{:?}", some_vec);
 note: `into_iter` takes ownership of the receiver `self`, which moves `some_vec`
   --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
    = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)
-help: consider cloning the value if the performance cost is acceptable
+help: you can `clone` the value and consume it, but this might not be your desired behavior
    |
 LL |     some_vec.clone().into_iter();
-   |             ++++++++
+   |              ++++++++
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/command/command-argv0-debug.rs b/src/test/ui/command/command-argv0-debug.rs
deleted file mode 100644
index 4aba1229f29..00000000000
--- a/src/test/ui/command/command-argv0-debug.rs
+++ /dev/null
@@ -1,21 +0,0 @@
-// run-pass
-
-// ignore-windows - this is a unix-specific test
-// ignore-emscripten no processes
-// ignore-sgx no processes
-use std::os::unix::process::CommandExt;
-use std::process::Command;
-
-fn main() {
-    let mut command = Command::new("some-boring-name");
-
-    assert_eq!(format!("{:?}", command), r#""some-boring-name""#);
-
-    command.args(&["1", "2", "3"]);
-
-    assert_eq!(format!("{:?}", command), r#""some-boring-name" "1" "2" "3""#);
-
-    command.arg0("exciting-name");
-
-    assert_eq!(format!("{:?}", command), r#"["some-boring-name"] "exciting-name" "1" "2" "3""#);
-}
diff --git a/src/test/ui/const-generics/generic_const_exprs/issue-94293.rs b/src/test/ui/const-generics/generic_const_exprs/issue-94293.rs
new file mode 100644
index 00000000000..713c5d89a93
--- /dev/null
+++ b/src/test/ui/const-generics/generic_const_exprs/issue-94293.rs
@@ -0,0 +1,31 @@
+// check-pass
+
+#![feature(generic_const_exprs)]
+#![allow(incomplete_features)]
+#![deny(const_evaluatable_unchecked)]
+
+pub struct If<const CONDITION: bool>;
+pub trait True {}
+impl True for If<true> {}
+
+pub struct FixedI8<const FRAC: u32> {
+    pub bits: i8,
+}
+
+impl<const FRAC_LHS: u32, const FRAC_RHS: u32> PartialEq<FixedI8<FRAC_RHS>> for FixedI8<FRAC_LHS>
+where
+    If<{ FRAC_RHS <= 8 }>: True,
+{
+    fn eq(&self, _rhs: &FixedI8<FRAC_RHS>) -> bool {
+        unimplemented!()
+    }
+}
+
+impl<const FRAC: u32> PartialEq<i8> for FixedI8<FRAC> {
+    fn eq(&self, rhs: &i8) -> bool {
+        let rhs_as_fixed = FixedI8::<0> { bits: *rhs };
+        PartialEq::eq(self, &rhs_as_fixed)
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/const-generics/generic_const_exprs/issue-99647.rs b/src/test/ui/const-generics/generic_const_exprs/issue-99647.rs
new file mode 100644
index 00000000000..f797beda8e6
--- /dev/null
+++ b/src/test/ui/const-generics/generic_const_exprs/issue-99647.rs
@@ -0,0 +1,15 @@
+// edition:2018
+// run-pass
+
+#![allow(incomplete_features)]
+#![feature(generic_const_exprs)]
+
+#[allow(unused)]
+async fn foo<'a>() {
+    let _data = &mut [0u8; { 1 + 4 }];
+    bar().await
+}
+
+async fn bar() {}
+
+fn main() {}
diff --git a/src/test/ui/consts/assert-type-intrinsics.rs b/src/test/ui/consts/assert-type-intrinsics.rs
index 263d1ae6a3e..b4fd423becd 100644
--- a/src/test/ui/consts/assert-type-intrinsics.rs
+++ b/src/test/ui/consts/assert-type-intrinsics.rs
@@ -13,7 +13,7 @@ fn main() {
         //~^ERROR: evaluation of constant value failed
     };
     const _BAD2: () = {
-        intrinsics::assert_uninit_valid::<&'static i32>();
+        intrinsics::assert_mem_uninitialized_valid::<&'static i32>();
         //~^ERROR: evaluation of constant value failed
     };
     const _BAD3: () = {
diff --git a/src/test/ui/consts/assert-type-intrinsics.stderr b/src/test/ui/consts/assert-type-intrinsics.stderr
index f92f9fda069..70aec91e226 100644
--- a/src/test/ui/consts/assert-type-intrinsics.stderr
+++ b/src/test/ui/consts/assert-type-intrinsics.stderr
@@ -7,8 +7,8 @@ LL |         MaybeUninit::<!>::uninit().assume_init();
 error[E0080]: evaluation of constant value failed
   --> $DIR/assert-type-intrinsics.rs:16:9
    |
-LL |         intrinsics::assert_uninit_valid::<&'static i32>();
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ aborted execution: attempted to leave type `&i32` uninitialized, which is invalid
+LL |         intrinsics::assert_mem_uninitialized_valid::<&'static i32>();
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ aborted execution: attempted to leave type `&i32` uninitialized, which is invalid
 
 error[E0080]: evaluation of constant value failed
   --> $DIR/assert-type-intrinsics.rs:20:9
diff --git a/src/test/ui/consts/issue-104396.rs b/src/test/ui/consts/issue-104396.rs
new file mode 100644
index 00000000000..315b0cf0fd6
--- /dev/null
+++ b/src/test/ui/consts/issue-104396.rs
@@ -0,0 +1,36 @@
+// compile-flags: -Zmir-opt-level=3
+// check-pass
+
+#![feature(generic_const_exprs)]
+//~^ WARN the feature `generic_const_exprs` is incomplete
+
+#[inline(always)]
+fn from_fn_1<const N: usize, F: FnMut(usize) -> f32>(mut f: F) -> [f32; N] {
+    let mut result = [0.0; N];
+    let mut i = 0;
+    while i < N {
+        result[i] = f(i);
+        i += 1;
+    }
+    result
+}
+
+pub struct TestArray<const N: usize>
+where
+    [(); N / 2]:,
+{
+    array: [f32; N / 2],
+}
+
+impl<const N: usize> TestArray<N>
+where
+    [(); N / 2]:,
+{
+    fn from_fn_2<F: FnMut(usize) -> f32>(f: F) -> Self {
+        Self { array: from_fn_1(f) }
+    }
+}
+
+fn main() {
+    TestArray::<4>::from_fn_2(|i| 0.0);
+}
diff --git a/src/test/ui/consts/issue-104396.stderr b/src/test/ui/consts/issue-104396.stderr
new file mode 100644
index 00000000000..5856bee09a3
--- /dev/null
+++ b/src/test/ui/consts/issue-104396.stderr
@@ -0,0 +1,11 @@
+warning: the feature `generic_const_exprs` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/issue-104396.rs:4:12
+   |
+LL | #![feature(generic_const_exprs)]
+   |            ^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #76560 <https://github.com/rust-lang/rust/issues/76560> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/consts/promoted_const_call.rs b/src/test/ui/consts/promoted_const_call.rs
new file mode 100644
index 00000000000..30ae730535c
--- /dev/null
+++ b/src/test/ui/consts/promoted_const_call.rs
@@ -0,0 +1,19 @@
+#![feature(const_mut_refs)]
+#![feature(const_trait_impl)]
+struct Panic;
+impl const Drop for Panic { fn drop(&mut self) { panic!(); } }
+pub const fn id<T>(x: T) -> T { x }
+pub const C: () = {
+    let _: &'static _ = &id(&Panic);
+    //~^ ERROR: temporary value dropped while borrowed
+    //~| ERROR: temporary value dropped while borrowed
+};
+
+fn main() {
+    let _: &'static _ = &id(&Panic);
+    //~^ ERROR: temporary value dropped while borrowed
+    //~| ERROR: temporary value dropped while borrowed
+    let _: &'static _ = &&(Panic, 0).1;
+    //~^ ERROR: temporary value dropped while borrowed
+    //~| ERROR: temporary value dropped while borrowed
+}
diff --git a/src/test/ui/consts/promoted_const_call.stderr b/src/test/ui/consts/promoted_const_call.stderr
new file mode 100644
index 00000000000..83cc16f6f94
--- /dev/null
+++ b/src/test/ui/consts/promoted_const_call.stderr
@@ -0,0 +1,65 @@
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/promoted_const_call.rs:7:26
+   |
+LL |     let _: &'static _ = &id(&Panic);
+   |            ----------    ^^^^^^^^^^ creates a temporary value which is freed while still in use
+   |            |
+   |            type annotation requires that borrow lasts for `'static`
+...
+LL | };
+   | - temporary value is freed at the end of this statement
+
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/promoted_const_call.rs:7:30
+   |
+LL |     let _: &'static _ = &id(&Panic);
+   |            ----------        ^^^^^ - temporary value is freed at the end of this statement
+   |            |                 |
+   |            |                 creates a temporary value which is freed while still in use
+   |            type annotation requires that borrow lasts for `'static`
+
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/promoted_const_call.rs:13:26
+   |
+LL |     let _: &'static _ = &id(&Panic);
+   |            ----------    ^^^^^^^^^^ creates a temporary value which is freed while still in use
+   |            |
+   |            type annotation requires that borrow lasts for `'static`
+...
+LL | }
+   | - temporary value is freed at the end of this statement
+
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/promoted_const_call.rs:13:30
+   |
+LL |     let _: &'static _ = &id(&Panic);
+   |            ----------        ^^^^^ - temporary value is freed at the end of this statement
+   |            |                 |
+   |            |                 creates a temporary value which is freed while still in use
+   |            type annotation requires that borrow lasts for `'static`
+
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/promoted_const_call.rs:16:26
+   |
+LL |     let _: &'static _ = &&(Panic, 0).1;
+   |            ----------    ^^^^^^^^^^^^^ creates a temporary value which is freed while still in use
+   |            |
+   |            type annotation requires that borrow lasts for `'static`
+...
+LL | }
+   | - temporary value is freed at the end of this statement
+
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/promoted_const_call.rs:16:27
+   |
+LL |     let _: &'static _ = &&(Panic, 0).1;
+   |            ----------     ^^^^^^^^^^ creates a temporary value which is freed while still in use
+   |            |
+   |            type annotation requires that borrow lasts for `'static`
+...
+LL | }
+   | - temporary value is freed at the end of this statement
+
+error: aborting due to 6 previous errors
+
+For more information about this error, try `rustc --explain E0716`.
diff --git a/src/test/ui/consts/promoted_const_call2.rs b/src/test/ui/consts/promoted_const_call2.rs
new file mode 100644
index 00000000000..f332cd18cea
--- /dev/null
+++ b/src/test/ui/consts/promoted_const_call2.rs
@@ -0,0 +1,14 @@
+#![feature(const_precise_live_drops)]
+pub const fn id<T>(x: T) -> T { x }
+pub const C: () = {
+    let _: &'static _ = &id(&String::new());
+    //~^ ERROR: temporary value dropped while borrowed
+    //~| ERROR: temporary value dropped while borrowed
+    //~| ERROR: destructor of `String` cannot be evaluated at compile-time
+};
+
+fn main() {
+    let _: &'static _ = &id(&String::new());
+    //~^ ERROR: temporary value dropped while borrowed
+    //~| ERROR: temporary value dropped while borrowed
+}
diff --git a/src/test/ui/consts/promoted_const_call2.stderr b/src/test/ui/consts/promoted_const_call2.stderr
new file mode 100644
index 00000000000..13d864ed3db
--- /dev/null
+++ b/src/test/ui/consts/promoted_const_call2.stderr
@@ -0,0 +1,50 @@
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/promoted_const_call2.rs:4:26
+   |
+LL |     let _: &'static _ = &id(&String::new());
+   |            ----------    ^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use
+   |            |
+   |            type annotation requires that borrow lasts for `'static`
+...
+LL | };
+   | - temporary value is freed at the end of this statement
+
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/promoted_const_call2.rs:4:30
+   |
+LL |     let _: &'static _ = &id(&String::new());
+   |            ----------        ^^^^^^^^^^^^^ - temporary value is freed at the end of this statement
+   |            |                 |
+   |            |                 creates a temporary value which is freed while still in use
+   |            type annotation requires that borrow lasts for `'static`
+
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/promoted_const_call2.rs:11:26
+   |
+LL |     let _: &'static _ = &id(&String::new());
+   |            ----------    ^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use
+   |            |
+   |            type annotation requires that borrow lasts for `'static`
+...
+LL | }
+   | - temporary value is freed at the end of this statement
+
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/promoted_const_call2.rs:11:30
+   |
+LL |     let _: &'static _ = &id(&String::new());
+   |            ----------        ^^^^^^^^^^^^^ - temporary value is freed at the end of this statement
+   |            |                 |
+   |            |                 creates a temporary value which is freed while still in use
+   |            type annotation requires that borrow lasts for `'static`
+
+error[E0493]: destructor of `String` cannot be evaluated at compile-time
+  --> $DIR/promoted_const_call2.rs:4:30
+   |
+LL |     let _: &'static _ = &id(&String::new());
+   |                              ^^^^^^^^^^^^^ the destructor for this type cannot be evaluated in constants
+
+error: aborting due to 5 previous errors
+
+Some errors have detailed explanations: E0493, E0716.
+For more information about an error, try `rustc --explain E0493`.
diff --git a/src/test/ui/consts/promoted_const_call3.rs b/src/test/ui/consts/promoted_const_call3.rs
new file mode 100644
index 00000000000..6d68a2de70e
--- /dev/null
+++ b/src/test/ui/consts/promoted_const_call3.rs
@@ -0,0 +1,26 @@
+pub const fn id<T>(x: T) -> T { x }
+pub const C: () = {
+    let _: &'static _ = &String::new();
+    //~^ ERROR: destructor of `String` cannot be evaluated at compile-time
+    //~| ERROR: temporary value dropped while borrowed
+
+    let _: &'static _ = &id(&String::new());
+    //~^ ERROR: destructor of `String` cannot be evaluated at compile-time
+    //~| ERROR: temporary value dropped while borrowed
+    //~| ERROR: temporary value dropped while borrowed
+
+    let _: &'static _ = &std::mem::ManuallyDrop::new(String::new());
+    //~^ ERROR: temporary value dropped while borrowed
+};
+
+fn main() {
+    let _: &'static _ = &String::new();
+    //~^ ERROR: temporary value dropped while borrowed
+
+    let _: &'static _ = &id(&String::new());
+    //~^ ERROR: temporary value dropped while borrowed
+    //~| ERROR: temporary value dropped while borrowed
+
+    let _: &'static _ = &std::mem::ManuallyDrop::new(String::new());
+    //~^ ERROR: temporary value dropped while borrowed
+}
diff --git a/src/test/ui/consts/promoted_const_call3.stderr b/src/test/ui/consts/promoted_const_call3.stderr
new file mode 100644
index 00000000000..af17457a10a
--- /dev/null
+++ b/src/test/ui/consts/promoted_const_call3.stderr
@@ -0,0 +1,105 @@
+error[E0493]: destructor of `String` cannot be evaluated at compile-time
+  --> $DIR/promoted_const_call3.rs:7:30
+   |
+LL |     let _: &'static _ = &id(&String::new());
+   |                              ^^^^^^^^^^^^^ - value is dropped here
+   |                              |
+   |                              the destructor for this type cannot be evaluated in constants
+
+error[E0493]: destructor of `String` cannot be evaluated at compile-time
+  --> $DIR/promoted_const_call3.rs:3:26
+   |
+LL |     let _: &'static _ = &String::new();
+   |                          ^^^^^^^^^^^^^ the destructor for this type cannot be evaluated in constants
+...
+LL | };
+   | - value is dropped here
+
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/promoted_const_call3.rs:3:26
+   |
+LL |     let _: &'static _ = &String::new();
+   |            ----------    ^^^^^^^^^^^^^ creates a temporary value which is freed while still in use
+   |            |
+   |            type annotation requires that borrow lasts for `'static`
+...
+LL | };
+   | - temporary value is freed at the end of this statement
+
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/promoted_const_call3.rs:7:26
+   |
+LL |     let _: &'static _ = &id(&String::new());
+   |            ----------    ^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use
+   |            |
+   |            type annotation requires that borrow lasts for `'static`
+...
+LL | };
+   | - temporary value is freed at the end of this statement
+
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/promoted_const_call3.rs:7:30
+   |
+LL |     let _: &'static _ = &id(&String::new());
+   |            ----------        ^^^^^^^^^^^^^ - temporary value is freed at the end of this statement
+   |            |                 |
+   |            |                 creates a temporary value which is freed while still in use
+   |            type annotation requires that borrow lasts for `'static`
+
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/promoted_const_call3.rs:12:26
+   |
+LL |     let _: &'static _ = &std::mem::ManuallyDrop::new(String::new());
+   |            ----------    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use
+   |            |
+   |            type annotation requires that borrow lasts for `'static`
+LL |
+LL | };
+   | - temporary value is freed at the end of this statement
+
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/promoted_const_call3.rs:17:26
+   |
+LL |     let _: &'static _ = &String::new();
+   |            ----------    ^^^^^^^^^^^^^ creates a temporary value which is freed while still in use
+   |            |
+   |            type annotation requires that borrow lasts for `'static`
+...
+LL | }
+   | - temporary value is freed at the end of this statement
+
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/promoted_const_call3.rs:20:26
+   |
+LL |     let _: &'static _ = &id(&String::new());
+   |            ----------    ^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use
+   |            |
+   |            type annotation requires that borrow lasts for `'static`
+...
+LL | }
+   | - temporary value is freed at the end of this statement
+
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/promoted_const_call3.rs:20:30
+   |
+LL |     let _: &'static _ = &id(&String::new());
+   |            ----------        ^^^^^^^^^^^^^ - temporary value is freed at the end of this statement
+   |            |                 |
+   |            |                 creates a temporary value which is freed while still in use
+   |            type annotation requires that borrow lasts for `'static`
+
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/promoted_const_call3.rs:24:26
+   |
+LL |     let _: &'static _ = &std::mem::ManuallyDrop::new(String::new());
+   |            ----------    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use
+   |            |
+   |            type annotation requires that borrow lasts for `'static`
+LL |
+LL | }
+   | - temporary value is freed at the end of this statement
+
+error: aborting due to 10 previous errors
+
+Some errors have detailed explanations: E0493, E0716.
+For more information about an error, try `rustc --explain E0493`.
diff --git a/src/test/ui/consts/promoted_const_call4.rs b/src/test/ui/consts/promoted_const_call4.rs
new file mode 100644
index 00000000000..82a17b7bf86
--- /dev/null
+++ b/src/test/ui/consts/promoted_const_call4.rs
@@ -0,0 +1,18 @@
+// run-pass
+
+use std::sync::atomic::*;
+
+static FLAG: AtomicBool = AtomicBool::new(false);
+
+struct NoisyDrop(&'static str);
+impl Drop for NoisyDrop {
+    fn drop(&mut self) {
+        FLAG.store(true, Ordering::SeqCst);
+    }
+}
+fn main() {
+    {
+        let _val = &&(NoisyDrop("drop!"), 0).1;
+    }
+    assert!(FLAG.load(Ordering::SeqCst));
+}
diff --git a/src/test/ui/consts/promoted_const_call5.rs b/src/test/ui/consts/promoted_const_call5.rs
new file mode 100644
index 00000000000..3ac8d358ce4
--- /dev/null
+++ b/src/test/ui/consts/promoted_const_call5.rs
@@ -0,0 +1,42 @@
+#![feature(rustc_attrs)]
+#![feature(staged_api)]
+#![stable(feature = "a", since = "1.0.0")]
+
+#[rustc_promotable]
+#[stable(feature = "a", since = "1.0.0")]
+#[rustc_const_stable(feature = "a", since = "1.0.0")]
+pub const fn id<T>(x: &'static T) -> &'static T { x }
+
+#[rustc_promotable]
+#[stable(feature = "a", since = "1.0.0")]
+#[rustc_const_stable(feature = "a", since = "1.0.0")]
+pub const fn new_string() -> String {
+    String::new()
+}
+
+#[rustc_promotable]
+#[stable(feature = "a", since = "1.0.0")]
+#[rustc_const_stable(feature = "a", since = "1.0.0")]
+pub const fn new_manually_drop<T>(t: T) -> std::mem::ManuallyDrop<T>  {
+    std::mem::ManuallyDrop::new(t)
+}
+
+
+const C: () = {
+    let _: &'static _ = &id(&new_string());
+    //~^ ERROR destructor of `String` cannot be evaluated at compile-time
+    //~| ERROR: temporary value dropped while borrowed
+    //~| ERROR: temporary value dropped while borrowed
+
+    let _: &'static _ = &new_manually_drop(new_string());
+    //~^ ERROR: temporary value dropped while borrowed
+};
+
+fn main() {
+    let _: &'static _ = &id(&new_string());
+    //~^ ERROR: temporary value dropped while borrowed
+    //~| ERROR: temporary value dropped while borrowed
+
+    let _: &'static _ = &new_manually_drop(new_string());
+    //~^ ERROR: temporary value dropped while borrowed
+}
diff --git a/src/test/ui/consts/promoted_const_call5.stderr b/src/test/ui/consts/promoted_const_call5.stderr
new file mode 100644
index 00000000000..f736220b183
--- /dev/null
+++ b/src/test/ui/consts/promoted_const_call5.stderr
@@ -0,0 +1,74 @@
+error[E0493]: destructor of `String` cannot be evaluated at compile-time
+  --> $DIR/promoted_const_call5.rs:26:30
+   |
+LL |     let _: &'static _ = &id(&new_string());
+   |                              ^^^^^^^^^^^^ - value is dropped here
+   |                              |
+   |                              the destructor for this type cannot be evaluated in constants
+
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/promoted_const_call5.rs:26:26
+   |
+LL |     let _: &'static _ = &id(&new_string());
+   |            ----------    ^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use
+   |            |
+   |            type annotation requires that borrow lasts for `'static`
+...
+LL | };
+   | - temporary value is freed at the end of this statement
+
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/promoted_const_call5.rs:26:30
+   |
+LL |     let _: &'static _ = &id(&new_string());
+   |                          ----^^^^^^^^^^^^-- temporary value is freed at the end of this statement
+   |                          |   |
+   |                          |   creates a temporary value which is freed while still in use
+   |                          argument requires that borrow lasts for `'static`
+
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/promoted_const_call5.rs:31:26
+   |
+LL |     let _: &'static _ = &new_manually_drop(new_string());
+   |            ----------    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use
+   |            |
+   |            type annotation requires that borrow lasts for `'static`
+LL |
+LL | };
+   | - temporary value is freed at the end of this statement
+
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/promoted_const_call5.rs:36:26
+   |
+LL |     let _: &'static _ = &id(&new_string());
+   |            ----------    ^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use
+   |            |
+   |            type annotation requires that borrow lasts for `'static`
+...
+LL | }
+   | - temporary value is freed at the end of this statement
+
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/promoted_const_call5.rs:36:30
+   |
+LL |     let _: &'static _ = &id(&new_string());
+   |                          ----^^^^^^^^^^^^-- temporary value is freed at the end of this statement
+   |                          |   |
+   |                          |   creates a temporary value which is freed while still in use
+   |                          argument requires that borrow lasts for `'static`
+
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/promoted_const_call5.rs:40:26
+   |
+LL |     let _: &'static _ = &new_manually_drop(new_string());
+   |            ----------    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use
+   |            |
+   |            type annotation requires that borrow lasts for `'static`
+LL |
+LL | }
+   | - temporary value is freed at the end of this statement
+
+error: aborting due to 7 previous errors
+
+Some errors have detailed explanations: E0493, E0716.
+For more information about an error, try `rustc --explain E0493`.
diff --git a/src/test/ui/error-codes/E0033-teach.rs b/src/test/ui/error-codes/E0033-teach.rs
index 19439651394..289561bad8a 100644
--- a/src/test/ui/error-codes/E0033-teach.rs
+++ b/src/test/ui/error-codes/E0033-teach.rs
@@ -1,13 +1,13 @@
 // compile-flags: -Z teach
-
 trait SomeTrait {
-    fn foo(); //~ associated function `foo` has no `self` parameter
+    fn foo(&self);
+}
+struct S;
+impl SomeTrait for S {
+    fn foo(&self) {}
 }
-
 fn main() {
-    let trait_obj: &dyn SomeTrait = SomeTrait;
-    //~^ ERROR expected value, found trait `SomeTrait`
-    //~| ERROR E0038
+    let trait_obj: &dyn SomeTrait = &S;
 
     let &invalid = trait_obj;
     //~^ ERROR E0033
diff --git a/src/test/ui/error-codes/E0033-teach.stderr b/src/test/ui/error-codes/E0033-teach.stderr
index 3b68abbb4a0..31bc6719a56 100644
--- a/src/test/ui/error-codes/E0033-teach.stderr
+++ b/src/test/ui/error-codes/E0033-teach.stderr
@@ -1,31 +1,3 @@
-error[E0423]: expected value, found trait `SomeTrait`
-  --> $DIR/E0033-teach.rs:8:37
-   |
-LL |     let trait_obj: &dyn SomeTrait = SomeTrait;
-   |                                     ^^^^^^^^^ not a value
-
-error[E0038]: the trait `SomeTrait` cannot be made into an object
-  --> $DIR/E0033-teach.rs:8:20
-   |
-LL |     let trait_obj: &dyn SomeTrait = SomeTrait;
-   |                    ^^^^^^^^^^^^^^ `SomeTrait` cannot be made into an object
-   |
-note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
-  --> $DIR/E0033-teach.rs:4:8
-   |
-LL | trait SomeTrait {
-   |       --------- this trait cannot be made into an object...
-LL |     fn foo();
-   |        ^^^ ...because associated function `foo` has no `self` parameter
-help: consider turning `foo` into a method by giving it a `&self` argument
-   |
-LL |     fn foo(&self);
-   |            +++++
-help: alternatively, consider constraining `foo` so it does not apply to trait objects
-   |
-LL |     fn foo() where Self: Sized;
-   |              +++++++++++++++++
-
 error[E0033]: type `&dyn SomeTrait` cannot be dereferenced
   --> $DIR/E0033-teach.rs:12:9
    |
@@ -36,7 +8,6 @@ LL |     let &invalid = trait_obj;
            
            You can read more about trait objects in the Trait Objects section of the Reference: https://doc.rust-lang.org/reference/types.html#trait-objects
 
-error: aborting due to 3 previous errors
+error: aborting due to previous error
 
-Some errors have detailed explanations: E0033, E0038, E0423.
-For more information about an error, try `rustc --explain E0033`.
+For more information about this error, try `rustc --explain E0033`.
diff --git a/src/test/ui/error-codes/E0033.rs b/src/test/ui/error-codes/E0033.rs
index e5f0530f45f..bd6ec207223 100644
--- a/src/test/ui/error-codes/E0033.rs
+++ b/src/test/ui/error-codes/E0033.rs
@@ -1,11 +1,12 @@
 trait SomeTrait {
-    fn foo(); //~ associated function `foo` has no `self` parameter
+    fn foo(&self);
+}
+struct S;
+impl SomeTrait for S {
+    fn foo(&self) {}
 }
-
 fn main() {
-    let trait_obj: &dyn SomeTrait = SomeTrait;
-    //~^ ERROR expected value, found trait `SomeTrait`
-    //~| ERROR E0038
+    let trait_obj: &dyn SomeTrait = &S;
 
     let &invalid = trait_obj;
     //~^ ERROR E0033
diff --git a/src/test/ui/error-codes/E0033.stderr b/src/test/ui/error-codes/E0033.stderr
index f0645107831..ab2e780ee62 100644
--- a/src/test/ui/error-codes/E0033.stderr
+++ b/src/test/ui/error-codes/E0033.stderr
@@ -1,38 +1,9 @@
-error[E0423]: expected value, found trait `SomeTrait`
-  --> $DIR/E0033.rs:6:37
-   |
-LL |     let trait_obj: &dyn SomeTrait = SomeTrait;
-   |                                     ^^^^^^^^^ not a value
-
-error[E0038]: the trait `SomeTrait` cannot be made into an object
-  --> $DIR/E0033.rs:6:20
-   |
-LL |     let trait_obj: &dyn SomeTrait = SomeTrait;
-   |                    ^^^^^^^^^^^^^^ `SomeTrait` cannot be made into an object
-   |
-note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
-  --> $DIR/E0033.rs:2:8
-   |
-LL | trait SomeTrait {
-   |       --------- this trait cannot be made into an object...
-LL |     fn foo();
-   |        ^^^ ...because associated function `foo` has no `self` parameter
-help: consider turning `foo` into a method by giving it a `&self` argument
-   |
-LL |     fn foo(&self);
-   |            +++++
-help: alternatively, consider constraining `foo` so it does not apply to trait objects
-   |
-LL |     fn foo() where Self: Sized;
-   |              +++++++++++++++++
-
 error[E0033]: type `&dyn SomeTrait` cannot be dereferenced
-  --> $DIR/E0033.rs:10:9
+  --> $DIR/E0033.rs:11:9
    |
 LL |     let &invalid = trait_obj;
    |         ^^^^^^^^ type `&dyn SomeTrait` cannot be dereferenced
 
-error: aborting due to 3 previous errors
+error: aborting due to previous error
 
-Some errors have detailed explanations: E0033, E0038, E0423.
-For more information about an error, try `rustc --explain E0033`.
+For more information about this error, try `rustc --explain E0033`.
diff --git a/src/test/ui/error-codes/E0462.rs b/src/test/ui/error-codes/E0462.rs
new file mode 100644
index 00000000000..f839ee783b5
--- /dev/null
+++ b/src/test/ui/error-codes/E0462.rs
@@ -0,0 +1,11 @@
+// aux-build:found-staticlib.rs
+
+// normalize-stderr-test: "\.nll/" -> "/"
+// normalize-stderr-test: "\\\?\\" -> ""
+// normalize-stderr-test: "(lib)?found_staticlib\.[a-z]+" -> "libfound_staticlib.somelib"
+
+extern crate found_staticlib; //~ ERROR E0462
+
+fn main() {
+    found_staticlib::foo();
+}
diff --git a/src/test/ui/error-codes/E0462.stderr b/src/test/ui/error-codes/E0462.stderr
new file mode 100644
index 00000000000..43e27965ffc
--- /dev/null
+++ b/src/test/ui/error-codes/E0462.stderr
@@ -0,0 +1,13 @@
+error[E0462]: found staticlib `found_staticlib` instead of rlib or dylib
+  --> $DIR/E0462.rs:7:1
+   |
+LL | extern crate found_staticlib;
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: the following crate versions were found:
+           crate `found_staticlib`: $TEST_BUILD_DIR/error-codes/E0462/auxiliary/libfound_staticlib.somelib
+   = help: please recompile that crate using --crate-type lib
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0462`.
diff --git a/src/test/ui/error-codes/auxiliary/found-staticlib.rs b/src/test/ui/error-codes/auxiliary/found-staticlib.rs
new file mode 100644
index 00000000000..04e2c59789d
--- /dev/null
+++ b/src/test/ui/error-codes/auxiliary/found-staticlib.rs
@@ -0,0 +1,4 @@
+// no-prefer-dynamic
+#![crate_type = "staticlib"]
+
+pub fn foo() {}
diff --git a/src/test/ui/feature-gates/feature-gate-multiple_supertrait_upcastable.rs b/src/test/ui/feature-gates/feature-gate-multiple_supertrait_upcastable.rs
new file mode 100644
index 00000000000..0467dea621b
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-multiple_supertrait_upcastable.rs
@@ -0,0 +1,12 @@
+// check-pass
+
+#![deny(multiple_supertrait_upcastable)]
+//~^ WARNING unknown lint: `multiple_supertrait_upcastable`
+//~| WARNING unknown lint: `multiple_supertrait_upcastable`
+//~| WARNING unknown lint: `multiple_supertrait_upcastable`
+#![warn(multiple_supertrait_upcastable)]
+//~^ WARNING unknown lint: `multiple_supertrait_upcastable`
+//~| WARNING unknown lint: `multiple_supertrait_upcastable`
+//~| WARNING unknown lint: `multiple_supertrait_upcastable`
+
+fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-multiple_supertrait_upcastable.stderr b/src/test/ui/feature-gates/feature-gate-multiple_supertrait_upcastable.stderr
new file mode 100644
index 00000000000..1f725f35417
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-multiple_supertrait_upcastable.stderr
@@ -0,0 +1,57 @@
+warning: unknown lint: `multiple_supertrait_upcastable`
+  --> $DIR/feature-gate-multiple_supertrait_upcastable.rs:3:1
+   |
+LL | #![deny(multiple_supertrait_upcastable)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: the `multiple_supertrait_upcastable` lint is unstable
+   = help: add `#![feature(multiple_supertrait_upcastable)]` to the crate attributes to enable
+   = note: `#[warn(unknown_lints)]` on by default
+
+warning: unknown lint: `multiple_supertrait_upcastable`
+  --> $DIR/feature-gate-multiple_supertrait_upcastable.rs:7:1
+   |
+LL | #![warn(multiple_supertrait_upcastable)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: the `multiple_supertrait_upcastable` lint is unstable
+   = help: add `#![feature(multiple_supertrait_upcastable)]` to the crate attributes to enable
+
+warning: unknown lint: `multiple_supertrait_upcastable`
+  --> $DIR/feature-gate-multiple_supertrait_upcastable.rs:3:1
+   |
+LL | #![deny(multiple_supertrait_upcastable)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: the `multiple_supertrait_upcastable` lint is unstable
+   = help: add `#![feature(multiple_supertrait_upcastable)]` to the crate attributes to enable
+
+warning: unknown lint: `multiple_supertrait_upcastable`
+  --> $DIR/feature-gate-multiple_supertrait_upcastable.rs:7:1
+   |
+LL | #![warn(multiple_supertrait_upcastable)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: the `multiple_supertrait_upcastable` lint is unstable
+   = help: add `#![feature(multiple_supertrait_upcastable)]` to the crate attributes to enable
+
+warning: unknown lint: `multiple_supertrait_upcastable`
+  --> $DIR/feature-gate-multiple_supertrait_upcastable.rs:3:1
+   |
+LL | #![deny(multiple_supertrait_upcastable)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: the `multiple_supertrait_upcastable` lint is unstable
+   = help: add `#![feature(multiple_supertrait_upcastable)]` to the crate attributes to enable
+
+warning: unknown lint: `multiple_supertrait_upcastable`
+  --> $DIR/feature-gate-multiple_supertrait_upcastable.rs:7:1
+   |
+LL | #![warn(multiple_supertrait_upcastable)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: the `multiple_supertrait_upcastable` lint is unstable
+   = help: add `#![feature(multiple_supertrait_upcastable)]` to the crate attributes to enable
+
+warning: 6 warnings emitted
+
diff --git a/src/test/ui/fmt/issue-103826.rs b/src/test/ui/fmt/issue-103826.rs
new file mode 100644
index 00000000000..a11ec37a06d
--- /dev/null
+++ b/src/test/ui/fmt/issue-103826.rs
@@ -0,0 +1,8 @@
+fn main() {
+    format!("{\x7D");
+    //~^ ERROR 1 positional argument in format string, but no arguments were given
+    format!("\x7B\x7D");
+    //~^ ERROR 1 positional argument in format string, but no arguments were given
+    format!("{\x7D {\x7D");
+    //~^ ERROR 2 positional arguments in format string, but no arguments were given
+}
diff --git a/src/test/ui/fmt/issue-103826.stderr b/src/test/ui/fmt/issue-103826.stderr
new file mode 100644
index 00000000000..0f27e1930bc
--- /dev/null
+++ b/src/test/ui/fmt/issue-103826.stderr
@@ -0,0 +1,20 @@
+error: 1 positional argument in format string, but no arguments were given
+  --> $DIR/issue-103826.rs:2:14
+   |
+LL |     format!("{\x7D");
+   |              ^^^^^
+
+error: 1 positional argument in format string, but no arguments were given
+  --> $DIR/issue-103826.rs:4:14
+   |
+LL |     format!("\x7B\x7D");
+   |              ^^^^^^^^
+
+error: 2 positional arguments in format string, but no arguments were given
+  --> $DIR/issue-103826.rs:6:14
+   |
+LL |     format!("{\x7D {\x7D");
+   |              ^^^^^ ^^^^^
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/issues/issue-3044.rs b/src/test/ui/fn/issue-3044.rs
index 7c626a01b12..7c626a01b12 100644
--- a/src/test/ui/issues/issue-3044.rs
+++ b/src/test/ui/fn/issue-3044.rs
diff --git a/src/test/ui/issues/issue-3044.stderr b/src/test/ui/fn/issue-3044.stderr
index 1232b83c391..1232b83c391 100644
--- a/src/test/ui/issues/issue-3044.stderr
+++ b/src/test/ui/fn/issue-3044.stderr
diff --git a/src/test/ui/issues/issue-3904.rs b/src/test/ui/fn/issue-3904.rs
index 7beb91a28d2..7beb91a28d2 100644
--- a/src/test/ui/issues/issue-3904.rs
+++ b/src/test/ui/fn/issue-3904.rs
diff --git a/src/test/ui/generator/unresolved-ct-var-drop-tracking.rs b/src/test/ui/generator/unresolved-ct-var-drop-tracking.rs
new file mode 100644
index 00000000000..a6589348d30
--- /dev/null
+++ b/src/test/ui/generator/unresolved-ct-var-drop-tracking.rs
@@ -0,0 +1,15 @@
+// incremental
+// edition:2021
+// compile-flags: -Zdrop-tracking
+
+fn main() {
+    let _ = async {
+        let s = std::array::from_fn(|_| ()).await;
+        //~^ ERROR `[(); _]` is not a future
+        //~| ERROR type inside `async` block must be known in this context
+        //~| ERROR type inside `async` block must be known in this context
+        //~| ERROR type inside `async` block must be known in this context
+        //~| ERROR type inside `async` block must be known in this context
+        //~| ERROR type inside `async` block must be known in this context
+    };
+}
diff --git a/src/test/ui/generator/unresolved-ct-var-drop-tracking.stderr b/src/test/ui/generator/unresolved-ct-var-drop-tracking.stderr
new file mode 100644
index 00000000000..9e1fed54c54
--- /dev/null
+++ b/src/test/ui/generator/unresolved-ct-var-drop-tracking.stderr
@@ -0,0 +1,78 @@
+error[E0277]: `[(); _]` is not a future
+  --> $DIR/unresolved-ct-var-drop-tracking.rs:7:44
+   |
+LL |         let s = std::array::from_fn(|_| ()).await;
+   |                 ---------------------------^^^^^^
+   |                 |                          |
+   |                 |                          `[(); _]` is not a future
+   |                 |                          help: remove the `.await`
+   |                 this call returns `[(); _]`
+   |
+   = help: the trait `Future` is not implemented for `[(); _]`
+   = note: [(); _] must be a future or must implement `IntoFuture` to be awaited
+   = note: required for `[(); _]` to implement `IntoFuture`
+
+error[E0698]: type inside `async` block must be known in this context
+  --> $DIR/unresolved-ct-var-drop-tracking.rs:7:17
+   |
+LL |         let s = std::array::from_fn(|_| ()).await;
+   |                 ^^^^^^^^^^^^^^^^^^^ cannot infer the value of const parameter `N` declared on the function `from_fn`
+   |
+note: the type is part of the `async` block because of this `await`
+  --> $DIR/unresolved-ct-var-drop-tracking.rs:7:44
+   |
+LL |         let s = std::array::from_fn(|_| ()).await;
+   |                                            ^^^^^^
+
+error[E0698]: type inside `async` block must be known in this context
+  --> $DIR/unresolved-ct-var-drop-tracking.rs:7:17
+   |
+LL |         let s = std::array::from_fn(|_| ()).await;
+   |                 ^^^^^^^^^^^^^^^^^^^ cannot infer the value of const parameter `N` declared on the function `from_fn`
+   |
+note: the type is part of the `async` block because of this `await`
+  --> $DIR/unresolved-ct-var-drop-tracking.rs:7:44
+   |
+LL |         let s = std::array::from_fn(|_| ()).await;
+   |                                            ^^^^^^
+
+error[E0698]: type inside `async` block must be known in this context
+  --> $DIR/unresolved-ct-var-drop-tracking.rs:7:17
+   |
+LL |         let s = std::array::from_fn(|_| ()).await;
+   |                 ^^^^^^^^^^^^^^^^^^^ cannot infer the value of const parameter `N` declared on the function `from_fn`
+   |
+note: the type is part of the `async` block because of this `await`
+  --> $DIR/unresolved-ct-var-drop-tracking.rs:7:44
+   |
+LL |         let s = std::array::from_fn(|_| ()).await;
+   |                                            ^^^^^^
+
+error[E0698]: type inside `async` block must be known in this context
+  --> $DIR/unresolved-ct-var-drop-tracking.rs:7:17
+   |
+LL |         let s = std::array::from_fn(|_| ()).await;
+   |                 ^^^^^^^^^^^^^^^^^^^ cannot infer the value of const parameter `N` declared on the function `from_fn`
+   |
+note: the type is part of the `async` block because of this `await`
+  --> $DIR/unresolved-ct-var-drop-tracking.rs:7:44
+   |
+LL |         let s = std::array::from_fn(|_| ()).await;
+   |                                            ^^^^^^
+
+error[E0698]: type inside `async` block must be known in this context
+  --> $DIR/unresolved-ct-var-drop-tracking.rs:7:17
+   |
+LL |         let s = std::array::from_fn(|_| ()).await;
+   |                 ^^^^^^^^^^^^^^^^^^^ cannot infer the value of const parameter `N` declared on the function `from_fn`
+   |
+note: the type is part of the `async` block because of this `await`
+  --> $DIR/unresolved-ct-var-drop-tracking.rs:7:44
+   |
+LL |         let s = std::array::from_fn(|_| ()).await;
+   |                                            ^^^^^^
+
+error: aborting due to 6 previous errors
+
+Some errors have detailed explanations: E0277, E0698.
+For more information about an error, try `rustc --explain E0277`.
diff --git a/src/test/ui/generic-associated-types/impl_bounds.rs b/src/test/ui/generic-associated-types/impl_bounds.rs
index 01165fcebaf..e45bdcf9213 100644
--- a/src/test/ui/generic-associated-types/impl_bounds.rs
+++ b/src/test/ui/generic-associated-types/impl_bounds.rs
@@ -15,7 +15,6 @@ impl<T> Foo for Fooy<T> {
     //~^ ERROR impl has stricter requirements than trait
     type B<'a, 'b> = (&'a(), &'b ()) where 'b: 'a;
     //~^ ERROR impl has stricter requirements than trait
-    //~| ERROR lifetime bound not satisfied
     type C = String where Self: Copy;
     //~^ ERROR the trait bound `T: Copy` is not satisfied
     fn d() where Self: Copy {}
diff --git a/src/test/ui/generic-associated-types/impl_bounds.stderr b/src/test/ui/generic-associated-types/impl_bounds.stderr
index 442d4f33690..3acd85c8ac6 100644
--- a/src/test/ui/generic-associated-types/impl_bounds.stderr
+++ b/src/test/ui/generic-associated-types/impl_bounds.stderr
@@ -16,28 +16,8 @@ LL |     type B<'a, 'b> where 'a: 'b;
 LL |     type B<'a, 'b> = (&'a(), &'b ()) where 'b: 'a;
    |                                                ^^ impl has extra requirement `'b: 'a`
 
-error[E0478]: lifetime bound not satisfied
-  --> $DIR/impl_bounds.rs:16:22
-   |
-LL |     type B<'a, 'b> where 'a: 'b;
-   |     -------------- definition of `B` from trait
-...
-LL |     type B<'a, 'b> = (&'a(), &'b ()) where 'b: 'a;
-   |                      ^^^^^^^^^^^^^^^             - help: try copying this clause from the trait: `, 'a: 'b`
-   |
-note: lifetime parameter instantiated with the lifetime `'a` as defined here
-  --> $DIR/impl_bounds.rs:16:12
-   |
-LL |     type B<'a, 'b> = (&'a(), &'b ()) where 'b: 'a;
-   |            ^^
-note: but lifetime parameter must outlive the lifetime `'b` as defined here
-  --> $DIR/impl_bounds.rs:16:16
-   |
-LL |     type B<'a, 'b> = (&'a(), &'b ()) where 'b: 'a;
-   |                ^^
-
 error[E0277]: the trait bound `T: Copy` is not satisfied
-  --> $DIR/impl_bounds.rs:19:33
+  --> $DIR/impl_bounds.rs:18:33
    |
 LL |     type C = String where Self: Copy;
    |                                 ^^^^ the trait `Copy` is not implemented for `T`
@@ -62,7 +42,7 @@ LL | impl<T: std::marker::Copy> Foo for Fooy<T> {
    |       +++++++++++++++++++
 
 error[E0277]: the trait bound `T: Copy` is not satisfied
-  --> $DIR/impl_bounds.rs:21:24
+  --> $DIR/impl_bounds.rs:20:24
    |
 LL |     fn d() where Self: Copy {}
    |                        ^^^^ the trait `Copy` is not implemented for `T`
@@ -86,7 +66,7 @@ help: consider restricting type parameter `T`
 LL | impl<T: std::marker::Copy> Foo for Fooy<T> {
    |       +++++++++++++++++++
 
-error: aborting due to 5 previous errors
+error: aborting due to 4 previous errors
 
-Some errors have detailed explanations: E0276, E0277, E0478.
+Some errors have detailed explanations: E0276, E0277.
 For more information about an error, try `rustc --explain E0276`.
diff --git a/src/test/ui/imports/local-modularized-tricky-fail-1.rs b/src/test/ui/imports/local-modularized-tricky-fail-1.rs
index 37fe0eceed6..29e9b8ec841 100644
--- a/src/test/ui/imports/local-modularized-tricky-fail-1.rs
+++ b/src/test/ui/imports/local-modularized-tricky-fail-1.rs
@@ -26,7 +26,6 @@ mod inner1 {
 }
 
 exported!(); //~ ERROR `exported` is ambiguous
-             //~| ERROR `exported` is ambiguous
 
 mod inner2 {
     define_exported!();
diff --git a/src/test/ui/imports/local-modularized-tricky-fail-1.stderr b/src/test/ui/imports/local-modularized-tricky-fail-1.stderr
index c048d2ea204..20eadaaaa56 100644
--- a/src/test/ui/imports/local-modularized-tricky-fail-1.stderr
+++ b/src/test/ui/imports/local-modularized-tricky-fail-1.stderr
@@ -23,33 +23,8 @@ LL | use inner1::*;
    = help: consider adding an explicit import of `exported` to disambiguate
    = note: this error originates in the macro `define_exported` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error[E0659]: `exported` is ambiguous
-  --> $DIR/local-modularized-tricky-fail-1.rs:28:1
-   |
-LL | exported!();
-   | ^^^^^^^^ ambiguous name
-   |
-   = note: ambiguous because of a conflict between a name from a glob import and a macro-expanded name in the same module during import or macro resolution
-note: `exported` could refer to the macro defined here
-  --> $DIR/local-modularized-tricky-fail-1.rs:5:5
-   |
-LL | /     macro_rules! exported {
-LL | |         () => ()
-LL | |     }
-   | |_____^
-...
-LL |       define_exported!();
-   |       ------------------ in this macro invocation
-note: `exported` could also refer to the macro imported here
-  --> $DIR/local-modularized-tricky-fail-1.rs:22:5
-   |
-LL | use inner1::*;
-   |     ^^^^^^^^^
-   = help: consider adding an explicit import of `exported` to disambiguate
-   = note: this error originates in the macro `define_exported` (in Nightly builds, run with -Z macro-backtrace for more info)
-
 error[E0659]: `panic` is ambiguous
-  --> $DIR/local-modularized-tricky-fail-1.rs:36:5
+  --> $DIR/local-modularized-tricky-fail-1.rs:35:5
    |
 LL |     panic!();
    |     ^^^^^ ambiguous name
@@ -70,7 +45,7 @@ LL |       define_panic!();
    = note: this error originates in the macro `define_panic` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0659]: `include` is ambiguous
-  --> $DIR/local-modularized-tricky-fail-1.rs:47:1
+  --> $DIR/local-modularized-tricky-fail-1.rs:46:1
    |
 LL | include!();
    | ^^^^^^^ ambiguous name
@@ -90,6 +65,6 @@ LL |       define_include!();
    = help: use `crate::include` to refer to this macro unambiguously
    = note: this error originates in the macro `define_include` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error: aborting due to 4 previous errors
+error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0659`.
diff --git a/src/test/ui/imports/macros.rs b/src/test/ui/imports/macros.rs
index f39711898cd..f2a22ad620b 100644
--- a/src/test/ui/imports/macros.rs
+++ b/src/test/ui/imports/macros.rs
@@ -14,7 +14,6 @@ mod m1 {
 mod m2 {
     use two_macros::*;
     m! { //~ ERROR ambiguous
-         //~| ERROR ambiguous
         use foo::m;
     }
 }
diff --git a/src/test/ui/imports/macros.stderr b/src/test/ui/imports/macros.stderr
index 110548d1d6a..e34e5359b48 100644
--- a/src/test/ui/imports/macros.stderr
+++ b/src/test/ui/imports/macros.stderr
@@ -6,7 +6,7 @@ LL |     m! {
    |
    = note: ambiguous because of a conflict between a name from a glob import and a macro-expanded name in the same module during import or macro resolution
 note: `m` could refer to the macro imported here
-  --> $DIR/macros.rs:18:13
+  --> $DIR/macros.rs:17:13
    |
 LL |         use foo::m;
    |             ^^^^^^
@@ -18,43 +18,24 @@ LL |     use two_macros::*;
    = help: consider adding an explicit import of `m` to disambiguate
 
 error[E0659]: `m` is ambiguous
-  --> $DIR/macros.rs:16:5
-   |
-LL |     m! {
-   |     ^ ambiguous name
-   |
-   = note: ambiguous because of a conflict between a name from a glob import and a macro-expanded name in the same module during import or macro resolution
-note: `m` could refer to the macro imported here
-  --> $DIR/macros.rs:18:13
-   |
-LL |         use foo::m;
-   |             ^^^^^^
-note: `m` could also refer to the macro imported here
-  --> $DIR/macros.rs:15:9
-   |
-LL |     use two_macros::*;
-   |         ^^^^^^^^^^^^^
-   = help: consider adding an explicit import of `m` to disambiguate
-
-error[E0659]: `m` is ambiguous
-  --> $DIR/macros.rs:30:9
+  --> $DIR/macros.rs:29:9
    |
 LL |         m! {
    |         ^ ambiguous name
    |
    = note: ambiguous because of a conflict between a macro-expanded name and a less macro-expanded name from outer scope during import or macro resolution
 note: `m` could refer to the macro imported here
-  --> $DIR/macros.rs:31:17
+  --> $DIR/macros.rs:30:17
    |
 LL |             use two_macros::n as m;
    |                 ^^^^^^^^^^^^^^^^^^
 note: `m` could also refer to the macro imported here
-  --> $DIR/macros.rs:23:9
+  --> $DIR/macros.rs:22:9
    |
 LL |     use two_macros::m;
    |         ^^^^^^^^^^^^^
    = help: use `self::m` to refer to this macro unambiguously
 
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0659`.
diff --git a/src/test/ui/intrinsics/panic-uninitialized-zeroed.rs b/src/test/ui/intrinsics/panic-uninitialized-zeroed.rs
index ec3860a322f..1a0104b859e 100644
--- a/src/test/ui/intrinsics/panic-uninitialized-zeroed.rs
+++ b/src/test/ui/intrinsics/panic-uninitialized-zeroed.rs
@@ -1,9 +1,9 @@
 // run-pass
-// needs-unwind
-// revisions: mir thir strict
-// [thir]compile-flags: -Zthir-unsafeck
+// revisions: default strict
 // [strict]compile-flags: -Zstrict-init-checks
 // ignore-tidy-linelength
+// ignore-emscripten spawning processes is not supported
+// ignore-sgx no processes
 
 // This test checks panic emitted from `mem::{uninitialized,zeroed}`.
 
@@ -12,7 +12,6 @@
 
 use std::{
     mem::{self, MaybeUninit, ManuallyDrop},
-    panic,
     ptr::NonNull,
     num,
 };
@@ -70,21 +69,42 @@ enum ZeroIsValid {
 }
 
 #[track_caller]
-fn test_panic_msg<T>(op: impl (FnOnce() -> T) + panic::UnwindSafe, msg: &str) {
-    let err = panic::catch_unwind(op).err();
-    assert_eq!(
-        err.as_ref().and_then(|a| a.downcast_ref::<&str>()),
-        Some(&msg)
-    );
+fn test_panic_msg<T, F: (FnOnce() -> T) + 'static>(op: F, msg: &str) {
+    use std::{panic, env, process};
+
+    // The tricky part is that we can't just run `op`, as that would *abort* the process.
+    // So instead, we reinvoke this process with the caller location as argument.
+    // For the purpose of this test, the line number is unique enough.
+    // If we are running in such a re-invocation, we skip all the tests *except* for the one with that type name.
+    let our_loc = panic::Location::caller().line().to_string();
+    let mut args = env::args();
+    let this = args.next().unwrap();
+    if let Some(loc) = args.next() {
+        if loc == our_loc {
+            op();
+            panic!("we did not abort");
+        } else {
+            // Nothing, we are running another test.
+        }
+    } else {
+        // Invoke new process for actual test, and check result.
+        let mut cmd = process::Command::new(this);
+        cmd.arg(our_loc);
+        let res = cmd.output().unwrap();
+        assert!(!res.status.success(), "test did not fail");
+        let stderr = String::from_utf8_lossy(&res.stderr);
+        assert!(stderr.contains(msg), "test did not contain expected output: looking for {:?}, output:\n{}", msg, stderr);
+    }
 }
 
 #[track_caller]
-fn test_panic_msg_only_if_strict<T>(op: impl (FnOnce() -> T) + panic::UnwindSafe, msg: &str) {
-    let err = panic::catch_unwind(op).err();
-    assert_eq!(
-        err.as_ref().and_then(|a| a.downcast_ref::<&str>()),
-        if cfg!(strict) { Some(&msg) } else { None },
-    );
+fn test_panic_msg_only_if_strict<T>(op: impl (FnOnce() -> T) + 'static, msg: &str) {
+    if !cfg!(strict) {
+        // Just run it.
+        op();
+    } else {
+        test_panic_msg(op, msg);
+    }
 }
 
 fn main() {
diff --git a/src/test/ui/issues/issue-6470.rs b/src/test/ui/issues/issue-6470.rs
deleted file mode 100644
index 8c6192a59db..00000000000
--- a/src/test/ui/issues/issue-6470.rs
+++ /dev/null
@@ -1,17 +0,0 @@
-// build-pass
-#![allow(dead_code)]
-#![allow(improper_ctypes)]
-// pretty-expanded FIXME #23616
-#![allow(non_snake_case)]
-
-pub mod Bar {
-    pub struct Foo {
-        v: isize,
-    }
-
-    extern "C" {
-        pub fn foo(v: *const Foo) -> Foo;
-    }
-}
-
-pub fn main() {}
diff --git a/src/test/ui/iterators/invalid-iterator-chain.stderr b/src/test/ui/iterators/invalid-iterator-chain.stderr
index d76a4bfb7b3..f3dceca7e41 100644
--- a/src/test/ui/iterators/invalid-iterator-chain.stderr
+++ b/src/test/ui/iterators/invalid-iterator-chain.stderr
@@ -52,14 +52,14 @@ LL |             .sum::<i32>(),
              <i32 as Sum<&'a i32>>
              <i32 as Sum>
 note: the method call chain might not have had the expected associated types
-  --> $DIR/invalid-iterator-chain.rs:20:14
+  --> $DIR/invalid-iterator-chain.rs:25:14
    |
 LL |         vec![0, 1]
    |         ---------- this expression has type `Vec<{integer}>`
 LL |             .iter()
    |              ------ `Iterator::Item` is `&{integer}` here
 LL |             .map(|x| x * 2)
-   |              ^^^^^^^^^^^^^^ `Iterator::Item` changed to `{integer}` here
+   |              -------------- `Iterator::Item` changed to `{integer}` here
 LL |             .map(|x| x as f64)
    |              ----------------- `Iterator::Item` changed to `f64` here
 LL |             .map(|x| x as i64)
@@ -84,14 +84,14 @@ LL |             .sum::<i32>(),
              <i32 as Sum<&'a i32>>
              <i32 as Sum>
 note: the method call chain might not have had the expected associated types
-  --> $DIR/invalid-iterator-chain.rs:32:14
+  --> $DIR/invalid-iterator-chain.rs:33:14
    |
 LL |         vec![0, 1]
    |         ---------- this expression has type `Vec<{integer}>`
 LL |             .iter()
    |              ------ `Iterator::Item` is `&{integer}` here
 LL |             .map(|x| x * 2)
-   |              ^^^^^^^^^^^^^^ `Iterator::Item` changed to `{integer}` here
+   |              -------------- `Iterator::Item` changed to `{integer}` here
 LL |             .map(|x| x as f64)
    |              ^^^^^^^^^^^^^^^^^ `Iterator::Item` changed to `f64` here
 LL |             .filter(|x| *x > 0.0)
diff --git a/src/test/ui/issues/issue-36381.rs b/src/test/ui/late-bound-lifetimes/issue-36381.rs
index 7db56f1dce8..7db56f1dce8 100644
--- a/src/test/ui/issues/issue-36381.rs
+++ b/src/test/ui/late-bound-lifetimes/issue-36381.rs
diff --git a/src/test/ui/lexer/lex-bad-char-literals-6.rs b/src/test/ui/lexer/lex-bad-char-literals-6.rs
index 4379b4fa6d7..1b498c0fbca 100644
--- a/src/test/ui/lexer/lex-bad-char-literals-6.rs
+++ b/src/test/ui/lexer/lex-bad-char-literals-6.rs
@@ -7,10 +7,8 @@ fn main() {
     //~^ ERROR: character literal may only contain one codepoint
 
     if x == y {}
-    //~^ ERROR: can't compare `&str` with `char`
     if y == z {}  // no error here
     if x == z {}
-    //~^ ERROR: can't compare `&str` with `char`
 
     let a: usize = "";
     //~^ ERROR: mismatched types
diff --git a/src/test/ui/lexer/lex-bad-char-literals-6.stderr b/src/test/ui/lexer/lex-bad-char-literals-6.stderr
index ce41942467c..2fe30304a50 100644
--- a/src/test/ui/lexer/lex-bad-char-literals-6.stderr
+++ b/src/test/ui/lexer/lex-bad-char-literals-6.stderr
@@ -31,49 +31,14 @@ help: if you meant to write a `str` literal, use double quotes
 LL |     let z = "ef";
    |             ~~~~
 
-error[E0277]: can't compare `&str` with `char`
-  --> $DIR/lex-bad-char-literals-6.rs:9:10
-   |
-LL |     if x == y {}
-   |          ^^ no implementation for `&str == char`
-   |
-   = help: the trait `PartialEq<char>` is not implemented for `&str`
-   = help: the following other types implement trait `PartialEq<Rhs>`:
-             <&'a str as PartialEq<OsString>>
-             <&'a str as PartialEq<String>>
-             <&'b str as PartialEq<Cow<'a, str>>>
-             <str as PartialEq<Cow<'a, str>>>
-             <str as PartialEq<OsStr>>
-             <str as PartialEq<OsString>>
-             <str as PartialEq<String>>
-             <str as PartialEq>
-
 error[E0308]: mismatched types
-  --> $DIR/lex-bad-char-literals-6.rs:15:20
+  --> $DIR/lex-bad-char-literals-6.rs:13:20
    |
 LL |     let a: usize = "";
    |            -----   ^^ expected `usize`, found `&str`
    |            |
    |            expected due to this
 
-error[E0277]: can't compare `&str` with `char`
-  --> $DIR/lex-bad-char-literals-6.rs:12:10
-   |
-LL |     if x == z {}
-   |          ^^ no implementation for `&str == char`
-   |
-   = help: the trait `PartialEq<char>` is not implemented for `&str`
-   = help: the following other types implement trait `PartialEq<Rhs>`:
-             <&'a str as PartialEq<OsString>>
-             <&'a str as PartialEq<String>>
-             <&'b str as PartialEq<Cow<'a, str>>>
-             <str as PartialEq<Cow<'a, str>>>
-             <str as PartialEq<OsStr>>
-             <str as PartialEq<OsString>>
-             <str as PartialEq<String>>
-             <str as PartialEq>
-
-error: aborting due to 6 previous errors
+error: aborting due to 4 previous errors
 
-Some errors have detailed explanations: E0277, E0308.
-For more information about an error, try `rustc --explain E0277`.
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/lint/must_not_suspend/tuple-mismatch.rs b/src/test/ui/lint/must_not_suspend/tuple-mismatch.rs
new file mode 100644
index 00000000000..c7e14e42561
--- /dev/null
+++ b/src/test/ui/lint/must_not_suspend/tuple-mismatch.rs
@@ -0,0 +1,9 @@
+#![feature(generators)]
+
+fn main() {
+    let _generator = || {
+        yield ((), ((), ()));
+        yield ((), ());
+        //~^ ERROR mismatched types
+    };
+}
diff --git a/src/test/ui/lint/must_not_suspend/tuple-mismatch.stderr b/src/test/ui/lint/must_not_suspend/tuple-mismatch.stderr
new file mode 100644
index 00000000000..cca8cd9bd89
--- /dev/null
+++ b/src/test/ui/lint/must_not_suspend/tuple-mismatch.stderr
@@ -0,0 +1,12 @@
+error[E0308]: mismatched types
+  --> $DIR/tuple-mismatch.rs:6:20
+   |
+LL |         yield ((), ());
+   |                    ^^ expected tuple, found `()`
+   |
+   = note:  expected tuple `((), ())`
+           found unit type `()`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/lint/unused/must-use-box-from-raw.stderr b/src/test/ui/lint/unused/must-use-box-from-raw.stderr
index 72118275774..47ab613bec2 100644
--- a/src/test/ui/lint/unused/must-use-box-from-raw.stderr
+++ b/src/test/ui/lint/unused/must-use-box-from-raw.stderr
@@ -4,7 +4,7 @@ warning: unused return value of `Box::<T>::from_raw` that must be used
 LL |     Box::from_raw(ptr);
    |     ^^^^^^^^^^^^^^^^^^
    |
-   = note: call `drop(from_raw(ptr))` if you intend to drop the `Box`
+   = note: call `drop(Box::from_raw(ptr))` if you intend to drop the `Box`
 note: the lint level is defined here
   --> $DIR/must-use-box-from-raw.rs:5:9
    |
diff --git a/src/test/ui/lint/unused_braces_macro.rs b/src/test/ui/lint/unused_braces_macro.rs
new file mode 100644
index 00000000000..bfee95378bf
--- /dev/null
+++ b/src/test/ui/lint/unused_braces_macro.rs
@@ -0,0 +1,6 @@
+// build-pass
+pub fn foo<const BAR: bool> () {}
+
+fn main() {
+    foo::<{cfg!(feature = "foo")}>();
+}
diff --git a/src/test/ui/macros/best-failure.rs b/src/test/ui/macros/best-failure.rs
new file mode 100644
index 00000000000..bbdd465d5ec
--- /dev/null
+++ b/src/test/ui/macros/best-failure.rs
@@ -0,0 +1,11 @@
+macro_rules! number {
+    (neg false, $self:ident) => { $self };
+    ($signed:tt => $ty:ty;) => {
+        number!(neg $signed, $self);
+        //~^ ERROR no rules expected the token `$`
+    };
+}
+
+number! { false => u8; }
+
+fn main() {}
diff --git a/src/test/ui/macros/best-failure.stderr b/src/test/ui/macros/best-failure.stderr
new file mode 100644
index 00000000000..a52fc5e3da6
--- /dev/null
+++ b/src/test/ui/macros/best-failure.stderr
@@ -0,0 +1,21 @@
+error: no rules expected the token `$`
+  --> $DIR/best-failure.rs:4:30
+   |
+LL | macro_rules! number {
+   | ------------------- when calling this macro
+...
+LL |         number!(neg $signed, $self);
+   |                              ^^^^^ no rules expected this token in macro call
+...
+LL | number! { false => u8; }
+   | ------------------------ in this macro invocation
+   |
+note: while trying to match meta-variable `$self:ident`
+  --> $DIR/best-failure.rs:2:17
+   |
+LL |     (neg false, $self:ident) => { $self };
+   |                 ^^^^^^^^^^^
+   = note: this error originates in the macro `number` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/issues/issue-25385.rs b/src/test/ui/macros/issue-25385.rs
index ea042a6c76b..ea042a6c76b 100644
--- a/src/test/ui/issues/issue-25385.rs
+++ b/src/test/ui/macros/issue-25385.rs
diff --git a/src/test/ui/issues/issue-25385.stderr b/src/test/ui/macros/issue-25385.stderr
index 39dbdd753a6..39dbdd753a6 100644
--- a/src/test/ui/issues/issue-25385.stderr
+++ b/src/test/ui/macros/issue-25385.stderr
diff --git a/src/test/ui/issues/issue-5530.rs b/src/test/ui/match/issue-5530.rs
index 72731cbb177..72731cbb177 100644
--- a/src/test/ui/issues/issue-5530.rs
+++ b/src/test/ui/match/issue-5530.rs
diff --git a/src/test/ui/match/single-line.rs b/src/test/ui/match/single-line.rs
new file mode 100644
index 00000000000..0f69d089f9a
--- /dev/null
+++ b/src/test/ui/match/single-line.rs
@@ -0,0 +1,3 @@
+fn main() {
+    let _ = match Some(42) { Some(x) => x, None => "" }; //~ ERROR E0308
+}
diff --git a/src/test/ui/match/single-line.stderr b/src/test/ui/match/single-line.stderr
new file mode 100644
index 00000000000..ec3b76e3f4d
--- /dev/null
+++ b/src/test/ui/match/single-line.stderr
@@ -0,0 +1,12 @@
+error[E0308]: `match` arms have incompatible types
+  --> $DIR/single-line.rs:2:52
+   |
+LL |     let _ = match Some(42) { Some(x) => x, None => "" };
+   |             --------------              -          ^^ expected integer, found `&str`
+   |             |                           |
+   |             |                           this is found to be of type `{integer}`
+   |             `match` arms have incompatible types
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/methods/issues/issue-105732.rs b/src/test/ui/methods/issues/issue-105732.rs
index 98b7a8d0d04..d7005065813 100644
--- a/src/test/ui/methods/issues/issue-105732.rs
+++ b/src/test/ui/methods/issues/issue-105732.rs
@@ -6,7 +6,8 @@ auto trait Foo {
 
 trait Bar {
     fn f(&self) {
-        self.g(); //~ ERROR the method `g` exists for reference `&Self`, but its trait bounds were not satisfied
+        // issue #105788
+        self.g(); //~ ERROR no method named `g` found for reference `&Self` in the current scope
     }
 }
 
diff --git a/src/test/ui/methods/issues/issue-105732.stderr b/src/test/ui/methods/issues/issue-105732.stderr
index fb2bdf47de7..7696642548d 100644
--- a/src/test/ui/methods/issues/issue-105732.stderr
+++ b/src/test/ui/methods/issues/issue-105732.stderr
@@ -6,21 +6,11 @@ LL | auto trait Foo {
 LL |     fn g(&self);
    |     ---^-------- help: remove these associated items
 
-error[E0599]: the method `g` exists for reference `&Self`, but its trait bounds were not satisfied
-  --> $DIR/issue-105732.rs:9:14
+error[E0599]: no method named `g` found for reference `&Self` in the current scope
+  --> $DIR/issue-105732.rs:10:14
    |
 LL |         self.g();
-   |              ^
-   |
-   = note: the following trait bounds were not satisfied:
-           `Self: Foo`
-           which is required by `&Self: Foo`
-           `&Self: Foo`
-   = help: items from traits can only be used if the type parameter is bounded by the trait
-help: the following trait defines an item `g`, perhaps you need to add a supertrait for it:
-   |
-LL | trait Bar: Foo {
-   |          +++++
+   |              ^ help: there is a method with a similar name: `f`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/mismatched_types/suggest-removing-tulpe-struct-field.fixed b/src/test/ui/mismatched_types/suggest-removing-tuple-struct-field.fixed
index 63b65ab20fe..63b65ab20fe 100644
--- a/src/test/ui/mismatched_types/suggest-removing-tulpe-struct-field.fixed
+++ b/src/test/ui/mismatched_types/suggest-removing-tuple-struct-field.fixed
diff --git a/src/test/ui/mismatched_types/suggest-removing-tulpe-struct-field.rs b/src/test/ui/mismatched_types/suggest-removing-tuple-struct-field.rs
index 2ab4e3955f3..2ab4e3955f3 100644
--- a/src/test/ui/mismatched_types/suggest-removing-tulpe-struct-field.rs
+++ b/src/test/ui/mismatched_types/suggest-removing-tuple-struct-field.rs
diff --git a/src/test/ui/mismatched_types/suggest-removing-tulpe-struct-field.stderr b/src/test/ui/mismatched_types/suggest-removing-tuple-struct-field.stderr
index 82a7f276372..35871afb58b 100644
--- a/src/test/ui/mismatched_types/suggest-removing-tulpe-struct-field.stderr
+++ b/src/test/ui/mismatched_types/suggest-removing-tuple-struct-field.stderr
@@ -1,5 +1,5 @@
 error[E0308]: mismatched types
-  --> $DIR/suggest-removing-tulpe-struct-field.rs:11:13
+  --> $DIR/suggest-removing-tuple-struct-field.rs:11:13
    |
 LL |     some_fn(value.0);
    |     ------- ^^^^^^^ expected struct `MyWrapper`, found `u32`
@@ -7,7 +7,7 @@ LL |     some_fn(value.0);
    |     arguments to this function are incorrect
    |
 note: function defined here
-  --> $DIR/suggest-removing-tulpe-struct-field.rs:15:4
+  --> $DIR/suggest-removing-tuple-struct-field.rs:15:4
    |
 LL | fn some_fn(wrapped: MyWrapper) {
    |    ^^^^^^^ ------------------
@@ -18,7 +18,7 @@ LL +     some_fn(value);
    |
 
 error[E0308]: mismatched types
-  --> $DIR/suggest-removing-tulpe-struct-field.rs:12:13
+  --> $DIR/suggest-removing-tuple-struct-field.rs:12:13
    |
 LL |     some_fn(my_wrapper!(123).0);
    |     ------- ^^^^^^^^^^^^^^^^^^ expected struct `MyWrapper`, found `u32`
@@ -26,7 +26,7 @@ LL |     some_fn(my_wrapper!(123).0);
    |     arguments to this function are incorrect
    |
 note: function defined here
-  --> $DIR/suggest-removing-tulpe-struct-field.rs:15:4
+  --> $DIR/suggest-removing-tuple-struct-field.rs:15:4
    |
 LL | fn some_fn(wrapped: MyWrapper) {
    |    ^^^^^^^ ------------------
diff --git a/src/test/ui/moves/move-fn-self-receiver.stderr b/src/test/ui/moves/move-fn-self-receiver.stderr
index b3f95ee192a..7f69e5dcfb7 100644
--- a/src/test/ui/moves/move-fn-self-receiver.stderr
+++ b/src/test/ui/moves/move-fn-self-receiver.stderr
@@ -9,6 +9,10 @@ LL |     val.0;
 note: `into_iter` takes ownership of the receiver `self`, which moves `val.0`
   --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
    = note: move occurs because `val.0` has type `Vec<bool>`, which does not implement the `Copy` trait
+help: you can `clone` the value and consume it, but this might not be your desired behavior
+   |
+LL |     val.0.clone().into_iter().next();
+   |           ++++++++
 
 error[E0382]: use of moved value: `foo`
   --> $DIR/move-fn-self-receiver.rs:34:5
@@ -93,10 +97,10 @@ note: `Foo::use_rc_self` takes ownership of the receiver `self`, which moves `rc
    |
 LL |     fn use_rc_self(self: Rc<Self>) {}
    |                    ^^^^
-help: consider cloning the value if the performance cost is acceptable
+help: you can `clone` the value and consume it, but this might not be your desired behavior
    |
 LL |     rc_foo.clone().use_rc_self();
-   |           ++++++++
+   |            ++++++++
 
 error[E0382]: use of moved value: `foo_add`
   --> $DIR/move-fn-self-receiver.rs:59:5
@@ -136,10 +140,10 @@ LL |     for _val in explicit_into_iter.into_iter() {}
 LL |     explicit_into_iter;
    |     ^^^^^^^^^^^^^^^^^^ value used here after move
    |
-help: consider cloning the value if the performance cost is acceptable
+help: you can `clone` the value and consume it, but this might not be your desired behavior
    |
 LL |     for _val in explicit_into_iter.clone().into_iter() {}
-   |                                   ++++++++
+   |                                    ++++++++
 
 error[E0382]: use of moved value: `container`
   --> $DIR/move-fn-self-receiver.rs:71:5
diff --git a/src/test/ui/moves/moves-based-on-type-access-to-field.stderr b/src/test/ui/moves/moves-based-on-type-access-to-field.stderr
index 0b1a623a013..a28f324aafa 100644
--- a/src/test/ui/moves/moves-based-on-type-access-to-field.stderr
+++ b/src/test/ui/moves/moves-based-on-type-access-to-field.stderr
@@ -10,10 +10,10 @@ LL |     touch(&x[0]);
    |
 note: `into_iter` takes ownership of the receiver `self`, which moves `x`
   --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
-help: consider cloning the value if the performance cost is acceptable
+help: you can `clone` the value and consume it, but this might not be your desired behavior
    |
 LL |     consume(x.clone().into_iter().next().unwrap());
-   |              ++++++++
+   |               ++++++++
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/moves/moves-based-on-type-exprs.stderr b/src/test/ui/moves/moves-based-on-type-exprs.stderr
index ae76889f104..ab7c2745688 100644
--- a/src/test/ui/moves/moves-based-on-type-exprs.stderr
+++ b/src/test/ui/moves/moves-based-on-type-exprs.stderr
@@ -162,10 +162,10 @@ LL |     touch(&x);
    |
 note: `into_iter` takes ownership of the receiver `self`, which moves `x`
   --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
-help: consider cloning the value if the performance cost is acceptable
+help: you can `clone` the value and consume it, but this might not be your desired behavior
    |
 LL |     let _y = x.clone().into_iter().next().unwrap();
-   |               ++++++++
+   |                ++++++++
 
 error[E0382]: borrow of moved value: `x`
   --> $DIR/moves-based-on-type-exprs.rs:83:11
@@ -179,10 +179,10 @@ LL |     touch(&x);
    |
 note: `into_iter` takes ownership of the receiver `self`, which moves `x`
   --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
-help: consider cloning the value if the performance cost is acceptable
+help: you can `clone` the value and consume it, but this might not be your desired behavior
    |
 LL |     let _y = [x.clone().into_iter().next().unwrap(); 1];
-   |                ++++++++
+   |                 ++++++++
 
 error: aborting due to 11 previous errors
 
diff --git a/src/test/ui/moves/pin-mut-reborrow.fixed b/src/test/ui/moves/pin-mut-reborrow.fixed
new file mode 100644
index 00000000000..e808186d7d4
--- /dev/null
+++ b/src/test/ui/moves/pin-mut-reborrow.fixed
@@ -0,0 +1,15 @@
+// run-rustfix
+use std::pin::Pin;
+
+struct Foo;
+
+impl Foo {
+    fn foo(self: Pin<&mut Self>) {}
+}
+
+fn main() {
+    let mut foo = Foo;
+    let mut foo = Pin::new(&mut foo);
+    foo.as_mut().foo();
+    foo.foo(); //~ ERROR use of moved value
+}
diff --git a/src/test/ui/moves/pin-mut-reborrow.rs b/src/test/ui/moves/pin-mut-reborrow.rs
new file mode 100644
index 00000000000..fee6236ebb4
--- /dev/null
+++ b/src/test/ui/moves/pin-mut-reborrow.rs
@@ -0,0 +1,15 @@
+// run-rustfix
+use std::pin::Pin;
+
+struct Foo;
+
+impl Foo {
+    fn foo(self: Pin<&mut Self>) {}
+}
+
+fn main() {
+    let mut foo = Foo;
+    let mut foo = Pin::new(&mut foo);
+    foo.foo();
+    foo.foo(); //~ ERROR use of moved value
+}
diff --git a/src/test/ui/moves/pin-mut-reborrow.stderr b/src/test/ui/moves/pin-mut-reborrow.stderr
new file mode 100644
index 00000000000..16fa4bacc2d
--- /dev/null
+++ b/src/test/ui/moves/pin-mut-reborrow.stderr
@@ -0,0 +1,23 @@
+error[E0382]: use of moved value: `foo`
+  --> $DIR/pin-mut-reborrow.rs:14:5
+   |
+LL |     let mut foo = Pin::new(&mut foo);
+   |         ------- move occurs because `foo` has type `Pin<&mut Foo>`, which does not implement the `Copy` trait
+LL |     foo.foo();
+   |         ----- `foo` moved due to this method call
+LL |     foo.foo();
+   |     ^^^ value used here after move
+   |
+note: `Foo::foo` takes ownership of the receiver `self`, which moves `foo`
+  --> $DIR/pin-mut-reborrow.rs:7:12
+   |
+LL |     fn foo(self: Pin<&mut Self>) {}
+   |            ^^^^
+help: consider reborrowing the `Pin` instead of moving it
+   |
+LL |     foo.as_mut().foo();
+   |         +++++++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/moves/suggest-clone.fixed b/src/test/ui/moves/suggest-clone.fixed
new file mode 100644
index 00000000000..204bfdb10b0
--- /dev/null
+++ b/src/test/ui/moves/suggest-clone.fixed
@@ -0,0 +1,11 @@
+// run-rustfix
+
+#[derive(Clone)]
+struct Foo;
+impl Foo {
+    fn foo(self) {}
+}
+fn main() {
+    let foo = &Foo;
+    foo.clone().foo(); //~ ERROR cannot move out
+}
diff --git a/src/test/ui/moves/suggest-clone.rs b/src/test/ui/moves/suggest-clone.rs
new file mode 100644
index 00000000000..25dd9f006f9
--- /dev/null
+++ b/src/test/ui/moves/suggest-clone.rs
@@ -0,0 +1,11 @@
+// run-rustfix
+
+#[derive(Clone)]
+struct Foo;
+impl Foo {
+    fn foo(self) {}
+}
+fn main() {
+    let foo = &Foo;
+    foo.foo(); //~ ERROR cannot move out
+}
diff --git a/src/test/ui/moves/suggest-clone.stderr b/src/test/ui/moves/suggest-clone.stderr
new file mode 100644
index 00000000000..cbb3dfea3ba
--- /dev/null
+++ b/src/test/ui/moves/suggest-clone.stderr
@@ -0,0 +1,22 @@
+error[E0507]: cannot move out of `*foo` which is behind a shared reference
+  --> $DIR/suggest-clone.rs:10:5
+   |
+LL |     foo.foo();
+   |     ^^^^-----
+   |     |   |
+   |     |   `*foo` moved due to this method call
+   |     move occurs because `*foo` has type `Foo`, which does not implement the `Copy` trait
+   |
+note: `Foo::foo` takes ownership of the receiver `self`, which moves `*foo`
+  --> $DIR/suggest-clone.rs:6:12
+   |
+LL |     fn foo(self) {}
+   |            ^^^^
+help: you can `clone` the value and consume it, but this might not be your desired behavior
+   |
+LL |     foo.clone().foo();
+   |         ++++++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0507`.
diff --git a/src/test/ui/parser/intersection-patterns-1.fixed b/src/test/ui/parser/intersection-patterns-1.fixed
new file mode 100644
index 00000000000..44773095b87
--- /dev/null
+++ b/src/test/ui/parser/intersection-patterns-1.fixed
@@ -0,0 +1,35 @@
+// This tests the parser recovery in `recover_intersection_pat`
+// and serves as a regression test for the diagnostics issue #65400.
+//
+// The general idea is that for `$pat_lhs @ $pat_rhs` where
+// `$pat_lhs` is not generated by `ref? mut? $ident` we want
+// to suggest either switching the order or note that intersection
+// patterns are not allowed.
+
+// run-rustfix
+
+#![allow(unused_variables)]
+
+fn main() {
+    let s: Option<u8> = None;
+
+    match s {
+        y @ Some(x) => {}
+        //~^ ERROR pattern on wrong side of `@`
+        //~| pattern on the left, should be on the right
+        //~| binding on the right, should be on the left
+        //~| HELP switch the order
+        //~| SUGGESTION y @ Some(x)
+        _ => {}
+    }
+
+    match 2 {
+        e @ 1..=5 => {}
+        //~^ ERROR pattern on wrong side of `@`
+        //~| pattern on the left, should be on the right
+        //~| binding on the right, should be on the left
+        //~| HELP switch the order
+        //~| SUGGESTION e @ 1..=5
+        _ => {}
+    }
+}
diff --git a/src/test/ui/parser/intersection-patterns.rs b/src/test/ui/parser/intersection-patterns-1.rs
index a6d27aab4f6..1036b9daf64 100644
--- a/src/test/ui/parser/intersection-patterns.rs
+++ b/src/test/ui/parser/intersection-patterns-1.rs
@@ -6,6 +6,10 @@
 // to suggest either switching the order or note that intersection
 // patterns are not allowed.
 
+// run-rustfix
+
+#![allow(unused_variables)]
+
 fn main() {
     let s: Option<u8> = None;
 
@@ -19,15 +23,6 @@ fn main() {
         _ => {}
     }
 
-    match s {
-        Some(x) @ Some(y) => {}
-        //~^ ERROR left-hand side of `@` must be a binding
-        //~| interpreted as a pattern, not a binding
-        //~| also a pattern
-        //~| NOTE bindings are `x`, `mut x`, `ref x`, and `ref mut x`
-        _ => {}
-    }
-
     match 2 {
         1 ..= 5 @ e => {}
         //~^ ERROR pattern on wrong side of `@`
diff --git a/src/test/ui/parser/intersection-patterns.stderr b/src/test/ui/parser/intersection-patterns-1.stderr
index 9dc4c469a60..dc968656c91 100644
--- a/src/test/ui/parser/intersection-patterns.stderr
+++ b/src/test/ui/parser/intersection-patterns-1.stderr
@@ -1,5 +1,5 @@
 error: pattern on wrong side of `@`
-  --> $DIR/intersection-patterns.rs:13:9
+  --> $DIR/intersection-patterns-1.rs:17:9
    |
 LL |         Some(x) @ y => {}
    |         -------^^^-
@@ -8,19 +8,8 @@ LL |         Some(x) @ y => {}
    |         pattern on the left, should be on the right
    |         help: switch the order: `y @ Some(x)`
 
-error: left-hand side of `@` must be a binding
-  --> $DIR/intersection-patterns.rs:23:9
-   |
-LL |         Some(x) @ Some(y) => {}
-   |         -------^^^-------
-   |         |         |
-   |         |         also a pattern
-   |         interpreted as a pattern, not a binding
-   |
-   = note: bindings are `x`, `mut x`, `ref x`, and `ref mut x`
-
 error: pattern on wrong side of `@`
-  --> $DIR/intersection-patterns.rs:32:9
+  --> $DIR/intersection-patterns-1.rs:27:9
    |
 LL |         1 ..= 5 @ e => {}
    |         -------^^^-
@@ -29,5 +18,5 @@ LL |         1 ..= 5 @ e => {}
    |         pattern on the left, should be on the right
    |         help: switch the order: `e @ 1..=5`
 
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/parser/intersection-patterns-2.rs b/src/test/ui/parser/intersection-patterns-2.rs
new file mode 100644
index 00000000000..408415e87ef
--- /dev/null
+++ b/src/test/ui/parser/intersection-patterns-2.rs
@@ -0,0 +1,20 @@
+// This tests the parser recovery in `recover_intersection_pat`
+// and serves as a regression test for the diagnostics issue #65400.
+//
+// The general idea is that for `$pat_lhs @ $pat_rhs` where
+// `$pat_lhs` is not generated by `ref? mut? $ident` we want
+// to suggest either switching the order or note that intersection
+// patterns are not allowed.
+
+fn main() {
+    let s: Option<u8> = None;
+
+    match s {
+        Some(x) @ Some(y) => {}
+        //~^ ERROR left-hand side of `@` must be a binding
+        //~| interpreted as a pattern, not a binding
+        //~| also a pattern
+        //~| NOTE bindings are `x`, `mut x`, `ref x`, and `ref mut x`
+        _ => {}
+    }
+}
diff --git a/src/test/ui/parser/intersection-patterns-2.stderr b/src/test/ui/parser/intersection-patterns-2.stderr
new file mode 100644
index 00000000000..f7e78814ca5
--- /dev/null
+++ b/src/test/ui/parser/intersection-patterns-2.stderr
@@ -0,0 +1,13 @@
+error: left-hand side of `@` must be a binding
+  --> $DIR/intersection-patterns-2.rs:13:9
+   |
+LL |         Some(x) @ Some(y) => {}
+   |         -------^^^-------
+   |         |         |
+   |         |         also a pattern
+   |         interpreted as a pattern, not a binding
+   |
+   = note: bindings are `x`, `mut x`, `ref x`, and `ref mut x`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/issue-105634.rs b/src/test/ui/parser/issue-105634.rs
new file mode 100644
index 00000000000..579aa6e5bfb
--- /dev/null
+++ b/src/test/ui/parser/issue-105634.rs
@@ -0,0 +1,8 @@
+// check-pass
+
+fn main() {
+    let _a = ..;
+    let _b = ..=10;
+    let _c = &..;
+    let _d = &..=10;
+}
diff --git a/src/test/ui/parser/kw-in-trait-bounds.rs b/src/test/ui/parser/kw-in-trait-bounds.rs
index fa037e5937d..e9e85339aff 100644
--- a/src/test/ui/parser/kw-in-trait-bounds.rs
+++ b/src/test/ui/parser/kw-in-trait-bounds.rs
@@ -4,21 +4,13 @@ fn _f<F: fn(), G>(_: impl fn(), _: &dyn fn())
 //~^ ERROR expected identifier, found keyword `fn`
 //~| ERROR expected identifier, found keyword `fn`
 //~| ERROR expected identifier, found keyword `fn`
-//~| ERROR cannot find trait `r#fn` in this scope
-//~| ERROR cannot find trait `r#fn` in this scope
-//~| ERROR cannot find trait `r#fn` in this scope
-//~| HELP  a trait with a similar name exists
-//~| HELP  a trait with a similar name exists
-//~| HELP  a trait with a similar name exists
-//~| HELP  escape `fn` to use it as an identifier
-//~| HELP  escape `fn` to use it as an identifier
-//~| HELP  escape `fn` to use it as an identifier
+//~| HELP use `Fn` to refer to the trait
+//~| HELP use `Fn` to refer to the trait
+//~| HELP use `Fn` to refer to the trait
 where
 G: fn(),
     //~^ ERROR expected identifier, found keyword `fn`
-    //~| ERROR cannot find trait `r#fn` in this scope
-    //~| HELP  a trait with a similar name exists
-    //~| HELP  escape `fn` to use it as an identifier
+    //~| HELP use `Fn` to refer to the trait
 {}
 
 fn _g<A: struct, B>(_: impl struct, _: &dyn struct)
diff --git a/src/test/ui/parser/kw-in-trait-bounds.stderr b/src/test/ui/parser/kw-in-trait-bounds.stderr
index 79643660e8b..2d3aad4d6ba 100644
--- a/src/test/ui/parser/kw-in-trait-bounds.stderr
+++ b/src/test/ui/parser/kw-in-trait-bounds.stderr
@@ -2,48 +2,48 @@ error: expected identifier, found keyword `fn`
   --> $DIR/kw-in-trait-bounds.rs:3:10
    |
 LL | fn _f<F: fn(), G>(_: impl fn(), _: &dyn fn())
-   |          ^^ expected identifier, found keyword
+   |          ^^
    |
-help: escape `fn` to use it as an identifier
+help: use `Fn` to refer to the trait
    |
-LL | fn _f<F: r#fn(), G>(_: impl fn(), _: &dyn fn())
-   |          ++
+LL | fn _f<F: Fn(), G>(_: impl fn(), _: &dyn fn())
+   |          ~~
 
 error: expected identifier, found keyword `fn`
   --> $DIR/kw-in-trait-bounds.rs:3:27
    |
 LL | fn _f<F: fn(), G>(_: impl fn(), _: &dyn fn())
-   |                           ^^ expected identifier, found keyword
+   |                           ^^
    |
-help: escape `fn` to use it as an identifier
+help: use `Fn` to refer to the trait
    |
-LL | fn _f<F: fn(), G>(_: impl r#fn(), _: &dyn fn())
-   |                           ++
+LL | fn _f<F: fn(), G>(_: impl Fn(), _: &dyn fn())
+   |                           ~~
 
 error: expected identifier, found keyword `fn`
   --> $DIR/kw-in-trait-bounds.rs:3:41
    |
 LL | fn _f<F: fn(), G>(_: impl fn(), _: &dyn fn())
-   |                                         ^^ expected identifier, found keyword
+   |                                         ^^
    |
-help: escape `fn` to use it as an identifier
+help: use `Fn` to refer to the trait
    |
-LL | fn _f<F: fn(), G>(_: impl fn(), _: &dyn r#fn())
-   |                                         ++
+LL | fn _f<F: fn(), G>(_: impl fn(), _: &dyn Fn())
+   |                                         ~~
 
 error: expected identifier, found keyword `fn`
-  --> $DIR/kw-in-trait-bounds.rs:17:4
+  --> $DIR/kw-in-trait-bounds.rs:11:4
    |
 LL | G: fn(),
-   |    ^^ expected identifier, found keyword
+   |    ^^
    |
-help: escape `fn` to use it as an identifier
+help: use `Fn` to refer to the trait
    |
-LL | G: r#fn(),
-   |    ++
+LL | G: Fn(),
+   |    ~~
 
 error: expected identifier, found keyword `struct`
-  --> $DIR/kw-in-trait-bounds.rs:24:10
+  --> $DIR/kw-in-trait-bounds.rs:16:10
    |
 LL | fn _g<A: struct, B>(_: impl struct, _: &dyn struct)
    |          ^^^^^^ expected identifier, found keyword
@@ -54,7 +54,7 @@ LL | fn _g<A: r#struct, B>(_: impl struct, _: &dyn struct)
    |          ++
 
 error: expected identifier, found keyword `struct`
-  --> $DIR/kw-in-trait-bounds.rs:24:29
+  --> $DIR/kw-in-trait-bounds.rs:16:29
    |
 LL | fn _g<A: struct, B>(_: impl struct, _: &dyn struct)
    |                             ^^^^^^ expected identifier, found keyword
@@ -65,7 +65,7 @@ LL | fn _g<A: struct, B>(_: impl r#struct, _: &dyn struct)
    |                             ++
 
 error: expected identifier, found keyword `struct`
-  --> $DIR/kw-in-trait-bounds.rs:24:45
+  --> $DIR/kw-in-trait-bounds.rs:16:45
    |
 LL | fn _g<A: struct, B>(_: impl struct, _: &dyn struct)
    |                                             ^^^^^^ expected identifier, found keyword
@@ -76,7 +76,7 @@ LL | fn _g<A: struct, B>(_: impl struct, _: &dyn r#struct)
    |                                             ++
 
 error: expected identifier, found keyword `struct`
-  --> $DIR/kw-in-trait-bounds.rs:38:8
+  --> $DIR/kw-in-trait-bounds.rs:30:8
    |
 LL |     B: struct,
    |        ^^^^^^ expected identifier, found keyword
@@ -86,44 +86,8 @@ help: escape `struct` to use it as an identifier
 LL |     B: r#struct,
    |        ++
 
-error[E0405]: cannot find trait `r#fn` in this scope
-  --> $DIR/kw-in-trait-bounds.rs:3:10
-   |
-LL | fn _f<F: fn(), G>(_: impl fn(), _: &dyn fn())
-   |          ^^ help: a trait with a similar name exists (notice the capitalization): `Fn`
-  --> $SRC_DIR/core/src/ops/function.rs:LL:COL
-   |
-   = note: similarly named trait `Fn` defined here
-
-error[E0405]: cannot find trait `r#fn` in this scope
-  --> $DIR/kw-in-trait-bounds.rs:17:4
-   |
-LL | G: fn(),
-   |    ^^ help: a trait with a similar name exists (notice the capitalization): `Fn`
-  --> $SRC_DIR/core/src/ops/function.rs:LL:COL
-   |
-   = note: similarly named trait `Fn` defined here
-
-error[E0405]: cannot find trait `r#fn` in this scope
-  --> $DIR/kw-in-trait-bounds.rs:3:27
-   |
-LL | fn _f<F: fn(), G>(_: impl fn(), _: &dyn fn())
-   |                           ^^ help: a trait with a similar name exists (notice the capitalization): `Fn`
-  --> $SRC_DIR/core/src/ops/function.rs:LL:COL
-   |
-   = note: similarly named trait `Fn` defined here
-
-error[E0405]: cannot find trait `r#fn` in this scope
-  --> $DIR/kw-in-trait-bounds.rs:3:41
-   |
-LL | fn _f<F: fn(), G>(_: impl fn(), _: &dyn fn())
-   |                                         ^^ help: a trait with a similar name exists (notice the capitalization): `Fn`
-  --> $SRC_DIR/core/src/ops/function.rs:LL:COL
-   |
-   = note: similarly named trait `Fn` defined here
-
 error[E0405]: cannot find trait `r#struct` in this scope
-  --> $DIR/kw-in-trait-bounds.rs:24:10
+  --> $DIR/kw-in-trait-bounds.rs:16:10
    |
 LL | fn _g<A: struct, B>(_: impl struct, _: &dyn struct)
    |          ^^^^^^ help: a trait with a similar name exists (notice the capitalization): `Struct`
@@ -132,7 +96,7 @@ LL | trait Struct {}
    | ------------ similarly named trait `Struct` defined here
 
 error[E0405]: cannot find trait `r#struct` in this scope
-  --> $DIR/kw-in-trait-bounds.rs:38:8
+  --> $DIR/kw-in-trait-bounds.rs:30:8
    |
 LL |     B: struct,
    |        ^^^^^^ help: a trait with a similar name exists (notice the capitalization): `Struct`
@@ -141,7 +105,7 @@ LL | trait Struct {}
    | ------------ similarly named trait `Struct` defined here
 
 error[E0405]: cannot find trait `r#struct` in this scope
-  --> $DIR/kw-in-trait-bounds.rs:24:29
+  --> $DIR/kw-in-trait-bounds.rs:16:29
    |
 LL | fn _g<A: struct, B>(_: impl struct, _: &dyn struct)
    |                             ^^^^^^ help: a trait with a similar name exists (notice the capitalization): `Struct`
@@ -150,7 +114,7 @@ LL | trait Struct {}
    | ------------ similarly named trait `Struct` defined here
 
 error[E0405]: cannot find trait `r#struct` in this scope
-  --> $DIR/kw-in-trait-bounds.rs:24:45
+  --> $DIR/kw-in-trait-bounds.rs:16:45
    |
 LL | fn _g<A: struct, B>(_: impl struct, _: &dyn struct)
    |                                             ^^^^^^ help: a trait with a similar name exists (notice the capitalization): `Struct`
@@ -158,6 +122,6 @@ LL | fn _g<A: struct, B>(_: impl struct, _: &dyn struct)
 LL | trait Struct {}
    | ------------ similarly named trait `Struct` defined here
 
-error: aborting due to 16 previous errors
+error: aborting due to 12 previous errors
 
 For more information about this error, try `rustc --explain E0405`.
diff --git a/src/test/ui/parser/recover-fn-trait-from-fn-kw.rs b/src/test/ui/parser/recover-fn-trait-from-fn-kw.rs
new file mode 100644
index 00000000000..b6611e6273d
--- /dev/null
+++ b/src/test/ui/parser/recover-fn-trait-from-fn-kw.rs
@@ -0,0 +1,12 @@
+fn foo(_: impl fn() -> i32) {}
+//~^ ERROR expected identifier, found keyword `fn`
+
+fn foo2<T: fn(i32)>(_: T) {}
+//~^ ERROR expected identifier, found keyword `fn`
+
+fn main() {
+    foo(|| ());
+    //~^ mismatched types
+    foo2(|_: ()| {});
+    //~^ type mismatch in closure arguments
+}
diff --git a/src/test/ui/parser/recover-fn-trait-from-fn-kw.stderr b/src/test/ui/parser/recover-fn-trait-from-fn-kw.stderr
new file mode 100644
index 00000000000..3681a796c53
--- /dev/null
+++ b/src/test/ui/parser/recover-fn-trait-from-fn-kw.stderr
@@ -0,0 +1,48 @@
+error: expected identifier, found keyword `fn`
+  --> $DIR/recover-fn-trait-from-fn-kw.rs:1:16
+   |
+LL | fn foo(_: impl fn() -> i32) {}
+   |                ^^
+   |
+help: use `Fn` to refer to the trait
+   |
+LL | fn foo(_: impl Fn() -> i32) {}
+   |                ~~
+
+error: expected identifier, found keyword `fn`
+  --> $DIR/recover-fn-trait-from-fn-kw.rs:4:12
+   |
+LL | fn foo2<T: fn(i32)>(_: T) {}
+   |            ^^
+   |
+help: use `Fn` to refer to the trait
+   |
+LL | fn foo2<T: Fn(i32)>(_: T) {}
+   |            ~~
+
+error[E0308]: mismatched types
+  --> $DIR/recover-fn-trait-from-fn-kw.rs:8:12
+   |
+LL |     foo(|| ());
+   |            ^^ expected `i32`, found `()`
+
+error[E0631]: type mismatch in closure arguments
+  --> $DIR/recover-fn-trait-from-fn-kw.rs:10:5
+   |
+LL |     foo2(|_: ()| {});
+   |     ^^^^ ------- found signature defined here
+   |     |
+   |     expected due to this
+   |
+   = note: expected closure signature `fn(i32) -> _`
+              found closure signature `fn(()) -> _`
+note: required by a bound in `foo2`
+  --> $DIR/recover-fn-trait-from-fn-kw.rs:4:12
+   |
+LL | fn foo2<T: fn(i32)>(_: T) {}
+   |            ^^^^^^^ required by this bound in `foo2`
+
+error: aborting due to 4 previous errors
+
+Some errors have detailed explanations: E0308, E0631.
+For more information about an error, try `rustc --explain E0308`.
diff --git a/src/test/ui/proc-macro/quote-debug.stdout b/src/test/ui/proc-macro/quote-debug.stdout
index d2cc5c6e2a3..9f64a1e06b9 100644
--- a/src/test/ui/proc-macro/quote-debug.stdout
+++ b/src/test/ui/proc-macro/quote-debug.stdout
@@ -42,6 +42,7 @@ const _: () =
     {
         extern crate proc_macro;
         #[rustc_proc_macro_decls]
+        #[used]
         #[allow(deprecated)]
         static _DECLS: &[proc_macro::bridge::client::ProcMacro] = &[];
     };
diff --git a/src/test/ui/repr/transparent-enum-too-many-variants.rs b/src/test/ui/repr/transparent-enum-too-many-variants.rs
new file mode 100644
index 00000000000..0dd4b4e6846
--- /dev/null
+++ b/src/test/ui/repr/transparent-enum-too-many-variants.rs
@@ -0,0 +1,10 @@
+use std::mem::size_of;
+
+#[repr(transparent)]
+enum Foo { //~ ERROR E0731
+    A(u8), B(u8),
+}
+
+fn main() {
+    println!("Foo: {}", size_of::<Foo>());
+}
diff --git a/src/test/ui/repr/transparent-enum-too-many-variants.stderr b/src/test/ui/repr/transparent-enum-too-many-variants.stderr
new file mode 100644
index 00000000000..fb44757efaf
--- /dev/null
+++ b/src/test/ui/repr/transparent-enum-too-many-variants.stderr
@@ -0,0 +1,11 @@
+error[E0731]: transparent enum needs exactly one variant, but has 2
+  --> $DIR/transparent-enum-too-many-variants.rs:4:1
+   |
+LL | enum Foo {
+   | ^^^^^^^^ needs exactly one variant, but has 2
+LL |     A(u8), B(u8),
+   |     -      - too many variants in `Foo`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0731`.
diff --git a/src/test/ui/issues/auxiliary/issue-30535.rs b/src/test/ui/resolve/auxiliary/issue-30535.rs
index 3608d4a2f14..3608d4a2f14 100644
--- a/src/test/ui/issues/auxiliary/issue-30535.rs
+++ b/src/test/ui/resolve/auxiliary/issue-30535.rs
diff --git a/src/test/ui/issues/issue-30535.rs b/src/test/ui/resolve/issue-30535.rs
index d48f00d5aca..d48f00d5aca 100644
--- a/src/test/ui/issues/issue-30535.rs
+++ b/src/test/ui/resolve/issue-30535.rs
diff --git a/src/test/ui/issues/issue-30535.stderr b/src/test/ui/resolve/issue-30535.stderr
index e3692934b62..e3692934b62 100644
--- a/src/test/ui/issues/issue-30535.stderr
+++ b/src/test/ui/resolve/issue-30535.stderr
diff --git a/src/test/ui/issues/issue-39559-2.rs b/src/test/ui/resolve/issue-39559-2.rs
index 07d3a82b1ed..07d3a82b1ed 100644
--- a/src/test/ui/issues/issue-39559-2.rs
+++ b/src/test/ui/resolve/issue-39559-2.rs
diff --git a/src/test/ui/issues/issue-39559-2.stderr b/src/test/ui/resolve/issue-39559-2.stderr
index ea27e7bd250..ea27e7bd250 100644
--- a/src/test/ui/issues/issue-39559-2.stderr
+++ b/src/test/ui/resolve/issue-39559-2.stderr
diff --git a/src/test/ui/issues/issue-39559.rs b/src/test/ui/resolve/issue-39559.rs
index 58d25940733..58d25940733 100644
--- a/src/test/ui/issues/issue-39559.rs
+++ b/src/test/ui/resolve/issue-39559.rs
diff --git a/src/test/ui/issues/issue-39559.stderr b/src/test/ui/resolve/issue-39559.stderr
index 7626f827fc5..7626f827fc5 100644
--- a/src/test/ui/issues/issue-39559.stderr
+++ b/src/test/ui/resolve/issue-39559.stderr
diff --git a/src/test/ui/rust-2018/edition-lint-infer-outlives-macro.fixed b/src/test/ui/rust-2018/edition-lint-infer-outlives-macro.fixed
new file mode 100644
index 00000000000..8cdb08e81b9
--- /dev/null
+++ b/src/test/ui/rust-2018/edition-lint-infer-outlives-macro.fixed
@@ -0,0 +1,137 @@
+// edition:2018
+// aux-build:edition-lint-infer-outlives-macro.rs
+// run-rustfix
+
+#![deny(explicit_outlives_requirements)]
+#![allow(dead_code)]
+
+#[macro_use]
+extern crate edition_lint_infer_outlives_macro;
+
+// Test that the lint does not fire if the predicate is from the local crate,
+// but all the bounds are from an external macro.
+macro_rules! make_foo {
+    ($a:tt) => {
+        struct Foo<$a, 'b: $a> {
+            foo: &$a &'b (),
+        }
+
+        struct FooWhere<$a, 'b> where 'b: $a {
+            foo: &$a &'b (),
+        }
+    }
+}
+
+gimme_a! {make_foo!}
+
+struct Bar<'a, 'b> {
+    //~^ ERROR: outlives requirements can be inferred
+    bar: &'a &'b (),
+}
+
+struct BarWhere<'a, 'b> {
+    //~^ ERROR: outlives requirements can be inferred
+    bar: &'a &'b (),
+}
+
+// Test that the lint *does* fire if the predicate is contained in a local macro.
+mod everything_inside {
+    macro_rules! m {
+        ('b: 'a) => {
+            struct Foo<'a, 'b>(&'a &'b ());
+            //~^ ERROR: outlives requirements can be inferred
+            struct Bar<'a, 'b>(&'a &'b ()) ;
+            //~^ ERROR: outlives requirements can be inferred
+            struct Baz<'a, 'b>(&'a &'b ()) where (): Sized, ;
+            //~^ ERROR: outlives requirements can be inferred
+        };
+    }
+    m!('b: 'a);
+}
+
+mod inner_lifetime_outside_colon_inside {
+    macro_rules! m {
+        ($b:lifetime: 'a) => {
+            struct Foo<'a, $b>(&'a &$b ());
+            //~^ ERROR: outlives requirements can be inferred
+            struct Bar<'a, $b>(&'a &$b ()) ;
+            //~^ ERROR: outlives requirements can be inferred
+            struct Baz<'a, $b>(&'a &$b ()) where (): Sized, ;
+            //~^ ERROR: outlives requirements can be inferred
+        }
+    }
+    m!('b: 'a);
+}
+
+mod outer_lifetime_outside_colon_inside {
+    macro_rules! m {
+        ('b: $a:lifetime) => {
+            struct Foo<$a, 'b: $a>(&$a &'b ());
+            struct Bar<$a, 'b>(&$a &'b ()) where 'b: $a;
+            struct Baz<$a, 'b>(&$a &'b ()) where (): Sized, 'b: $a;
+        }
+    }
+    m!('b: 'a);
+}
+
+mod both_lifetimes_outside_colon_inside {
+    macro_rules! m {
+        ($b:lifetime: $a:lifetime) => {
+            struct Foo<$a, $b: $a>(&$a &$b ());
+            struct Bar<$a, $b>(&$a &$b ()) where $b: $a;
+            struct Baz<$a, $b>(&$a &$b ()) where (): Sized, $b: $a;
+        }
+    }
+    m!('b: 'a);
+}
+
+mod everything_outside {
+    macro_rules! m {
+        ($b:lifetime $colon:tt $a:lifetime) => {
+            struct Foo<$a, $b $colon $a>(&$a &$b ());
+            struct Bar<$a, $b>(&$a &$b ()) where $b $colon $a;
+            struct Baz<$a, $b>(&$a &$b ()) where (): Sized, $b $colon $a;
+        }
+    }
+    m!('b: 'a);
+}
+
+mod everything_outside_with_tt_inner {
+    macro_rules! m {
+        ($b:tt $colon:tt $a:lifetime) => {
+            struct Foo<$a, $b $colon $a>(&$a &$b ());
+            struct Bar<$a, $b>(&$a &$b ()) where $b $colon $a;
+            struct Baz<$a, $b>(&$a &$b ()) where (): Sized, $b $colon $a;
+        }
+    }
+    m!('b: 'a);
+}
+
+// FIXME: These should be consistent.
+mod everything_outside_with_tt_outer {
+    macro_rules! m {
+        ($b:lifetime $colon:tt $a:tt) => {
+            struct Foo<$a, $b >(&$a &$b ());
+            //~^ ERROR: outlives requirements can be inferred
+            struct Bar<$a, $b>(&$a &$b ()) where $b $colon $a;
+            struct Baz<$a, $b>(&$a &$b ()) where (): Sized, $b $colon $a;
+        }
+    }
+    m!('b: 'a);
+}
+
+mod everything_outside_with_tt_both {
+    macro_rules! m {
+        ($b:tt $colon:tt $a:tt) => {
+            struct Foo<$a, $b >(&$a &$b ());
+            //~^ ERROR: outlives requirements can be inferred
+            struct Bar<$a, $b>(&$a &$b ()) where ;
+            //~^ ERROR: outlives requirements can be inferred
+            struct Baz<$a, $b>(&$a &$b ()) where (): Sized, ;
+            //~^ ERROR: outlives requirements can be inferred
+        }
+    }
+    m!('b: 'a);
+}
+
+fn main() {}
diff --git a/src/test/ui/rust-2018/edition-lint-infer-outlives-macro.rs b/src/test/ui/rust-2018/edition-lint-infer-outlives-macro.rs
index d7a832831c1..647906c2dc2 100644
--- a/src/test/ui/rust-2018/edition-lint-infer-outlives-macro.rs
+++ b/src/test/ui/rust-2018/edition-lint-infer-outlives-macro.rs
@@ -1,18 +1,22 @@
 // edition:2018
 // aux-build:edition-lint-infer-outlives-macro.rs
-
-// Test that the lint does not fire if the where predicate
-// is from the local crate, but all the bounds are from an
-// external macro.
+// run-rustfix
 
 #![deny(explicit_outlives_requirements)]
+#![allow(dead_code)]
 
 #[macro_use]
 extern crate edition_lint_infer_outlives_macro;
 
+// Test that the lint does not fire if the predicate is from the local crate,
+// but all the bounds are from an external macro.
 macro_rules! make_foo {
     ($a:tt) => {
-        struct Foo<$a, 'b> where 'b: $a {
+        struct Foo<$a, 'b: $a> {
+            foo: &$a &'b (),
+        }
+
+        struct FooWhere<$a, 'b> where 'b: $a {
             foo: &$a &'b (),
         }
     }
@@ -25,4 +29,109 @@ struct Bar<'a, 'b: 'a> {
     bar: &'a &'b (),
 }
 
+struct BarWhere<'a, 'b> where 'b: 'a {
+    //~^ ERROR: outlives requirements can be inferred
+    bar: &'a &'b (),
+}
+
+// Test that the lint *does* fire if the predicate is contained in a local macro.
+mod everything_inside {
+    macro_rules! m {
+        ('b: 'a) => {
+            struct Foo<'a, 'b: 'a>(&'a &'b ());
+            //~^ ERROR: outlives requirements can be inferred
+            struct Bar<'a, 'b>(&'a &'b ()) where 'b: 'a;
+            //~^ ERROR: outlives requirements can be inferred
+            struct Baz<'a, 'b>(&'a &'b ()) where (): Sized, 'b: 'a;
+            //~^ ERROR: outlives requirements can be inferred
+        };
+    }
+    m!('b: 'a);
+}
+
+mod inner_lifetime_outside_colon_inside {
+    macro_rules! m {
+        ($b:lifetime: 'a) => {
+            struct Foo<'a, $b: 'a>(&'a &$b ());
+            //~^ ERROR: outlives requirements can be inferred
+            struct Bar<'a, $b>(&'a &$b ()) where $b: 'a;
+            //~^ ERROR: outlives requirements can be inferred
+            struct Baz<'a, $b>(&'a &$b ()) where (): Sized, $b: 'a;
+            //~^ ERROR: outlives requirements can be inferred
+        }
+    }
+    m!('b: 'a);
+}
+
+mod outer_lifetime_outside_colon_inside {
+    macro_rules! m {
+        ('b: $a:lifetime) => {
+            struct Foo<$a, 'b: $a>(&$a &'b ());
+            struct Bar<$a, 'b>(&$a &'b ()) where 'b: $a;
+            struct Baz<$a, 'b>(&$a &'b ()) where (): Sized, 'b: $a;
+        }
+    }
+    m!('b: 'a);
+}
+
+mod both_lifetimes_outside_colon_inside {
+    macro_rules! m {
+        ($b:lifetime: $a:lifetime) => {
+            struct Foo<$a, $b: $a>(&$a &$b ());
+            struct Bar<$a, $b>(&$a &$b ()) where $b: $a;
+            struct Baz<$a, $b>(&$a &$b ()) where (): Sized, $b: $a;
+        }
+    }
+    m!('b: 'a);
+}
+
+mod everything_outside {
+    macro_rules! m {
+        ($b:lifetime $colon:tt $a:lifetime) => {
+            struct Foo<$a, $b $colon $a>(&$a &$b ());
+            struct Bar<$a, $b>(&$a &$b ()) where $b $colon $a;
+            struct Baz<$a, $b>(&$a &$b ()) where (): Sized, $b $colon $a;
+        }
+    }
+    m!('b: 'a);
+}
+
+mod everything_outside_with_tt_inner {
+    macro_rules! m {
+        ($b:tt $colon:tt $a:lifetime) => {
+            struct Foo<$a, $b $colon $a>(&$a &$b ());
+            struct Bar<$a, $b>(&$a &$b ()) where $b $colon $a;
+            struct Baz<$a, $b>(&$a &$b ()) where (): Sized, $b $colon $a;
+        }
+    }
+    m!('b: 'a);
+}
+
+// FIXME: These should be consistent.
+mod everything_outside_with_tt_outer {
+    macro_rules! m {
+        ($b:lifetime $colon:tt $a:tt) => {
+            struct Foo<$a, $b $colon $a>(&$a &$b ());
+            //~^ ERROR: outlives requirements can be inferred
+            struct Bar<$a, $b>(&$a &$b ()) where $b $colon $a;
+            struct Baz<$a, $b>(&$a &$b ()) where (): Sized, $b $colon $a;
+        }
+    }
+    m!('b: 'a);
+}
+
+mod everything_outside_with_tt_both {
+    macro_rules! m {
+        ($b:tt $colon:tt $a:tt) => {
+            struct Foo<$a, $b $colon $a>(&$a &$b ());
+            //~^ ERROR: outlives requirements can be inferred
+            struct Bar<$a, $b>(&$a &$b ()) where $b $colon $a;
+            //~^ ERROR: outlives requirements can be inferred
+            struct Baz<$a, $b>(&$a &$b ()) where (): Sized, $b $colon $a;
+            //~^ ERROR: outlives requirements can be inferred
+        }
+    }
+    m!('b: 'a);
+}
+
 fn main() {}
diff --git a/src/test/ui/rust-2018/edition-lint-infer-outlives-macro.stderr b/src/test/ui/rust-2018/edition-lint-infer-outlives-macro.stderr
index 553b1cd976a..734ae687978 100644
--- a/src/test/ui/rust-2018/edition-lint-infer-outlives-macro.stderr
+++ b/src/test/ui/rust-2018/edition-lint-infer-outlives-macro.stderr
@@ -1,14 +1,110 @@
 error: outlives requirements can be inferred
-  --> $DIR/edition-lint-infer-outlives-macro.rs:23:18
+  --> $DIR/edition-lint-infer-outlives-macro.rs:27:18
    |
 LL | struct Bar<'a, 'b: 'a> {
    |                  ^^^^ help: remove this bound
    |
 note: the lint level is defined here
-  --> $DIR/edition-lint-infer-outlives-macro.rs:8:9
+  --> $DIR/edition-lint-infer-outlives-macro.rs:5:9
    |
 LL | #![deny(explicit_outlives_requirements)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to previous error
+error: outlives requirements can be inferred
+  --> $DIR/edition-lint-infer-outlives-macro.rs:32:24
+   |
+LL | struct BarWhere<'a, 'b> where 'b: 'a {
+   |                        ^^^^^^^^^^^^^ help: remove this bound
+
+error: outlives requirements can be inferred
+  --> $DIR/edition-lint-infer-outlives-macro.rs:41:30
+   |
+LL |             struct Foo<'a, 'b: 'a>(&'a &'b ());
+   |                              ^^^^ help: remove this bound
+...
+LL |     m!('b: 'a);
+   |     ---------- in this macro invocation
+   |
+   = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: outlives requirements can be inferred
+  --> $DIR/edition-lint-infer-outlives-macro.rs:43:44
+   |
+LL |             struct Bar<'a, 'b>(&'a &'b ()) where 'b: 'a;
+   |                                            ^^^^^^^^^^^^ help: remove this bound
+...
+LL |     m!('b: 'a);
+   |     ---------- in this macro invocation
+   |
+   = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: outlives requirements can be inferred
+  --> $DIR/edition-lint-infer-outlives-macro.rs:45:61
+   |
+LL |             struct Baz<'a, 'b>(&'a &'b ()) where (): Sized, 'b: 'a;
+   |                                                             ^^^^^^ help: remove this bound
+...
+LL |     m!('b: 'a);
+   |     ---------- in this macro invocation
+   |
+   = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: outlives requirements can be inferred
+  --> $DIR/edition-lint-infer-outlives-macro.rs:55:30
+   |
+LL |             struct Foo<'a, $b: 'a>(&'a &$b ());
+   |                              ^^^^ help: remove this bound
+...
+LL |     m!('b: 'a);
+   |     ---------- in this macro invocation
+   |
+   = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: outlives requirements can be inferred
+  --> $DIR/edition-lint-infer-outlives-macro.rs:57:44
+   |
+LL |             struct Bar<'a, $b>(&'a &$b ()) where $b: 'a;
+   |                                            ^^^^^^^^^^^^ help: remove this bound
+...
+LL |     m!('b: 'a);
+   |     ---------- in this macro invocation
+   |
+   = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: outlives requirements can be inferred
+  --> $DIR/edition-lint-infer-outlives-macro.rs:59:61
+   |
+LL |             struct Baz<'a, $b>(&'a &$b ()) where (): Sized, $b: 'a;
+   |                                                             ^^^^^^ help: remove this bound
+...
+LL |     m!('b: 'a);
+   |     ---------- in this macro invocation
+   |
+   = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: outlives requirements can be inferred
+  --> $DIR/edition-lint-infer-outlives-macro.rs:114:31
+   |
+LL |             struct Foo<$a, $b $colon $a>(&$a &$b ());
+   |                               ^^^^^^^^^ help: remove this bound
+
+error: outlives requirements can be inferred
+  --> $DIR/edition-lint-infer-outlives-macro.rs:126:31
+   |
+LL |             struct Foo<$a, $b $colon $a>(&$a &$b ());
+   |                               ^^^^^^^^^ help: remove this bound
+
+error: outlives requirements can be inferred
+  --> $DIR/edition-lint-infer-outlives-macro.rs:128:50
+   |
+LL |             struct Bar<$a, $b>(&$a &$b ()) where $b $colon $a;
+   |                                                  ^^^^^^^^^^^^ help: remove this bound
+
+error: outlives requirements can be inferred
+  --> $DIR/edition-lint-infer-outlives-macro.rs:130:61
+   |
+LL |             struct Baz<$a, $b>(&$a &$b ()) where (): Sized, $b $colon $a;
+   |                                                             ^^^^^^^^^^^^ help: remove this bound
+
+error: aborting due to 12 previous errors
 
diff --git a/src/test/ui/issues/issue-18118-2.rs b/src/test/ui/static/issue-18118-2.rs
index f712a2eedb7..f712a2eedb7 100644
--- a/src/test/ui/issues/issue-18118-2.rs
+++ b/src/test/ui/static/issue-18118-2.rs
diff --git a/src/test/ui/issues/issue-18118-2.stderr b/src/test/ui/static/issue-18118-2.stderr
index 4fc3ca78f96..4fc3ca78f96 100644
--- a/src/test/ui/issues/issue-18118-2.stderr
+++ b/src/test/ui/static/issue-18118-2.stderr
diff --git a/src/test/ui/issues/issue-18118.rs b/src/test/ui/static/issue-18118.rs
index f58a3de281f..f58a3de281f 100644
--- a/src/test/ui/issues/issue-18118.rs
+++ b/src/test/ui/static/issue-18118.rs
diff --git a/src/test/ui/issues/issue-18118.stderr b/src/test/ui/static/issue-18118.stderr
index 49798a148de..49798a148de 100644
--- a/src/test/ui/issues/issue-18118.stderr
+++ b/src/test/ui/static/issue-18118.stderr
diff --git a/src/test/ui/suggestions/assoc-ct-for-assoc-method.rs b/src/test/ui/suggestions/assoc-ct-for-assoc-method.rs
new file mode 100644
index 00000000000..fe222776989
--- /dev/null
+++ b/src/test/ui/suggestions/assoc-ct-for-assoc-method.rs
@@ -0,0 +1,25 @@
+struct MyS;
+
+impl MyS {
+    const FOO: i32 = 1;
+    fn foo() -> MyS {
+        MyS
+    }
+}
+
+fn main() {
+    let x: i32 = MyS::foo;
+    //~^ ERROR mismatched types
+    //~| HELP try referring to the
+
+    let z: i32 = i32::max;
+    //~^ ERROR mismatched types
+    //~| HELP try referring to the
+
+    // This example is still broken though... This is a hard suggestion to make,
+    // because we don't have access to the associated const probing code to make
+    // this suggestion where it's emitted, i.e. in trait selection.
+    let y: i32 = i32::max - 42;
+    //~^ ERROR cannot subtract
+    //~| HELP use parentheses
+}
diff --git a/src/test/ui/suggestions/assoc-ct-for-assoc-method.stderr b/src/test/ui/suggestions/assoc-ct-for-assoc-method.stderr
new file mode 100644
index 00000000000..afef38f1296
--- /dev/null
+++ b/src/test/ui/suggestions/assoc-ct-for-assoc-method.stderr
@@ -0,0 +1,47 @@
+error[E0308]: mismatched types
+  --> $DIR/assoc-ct-for-assoc-method.rs:11:18
+   |
+LL |     let x: i32 = MyS::foo;
+   |            ---   ^^^^^^^^ expected `i32`, found fn item
+   |            |
+   |            expected due to this
+   |
+   = note: expected type `i32`
+           found fn item `fn() -> MyS {MyS::foo}`
+help: try referring to the associated const `FOO` instead
+   |
+LL |     let x: i32 = MyS::FOO;
+   |                       ~~~
+
+error[E0308]: mismatched types
+  --> $DIR/assoc-ct-for-assoc-method.rs:15:18
+   |
+LL |     let z: i32 = i32::max;
+   |            ---   ^^^^^^^^ expected `i32`, found fn item
+   |            |
+   |            expected due to this
+   |
+   = note: expected type `i32`
+           found fn item `fn(i32, i32) -> i32 {<i32 as Ord>::max}`
+help: try referring to the associated const `MAX` instead
+   |
+LL |     let z: i32 = i32::MAX;
+   |                       ~~~
+
+error[E0369]: cannot subtract `{integer}` from `fn(i32, i32) -> i32 {<i32 as Ord>::max}`
+  --> $DIR/assoc-ct-for-assoc-method.rs:22:27
+   |
+LL |     let y: i32 = i32::max - 42;
+   |                  -------- ^ -- {integer}
+   |                  |
+   |                  fn(i32, i32) -> i32 {<i32 as Ord>::max}
+   |
+help: use parentheses to call this associated function
+   |
+LL |     let y: i32 = i32::max(/* i32 */, /* i32 */) - 42;
+   |                          ++++++++++++++++++++++
+
+error: aborting due to 3 previous errors
+
+Some errors have detailed explanations: E0308, E0369.
+For more information about an error, try `rustc --explain E0308`.
diff --git a/src/test/ui/suggestions/bad-hex-float-lit.rs b/src/test/ui/suggestions/bad-hex-float-lit.rs
new file mode 100644
index 00000000000..cd6fdbde96c
--- /dev/null
+++ b/src/test/ui/suggestions/bad-hex-float-lit.rs
@@ -0,0 +1,13 @@
+fn main() {
+    let _f: f32 = 0xAAf32;
+    //~^ ERROR mismatched types
+    //~| HELP rewrite this
+
+    let _f: f32 = 0xAB_f32;
+    //~^ ERROR mismatched types
+    //~| HELP rewrite this
+
+    let _f: f64 = 0xFF_f64;
+    //~^ ERROR mismatched types
+    //~| HELP rewrite this
+}
diff --git a/src/test/ui/suggestions/bad-hex-float-lit.stderr b/src/test/ui/suggestions/bad-hex-float-lit.stderr
new file mode 100644
index 00000000000..bc09abb1a56
--- /dev/null
+++ b/src/test/ui/suggestions/bad-hex-float-lit.stderr
@@ -0,0 +1,48 @@
+error[E0308]: mismatched types
+  --> $DIR/bad-hex-float-lit.rs:2:19
+   |
+LL |     let _f: f32 = 0xAAf32;
+   |             ---   ^^^^^^^ expected `f32`, found integer
+   |             |
+   |             expected due to this
+   |
+help: rewrite this as a decimal floating point literal, or use `as` to turn a hex literal into a float
+   |
+LL |     let _f: f32 = 0xAA as f32;
+   |                   ~~~~~~~~~~~
+LL |     let _f: f32 = 170_f32;
+   |                   ~~~~~~~
+
+error[E0308]: mismatched types
+  --> $DIR/bad-hex-float-lit.rs:6:19
+   |
+LL |     let _f: f32 = 0xAB_f32;
+   |             ---   ^^^^^^^^ expected `f32`, found integer
+   |             |
+   |             expected due to this
+   |
+help: rewrite this as a decimal floating point literal, or use `as` to turn a hex literal into a float
+   |
+LL |     let _f: f32 = 0xAB as f32;
+   |                   ~~~~~~~~~~~
+LL |     let _f: f32 = 171_f32;
+   |                   ~~~~~~~
+
+error[E0308]: mismatched types
+  --> $DIR/bad-hex-float-lit.rs:10:19
+   |
+LL |     let _f: f64 = 0xFF_f64;
+   |             ---   ^^^^^^^^ expected `f64`, found integer
+   |             |
+   |             expected due to this
+   |
+help: rewrite this as a decimal floating point literal, or use `as` to turn a hex literal into a float
+   |
+LL |     let _f: f64 = 0xFF as f64;
+   |                   ~~~~~~~~~~~
+LL |     let _f: f64 = 255_f64;
+   |                   ~~~~~~~
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/suggestions/fn-to-method-deeply-nested.rs b/src/test/ui/suggestions/fn-to-method-deeply-nested.rs
new file mode 100644
index 00000000000..58ee3d6409a
--- /dev/null
+++ b/src/test/ui/suggestions/fn-to-method-deeply-nested.rs
@@ -0,0 +1,13 @@
+fn main() -> Result<(), ()> {
+    a(b(c(d(e(
+        //~^ ERROR cannot find function `a` in this scope
+        //~| ERROR cannot find function `b` in this scope
+        //~| ERROR cannot find function `c` in this scope
+        //~| ERROR cannot find function `d` in this scope
+        //~| ERROR cannot find function `e` in this scope
+        z????????????????????????????????????????????????????????????????????????????????????????
+        ?????????????????????????????????????????????????????????????????????????????????????????
+        ??????????????????????????????????????????????????????????????????
+        //~^^^ ERROR cannot find value `z` in this scope
+    )))))
+}
diff --git a/src/test/ui/suggestions/fn-to-method-deeply-nested.stderr b/src/test/ui/suggestions/fn-to-method-deeply-nested.stderr
new file mode 100644
index 00000000000..ce813ea7aba
--- /dev/null
+++ b/src/test/ui/suggestions/fn-to-method-deeply-nested.stderr
@@ -0,0 +1,39 @@
+error[E0425]: cannot find value `z` in this scope
+  --> $DIR/fn-to-method-deeply-nested.rs:8:9
+   |
+LL |         z????????????????????????????????????????????????????????????????????????????????????????
+   |         ^ not found in this scope
+
+error[E0425]: cannot find function `e` in this scope
+  --> $DIR/fn-to-method-deeply-nested.rs:2:13
+   |
+LL |     a(b(c(d(e(
+   |             ^ not found in this scope
+
+error[E0425]: cannot find function `d` in this scope
+  --> $DIR/fn-to-method-deeply-nested.rs:2:11
+   |
+LL |     a(b(c(d(e(
+   |           ^ not found in this scope
+
+error[E0425]: cannot find function `c` in this scope
+  --> $DIR/fn-to-method-deeply-nested.rs:2:9
+   |
+LL |     a(b(c(d(e(
+   |         ^ not found in this scope
+
+error[E0425]: cannot find function `b` in this scope
+  --> $DIR/fn-to-method-deeply-nested.rs:2:7
+   |
+LL |     a(b(c(d(e(
+   |       ^ not found in this scope
+
+error[E0425]: cannot find function `a` in this scope
+  --> $DIR/fn-to-method-deeply-nested.rs:2:5
+   |
+LL |     a(b(c(d(e(
+   |     ^ not found in this scope
+
+error: aborting due to 6 previous errors
+
+For more information about this error, try `rustc --explain E0425`.
diff --git a/src/test/ui/suggestions/issue-104287.rs b/src/test/ui/suggestions/issue-104287.rs
index b7601a548b9..e3fa22a8f66 100644
--- a/src/test/ui/suggestions/issue-104287.rs
+++ b/src/test/ui/suggestions/issue-104287.rs
@@ -1,9 +1,13 @@
 // The purpose of this test is not to validate the output of the compiler.
 // Instead, it ensures the suggestion is generated without performing an arithmetic overflow.
 
+struct S;
+impl S {
+    fn foo(&self) {}
+}
 fn main() {
-    let x = not_found; //~ ERROR cannot find value `not_found` in this scope
-    simd_gt::<()>(x);
+    let x = S;
+    foo::<()>(x);
     //~^ ERROR this associated function takes 0 generic arguments but 1 generic argument was supplied
-    //~| ERROR cannot find function `simd_gt` in this scope
+    //~| ERROR cannot find function `foo` in this scope
 }
diff --git a/src/test/ui/suggestions/issue-104287.stderr b/src/test/ui/suggestions/issue-104287.stderr
index 79812a2985e..602a01828b2 100644
--- a/src/test/ui/suggestions/issue-104287.stderr
+++ b/src/test/ui/suggestions/issue-104287.stderr
@@ -1,30 +1,30 @@
-error[E0425]: cannot find value `not_found` in this scope
-  --> $DIR/issue-104287.rs:5:13
-   |
-LL |     let x = not_found;
-   |             ^^^^^^^^^ not found in this scope
-
 error[E0107]: this associated function takes 0 generic arguments but 1 generic argument was supplied
-  --> $DIR/issue-104287.rs:6:5
+  --> $DIR/issue-104287.rs:10:5
    |
-LL |     simd_gt::<()>(x);
-   |     ^^^^^^^------ help: remove these generics
+LL |     foo::<()>(x);
+   |     ^^^------ help: remove these generics
    |     |
    |     expected 0 generic arguments
+   |
+note: associated function defined here, with 0 generic parameters
+  --> $DIR/issue-104287.rs:6:8
+   |
+LL |     fn foo(&self) {}
+   |        ^^^
 
-error[E0425]: cannot find function `simd_gt` in this scope
-  --> $DIR/issue-104287.rs:6:5
+error[E0425]: cannot find function `foo` in this scope
+  --> $DIR/issue-104287.rs:10:5
    |
-LL |     simd_gt::<()>(x);
-   |     ^^^^^^^ not found in this scope
+LL |     foo::<()>(x);
+   |     ^^^ not found in this scope
    |
-help: use the `.` operator to call the method `SimdPartialOrd::simd_gt` on `[type error]`
+help: use the `.` operator to call the method `foo` on `&S`
    |
-LL -     simd_gt::<()>(x);
-LL +     x.simd_gt();
+LL -     foo::<()>(x);
+LL +     x.foo();
    |
 
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
 
 Some errors have detailed explanations: E0107, E0425.
 For more information about an error, try `rustc --explain E0107`.
diff --git a/src/test/ui/suggestions/issue-105494.rs b/src/test/ui/suggestions/issue-105494.rs
new file mode 100644
index 00000000000..8b409232c20
--- /dev/null
+++ b/src/test/ui/suggestions/issue-105494.rs
@@ -0,0 +1,22 @@
+fn test1() {
+    let _v: i32 = (1 as i32).to_string(); //~ ERROR mismatched types
+
+    // won't suggestion
+    let _v: i32 = (1 as i128).to_string(); //~ ERROR mismatched types
+
+    let _v: &str = "foo".to_string(); //~ ERROR mismatched types
+}
+
+fn test2() {
+    let mut path: String = "/usr".to_string();
+    let folder: String = "lib".to_string();
+
+    path = format!("{}/{}", path, folder).as_str(); //~ ERROR mismatched types
+
+    println!("{}", &path);
+}
+
+fn main() {
+    test1();
+    test2();
+}
diff --git a/src/test/ui/suggestions/issue-105494.stderr b/src/test/ui/suggestions/issue-105494.stderr
new file mode 100644
index 00000000000..5aa3f2af738
--- /dev/null
+++ b/src/test/ui/suggestions/issue-105494.stderr
@@ -0,0 +1,54 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-105494.rs:2:19
+   |
+LL |     let _v: i32 = (1 as i32).to_string();
+   |             ---   ^^^^^^^^^^^^^^^^^^^^^^ expected `i32`, found struct `String`
+   |             |
+   |             expected due to this
+   |
+help: try removing the method call
+   |
+LL -     let _v: i32 = (1 as i32).to_string();
+LL +     let _v: i32 = (1 as i32);
+   |
+
+error[E0308]: mismatched types
+  --> $DIR/issue-105494.rs:5:19
+   |
+LL |     let _v: i32 = (1 as i128).to_string();
+   |             ---   ^^^^^^^^^^^^^^^^^^^^^^^ expected `i32`, found struct `String`
+   |             |
+   |             expected due to this
+
+error[E0308]: mismatched types
+  --> $DIR/issue-105494.rs:7:20
+   |
+LL |     let _v: &str = "foo".to_string();
+   |             ----   ^^^^^^^^^^^^^^^^^ expected `&str`, found struct `String`
+   |             |
+   |             expected due to this
+   |
+help: try removing the method call
+   |
+LL -     let _v: &str = "foo".to_string();
+LL +     let _v: &str = "foo";
+   |
+
+error[E0308]: mismatched types
+  --> $DIR/issue-105494.rs:14:12
+   |
+LL |     let mut path: String = "/usr".to_string();
+   |                   ------ expected due to this type
+...
+LL |     path = format!("{}/{}", path, folder).as_str();
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected struct `String`, found `&str`
+   |
+help: try removing the method call
+   |
+LL -     path = format!("{}/{}", path, folder).as_str();
+LL +     path = format!("{}/{}", path, folder);
+   |
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/suggestions/method-access-to-range-literal-typo.rs b/src/test/ui/suggestions/method-access-to-range-literal-typo.rs
new file mode 100644
index 00000000000..ac662edafe6
--- /dev/null
+++ b/src/test/ui/suggestions/method-access-to-range-literal-typo.rs
@@ -0,0 +1,30 @@
+fn as_ref() -> Option<Vec<u8>> {
+    None
+}
+struct Type {
+    option: Option<Vec<u8>>
+}
+trait Trait {
+    fn foo(&self) -> Vec<u8>;
+}
+impl Trait for Option<Vec<u8>> {
+    fn foo(&self) -> Vec<u8> {
+        vec![1, 2, 3]
+    }
+}
+
+impl Type {
+    fn method(&self) -> Option<Vec<u8>> {
+        self.option..as_ref().map(|x| x)
+        //~^ ERROR E0308
+    }
+    fn method2(&self) -> &u8 {
+        self.option..foo().get(0)
+        //~^ ERROR E0425
+        //~| ERROR E0308
+    }
+}
+
+fn main() {
+    let _ = Type { option: None }.method();
+}
diff --git a/src/test/ui/suggestions/method-access-to-range-literal-typo.stderr b/src/test/ui/suggestions/method-access-to-range-literal-typo.stderr
new file mode 100644
index 00000000000..c84f9467891
--- /dev/null
+++ b/src/test/ui/suggestions/method-access-to-range-literal-typo.stderr
@@ -0,0 +1,48 @@
+error[E0425]: cannot find function `foo` in this scope
+  --> $DIR/method-access-to-range-literal-typo.rs:22:22
+   |
+LL |         self.option..foo().get(0)
+   |                      ^^^ not found in this scope
+   |
+help: you might have meant to write `.` instead of `..`
+   |
+LL -         self.option..foo().get(0)
+LL +         self.option.foo().get(0)
+   |
+
+error[E0308]: mismatched types
+  --> $DIR/method-access-to-range-literal-typo.rs:18:9
+   |
+LL |     fn method(&self) -> Option<Vec<u8>> {
+   |                         --------------- expected `Option<Vec<u8>>` because of return type
+LL |         self.option..as_ref().map(|x| x)
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected enum `Option`, found struct `Range`
+   |
+   = note: expected enum `Option<_>`
+            found struct `std::ops::Range<Option<_>>`
+help: you likely meant to write a method call instead of a range
+   |
+LL -         self.option..as_ref().map(|x| x)
+LL +         self.option.as_ref().map(|x| x)
+   |
+
+error[E0308]: mismatched types
+  --> $DIR/method-access-to-range-literal-typo.rs:22:9
+   |
+LL |     fn method2(&self) -> &u8 {
+   |                          --- expected `&u8` because of return type
+LL |         self.option..foo().get(0)
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^ expected `&u8`, found struct `Range`
+   |
+   = note: expected reference `&u8`
+                 found struct `std::ops::Range<Option<Vec<u8>>>`
+help: you likely meant to write a method call instead of a range
+   |
+LL -         self.option..foo().get(0)
+LL +         self.option.foo().get(0)
+   |
+
+error: aborting due to 3 previous errors
+
+Some errors have detailed explanations: E0308, E0425.
+For more information about an error, try `rustc --explain E0308`.
diff --git a/src/test/ui/suggestions/option-content-move.stderr b/src/test/ui/suggestions/option-content-move.stderr
index 3e0271d0257..474a72093c6 100644
--- a/src/test/ui/suggestions/option-content-move.stderr
+++ b/src/test/ui/suggestions/option-content-move.stderr
@@ -9,6 +9,10 @@ LL |                 if selection.1.unwrap().contains(selection.0) {
    |
 note: `Option::<T>::unwrap` takes ownership of the receiver `self`, which moves `selection.1`
   --> $SRC_DIR/core/src/option.rs:LL:COL
+help: you can `clone` the value and consume it, but this might not be your desired behavior
+   |
+LL |                 if selection.1.clone().unwrap().contains(selection.0) {
+   |                                ++++++++
 
 error[E0507]: cannot move out of `selection.1` which is behind a shared reference
   --> $DIR/option-content-move.rs:27:20
@@ -21,6 +25,10 @@ LL |                 if selection.1.unwrap().contains(selection.0) {
    |
 note: `Result::<T, E>::unwrap` takes ownership of the receiver `self`, which moves `selection.1`
   --> $SRC_DIR/core/src/result.rs:LL:COL
+help: you can `clone` the value and consume it, but this might not be your desired behavior
+   |
+LL |                 if selection.1.clone().unwrap().contains(selection.0) {
+   |                                ++++++++
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/suggestions/shadowed-lplace-method-2.rs b/src/test/ui/suggestions/shadowed-lplace-method-2.rs
new file mode 100644
index 00000000000..dab99fbacd9
--- /dev/null
+++ b/src/test/ui/suggestions/shadowed-lplace-method-2.rs
@@ -0,0 +1,23 @@
+#![allow(unused)]
+
+struct X {
+    x: (),
+}
+pub trait A {
+    fn foo(&mut self, _: usize) -> &mut ();
+}
+impl A for X {
+    fn foo(&mut self, _: usize) -> &mut () {
+        &mut self.x
+    }
+}
+impl X {
+    fn foo(&mut self, _: usize) -> &mut Self {
+        self
+    }
+}
+
+fn main() {
+    let mut x = X { x: () };
+    *x.foo(0) = (); //~ ERROR E0308
+}
diff --git a/src/test/ui/suggestions/shadowed-lplace-method-2.stderr b/src/test/ui/suggestions/shadowed-lplace-method-2.stderr
new file mode 100644
index 00000000000..94eef15f330
--- /dev/null
+++ b/src/test/ui/suggestions/shadowed-lplace-method-2.stderr
@@ -0,0 +1,25 @@
+error[E0308]: mismatched types
+  --> $DIR/shadowed-lplace-method-2.rs:22:17
+   |
+LL |     *x.foo(0) = ();
+   |     ---------   ^^ expected struct `X`, found `()`
+   |     |
+   |     expected due to the type of this binding
+   |
+note: the `foo` call is resolved to the method in `X`, shadowing the method of the same name on trait `A`
+  --> $DIR/shadowed-lplace-method-2.rs:22:8
+   |
+LL |     *x.foo(0) = ();
+   |        ^^^ refers to `X::foo`
+help: you might have meant to call the other method; you can use the fully-qualified path to call it explicitly
+   |
+LL |     *<_ as A>::foo(&mut x, 0) = ();
+   |      ++++++++++++++++++  ~
+help: try wrapping the expression in `X`
+   |
+LL |     *x.foo(0) = X { x: () };
+   |                 ++++++    +
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/suggestions/shadowed-lplace-method.fixed b/src/test/ui/suggestions/shadowed-lplace-method.fixed
new file mode 100644
index 00000000000..740ac77ee0c
--- /dev/null
+++ b/src/test/ui/suggestions/shadowed-lplace-method.fixed
@@ -0,0 +1,10 @@
+// run-rustfix
+#![allow(unused_imports)]
+use std::borrow::BorrowMut;
+use std::cell::RefCell;
+use std::rc::Rc;
+
+fn main() {
+    let rc = Rc::new(RefCell::new(true));
+    *std::cell::RefCell::<_>::borrow_mut(&rc) = false; //~ ERROR E0308
+}
diff --git a/src/test/ui/suggestions/shadowed-lplace-method.rs b/src/test/ui/suggestions/shadowed-lplace-method.rs
new file mode 100644
index 00000000000..6bf12879e6f
--- /dev/null
+++ b/src/test/ui/suggestions/shadowed-lplace-method.rs
@@ -0,0 +1,10 @@
+// run-rustfix
+#![allow(unused_imports)]
+use std::borrow::BorrowMut;
+use std::cell::RefCell;
+use std::rc::Rc;
+
+fn main() {
+    let rc = Rc::new(RefCell::new(true));
+    *rc.borrow_mut() = false; //~ ERROR E0308
+}
diff --git a/src/test/ui/suggestions/shadowed-lplace-method.stderr b/src/test/ui/suggestions/shadowed-lplace-method.stderr
new file mode 100644
index 00000000000..91d0d1200d4
--- /dev/null
+++ b/src/test/ui/suggestions/shadowed-lplace-method.stderr
@@ -0,0 +1,26 @@
+error[E0308]: mismatched types
+  --> $DIR/shadowed-lplace-method.rs:9:24
+   |
+LL |     *rc.borrow_mut() = false;
+   |     ----------------   ^^^^^ expected struct `Rc`, found `bool`
+   |     |
+   |     expected due to the type of this binding
+   |
+   = note: expected struct `Rc<RefCell<bool>>`
+                found type `bool`
+note: the `borrow_mut` call is resolved to the method in `std::borrow::BorrowMut`, shadowing the method of the same name on the inherent impl for `std::cell::RefCell<T>`
+  --> $DIR/shadowed-lplace-method.rs:9:9
+   |
+LL | use std::borrow::BorrowMut;
+   |     ---------------------- `std::borrow::BorrowMut` imported here
+...
+LL |     *rc.borrow_mut() = false;
+   |         ^^^^^^^^^^ refers to `std::borrow::BorrowMut::borrow_mut`
+help: you might have meant to call the other method; you can use the fully-qualified path to call it explicitly
+   |
+LL |     *std::cell::RefCell::<_>::borrow_mut(&rc) = false;
+   |      +++++++++++++++++++++++++++++++++++++  ~
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/suggestions/unnamable-types.stderr b/src/test/ui/suggestions/unnamable-types.stderr
index ede3ebfa739..24bedb5297b 100644
--- a/src/test/ui/suggestions/unnamable-types.stderr
+++ b/src/test/ui/suggestions/unnamable-types.stderr
@@ -19,7 +19,7 @@ error[E0121]: the placeholder `_` is not allowed within types on item signatures
 LL | const C: _ = || 42;
    |          ^ not allowed in type signatures
    |
-note: however, the inferred type `[closure@$DIR/unnamable-types.rs:17:14: 17:16]` cannot be named
+note: however, the inferred type `[closure@unnamable-types.rs:17:14]` cannot be named
   --> $DIR/unnamable-types.rs:17:14
    |
 LL | const C: _ = || 42;
@@ -31,7 +31,7 @@ error: missing type for `const` item
 LL | const D = S { t: { let i = 0; move || -> i32 { i } } };
    |        ^
    |
-note: however, the inferred type `S<[closure@$DIR/unnamable-types.rs:23:31: 23:45]>` cannot be named
+note: however, the inferred type `S<[closure@unnamable-types.rs:23:31]>` cannot be named
   --> $DIR/unnamable-types.rs:23:11
    |
 LL | const D = S { t: { let i = 0; move || -> i32 { i } } };
diff --git a/src/test/ui/issues/issue-52557.rs b/src/test/ui/test-attrs/issue-52557.rs
index 09f7a8c5131..09f7a8c5131 100644
--- a/src/test/ui/issues/issue-52557.rs
+++ b/src/test/ui/test-attrs/issue-52557.rs
diff --git a/src/test/ui/traits/solver-cycles/inductive-canonical-cycle.rs b/src/test/ui/traits/solver-cycles/inductive-canonical-cycle.rs
new file mode 100644
index 00000000000..a3bb76d7e3b
--- /dev/null
+++ b/src/test/ui/traits/solver-cycles/inductive-canonical-cycle.rs
@@ -0,0 +1,28 @@
+// known-bug
+
+// This should compile but fails with the current solver.
+//
+// This checks that the new solver uses `Ambiguous` when hitting the
+// inductive cycle here when proving `exists<^0, ^1> (): Trait<^0, ^1>`
+// which requires proving `Trait<?1, ?0>` but that has the same
+// canonical representation.
+trait Trait<T, U> {}
+
+impl<T, U> Trait<T, U> for ()
+where
+    (): Trait<U, T>,
+    T: OtherTrait,
+{}
+
+trait OtherTrait {}
+impl OtherTrait for u32 {}
+
+fn require_trait<T, U>()
+where
+    (): Trait<T, U>
+{}
+
+fn main() {
+    require_trait::<_, _>();
+    //~^ ERROR overflow evaluating
+}
diff --git a/src/test/ui/traits/solver-cycles/inductive-canonical-cycle.stderr b/src/test/ui/traits/solver-cycles/inductive-canonical-cycle.stderr
new file mode 100644
index 00000000000..e4b84e07822
--- /dev/null
+++ b/src/test/ui/traits/solver-cycles/inductive-canonical-cycle.stderr
@@ -0,0 +1,26 @@
+error[E0275]: overflow evaluating the requirement `_: Sized`
+  --> $DIR/inductive-canonical-cycle.rs:26:5
+   |
+LL |     require_trait::<_, _>();
+   |     ^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`inductive_canonical_cycle`)
+note: required for `()` to implement `Trait<_, _>`
+  --> $DIR/inductive-canonical-cycle.rs:11:12
+   |
+LL | impl<T, U> Trait<T, U> for ()
+   |            ^^^^^^^^^^^     ^^
+   = note: 128 redundant requirements hidden
+   = note: required for `()` to implement `Trait<_, _>`
+note: required by a bound in `require_trait`
+  --> $DIR/inductive-canonical-cycle.rs:22:9
+   |
+LL | fn require_trait<T, U>()
+   |    ------------- required by a bound in this
+LL | where
+LL |     (): Trait<T, U>
+   |         ^^^^^^^^^^^ required by this bound in `require_trait`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0275`.
diff --git a/src/test/ui/traits/trait-upcasting/multiple_supertrait_upcastable.rs b/src/test/ui/traits/trait-upcasting/multiple_supertrait_upcastable.rs
new file mode 100644
index 00000000000..3c6ab86e4c6
--- /dev/null
+++ b/src/test/ui/traits/trait-upcasting/multiple_supertrait_upcastable.rs
@@ -0,0 +1,10 @@
+#![feature(multiple_supertrait_upcastable)]
+#![deny(multiple_supertrait_upcastable)]
+
+trait A {}
+trait B {}
+
+trait C: A + B {}
+//~^ ERROR `C` is object-safe and has multiple supertraits
+
+fn main() {}
diff --git a/src/test/ui/traits/trait-upcasting/multiple_supertrait_upcastable.stderr b/src/test/ui/traits/trait-upcasting/multiple_supertrait_upcastable.stderr
new file mode 100644
index 00000000000..ad80a009ece
--- /dev/null
+++ b/src/test/ui/traits/trait-upcasting/multiple_supertrait_upcastable.stderr
@@ -0,0 +1,14 @@
+error: `C` is object-safe and has multiple supertraits
+  --> $DIR/multiple_supertrait_upcastable.rs:7:1
+   |
+LL | trait C: A + B {}
+   | ^^^^^^^^^^^^^^
+   |
+note: the lint level is defined here
+  --> $DIR/multiple_supertrait_upcastable.rs:2:9
+   |
+LL | #![deny(multiple_supertrait_upcastable)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/type-alias-impl-trait/coherence.stderr b/src/test/ui/type-alias-impl-trait/coherence.stderr
index c923eb08ab3..00b0dbbb583 100644
--- a/src/test/ui/type-alias-impl-trait/coherence.stderr
+++ b/src/test/ui/type-alias-impl-trait/coherence.stderr
@@ -4,7 +4,7 @@ error[E0117]: only traits defined in the current crate can be implemented for ar
 LL | impl<T> foreign_crate::ForeignTrait for AliasOfForeignType<T> {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---------------------
    | |                                       |
-   | |                                       `AliasOfForeignType<T>` is not defined in the current crate
+   | |                                       type alias impl trait is treated as if it were foreign, because its hidden type could be from a foreign crate
    | impl doesn't use only types from inside the current crate
    |
    = note: define and implement a trait or new type instead
diff --git a/src/test/ui/type-alias-impl-trait/destructuring.rs b/src/test/ui/type-alias-impl-trait/destructuring.rs
new file mode 100644
index 00000000000..b752e58380a
--- /dev/null
+++ b/src/test/ui/type-alias-impl-trait/destructuring.rs
@@ -0,0 +1,10 @@
+#![feature(type_alias_impl_trait)]
+
+// check-pass
+
+// issue: https://github.com/rust-lang/rust/issues/104551
+
+fn main() {
+    type T = impl Sized;
+    let (_a, _b): T = (1u32, 2u32);
+}
diff --git a/src/test/ui/type/issue-102598.rs b/src/test/ui/type/issue-102598.rs
new file mode 100644
index 00000000000..93808f18b99
--- /dev/null
+++ b/src/test/ui/type/issue-102598.rs
@@ -0,0 +1,8 @@
+fn foo<'a>(_: impl 'a Sized) {}
+//~^ ERROR: expected `+` between lifetime and Sized
+//~| ERROR: expected one of `:`, `@`, or `|`, found `)`
+//~| ERROR: expected one of `)`, `+`, or `,`, found `Sized`
+//~| ERROR: at least one trait must be specified
+
+fn main(){
+}
diff --git a/src/test/ui/type/issue-102598.stderr b/src/test/ui/type/issue-102598.stderr
new file mode 100644
index 00000000000..a232395cedb
--- /dev/null
+++ b/src/test/ui/type/issue-102598.stderr
@@ -0,0 +1,43 @@
+error: expected `+` between lifetime and Sized
+  --> $DIR/issue-102598.rs:1:20
+   |
+LL | fn foo<'a>(_: impl 'a Sized) {}
+   |                    ^^
+   |
+help: add `+`
+   |
+LL | fn foo<'a>(_: impl 'a + Sized) {}
+   |                       +
+
+error: expected one of `:`, `@`, or `|`, found `)`
+  --> $DIR/issue-102598.rs:1:28
+   |
+LL | fn foo<'a>(_: impl 'a Sized) {}
+   |                            ^ expected one of `:`, `@`, or `|`
+   |
+   = note: anonymous parameters are removed in the 2018 edition (see RFC 1685)
+help: if this is a parameter name, give it a type
+   |
+LL | fn foo<'a>(_: impl 'a Sized: TypeName) {}
+   |                            ++++++++++
+help: if this is a type, explicitly ignore the parameter name
+   |
+LL | fn foo<'a>(_: impl 'a _: Sized) {}
+   |                       ++
+
+error: expected one of `)`, `+`, or `,`, found `Sized`
+  --> $DIR/issue-102598.rs:1:23
+   |
+LL | fn foo<'a>(_: impl 'a Sized) {}
+   |                      -^^^^^ expected one of `)`, `+`, or `,`
+   |                      |
+   |                      help: missing `,`
+
+error: at least one trait must be specified
+  --> $DIR/issue-102598.rs:1:15
+   |
+LL | fn foo<'a>(_: impl 'a Sized) {}
+   |               ^^^^^^^
+
+error: aborting due to 4 previous errors
+
diff --git a/src/test/ui/typeck/check-args-on-fn-err-2.rs b/src/test/ui/typeck/check-args-on-fn-err-2.rs
new file mode 100644
index 00000000000..af57dbe3317
--- /dev/null
+++ b/src/test/ui/typeck/check-args-on-fn-err-2.rs
@@ -0,0 +1,5 @@
+fn main() {
+    a((), 1i32 == 2u32);
+    //~^ ERROR cannot find function `a` in this scope
+    //~| ERROR mismatched types
+}
diff --git a/src/test/ui/typeck/check-args-on-fn-err-2.stderr b/src/test/ui/typeck/check-args-on-fn-err-2.stderr
new file mode 100644
index 00000000000..301bb88dbac
--- /dev/null
+++ b/src/test/ui/typeck/check-args-on-fn-err-2.stderr
@@ -0,0 +1,23 @@
+error[E0308]: mismatched types
+  --> $DIR/check-args-on-fn-err-2.rs:2:19
+   |
+LL |     a((), 1i32 == 2u32);
+   |           ----    ^^^^ expected `i32`, found `u32`
+   |           |
+   |           expected because this is `i32`
+   |
+help: change the type of the numeric literal from `u32` to `i32`
+   |
+LL |     a((), 1i32 == 2i32);
+   |                    ~~~
+
+error[E0425]: cannot find function `a` in this scope
+  --> $DIR/check-args-on-fn-err-2.rs:2:5
+   |
+LL |     a((), 1i32 == 2u32);
+   |     ^ not found in this scope
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0308, E0425.
+For more information about an error, try `rustc --explain E0308`.
diff --git a/src/test/ui/typeck/check-args-on-fn-err.rs b/src/test/ui/typeck/check-args-on-fn-err.rs
new file mode 100644
index 00000000000..04b98ddd952
--- /dev/null
+++ b/src/test/ui/typeck/check-args-on-fn-err.rs
@@ -0,0 +1,6 @@
+fn main() {
+    unknown(1, |glyf| {
+        //~^ ERROR: cannot find function `unknown` in this scope
+        let actual = glyf;
+    });
+}
diff --git a/src/test/ui/typeck/check-args-on-fn-err.stderr b/src/test/ui/typeck/check-args-on-fn-err.stderr
new file mode 100644
index 00000000000..864d33e0e93
--- /dev/null
+++ b/src/test/ui/typeck/check-args-on-fn-err.stderr
@@ -0,0 +1,9 @@
+error[E0425]: cannot find function `unknown` in this scope
+  --> $DIR/check-args-on-fn-err.rs:2:5
+   |
+LL |     unknown(1, |glyf| {
+   |     ^^^^^^^ not found in this scope
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0425`.
diff --git a/src/test/ui/issues/issue-22375.rs b/src/test/ui/typeck/issue-22375.rs
index 21a1a4c8380..21a1a4c8380 100644
--- a/src/test/ui/issues/issue-22375.rs
+++ b/src/test/ui/typeck/issue-22375.rs
diff --git a/src/test/ui/typeck/issue-96530.rs b/src/test/ui/typeck/issue-96530.rs
new file mode 100644
index 00000000000..4ab93ab4938
--- /dev/null
+++ b/src/test/ui/typeck/issue-96530.rs
@@ -0,0 +1,20 @@
+struct Person {
+    first_name: String,
+    age: u32,
+}
+
+fn first_woman(man: &Person) -> Person {
+    Person {
+        first_name: "Eve".to_string(),
+        ..man.clone() //~ ERROR: mismatched types
+    }
+}
+
+fn main() {
+    let adam = Person {
+        first_name: "Adam".to_string(),
+        age: 0,
+    };
+
+    let eve = first_woman(&adam);
+}
diff --git a/src/test/ui/typeck/issue-96530.stderr b/src/test/ui/typeck/issue-96530.stderr
new file mode 100644
index 00000000000..4b4568b1de9
--- /dev/null
+++ b/src/test/ui/typeck/issue-96530.stderr
@@ -0,0 +1,9 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-96530.rs:9:11
+   |
+LL |         ..man.clone()
+   |           ^^^^^^^^^^^ expected struct `Person`, found `&Person`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/typeck/quiet-type-err-let-binding.rs b/src/test/ui/typeck/quiet-type-err-let-binding.rs
new file mode 100644
index 00000000000..a6eab536a6b
--- /dev/null
+++ b/src/test/ui/typeck/quiet-type-err-let-binding.rs
@@ -0,0 +1,17 @@
+// fn foo() -> String {
+//    String::new()
+// }
+
+fn test(s: &str) {
+    println!("{}", s);
+}
+
+fn test2(s: String) {
+    println!("{}", s);
+}
+
+fn main() {
+    let x = foo(); //~ERROR cannot find function `foo` in this scope
+    test(&x);
+    test2(x); // Does not complain about `x` being a `&str`.
+}
diff --git a/src/test/ui/typeck/quiet-type-err-let-binding.stderr b/src/test/ui/typeck/quiet-type-err-let-binding.stderr
new file mode 100644
index 00000000000..ad7f85e01ec
--- /dev/null
+++ b/src/test/ui/typeck/quiet-type-err-let-binding.stderr
@@ -0,0 +1,9 @@
+error[E0425]: cannot find function `foo` in this scope
+  --> $DIR/quiet-type-err-let-binding.rs:14:13
+   |
+LL |     let x = foo();
+   |             ^^^ not found in this scope
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0425`.
diff --git a/src/test/ui/typeck/typeck_type_placeholder_item.rs b/src/test/ui/typeck/typeck_type_placeholder_item.rs
index 22fedb22d66..b96c5271339 100644
--- a/src/test/ui/typeck/typeck_type_placeholder_item.rs
+++ b/src/test/ui/typeck/typeck_type_placeholder_item.rs
@@ -220,3 +220,11 @@ fn value() -> Option<&'static _> {
 
 const _: Option<_> = map(value);
 //~^ ERROR the placeholder `_` is not allowed within types on item signatures for constants
+
+fn evens_squared(n: usize) -> _ {
+//~^ ERROR the placeholder `_` is not allowed within types on item signatures for return types
+    (1..n).filter(|x| x % 2 == 0).map(|x| x * x)
+}
+
+const _: _ = (1..10).filter(|x| x % 2 == 0).map(|x| x * x);
+//~^ ERROR the placeholder `_` is not allowed within types on item signatures for constants
diff --git a/src/test/ui/typeck/typeck_type_placeholder_item.stderr b/src/test/ui/typeck/typeck_type_placeholder_item.stderr
index c57f71b8057..bc02547c65e 100644
--- a/src/test/ui/typeck/typeck_type_placeholder_item.stderr
+++ b/src/test/ui/typeck/typeck_type_placeholder_item.stderr
@@ -428,6 +428,27 @@ LL | const _: Option<_> = map(value);
    |          not allowed in type signatures
    |          help: replace with the correct type: `Option<u8>`
 
+error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types
+  --> $DIR/typeck_type_placeholder_item.rs:224:31
+   |
+LL | fn evens_squared(n: usize) -> _ {
+   |                               ^
+   |                               |
+   |                               not allowed in type signatures
+   |                               help: replace with an appropriate return type: `impl Iterator<Item = usize>`
+
+error[E0121]: the placeholder `_` is not allowed within types on item signatures for constants
+  --> $DIR/typeck_type_placeholder_item.rs:229:10
+   |
+LL | const _: _ = (1..10).filter(|x| x % 2 == 0).map(|x| x * x);
+   |          ^ not allowed in type signatures
+   |
+note: however, the inferred type `Map<Filter<Range<i32>, [closure@typeck_type_placeholder_item.rs:229:29]>, [closure@typeck_type_placeholder_item.rs:229:49]>` cannot be named
+  --> $DIR/typeck_type_placeholder_item.rs:229:14
+   |
+LL | const _: _ = (1..10).filter(|x| x % 2 == 0).map(|x| x * x);
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
 error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions
   --> $DIR/typeck_type_placeholder_item.rs:140:31
    |
@@ -636,7 +657,7 @@ LL |     const D: _ = 42;
    |              not allowed in type signatures
    |              help: replace with the correct type: `i32`
 
-error: aborting due to 69 previous errors
+error: aborting due to 71 previous errors
 
 Some errors have detailed explanations: E0121, E0282, E0403.
 For more information about an error, try `rustc --explain E0121`.
diff --git a/src/test/ui/unboxed-closures/non-tupled-call.rs b/src/test/ui/unboxed-closures/non-tupled-call.rs
new file mode 100644
index 00000000000..08bea4f1678
--- /dev/null
+++ b/src/test/ui/unboxed-closures/non-tupled-call.rs
@@ -0,0 +1,17 @@
+#![feature(fn_traits, unboxed_closures, tuple_trait)]
+
+use std::default::Default;
+use std::marker::Tuple;
+
+fn wrap<P: Tuple + Default, T>(func: impl Fn<P, Output = T>) {
+    let x: P = Default::default();
+    // Should be: `func.call(x);`
+    func(x);
+    //~^ ERROR cannot use call notation; the first type parameter for the function trait is neither a tuple nor unit
+}
+
+fn foo() {}
+
+fn main() {
+    wrap(foo);
+}
diff --git a/src/test/ui/unboxed-closures/non-tupled-call.stderr b/src/test/ui/unboxed-closures/non-tupled-call.stderr
new file mode 100644
index 00000000000..35ac9ebe291
--- /dev/null
+++ b/src/test/ui/unboxed-closures/non-tupled-call.stderr
@@ -0,0 +1,9 @@
+error[E0059]: cannot use call notation; the first type parameter for the function trait is neither a tuple nor unit
+  --> $DIR/non-tupled-call.rs:9:5
+   |
+LL |     func(x);
+   |     ^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0059`.
diff --git a/src/tools/cargo b/src/tools/cargo
-Subproject c994a4a638370bc7e0ffcbb0e2865afdfa7d441
+Subproject 2381cbdb4e9b07090f552d34a44a529b6e620e4
diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs
index 07b80b8baac..a4f1167bf9d 100644
--- a/src/tools/compiletest/src/common.rs
+++ b/src/tools/compiletest/src/common.rs
@@ -617,6 +617,6 @@ pub fn output_base_name(config: &Config, testpaths: &TestPaths, revision: Option
 
 /// Absolute path to the directory to use for incremental compilation. Example:
 ///   /path/to/build/host-triple/test/ui/relative/testname.mode/testname.inc
-pub fn incremental_dir(config: &Config, testpaths: &TestPaths) -> PathBuf {
-    output_base_name(config, testpaths, None).with_extension("inc")
+pub fn incremental_dir(config: &Config, testpaths: &TestPaths, revision: Option<&str>) -> PathBuf {
+    output_base_name(config, testpaths, revision).with_extension("inc")
 }
diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs
index 72a43108dc4..7a3c0d28fc3 100644
--- a/src/tools/compiletest/src/runtest.rs
+++ b/src/tools/compiletest/src/runtest.rs
@@ -117,8 +117,12 @@ pub fn run(config: Config, testpaths: &TestPaths, revision: Option<&str>) {
     }
     debug!("running {:?}", testpaths.file.display());
     let mut props = TestProps::from_file(&testpaths.file, revision, &config);
+
+    // For non-incremental (i.e. regular UI) tests, the incremental directory
+    // takes into account the revision name, since the revisions are independent
+    // of each other and can race.
     if props.incremental {
-        props.incremental_dir = Some(incremental_dir(&config, testpaths));
+        props.incremental_dir = Some(incremental_dir(&config, testpaths, revision));
     }
 
     let cx = TestCx { config: &config, props: &props, testpaths, revision };
@@ -2299,6 +2303,8 @@ impl<'test> TestCx<'test> {
         } else {
             filecheck.args(&["--check-prefixes", &prefixes]);
         }
+        // Provide more context on failures.
+        filecheck.args(&["--dump-input-context", "100"]);
         self.compose_and_run(filecheck, "", None, None)
     }
 
diff --git a/src/tools/miri/CONTRIBUTING.md b/src/tools/miri/CONTRIBUTING.md
index 9d61cc4e2d5..5b538691de1 100644
--- a/src/tools/miri/CONTRIBUTING.md
+++ b/src/tools/miri/CONTRIBUTING.md
@@ -232,16 +232,16 @@ You can also directly run Miri on a Rust source file:
 
 ## Advanced topic: Syncing with the rustc repo
 
-We use the [`josh` proxy](https://github.com/josh-project/josh) to transmit
-changes between the rustc and Miri repositories. For now, the latest git version
-of josh needs to be built from source. This downloads and runs josh:
+We use the [`josh` proxy](https://github.com/josh-project/josh) to transmit changes between the
+rustc and Miri repositories.
 
 ```sh
-git clone https://github.com/josh-project/josh
-cd josh
-cargo run --release -p josh-proxy -- --local=local --remote=https://github.com --no-background
+cargo +stable install josh-proxy --git https://github.com/josh-project/josh --tag r22.12.06
+josh-proxy --local=$HOME/.cache/josh --remote=https://github.com --no-background
 ```
 
+This uses a directory `$HOME/.cache/josh` as a cache, to speed up repeated pulling/pushing.
+
 ### Importing changes from the rustc repo
 
 Josh needs to be running, as described above.
diff --git a/src/tools/miri/README.md b/src/tools/miri/README.md
index dac0a9820b9..48581f6bbff 100644
--- a/src/tools/miri/README.md
+++ b/src/tools/miri/README.md
@@ -399,6 +399,8 @@ to Miri failing to detect cases of undefined behavior in a program.
 * `-Zmiri-track-weak-memory-loads` shows a backtrace when weak memory emulation returns an outdated
   value from a load. This can help diagnose problems that disappear under
   `-Zmiri-disable-weak-memory-emulation`.
+* `-Zmiri-force-page-size=<num>` overrides the default page size for an architecture, in multiples of 1k.
+  `4` is default for most targets. This value should always be a power of 2 and nonzero.
 
 [function ABI]: https://doc.rust-lang.org/reference/items/functions.html#extern-function-qualifier
 
@@ -574,6 +576,21 @@ extern "Rust" {
 
     /// Miri-provided extern function to deallocate memory.
     fn miri_dealloc(ptr: *mut u8, size: usize, align: usize);
+
+    /// Convert a path from the host Miri runs on to the target Miri interprets.
+    /// Performs conversion of path separators as needed.
+    ///
+    /// Usually Miri performs this kind of conversion automatically. However, manual conversion
+    /// might be necessary when reading an environment variable that was set on the host
+    /// (such as TMPDIR) and using it as a target path.
+    ///
+    /// Only works with isolation disabled.
+    ///
+    /// `in` must point to a null-terminated string, and will be read as the input host path.
+    /// `out` must point to at least `out_size` many bytes, and the result will be stored there
+    /// with a null terminator.
+    /// Returns 0 if the `out` buffer was large enough, and the required size otherwise.
+    fn miri_host_to_target_path(path: *const i8, out: *mut i8, out_size: usize) -> usize;
 }
 ```
 
@@ -639,6 +656,7 @@ Definite bugs found:
 * [Data race in `thread::scope`](https://github.com/rust-lang/rust/issues/98498)
 * [`regex` incorrectly handling unaligned `Vec<u8>` buffers](https://www.reddit.com/r/rust/comments/vq3mmu/comment/ienc7t0?context=3)
 * [Incorrect use of `compare_exchange_weak` in `once_cell`](https://github.com/matklad/once_cell/issues/186)
+* [Dropping with unaligned pointers in `vec::IntoIter`](https://github.com/rust-lang/rust/pull/106084)
 
 Violations of [Stacked Borrows] found that are likely bugs (but Stacked Borrows is currently just an experiment):
 
diff --git a/src/tools/miri/miri b/src/tools/miri/miri
index a259576ed42..0c0bbbc7020 100755
--- a/src/tools/miri/miri
+++ b/src/tools/miri/miri
@@ -243,7 +243,7 @@ if [ -z "$CARGO_PROFILE_DEV_OPT_LEVEL" ]; then
     export CARGO_PROFILE_DEV_OPT_LEVEL=2
 fi
 # Enable rustc-specific lints (ignored without `-Zunstable-options`).
-export RUSTFLAGS="-Zunstable-options -Wrustc::internal $RUSTFLAGS"
+export RUSTFLAGS="-Zunstable-options -Wrustc::internal -Wrust_2018_idioms -Wunused_lifetimes -Wsemicolon_in_expressions_from_macros $RUSTFLAGS"
 # We set the rpath so that Miri finds the private rustc libraries it needs.
 export RUSTFLAGS="-C link-args=-Wl,-rpath,$LIBDIR $RUSTFLAGS"
 
diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version
index 8dd18ae98e6..ee75e7a2932 100644
--- a/src/tools/miri/rust-version
+++ b/src/tools/miri/rust-version
@@ -1 +1 @@
-203c8765ea33c65d888febe0e8219c4bb11b0d89
+4f4d0586ad20c66a16d547581ca379beafece93a
diff --git a/src/tools/miri/src/bin/miri.rs b/src/tools/miri/src/bin/miri.rs
index fce95b987f7..8c01748613c 100644
--- a/src/tools/miri/src/bin/miri.rs
+++ b/src/tools/miri/src/bin/miri.rs
@@ -512,6 +512,18 @@ fn main() {
             };
 
             miri_config.num_cpus = num_cpus;
+        } else if let Some(param) = arg.strip_prefix("-Zmiri-force-page-size=") {
+            let page_size = match param.parse::<u64>() {
+                Ok(i) =>
+                    if i.is_power_of_two() {
+                        i * 1024
+                    } else {
+                        show_error!("-Zmiri-force-page-size requires a power of 2: {}", i)
+                    },
+                Err(err) => show_error!("-Zmiri-force-page-size requires a `u64`: {}", err),
+            };
+
+            miri_config.page_size = Some(page_size);
         } else {
             // Forward to rustc.
             rustc_args.push(arg);
diff --git a/src/tools/miri/src/borrow_tracker/mod.rs b/src/tools/miri/src/borrow_tracker/mod.rs
index f896a337f42..9f6cbe7f3c7 100644
--- a/src/tools/miri/src/borrow_tracker/mod.rs
+++ b/src/tools/miri/src/borrow_tracker/mod.rs
@@ -264,7 +264,11 @@ impl GlobalStateInner {
 
 impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
 pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
-    fn retag_ptr_value(&mut self, kind: RetagKind, val: &ImmTy<'tcx, Provenance>) -> InterpResult<'tcx, ImmTy<'tcx, Provenance>> {
+    fn retag_ptr_value(
+        &mut self,
+        kind: RetagKind,
+        val: &ImmTy<'tcx, Provenance>,
+    ) -> InterpResult<'tcx, ImmTy<'tcx, Provenance>> {
         let this = self.eval_context_mut();
         let method = this.machine.borrow_tracker.as_ref().unwrap().borrow().borrow_tracker_method;
         match method {
@@ -272,7 +276,11 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         }
     }
 
-    fn retag_place_contents(&mut self, kind: RetagKind, place: &PlaceTy<'tcx, Provenance>) -> InterpResult<'tcx> {
+    fn retag_place_contents(
+        &mut self,
+        kind: RetagKind,
+        place: &PlaceTy<'tcx, Provenance>,
+    ) -> InterpResult<'tcx> {
         let this = self.eval_context_mut();
         let method = this.machine.borrow_tracker.as_ref().unwrap().borrow().borrow_tracker_method;
         match method {
diff --git a/src/tools/miri/src/borrow_tracker/stacked_borrows/diagnostics.rs b/src/tools/miri/src/borrow_tracker/stacked_borrows/diagnostics.rs
index 24b3489e0d1..5f132bf11a9 100644
--- a/src/tools/miri/src/borrow_tracker/stacked_borrows/diagnostics.rs
+++ b/src/tools/miri/src/borrow_tracker/stacked_borrows/diagnostics.rs
@@ -462,7 +462,9 @@ impl<'history, 'ecx, 'mir, 'tcx> DiagnosticCx<'history, 'ecx, 'mir, 'tcx> {
             Operation::Retag(RetagOp { orig_tag, permission, new_tag, .. }) => {
                 let permission = permission
                     .expect("start_grant should set the current permission before popping a tag");
-                format!(" due to {permission:?} retag from {orig_tag:?} (that retag created {new_tag:?})")
+                format!(
+                    " due to {permission:?} retag from {orig_tag:?} (that retag created {new_tag:?})"
+                )
             }
         };
 
diff --git a/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs b/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs
index ffbc0086402..bcdf2e75179 100644
--- a/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs
+++ b/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs
@@ -14,6 +14,7 @@ use rustc_middle::mir::{Mutability, RetagKind};
 use rustc_middle::ty::{
     self,
     layout::{HasParamEnv, LayoutOf},
+    Ty,
 };
 use rustc_target::abi::{Abi, Size};
 
@@ -64,7 +65,7 @@ impl NewPermission {
     /// A key function: determine the permissions to grant at a retag for the given kind of
     /// reference/pointer.
     fn from_ref_ty<'tcx>(
-        ty: ty::Ty<'tcx>,
+        ty: Ty<'tcx>,
         kind: RetagKind,
         cx: &crate::MiriInterpCx<'_, 'tcx>,
     ) -> Self {
@@ -864,7 +865,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
             RetagKind::FnEntry => unreachable!(),
             RetagKind::Raw | RetagKind::Default => RetagCause::Normal,
         };
-        this.sb_retag_reference(&val, new_perm, retag_cause)
+        this.sb_retag_reference(val, new_perm, retag_cause)
     }
 
     fn sb_retag_place_contents(
diff --git a/src/tools/miri/src/concurrency/data_race.rs b/src/tools/miri/src/concurrency/data_race.rs
index bcbf45a3d24..96463279668 100644
--- a/src/tools/miri/src/concurrency/data_race.rs
+++ b/src/tools/miri/src/concurrency/data_race.rs
@@ -50,8 +50,10 @@ use rustc_ast::Mutability;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_index::vec::{Idx, IndexVec};
 use rustc_middle::mir;
+use rustc_span::Span;
 use rustc_target::abi::{Align, Size};
 
+use crate::diagnostics::RacingOp;
 use crate::*;
 
 use super::{
@@ -144,8 +146,8 @@ impl ThreadClockSet {
     /// Increment the happens-before clock at a
     /// known index.
     #[inline]
-    fn increment_clock(&mut self, index: VectorIdx) {
-        self.clock.increment_index(index);
+    fn increment_clock(&mut self, index: VectorIdx, current_span: Span) {
+        self.clock.increment_index(index, current_span);
     }
 
     /// Join the happens-before clock with that of
@@ -356,13 +358,9 @@ impl MemoryCellClocks {
         index: VectorIdx,
     ) -> Result<(), DataRace> {
         log::trace!("Atomic read with vectors: {:#?} :: {:#?}", self, clocks);
-        if self.write <= clocks.clock[self.write_index] {
-            let atomic = self.atomic_mut();
-            atomic.read_vector.set_at_index(&clocks.clock, index);
-            Ok(())
-        } else {
-            Err(DataRace)
-        }
+        let atomic = self.atomic_mut();
+        atomic.read_vector.set_at_index(&clocks.clock, index);
+        if self.write <= clocks.clock[self.write_index] { Ok(()) } else { Err(DataRace) }
     }
 
     /// Detect data-races with an atomic write, either with a non-atomic read or with
@@ -373,9 +371,9 @@ impl MemoryCellClocks {
         index: VectorIdx,
     ) -> Result<(), DataRace> {
         log::trace!("Atomic write with vectors: {:#?} :: {:#?}", self, clocks);
+        let atomic = self.atomic_mut();
+        atomic.write_vector.set_at_index(&clocks.clock, index);
         if self.write <= clocks.clock[self.write_index] && self.read <= clocks.clock {
-            let atomic = self.atomic_mut();
-            atomic.write_vector.set_at_index(&clocks.clock, index);
             Ok(())
         } else {
             Err(DataRace)
@@ -386,22 +384,22 @@ impl MemoryCellClocks {
     /// returns true if a data-race is detected.
     fn read_race_detect(
         &mut self,
-        clocks: &ThreadClockSet,
+        clocks: &mut ThreadClockSet,
         index: VectorIdx,
+        current_span: Span,
     ) -> Result<(), DataRace> {
         log::trace!("Unsynchronized read with vectors: {:#?} :: {:#?}", self, clocks);
+        if !current_span.is_dummy() {
+            clocks.clock[index].span = current_span;
+        }
         if self.write <= clocks.clock[self.write_index] {
             let race_free = if let Some(atomic) = self.atomic() {
                 atomic.write_vector <= clocks.clock
             } else {
                 true
             };
-            if race_free {
-                self.read.set_at_index(&clocks.clock, index);
-                Ok(())
-            } else {
-                Err(DataRace)
-            }
+            self.read.set_at_index(&clocks.clock, index);
+            if race_free { Ok(()) } else { Err(DataRace) }
         } else {
             Err(DataRace)
         }
@@ -411,21 +409,25 @@ impl MemoryCellClocks {
     /// returns true if a data-race is detected.
     fn write_race_detect(
         &mut self,
-        clocks: &ThreadClockSet,
+        clocks: &mut ThreadClockSet,
         index: VectorIdx,
         write_type: WriteType,
+        current_span: Span,
     ) -> Result<(), DataRace> {
         log::trace!("Unsynchronized write with vectors: {:#?} :: {:#?}", self, clocks);
+        if !current_span.is_dummy() {
+            clocks.clock[index].span = current_span;
+        }
         if self.write <= clocks.clock[self.write_index] && self.read <= clocks.clock {
             let race_free = if let Some(atomic) = self.atomic() {
                 atomic.write_vector <= clocks.clock && atomic.read_vector <= clocks.clock
             } else {
                 true
             };
+            self.write = clocks.clock[index];
+            self.write_index = index;
+            self.write_type = write_type;
             if race_free {
-                self.write = clocks.clock[index];
-                self.write_index = index;
-                self.write_type = write_type;
                 self.read.set_zero_vector();
                 Ok(())
             } else {
@@ -621,30 +623,35 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: MiriInterpCxExt<'mir, 'tcx> {
     /// Update the data-race detector for an atomic fence on the current thread.
     fn atomic_fence(&mut self, atomic: AtomicFenceOrd) -> InterpResult<'tcx> {
         let this = self.eval_context_mut();
+        let current_span = this.machine.current_span();
         if let Some(data_race) = &mut this.machine.data_race {
-            data_race.maybe_perform_sync_operation(&this.machine.threads, |index, mut clocks| {
-                log::trace!("Atomic fence on {:?} with ordering {:?}", index, atomic);
-
-                // Apply data-race detection for the current fences
-                // this treats AcqRel and SeqCst as the same as an acquire
-                // and release fence applied in the same timestamp.
-                if atomic != AtomicFenceOrd::Release {
-                    // Either Acquire | AcqRel | SeqCst
-                    clocks.apply_acquire_fence();
-                }
-                if atomic != AtomicFenceOrd::Acquire {
-                    // Either Release | AcqRel | SeqCst
-                    clocks.apply_release_fence();
-                }
-                if atomic == AtomicFenceOrd::SeqCst {
-                    data_race.last_sc_fence.borrow_mut().set_at_index(&clocks.clock, index);
-                    clocks.fence_seqcst.join(&data_race.last_sc_fence.borrow());
-                    clocks.write_seqcst.join(&data_race.last_sc_write.borrow());
-                }
+            data_race.maybe_perform_sync_operation(
+                &this.machine.threads,
+                current_span,
+                |index, mut clocks| {
+                    log::trace!("Atomic fence on {:?} with ordering {:?}", index, atomic);
+
+                    // Apply data-race detection for the current fences
+                    // this treats AcqRel and SeqCst as the same as an acquire
+                    // and release fence applied in the same timestamp.
+                    if atomic != AtomicFenceOrd::Release {
+                        // Either Acquire | AcqRel | SeqCst
+                        clocks.apply_acquire_fence();
+                    }
+                    if atomic != AtomicFenceOrd::Acquire {
+                        // Either Release | AcqRel | SeqCst
+                        clocks.apply_release_fence();
+                    }
+                    if atomic == AtomicFenceOrd::SeqCst {
+                        data_race.last_sc_fence.borrow_mut().set_at_index(&clocks.clock, index);
+                        clocks.fence_seqcst.join(&data_race.last_sc_fence.borrow());
+                        clocks.write_seqcst.join(&data_race.last_sc_write.borrow());
+                    }
 
-                // Increment timestamp in case of release semantics.
-                Ok(atomic != AtomicFenceOrd::Acquire)
-            })
+                    // Increment timestamp in case of release semantics.
+                    Ok(atomic != AtomicFenceOrd::Acquire)
+                },
+            )
         } else {
             Ok(())
         }
@@ -682,6 +689,7 @@ impl VClockAlloc {
         thread_mgr: &ThreadManager<'_, '_>,
         len: Size,
         kind: MemoryKind<MiriMemoryKind>,
+        current_span: Span,
     ) -> VClockAlloc {
         let (alloc_timestamp, alloc_index) = match kind {
             // User allocated and stack memory should track allocation.
@@ -693,7 +701,8 @@ impl VClockAlloc {
             )
             | MemoryKind::Stack => {
                 let (alloc_index, clocks) = global.current_thread_state(thread_mgr);
-                let alloc_timestamp = clocks.clock[alloc_index];
+                let mut alloc_timestamp = clocks.clock[alloc_index];
+                alloc_timestamp.span = current_span;
                 (alloc_timestamp, alloc_index)
             }
             // Other global memory should trace races but be allocated at the 0 timestamp.
@@ -704,7 +713,7 @@ impl VClockAlloc {
                 | MiriMemoryKind::ExternStatic
                 | MiriMemoryKind::Tls,
             )
-            | MemoryKind::CallerLocation => (0, VectorIdx::MAX_INDEX),
+            | MemoryKind::CallerLocation => (VTimestamp::ZERO, VectorIdx::MAX_INDEX),
         };
         VClockAlloc {
             alloc_ranges: RefCell::new(RangeMap::new(
@@ -735,7 +744,7 @@ impl VClockAlloc {
                     let idx = l_remainder_slice
                         .iter()
                         .enumerate()
-                        .find_map(|(idx, &r)| if r == 0 { None } else { Some(idx) })
+                        .find_map(|(idx, &r)| if r == VTimestamp::ZERO { None } else { Some(idx) })
                         .expect("Invalid VClock Invariant");
                     Some(idx + r_slice.len())
                 } else {
@@ -762,7 +771,7 @@ impl VClockAlloc {
     ) -> InterpResult<'tcx> {
         let (current_index, current_clocks) = global.current_thread_state(thread_mgr);
         let write_clock;
-        let (other_action, other_thread, _other_clock) = if range.write
+        let (other_action, other_thread, other_clock) = if range.write
             > current_clocks.clock[range.write_index]
         {
             // Convert the write action into the vector clock it
@@ -799,14 +808,19 @@ impl VClockAlloc {
         let other_thread_info = global.print_thread_metadata(thread_mgr, other_thread);
 
         // Throw the data-race detection.
-        throw_ub_format!(
-            "Data race detected between {} on {} and {} on {} at {:?}",
-            action,
-            current_thread_info,
-            other_action,
-            other_thread_info,
-            ptr_dbg,
-        )
+        Err(err_machine_stop!(TerminationInfo::DataRace {
+            ptr: ptr_dbg,
+            op1: RacingOp {
+                action: other_action.to_string(),
+                thread_info: other_thread_info,
+                span: other_clock.as_slice()[other_thread.index()].span_data(),
+            },
+            op2: RacingOp {
+                action: action.to_string(),
+                thread_info: current_thread_info,
+                span: current_clocks.clock.as_slice()[current_index.index()].span_data(),
+            },
+        }))?
     }
 
     /// Detect racing atomic read and writes (not data races)
@@ -840,12 +854,14 @@ impl VClockAlloc {
         range: AllocRange,
         machine: &MiriMachine<'_, '_>,
     ) -> InterpResult<'tcx> {
+        let current_span = machine.current_span();
         let global = machine.data_race.as_ref().unwrap();
         if global.race_detecting() {
-            let (index, clocks) = global.current_thread_state(&machine.threads);
+            let (index, mut clocks) = global.current_thread_state_mut(&machine.threads);
             let mut alloc_ranges = self.alloc_ranges.borrow_mut();
             for (offset, range) in alloc_ranges.iter_mut(range.start, range.size) {
-                if let Err(DataRace) = range.read_race_detect(&clocks, index) {
+                if let Err(DataRace) = range.read_race_detect(&mut clocks, index, current_span) {
+                    drop(clocks);
                     // Report data-race.
                     return Self::report_data_race(
                         global,
@@ -871,11 +887,15 @@ impl VClockAlloc {
         write_type: WriteType,
         machine: &mut MiriMachine<'_, '_>,
     ) -> InterpResult<'tcx> {
+        let current_span = machine.current_span();
         let global = machine.data_race.as_mut().unwrap();
         if global.race_detecting() {
-            let (index, clocks) = global.current_thread_state(&machine.threads);
+            let (index, mut clocks) = global.current_thread_state_mut(&machine.threads);
             for (offset, range) in self.alloc_ranges.get_mut().iter_mut(range.start, range.size) {
-                if let Err(DataRace) = range.write_race_detect(&clocks, index, write_type) {
+                if let Err(DataRace) =
+                    range.write_race_detect(&mut clocks, index, write_type, current_span)
+                {
+                    drop(clocks);
                     // Report data-race
                     return Self::report_data_race(
                         global,
@@ -1100,9 +1120,11 @@ trait EvalContextPrivExt<'mir, 'tcx: 'mir>: MiriInterpCxExt<'mir, 'tcx> {
                     size.bytes()
                 );
 
+                let current_span = this.machine.current_span();
                 // Perform the atomic operation.
                 data_race.maybe_perform_sync_operation(
                     &this.machine.threads,
+                    current_span,
                     |index, mut clocks| {
                         for (offset, range) in
                             alloc_meta.alloc_ranges.borrow_mut().iter_mut(base_offset, size)
@@ -1303,7 +1325,12 @@ impl GlobalState {
     // Hook for thread creation, enabled multi-threaded execution and marks
     // the current thread timestamp as happening-before the current thread.
     #[inline]
-    pub fn thread_created(&mut self, thread_mgr: &ThreadManager<'_, '_>, thread: ThreadId) {
+    pub fn thread_created(
+        &mut self,
+        thread_mgr: &ThreadManager<'_, '_>,
+        thread: ThreadId,
+        current_span: Span,
+    ) {
         let current_index = self.current_index(thread_mgr);
 
         // Enable multi-threaded execution, there are now at least two threads
@@ -1320,7 +1347,7 @@ impl GlobalState {
             // Now re-configure the re-use candidate, increment the clock
             // for the new sync use of the vector.
             let vector_clocks = self.vector_clocks.get_mut();
-            vector_clocks[reuse_index].increment_clock(reuse_index);
+            vector_clocks[reuse_index].increment_clock(reuse_index, current_span);
 
             // Locate the old thread the vector was associated with and update
             // it to represent the new thread instead.
@@ -1360,8 +1387,8 @@ impl GlobalState {
 
         // Advance both threads after the synchronized operation.
         // Both operations are considered to have release semantics.
-        current.increment_clock(current_index);
-        created.increment_clock(created_index);
+        current.increment_clock(current_index, current_span);
+        created.increment_clock(created_index, current_span);
     }
 
     /// Hook on a thread join to update the implicit happens-before relation between the joined
@@ -1427,13 +1454,13 @@ impl GlobalState {
     /// This should be called strictly before any calls to
     /// `thread_joined`.
     #[inline]
-    pub fn thread_terminated(&mut self, thread_mgr: &ThreadManager<'_, '_>) {
+    pub fn thread_terminated(&mut self, thread_mgr: &ThreadManager<'_, '_>, current_span: Span) {
         let current_index = self.current_index(thread_mgr);
 
         // Increment the clock to a unique termination timestamp.
         let vector_clocks = self.vector_clocks.get_mut();
         let current_clocks = &mut vector_clocks[current_index];
-        current_clocks.increment_clock(current_index);
+        current_clocks.increment_clock(current_index, current_span);
 
         // Load the current thread id for the executing vector.
         let vector_info = self.vector_info.get_mut();
@@ -1462,13 +1489,14 @@ impl GlobalState {
     fn maybe_perform_sync_operation<'tcx>(
         &self,
         thread_mgr: &ThreadManager<'_, '_>,
+        current_span: Span,
         op: impl FnOnce(VectorIdx, RefMut<'_, ThreadClockSet>) -> InterpResult<'tcx, bool>,
     ) -> InterpResult<'tcx> {
         if self.multi_threaded.get() {
             let (index, clocks) = self.current_thread_state_mut(thread_mgr);
             if op(index, clocks)? {
                 let (_, mut clocks) = self.current_thread_state_mut(thread_mgr);
-                clocks.increment_clock(index);
+                clocks.increment_clock(index, current_span);
             }
         }
         Ok(())
@@ -1501,10 +1529,10 @@ impl GlobalState {
     /// since an acquire operation should have occurred before, however
     /// for futex & condvar operations this is not the case and this
     /// operation must be used.
-    pub fn validate_lock_release(&self, lock: &mut VClock, thread: ThreadId) {
+    pub fn validate_lock_release(&self, lock: &mut VClock, thread: ThreadId, current_span: Span) {
         let (index, mut clocks) = self.load_thread_state_mut(thread);
         lock.clone_from(&clocks.clock);
-        clocks.increment_clock(index);
+        clocks.increment_clock(index, current_span);
     }
 
     /// Release a lock handle, express that this happens-before
@@ -1514,10 +1542,15 @@ impl GlobalState {
     /// For normal locks this should be equivalent to `validate_lock_release`.
     /// This function only exists for joining over the set of concurrent readers
     /// in a read-write lock and should not be used for anything else.
-    pub fn validate_lock_release_shared(&self, lock: &mut VClock, thread: ThreadId) {
+    pub fn validate_lock_release_shared(
+        &self,
+        lock: &mut VClock,
+        thread: ThreadId,
+        current_span: Span,
+    ) {
         let (index, mut clocks) = self.load_thread_state_mut(thread);
         lock.join(&clocks.clock);
-        clocks.increment_clock(index);
+        clocks.increment_clock(index, current_span);
     }
 
     /// Load the vector index used by the given thread as well as the set of vector clocks
diff --git a/src/tools/miri/src/concurrency/init_once.rs b/src/tools/miri/src/concurrency/init_once.rs
index 9c9d505297c..867683d3552 100644
--- a/src/tools/miri/src/concurrency/init_once.rs
+++ b/src/tools/miri/src/concurrency/init_once.rs
@@ -160,6 +160,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
     fn init_once_complete(&mut self, id: InitOnceId) -> InterpResult<'tcx> {
         let this = self.eval_context_mut();
         let current_thread = this.get_active_thread();
+        let current_span = this.machine.current_span();
         let init_once = &mut this.machine.threads.sync.init_onces[id];
 
         assert_eq!(
@@ -172,7 +173,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
 
         // Each complete happens-before the end of the wait
         if let Some(data_race) = &this.machine.data_race {
-            data_race.validate_lock_release(&mut init_once.data_race, current_thread);
+            data_race.validate_lock_release(&mut init_once.data_race, current_thread, current_span);
         }
 
         // Wake up everyone.
@@ -188,6 +189,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
     fn init_once_fail(&mut self, id: InitOnceId) -> InterpResult<'tcx> {
         let this = self.eval_context_mut();
         let current_thread = this.get_active_thread();
+        let current_span = this.machine.current_span();
         let init_once = &mut this.machine.threads.sync.init_onces[id];
         assert_eq!(
             init_once.status,
@@ -197,7 +199,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
 
         // Each complete happens-before the end of the wait
         if let Some(data_race) = &this.machine.data_race {
-            data_race.validate_lock_release(&mut init_once.data_race, current_thread);
+            data_race.validate_lock_release(&mut init_once.data_race, current_thread, current_span);
         }
 
         // Wake up one waiting thread, so they can go ahead and try to init this.
diff --git a/src/tools/miri/src/concurrency/sync.rs b/src/tools/miri/src/concurrency/sync.rs
index 402c9ce6fc9..b9620523974 100644
--- a/src/tools/miri/src/concurrency/sync.rs
+++ b/src/tools/miri/src/concurrency/sync.rs
@@ -359,6 +359,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
     /// return `None`.
     fn mutex_unlock(&mut self, id: MutexId, expected_owner: ThreadId) -> Option<usize> {
         let this = self.eval_context_mut();
+        let current_span = this.machine.current_span();
         let mutex = &mut this.machine.threads.sync.mutexes[id];
         if let Some(current_owner) = mutex.owner {
             // Mutex is locked.
@@ -375,7 +376,11 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 // The mutex is completely unlocked. Try transfering ownership
                 // to another thread.
                 if let Some(data_race) = &this.machine.data_race {
-                    data_race.validate_lock_release(&mut mutex.data_race, current_owner);
+                    data_race.validate_lock_release(
+                        &mut mutex.data_race,
+                        current_owner,
+                        current_span,
+                    );
                 }
                 this.mutex_dequeue_and_lock(id);
             }
@@ -454,6 +459,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
     /// Returns `true` if succeeded, `false` if this `reader` did not hold the lock.
     fn rwlock_reader_unlock(&mut self, id: RwLockId, reader: ThreadId) -> bool {
         let this = self.eval_context_mut();
+        let current_span = this.machine.current_span();
         let rwlock = &mut this.machine.threads.sync.rwlocks[id];
         match rwlock.readers.entry(reader) {
             Entry::Occupied(mut entry) => {
@@ -470,7 +476,11 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
             Entry::Vacant(_) => return false, // we did not even own this lock
         }
         if let Some(data_race) = &this.machine.data_race {
-            data_race.validate_lock_release_shared(&mut rwlock.data_race_reader, reader);
+            data_race.validate_lock_release_shared(
+                &mut rwlock.data_race_reader,
+                reader,
+                current_span,
+            );
         }
 
         // The thread was a reader. If the lock is not held any more, give it to a writer.
@@ -511,6 +521,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
     #[inline]
     fn rwlock_writer_unlock(&mut self, id: RwLockId, expected_writer: ThreadId) -> bool {
         let this = self.eval_context_mut();
+        let current_span = this.machine.current_span();
         let rwlock = &mut this.machine.threads.sync.rwlocks[id];
         if let Some(current_writer) = rwlock.writer {
             if current_writer != expected_writer {
@@ -523,8 +534,16 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
             //  since this writer happens-before both the union of readers once they are finished
             //  and the next writer
             if let Some(data_race) = &this.machine.data_race {
-                data_race.validate_lock_release(&mut rwlock.data_race, current_writer);
-                data_race.validate_lock_release(&mut rwlock.data_race_reader, current_writer);
+                data_race.validate_lock_release(
+                    &mut rwlock.data_race,
+                    current_writer,
+                    current_span,
+                );
+                data_race.validate_lock_release(
+                    &mut rwlock.data_race_reader,
+                    current_writer,
+                    current_span,
+                );
             }
             // The thread was a writer.
             //
@@ -595,12 +614,13 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
     fn condvar_signal(&mut self, id: CondvarId) -> Option<(ThreadId, CondvarLock)> {
         let this = self.eval_context_mut();
         let current_thread = this.get_active_thread();
+        let current_span = this.machine.current_span();
         let condvar = &mut this.machine.threads.sync.condvars[id];
         let data_race = &this.machine.data_race;
 
         // Each condvar signal happens-before the end of the condvar wake
         if let Some(data_race) = data_race {
-            data_race.validate_lock_release(&mut condvar.data_race, current_thread);
+            data_race.validate_lock_release(&mut condvar.data_race, current_thread, current_span);
         }
         condvar.waiters.pop_front().map(|waiter| {
             if let Some(data_race) = data_race {
@@ -628,12 +648,13 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
     fn futex_wake(&mut self, addr: u64, bitset: u32) -> Option<ThreadId> {
         let this = self.eval_context_mut();
         let current_thread = this.get_active_thread();
+        let current_span = this.machine.current_span();
         let futex = &mut this.machine.threads.sync.futexes.get_mut(&addr)?;
         let data_race = &this.machine.data_race;
 
         // Each futex-wake happens-before the end of the futex wait
         if let Some(data_race) = data_race {
-            data_race.validate_lock_release(&mut futex.data_race, current_thread);
+            data_race.validate_lock_release(&mut futex.data_race, current_thread, current_span);
         }
 
         // Wake up the first thread in the queue that matches any of the bits in the bitset.
diff --git a/src/tools/miri/src/concurrency/thread.rs b/src/tools/miri/src/concurrency/thread.rs
index 03f9ed351fb..9173eb3c4ee 100644
--- a/src/tools/miri/src/concurrency/thread.rs
+++ b/src/tools/miri/src/concurrency/thread.rs
@@ -13,6 +13,7 @@ use rustc_hir::def_id::DefId;
 use rustc_index::vec::{Idx, IndexVec};
 use rustc_middle::mir::Mutability;
 use rustc_middle::ty::layout::TyAndLayout;
+use rustc_span::Span;
 use rustc_target::spec::abi::Abi;
 
 use crate::concurrency::data_race;
@@ -617,6 +618,7 @@ impl<'mir, 'tcx: 'mir> ThreadManager<'mir, 'tcx> {
     fn thread_terminated(
         &mut self,
         mut data_race: Option<&mut data_race::GlobalState>,
+        current_span: Span,
     ) -> Vec<Pointer<Provenance>> {
         let mut free_tls_statics = Vec::new();
         {
@@ -634,7 +636,7 @@ impl<'mir, 'tcx: 'mir> ThreadManager<'mir, 'tcx> {
         }
         // Set the thread into a terminated state in the data-race detector.
         if let Some(ref mut data_race) = data_race {
-            data_race.thread_terminated(self);
+            data_race.thread_terminated(self, current_span);
         }
         // Check if we need to unblock any threads.
         let mut joined_threads = vec![]; // store which threads joined, we'll need it
@@ -813,8 +815,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
             let mut state = tls::TlsDtorsState::default();
             Box::new(move |m| state.on_stack_empty(m))
         });
+        let current_span = this.machine.current_span();
         if let Some(data_race) = &mut this.machine.data_race {
-            data_race.thread_created(&this.machine.threads, new_thread_id);
+            data_race.thread_created(&this.machine.threads, new_thread_id, current_span);
         }
 
         // Write the current thread-id, switch to the next thread later
@@ -1041,7 +1044,10 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         assert!(thread.stack.is_empty(), "only threads with an empty stack can be terminated");
         thread.state = ThreadState::Terminated;
 
-        for ptr in this.machine.threads.thread_terminated(this.machine.data_race.as_mut()) {
+        let current_span = this.machine.current_span();
+        for ptr in
+            this.machine.threads.thread_terminated(this.machine.data_race.as_mut(), current_span)
+        {
             this.deallocate_ptr(ptr.into(), None, MiriMemoryKind::Tls.into())?;
         }
         Ok(())
diff --git a/src/tools/miri/src/concurrency/vector_clock.rs b/src/tools/miri/src/concurrency/vector_clock.rs
index ba04991a588..ab4764dd1c8 100644
--- a/src/tools/miri/src/concurrency/vector_clock.rs
+++ b/src/tools/miri/src/concurrency/vector_clock.rs
@@ -1,6 +1,11 @@
 use rustc_index::vec::Idx;
+use rustc_span::{Span, SpanData, DUMMY_SP};
 use smallvec::SmallVec;
-use std::{cmp::Ordering, fmt::Debug, ops::Index};
+use std::{
+    cmp::Ordering,
+    fmt::Debug,
+    ops::{Index, IndexMut},
+};
 
 /// A vector clock index, this is associated with a thread id
 /// but in some cases one vector index may be shared with
@@ -40,9 +45,42 @@ impl From<u32> for VectorIdx {
 /// clock vectors larger than this will be stored on the heap
 const SMALL_VECTOR: usize = 4;
 
-/// The type of the time-stamps recorded in the data-race detector
-/// set to a type of unsigned integer
-pub type VTimestamp = u32;
+/// The time-stamps recorded in the data-race detector consist of both
+/// a 32-bit unsigned integer which is the actual timestamp, and a `Span`
+/// so that diagnostics can report what code was responsible for an operation.
+#[derive(Clone, Copy, Debug)]
+pub struct VTimestamp {
+    time: u32,
+    pub span: Span,
+}
+
+impl VTimestamp {
+    pub const ZERO: VTimestamp = VTimestamp { time: 0, span: DUMMY_SP };
+
+    pub fn span_data(&self) -> SpanData {
+        self.span.data()
+    }
+}
+
+impl PartialEq for VTimestamp {
+    fn eq(&self, other: &Self) -> bool {
+        self.time == other.time
+    }
+}
+
+impl Eq for VTimestamp {}
+
+impl PartialOrd for VTimestamp {
+    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
+        Some(self.cmp(other))
+    }
+}
+
+impl Ord for VTimestamp {
+    fn cmp(&self, other: &Self) -> Ordering {
+        self.time.cmp(&other.time)
+    }
+}
 
 /// A vector clock for detecting data-races, this is conceptually
 /// a map from a vector index (and thus a thread id) to a timestamp.
@@ -62,7 +100,7 @@ impl VClock {
     /// for a value at the given index
     pub fn new_with_index(index: VectorIdx, timestamp: VTimestamp) -> VClock {
         let len = index.index() + 1;
-        let mut vec = smallvec::smallvec![0; len];
+        let mut vec = smallvec::smallvec![VTimestamp::ZERO; len];
         vec[index.index()] = timestamp;
         VClock(vec)
     }
@@ -79,7 +117,7 @@ impl VClock {
     #[inline]
     fn get_mut_with_min_len(&mut self, min_len: usize) -> &mut [VTimestamp] {
         if self.0.len() < min_len {
-            self.0.resize(min_len, 0);
+            self.0.resize(min_len, VTimestamp::ZERO);
         }
         assert!(self.0.len() >= min_len);
         self.0.as_mut_slice()
@@ -88,11 +126,14 @@ impl VClock {
     /// Increment the vector clock at a known index
     /// this will panic if the vector index overflows
     #[inline]
-    pub fn increment_index(&mut self, idx: VectorIdx) {
+    pub fn increment_index(&mut self, idx: VectorIdx, current_span: Span) {
         let idx = idx.index();
         let mut_slice = self.get_mut_with_min_len(idx + 1);
         let idx_ref = &mut mut_slice[idx];
-        *idx_ref = idx_ref.checked_add(1).expect("Vector clock overflow")
+        idx_ref.time = idx_ref.time.checked_add(1).expect("Vector clock overflow");
+        if !current_span.is_dummy() {
+            idx_ref.span = current_span;
+        }
     }
 
     // Join the two vector-clocks together, this
@@ -102,14 +143,23 @@ impl VClock {
         let rhs_slice = other.as_slice();
         let lhs_slice = self.get_mut_with_min_len(rhs_slice.len());
         for (l, &r) in lhs_slice.iter_mut().zip(rhs_slice.iter()) {
+            let l_span = l.span;
+            let r_span = r.span;
             *l = r.max(*l);
+            l.span = l.span.substitute_dummy(r_span).substitute_dummy(l_span);
         }
     }
 
     /// Set the element at the current index of the vector
     pub fn set_at_index(&mut self, other: &Self, idx: VectorIdx) {
         let mut_slice = self.get_mut_with_min_len(idx.index() + 1);
+
+        let prev_span = mut_slice[idx.index()].span;
+
         mut_slice[idx.index()] = other[idx];
+
+        let span = &mut mut_slice[idx.index()].span;
+        *span = span.substitute_dummy(prev_span);
     }
 
     /// Set the vector to the all-zero vector
@@ -313,7 +363,14 @@ impl Index<VectorIdx> for VClock {
 
     #[inline]
     fn index(&self, index: VectorIdx) -> &VTimestamp {
-        self.as_slice().get(index.to_u32() as usize).unwrap_or(&0)
+        self.as_slice().get(index.to_u32() as usize).unwrap_or(&VTimestamp::ZERO)
+    }
+}
+
+impl IndexMut<VectorIdx> for VClock {
+    #[inline]
+    fn index_mut(&mut self, index: VectorIdx) -> &mut VTimestamp {
+        self.0.as_mut_slice().get_mut(index.to_u32() as usize).unwrap()
     }
 }
 
@@ -324,6 +381,7 @@ impl Index<VectorIdx> for VClock {
 mod tests {
 
     use super::{VClock, VTimestamp, VectorIdx};
+    use rustc_span::DUMMY_SP;
     use std::cmp::Ordering;
 
     #[test]
@@ -331,13 +389,13 @@ mod tests {
         let mut c1 = VClock::default();
         let mut c2 = VClock::default();
         assert_eq!(c1, c2);
-        c1.increment_index(VectorIdx(5));
+        c1.increment_index(VectorIdx(5), DUMMY_SP);
         assert_ne!(c1, c2);
-        c2.increment_index(VectorIdx(53));
+        c2.increment_index(VectorIdx(53), DUMMY_SP);
         assert_ne!(c1, c2);
-        c1.increment_index(VectorIdx(53));
+        c1.increment_index(VectorIdx(53), DUMMY_SP);
         assert_ne!(c1, c2);
-        c2.increment_index(VectorIdx(5));
+        c2.increment_index(VectorIdx(5), DUMMY_SP);
         assert_eq!(c1, c2);
     }
 
@@ -386,14 +444,14 @@ mod tests {
         );
     }
 
-    fn from_slice(mut slice: &[VTimestamp]) -> VClock {
+    fn from_slice(mut slice: &[u32]) -> VClock {
         while let Some(0) = slice.last() {
             slice = &slice[..slice.len() - 1]
         }
-        VClock(smallvec::SmallVec::from_slice(slice))
+        VClock(slice.iter().copied().map(|time| VTimestamp { time, span: DUMMY_SP }).collect())
     }
 
-    fn assert_order(l: &[VTimestamp], r: &[VTimestamp], o: Option<Ordering>) {
+    fn assert_order(l: &[u32], r: &[u32], o: Option<Ordering>) {
         let l = from_slice(l);
         let r = from_slice(r);
 
diff --git a/src/tools/miri/src/concurrency/weak_memory.rs b/src/tools/miri/src/concurrency/weak_memory.rs
index 391681444d9..2a48c9e6cd0 100644
--- a/src/tools/miri/src/concurrency/weak_memory.rs
+++ b/src/tools/miri/src/concurrency/weak_memory.rs
@@ -258,7 +258,7 @@ impl<'mir, 'tcx: 'mir> StoreBuffer {
             // The thread index and timestamp of the initialisation write
             // are never meaningfully used, so it's fine to leave them as 0
             store_index: VectorIdx::from(0),
-            timestamp: 0,
+            timestamp: VTimestamp::ZERO,
             val: init,
             is_seqcst: false,
             load_info: RefCell::new(LoadInfo::default()),
diff --git a/src/tools/miri/src/diagnostics.rs b/src/tools/miri/src/diagnostics.rs
index c22ac50e455..035c0e64233 100644
--- a/src/tools/miri/src/diagnostics.rs
+++ b/src/tools/miri/src/diagnostics.rs
@@ -35,6 +35,17 @@ pub enum TerminationInfo {
         link_name: Symbol,
         span: SpanData,
     },
+    DataRace {
+        op1: RacingOp,
+        op2: RacingOp,
+        ptr: Pointer,
+    },
+}
+
+pub struct RacingOp {
+    pub action: String,
+    pub thread_info: String,
+    pub span: SpanData,
 }
 
 impl fmt::Display for TerminationInfo {
@@ -55,6 +66,12 @@ impl fmt::Display for TerminationInfo {
                 write!(f, "multiple definitions of symbol `{link_name}`"),
             SymbolShimClashing { link_name, .. } =>
                 write!(f, "found `{link_name}` symbol definition that clashes with a built-in shim",),
+            DataRace { ptr, op1, op2 } =>
+                write!(
+                    f,
+                    "Data race detected between (1) {} on {} and (2) {} on {} at {ptr:?}. (2) just happened here",
+                    op1.action, op1.thread_info, op2.action, op2.thread_info
+                ),
         }
     }
 }
@@ -167,7 +184,7 @@ pub fn report_error<'tcx, 'mir>(
             Abort(_) => Some("abnormal termination"),
             UnsupportedInIsolation(_) | Int2PtrWithStrictProvenance =>
                 Some("unsupported operation"),
-            StackedBorrowsUb { .. } => Some("Undefined Behavior"),
+            StackedBorrowsUb { .. } | DataRace { .. } => Some("Undefined Behavior"),
             Deadlock => Some("deadlock"),
             MultipleSymbolDefinitions { .. } | SymbolShimClashing { .. } => None,
         };
@@ -205,6 +222,12 @@ pub fn report_error<'tcx, 'mir>(
                 vec![(Some(*span), format!("the `{link_name}` symbol is defined here"))],
             Int2PtrWithStrictProvenance =>
                 vec![(None, format!("use Strict Provenance APIs (https://doc.rust-lang.org/nightly/std/ptr/index.html#strict-provenance, https://crates.io/crates/sptr) instead"))],
+            DataRace { op1, .. } =>
+                vec![
+                    (Some(op1.span), format!("and (1) occurred earlier here")),
+                    (None, format!("this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior")),
+                    (None, format!("see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information")),
+                ],
             _ => vec![],
         };
         (title, helps)
@@ -339,9 +362,11 @@ fn report_msg<'tcx>(
     }
 
     // Show note and help messages.
+    let mut extra_span = false;
     for (span_data, note) in &notes {
         if let Some(span_data) = span_data {
             err.span_note(span_data.span(), note);
+            extra_span = true;
         } else {
             err.note(note);
         }
@@ -349,13 +374,14 @@ fn report_msg<'tcx>(
     for (span_data, help) in &helps {
         if let Some(span_data) = span_data {
             err.span_help(span_data.span(), help);
+            extra_span = true;
         } else {
             err.help(help);
         }
     }
     if notes.len() + helps.len() > 0 {
         // Add visual separator before backtrace.
-        err.note("BACKTRACE:");
+        err.note(if extra_span { "BACKTRACE (of the first span):" } else { "BACKTRACE:" });
     }
     // Add backtrace
     for (idx, frame_info) in stacktrace.iter().enumerate() {
@@ -395,7 +421,8 @@ impl<'mir, 'tcx> MiriMachine<'mir, 'tcx> {
 
         let msg = match &e {
             CreatedPointerTag(tag, None, _) => format!("created base tag {tag:?}"),
-            CreatedPointerTag(tag, Some(perm), None) => format!("created {tag:?} with {perm} derived from unknown tag"),
+            CreatedPointerTag(tag, Some(perm), None) =>
+                format!("created {tag:?} with {perm} derived from unknown tag"),
             CreatedPointerTag(tag, Some(perm), Some((alloc_id, range, orig_tag))) =>
                 format!(
                     "created tag {tag:?} with {perm} at {alloc_id:?}{range:?} derived from {orig_tag:?}"
diff --git a/src/tools/miri/src/eval.rs b/src/tools/miri/src/eval.rs
index 7b4973f3b9d..6c87dad1f1f 100644
--- a/src/tools/miri/src/eval.rs
+++ b/src/tools/miri/src/eval.rs
@@ -143,6 +143,8 @@ pub struct MiriConfig {
     pub gc_interval: u32,
     /// The number of CPUs to be reported by miri.
     pub num_cpus: u32,
+    /// Requires Miri to emulate pages of a certain size
+    pub page_size: Option<u64>,
 }
 
 impl Default for MiriConfig {
@@ -176,6 +178,7 @@ impl Default for MiriConfig {
             external_so_file: None,
             gc_interval: 10_000,
             num_cpus: 1,
+            page_size: None,
         }
     }
 }
@@ -233,7 +236,7 @@ impl MainThreadState {
                     this.machine.main_fn_ret_place.unwrap().ptr,
                     this.machine.layouts.isize,
                 );
-                let exit_code = this.read_scalar(&ret_place.into())?.to_machine_isize(this)?;
+                let exit_code = this.read_machine_isize(&ret_place.into())?;
                 // Need to call this ourselves since we are not going to return to the scheduler
                 // loop, and we want the main thread TLS to not show up as memory leaks.
                 this.terminate_active_thread()?;
diff --git a/src/tools/miri/src/helpers.rs b/src/tools/miri/src/helpers.rs
index 7fb2539ca5a..c11c6104c28 100644
--- a/src/tools/miri/src/helpers.rs
+++ b/src/tools/miri/src/helpers.rs
@@ -138,55 +138,77 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
             .unwrap_or_else(|| panic!("failed to find required Rust item: {path:?}"))
     }
 
-    /// Evaluates the scalar at the specified path. Returns Some(val)
-    /// if the path could be resolved, and None otherwise
-    fn eval_path_scalar(&self, path: &[&str]) -> InterpResult<'tcx, Scalar<Provenance>> {
+    /// Evaluates the scalar at the specified path.
+    fn eval_path_scalar(&self, path: &[&str]) -> Scalar<Provenance> {
         let this = self.eval_context_ref();
         let instance = this.resolve_path(path, Namespace::ValueNS);
         let cid = GlobalId { instance, promoted: None };
         // We don't give a span -- this isn't actually used directly by the program anyway.
-        let const_val = this.eval_global(cid, None)?;
+        let const_val = this
+            .eval_global(cid, None)
+            .unwrap_or_else(|err| panic!("failed to evaluate required Rust item: {path:?}\n{err}"));
         this.read_scalar(&const_val.into())
+            .unwrap_or_else(|err| panic!("failed to read required Rust item: {path:?}\n{err}"))
     }
 
     /// Helper function to get a `libc` constant as a `Scalar`.
-    fn eval_libc(&self, name: &str) -> InterpResult<'tcx, Scalar<Provenance>> {
+    fn eval_libc(&self, name: &str) -> Scalar<Provenance> {
         self.eval_path_scalar(&["libc", name])
     }
 
     /// Helper function to get a `libc` constant as an `i32`.
-    fn eval_libc_i32(&self, name: &str) -> InterpResult<'tcx, i32> {
+    fn eval_libc_i32(&self, name: &str) -> i32 {
         // TODO: Cache the result.
-        self.eval_libc(name)?.to_i32()
+        self.eval_libc(name).to_i32().unwrap_or_else(|_err| {
+            panic!("required libc item has unexpected type (not `i32`): {name}")
+        })
+    }
+
+    /// Helper function to get a `libc` constant as an `u32`.
+    fn eval_libc_u32(&self, name: &str) -> u32 {
+        // TODO: Cache the result.
+        self.eval_libc(name).to_u32().unwrap_or_else(|_err| {
+            panic!("required libc item has unexpected type (not `u32`): {name}")
+        })
     }
 
     /// Helper function to get a `windows` constant as a `Scalar`.
-    fn eval_windows(&self, module: &str, name: &str) -> InterpResult<'tcx, Scalar<Provenance>> {
+    fn eval_windows(&self, module: &str, name: &str) -> Scalar<Provenance> {
         self.eval_context_ref().eval_path_scalar(&["std", "sys", "windows", module, name])
     }
 
+    /// Helper function to get a `windows` constant as a `u32`.
+    fn eval_windows_u32(&self, module: &str, name: &str) -> u32 {
+        // TODO: Cache the result.
+        self.eval_windows(module, name).to_u32().unwrap_or_else(|_err| {
+            panic!("required Windows item has unexpected type (not `u32`): {module}::{name}")
+        })
+    }
+
     /// Helper function to get a `windows` constant as a `u64`.
-    fn eval_windows_u64(&self, module: &str, name: &str) -> InterpResult<'tcx, u64> {
+    fn eval_windows_u64(&self, module: &str, name: &str) -> u64 {
         // TODO: Cache the result.
-        self.eval_windows(module, name)?.to_u64()
+        self.eval_windows(module, name).to_u64().unwrap_or_else(|_err| {
+            panic!("required Windows item has unexpected type (not `u64`): {module}::{name}")
+        })
     }
 
     /// Helper function to get the `TyAndLayout` of a `libc` type
-    fn libc_ty_layout(&self, name: &str) -> InterpResult<'tcx, TyAndLayout<'tcx>> {
+    fn libc_ty_layout(&self, name: &str) -> TyAndLayout<'tcx> {
         let this = self.eval_context_ref();
         let ty = this
             .resolve_path(&["libc", name], Namespace::TypeNS)
             .ty(*this.tcx, ty::ParamEnv::reveal_all());
-        this.layout_of(ty)
+        this.layout_of(ty).unwrap()
     }
 
     /// Helper function to get the `TyAndLayout` of a `windows` type
-    fn windows_ty_layout(&self, name: &str) -> InterpResult<'tcx, TyAndLayout<'tcx>> {
+    fn windows_ty_layout(&self, name: &str) -> TyAndLayout<'tcx> {
         let this = self.eval_context_ref();
         let ty = this
             .resolve_path(&["std", "sys", "windows", "c", name], Namespace::TypeNS)
             .ty(*this.tcx, ty::ParamEnv::reveal_all());
-        this.layout_of(ty)
+        this.layout_of(ty).unwrap()
     }
 
     /// Project to the given *named* field of the mplace (which must be a struct or union type).
@@ -609,14 +631,14 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         if target.families.iter().any(|f| f == "unix") {
             for &(name, kind) in UNIX_IO_ERROR_TABLE {
                 if err_kind == kind {
-                    return this.eval_libc(name);
+                    return Ok(this.eval_libc(name));
                 }
             }
             throw_unsup_format!("io error {:?} cannot be translated into a raw os error", err_kind)
         } else if target.families.iter().any(|f| f == "windows") {
             // FIXME: we have to finish implementing the Windows equivalent of this.
             use std::io::ErrorKind::*;
-            this.eval_windows(
+            Ok(this.eval_windows(
                 "c",
                 match err_kind {
                     NotFound => "ERROR_FILE_NOT_FOUND",
@@ -627,7 +649,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                             err_kind
                         ),
                 },
-            )
+            ))
         } else {
             throw_unsup_format!(
                 "converting io::Error into errnum is unsupported for OS {}",
@@ -647,7 +669,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         if target.families.iter().any(|f| f == "unix") {
             let errnum = errnum.to_i32()?;
             for &(name, kind) in UNIX_IO_ERROR_TABLE {
-                if errnum == this.eval_libc_i32(name)? {
+                if errnum == this.eval_libc_i32(name) {
                     return Ok(Some(kind));
                 }
             }
diff --git a/src/tools/miri/src/intptrcast.rs b/src/tools/miri/src/intptrcast.rs
index c26828b11e0..618cf9df7f3 100644
--- a/src/tools/miri/src/intptrcast.rs
+++ b/src/tools/miri/src/intptrcast.rs
@@ -51,12 +51,12 @@ impl VisitTags for GlobalStateInner {
 }
 
 impl GlobalStateInner {
-    pub fn new(config: &MiriConfig) -> Self {
+    pub fn new(config: &MiriConfig, stack_addr: u64) -> Self {
         GlobalStateInner {
             int_to_ptr_map: Vec::default(),
             base_addr: FxHashMap::default(),
             exposed: FxHashSet::default(),
-            next_base_addr: STACK_ADDR,
+            next_base_addr: stack_addr,
             provenance_mode: config.provenance_mode,
         }
     }
diff --git a/src/tools/miri/src/lib.rs b/src/tools/miri/src/lib.rs
index 42519797976..97750cb78cd 100644
--- a/src/tools/miri/src/lib.rs
+++ b/src/tools/miri/src/lib.rs
@@ -27,6 +27,7 @@
     clippy::single_element_loop,
     clippy::needless_return,
     clippy::bool_to_int_with_if,
+    clippy::box_default,
     // We are not implementing queries here so it's fine
     rustc::potential_query_instability
 )]
@@ -107,7 +108,7 @@ pub use crate::helpers::EvalContextExt as _;
 pub use crate::intptrcast::ProvenanceMode;
 pub use crate::machine::{
     AllocExtra, FrameExtra, MiriInterpCx, MiriInterpCxExt, MiriMachine, MiriMemoryKind,
-    PrimitiveLayouts, Provenance, ProvenanceExtra, PAGE_SIZE, STACK_ADDR, STACK_SIZE,
+    PrimitiveLayouts, Provenance, ProvenanceExtra,
 };
 pub use crate::mono_hash_map::MonoHashMap;
 pub use crate::operator::EvalContextExt as _;
diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs
index ab629e4711b..01a3d7550e2 100644
--- a/src/tools/miri/src/machine.rs
+++ b/src/tools/miri/src/machine.rs
@@ -9,6 +9,7 @@ use rand::rngs::StdRng;
 use rand::SeedableRng;
 
 use rustc_ast::ast::Mutability;
+use rustc_const_eval::const_eval::CheckAlignment;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 #[allow(unused)]
 use rustc_data_structures::static_assert_size;
@@ -22,9 +23,8 @@ use rustc_middle::{
 };
 use rustc_span::def_id::{CrateNum, DefId};
 use rustc_span::Symbol;
-use rustc_target::abi::{Size, Align};
+use rustc_target::abi::{Align, Size};
 use rustc_target::spec::abi::Abi;
-use rustc_const_eval::const_eval::CheckAlignment;
 
 use crate::{
     concurrency::{data_race, weak_memory},
@@ -32,10 +32,9 @@ use crate::{
     *,
 };
 
-// Some global facts about the emulated machine.
-pub const PAGE_SIZE: u64 = 4 * 1024; // FIXME: adjust to target architecture
-pub const STACK_ADDR: u64 = 32 * PAGE_SIZE; // not really about the "stack", but where we start assigning integer addresses to allocations
-pub const STACK_SIZE: u64 = 16 * PAGE_SIZE; // whatever
+/// The number of the available real-time signal with the lowest priority.
+/// Dummy constant related to epoll, must be between 32 and 64.
+pub const SIGRTMAX: i32 = 42;
 
 /// Extra data stored with each stack frame
 pub struct FrameExtra<'tcx> {
@@ -470,6 +469,10 @@ pub struct MiriMachine<'mir, 'tcx> {
     pub(crate) since_gc: u32,
     /// The number of CPUs to be reported by miri.
     pub(crate) num_cpus: u32,
+    /// Determines Miri's page size and associated values
+    pub(crate) page_size: u64,
+    pub(crate) stack_addr: u64,
+    pub(crate) stack_size: u64,
 }
 
 impl<'mir, 'tcx> MiriMachine<'mir, 'tcx> {
@@ -483,11 +486,31 @@ impl<'mir, 'tcx> MiriMachine<'mir, 'tcx> {
         let rng = StdRng::seed_from_u64(config.seed.unwrap_or(0));
         let borrow_tracker = config.borrow_tracker.map(|bt| bt.instanciate_global_state(config));
         let data_race = config.data_race_detector.then(|| data_race::GlobalState::new(config));
+        let page_size = if let Some(page_size) = config.page_size {
+            page_size
+        } else {
+            let target = &layout_cx.tcx.sess.target;
+            match target.arch.as_ref() {
+                "wasm32" | "wasm64" => 64 * 1024, // https://webassembly.github.io/spec/core/exec/runtime.html#memory-instances
+                "aarch64" =>
+                    if target.options.vendor.as_ref() == "apple" {
+                        // No "definitive" source, but see:
+                        // https://www.wwdcnotes.com/notes/wwdc20/10214/
+                        // https://github.com/ziglang/zig/issues/11308 etc.
+                        16 * 1024
+                    } else {
+                        4 * 1024
+                    },
+                _ => 4 * 1024,
+            }
+        };
+        let stack_addr = page_size * 32;
+        let stack_size = page_size * 16;
         MiriMachine {
             tcx: layout_cx.tcx,
             borrow_tracker,
             data_race,
-            intptrcast: RefCell::new(intptrcast::GlobalStateInner::new(config)),
+            intptrcast: RefCell::new(intptrcast::GlobalStateInner::new(config, stack_addr)),
             // `env_vars` depends on a full interpreter so we cannot properly initialize it yet.
             env_vars: EnvVars::default(),
             main_fn_ret_place: None,
@@ -549,6 +572,9 @@ impl<'mir, 'tcx> MiriMachine<'mir, 'tcx> {
             gc_interval: config.gc_interval,
             since_gc: 0,
             num_cpus: config.num_cpus,
+            page_size,
+            stack_addr,
+            stack_size,
         }
     }
 
@@ -693,6 +719,9 @@ impl VisitTags for MiriMachine<'_, '_> {
             gc_interval: _,
             since_gc: _,
             num_cpus: _,
+            page_size: _,
+            stack_addr: _,
+            stack_size: _,
         } = self;
 
         threads.visit_tags(visit);
@@ -927,6 +956,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> {
                 &ecx.machine.threads,
                 alloc.size(),
                 kind,
+                ecx.machine.current_span(),
             )
         });
         let buffer_alloc = ecx.machine.weak_memory.then(weak_memory::AllocState::new_allocation);
@@ -981,9 +1011,8 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> {
         ptr: Pointer<Self::Provenance>,
     ) -> InterpResult<'tcx> {
         match ptr.provenance {
-            Provenance::Concrete { alloc_id, tag } => {
-                intptrcast::GlobalStateInner::expose_ptr(ecx, alloc_id, tag)
-            }
+            Provenance::Concrete { alloc_id, tag } =>
+                intptrcast::GlobalStateInner::expose_ptr(ecx, alloc_id, tag),
             Provenance::Wildcard => {
                 // No need to do anything for wildcard pointers as
                 // their provenances have already been previously exposed.
diff --git a/src/tools/miri/src/shims/env.rs b/src/tools/miri/src/shims/env.rs
index 80fb4ff2fe9..e049eec57a3 100644
--- a/src/tools/miri/src/shims/env.rs
+++ b/src/tools/miri/src/shims/env.rs
@@ -170,7 +170,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 ))
             }
             None => {
-                let envvar_not_found = this.eval_windows("c", "ERROR_ENVVAR_NOT_FOUND")?;
+                let envvar_not_found = this.eval_windows("c", "ERROR_ENVVAR_NOT_FOUND");
                 this.set_last_error(envvar_not_found)?;
                 Scalar::from_u32(0) // return zero upon failure
             }
@@ -240,7 +240,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
             Ok(0) // return zero on success
         } else {
             // name argument is a null pointer, points to an empty string, or points to a string containing an '=' character.
-            let einval = this.eval_libc("EINVAL")?;
+            let einval = this.eval_libc("EINVAL");
             this.set_last_error(einval)?;
             Ok(-1)
         }
@@ -274,7 +274,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 this.deallocate_ptr(var, None, MiriMemoryKind::Runtime.into())?;
                 this.update_environ()?;
             }
-            Ok(this.eval_windows("c", "TRUE")?)
+            Ok(this.eval_windows("c", "TRUE"))
         } else {
             let value = this.read_os_str_from_wide_str(value_ptr)?;
             let var_ptr = alloc_env_var_as_wide_str(&name, &value, this)?;
@@ -282,7 +282,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 this.deallocate_ptr(var, None, MiriMemoryKind::Runtime.into())?;
             }
             this.update_environ()?;
-            Ok(this.eval_windows("c", "TRUE")?)
+            Ok(this.eval_windows("c", "TRUE"))
         }
     }
 
@@ -306,7 +306,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
             Ok(0)
         } else {
             // name argument is a null pointer, points to an empty string, or points to a string containing an '=' character.
-            let einval = this.eval_libc("EINVAL")?;
+            let einval = this.eval_libc("EINVAL");
             this.set_last_error(einval)?;
             Ok(-1)
         }
@@ -321,7 +321,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         this.assert_target_os_is_unix("getcwd");
 
         let buf = this.read_pointer(buf_op)?;
-        let size = this.read_scalar(size_op)?.to_machine_usize(&*this.tcx)?;
+        let size = this.read_machine_usize(size_op)?;
 
         if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op {
             this.reject_in_isolation("`getcwd`", reject_with)?;
@@ -335,7 +335,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 if this.write_path_to_c_str(&cwd, buf, size)?.0 {
                     return Ok(buf);
                 }
-                let erange = this.eval_libc("ERANGE")?;
+                let erange = this.eval_libc("ERANGE");
                 this.set_last_error(erange)?;
             }
             Err(e) => this.set_last_error_from_io_error(e.kind())?,
@@ -411,14 +411,14 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
             this.reject_in_isolation("`SetCurrentDirectoryW`", reject_with)?;
             this.set_last_error_from_io_error(ErrorKind::PermissionDenied)?;
 
-            return this.eval_windows("c", "FALSE");
+            return Ok(this.eval_windows("c", "FALSE"));
         }
 
         match env::set_current_dir(path) {
-            Ok(()) => this.eval_windows("c", "TRUE"),
+            Ok(()) => Ok(this.eval_windows("c", "TRUE")),
             Err(e) => {
                 this.set_last_error_from_io_error(e.kind())?;
-                this.eval_windows("c", "FALSE")
+                Ok(this.eval_windows("c", "FALSE"))
             }
         }
     }
diff --git a/src/tools/miri/src/shims/foreign_items.rs b/src/tools/miri/src/shims/foreign_items.rs
index 8370e02b588..4321bdf9aae 100644
--- a/src/tools/miri/src/shims/foreign_items.rs
+++ b/src/tools/miri/src/shims/foreign_items.rs
@@ -1,4 +1,4 @@
-use std::{collections::hash_map::Entry, io::Write, iter};
+use std::{collections::hash_map::Entry, io::Write, iter, path::Path};
 
 use log::trace;
 
@@ -442,6 +442,21 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 }
                 this.machine.static_roots.push(alloc_id);
             }
+            "miri_host_to_target_path" => {
+                let [ptr, out, out_size] = this.check_shim(abi, Abi::Rust, link_name, args)?;
+                let ptr = this.read_pointer(ptr)?;
+                let out = this.read_pointer(out)?;
+                let out_size = this.read_scalar(out_size)?.to_machine_usize(this)?;
+
+                // The host affects program behavior here, so this requires isolation to be disabled.
+                this.check_no_isolation("`miri_host_to_target_path`")?;
+
+                // We read this as a plain OsStr and write it as a path, which will convert it to the target.
+                let path = this.read_os_str_from_c_str(ptr)?.to_owned();
+                let (success, needed_size) = this.write_path_to_c_str(Path::new(&path), out, out_size)?;
+                // Return value: 0 on success, otherwise the size it would have needed.
+                this.write_int(if success { 0 } else { needed_size }, dest)?;
+            }
 
             // Obtains the size of a Miri backtrace. See the README for details.
             "miri_backtrace_size" => {
@@ -485,14 +500,14 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
             // Standard C allocation
             "malloc" => {
                 let [size] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
-                let size = this.read_scalar(size)?.to_machine_usize(this)?;
+                let size = this.read_machine_usize(size)?;
                 let res = this.malloc(size, /*zero_init:*/ false, MiriMemoryKind::C)?;
                 this.write_pointer(res, dest)?;
             }
             "calloc" => {
                 let [items, len] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
-                let items = this.read_scalar(items)?.to_machine_usize(this)?;
-                let len = this.read_scalar(len)?.to_machine_usize(this)?;
+                let items = this.read_machine_usize(items)?;
+                let len = this.read_machine_usize(len)?;
                 let size =
                     items.checked_mul(len).ok_or_else(|| err_ub_format!("overflow during calloc size computation"))?;
                 let res = this.malloc(size, /*zero_init:*/ true, MiriMemoryKind::C)?;
@@ -506,7 +521,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
             "realloc" => {
                 let [old_ptr, new_size] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
                 let old_ptr = this.read_pointer(old_ptr)?;
-                let new_size = this.read_scalar(new_size)?.to_machine_usize(this)?;
+                let new_size = this.read_machine_usize(new_size)?;
                 let res = this.realloc(old_ptr, new_size, MiriMemoryKind::C)?;
                 this.write_pointer(res, dest)?;
             }
@@ -514,8 +529,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
             // Rust allocation
             "__rust_alloc" | "miri_alloc" => {
                 let [size, align] = this.check_shim(abi, Abi::Rust, link_name, args)?;
-                let size = this.read_scalar(size)?.to_machine_usize(this)?;
-                let align = this.read_scalar(align)?.to_machine_usize(this)?;
+                let size = this.read_machine_usize(size)?;
+                let align = this.read_machine_usize(align)?;
 
                 let default = |this: &mut MiriInterpCx<'mir, 'tcx>| {
                     Self::check_alloc_request(size, align)?;
@@ -546,8 +561,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
             }
             "__rust_alloc_zeroed" => {
                 let [size, align] = this.check_shim(abi, Abi::Rust, link_name, args)?;
-                let size = this.read_scalar(size)?.to_machine_usize(this)?;
-                let align = this.read_scalar(align)?.to_machine_usize(this)?;
+                let size = this.read_machine_usize(size)?;
+                let align = this.read_machine_usize(align)?;
 
                 return this.emulate_allocator(Symbol::intern("__rg_alloc_zeroed"), |this| {
                     Self::check_alloc_request(size, align)?;
@@ -566,8 +581,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
             "__rust_dealloc" | "miri_dealloc" => {
                 let [ptr, old_size, align] = this.check_shim(abi, Abi::Rust, link_name, args)?;
                 let ptr = this.read_pointer(ptr)?;
-                let old_size = this.read_scalar(old_size)?.to_machine_usize(this)?;
-                let align = this.read_scalar(align)?.to_machine_usize(this)?;
+                let old_size = this.read_machine_usize(old_size)?;
+                let align = this.read_machine_usize(align)?;
 
                 let default = |this: &mut MiriInterpCx<'mir, 'tcx>| {
                     let memory_kind = match link_name.as_str() {
@@ -596,9 +611,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
             "__rust_realloc" => {
                 let [ptr, old_size, align, new_size] = this.check_shim(abi, Abi::Rust, link_name, args)?;
                 let ptr = this.read_pointer(ptr)?;
-                let old_size = this.read_scalar(old_size)?.to_machine_usize(this)?;
-                let align = this.read_scalar(align)?.to_machine_usize(this)?;
-                let new_size = this.read_scalar(new_size)?.to_machine_usize(this)?;
+                let old_size = this.read_machine_usize(old_size)?;
+                let align = this.read_machine_usize(align)?;
+                let new_size = this.read_machine_usize(new_size)?;
                 // No need to check old_size; we anyway check that they match the allocation.
 
                 return this.emulate_allocator(Symbol::intern("__rg_realloc"), |this| {
@@ -621,7 +636,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 let [left, right, n] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
                 let left = this.read_pointer(left)?;
                 let right = this.read_pointer(right)?;
-                let n = Size::from_bytes(this.read_scalar(n)?.to_machine_usize(this)?);
+                let n = Size::from_bytes(this.read_machine_usize(n)?);
 
                 let result = {
                     let left_bytes = this.read_bytes_ptr_strip_provenance(left, n)?;
@@ -641,7 +656,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 let [ptr, val, num] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
                 let ptr = this.read_pointer(ptr)?;
                 let val = this.read_scalar(val)?.to_i32()?;
-                let num = this.read_scalar(num)?.to_machine_usize(this)?;
+                let num = this.read_machine_usize(num)?;
                 // The docs say val is "interpreted as unsigned char".
                 #[allow(clippy::cast_sign_loss, clippy::cast_possible_truncation)]
                 let val = val as u8;
@@ -664,7 +679,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 let [ptr, val, num] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
                 let ptr = this.read_pointer(ptr)?;
                 let val = this.read_scalar(val)?.to_i32()?;
-                let num = this.read_scalar(num)?.to_machine_usize(this)?;
+                let num = this.read_machine_usize(num)?;
                 // The docs say val is "interpreted as unsigned char".
                 #[allow(clippy::cast_sign_loss, clippy::cast_possible_truncation)]
                 let val = val as u8;
diff --git a/src/tools/miri/src/shims/intrinsics/mod.rs b/src/tools/miri/src/shims/intrinsics/mod.rs
index 5ea82adb9c6..1b97a9d20de 100644
--- a/src/tools/miri/src/shims/intrinsics/mod.rs
+++ b/src/tools/miri/src/shims/intrinsics/mod.rs
@@ -111,7 +111,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 let ty_layout = this.layout_of(ty)?;
                 let val_byte = this.read_scalar(val_byte)?.to_u8()?;
                 let ptr = this.read_pointer(ptr)?;
-                let count = this.read_scalar(count)?.to_machine_usize(this)?;
+                let count = this.read_machine_usize(count)?;
                 // `checked_mul` enforces a too small bound (the correct one would probably be machine_isize_max),
                 // but no actual allocation can be big enough for the difference to be noticeable.
                 let byte_count = ty_layout.size.checked_mul(count, this).ok_or_else(|| {
@@ -124,7 +124,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 let [ptr, mask] = check_arg_count(args)?;
 
                 let ptr = this.read_pointer(ptr)?;
-                let mask = this.read_scalar(mask)?.to_machine_usize(this)?;
+                let mask = this.read_machine_usize(mask)?;
 
                 let masked_addr = Size::from_bytes(ptr.addr().bytes() & mask);
 
diff --git a/src/tools/miri/src/shims/mod.rs b/src/tools/miri/src/shims/mod.rs
index b6efad6b5ee..39db97b72e2 100644
--- a/src/tools/miri/src/shims/mod.rs
+++ b/src/tools/miri/src/shims/mod.rs
@@ -80,7 +80,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
             return Ok(false);
         }
 
-        let req_align = this.read_scalar(align_op)?.to_machine_usize(this)?;
+        let req_align = this.read_machine_usize(align_op)?;
 
         // Stop if the alignment is not a power of two.
         if !req_align.is_power_of_two() {
diff --git a/src/tools/miri/src/shims/os_str.rs b/src/tools/miri/src/shims/os_str.rs
index bc7ca82997b..0375a228a21 100644
--- a/src/tools/miri/src/shims/os_str.rs
+++ b/src/tools/miri/src/shims/os_str.rs
@@ -174,7 +174,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         let this = self.eval_context_ref();
         let os_str = this.read_os_str_from_c_str(ptr)?;
 
-        Ok(match this.convert_path_separator(Cow::Borrowed(os_str), PathConversion::TargetToHost) {
+        Ok(match this.convert_path(Cow::Borrowed(os_str), PathConversion::TargetToHost) {
             Cow::Borrowed(x) => Cow::Borrowed(Path::new(x)),
             Cow::Owned(y) => Cow::Owned(PathBuf::from(y)),
         })
@@ -188,10 +188,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         let this = self.eval_context_ref();
         let os_str = this.read_os_str_from_wide_str(ptr)?;
 
-        Ok(this
-            .convert_path_separator(Cow::Owned(os_str), PathConversion::TargetToHost)
-            .into_owned()
-            .into())
+        Ok(this.convert_path(Cow::Owned(os_str), PathConversion::TargetToHost).into_owned().into())
     }
 
     /// Write a Path to the machine memory (as a null-terminated sequence of bytes),
@@ -203,8 +200,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         size: u64,
     ) -> InterpResult<'tcx, (bool, u64)> {
         let this = self.eval_context_mut();
-        let os_str = this
-            .convert_path_separator(Cow::Borrowed(path.as_os_str()), PathConversion::HostToTarget);
+        let os_str =
+            this.convert_path(Cow::Borrowed(path.as_os_str()), PathConversion::HostToTarget);
         this.write_os_str_to_c_str(&os_str, ptr, size)
     }
 
@@ -217,8 +214,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         size: u64,
     ) -> InterpResult<'tcx, (bool, u64)> {
         let this = self.eval_context_mut();
-        let os_str = this
-            .convert_path_separator(Cow::Borrowed(path.as_os_str()), PathConversion::HostToTarget);
+        let os_str =
+            this.convert_path(Cow::Borrowed(path.as_os_str()), PathConversion::HostToTarget);
         this.write_os_str_to_wide_str(&os_str, ptr, size)
     }
 
@@ -230,18 +227,20 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         memkind: MemoryKind<MiriMemoryKind>,
     ) -> InterpResult<'tcx, Pointer<Option<Provenance>>> {
         let this = self.eval_context_mut();
-        let os_str = this
-            .convert_path_separator(Cow::Borrowed(path.as_os_str()), PathConversion::HostToTarget);
+        let os_str =
+            this.convert_path(Cow::Borrowed(path.as_os_str()), PathConversion::HostToTarget);
         this.alloc_os_str_as_c_str(&os_str, memkind)
     }
 
-    fn convert_path_separator<'a>(
+    #[allow(clippy::get_first)]
+    fn convert_path<'a>(
         &self,
         os_str: Cow<'a, OsStr>,
         direction: PathConversion,
     ) -> Cow<'a, OsStr> {
         let this = self.eval_context_ref();
         let target_os = &this.tcx.sess.target.os;
+
         #[cfg(windows)]
         return if target_os == "windows" {
             // Windows-on-Windows, all fine.
@@ -252,24 +251,71 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 PathConversion::HostToTarget => ('\\', '/'),
                 PathConversion::TargetToHost => ('/', '\\'),
             };
-            let converted = os_str
+            let mut converted = os_str
                 .encode_wide()
                 .map(|wchar| if wchar == from as u16 { to as u16 } else { wchar })
                 .collect::<Vec<_>>();
+            // We also have to ensure that absolute paths remain absolute.
+            match direction {
+                PathConversion::HostToTarget => {
+                    // If this is an absolute Windows path that starts with a drive letter (`C:/...`
+                    // after separator conversion), it would not be considered absolute by Unix
+                    // target code.
+                    if converted.get(1).copied() == Some(b':' as u16)
+                        && converted.get(2).copied() == Some(b'/' as u16)
+                    {
+                        // We add a `/` at the beginning, to store the absolute Windows
+                        // path in something that looks like an absolute Unix path.
+                        converted.insert(0, b'/' as u16);
+                    }
+                }
+                PathConversion::TargetToHost => {
+                    // If the path is `\C:\`, the leading backslash was probably added by the above code
+                    // and we should get rid of it again.
+                    if converted.get(0).copied() == Some(b'\\' as u16)
+                        && converted.get(2).copied() == Some(b':' as u16)
+                        && converted.get(3).copied() == Some(b'\\' as u16)
+                    {
+                        converted.remove(0);
+                    }
+                }
+            }
             Cow::Owned(OsString::from_wide(&converted))
         };
         #[cfg(unix)]
         return if target_os == "windows" {
             // Windows target, Unix host.
             let (from, to) = match direction {
-                PathConversion::HostToTarget => ('/', '\\'),
-                PathConversion::TargetToHost => ('\\', '/'),
+                PathConversion::HostToTarget => (b'/', b'\\'),
+                PathConversion::TargetToHost => (b'\\', b'/'),
             };
-            let converted = os_str
+            let mut converted = os_str
                 .as_bytes()
                 .iter()
-                .map(|&wchar| if wchar == from as u8 { to as u8 } else { wchar })
+                .map(|&wchar| if wchar == from { to } else { wchar })
                 .collect::<Vec<_>>();
+            // We also have to ensure that absolute paths remain absolute.
+            match direction {
+                PathConversion::HostToTarget => {
+                    // If this start withs a `\`, we add `\\?` so it starts with `\\?\` which is
+                    // some magic path on Windos that *is* considered absolute.
+                    if converted.get(0).copied() == Some(b'\\') {
+                        converted.splice(0..0, b"\\\\?".iter().copied());
+                    }
+                }
+                PathConversion::TargetToHost => {
+                    // If this starts with `//?/`, it was probably produced by the above code and we
+                    // remove the `//?` that got added to get the Unix path back out.
+                    if converted.get(0).copied() == Some(b'/')
+                        && converted.get(1).copied() == Some(b'/')
+                        && converted.get(2).copied() == Some(b'?')
+                        && converted.get(3).copied() == Some(b'/')
+                    {
+                        // Remove first 3 characters
+                        converted.splice(0..3, std::iter::empty());
+                    }
+                }
+            }
             Cow::Owned(OsString::from_vec(converted))
         } else {
             // Unix-on-Unix, all is fine.
diff --git a/src/tools/miri/src/shims/time.rs b/src/tools/miri/src/shims/time.rs
index d263aab351b..ef411eb8aa7 100644
--- a/src/tools/miri/src/shims/time.rs
+++ b/src/tools/miri/src/shims/time.rs
@@ -36,26 +36,26 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 // Linux further distinguishes regular and "coarse" clocks, but the "coarse" version
                 // is just specified to be "faster and less precise", so we implement both the same way.
                 absolute_clocks = vec![
-                    this.eval_libc_i32("CLOCK_REALTIME")?,
-                    this.eval_libc_i32("CLOCK_REALTIME_COARSE")?,
+                    this.eval_libc_i32("CLOCK_REALTIME"),
+                    this.eval_libc_i32("CLOCK_REALTIME_COARSE"),
                 ];
                 // The second kind is MONOTONIC clocks for which 0 is an arbitrary time point, but they are
                 // never allowed to go backwards. We don't need to do any additonal monotonicity
                 // enforcement because std::time::Instant already guarantees that it is monotonic.
                 relative_clocks = vec![
-                    this.eval_libc_i32("CLOCK_MONOTONIC")?,
-                    this.eval_libc_i32("CLOCK_MONOTONIC_COARSE")?,
+                    this.eval_libc_i32("CLOCK_MONOTONIC"),
+                    this.eval_libc_i32("CLOCK_MONOTONIC_COARSE"),
                 ];
             }
             "macos" => {
-                absolute_clocks = vec![this.eval_libc_i32("CLOCK_REALTIME")?];
-                relative_clocks = vec![this.eval_libc_i32("CLOCK_MONOTONIC")?];
+                absolute_clocks = vec![this.eval_libc_i32("CLOCK_REALTIME")];
+                relative_clocks = vec![this.eval_libc_i32("CLOCK_MONOTONIC")];
                 // Some clocks only seem to exist in the aarch64 version of the target.
                 if this.tcx.sess.target.arch == "aarch64" {
                     // `CLOCK_UPTIME_RAW` supposed to not increment while the system is asleep... but
                     // that's not really something a program running inside Miri can tell, anyway.
                     // We need to support it because std uses it.
-                    relative_clocks.push(this.eval_libc_i32("CLOCK_UPTIME_RAW")?);
+                    relative_clocks.push(this.eval_libc_i32("CLOCK_UPTIME_RAW"));
                 }
             }
             target => throw_unsup_format!("`clock_gettime` is not supported on target OS {target}"),
@@ -68,7 +68,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
             this.machine.clock.now().duration_since(this.machine.clock.anchor())
         } else {
             // Unsupported clock.
-            let einval = this.eval_libc("EINVAL")?;
+            let einval = this.eval_libc("EINVAL");
             this.set_last_error(einval)?;
             return Ok(Scalar::from_i32(-1));
         };
@@ -94,7 +94,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         // Using tz is obsolete and should always be null
         let tz = this.read_pointer(tz_op)?;
         if !this.ptr_is_null(tz)? {
-            let einval = this.eval_libc("EINVAL")?;
+            let einval = this.eval_libc("EINVAL");
             this.set_last_error(einval)?;
             return Ok(-1);
         }
@@ -118,9 +118,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         this.assert_target_os("windows", "GetSystemTimeAsFileTime");
         this.check_no_isolation("`GetSystemTimeAsFileTime`")?;
 
-        let NANOS_PER_SEC = this.eval_windows_u64("time", "NANOS_PER_SEC")?;
-        let INTERVALS_PER_SEC = this.eval_windows_u64("time", "INTERVALS_PER_SEC")?;
-        let INTERVALS_TO_UNIX_EPOCH = this.eval_windows_u64("time", "INTERVALS_TO_UNIX_EPOCH")?;
+        let NANOS_PER_SEC = this.eval_windows_u64("time", "NANOS_PER_SEC");
+        let INTERVALS_PER_SEC = this.eval_windows_u64("time", "INTERVALS_PER_SEC");
+        let INTERVALS_TO_UNIX_EPOCH = this.eval_windows_u64("time", "INTERVALS_TO_UNIX_EPOCH");
         let NANOS_PER_INTERVAL = NANOS_PER_SEC / INTERVALS_PER_SEC;
         let SECONDS_TO_UNIX_EPOCH = INTERVALS_TO_UNIX_EPOCH / INTERVALS_PER_SEC;
 
@@ -226,7 +226,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         let duration = match this.read_timespec(&this.deref_operand(req_op)?)? {
             Some(duration) => duration,
             None => {
-                let einval = this.eval_libc("EINVAL")?;
+                let einval = this.eval_libc("EINVAL");
                 this.set_last_error(einval)?;
                 return Ok(-1);
             }
diff --git a/src/tools/miri/src/shims/tls.rs b/src/tools/miri/src/shims/tls.rs
index 54fdf2872ab..7768772338a 100644
--- a/src/tools/miri/src/shims/tls.rs
+++ b/src/tools/miri/src/shims/tls.rs
@@ -303,12 +303,12 @@ trait EvalContextPrivExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
             return Ok(());
         }
         let thread_callback =
-            this.eval_windows("thread_local_key", "p_thread_callback")?.to_pointer(this)?;
+            this.eval_windows("thread_local_key", "p_thread_callback").to_pointer(this)?;
         let thread_callback = this.get_ptr_fn(thread_callback)?.as_instance()?;
 
         // FIXME: Technically, the reason should be `DLL_PROCESS_DETACH` when the main thread exits
         // but std treats both the same.
-        let reason = this.eval_windows("c", "DLL_THREAD_DETACH")?;
+        let reason = this.eval_windows("c", "DLL_THREAD_DETACH");
 
         // The signature of this function is `unsafe extern "system" fn(h: c::LPVOID, dwReason: c::DWORD, pv: c::LPVOID)`.
         // FIXME: `h` should be a handle to the current module and what `pv` should be is unknown
diff --git a/src/tools/miri/src/shims/unix/foreign_items.rs b/src/tools/miri/src/shims/unix/foreign_items.rs
index d746f9df90a..7f43afb7820 100644
--- a/src/tools/miri/src/shims/unix/foreign_items.rs
+++ b/src/tools/miri/src/shims/unix/foreign_items.rs
@@ -78,7 +78,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 let [fd, buf, count] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
                 let fd = this.read_scalar(fd)?.to_i32()?;
                 let buf = this.read_pointer(buf)?;
-                let count = this.read_scalar(count)?.to_machine_usize(this)?;
+                let count = this.read_machine_usize(count)?;
                 let result = this.read(fd, buf, count)?;
                 this.write_scalar(Scalar::from_machine_isize(result, this), dest)?;
             }
@@ -86,7 +86,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 let [fd, buf, n] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
                 let fd = this.read_scalar(fd)?.to_i32()?;
                 let buf = this.read_pointer(buf)?;
-                let count = this.read_scalar(n)?.to_machine_usize(this)?;
+                let count = this.read_machine_usize(n)?;
                 trace!("Called write({:?}, {:?}, {:?})", fd, buf, count);
                 let result = this.write(fd, buf, count)?;
                 // Now, `result` is the value we return back to the program.
@@ -157,8 +157,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 let [fd, offset, len, advice] =
                     this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
                 this.read_scalar(fd)?.to_i32()?;
-                this.read_scalar(offset)?.to_machine_isize(this)?;
-                this.read_scalar(len)?.to_machine_isize(this)?;
+                this.read_machine_isize(offset)?;
+                this.read_machine_isize(len)?;
                 this.read_scalar(advice)?.to_i32()?;
                 // fadvise is only informational, we can ignore it.
                 this.write_null(dest)?;
@@ -191,12 +191,12 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
             "posix_memalign" => {
                 let [ret, align, size] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
                 let ret = this.deref_operand(ret)?;
-                let align = this.read_scalar(align)?.to_machine_usize(this)?;
-                let size = this.read_scalar(size)?.to_machine_usize(this)?;
+                let align = this.read_machine_usize(align)?;
+                let size = this.read_machine_usize(size)?;
                 // Align must be power of 2, and also at least ptr-sized (POSIX rules).
                 // But failure to adhere to this is not UB, it's an error condition.
                 if !align.is_power_of_two() || align < this.pointer_size().bytes() {
-                    let einval = this.eval_libc_i32("EINVAL")?;
+                    let einval = this.eval_libc_i32("EINVAL");
                     this.write_int(einval, dest)?;
                 } else {
                     if size == 0 {
@@ -216,7 +216,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
             // Dynamic symbol loading
             "dlsym" => {
                 let [handle, symbol] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
-                this.read_scalar(handle)?.to_machine_usize(this)?;
+                this.read_machine_usize(handle)?;
                 let symbol = this.read_pointer(symbol)?;
                 let symbol_name = this.read_c_str(symbol)?;
                 if let Some(dlsym) = Dlsym::from_str(symbol_name, &this.tcx.sess.target.os)? {
@@ -234,7 +234,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 // FIXME: Which of these are POSIX, and which are GNU/Linux?
                 // At least the names seem to all also exist on macOS.
                 let sysconfs: &[(&str, fn(&MiriInterpCx<'_, '_>) -> Scalar<Provenance>)] = &[
-                    ("_SC_PAGESIZE", |this| Scalar::from_int(PAGE_SIZE, this.pointer_size())),
+                    ("_SC_PAGESIZE", |this| Scalar::from_int(this.machine.page_size, this.pointer_size())),
                     ("_SC_NPROCESSORS_CONF", |this| Scalar::from_int(this.machine.num_cpus, this.pointer_size())),
                     ("_SC_NPROCESSORS_ONLN", |this| Scalar::from_int(this.machine.num_cpus, this.pointer_size())),
                     // 512 seems to be a reasonable default. The value is not critical, in
@@ -243,7 +243,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 ];
                 let mut result = None;
                 for &(sysconf_name, value) in sysconfs {
-                    let sysconf_name = this.eval_libc_i32(sysconf_name)?;
+                    let sysconf_name = this.eval_libc_i32(sysconf_name);
                     if sysconf_name == name {
                         result = Some(value(this));
                         break;
@@ -472,7 +472,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 let [errnum, buf, buflen] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
                 let errnum = this.read_scalar(errnum)?;
                 let buf = this.read_pointer(buf)?;
-                let buflen = this.read_scalar(buflen)?.to_machine_usize(this)?;
+                let buflen = this.read_machine_usize(buflen)?;
 
                 let error = this.try_errnum_to_io_error(errnum)?;
                 let formatted = match error {
@@ -480,7 +480,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                     None => format!("<unknown errnum in strerror_r: {errnum}>"),
                 };
                 let (complete, _) = this.write_os_str_to_c_str(OsStr::new(&formatted), buf, buflen)?;
-                let ret = if complete { 0 } else { this.eval_libc_i32("ERANGE")? };
+                let ret = if complete { 0 } else { this.eval_libc_i32("ERANGE") };
                 this.write_int(ret, dest)?;
             }
             "getpid" => {
@@ -495,8 +495,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
             if this.frame_in_std() => {
                 let [_attr, guard_size] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
                 let guard_size = this.deref_operand(guard_size)?;
-                let guard_size_layout = this.libc_ty_layout("size_t")?;
-                this.write_scalar(Scalar::from_uint(crate::PAGE_SIZE, guard_size_layout.size), &guard_size.into())?;
+                let guard_size_layout = this.libc_ty_layout("size_t");
+                this.write_scalar(Scalar::from_uint(this.machine.page_size, guard_size_layout.size), &guard_size.into())?;
 
                 // Return success (`0`).
                 this.write_null(dest)?;
@@ -525,11 +525,11 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 let size_place = this.deref_operand(size_place)?;
 
                 this.write_scalar(
-                    Scalar::from_uint(STACK_ADDR, this.pointer_size()),
+                    Scalar::from_uint(this.machine.stack_addr, this.pointer_size()),
                     &addr_place.into(),
                 )?;
                 this.write_scalar(
-                    Scalar::from_uint(STACK_SIZE, this.pointer_size()),
+                    Scalar::from_uint(this.machine.stack_size, this.pointer_size()),
                     &size_place.into(),
                 )?;
 
@@ -565,7 +565,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 let uid = this.read_scalar(uid)?.to_u32()?;
                 let pwd = this.deref_operand(pwd)?;
                 let buf = this.read_pointer(buf)?;
-                let buflen = this.read_scalar(buflen)?.to_machine_usize(this)?;
+                let buflen = this.read_machine_usize(buflen)?;
                 let result = this.deref_operand(result)?;
 
                 // Must be for "us".
@@ -589,7 +589,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                     this.write_null(dest)?;
                 } else {
                     this.write_null(&result.into())?;
-                    this.write_scalar(this.eval_libc("ERANGE")?, dest)?;
+                    this.write_scalar(this.eval_libc("ERANGE"), dest)?;
                 }
             }
 
diff --git a/src/tools/miri/src/shims/unix/fs.rs b/src/tools/miri/src/shims/unix/fs.rs
index 988627db561..1b8f52f3665 100644
--- a/src/tools/miri/src/shims/unix/fs.rs
+++ b/src/tools/miri/src/shims/unix/fs.rs
@@ -17,20 +17,25 @@ use crate::shims::os_str::bytes_to_os_str;
 use crate::*;
 use shims::os_str::os_str_to_bytes;
 use shims::time::system_time_to_duration;
+use shims::unix::linux::fd::epoll::Epoll;
 
 #[derive(Debug)]
-struct FileHandle {
+pub struct FileHandle {
     file: File,
     writable: bool,
 }
 
-trait FileDescriptor: std::fmt::Debug {
+pub trait FileDescriptor: std::fmt::Debug {
     fn name(&self) -> &'static str;
 
     fn as_file_handle<'tcx>(&self) -> InterpResult<'tcx, &FileHandle> {
         throw_unsup_format!("{} cannot be used as FileHandle", self.name());
     }
 
+    fn as_epoll_handle<'tcx>(&mut self) -> InterpResult<'tcx, &mut Epoll> {
+        throw_unsup_format!("not an epoll file descriptor");
+    }
+
     fn read<'tcx>(
         &mut self,
         _communicate_allowed: bool,
@@ -274,7 +279,7 @@ impl FileDescriptor for NullOutput {
 
 #[derive(Debug)]
 pub struct FileHandler {
-    handles: BTreeMap<i32, Box<dyn FileDescriptor>>,
+    pub handles: BTreeMap<i32, Box<dyn FileDescriptor>>,
 }
 
 impl VisitTags for FileHandler {
@@ -297,7 +302,7 @@ impl FileHandler {
         FileHandler { handles }
     }
 
-    fn insert_fd(&mut self, file_handle: Box<dyn FileDescriptor>) -> i32 {
+    pub fn insert_fd(&mut self, file_handle: Box<dyn FileDescriptor>) -> i32 {
         self.insert_fd_with_min_fd(file_handle, 0)
     }
 
@@ -376,17 +381,6 @@ trait EvalContextExtPrivate<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx
         Ok(0)
     }
 
-    /// Function used when a handle is not found inside `FileHandler`. It returns `Ok(-1)`and sets
-    /// the last OS error to `libc::EBADF` (invalid file descriptor). This function uses
-    /// `T: From<i32>` instead of `i32` directly because some fs functions return different integer
-    /// types (like `read`, that returns an `i64`).
-    fn handle_not_found<T: From<i32>>(&mut self) -> InterpResult<'tcx, T> {
-        let this = self.eval_context_mut();
-        let ebadf = this.eval_libc("EBADF")?;
-        this.set_last_error(ebadf)?;
-        Ok((-1).into())
-    }
-
     fn file_type_to_d_type(
         &mut self,
         file_type: std::io::Result<FileType>,
@@ -395,11 +389,11 @@ trait EvalContextExtPrivate<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx
         match file_type {
             Ok(file_type) => {
                 if file_type.is_dir() {
-                    Ok(this.eval_libc("DT_DIR")?.to_u8()?.into())
+                    Ok(this.eval_libc("DT_DIR").to_u8()?.into())
                 } else if file_type.is_file() {
-                    Ok(this.eval_libc("DT_REG")?.to_u8()?.into())
+                    Ok(this.eval_libc("DT_REG").to_u8()?.into())
                 } else if file_type.is_symlink() {
-                    Ok(this.eval_libc("DT_LNK")?.to_u8()?.into())
+                    Ok(this.eval_libc("DT_LNK").to_u8()?.into())
                 } else {
                     // Certain file types are only supported when the host is a Unix system.
                     // (i.e. devices and sockets) If it is, check those cases, if not, fall back to
@@ -409,19 +403,19 @@ trait EvalContextExtPrivate<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx
                     {
                         use std::os::unix::fs::FileTypeExt;
                         if file_type.is_block_device() {
-                            Ok(this.eval_libc("DT_BLK")?.to_u8()?.into())
+                            Ok(this.eval_libc("DT_BLK").to_u8()?.into())
                         } else if file_type.is_char_device() {
-                            Ok(this.eval_libc("DT_CHR")?.to_u8()?.into())
+                            Ok(this.eval_libc("DT_CHR").to_u8()?.into())
                         } else if file_type.is_fifo() {
-                            Ok(this.eval_libc("DT_FIFO")?.to_u8()?.into())
+                            Ok(this.eval_libc("DT_FIFO").to_u8()?.into())
                         } else if file_type.is_socket() {
-                            Ok(this.eval_libc("DT_SOCK")?.to_u8()?.into())
+                            Ok(this.eval_libc("DT_SOCK").to_u8()?.into())
                         } else {
-                            Ok(this.eval_libc("DT_UNKNOWN")?.to_u8()?.into())
+                            Ok(this.eval_libc("DT_UNKNOWN").to_u8()?.into())
                         }
                     }
                     #[cfg(not(unix))]
-                    Ok(this.eval_libc("DT_UNKNOWN")?.to_u8()?.into())
+                    Ok(this.eval_libc("DT_UNKNOWN").to_u8()?.into())
                 }
             }
             Err(e) =>
@@ -532,9 +526,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
 
         let mut options = OpenOptions::new();
 
-        let o_rdonly = this.eval_libc_i32("O_RDONLY")?;
-        let o_wronly = this.eval_libc_i32("O_WRONLY")?;
-        let o_rdwr = this.eval_libc_i32("O_RDWR")?;
+        let o_rdonly = this.eval_libc_i32("O_RDONLY");
+        let o_wronly = this.eval_libc_i32("O_WRONLY");
+        let o_rdwr = this.eval_libc_i32("O_RDWR");
         // The first two bits of the flag correspond to the access mode in linux, macOS and
         // windows. We need to check that in fact the access mode flags for the current target
         // only use these two bits, otherwise we are in an unsupported target and should error.
@@ -561,18 +555,18 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         // options.
         let mut mirror = access_mode;
 
-        let o_append = this.eval_libc_i32("O_APPEND")?;
-        if flag & o_append != 0 {
+        let o_append = this.eval_libc_i32("O_APPEND");
+        if flag & o_append == o_append {
             options.append(true);
             mirror |= o_append;
         }
-        let o_trunc = this.eval_libc_i32("O_TRUNC")?;
-        if flag & o_trunc != 0 {
+        let o_trunc = this.eval_libc_i32("O_TRUNC");
+        if flag & o_trunc == o_trunc {
             options.truncate(true);
             mirror |= o_trunc;
         }
-        let o_creat = this.eval_libc_i32("O_CREAT")?;
-        if flag & o_creat != 0 {
+        let o_creat = this.eval_libc_i32("O_CREAT");
+        if flag & o_creat == o_creat {
             // Get the mode.  On macOS, the argument type `mode_t` is actually `u16`, but
             // C integer promotion rules mean that on the ABI level, it gets passed as `u32`
             // (see https://github.com/rust-lang/rust/issues/71915).
@@ -591,20 +585,29 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
 
             mirror |= o_creat;
 
-            let o_excl = this.eval_libc_i32("O_EXCL")?;
-            if flag & o_excl != 0 {
+            let o_excl = this.eval_libc_i32("O_EXCL");
+            if flag & o_excl == o_excl {
                 mirror |= o_excl;
                 options.create_new(true);
             } else {
                 options.create(true);
             }
         }
-        let o_cloexec = this.eval_libc_i32("O_CLOEXEC")?;
-        if flag & o_cloexec != 0 {
+        let o_cloexec = this.eval_libc_i32("O_CLOEXEC");
+        if flag & o_cloexec == o_cloexec {
             // We do not need to do anything for this flag because `std` already sets it.
             // (Technically we do not support *not* setting this flag, but we ignore that.)
             mirror |= o_cloexec;
         }
+        if this.tcx.sess.target.os == "linux" {
+            let o_tmpfile = this.eval_libc_i32("O_TMPFILE");
+            if flag & o_tmpfile == o_tmpfile {
+                // if the flag contains `O_TMPFILE` then we return a graceful error
+                let eopnotsupp = this.eval_libc("EOPNOTSUPP");
+                this.set_last_error(eopnotsupp)?;
+                return Ok(-1);
+            }
+        }
         // If `flag` is not equal to `mirror`, there is an unsupported option enabled in `flag`,
         // then we throw an error.
         if flag != mirror {
@@ -648,18 +651,18 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         }
 
         // We only support getting the flags for a descriptor.
-        if cmd == this.eval_libc_i32("F_GETFD")? {
+        if cmd == this.eval_libc_i32("F_GETFD") {
             // Currently this is the only flag that `F_GETFD` returns. It is OK to just return the
             // `FD_CLOEXEC` value without checking if the flag is set for the file because `std`
             // always sets this flag when opening a file. However we still need to check that the
             // file itself is open.
             if this.machine.file_handler.handles.contains_key(&fd) {
-                Ok(this.eval_libc_i32("FD_CLOEXEC")?)
+                Ok(this.eval_libc_i32("FD_CLOEXEC"))
             } else {
                 this.handle_not_found()
             }
-        } else if cmd == this.eval_libc_i32("F_DUPFD")?
-            || cmd == this.eval_libc_i32("F_DUPFD_CLOEXEC")?
+        } else if cmd == this.eval_libc_i32("F_DUPFD")
+            || cmd == this.eval_libc_i32("F_DUPFD_CLOEXEC")
         {
             // Note that we always assume the FD_CLOEXEC flag is set for every open file, in part
             // because exec() isn't supported. The F_DUPFD and F_DUPFD_CLOEXEC commands only
@@ -688,7 +691,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 }
                 None => this.handle_not_found(),
             }
-        } else if this.tcx.sess.target.os == "macos" && cmd == this.eval_libc_i32("F_FULLFSYNC")? {
+        } else if this.tcx.sess.target.os == "macos" && cmd == this.eval_libc_i32("F_FULLFSYNC") {
             if let Some(file_descriptor) = this.machine.file_handler.handles.get(&fd) {
                 // FIXME: Support fullfsync for all FDs
                 let FileHandle { file, writable } = file_descriptor.as_file_handle()?;
@@ -717,6 +720,17 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         ))
     }
 
+    /// Function used when a handle is not found inside `FileHandler`. It returns `Ok(-1)`and sets
+    /// the last OS error to `libc::EBADF` (invalid file descriptor). This function uses
+    /// `T: From<i32>` instead of `i32` directly because some fs functions return different integer
+    /// types (like `read`, that returns an `i64`).
+    fn handle_not_found<T: From<i32>>(&mut self) -> InterpResult<'tcx, T> {
+        let this = self.eval_context_mut();
+        let ebadf = this.eval_libc("EBADF");
+        this.set_last_error(ebadf)?;
+        Ok((-1).into())
+    }
+
     fn read(
         &mut self,
         fd: i32,
@@ -821,14 +835,14 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         let offset = this.read_scalar(offset_op)?.to_i64()?;
         let whence = this.read_scalar(whence_op)?.to_i32()?;
 
-        let seek_from = if whence == this.eval_libc_i32("SEEK_SET")? {
+        let seek_from = if whence == this.eval_libc_i32("SEEK_SET") {
             SeekFrom::Start(u64::try_from(offset).unwrap())
-        } else if whence == this.eval_libc_i32("SEEK_CUR")? {
+        } else if whence == this.eval_libc_i32("SEEK_CUR") {
             SeekFrom::Current(offset)
-        } else if whence == this.eval_libc_i32("SEEK_END")? {
+        } else if whence == this.eval_libc_i32("SEEK_END") {
             SeekFrom::End(offset)
         } else {
-            let einval = this.eval_libc("EINVAL")?;
+            let einval = this.eval_libc("EINVAL");
             this.set_last_error(einval)?;
             return Ok(Scalar::from_i64(-1));
         };
@@ -907,7 +921,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         // Reject if isolation is enabled.
         if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op {
             this.reject_in_isolation("`stat`", reject_with)?;
-            let eacc = this.eval_libc("EACCES")?;
+            let eacc = this.eval_libc("EACCES");
             this.set_last_error(eacc)?;
             return Ok(Scalar::from_i32(-1));
         }
@@ -936,7 +950,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         // Reject if isolation is enabled.
         if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op {
             this.reject_in_isolation("`lstat`", reject_with)?;
-            let eacc = this.eval_libc("EACCES")?;
+            let eacc = this.eval_libc("EACCES");
             this.set_last_error(eacc)?;
             return Ok(Scalar::from_i32(-1));
         }
@@ -994,7 +1008,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
 
         // If the statxbuf or pathname pointers are null, the function fails with `EFAULT`.
         if this.ptr_is_null(statxbuf_ptr)? || this.ptr_is_null(pathname_ptr)? {
-            let efault = this.eval_libc("EFAULT")?;
+            let efault = this.eval_libc("EFAULT");
             this.set_last_error(efault)?;
             return Ok(-1);
         }
@@ -1005,13 +1019,14 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         // as `isize`s instead of having the proper types. Thus, we have to recover the layout of
         // `statxbuf_op` by using the `libc::statx` struct type.
         let statxbuf = {
-            let statx_layout = this.libc_ty_layout("statx")?;
+            let statx_layout = this.libc_ty_layout("statx");
             MPlaceTy::from_aligned_ptr(statxbuf_ptr, statx_layout)
         };
 
         let path = this.read_path_from_c_str(pathname_ptr)?.into_owned();
         // See <https://github.com/rust-lang/rust/pull/79196> for a discussion of argument sizes.
-        let empty_path_flag = flags & this.eval_libc("AT_EMPTY_PATH")?.to_i32()? != 0;
+        let at_ampty_path = this.eval_libc_i32("AT_EMPTY_PATH");
+        let empty_path_flag = flags & at_ampty_path == at_ampty_path;
         // We only support:
         // * interpreting `path` as an absolute directory,
         // * interpreting `path` as a path relative to `dirfd` when the latter is `AT_FDCWD`, or
@@ -1020,7 +1035,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         // Other behaviors cannot be tested from `libstd` and thus are not implemented. If you
         // found this error, please open an issue reporting it.
         if !(path.is_absolute()
-            || dirfd == this.eval_libc_i32("AT_FDCWD")?
+            || dirfd == this.eval_libc_i32("AT_FDCWD")
             || (path.as_os_str().is_empty() && empty_path_flag))
         {
             throw_unsup_format!(
@@ -1033,16 +1048,16 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         // Reject if isolation is enabled.
         if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op {
             this.reject_in_isolation("`statx`", reject_with)?;
-            let ecode = if path.is_absolute() || dirfd == this.eval_libc_i32("AT_FDCWD")? {
+            let ecode = if path.is_absolute() || dirfd == this.eval_libc_i32("AT_FDCWD") {
                 // since `path` is provided, either absolute or
                 // relative to CWD, `EACCES` is the most relevant.
-                this.eval_libc("EACCES")?
+                this.eval_libc("EACCES")
             } else {
                 // `dirfd` is set to target file, and `path` is empty
                 // (or we would have hit the `throw_unsup_format`
                 // above). `EACCES` would violate the spec.
                 assert!(empty_path_flag);
-                this.eval_libc("EBADF")?
+                this.eval_libc("EBADF")
             };
             this.set_last_error(ecode)?;
             return Ok(-1);
@@ -1052,12 +1067,11 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         // However `statx` is allowed to return information that was not requested or to not
         // return information that was requested. This `mask` represents the information we can
         // actually provide for any target.
-        let mut mask =
-            this.eval_libc("STATX_TYPE")?.to_u32()? | this.eval_libc("STATX_SIZE")?.to_u32()?;
+        let mut mask = this.eval_libc_u32("STATX_TYPE") | this.eval_libc_u32("STATX_SIZE");
 
         // If the `AT_SYMLINK_NOFOLLOW` flag is set, we query the file's metadata without following
         // symbolic links.
-        let follow_symlink = flags & this.eval_libc("AT_SYMLINK_NOFOLLOW")?.to_i32()? == 0;
+        let follow_symlink = flags & this.eval_libc_i32("AT_SYMLINK_NOFOLLOW") == 0;
 
         // If the path is empty, and the AT_EMPTY_PATH flag is set, we query the open file
         // represented by dirfd, whether it's a directory or otherwise.
@@ -1086,7 +1100,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         let (access_sec, access_nsec) = metadata
             .accessed
             .map(|tup| {
-                mask |= this.eval_libc("STATX_ATIME")?.to_u32()?;
+                mask |= this.eval_libc_u32("STATX_ATIME");
                 InterpResult::Ok(tup)
             })
             .unwrap_or_else(|| Ok((0, 0)))?;
@@ -1094,7 +1108,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         let (created_sec, created_nsec) = metadata
             .created
             .map(|tup| {
-                mask |= this.eval_libc("STATX_BTIME")?.to_u32()?;
+                mask |= this.eval_libc_u32("STATX_BTIME");
                 InterpResult::Ok(tup)
             })
             .unwrap_or_else(|| Ok((0, 0)))?;
@@ -1102,7 +1116,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         let (modified_sec, modified_nsec) = metadata
             .modified
             .map(|tup| {
-                mask |= this.eval_libc("STATX_MTIME")?.to_u32()?;
+                mask |= this.eval_libc_u32("STATX_MTIME");
                 InterpResult::Ok(tup)
             })
             .unwrap_or_else(|| Ok((0, 0)))?;
@@ -1175,7 +1189,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         let newpath_ptr = this.read_pointer(newpath_op)?;
 
         if this.ptr_is_null(oldpath_ptr)? || this.ptr_is_null(newpath_ptr)? {
-            let efault = this.eval_libc("EFAULT")?;
+            let efault = this.eval_libc("EFAULT");
             this.set_last_error(efault)?;
             return Ok(-1);
         }
@@ -1262,7 +1276,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         // Reject if isolation is enabled.
         if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op {
             this.reject_in_isolation("`opendir`", reject_with)?;
-            let eacc = this.eval_libc("EACCES")?;
+            let eacc = this.eval_libc("EACCES");
             this.set_last_error(eacc)?;
             return Ok(Scalar::null_ptr(this));
         }
@@ -1293,12 +1307,12 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
 
         this.assert_target_os("linux", "readdir64");
 
-        let dirp = this.read_scalar(dirp_op)?.to_machine_usize(this)?;
+        let dirp = this.read_machine_usize(dirp_op)?;
 
         // Reject if isolation is enabled.
         if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op {
             this.reject_in_isolation("`readdir`", reject_with)?;
-            let eacc = this.eval_libc("EBADF")?;
+            let eacc = this.eval_libc("EBADF");
             this.set_last_error(eacc)?;
             return Ok(Scalar::null_ptr(this));
         }
@@ -1327,7 +1341,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 let name_bytes = os_str_to_bytes(&name)?;
                 let name_len = u64::try_from(name_bytes.len()).unwrap();
 
-                let dirent64_layout = this.libc_ty_layout("dirent64")?;
+                let dirent64_layout = this.libc_ty_layout("dirent64");
                 let d_name_offset = dirent64_layout.fields.offset(4 /* d_name */).bytes();
                 let size = d_name_offset.checked_add(name_len).unwrap();
 
@@ -1385,7 +1399,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
 
         this.assert_target_os("macos", "readdir_r");
 
-        let dirp = this.read_scalar(dirp_op)?.to_machine_usize(this)?;
+        let dirp = this.read_machine_usize(dirp_op)?;
 
         // Reject if isolation is enabled.
         if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op {
@@ -1478,7 +1492,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
     fn closedir(&mut self, dirp_op: &OpTy<'tcx, Provenance>) -> InterpResult<'tcx, i32> {
         let this = self.eval_context_mut();
 
-        let dirp = this.read_scalar(dirp_op)?.to_machine_usize(this)?;
+        let dirp = this.read_machine_usize(dirp_op)?;
 
         // Reject if isolation is enabled.
         if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op {
@@ -1522,13 +1536,13 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                         let result = file.set_len(length);
                         this.try_unwrap_io_result(result.map(|_| 0i32))?
                     } else {
-                        let einval = this.eval_libc("EINVAL")?;
+                        let einval = this.eval_libc("EINVAL");
                         this.set_last_error(einval)?;
                         -1
                     }
                 } else {
                     // The file is not writable
-                    let einval = this.eval_libc("EINVAL")?;
+                    let einval = this.eval_libc("EINVAL");
                     this.set_last_error(einval)?;
                     -1
                 }
@@ -1602,15 +1616,15 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         let flags = this.read_scalar(flags_op)?.to_i32()?;
 
         if offset < 0 || nbytes < 0 {
-            let einval = this.eval_libc("EINVAL")?;
+            let einval = this.eval_libc("EINVAL");
             this.set_last_error(einval)?;
             return Ok(Scalar::from_i32(-1));
         }
-        let allowed_flags = this.eval_libc_i32("SYNC_FILE_RANGE_WAIT_BEFORE")?
-            | this.eval_libc_i32("SYNC_FILE_RANGE_WRITE")?
-            | this.eval_libc_i32("SYNC_FILE_RANGE_WAIT_AFTER")?;
+        let allowed_flags = this.eval_libc_i32("SYNC_FILE_RANGE_WAIT_BEFORE")
+            | this.eval_libc_i32("SYNC_FILE_RANGE_WRITE")
+            | this.eval_libc_i32("SYNC_FILE_RANGE_WAIT_AFTER");
         if flags & allowed_flags != flags {
-            let einval = this.eval_libc("EINVAL")?;
+            let einval = this.eval_libc("EINVAL");
             this.set_last_error(einval)?;
             return Ok(Scalar::from_i32(-1));
         }
@@ -1642,12 +1656,12 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
 
         let pathname = this.read_path_from_c_str(this.read_pointer(pathname_op)?)?;
         let buf = this.read_pointer(buf_op)?;
-        let bufsize = this.read_scalar(bufsize_op)?.to_machine_usize(this)?;
+        let bufsize = this.read_machine_usize(bufsize_op)?;
 
         // Reject if isolation is enabled.
         if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op {
             this.reject_in_isolation("`readlink`", reject_with)?;
-            let eacc = this.eval_libc("EACCES")?;
+            let eacc = this.eval_libc("EACCES");
             this.set_last_error(eacc)?;
             return Ok(-1);
         }
@@ -1658,7 +1672,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 // 'readlink' truncates the resolved path if the provided buffer is not large
                 // enough, and does *not* add a null terminator. That means we cannot use the usual
                 // `write_path_to_c_str` and have to re-implement parts of it ourselves.
-                let resolved = this.convert_path_separator(
+                let resolved = this.convert_path(
                     Cow::Borrowed(resolved.as_ref()),
                     crate::shims::os_str::PathConversion::HostToTarget,
                 );
@@ -1692,7 +1706,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
             }
         }
         // Fallback when the FD was not found or isolation is enabled.
-        let enotty = this.eval_libc("ENOTTY")?;
+        let enotty = this.eval_libc("ENOTTY");
         this.set_last_error(enotty)?;
         Ok(Scalar::from_i32(0))
     }
@@ -1711,7 +1725,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         // Reject if isolation is enabled.
         if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op {
             this.reject_in_isolation("`realpath`", reject_with)?;
-            let eacc = this.eval_libc("EACCES")?;
+            let eacc = this.eval_libc("EACCES");
             this.set_last_error(eacc)?;
             return Ok(Scalar::from_machine_usize(0, this));
         }
@@ -1720,7 +1734,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         match result {
             Ok(resolved) => {
                 let path_max = this
-                    .eval_libc_i32("PATH_MAX")?
+                    .eval_libc_i32("PATH_MAX")
                     .try_into()
                     .expect("PATH_MAX does not fit in u64");
                 let dest = if this.ptr_is_null(processed_ptr)? {
@@ -1742,7 +1756,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                         // Note that we do not explicitly handle `FILENAME_MAX`
                         // (different from `PATH_MAX` above) as it is Linux-specific and
                         // seems like a bit of a mess anyway: <https://eklitzke.org/path-max-is-tricky>.
-                        let enametoolong = this.eval_libc("ENAMETOOLONG")?;
+                        let enametoolong = this.eval_libc("ENAMETOOLONG");
                         this.set_last_error(enametoolong)?;
                         return Ok(Scalar::from_machine_usize(0, this));
                     }
@@ -1775,7 +1789,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         //   * The value of `TMP_MAX` is at least 25.
         //   * On XSI-conformant systems, the value of `TMP_MAX` is at least 10000.
         // See <https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/stdio.h.html>.
-        let max_attempts = this.eval_libc("TMP_MAX")?.to_u32()?;
+        let max_attempts = this.eval_libc_u32("TMP_MAX");
 
         // Get the raw bytes from the template -- as a byte slice, this is a string in the target
         // (and the target is unix, so a byte slice is the right representation).
@@ -1786,7 +1800,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         // Reject if isolation is enabled.
         if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op {
             this.reject_in_isolation("`mkstemp`", reject_with)?;
-            let eacc = this.eval_libc("EACCES")?;
+            let eacc = this.eval_libc("EACCES");
             this.set_last_error(eacc)?;
             return Ok(-1);
         }
@@ -1804,7 +1818,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
 
         // If we don't find the suffix, it is an error.
         if last_six_char_bytes != suffix_bytes {
-            let einval = this.eval_libc("EINVAL")?;
+            let einval = this.eval_libc("EINVAL");
             this.set_last_error(einval)?;
             return Ok(-1);
         }
@@ -1880,7 +1894,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         }
 
         // We ran out of attempts to create the file, return an error.
-        let eexist = this.eval_libc("EEXIST")?;
+        let eexist = this.eval_libc("EEXIST");
         this.set_last_error(eexist)?;
         Ok(-1)
     }
@@ -1958,7 +1972,7 @@ impl FileMetadata {
             "S_IFLNK"
         };
 
-        let mode = ecx.eval_libc(mode_name)?;
+        let mode = ecx.eval_libc(mode_name);
 
         let size = metadata.len();
 
diff --git a/src/tools/miri/src/shims/unix/linux/fd.rs b/src/tools/miri/src/shims/unix/linux/fd.rs
new file mode 100644
index 00000000000..212b7936341
--- /dev/null
+++ b/src/tools/miri/src/shims/unix/linux/fd.rs
@@ -0,0 +1,191 @@
+use rustc_middle::ty::ScalarInt;
+
+use crate::*;
+use epoll::{Epoll, EpollEvent};
+use event::Event;
+use socketpair::SocketPair;
+
+use shims::unix::fs::EvalContextExt as _;
+
+pub mod epoll;
+pub mod event;
+pub mod socketpair;
+
+impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
+pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
+    /// This function returns a file descriptor referring to the new `Epoll` instance. This file
+    /// descriptor is used for all subsequent calls to the epoll interface. If the `flags` argument
+    /// is 0, then this function is the same as `epoll_create()`.
+    ///
+    /// <https://linux.die.net/man/2/epoll_create1>
+    fn epoll_create1(
+        &mut self,
+        flags: &OpTy<'tcx, Provenance>,
+    ) -> InterpResult<'tcx, Scalar<Provenance>> {
+        let this = self.eval_context_mut();
+
+        let flags = this.read_scalar(flags)?.to_i32()?;
+
+        let epoll_cloexec = this.eval_libc_i32("EPOLL_CLOEXEC");
+        if flags == epoll_cloexec {
+            // Miri does not support exec, so this flag has no effect.
+        } else if flags != 0 {
+            throw_unsup_format!("epoll_create1 flags {flags} are not implemented");
+        }
+
+        let fd = this.machine.file_handler.insert_fd(Box::new(Epoll::default()));
+        Ok(Scalar::from_i32(fd))
+    }
+
+    /// This function performs control operations on the `Epoll` instance referred to by the file
+    /// descriptor `epfd`. It requests that the operation `op` be performed for the target file
+    /// descriptor, `fd`.
+    ///
+    /// Valid values for the op argument are:
+    /// `EPOLL_CTL_ADD` - Register the target file descriptor `fd` on the `Epoll` instance referred
+    /// to by the file descriptor `epfd` and associate the event `event` with the internal file
+    /// linked to `fd`.
+    /// `EPOLL_CTL_MOD` - Change the event `event` associated with the target file descriptor `fd`.
+    /// `EPOLL_CTL_DEL` - Deregister the target file descriptor `fd` from the `Epoll` instance
+    /// referred to by `epfd`. The `event` is ignored and can be null.
+    ///
+    /// <https://linux.die.net/man/2/epoll_ctl>
+    fn epoll_ctl(
+        &mut self,
+        epfd: &OpTy<'tcx, Provenance>,
+        op: &OpTy<'tcx, Provenance>,
+        fd: &OpTy<'tcx, Provenance>,
+        event: &OpTy<'tcx, Provenance>,
+    ) -> InterpResult<'tcx, Scalar<Provenance>> {
+        let this = self.eval_context_mut();
+
+        let epfd = this.read_scalar(epfd)?.to_i32()?;
+        let op = this.read_scalar(op)?.to_i32()?;
+        let fd = this.read_scalar(fd)?.to_i32()?;
+        let _event = this.read_scalar(event)?.to_pointer(this)?;
+
+        let epoll_ctl_add = this.eval_libc_i32("EPOLL_CTL_ADD");
+        let epoll_ctl_mod = this.eval_libc_i32("EPOLL_CTL_MOD");
+        let epoll_ctl_del = this.eval_libc_i32("EPOLL_CTL_DEL");
+
+        if op == epoll_ctl_add || op == epoll_ctl_mod {
+            let event = this.deref_operand(event)?;
+
+            let events = this.mplace_field(&event, 0)?;
+            let events = this.read_scalar(&events.into())?.to_u32()?;
+            let data = this.mplace_field(&event, 1)?;
+            let data = this.read_scalar(&data.into())?;
+            let event = EpollEvent { events, data };
+
+            if let Some(epfd) = this.machine.file_handler.handles.get_mut(&epfd) {
+                let epfd = epfd.as_epoll_handle()?;
+
+                epfd.file_descriptors.insert(fd, event);
+                Ok(Scalar::from_i32(0))
+            } else {
+                Ok(Scalar::from_i32(this.handle_not_found()?))
+            }
+        } else if op == epoll_ctl_del {
+            if let Some(epfd) = this.machine.file_handler.handles.get_mut(&epfd) {
+                let epfd = epfd.as_epoll_handle()?;
+
+                epfd.file_descriptors.remove(&fd);
+                Ok(Scalar::from_i32(0))
+            } else {
+                Ok(Scalar::from_i32(this.handle_not_found()?))
+            }
+        } else {
+            let einval = this.eval_libc("EINVAL");
+            this.set_last_error(einval)?;
+            Ok(Scalar::from_i32(-1))
+        }
+    }
+
+    /// This function creates an `Event` that is used as an event wait/notify mechanism by
+    /// user-space applications, and by the kernel to notify user-space applications of events.
+    /// The `Event` contains an `u64` counter maintained by the kernel. The counter is initialized
+    /// with the value specified in the `initval` argument.
+    ///
+    /// A new file descriptor referring to the `Event` is returned. The `read`, `write`, `poll`,
+    /// `select`, and `close` operations can be performed on the file descriptor. For more
+    /// information on these operations, see the man page linked below.
+    ///
+    /// The `flags` are not currently implemented for eventfd.
+    /// The `flags` may be bitwise ORed to change the behavior of `eventfd`:
+    /// `EFD_CLOEXEC` - Set the close-on-exec (`FD_CLOEXEC`) flag on the new file descriptor.
+    /// `EFD_NONBLOCK` - Set the `O_NONBLOCK` file status flag on the new open file description.
+    /// `EFD_SEMAPHORE` - miri does not support semaphore-like semantics.
+    ///
+    /// <https://linux.die.net/man/2/eventfd>
+    fn eventfd(
+        &mut self,
+        val: &OpTy<'tcx, Provenance>,
+        flags: &OpTy<'tcx, Provenance>,
+    ) -> InterpResult<'tcx, Scalar<Provenance>> {
+        let this = self.eval_context_mut();
+
+        let val = this.read_scalar(val)?.to_u32()?;
+        let flags = this.read_scalar(flags)?.to_i32()?;
+
+        let efd_cloexec = this.eval_libc_i32("EFD_CLOEXEC");
+        let efd_nonblock = this.eval_libc_i32("EFD_NONBLOCK");
+        let efd_semaphore = this.eval_libc_i32("EFD_SEMAPHORE");
+
+        if flags & (efd_cloexec | efd_nonblock | efd_semaphore) == 0 {
+            throw_unsup_format!("{flags} is unsupported");
+        }
+        // FIXME handle the cloexec and nonblock flags
+        if flags & efd_cloexec == efd_cloexec {}
+        if flags & efd_nonblock == efd_nonblock {}
+        if flags & efd_semaphore == efd_semaphore {
+            throw_unsup_format!("EFD_SEMAPHORE is unsupported");
+        }
+
+        let fh = &mut this.machine.file_handler;
+        let fd = fh.insert_fd(Box::new(Event { val }));
+        Ok(Scalar::from_i32(fd))
+    }
+
+    /// Currently this function creates new `SocketPair`s without specifying the domain, type, or
+    /// protocol of the new socket and these are stored in the socket values `sv` argument.
+    ///
+    /// This function creates an unnamed pair of connected sockets in the specified domain, of the
+    /// specified type, and using the optionally specified protocol.
+    ///
+    /// The `domain` argument specified a communication domain; this selects the protocol family
+    /// used for communication. The socket `type` specifies the communication semantics.
+    /// The `protocol` specifies a particular protocol to use with the socket. Normally there's
+    /// only a single protocol supported for a particular socket type within a given protocol
+    /// family, in which case `protocol` can be specified as 0. It is possible that many protocols
+    /// exist and in that case, a particular protocol must be specified.
+    ///
+    /// For more information on the arguments see the socket manpage:
+    /// <https://linux.die.net/man/2/socket>
+    ///
+    /// <https://linux.die.net/man/2/socketpair>
+    fn socketpair(
+        &mut self,
+        domain: &OpTy<'tcx, Provenance>,
+        type_: &OpTy<'tcx, Provenance>,
+        protocol: &OpTy<'tcx, Provenance>,
+        sv: &OpTy<'tcx, Provenance>,
+    ) -> InterpResult<'tcx, Scalar<Provenance>> {
+        let this = self.eval_context_mut();
+
+        let _domain = this.read_scalar(domain)?.to_i32()?;
+        let _type_ = this.read_scalar(type_)?.to_i32()?;
+        let _protocol = this.read_scalar(protocol)?.to_i32()?;
+        let sv = this.deref_operand(sv)?;
+
+        let fh = &mut this.machine.file_handler;
+        let sv0 = fh.insert_fd(Box::new(SocketPair));
+        let sv0 = ScalarInt::try_from_int(sv0, sv.layout.size).unwrap();
+        let sv1 = fh.insert_fd(Box::new(SocketPair));
+        let sv1 = ScalarInt::try_from_int(sv1, sv.layout.size).unwrap();
+
+        this.write_scalar(sv0, &sv.into())?;
+        this.write_scalar(sv1, &sv.offset(sv.layout.size, sv.layout, this)?.into())?;
+
+        Ok(Scalar::from_i32(0))
+    }
+}
diff --git a/src/tools/miri/src/shims/unix/linux/fd/epoll.rs b/src/tools/miri/src/shims/unix/linux/fd/epoll.rs
new file mode 100644
index 00000000000..e33673fecf6
--- /dev/null
+++ b/src/tools/miri/src/shims/unix/linux/fd/epoll.rs
@@ -0,0 +1,53 @@
+use crate::*;
+
+use crate::shims::unix::fs::FileDescriptor;
+
+use rustc_data_structures::fx::FxHashMap;
+use std::io;
+
+/// An `Epoll` file descriptor connects file handles and epoll events
+#[derive(Clone, Debug, Default)]
+pub struct Epoll {
+    /// The file descriptors we are watching, and what we are watching for.
+    pub file_descriptors: FxHashMap<i32, EpollEvent>,
+}
+
+/// Epoll Events associate events with data.
+/// These fields are currently unused by miri.
+/// This matches the `epoll_event` struct defined
+/// by the epoll_ctl man page. For more information
+/// see the man page:
+///
+/// <https://man7.org/linux/man-pages/man2/epoll_ctl.2.html>
+#[derive(Clone, Debug)]
+pub struct EpollEvent {
+    pub events: u32,
+    /// `Scalar<Provenance>` is used to represent the
+    /// `epoll_data` type union.
+    pub data: Scalar<Provenance>,
+}
+
+impl FileDescriptor for Epoll {
+    fn name(&self) -> &'static str {
+        "epoll"
+    }
+
+    fn as_epoll_handle<'tcx>(&mut self) -> InterpResult<'tcx, &mut Epoll> {
+        Ok(self)
+    }
+
+    fn dup(&mut self) -> io::Result<Box<dyn FileDescriptor>> {
+        Ok(Box::new(self.clone()))
+    }
+
+    fn is_tty(&self) -> bool {
+        false
+    }
+
+    fn close<'tcx>(
+        self: Box<Self>,
+        _communicate_allowed: bool,
+    ) -> InterpResult<'tcx, io::Result<i32>> {
+        Ok(Ok(0))
+    }
+}
diff --git a/src/tools/miri/src/shims/unix/linux/fd/event.rs b/src/tools/miri/src/shims/unix/linux/fd/event.rs
new file mode 100644
index 00000000000..239eb462a1d
--- /dev/null
+++ b/src/tools/miri/src/shims/unix/linux/fd/event.rs
@@ -0,0 +1,38 @@
+use crate::shims::unix::fs::FileDescriptor;
+
+use rustc_const_eval::interpret::InterpResult;
+
+use std::io;
+
+/// A kind of file descriptor created by `eventfd`.
+/// The `Event` type isn't currently written to by `eventfd`.
+/// The interface is meant to keep track of objects associated
+/// with a file descriptor. For more information see the man
+/// page below:
+///
+/// <https://man.netbsd.org/eventfd.2>
+#[derive(Debug)]
+pub struct Event {
+    pub val: u32,
+}
+
+impl FileDescriptor for Event {
+    fn name(&self) -> &'static str {
+        "event"
+    }
+
+    fn dup(&mut self) -> io::Result<Box<dyn FileDescriptor>> {
+        Ok(Box::new(Event { val: self.val }))
+    }
+
+    fn is_tty(&self) -> bool {
+        false
+    }
+
+    fn close<'tcx>(
+        self: Box<Self>,
+        _communicate_allowed: bool,
+    ) -> InterpResult<'tcx, io::Result<i32>> {
+        Ok(Ok(0))
+    }
+}
diff --git a/src/tools/miri/src/shims/unix/linux/fd/socketpair.rs b/src/tools/miri/src/shims/unix/linux/fd/socketpair.rs
new file mode 100644
index 00000000000..f9e56b4a2b4
--- /dev/null
+++ b/src/tools/miri/src/shims/unix/linux/fd/socketpair.rs
@@ -0,0 +1,32 @@
+use crate::*;
+
+use crate::shims::unix::fs::FileDescriptor;
+
+use std::io;
+
+/// Pair of connected sockets.
+///
+/// We currently don't allow sending any data through this pair, so this can be just a dummy.
+#[derive(Debug)]
+pub struct SocketPair;
+
+impl FileDescriptor for SocketPair {
+    fn name(&self) -> &'static str {
+        "socketpair"
+    }
+
+    fn dup(&mut self) -> io::Result<Box<dyn FileDescriptor>> {
+        Ok(Box::new(SocketPair))
+    }
+
+    fn is_tty(&self) -> bool {
+        false
+    }
+
+    fn close<'tcx>(
+        self: Box<Self>,
+        _communicate_allowed: bool,
+    ) -> InterpResult<'tcx, io::Result<i32>> {
+        Ok(Ok(0))
+    }
+}
diff --git a/src/tools/miri/src/shims/unix/linux/foreign_items.rs b/src/tools/miri/src/shims/unix/linux/foreign_items.rs
index 34076e842d5..82cb21c124a 100644
--- a/src/tools/miri/src/shims/unix/linux/foreign_items.rs
+++ b/src/tools/miri/src/shims/unix/linux/foreign_items.rs
@@ -1,9 +1,11 @@
 use rustc_span::Symbol;
 use rustc_target::spec::abi::Abi;
 
+use crate::machine::SIGRTMAX;
 use crate::*;
 use shims::foreign_items::EmulateByNameResult;
 use shims::unix::fs::EvalContextExt as _;
+use shims::unix::linux::fd::EvalContextExt as _;
 use shims::unix::linux::sync::futex;
 use shims::unix::sync::EvalContextExt as _;
 use shims::unix::thread::EvalContextExt as _;
@@ -42,6 +44,35 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 let result = this.sync_file_range(fd, offset, nbytes, flags)?;
                 this.write_scalar(result, dest)?;
             }
+            "epoll_create1" => {
+                let [flag] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
+                let result = this.epoll_create1(flag)?;
+                this.write_scalar(result, dest)?;
+            }
+            "epoll_ctl" => {
+                let [epfd, op, fd, event] =
+                    this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
+                let result = this.epoll_ctl(epfd, op, fd, event)?;
+                this.write_scalar(result, dest)?;
+            }
+            "eventfd" => {
+                let [val, flag] =
+                    this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
+                let result = this.eventfd(val, flag)?;
+                this.write_scalar(result, dest)?;
+            }
+            "socketpair" => {
+                let [domain, type_, protocol, sv] =
+                    this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
+
+                let result = this.socketpair(domain, type_, protocol, sv)?;
+                this.write_scalar(result, dest)?;
+            }
+            "__libc_current_sigrtmax" => {
+                let [] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
+
+                this.write_scalar(Scalar::from_i32(SIGRTMAX), dest)?;
+            }
 
             // Threading
             "pthread_condattr_setclock" => {
@@ -88,18 +119,18 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 // argument, we have to also check all arguments *before* it to ensure that they
                 // have the right type.
 
-                let sys_getrandom = this.eval_libc("SYS_getrandom")?.to_machine_usize(this)?;
+                let sys_getrandom = this.eval_libc("SYS_getrandom").to_machine_usize(this)?;
 
-                let sys_statx = this.eval_libc("SYS_statx")?.to_machine_usize(this)?;
+                let sys_statx = this.eval_libc("SYS_statx").to_machine_usize(this)?;
 
-                let sys_futex = this.eval_libc("SYS_futex")?.to_machine_usize(this)?;
+                let sys_futex = this.eval_libc("SYS_futex").to_machine_usize(this)?;
 
                 if args.is_empty() {
                     throw_ub_format!(
                         "incorrect number of arguments for syscall: got 0, expected at least 1"
                     );
                 }
-                match this.read_scalar(&args[0])?.to_machine_usize(this)? {
+                match this.read_machine_usize(&args[0])? {
                     // `libc::syscall(NR_GETRANDOM, buf.as_mut_ptr(), buf.len(), GRND_NONBLOCK)`
                     // is called if a `HashMap` is created the regular way (e.g. HashMap<K, V>).
                     id if id == sys_getrandom => {
@@ -147,10 +178,10 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 let [pid, cpusetsize, mask] =
                     this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
                 this.read_scalar(pid)?.to_i32()?;
-                this.read_scalar(cpusetsize)?.to_machine_usize(this)?;
+                this.read_machine_usize(cpusetsize)?;
                 this.deref_operand(mask)?;
                 // FIXME: we just return an error; `num_cpus` then falls back to `sysconf`.
-                let einval = this.eval_libc("EINVAL")?;
+                let einval = this.eval_libc("EINVAL");
                 this.set_last_error(einval)?;
                 this.write_scalar(Scalar::from_i32(-1), dest)?;
             }
@@ -179,7 +210,7 @@ fn getrandom<'tcx>(
     dest: &PlaceTy<'tcx, Provenance>,
 ) -> InterpResult<'tcx> {
     let ptr = this.read_pointer(ptr)?;
-    let len = this.read_scalar(len)?.to_machine_usize(this)?;
+    let len = this.read_machine_usize(len)?;
 
     // The only supported flags are GRND_RANDOM and GRND_NONBLOCK,
     // neither of which have any effect on our current PRNG.
diff --git a/src/tools/miri/src/shims/unix/linux/mod.rs b/src/tools/miri/src/shims/unix/linux/mod.rs
index 498eb57c57f..437764c3824 100644
--- a/src/tools/miri/src/shims/unix/linux/mod.rs
+++ b/src/tools/miri/src/shims/unix/linux/mod.rs
@@ -1,3 +1,4 @@
 pub mod dlsym;
+pub mod fd;
 pub mod foreign_items;
 pub mod sync;
diff --git a/src/tools/miri/src/shims/unix/linux/sync.rs b/src/tools/miri/src/shims/unix/linux/sync.rs
index 343232c4bbb..ef43c9b0ff4 100644
--- a/src/tools/miri/src/shims/unix/linux/sync.rs
+++ b/src/tools/miri/src/shims/unix/linux/sync.rs
@@ -37,12 +37,12 @@ pub fn futex<'tcx>(
     let addr = MPlaceTy::from_aligned_ptr(addr, this.machine.layouts.i32);
     let addr_usize = addr.ptr.addr().bytes();
 
-    let futex_private = this.eval_libc_i32("FUTEX_PRIVATE_FLAG")?;
-    let futex_wait = this.eval_libc_i32("FUTEX_WAIT")?;
-    let futex_wait_bitset = this.eval_libc_i32("FUTEX_WAIT_BITSET")?;
-    let futex_wake = this.eval_libc_i32("FUTEX_WAKE")?;
-    let futex_wake_bitset = this.eval_libc_i32("FUTEX_WAKE_BITSET")?;
-    let futex_realtime = this.eval_libc_i32("FUTEX_CLOCK_REALTIME")?;
+    let futex_private = this.eval_libc_i32("FUTEX_PRIVATE_FLAG");
+    let futex_wait = this.eval_libc_i32("FUTEX_WAIT");
+    let futex_wait_bitset = this.eval_libc_i32("FUTEX_WAIT_BITSET");
+    let futex_wake = this.eval_libc_i32("FUTEX_WAKE");
+    let futex_wake_bitset = this.eval_libc_i32("FUTEX_WAKE_BITSET");
+    let futex_realtime = this.eval_libc_i32("FUTEX_CLOCK_REALTIME");
 
     // FUTEX_PRIVATE enables an optimization that stops it from working across processes.
     // Miri doesn't support that anyway, so we ignore that flag.
@@ -79,7 +79,7 @@ pub fn futex<'tcx>(
             };
 
             if bitset == 0 {
-                let einval = this.eval_libc("EINVAL")?;
+                let einval = this.eval_libc("EINVAL");
                 this.set_last_error(einval)?;
                 this.write_scalar(Scalar::from_machine_isize(-1, this), dest)?;
                 return Ok(());
@@ -90,7 +90,8 @@ pub fn futex<'tcx>(
             let timeout_time = if this.ptr_is_null(timeout.ptr)? {
                 None
             } else {
-                if op & futex_realtime != 0 {
+                let realtime = op & futex_realtime == futex_realtime;
+                if realtime {
                     this.check_no_isolation(
                         "`futex` syscall with `op=FUTEX_WAIT` and non-null timeout with `FUTEX_CLOCK_REALTIME`",
                     )?;
@@ -98,7 +99,7 @@ pub fn futex<'tcx>(
                 let duration = match this.read_timespec(&timeout)? {
                     Some(duration) => duration,
                     None => {
-                        let einval = this.eval_libc("EINVAL")?;
+                        let einval = this.eval_libc("EINVAL");
                         this.set_last_error(einval)?;
                         this.write_scalar(Scalar::from_machine_isize(-1, this), dest)?;
                         return Ok(());
@@ -106,14 +107,14 @@ pub fn futex<'tcx>(
                 };
                 Some(if wait_bitset {
                     // FUTEX_WAIT_BITSET uses an absolute timestamp.
-                    if op & futex_realtime != 0 {
+                    if realtime {
                         Time::RealTime(SystemTime::UNIX_EPOCH.checked_add(duration).unwrap())
                     } else {
                         Time::Monotonic(this.machine.clock.anchor().checked_add(duration).unwrap())
                     }
                 } else {
                     // FUTEX_WAIT uses a relative timestamp.
-                    if op & futex_realtime != 0 {
+                    if realtime {
                         Time::RealTime(SystemTime::now().checked_add(duration).unwrap())
                     } else {
                         Time::Monotonic(this.machine.clock.now().checked_add(duration).unwrap())
@@ -193,7 +194,7 @@ pub fn futex<'tcx>(
                         fn call(&self, this: &mut MiriInterpCx<'mir, 'tcx>) -> InterpResult<'tcx> {
                             this.unblock_thread(self.thread);
                             this.futex_remove_waiter(self.addr_usize, self.thread);
-                            let etimedout = this.eval_libc("ETIMEDOUT")?;
+                            let etimedout = this.eval_libc("ETIMEDOUT");
                             this.set_last_error(etimedout)?;
                             this.write_scalar(Scalar::from_machine_isize(-1, this), &self.dest)?;
 
@@ -210,7 +211,7 @@ pub fn futex<'tcx>(
             } else {
                 // The futex value doesn't match the expected value, so we return failure
                 // right away without sleeping: -1 and errno set to EAGAIN.
-                let eagain = this.eval_libc("EAGAIN")?;
+                let eagain = this.eval_libc("EAGAIN");
                 this.set_last_error(eagain)?;
                 this.write_scalar(Scalar::from_machine_isize(-1, this), dest)?;
             }
@@ -236,7 +237,7 @@ pub fn futex<'tcx>(
                 u32::MAX
             };
             if bitset == 0 {
-                let einval = this.eval_libc("EINVAL")?;
+                let einval = this.eval_libc("EINVAL");
                 this.set_last_error(einval)?;
                 this.write_scalar(Scalar::from_machine_isize(-1, this), dest)?;
                 return Ok(());
diff --git a/src/tools/miri/src/shims/unix/macos/dlsym.rs b/src/tools/miri/src/shims/unix/macos/dlsym.rs
index 18804b45efc..44b9af79005 100644
--- a/src/tools/miri/src/shims/unix/macos/dlsym.rs
+++ b/src/tools/miri/src/shims/unix/macos/dlsym.rs
@@ -39,7 +39,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
             Dlsym::getentropy => {
                 let [ptr, len] = check_arg_count(args)?;
                 let ptr = this.read_pointer(ptr)?;
-                let len = this.read_scalar(len)?.to_machine_usize(this)?;
+                let len = this.read_machine_usize(len)?;
                 this.gen_random(ptr, len)?;
                 this.write_null(dest)?;
             }
diff --git a/src/tools/miri/src/shims/unix/macos/foreign_items.rs b/src/tools/miri/src/shims/unix/macos/foreign_items.rs
index 221dc39697f..a55b0ee523b 100644
--- a/src/tools/miri/src/shims/unix/macos/foreign_items.rs
+++ b/src/tools/miri/src/shims/unix/macos/foreign_items.rs
@@ -161,14 +161,14 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
             // Querying system information
             "pthread_get_stackaddr_np" => {
                 let [thread] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
-                this.read_scalar(thread)?.to_machine_usize(this)?;
-                let stack_addr = Scalar::from_uint(STACK_ADDR, this.pointer_size());
+                this.read_machine_usize(thread)?;
+                let stack_addr = Scalar::from_uint(this.machine.stack_addr, this.pointer_size());
                 this.write_scalar(stack_addr, dest)?;
             }
             "pthread_get_stacksize_np" => {
                 let [thread] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
-                this.read_scalar(thread)?.to_machine_usize(this)?;
-                let stack_size = Scalar::from_uint(STACK_SIZE, this.pointer_size());
+                this.read_machine_usize(thread)?;
+                let stack_size = Scalar::from_uint(this.machine.stack_size, this.pointer_size());
                 this.write_scalar(stack_size, dest)?;
             }
 
@@ -176,7 +176,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
             "pthread_setname_np" => {
                 let [name] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
                 let thread = this.pthread_self()?;
-                let max_len = this.eval_libc("MAXTHREADNAMESIZE")?.to_machine_usize(this)?;
+                let max_len = this.eval_libc("MAXTHREADNAMESIZE").to_machine_usize(this)?;
                 let res = this.pthread_setname_np(
                     thread,
                     this.read_scalar(name)?,
diff --git a/src/tools/miri/src/shims/unix/sync.rs b/src/tools/miri/src/shims/unix/sync.rs
index f9b5774f009..b3c474dd3c9 100644
--- a/src/tools/miri/src/shims/unix/sync.rs
+++ b/src/tools/miri/src/shims/unix/sync.rs
@@ -21,14 +21,14 @@ fn is_mutex_kind_default<'mir, 'tcx: 'mir>(
     ecx: &mut MiriInterpCx<'mir, 'tcx>,
     kind: i32,
 ) -> InterpResult<'tcx, bool> {
-    Ok(kind == ecx.eval_libc_i32("PTHREAD_MUTEX_DEFAULT")?)
+    Ok(kind == ecx.eval_libc_i32("PTHREAD_MUTEX_DEFAULT"))
 }
 
 fn is_mutex_kind_normal<'mir, 'tcx: 'mir>(
     ecx: &mut MiriInterpCx<'mir, 'tcx>,
     kind: i32,
 ) -> InterpResult<'tcx, bool> {
-    let mutex_normal_kind = ecx.eval_libc_i32("PTHREAD_MUTEX_NORMAL")?;
+    let mutex_normal_kind = ecx.eval_libc_i32("PTHREAD_MUTEX_NORMAL");
     Ok(kind == (mutex_normal_kind | PTHREAD_MUTEX_NORMAL_FLAG))
 }
 
@@ -217,7 +217,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
     ) -> InterpResult<'tcx, i32> {
         let this = self.eval_context_mut();
 
-        let default_kind = this.eval_libc_i32("PTHREAD_MUTEX_DEFAULT")?;
+        let default_kind = this.eval_libc_i32("PTHREAD_MUTEX_DEFAULT");
         mutexattr_set_kind(this, attr_op, default_kind)?;
 
         Ok(0)
@@ -231,7 +231,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         let this = self.eval_context_mut();
 
         let kind = this.read_scalar(kind_op)?.to_i32()?;
-        if kind == this.eval_libc_i32("PTHREAD_MUTEX_NORMAL")? {
+        if kind == this.eval_libc_i32("PTHREAD_MUTEX_NORMAL") {
             // In `glibc` implementation, the numeric values of
             // `PTHREAD_MUTEX_NORMAL` and `PTHREAD_MUTEX_DEFAULT` are equal.
             // However, a mutex created by explicitly passing
@@ -247,17 +247,17 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
             let normal_kind = kind | PTHREAD_MUTEX_NORMAL_FLAG;
             // Check that after setting the flag, the kind is distinguishable
             // from all other kinds.
-            assert_ne!(normal_kind, this.eval_libc_i32("PTHREAD_MUTEX_DEFAULT")?);
-            assert_ne!(normal_kind, this.eval_libc_i32("PTHREAD_MUTEX_ERRORCHECK")?);
-            assert_ne!(normal_kind, this.eval_libc_i32("PTHREAD_MUTEX_RECURSIVE")?);
+            assert_ne!(normal_kind, this.eval_libc_i32("PTHREAD_MUTEX_DEFAULT"));
+            assert_ne!(normal_kind, this.eval_libc_i32("PTHREAD_MUTEX_ERRORCHECK"));
+            assert_ne!(normal_kind, this.eval_libc_i32("PTHREAD_MUTEX_RECURSIVE"));
             mutexattr_set_kind(this, attr_op, normal_kind)?;
-        } else if kind == this.eval_libc_i32("PTHREAD_MUTEX_DEFAULT")?
-            || kind == this.eval_libc_i32("PTHREAD_MUTEX_ERRORCHECK")?
-            || kind == this.eval_libc_i32("PTHREAD_MUTEX_RECURSIVE")?
+        } else if kind == this.eval_libc_i32("PTHREAD_MUTEX_DEFAULT")
+            || kind == this.eval_libc_i32("PTHREAD_MUTEX_ERRORCHECK")
+            || kind == this.eval_libc_i32("PTHREAD_MUTEX_RECURSIVE")
         {
             mutexattr_set_kind(this, attr_op, kind)?;
         } else {
-            let einval = this.eval_libc_i32("EINVAL")?;
+            let einval = this.eval_libc_i32("EINVAL");
             return Ok(einval);
         }
 
@@ -299,7 +299,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
 
         let attr = this.read_pointer(attr_op)?;
         let kind = if this.ptr_is_null(attr)? {
-            this.eval_libc_i32("PTHREAD_MUTEX_DEFAULT")?
+            this.eval_libc_i32("PTHREAD_MUTEX_DEFAULT")
         } else {
             mutexattr_get_kind(this, attr_op)?
         };
@@ -331,9 +331,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                     throw_ub_format!("trying to acquire already locked default mutex");
                 } else if is_mutex_kind_normal(this, kind)? {
                     throw_machine_stop!(TerminationInfo::Deadlock);
-                } else if kind == this.eval_libc_i32("PTHREAD_MUTEX_ERRORCHECK")? {
-                    this.eval_libc_i32("EDEADLK")
-                } else if kind == this.eval_libc_i32("PTHREAD_MUTEX_RECURSIVE")? {
+                } else if kind == this.eval_libc_i32("PTHREAD_MUTEX_ERRORCHECK") {
+                    Ok(this.eval_libc_i32("EDEADLK"))
+                } else if kind == this.eval_libc_i32("PTHREAD_MUTEX_RECURSIVE") {
                     this.mutex_lock(id, active_thread);
                     Ok(0)
                 } else {
@@ -362,14 +362,14 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         if this.mutex_is_locked(id) {
             let owner_thread = this.mutex_get_owner(id);
             if owner_thread != active_thread {
-                this.eval_libc_i32("EBUSY")
+                Ok(this.eval_libc_i32("EBUSY"))
             } else {
                 if is_mutex_kind_default(this, kind)?
                     || is_mutex_kind_normal(this, kind)?
-                    || kind == this.eval_libc_i32("PTHREAD_MUTEX_ERRORCHECK")?
+                    || kind == this.eval_libc_i32("PTHREAD_MUTEX_ERRORCHECK")
                 {
-                    this.eval_libc_i32("EBUSY")
-                } else if kind == this.eval_libc_i32("PTHREAD_MUTEX_RECURSIVE")? {
+                    Ok(this.eval_libc_i32("EBUSY"))
+                } else if kind == this.eval_libc_i32("PTHREAD_MUTEX_RECURSIVE") {
                     this.mutex_lock(id, active_thread);
                     Ok(0)
                 } else {
@@ -410,10 +410,10 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 throw_ub_format!(
                     "unlocked a PTHREAD_MUTEX_NORMAL mutex that was not locked by the current thread"
                 );
-            } else if kind == this.eval_libc_i32("PTHREAD_MUTEX_ERRORCHECK")?
-                || kind == this.eval_libc_i32("PTHREAD_MUTEX_RECURSIVE")?
+            } else if kind == this.eval_libc_i32("PTHREAD_MUTEX_ERRORCHECK")
+                || kind == this.eval_libc_i32("PTHREAD_MUTEX_RECURSIVE")
             {
-                this.eval_libc_i32("EPERM")
+                Ok(this.eval_libc_i32("EPERM"))
             } else {
                 throw_unsup_format!("called pthread_mutex_unlock on an unsupported type of mutex");
             }
@@ -471,7 +471,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         let active_thread = this.get_active_thread();
 
         if this.rwlock_is_write_locked(id) {
-            this.eval_libc_i32("EBUSY")
+            Ok(this.eval_libc_i32("EBUSY"))
         } else {
             this.rwlock_reader_lock(id, active_thread);
             Ok(0)
@@ -518,7 +518,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         let active_thread = this.get_active_thread();
 
         if this.rwlock_is_locked(id) {
-            this.eval_libc_i32("EBUSY")
+            Ok(this.eval_libc_i32("EBUSY"))
         } else {
             this.rwlock_writer_lock(id, active_thread);
             Ok(0)
@@ -575,7 +575,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         // The default value of the clock attribute shall refer to the system
         // clock.
         // https://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_condattr_setclock.html
-        let default_clock_id = this.eval_libc_i32("CLOCK_REALTIME")?;
+        let default_clock_id = this.eval_libc_i32("CLOCK_REALTIME");
         condattr_set_clock_id(this, attr_op, default_clock_id)?;
 
         Ok(0)
@@ -589,12 +589,12 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         let this = self.eval_context_mut();
 
         let clock_id = this.read_scalar(clock_id_op)?.to_i32()?;
-        if clock_id == this.eval_libc_i32("CLOCK_REALTIME")?
-            || clock_id == this.eval_libc_i32("CLOCK_MONOTONIC")?
+        if clock_id == this.eval_libc_i32("CLOCK_REALTIME")
+            || clock_id == this.eval_libc_i32("CLOCK_MONOTONIC")
         {
             condattr_set_clock_id(this, attr_op, clock_id)?;
         } else {
-            let einval = this.eval_libc_i32("EINVAL")?;
+            let einval = this.eval_libc_i32("EINVAL");
             return Ok(Scalar::from_i32(einval));
         }
 
@@ -638,7 +638,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
 
         let attr = this.read_pointer(attr_op)?;
         let clock_id = if this.ptr_is_null(attr)? {
-            this.eval_libc_i32("CLOCK_REALTIME")?
+            this.eval_libc_i32("CLOCK_REALTIME")
         } else {
             condattr_get_clock_id(this, attr_op)?
         };
@@ -718,16 +718,16 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         let duration = match this.read_timespec(&this.deref_operand(abstime_op)?)? {
             Some(duration) => duration,
             None => {
-                let einval = this.eval_libc("EINVAL")?;
+                let einval = this.eval_libc("EINVAL");
                 this.write_scalar(einval, dest)?;
                 return Ok(());
             }
         };
 
-        let timeout_time = if clock_id == this.eval_libc_i32("CLOCK_REALTIME")? {
+        let timeout_time = if clock_id == this.eval_libc_i32("CLOCK_REALTIME") {
             this.check_no_isolation("`pthread_cond_timedwait` with `CLOCK_REALTIME`")?;
             Time::RealTime(SystemTime::UNIX_EPOCH.checked_add(duration).unwrap())
-        } else if clock_id == this.eval_libc_i32("CLOCK_MONOTONIC")? {
+        } else if clock_id == this.eval_libc_i32("CLOCK_MONOTONIC") {
             Time::Monotonic(this.machine.clock.anchor().checked_add(duration).unwrap())
         } else {
             throw_unsup_format!("unsupported clock id: {}", clock_id);
@@ -763,7 +763,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 ecx.condvar_remove_waiter(self.id, self.active_thread);
 
                 // Set the return value: we timed out.
-                let etimedout = ecx.eval_libc("ETIMEDOUT")?;
+                let etimedout = ecx.eval_libc("ETIMEDOUT");
                 ecx.write_scalar(etimedout, &self.dest)?;
 
                 Ok(())
diff --git a/src/tools/miri/src/shims/unix/thread.rs b/src/tools/miri/src/shims/unix/thread.rs
index 5b9dc90f0f0..832628003d7 100644
--- a/src/tools/miri/src/shims/unix/thread.rs
+++ b/src/tools/miri/src/shims/unix/thread.rs
@@ -42,7 +42,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
             throw_unsup_format!("Miri supports pthread_join only with retval==NULL");
         }
 
-        let thread_id = this.read_scalar(thread)?.to_machine_usize(this)?;
+        let thread_id = this.read_machine_usize(thread)?;
         this.join_thread_exclusive(thread_id.try_into().expect("thread ID should fit in u32"))?;
 
         Ok(0)
@@ -51,7 +51,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
     fn pthread_detach(&mut self, thread: &OpTy<'tcx, Provenance>) -> InterpResult<'tcx, i32> {
         let this = self.eval_context_mut();
 
-        let thread_id = this.read_scalar(thread)?.to_machine_usize(this)?;
+        let thread_id = this.read_machine_usize(thread)?;
         this.detach_thread(
             thread_id.try_into().expect("thread ID should fit in u32"),
             /*allow_terminated_joined*/ false,
@@ -84,7 +84,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
 
         // Comparing with `>=` to account for null terminator.
         if name.len() >= max_name_len {
-            return this.eval_libc("ERANGE");
+            return Ok(this.eval_libc("ERANGE"));
         }
 
         this.set_thread_name(thread, name);
@@ -107,7 +107,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         let name = this.get_thread_name(thread).to_owned();
         let (success, _written) = this.write_c_str(&name, name_out, len)?;
 
-        if success { Ok(Scalar::from_u32(0)) } else { this.eval_libc("ERANGE") }
+        Ok(if success { Scalar::from_u32(0) } else { this.eval_libc("ERANGE") })
     }
 
     fn sched_yield(&mut self) -> InterpResult<'tcx, i32> {
diff --git a/src/tools/miri/src/shims/windows/dlsym.rs b/src/tools/miri/src/shims/windows/dlsym.rs
index 4b2a90723c7..857cf1ae703 100644
--- a/src/tools/miri/src/shims/windows/dlsym.rs
+++ b/src/tools/miri/src/shims/windows/dlsym.rs
@@ -67,10 +67,10 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                     byte_offset,
                     _key,
                 ] = check_arg_count(args)?;
-                let handle = this.read_scalar(handle)?.to_machine_isize(this)?;
+                let handle = this.read_machine_isize(handle)?;
                 let buf = this.read_pointer(buf)?;
                 let n = this.read_scalar(n)?.to_u32()?;
-                let byte_offset = this.read_scalar(byte_offset)?.to_machine_usize(this)?; // is actually a pointer
+                let byte_offset = this.read_machine_usize(byte_offset)?; // is actually a pointer
                 let io_status_block = this.deref_operand(io_status_block)?;
 
                 if byte_offset != 0 {
diff --git a/src/tools/miri/src/shims/windows/foreign_items.rs b/src/tools/miri/src/shims/windows/foreign_items.rs
index e16749c986b..1da8f7c0e3e 100644
--- a/src/tools/miri/src/shims/windows/foreign_items.rs
+++ b/src/tools/miri/src/shims/windows/foreign_items.rs
@@ -73,17 +73,18 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
             "HeapAlloc" => {
                 let [handle, flags, size] =
                     this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?;
-                this.read_scalar(handle)?.to_machine_isize(this)?;
+                this.read_machine_isize(handle)?;
                 let flags = this.read_scalar(flags)?.to_u32()?;
-                let size = this.read_scalar(size)?.to_machine_usize(this)?;
-                let zero_init = (flags & 0x00000008) != 0; // HEAP_ZERO_MEMORY
+                let size = this.read_machine_usize(size)?;
+                let heap_zero_memory = 0x00000008; // HEAP_ZERO_MEMORY
+                let zero_init = (flags & heap_zero_memory) == heap_zero_memory;
                 let res = this.malloc(size, zero_init, MiriMemoryKind::WinHeap)?;
                 this.write_pointer(res, dest)?;
             }
             "HeapFree" => {
                 let [handle, flags, ptr] =
                     this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?;
-                this.read_scalar(handle)?.to_machine_isize(this)?;
+                this.read_machine_isize(handle)?;
                 this.read_scalar(flags)?.to_u32()?;
                 let ptr = this.read_pointer(ptr)?;
                 this.free(ptr, MiriMemoryKind::WinHeap)?;
@@ -92,10 +93,10 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
             "HeapReAlloc" => {
                 let [handle, flags, ptr, size] =
                     this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?;
-                this.read_scalar(handle)?.to_machine_isize(this)?;
+                this.read_machine_isize(handle)?;
                 this.read_scalar(flags)?.to_u32()?;
                 let ptr = this.read_pointer(ptr)?;
-                let size = this.read_scalar(size)?.to_machine_usize(this)?;
+                let size = this.read_machine_usize(size)?;
                 let res = this.realloc(ptr, size, MiriMemoryKind::WinHeap)?;
                 this.write_pointer(res, dest)?;
             }
@@ -158,7 +159,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 // Set page size.
                 let page_size = system_info.offset(field_offsets[2], dword_layout, &this.tcx)?;
                 this.write_scalar(
-                    Scalar::from_int(PAGE_SIZE, dword_layout.size),
+                    Scalar::from_int(this.machine.page_size, dword_layout.size),
                     &page_size.into(),
                 )?;
                 // Set number of processors.
@@ -298,7 +299,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 #[allow(non_snake_case)]
                 let [hModule, lpProcName] =
                     this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?;
-                this.read_scalar(hModule)?.to_machine_isize(this)?;
+                this.read_machine_isize(hModule)?;
                 let name = this.read_c_str(this.read_pointer(lpProcName)?)?;
                 if let Some(dlsym) = Dlsym::from_str(name, &this.tcx.sess.target.os)? {
                     let ptr = this.create_fn_alloc_ptr(FnVal::Other(dlsym));
@@ -356,7 +357,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 // `term` needs this, so we fake it.
                 let [console, buffer_info] =
                     this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?;
-                this.read_scalar(console)?.to_machine_isize(this)?;
+                this.read_machine_isize(console)?;
                 this.deref_operand(buffer_info)?;
                 // Indicate an error.
                 // FIXME: we should set last_error, but to what?
@@ -432,7 +433,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
             "GetConsoleMode" if this.frame_in_std() => {
                 let [console, mode] =
                     this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?;
-                this.read_scalar(console)?.to_machine_isize(this)?;
+                this.read_machine_isize(console)?;
                 this.deref_operand(mode)?;
                 // Indicate an error.
                 this.write_null(dest)?;
diff --git a/src/tools/miri/src/shims/windows/sync.rs b/src/tools/miri/src/shims/windows/sync.rs
index 6b043c6d2c9..9177f1632f7 100644
--- a/src/tools/miri/src/shims/windows/sync.rs
+++ b/src/tools/miri/src/shims/windows/sync.rs
@@ -170,7 +170,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         match this.init_once_status(id) {
             InitOnceStatus::Uninitialized => {
                 this.init_once_begin(id);
-                this.write_scalar(this.eval_windows("c", "TRUE")?, &pending_place)?;
+                this.write_scalar(this.eval_windows("c", "TRUE"), &pending_place)?;
             }
             InitOnceStatus::Begun => {
                 // Someone else is already on it.
@@ -195,8 +195,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                                 unreachable!(
                                     "status should have either been set to begun or complete"
                                 ),
-                            InitOnceStatus::Begun => this.eval_windows("c", "TRUE")?,
-                            InitOnceStatus::Complete => this.eval_windows("c", "FALSE")?,
+                            InitOnceStatus::Begun => this.eval_windows("c", "TRUE"),
+                            InitOnceStatus::Complete => this.eval_windows("c", "FALSE"),
                         };
 
                         this.write_scalar(pending, &self.pending_place)?;
@@ -213,12 +213,12 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
             }
             InitOnceStatus::Complete => {
                 this.init_once_observe_completed(id);
-                this.write_scalar(this.eval_windows("c", "FALSE")?, &pending_place)?;
+                this.write_scalar(this.eval_windows("c", "FALSE"), &pending_place)?;
             }
         }
 
         // This always succeeds (even if the thread is blocked, we will succeed if we ever unblock).
-        this.eval_windows("c", "TRUE")
+        Ok(this.eval_windows("c", "TRUE"))
     }
 
     fn InitOnceComplete(
@@ -235,7 +235,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
 
         let success = if flags == 0 {
             true
-        } else if flags == this.eval_windows("c", "INIT_ONCE_INIT_FAILED")?.to_u32()? {
+        } else if flags == this.eval_windows_u32("c", "INIT_ONCE_INIT_FAILED") {
             false
         } else {
             throw_unsup_format!("unsupported `dwFlags` {flags} in `InitOnceBeginInitialize`");
@@ -258,7 +258,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
             this.init_once_fail(id)?;
         }
 
-        this.eval_windows("c", "TRUE")
+        Ok(this.eval_windows("c", "TRUE"))
     }
 
     fn WaitOnAddress(
@@ -273,21 +273,21 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
 
         let ptr = this.read_pointer(ptr_op)?;
         let compare = this.read_pointer(compare_op)?;
-        let size = this.read_scalar(size_op)?.to_machine_usize(this)?;
+        let size = this.read_machine_usize(size_op)?;
         let timeout_ms = this.read_scalar(timeout_op)?.to_u32()?;
 
         let thread = this.get_active_thread();
         let addr = ptr.addr().bytes();
 
         if size > 8 || !size.is_power_of_two() {
-            let invalid_param = this.eval_windows("c", "ERROR_INVALID_PARAMETER")?;
+            let invalid_param = this.eval_windows("c", "ERROR_INVALID_PARAMETER");
             this.set_last_error(invalid_param)?;
             this.write_scalar(Scalar::from_i32(0), dest)?;
             return Ok(());
         };
         let size = Size::from_bytes(size);
 
-        let timeout_time = if timeout_ms == this.eval_windows("c", "INFINITE")?.to_u32()? {
+        let timeout_time = if timeout_ms == this.eval_windows_u32("c", "INFINITE") {
             None
         } else {
             let duration = Duration::from_millis(timeout_ms.into());
@@ -325,7 +325,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                     fn call(&self, this: &mut MiriInterpCx<'mir, 'tcx>) -> InterpResult<'tcx> {
                         this.unblock_thread(self.thread);
                         this.futex_remove_waiter(self.addr, self.thread);
-                        let error_timeout = this.eval_windows("c", "ERROR_TIMEOUT")?;
+                        let error_timeout = this.eval_windows("c", "ERROR_TIMEOUT");
                         this.set_last_error(error_timeout)?;
                         this.write_scalar(Scalar::from_i32(0), &self.dest)?;
 
@@ -377,7 +377,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         let timeout_ms = this.read_scalar(timeout_op)?.to_u32()?;
         let flags = this.read_scalar(flags_op)?.to_u32()?;
 
-        let timeout_time = if timeout_ms == this.eval_windows("c", "INFINITE")?.to_u32()? {
+        let timeout_time = if timeout_ms == this.eval_windows_u32("c", "INFINITE") {
             None
         } else {
             let duration = Duration::from_millis(timeout_ms.into());
@@ -431,9 +431,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
 
                     this.condvar_remove_waiter(self.condvar_id, self.thread);
 
-                    let error_timeout = this.eval_windows("c", "ERROR_TIMEOUT")?;
+                    let error_timeout = this.eval_windows("c", "ERROR_TIMEOUT");
                     this.set_last_error(error_timeout)?;
-                    this.write_scalar(this.eval_windows("c", "FALSE")?, &self.dest)?;
+                    this.write_scalar(this.eval_windows("c", "FALSE"), &self.dest)?;
                     Ok(())
                 }
             }
@@ -451,7 +451,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
             );
         }
 
-        this.eval_windows("c", "TRUE")
+        Ok(this.eval_windows("c", "TRUE"))
     }
 
     fn WakeConditionVariable(&mut self, condvar_op: &OpTy<'tcx, Provenance>) -> InterpResult<'tcx> {
diff --git a/src/tools/miri/src/shims/windows/thread.rs b/src/tools/miri/src/shims/windows/thread.rs
index 25a5194caa0..f5bf362ea1c 100644
--- a/src/tools/miri/src/shims/windows/thread.rs
+++ b/src/tools/miri/src/shims/windows/thread.rs
@@ -21,7 +21,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
 
         let security = this.read_pointer(security_op)?;
         // stacksize is ignored, but still needs to be a valid usize
-        this.read_scalar(stacksize_op)?.to_machine_usize(this)?;
+        this.read_machine_usize(stacksize_op)?;
         let start_routine = this.read_pointer(start_op)?;
         let func_arg = this.read_immediate(arg_op)?;
         let flags = this.read_scalar(flags_op)?.to_u32()?;
@@ -34,7 +34,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         };
 
         let stack_size_param_is_a_reservation =
-            this.eval_windows("c", "STACK_SIZE_PARAM_IS_A_RESERVATION")?.to_u32()?;
+            this.eval_windows_u32("c", "STACK_SIZE_PARAM_IS_A_RESERVATION");
 
         // We ignore the stack size, so we also ignore the
         // `STACK_SIZE_PARAM_IS_A_RESERVATION` flag.
@@ -73,7 +73,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
             _ => this.invalid_handle("WaitForSingleObject")?,
         };
 
-        if timeout != this.eval_windows("c", "INFINITE")?.to_u32()? {
+        if timeout != this.eval_windows_u32("c", "INFINITE") {
             throw_unsup_format!("`WaitForSingleObject` with non-infinite timeout");
         }
 
diff --git a/src/tools/miri/test-cargo-miri/src/main.rs b/src/tools/miri/test-cargo-miri/src/main.rs
index 41c52b70170..048dbbbaa0f 100644
--- a/src/tools/miri/test-cargo-miri/src/main.rs
+++ b/src/tools/miri/test-cargo-miri/src/main.rs
@@ -2,6 +2,7 @@ use byteorder::{BigEndian, ByteOrder};
 use std::env;
 #[cfg(unix)]
 use std::io::{self, BufRead};
+use std::path::PathBuf;
 
 fn main() {
     // Check env var set by `build.rs`.
@@ -21,12 +22,30 @@ fn main() {
     // If there were no arguments, access stdin and test working dir.
     // (We rely on the test runner to always disable isolation when passing no arguments.)
     if std::env::args().len() <= 1 {
+        fn host_to_target_path(path: String) -> PathBuf {
+            use std::ffi::{CStr, CString};
+
+            let path = CString::new(path).unwrap();
+            let mut out = Vec::with_capacity(1024);
+
+            unsafe {
+                extern "Rust" {
+                    fn miri_host_to_target_path(
+                        path: *const i8,
+                        out: *mut i8,
+                        out_size: usize,
+                    ) -> usize;
+                }
+                let ret = miri_host_to_target_path(path.as_ptr(), out.as_mut_ptr(), out.capacity());
+                assert_eq!(ret, 0);
+                let out = CStr::from_ptr(out.as_ptr()).to_str().unwrap();
+                PathBuf::from(out)
+            }
+        }
+
         // CWD should be crate root.
-        // We have to normalize slashes, as the env var might be set for a different target's conventions.
         let env_dir = env::current_dir().unwrap();
-        let env_dir = env_dir.to_string_lossy().replace("\\", "/");
-        let crate_dir = env::var_os("CARGO_MANIFEST_DIR").unwrap();
-        let crate_dir = crate_dir.to_string_lossy().replace("\\", "/");
+        let crate_dir = host_to_target_path(env::var("CARGO_MANIFEST_DIR").unwrap());
         assert_eq!(env_dir, crate_dir);
 
         #[cfg(unix)]
diff --git a/src/tools/miri/test-cargo-miri/subcrate/main.rs b/src/tools/miri/test-cargo-miri/subcrate/main.rs
index 4ce80b37072..1cb8091f877 100644
--- a/src/tools/miri/test-cargo-miri/subcrate/main.rs
+++ b/src/tools/miri/test-cargo-miri/subcrate/main.rs
@@ -4,13 +4,30 @@ use std::path::PathBuf;
 fn main() {
     println!("subcrate running");
 
+    fn host_to_target_path(path: String) -> PathBuf {
+        use std::ffi::{CStr, CString};
+
+        let path = CString::new(path).unwrap();
+        let mut out = Vec::with_capacity(1024);
+
+        unsafe {
+            extern "Rust" {
+                fn miri_host_to_target_path(
+                    path: *const i8,
+                    out: *mut i8,
+                    out_size: usize,
+                ) -> usize;
+            }
+            let ret = miri_host_to_target_path(path.as_ptr(), out.as_mut_ptr(), out.capacity());
+            assert_eq!(ret, 0);
+            let out = CStr::from_ptr(out.as_ptr()).to_str().unwrap();
+            PathBuf::from(out)
+        }
+    }
+
     // CWD should be workspace root, i.e., one level up from crate root.
-    // We have to normalize slashes, as the env var might be set for a different target's conventions.
     let env_dir = env::current_dir().unwrap();
-    let env_dir = env_dir.to_string_lossy().replace("\\", "/");
-    let crate_dir = env::var_os("CARGO_MANIFEST_DIR").unwrap();
-    let crate_dir = crate_dir.to_string_lossy().replace("\\", "/");
-    let crate_dir = PathBuf::from(crate_dir);
-    let crate_dir = crate_dir.parent().unwrap().to_string_lossy();
+    let crate_dir = host_to_target_path(env::var("CARGO_MANIFEST_DIR").unwrap());
+    let crate_dir = crate_dir.parent().unwrap();
     assert_eq!(env_dir, crate_dir);
 }
diff --git a/src/tools/miri/test-cargo-miri/subcrate/test.rs b/src/tools/miri/test-cargo-miri/subcrate/test.rs
index 77e3c2878ca..619d8c72fd0 100644
--- a/src/tools/miri/test-cargo-miri/subcrate/test.rs
+++ b/src/tools/miri/test-cargo-miri/subcrate/test.rs
@@ -1,16 +1,37 @@
 use std::env;
 
+use std::path::PathBuf;
+
 use byteorder::{ByteOrder, LittleEndian};
 
 fn main() {
     println!("subcrate testing");
 
+    fn host_to_target_path(path: String) -> PathBuf {
+        use std::ffi::{CStr, CString};
+
+        let path = CString::new(path).unwrap();
+        let mut out = Vec::with_capacity(1024);
+
+        unsafe {
+            extern "Rust" {
+                fn miri_host_to_target_path(
+                    path: *const i8,
+                    out: *mut i8,
+                    out_size: usize,
+                ) -> usize;
+            }
+            let ret = miri_host_to_target_path(path.as_ptr(), out.as_mut_ptr(), out.capacity());
+            assert_eq!(ret, 0);
+            let out = CStr::from_ptr(out.as_ptr()).to_str().unwrap();
+            PathBuf::from(out)
+        }
+    }
+
     // CWD should be crate root.
     // We have to normalize slashes, as the env var might be set for a different target's conventions.
     let env_dir = env::current_dir().unwrap();
-    let env_dir = env_dir.to_string_lossy().replace("\\", "/");
-    let crate_dir = env::var_os("CARGO_MANIFEST_DIR").unwrap();
-    let crate_dir = crate_dir.to_string_lossy().replace("\\", "/");
+    let crate_dir = host_to_target_path(env::var("CARGO_MANIFEST_DIR").unwrap());
     assert_eq!(env_dir, crate_dir);
 
     // Make sure we can call dev-dependencies.
diff --git a/src/tools/miri/tests/fail/box-cell-alias.stderr b/src/tools/miri/tests/fail/box-cell-alias.stderr
index f57b52c4bda..fc946d6d39b 100644
--- a/src/tools/miri/tests/fail/box-cell-alias.stderr
+++ b/src/tools/miri/tests/fail/box-cell-alias.stderr
@@ -19,7 +19,7 @@ help: <TAG> was later invalidated at offsets [0x0..0x1] by a Unique retag
    |
 LL |     let res = helper(val, ptr);
    |                      ^^^
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside `helper` at $DIR/box-cell-alias.rs:LL:CC
 note: inside `main`
   --> $DIR/box-cell-alias.rs:LL:CC
diff --git a/src/tools/miri/tests/fail/crates/tokio_mvp.rs b/src/tools/miri/tests/fail/crates/tokio_mvp.rs
deleted file mode 100644
index 7cb42c09a96..00000000000
--- a/src/tools/miri/tests/fail/crates/tokio_mvp.rs
+++ /dev/null
@@ -1,7 +0,0 @@
-//@compile-flags: -Zmiri-disable-isolation
-//@error-pattern: can't call foreign function: epoll_create1
-//@normalize-stderr-test: "   = note: inside .*\n" -> ""
-//@only-target-linux: the errors differ too much between platforms
-
-#[tokio::main]
-async fn main() {}
diff --git a/src/tools/miri/tests/fail/crates/tokio_mvp.stderr b/src/tools/miri/tests/fail/crates/tokio_mvp.stderr
deleted file mode 100644
index 1e7dfaa7499..00000000000
--- a/src/tools/miri/tests/fail/crates/tokio_mvp.stderr
+++ /dev/null
@@ -1,19 +0,0 @@
-error: unsupported operation: can't call foreign function: epoll_create1
-  --> CARGO_REGISTRY/.../epoll.rs:LL:CC
-   |
-LL |         let res = syscall!(epoll_create1(libc::EPOLL_CLOEXEC));
-   |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't call foreign function: epoll_create1
-   |
-   = help: this is likely not a bug in the program; it indicates that the program performed an operation that the interpreter does not support
-   = note: BACKTRACE:
-note: inside `main`
-  --> $DIR/tokio_mvp.rs:LL:CC
-   |
-LL | #[tokio::main]
-   | ^^^^^^^^^^^^^^
-   = note: this error originates in the macro `syscall` which comes from the expansion of the attribute macro `tokio::main` (in Nightly builds, run with -Z macro-backtrace for more info)
-
-note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
-
-error: aborting due to previous error
-
diff --git a/src/tools/miri/tests/fail/data_race/alloc_read_race.rs b/src/tools/miri/tests/fail/data_race/alloc_read_race.rs
index 6040452a166..2698c63a445 100644
--- a/src/tools/miri/tests/fail/data_race/alloc_read_race.rs
+++ b/src/tools/miri/tests/fail/data_race/alloc_read_race.rs
@@ -37,7 +37,7 @@ pub fn main() {
             let pointer = &*ptr.0;
 
             // Note: could also error due to reading uninitialized memory, but the data-race detector triggers first.
-            *pointer.load(Ordering::Relaxed) //~ ERROR: Data race detected between Read on thread `<unnamed>` and Allocate on thread `<unnamed>`
+            *pointer.load(Ordering::Relaxed) //~ ERROR: Data race detected between (1) Allocate on thread `<unnamed>` and (2) Read on thread `<unnamed>`
         });
 
         j1.join().unwrap();
diff --git a/src/tools/miri/tests/fail/data_race/alloc_read_race.stderr b/src/tools/miri/tests/fail/data_race/alloc_read_race.stderr
index c6bfd12b241..5b809722c70 100644
--- a/src/tools/miri/tests/fail/data_race/alloc_read_race.stderr
+++ b/src/tools/miri/tests/fail/data_race/alloc_read_race.stderr
@@ -1,12 +1,17 @@
-error: Undefined Behavior: Data race detected between Read on thread `<unnamed>` and Allocate on thread `<unnamed>` at ALLOC
+error: Undefined Behavior: Data race detected between (1) Allocate on thread `<unnamed>` and (2) Read on thread `<unnamed>` at ALLOC. (2) just happened here
   --> $DIR/alloc_read_race.rs:LL:CC
    |
 LL |             *pointer.load(Ordering::Relaxed)
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Data race detected between Read on thread `<unnamed>` and Allocate on thread `<unnamed>` at ALLOC
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Data race detected between (1) Allocate on thread `<unnamed>` and (2) Read on thread `<unnamed>` at ALLOC. (2) just happened here
    |
+help: and (1) occurred earlier here
+  --> $DIR/alloc_read_race.rs:LL:CC
+   |
+LL |             pointer.store(Box::into_raw(Box::new_uninit()), Ordering::Relaxed);
+   |                                         ^^^^^^^^^^^^^^^^^
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside closure at $DIR/alloc_read_race.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/data_race/alloc_write_race.rs b/src/tools/miri/tests/fail/data_race/alloc_write_race.rs
index 51d431b36f3..b78d5ef27d3 100644
--- a/src/tools/miri/tests/fail/data_race/alloc_write_race.rs
+++ b/src/tools/miri/tests/fail/data_race/alloc_write_race.rs
@@ -35,7 +35,7 @@ pub fn main() {
 
         let j2 = spawn(move || {
             let pointer = &*ptr.0;
-            *pointer.load(Ordering::Relaxed) = 2; //~ ERROR: Data race detected between Write on thread `<unnamed>` and Allocate on thread `<unnamed>`
+            *pointer.load(Ordering::Relaxed) = 2; //~ ERROR: Data race detected between (1) Allocate on thread `<unnamed>` and (2) Write on thread `<unnamed>`
         });
 
         j1.join().unwrap();
diff --git a/src/tools/miri/tests/fail/data_race/alloc_write_race.stderr b/src/tools/miri/tests/fail/data_race/alloc_write_race.stderr
index c4efc175c20..8520bcf4e4e 100644
--- a/src/tools/miri/tests/fail/data_race/alloc_write_race.stderr
+++ b/src/tools/miri/tests/fail/data_race/alloc_write_race.stderr
@@ -1,12 +1,17 @@
-error: Undefined Behavior: Data race detected between Write on thread `<unnamed>` and Allocate on thread `<unnamed>` at ALLOC
+error: Undefined Behavior: Data race detected between (1) Allocate on thread `<unnamed>` and (2) Write on thread `<unnamed>` at ALLOC. (2) just happened here
   --> $DIR/alloc_write_race.rs:LL:CC
    |
 LL |             *pointer.load(Ordering::Relaxed) = 2;
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Data race detected between Write on thread `<unnamed>` and Allocate on thread `<unnamed>` at ALLOC
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Data race detected between (1) Allocate on thread `<unnamed>` and (2) Write on thread `<unnamed>` at ALLOC. (2) just happened here
    |
+help: and (1) occurred earlier here
+  --> $DIR/alloc_write_race.rs:LL:CC
+   |
+LL |                 .store(Box::into_raw(Box::<usize>::new_uninit()) as *mut usize, Ordering::Relaxed);
+   |                                      ^^^^^^^^^^^^^^^^^^^^^^^^^^
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside closure at $DIR/alloc_write_race.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/data_race/atomic_read_na_write_race1.rs b/src/tools/miri/tests/fail/data_race/atomic_read_na_write_race1.rs
index 79c6760b7c4..3f811d0f64d 100644
--- a/src/tools/miri/tests/fail/data_race/atomic_read_na_write_race1.rs
+++ b/src/tools/miri/tests/fail/data_race/atomic_read_na_write_race1.rs
@@ -20,7 +20,7 @@ pub fn main() {
         });
 
         let j2 = spawn(move || {
-            (&*c.0).load(Ordering::SeqCst) //~ ERROR: Data race detected between Atomic Load on thread `<unnamed>` and Write on thread `<unnamed>`
+            (&*c.0).load(Ordering::SeqCst) //~ ERROR: Data race detected between (1) Write on thread `<unnamed>` and (2) Atomic Load on thread `<unnamed>`
         });
 
         j1.join().unwrap();
diff --git a/src/tools/miri/tests/fail/data_race/atomic_read_na_write_race1.stderr b/src/tools/miri/tests/fail/data_race/atomic_read_na_write_race1.stderr
index 04adf0a98b6..e25629e14ea 100644
--- a/src/tools/miri/tests/fail/data_race/atomic_read_na_write_race1.stderr
+++ b/src/tools/miri/tests/fail/data_race/atomic_read_na_write_race1.stderr
@@ -1,12 +1,17 @@
-error: Undefined Behavior: Data race detected between Atomic Load on thread `<unnamed>` and Write on thread `<unnamed>` at ALLOC
+error: Undefined Behavior: Data race detected between (1) Write on thread `<unnamed>` and (2) Atomic Load on thread `<unnamed>` at ALLOC. (2) just happened here
   --> $DIR/atomic_read_na_write_race1.rs:LL:CC
    |
 LL |             (&*c.0).load(Ordering::SeqCst)
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Data race detected between Atomic Load on thread `<unnamed>` and Write on thread `<unnamed>` at ALLOC
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Data race detected between (1) Write on thread `<unnamed>` and (2) Atomic Load on thread `<unnamed>` at ALLOC. (2) just happened here
    |
+help: and (1) occurred earlier here
+  --> $DIR/atomic_read_na_write_race1.rs:LL:CC
+   |
+LL |             *(c.0 as *mut usize) = 32;
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside closure at $DIR/atomic_read_na_write_race1.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/data_race/atomic_read_na_write_race2.rs b/src/tools/miri/tests/fail/data_race/atomic_read_na_write_race2.rs
index e069ac4ad6a..34fb3ac066f 100644
--- a/src/tools/miri/tests/fail/data_race/atomic_read_na_write_race2.rs
+++ b/src/tools/miri/tests/fail/data_race/atomic_read_na_write_race2.rs
@@ -23,7 +23,7 @@ pub fn main() {
 
         let j2 = spawn(move || {
             let atomic_ref = &mut *c.0;
-            *atomic_ref.get_mut() = 32; //~ ERROR: Data race detected between Write on thread `<unnamed>` and Atomic Load on thread `<unnamed>`
+            *atomic_ref.get_mut() = 32; //~ ERROR: Data race detected between (1) Atomic Load on thread `<unnamed>` and (2) Write on thread `<unnamed>`
         });
 
         j1.join().unwrap();
diff --git a/src/tools/miri/tests/fail/data_race/atomic_read_na_write_race2.stderr b/src/tools/miri/tests/fail/data_race/atomic_read_na_write_race2.stderr
index b48f927b8fc..6953b1403b4 100644
--- a/src/tools/miri/tests/fail/data_race/atomic_read_na_write_race2.stderr
+++ b/src/tools/miri/tests/fail/data_race/atomic_read_na_write_race2.stderr
@@ -1,12 +1,17 @@
-error: Undefined Behavior: Data race detected between Write on thread `<unnamed>` and Atomic Load on thread `<unnamed>` at ALLOC
+error: Undefined Behavior: Data race detected between (1) Atomic Load on thread `<unnamed>` and (2) Write on thread `<unnamed>` at ALLOC. (2) just happened here
   --> $DIR/atomic_read_na_write_race2.rs:LL:CC
    |
 LL |             *atomic_ref.get_mut() = 32;
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^ Data race detected between Write on thread `<unnamed>` and Atomic Load on thread `<unnamed>` at ALLOC
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^ Data race detected between (1) Atomic Load on thread `<unnamed>` and (2) Write on thread `<unnamed>` at ALLOC. (2) just happened here
    |
+help: and (1) occurred earlier here
+  --> $DIR/atomic_read_na_write_race2.rs:LL:CC
+   |
+LL |             atomic_ref.load(Ordering::SeqCst)
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside closure at $DIR/atomic_read_na_write_race2.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/data_race/atomic_write_na_read_race1.rs b/src/tools/miri/tests/fail/data_race/atomic_write_na_read_race1.rs
index 9c025a0153d..63b0806f3bb 100644
--- a/src/tools/miri/tests/fail/data_race/atomic_write_na_read_race1.rs
+++ b/src/tools/miri/tests/fail/data_race/atomic_write_na_read_race1.rs
@@ -23,7 +23,7 @@ pub fn main() {
 
         let j2 = spawn(move || {
             let atomic_ref = &mut *c.0;
-            *atomic_ref.get_mut() //~ ERROR: Data race detected between Read on thread `<unnamed>` and Atomic Store on thread `<unnamed>`
+            *atomic_ref.get_mut() //~ ERROR: Data race detected between (1) Atomic Store on thread `<unnamed>` and (2) Read on thread `<unnamed>`
         });
 
         j1.join().unwrap();
diff --git a/src/tools/miri/tests/fail/data_race/atomic_write_na_read_race1.stderr b/src/tools/miri/tests/fail/data_race/atomic_write_na_read_race1.stderr
index fdb9b353a67..e52b8895a6a 100644
--- a/src/tools/miri/tests/fail/data_race/atomic_write_na_read_race1.stderr
+++ b/src/tools/miri/tests/fail/data_race/atomic_write_na_read_race1.stderr
@@ -1,12 +1,17 @@
-error: Undefined Behavior: Data race detected between Read on thread `<unnamed>` and Atomic Store on thread `<unnamed>` at ALLOC
+error: Undefined Behavior: Data race detected between (1) Atomic Store on thread `<unnamed>` and (2) Read on thread `<unnamed>` at ALLOC. (2) just happened here
   --> $DIR/atomic_write_na_read_race1.rs:LL:CC
    |
 LL |             *atomic_ref.get_mut()
-   |             ^^^^^^^^^^^^^^^^^^^^^ Data race detected between Read on thread `<unnamed>` and Atomic Store on thread `<unnamed>` at ALLOC
+   |             ^^^^^^^^^^^^^^^^^^^^^ Data race detected between (1) Atomic Store on thread `<unnamed>` and (2) Read on thread `<unnamed>` at ALLOC. (2) just happened here
    |
+help: and (1) occurred earlier here
+  --> $DIR/atomic_write_na_read_race1.rs:LL:CC
+   |
+LL |             atomic_ref.store(32, Ordering::SeqCst)
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside closure at $DIR/atomic_write_na_read_race1.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/data_race/atomic_write_na_read_race2.rs b/src/tools/miri/tests/fail/data_race/atomic_write_na_read_race2.rs
index 30b3c486374..9092254be21 100644
--- a/src/tools/miri/tests/fail/data_race/atomic_write_na_read_race2.rs
+++ b/src/tools/miri/tests/fail/data_race/atomic_write_na_read_race2.rs
@@ -20,7 +20,7 @@ pub fn main() {
         });
 
         let j2 = spawn(move || {
-            (&*c.0).store(32, Ordering::SeqCst); //~ ERROR: Data race detected between Atomic Store on thread `<unnamed>` and Read on thread `<unnamed>`
+            (&*c.0).store(32, Ordering::SeqCst); //~ ERROR: Data race detected between (1) Read on thread `<unnamed>` and (2) Atomic Store on thread `<unnamed>`
         });
 
         j1.join().unwrap();
diff --git a/src/tools/miri/tests/fail/data_race/atomic_write_na_read_race2.stderr b/src/tools/miri/tests/fail/data_race/atomic_write_na_read_race2.stderr
index ec581e322b7..513d13b0349 100644
--- a/src/tools/miri/tests/fail/data_race/atomic_write_na_read_race2.stderr
+++ b/src/tools/miri/tests/fail/data_race/atomic_write_na_read_race2.stderr
@@ -1,12 +1,17 @@
-error: Undefined Behavior: Data race detected between Atomic Store on thread `<unnamed>` and Read on thread `<unnamed>` at ALLOC
+error: Undefined Behavior: Data race detected between (1) Read on thread `<unnamed>` and (2) Atomic Store on thread `<unnamed>` at ALLOC. (2) just happened here
   --> $DIR/atomic_write_na_read_race2.rs:LL:CC
    |
 LL |             (&*c.0).store(32, Ordering::SeqCst);
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Data race detected between Atomic Store on thread `<unnamed>` and Read on thread `<unnamed>` at ALLOC
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Data race detected between (1) Read on thread `<unnamed>` and (2) Atomic Store on thread `<unnamed>` at ALLOC. (2) just happened here
    |
+help: and (1) occurred earlier here
+  --> $DIR/atomic_write_na_read_race2.rs:LL:CC
+   |
+LL |             let _val = *(c.0 as *mut usize);
+   |                        ^^^^^^^^^^^^^^^^^^^^
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside closure at $DIR/atomic_write_na_read_race2.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/data_race/atomic_write_na_write_race1.rs b/src/tools/miri/tests/fail/data_race/atomic_write_na_write_race1.rs
index 02b17cc57b6..5a713905f4e 100644
--- a/src/tools/miri/tests/fail/data_race/atomic_write_na_write_race1.rs
+++ b/src/tools/miri/tests/fail/data_race/atomic_write_na_write_race1.rs
@@ -20,7 +20,7 @@ pub fn main() {
         });
 
         let j2 = spawn(move || {
-            (&*c.0).store(64, Ordering::SeqCst); //~ ERROR: Data race detected between Atomic Store on thread `<unnamed>` and Write on thread `<unnamed>`
+            (&*c.0).store(64, Ordering::SeqCst); //~ ERROR: Data race detected between (1) Write on thread `<unnamed>` and (2) Atomic Store on thread `<unnamed>`
         });
 
         j1.join().unwrap();
diff --git a/src/tools/miri/tests/fail/data_race/atomic_write_na_write_race1.stderr b/src/tools/miri/tests/fail/data_race/atomic_write_na_write_race1.stderr
index 4c75f94d71c..2ff70ef1f6d 100644
--- a/src/tools/miri/tests/fail/data_race/atomic_write_na_write_race1.stderr
+++ b/src/tools/miri/tests/fail/data_race/atomic_write_na_write_race1.stderr
@@ -1,12 +1,17 @@
-error: Undefined Behavior: Data race detected between Atomic Store on thread `<unnamed>` and Write on thread `<unnamed>` at ALLOC
+error: Undefined Behavior: Data race detected between (1) Write on thread `<unnamed>` and (2) Atomic Store on thread `<unnamed>` at ALLOC. (2) just happened here
   --> $DIR/atomic_write_na_write_race1.rs:LL:CC
    |
 LL |             (&*c.0).store(64, Ordering::SeqCst);
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Data race detected between Atomic Store on thread `<unnamed>` and Write on thread `<unnamed>` at ALLOC
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Data race detected between (1) Write on thread `<unnamed>` and (2) Atomic Store on thread `<unnamed>` at ALLOC. (2) just happened here
    |
+help: and (1) occurred earlier here
+  --> $DIR/atomic_write_na_write_race1.rs:LL:CC
+   |
+LL |             *(c.0 as *mut usize) = 32;
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside closure at $DIR/atomic_write_na_write_race1.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/data_race/atomic_write_na_write_race2.rs b/src/tools/miri/tests/fail/data_race/atomic_write_na_write_race2.rs
index b5f4966d884..5848aa262b3 100644
--- a/src/tools/miri/tests/fail/data_race/atomic_write_na_write_race2.rs
+++ b/src/tools/miri/tests/fail/data_race/atomic_write_na_write_race2.rs
@@ -23,7 +23,7 @@ pub fn main() {
 
         let j2 = spawn(move || {
             let atomic_ref = &mut *c.0;
-            *atomic_ref.get_mut() = 32; //~ ERROR: Data race detected between Write on thread `<unnamed>` and Atomic Store on thread `<unnamed>`
+            *atomic_ref.get_mut() = 32; //~ ERROR: Data race detected between (1) Atomic Store on thread `<unnamed>` and (2) Write on thread `<unnamed>`
         });
 
         j1.join().unwrap();
diff --git a/src/tools/miri/tests/fail/data_race/atomic_write_na_write_race2.stderr b/src/tools/miri/tests/fail/data_race/atomic_write_na_write_race2.stderr
index 8c7f14081c8..166b4d2269a 100644
--- a/src/tools/miri/tests/fail/data_race/atomic_write_na_write_race2.stderr
+++ b/src/tools/miri/tests/fail/data_race/atomic_write_na_write_race2.stderr
@@ -1,12 +1,17 @@
-error: Undefined Behavior: Data race detected between Write on thread `<unnamed>` and Atomic Store on thread `<unnamed>` at ALLOC
+error: Undefined Behavior: Data race detected between (1) Atomic Store on thread `<unnamed>` and (2) Write on thread `<unnamed>` at ALLOC. (2) just happened here
   --> $DIR/atomic_write_na_write_race2.rs:LL:CC
    |
 LL |             *atomic_ref.get_mut() = 32;
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^ Data race detected between Write on thread `<unnamed>` and Atomic Store on thread `<unnamed>` at ALLOC
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^ Data race detected between (1) Atomic Store on thread `<unnamed>` and (2) Write on thread `<unnamed>` at ALLOC. (2) just happened here
    |
+help: and (1) occurred earlier here
+  --> $DIR/atomic_write_na_write_race2.rs:LL:CC
+   |
+LL |             atomic_ref.store(64, Ordering::SeqCst);
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside closure at $DIR/atomic_write_na_write_race2.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/data_race/dangling_thread_async_race.rs b/src/tools/miri/tests/fail/data_race/dangling_thread_async_race.rs
index 9922468e5f8..eecb980e905 100644
--- a/src/tools/miri/tests/fail/data_race/dangling_thread_async_race.rs
+++ b/src/tools/miri/tests/fail/data_race/dangling_thread_async_race.rs
@@ -34,7 +34,7 @@ fn main() {
 
     let join2 = unsafe {
         spawn(move || {
-            *c.0 = 64; //~ ERROR: Data race detected between Write on thread `<unnamed>` and Write on thread `<unnamed>`
+            *c.0 = 64; //~ ERROR: Data race detected between (1) Write on thread `<unnamed>` and (2) Write on thread `<unnamed>`
         })
     };
 
diff --git a/src/tools/miri/tests/fail/data_race/dangling_thread_async_race.stderr b/src/tools/miri/tests/fail/data_race/dangling_thread_async_race.stderr
index 663bb8d4af5..a08b21ab0e4 100644
--- a/src/tools/miri/tests/fail/data_race/dangling_thread_async_race.stderr
+++ b/src/tools/miri/tests/fail/data_race/dangling_thread_async_race.stderr
@@ -1,12 +1,17 @@
-error: Undefined Behavior: Data race detected between Write on thread `<unnamed>` and Write on thread `<unnamed>` at ALLOC
+error: Undefined Behavior: Data race detected between (1) Write on thread `<unnamed>` and (2) Write on thread `<unnamed>` at ALLOC. (2) just happened here
   --> $DIR/dangling_thread_async_race.rs:LL:CC
    |
 LL |             *c.0 = 64;
-   |             ^^^^^^^^^ Data race detected between Write on thread `<unnamed>` and Write on thread `<unnamed>` at ALLOC
+   |             ^^^^^^^^^ Data race detected between (1) Write on thread `<unnamed>` and (2) Write on thread `<unnamed>` at ALLOC. (2) just happened here
    |
+help: and (1) occurred earlier here
+  --> $DIR/dangling_thread_async_race.rs:LL:CC
+   |
+LL |             *c.0 = 32;
+   |             ^^^^^^^^^
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside closure at $DIR/dangling_thread_async_race.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/data_race/dangling_thread_race.rs b/src/tools/miri/tests/fail/data_race/dangling_thread_race.rs
index 8c8a6ac87f3..4c7fbdd7fe6 100644
--- a/src/tools/miri/tests/fail/data_race/dangling_thread_race.rs
+++ b/src/tools/miri/tests/fail/data_race/dangling_thread_race.rs
@@ -33,6 +33,6 @@ fn main() {
     spawn(|| ()).join().unwrap();
 
     unsafe {
-        *c.0 = 64; //~ ERROR: Data race detected between Write on thread `main` and Write on thread `<unnamed>`
+        *c.0 = 64; //~ ERROR: Data race detected between (1) Write on thread `<unnamed>` and (2) Write on thread `main`
     }
 }
diff --git a/src/tools/miri/tests/fail/data_race/dangling_thread_race.stderr b/src/tools/miri/tests/fail/data_race/dangling_thread_race.stderr
index ad3e1735378..aa2e6a6f712 100644
--- a/src/tools/miri/tests/fail/data_race/dangling_thread_race.stderr
+++ b/src/tools/miri/tests/fail/data_race/dangling_thread_race.stderr
@@ -1,12 +1,17 @@
-error: Undefined Behavior: Data race detected between Write on thread `main` and Write on thread `<unnamed>` at ALLOC
+error: Undefined Behavior: Data race detected between (1) Write on thread `<unnamed>` and (2) Write on thread `main` at ALLOC. (2) just happened here
   --> $DIR/dangling_thread_race.rs:LL:CC
    |
 LL |         *c.0 = 64;
-   |         ^^^^^^^^^ Data race detected between Write on thread `main` and Write on thread `<unnamed>` at ALLOC
+   |         ^^^^^^^^^ Data race detected between (1) Write on thread `<unnamed>` and (2) Write on thread `main` at ALLOC. (2) just happened here
    |
+help: and (1) occurred earlier here
+  --> $DIR/dangling_thread_race.rs:LL:CC
+   |
+LL |             *c.0 = 32;
+   |             ^^^^^^^^^
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside `main` at $DIR/dangling_thread_race.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/data_race/dealloc_read_race1.rs b/src/tools/miri/tests/fail/data_race/dealloc_read_race1.rs
index 8e1216f5bf0..18593cf56ae 100644
--- a/src/tools/miri/tests/fail/data_race/dealloc_read_race1.rs
+++ b/src/tools/miri/tests/fail/data_race/dealloc_read_race1.rs
@@ -25,7 +25,7 @@ pub fn main() {
 
         let j2 = spawn(move || {
             __rust_dealloc(
-                //~^ ERROR: Data race detected between Deallocate on thread `<unnamed>` and Read on thread `<unnamed>`
+                //~^ ERROR: Data race detected between (1) Read on thread `<unnamed>` and (2) Deallocate on thread `<unnamed>`
                 ptr.0 as *mut _,
                 std::mem::size_of::<usize>(),
                 std::mem::align_of::<usize>(),
diff --git a/src/tools/miri/tests/fail/data_race/dealloc_read_race1.stderr b/src/tools/miri/tests/fail/data_race/dealloc_read_race1.stderr
index 194c2260baa..5e546646479 100644
--- a/src/tools/miri/tests/fail/data_race/dealloc_read_race1.stderr
+++ b/src/tools/miri/tests/fail/data_race/dealloc_read_race1.stderr
@@ -1,4 +1,4 @@
-error: Undefined Behavior: Data race detected between Deallocate on thread `<unnamed>` and Read on thread `<unnamed>` at ALLOC
+error: Undefined Behavior: Data race detected between (1) Read on thread `<unnamed>` and (2) Deallocate on thread `<unnamed>` at ALLOC. (2) just happened here
   --> $DIR/dealloc_read_race1.rs:LL:CC
    |
 LL | /             __rust_dealloc(
@@ -7,11 +7,16 @@ LL | |                 ptr.0 as *mut _,
 LL | |                 std::mem::size_of::<usize>(),
 LL | |                 std::mem::align_of::<usize>(),
 LL | |             );
-   | |_____________^ Data race detected between Deallocate on thread `<unnamed>` and Read on thread `<unnamed>` at ALLOC
+   | |_____________^ Data race detected between (1) Read on thread `<unnamed>` and (2) Deallocate on thread `<unnamed>` at ALLOC. (2) just happened here
    |
+help: and (1) occurred earlier here
+  --> $DIR/dealloc_read_race1.rs:LL:CC
+   |
+LL |             let _val = *ptr.0;
+   |                        ^^^^^^
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside closure at $DIR/dealloc_read_race1.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/data_race/dealloc_read_race2.rs b/src/tools/miri/tests/fail/data_race/dealloc_read_race2.rs
index 38f76af9de1..a6f83d489e5 100644
--- a/src/tools/miri/tests/fail/data_race/dealloc_read_race2.rs
+++ b/src/tools/miri/tests/fail/data_race/dealloc_read_race2.rs
@@ -28,7 +28,7 @@ pub fn main() {
         });
 
         let j2 = spawn(move || {
-            // Also an error of the form: Data race detected between Read on thread `<unnamed>` and Deallocate on thread `<unnamed>`
+            // Also an error of the form: Data race detected between (1) Deallocate on thread `<unnamed>` and (2) Read on thread `<unnamed>`
             // but the invalid allocation is detected first.
             *ptr.0 //~ ERROR: dereferenced after this allocation got freed
         });
diff --git a/src/tools/miri/tests/fail/data_race/dealloc_read_race_stack.rs b/src/tools/miri/tests/fail/data_race/dealloc_read_race_stack.rs
index 665e5ce4a17..c82bfed09ee 100644
--- a/src/tools/miri/tests/fail/data_race/dealloc_read_race_stack.rs
+++ b/src/tools/miri/tests/fail/data_race/dealloc_read_race_stack.rs
@@ -35,7 +35,7 @@ pub fn main() {
                 sleep(Duration::from_millis(200));
 
                 // Now `stack_var` gets deallocated.
-            } //~ ERROR: Data race detected between Deallocate on thread `<unnamed>` and Read on thread `<unnamed>`
+            } //~ ERROR: Data race detected between (1) Read on thread `<unnamed>` and (2) Deallocate on thread `<unnamed>`
         });
 
         let j2 = spawn(move || {
diff --git a/src/tools/miri/tests/fail/data_race/dealloc_read_race_stack.stderr b/src/tools/miri/tests/fail/data_race/dealloc_read_race_stack.stderr
index c986e912f03..beb70c5a7fa 100644
--- a/src/tools/miri/tests/fail/data_race/dealloc_read_race_stack.stderr
+++ b/src/tools/miri/tests/fail/data_race/dealloc_read_race_stack.stderr
@@ -1,12 +1,17 @@
-error: Undefined Behavior: Data race detected between Deallocate on thread `<unnamed>` and Read on thread `<unnamed>` at ALLOC
+error: Undefined Behavior: Data race detected between (1) Read on thread `<unnamed>` and (2) Deallocate on thread `<unnamed>` at ALLOC. (2) just happened here
   --> $DIR/dealloc_read_race_stack.rs:LL:CC
    |
 LL |             }
-   |             ^ Data race detected between Deallocate on thread `<unnamed>` and Read on thread `<unnamed>` at ALLOC
+   |             ^ Data race detected between (1) Read on thread `<unnamed>` and (2) Deallocate on thread `<unnamed>` at ALLOC. (2) just happened here
    |
+help: and (1) occurred earlier here
+  --> $DIR/dealloc_read_race_stack.rs:LL:CC
+   |
+LL |             *pointer.load(Ordering::Acquire)
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside closure at $DIR/dealloc_read_race_stack.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/data_race/dealloc_write_race1.rs b/src/tools/miri/tests/fail/data_race/dealloc_write_race1.rs
index b36c6b5ac0e..1e93a6cb094 100644
--- a/src/tools/miri/tests/fail/data_race/dealloc_write_race1.rs
+++ b/src/tools/miri/tests/fail/data_race/dealloc_write_race1.rs
@@ -24,7 +24,7 @@ pub fn main() {
 
         let j2 = spawn(move || {
             __rust_dealloc(
-                //~^ ERROR: Data race detected between Deallocate on thread `<unnamed>` and Write on thread `<unnamed>`
+                //~^ ERROR: Data race detected between (1) Write on thread `<unnamed>` and (2) Deallocate on thread `<unnamed>`
                 ptr.0 as *mut _,
                 std::mem::size_of::<usize>(),
                 std::mem::align_of::<usize>(),
diff --git a/src/tools/miri/tests/fail/data_race/dealloc_write_race1.stderr b/src/tools/miri/tests/fail/data_race/dealloc_write_race1.stderr
index 56eb0b519c4..cc4c4524ba2 100644
--- a/src/tools/miri/tests/fail/data_race/dealloc_write_race1.stderr
+++ b/src/tools/miri/tests/fail/data_race/dealloc_write_race1.stderr
@@ -1,4 +1,4 @@
-error: Undefined Behavior: Data race detected between Deallocate on thread `<unnamed>` and Write on thread `<unnamed>` at ALLOC
+error: Undefined Behavior: Data race detected between (1) Write on thread `<unnamed>` and (2) Deallocate on thread `<unnamed>` at ALLOC. (2) just happened here
   --> $DIR/dealloc_write_race1.rs:LL:CC
    |
 LL | /             __rust_dealloc(
@@ -7,11 +7,16 @@ LL | |                 ptr.0 as *mut _,
 LL | |                 std::mem::size_of::<usize>(),
 LL | |                 std::mem::align_of::<usize>(),
 LL | |             );
-   | |_____________^ Data race detected between Deallocate on thread `<unnamed>` and Write on thread `<unnamed>` at ALLOC
+   | |_____________^ Data race detected between (1) Write on thread `<unnamed>` and (2) Deallocate on thread `<unnamed>` at ALLOC. (2) just happened here
    |
+help: and (1) occurred earlier here
+  --> $DIR/dealloc_write_race1.rs:LL:CC
+   |
+LL |             *ptr.0 = 2;
+   |             ^^^^^^^^^^
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside closure at $DIR/dealloc_write_race1.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/data_race/dealloc_write_race2.rs b/src/tools/miri/tests/fail/data_race/dealloc_write_race2.rs
index 4af8b904626..385584db27f 100644
--- a/src/tools/miri/tests/fail/data_race/dealloc_write_race2.rs
+++ b/src/tools/miri/tests/fail/data_race/dealloc_write_race2.rs
@@ -27,7 +27,7 @@ pub fn main() {
         });
 
         let j2 = spawn(move || {
-            // Also an error of the form: Data race detected between Write on thread `<unnamed>` and Deallocate on thread `<unnamed>`
+            // Also an error of the form: Data race detected between (1) Deallocate on thread `<unnamed>` and (2) Write on thread `<unnamed>`
             // but the invalid allocation is detected first.
             *ptr.0 = 2; //~ ERROR: dereferenced after this allocation got freed
         });
diff --git a/src/tools/miri/tests/fail/data_race/dealloc_write_race_stack.rs b/src/tools/miri/tests/fail/data_race/dealloc_write_race_stack.rs
index f851ce95785..259fbdc497a 100644
--- a/src/tools/miri/tests/fail/data_race/dealloc_write_race_stack.rs
+++ b/src/tools/miri/tests/fail/data_race/dealloc_write_race_stack.rs
@@ -35,7 +35,7 @@ pub fn main() {
                 sleep(Duration::from_millis(200));
 
                 // Now `stack_var` gets deallocated.
-            } //~ ERROR: Data race detected between Deallocate on thread `<unnamed>` and Write on thread `<unnamed>`
+            } //~ ERROR: Data race detected between (1) Write on thread `<unnamed>` and (2) Deallocate on thread `<unnamed>`
         });
 
         let j2 = spawn(move || {
diff --git a/src/tools/miri/tests/fail/data_race/dealloc_write_race_stack.stderr b/src/tools/miri/tests/fail/data_race/dealloc_write_race_stack.stderr
index 7b77e2470a1..5f9f4f9bee4 100644
--- a/src/tools/miri/tests/fail/data_race/dealloc_write_race_stack.stderr
+++ b/src/tools/miri/tests/fail/data_race/dealloc_write_race_stack.stderr
@@ -1,12 +1,17 @@
-error: Undefined Behavior: Data race detected between Deallocate on thread `<unnamed>` and Write on thread `<unnamed>` at ALLOC
+error: Undefined Behavior: Data race detected between (1) Write on thread `<unnamed>` and (2) Deallocate on thread `<unnamed>` at ALLOC. (2) just happened here
   --> $DIR/dealloc_write_race_stack.rs:LL:CC
    |
 LL |             }
-   |             ^ Data race detected between Deallocate on thread `<unnamed>` and Write on thread `<unnamed>` at ALLOC
+   |             ^ Data race detected between (1) Write on thread `<unnamed>` and (2) Deallocate on thread `<unnamed>` at ALLOC. (2) just happened here
    |
+help: and (1) occurred earlier here
+  --> $DIR/dealloc_write_race_stack.rs:LL:CC
+   |
+LL |             *pointer.load(Ordering::Acquire) = 3;
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside closure at $DIR/dealloc_write_race_stack.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/data_race/enable_after_join_to_main.rs b/src/tools/miri/tests/fail/data_race/enable_after_join_to_main.rs
index 27aa16a122f..3d47b1accb3 100644
--- a/src/tools/miri/tests/fail/data_race/enable_after_join_to_main.rs
+++ b/src/tools/miri/tests/fail/data_race/enable_after_join_to_main.rs
@@ -30,7 +30,7 @@ pub fn main() {
         });
 
         let j2 = spawn(move || {
-            *c.0 = 64; //~ ERROR: Data race detected between Write on thread `<unnamed>` and Write on thread `<unnamed>`
+            *c.0 = 64; //~ ERROR: Data race detected between (1) Write on thread `<unnamed>` and (2) Write on thread `<unnamed>`
         });
 
         j1.join().unwrap();
diff --git a/src/tools/miri/tests/fail/data_race/enable_after_join_to_main.stderr b/src/tools/miri/tests/fail/data_race/enable_after_join_to_main.stderr
index 26c07ae6962..84d1c0bf7e6 100644
--- a/src/tools/miri/tests/fail/data_race/enable_after_join_to_main.stderr
+++ b/src/tools/miri/tests/fail/data_race/enable_after_join_to_main.stderr
@@ -1,12 +1,17 @@
-error: Undefined Behavior: Data race detected between Write on thread `<unnamed>` and Write on thread `<unnamed>` at ALLOC
+error: Undefined Behavior: Data race detected between (1) Write on thread `<unnamed>` and (2) Write on thread `<unnamed>` at ALLOC. (2) just happened here
   --> $DIR/enable_after_join_to_main.rs:LL:CC
    |
 LL |             *c.0 = 64;
-   |             ^^^^^^^^^ Data race detected between Write on thread `<unnamed>` and Write on thread `<unnamed>` at ALLOC
+   |             ^^^^^^^^^ Data race detected between (1) Write on thread `<unnamed>` and (2) Write on thread `<unnamed>` at ALLOC. (2) just happened here
    |
+help: and (1) occurred earlier here
+  --> $DIR/enable_after_join_to_main.rs:LL:CC
+   |
+LL |             *c.0 = 32;
+   |             ^^^^^^^^^
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside closure at $DIR/enable_after_join_to_main.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/data_race/fence_after_load.rs b/src/tools/miri/tests/fail/data_race/fence_after_load.rs
index 4d436d51f98..0648aa55f4a 100644
--- a/src/tools/miri/tests/fail/data_race/fence_after_load.rs
+++ b/src/tools/miri/tests/fail/data_race/fence_after_load.rs
@@ -20,5 +20,5 @@ fn main() {
     // The fence is useless, since it did not happen-after the `store` in the other thread.
     // Hence this is a data race.
     // Also see https://github.com/rust-lang/miri/issues/2192.
-    unsafe { V = 2 } //~ERROR: Data race detected between Write on thread `main` and Write on thread `<unnamed>`
+    unsafe { V = 2 } //~ERROR: Data race detected between (1) Write on thread `<unnamed>` and (2) Write on thread `main`
 }
diff --git a/src/tools/miri/tests/fail/data_race/fence_after_load.stderr b/src/tools/miri/tests/fail/data_race/fence_after_load.stderr
index 0abfe213db1..c30d2354e76 100644
--- a/src/tools/miri/tests/fail/data_race/fence_after_load.stderr
+++ b/src/tools/miri/tests/fail/data_race/fence_after_load.stderr
@@ -1,12 +1,17 @@
-error: Undefined Behavior: Data race detected between Write on thread `main` and Write on thread `<unnamed>` at ALLOC
+error: Undefined Behavior: Data race detected between (1) Write on thread `<unnamed>` and (2) Write on thread `main` at ALLOC. (2) just happened here
   --> $DIR/fence_after_load.rs:LL:CC
    |
 LL |     unsafe { V = 2 }
-   |              ^^^^^ Data race detected between Write on thread `main` and Write on thread `<unnamed>` at ALLOC
+   |              ^^^^^ Data race detected between (1) Write on thread `<unnamed>` and (2) Write on thread `main` at ALLOC. (2) just happened here
    |
+help: and (1) occurred earlier here
+  --> $DIR/fence_after_load.rs:LL:CC
+   |
+LL |         unsafe { V = 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
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside `main` at $DIR/fence_after_load.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/data_race/read_write_race.rs b/src/tools/miri/tests/fail/data_race/read_write_race.rs
index b26ec6c4142..d996141db3e 100644
--- a/src/tools/miri/tests/fail/data_race/read_write_race.rs
+++ b/src/tools/miri/tests/fail/data_race/read_write_race.rs
@@ -19,7 +19,7 @@ pub fn main() {
         });
 
         let j2 = spawn(move || {
-            *c.0 = 64; //~ ERROR: Data race detected between Write on thread `<unnamed>` and Read on thread `<unnamed>`
+            *c.0 = 64; //~ ERROR: Data race detected between (1) Read on thread `<unnamed>` and (2) Write on thread `<unnamed>`
         });
 
         j1.join().unwrap();
diff --git a/src/tools/miri/tests/fail/data_race/read_write_race.stderr b/src/tools/miri/tests/fail/data_race/read_write_race.stderr
index 08a19537312..13bc5c74ae3 100644
--- a/src/tools/miri/tests/fail/data_race/read_write_race.stderr
+++ b/src/tools/miri/tests/fail/data_race/read_write_race.stderr
@@ -1,12 +1,17 @@
-error: Undefined Behavior: Data race detected between Write on thread `<unnamed>` and Read on thread `<unnamed>` at ALLOC
+error: Undefined Behavior: Data race detected between (1) Read on thread `<unnamed>` and (2) Write on thread `<unnamed>` at ALLOC. (2) just happened here
   --> $DIR/read_write_race.rs:LL:CC
    |
 LL |             *c.0 = 64;
-   |             ^^^^^^^^^ Data race detected between Write on thread `<unnamed>` and Read on thread `<unnamed>` at ALLOC
+   |             ^^^^^^^^^ Data race detected between (1) Read on thread `<unnamed>` and (2) Write on thread `<unnamed>` at ALLOC. (2) just happened here
    |
+help: and (1) occurred earlier here
+  --> $DIR/read_write_race.rs:LL:CC
+   |
+LL |             let _val = *c.0;
+   |                        ^^^^
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside closure at $DIR/read_write_race.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/data_race/read_write_race_stack.rs b/src/tools/miri/tests/fail/data_race/read_write_race_stack.rs
index 2fbac173993..b4e371f430d 100644
--- a/src/tools/miri/tests/fail/data_race/read_write_race_stack.rs
+++ b/src/tools/miri/tests/fail/data_race/read_write_race_stack.rs
@@ -42,7 +42,7 @@ pub fn main() {
 
             sleep(Duration::from_millis(200));
 
-            stack_var //~ ERROR: Data race detected between Read on thread `<unnamed>` and Write on thread `<unnamed>`
+            stack_var //~ ERROR: Data race detected between (1) Write on thread `<unnamed>` and (2) Read on thread `<unnamed>`
         });
 
         let j2 = spawn(move || {
diff --git a/src/tools/miri/tests/fail/data_race/read_write_race_stack.stderr b/src/tools/miri/tests/fail/data_race/read_write_race_stack.stderr
index 20f137afe73..96fcb494822 100644
--- a/src/tools/miri/tests/fail/data_race/read_write_race_stack.stderr
+++ b/src/tools/miri/tests/fail/data_race/read_write_race_stack.stderr
@@ -1,12 +1,17 @@
-error: Undefined Behavior: Data race detected between Read on thread `<unnamed>` and Write on thread `<unnamed>` at ALLOC
+error: Undefined Behavior: Data race detected between (1) Write on thread `<unnamed>` and (2) Read on thread `<unnamed>` at ALLOC. (2) just happened here
   --> $DIR/read_write_race_stack.rs:LL:CC
    |
 LL |             stack_var
-   |             ^^^^^^^^^ Data race detected between Read on thread `<unnamed>` and Write on thread `<unnamed>` at ALLOC
+   |             ^^^^^^^^^ Data race detected between (1) Write on thread `<unnamed>` and (2) Read on thread `<unnamed>` at ALLOC. (2) just happened here
    |
+help: and (1) occurred earlier here
+  --> $DIR/read_write_race_stack.rs:LL:CC
+   |
+LL |             *pointer.load(Ordering::Acquire) = 3;
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside closure at $DIR/read_write_race_stack.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/data_race/relax_acquire_race.rs b/src/tools/miri/tests/fail/data_race/relax_acquire_race.rs
index 24040a94961..b7226fa626f 100644
--- a/src/tools/miri/tests/fail/data_race/relax_acquire_race.rs
+++ b/src/tools/miri/tests/fail/data_race/relax_acquire_race.rs
@@ -37,7 +37,7 @@ pub fn main() {
 
         let j3 = spawn(move || {
             if SYNC.load(Ordering::Acquire) == 2 {
-                *c.0 //~ ERROR: Data race detected between Read on thread `<unnamed>` and Write on thread `<unnamed>`
+                *c.0 //~ ERROR: Data race detected between (1) Write on thread `<unnamed>` and (2) Read on thread `<unnamed>`
             } else {
                 0
             }
diff --git a/src/tools/miri/tests/fail/data_race/relax_acquire_race.stderr b/src/tools/miri/tests/fail/data_race/relax_acquire_race.stderr
index 6121c25db22..92755f5551d 100644
--- a/src/tools/miri/tests/fail/data_race/relax_acquire_race.stderr
+++ b/src/tools/miri/tests/fail/data_race/relax_acquire_race.stderr
@@ -1,12 +1,17 @@
-error: Undefined Behavior: Data race detected between Read on thread `<unnamed>` and Write on thread `<unnamed>` at ALLOC
+error: Undefined Behavior: Data race detected between (1) Write on thread `<unnamed>` and (2) Read on thread `<unnamed>` at ALLOC. (2) just happened here
   --> $DIR/relax_acquire_race.rs:LL:CC
    |
 LL |                 *c.0
-   |                 ^^^^ Data race detected between Read on thread `<unnamed>` and Write on thread `<unnamed>` at ALLOC
+   |                 ^^^^ Data race detected between (1) Write on thread `<unnamed>` and (2) Read on thread `<unnamed>` at ALLOC. (2) just happened here
    |
+help: and (1) occurred earlier here
+  --> $DIR/relax_acquire_race.rs:LL:CC
+   |
+LL |             *c.0 = 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
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside closure at $DIR/relax_acquire_race.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/data_race/release_seq_race.rs b/src/tools/miri/tests/fail/data_race/release_seq_race.rs
index 2d7246858e1..dff33a42a1c 100644
--- a/src/tools/miri/tests/fail/data_race/release_seq_race.rs
+++ b/src/tools/miri/tests/fail/data_race/release_seq_race.rs
@@ -41,7 +41,7 @@ pub fn main() {
         let j3 = spawn(move || {
             sleep(Duration::from_millis(500));
             if SYNC.load(Ordering::Acquire) == 3 {
-                *c.0 //~ ERROR: Data race detected between Read on thread `<unnamed>` and Write on thread `<unnamed>`
+                *c.0 //~ ERROR: Data race detected between (1) Write on thread `<unnamed>` and (2) Read on thread `<unnamed>`
             } else {
                 0
             }
diff --git a/src/tools/miri/tests/fail/data_race/release_seq_race.stderr b/src/tools/miri/tests/fail/data_race/release_seq_race.stderr
index 777bc4adadc..880268730db 100644
--- a/src/tools/miri/tests/fail/data_race/release_seq_race.stderr
+++ b/src/tools/miri/tests/fail/data_race/release_seq_race.stderr
@@ -1,12 +1,17 @@
-error: Undefined Behavior: Data race detected between Read on thread `<unnamed>` and Write on thread `<unnamed>` at ALLOC
+error: Undefined Behavior: Data race detected between (1) Write on thread `<unnamed>` and (2) Read on thread `<unnamed>` at ALLOC. (2) just happened here
   --> $DIR/release_seq_race.rs:LL:CC
    |
 LL |                 *c.0
-   |                 ^^^^ Data race detected between Read on thread `<unnamed>` and Write on thread `<unnamed>` at ALLOC
+   |                 ^^^^ Data race detected between (1) Write on thread `<unnamed>` and (2) Read on thread `<unnamed>` at ALLOC. (2) just happened here
    |
+help: and (1) occurred earlier here
+  --> $DIR/release_seq_race.rs:LL:CC
+   |
+LL |             *c.0 = 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
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside closure at $DIR/release_seq_race.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/data_race/release_seq_race_same_thread.rs b/src/tools/miri/tests/fail/data_race/release_seq_race_same_thread.rs
index 0f974e1c56d..f7a523841b8 100644
--- a/src/tools/miri/tests/fail/data_race/release_seq_race_same_thread.rs
+++ b/src/tools/miri/tests/fail/data_race/release_seq_race_same_thread.rs
@@ -37,7 +37,7 @@ pub fn main() {
 
         let j2 = spawn(move || {
             if SYNC.load(Ordering::Acquire) == 2 {
-                *c.0 //~ ERROR: Data race detected between Read on thread `<unnamed>` and Write on thread `<unnamed>`
+                *c.0 //~ ERROR: Data race detected between (1) Write on thread `<unnamed>` and (2) Read on thread `<unnamed>`
             } else {
                 0
             }
diff --git a/src/tools/miri/tests/fail/data_race/release_seq_race_same_thread.stderr b/src/tools/miri/tests/fail/data_race/release_seq_race_same_thread.stderr
index 0fcb192d920..386c012ba4e 100644
--- a/src/tools/miri/tests/fail/data_race/release_seq_race_same_thread.stderr
+++ b/src/tools/miri/tests/fail/data_race/release_seq_race_same_thread.stderr
@@ -1,12 +1,17 @@
-error: Undefined Behavior: Data race detected between Read on thread `<unnamed>` and Write on thread `<unnamed>` at ALLOC
+error: Undefined Behavior: Data race detected between (1) Write on thread `<unnamed>` and (2) Read on thread `<unnamed>` at ALLOC. (2) just happened here
   --> $DIR/release_seq_race_same_thread.rs:LL:CC
    |
 LL |                 *c.0
-   |                 ^^^^ Data race detected between Read on thread `<unnamed>` and Write on thread `<unnamed>` at ALLOC
+   |                 ^^^^ Data race detected between (1) Write on thread `<unnamed>` and (2) Read on thread `<unnamed>` at ALLOC. (2) just happened here
    |
+help: and (1) occurred earlier here
+  --> $DIR/release_seq_race_same_thread.rs:LL:CC
+   |
+LL |             *c.0 = 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
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside closure at $DIR/release_seq_race_same_thread.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/data_race/rmw_race.rs b/src/tools/miri/tests/fail/data_race/rmw_race.rs
index 2d13da30b46..2201362b167 100644
--- a/src/tools/miri/tests/fail/data_race/rmw_race.rs
+++ b/src/tools/miri/tests/fail/data_race/rmw_race.rs
@@ -38,7 +38,7 @@ pub fn main() {
 
         let j3 = spawn(move || {
             if SYNC.load(Ordering::Acquire) == 3 {
-                *c.0 //~ ERROR: Data race detected between Read on thread `<unnamed>` and Write on thread `<unnamed>`
+                *c.0 //~ ERROR: Data race detected between (1) Write on thread `<unnamed>` and (2) Read on thread `<unnamed>`
             } else {
                 0
             }
diff --git a/src/tools/miri/tests/fail/data_race/rmw_race.stderr b/src/tools/miri/tests/fail/data_race/rmw_race.stderr
index 3ae6f3b84fe..82cb2c4ecbb 100644
--- a/src/tools/miri/tests/fail/data_race/rmw_race.stderr
+++ b/src/tools/miri/tests/fail/data_race/rmw_race.stderr
@@ -1,12 +1,17 @@
-error: Undefined Behavior: Data race detected between Read on thread `<unnamed>` and Write on thread `<unnamed>` at ALLOC
+error: Undefined Behavior: Data race detected between (1) Write on thread `<unnamed>` and (2) Read on thread `<unnamed>` at ALLOC. (2) just happened here
   --> $DIR/rmw_race.rs:LL:CC
    |
 LL |                 *c.0
-   |                 ^^^^ Data race detected between Read on thread `<unnamed>` and Write on thread `<unnamed>` at ALLOC
+   |                 ^^^^ Data race detected between (1) Write on thread `<unnamed>` and (2) Read on thread `<unnamed>` at ALLOC. (2) just happened here
    |
+help: and (1) occurred earlier here
+  --> $DIR/rmw_race.rs:LL:CC
+   |
+LL |             *c.0 = 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
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside closure at $DIR/rmw_race.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/data_race/stack_pop_race.rs b/src/tools/miri/tests/fail/data_race/stack_pop_race.rs
index cf5c2ed81cb..dec5ff274cc 100644
--- a/src/tools/miri/tests/fail/data_race/stack_pop_race.rs
+++ b/src/tools/miri/tests/fail/data_race/stack_pop_race.rs
@@ -21,4 +21,4 @@ fn race(local: i32) {
     // Deallocating the local (when `main` returns)
     // races with the read in the other thread.
     // Make sure the error points at this function's end, not just the call site.
-} //~ERROR: Data race detected between Deallocate on thread `main` and Read on thread `<unnamed>`
+} //~ERROR: Data race detected between (1) Read on thread `<unnamed>` and (2) Deallocate on thread `main`
diff --git a/src/tools/miri/tests/fail/data_race/stack_pop_race.stderr b/src/tools/miri/tests/fail/data_race/stack_pop_race.stderr
index 0075f877b29..71e38c2727e 100644
--- a/src/tools/miri/tests/fail/data_race/stack_pop_race.stderr
+++ b/src/tools/miri/tests/fail/data_race/stack_pop_race.stderr
@@ -1,12 +1,17 @@
-error: Undefined Behavior: Data race detected between Deallocate on thread `main` and Read on thread `<unnamed>` at ALLOC
+error: Undefined Behavior: Data race detected between (1) Read on thread `<unnamed>` and (2) Deallocate on thread `main` at ALLOC. (2) just happened here
   --> $DIR/stack_pop_race.rs:LL:CC
    |
 LL | }
-   |  ^ Data race detected between Deallocate on thread `main` and Read on thread `<unnamed>` at ALLOC
+   |  ^ Data race detected between (1) Read on thread `<unnamed>` and (2) Deallocate on thread `main` at ALLOC. (2) just happened here
    |
+help: and (1) occurred earlier here
+  --> $DIR/stack_pop_race.rs:LL:CC
+   |
+LL |         let _val = unsafe { *ptr.0 };
+   |                             ^^^^^^
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside `race` at $DIR/stack_pop_race.rs:LL:CC
 note: inside `main`
   --> $DIR/stack_pop_race.rs:LL:CC
diff --git a/src/tools/miri/tests/fail/data_race/write_write_race.rs b/src/tools/miri/tests/fail/data_race/write_write_race.rs
index 60e9ac2ac6c..fe02d02f9dc 100644
--- a/src/tools/miri/tests/fail/data_race/write_write_race.rs
+++ b/src/tools/miri/tests/fail/data_race/write_write_race.rs
@@ -19,7 +19,7 @@ pub fn main() {
         });
 
         let j2 = spawn(move || {
-            *c.0 = 64; //~ ERROR: Data race detected between Write on thread `<unnamed>` and Write on thread `<unnamed>`
+            *c.0 = 64; //~ ERROR: Data race detected between (1) Write on thread `<unnamed>` and (2) Write on thread `<unnamed>`
         });
 
         j1.join().unwrap();
diff --git a/src/tools/miri/tests/fail/data_race/write_write_race.stderr b/src/tools/miri/tests/fail/data_race/write_write_race.stderr
index ee7072ccf5d..3b7eb2b8000 100644
--- a/src/tools/miri/tests/fail/data_race/write_write_race.stderr
+++ b/src/tools/miri/tests/fail/data_race/write_write_race.stderr
@@ -1,12 +1,17 @@
-error: Undefined Behavior: Data race detected between Write on thread `<unnamed>` and Write on thread `<unnamed>` at ALLOC
+error: Undefined Behavior: Data race detected between (1) Write on thread `<unnamed>` and (2) Write on thread `<unnamed>` at ALLOC. (2) just happened here
   --> $DIR/write_write_race.rs:LL:CC
    |
 LL |             *c.0 = 64;
-   |             ^^^^^^^^^ Data race detected between Write on thread `<unnamed>` and Write on thread `<unnamed>` at ALLOC
+   |             ^^^^^^^^^ Data race detected between (1) Write on thread `<unnamed>` and (2) Write on thread `<unnamed>` at ALLOC. (2) just happened here
    |
+help: and (1) occurred earlier here
+  --> $DIR/write_write_race.rs:LL:CC
+   |
+LL |             *c.0 = 32;
+   |             ^^^^^^^^^
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside closure at $DIR/write_write_race.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/data_race/write_write_race_stack.rs b/src/tools/miri/tests/fail/data_race/write_write_race_stack.rs
index 0a29dc13cba..c1c1b1fa6e3 100644
--- a/src/tools/miri/tests/fail/data_race/write_write_race_stack.rs
+++ b/src/tools/miri/tests/fail/data_race/write_write_race_stack.rs
@@ -39,7 +39,7 @@ pub fn main() {
 
             sleep(Duration::from_millis(200));
 
-            stack_var = 1usize; //~ ERROR: Data race detected between Write on thread `<unnamed>` and Write on thread `<unnamed>`
+            stack_var = 1usize; //~ ERROR: Data race detected between (1) Write on thread `<unnamed>` and (2) Write on thread `<unnamed>`
 
             // read to silence errors
             stack_var
diff --git a/src/tools/miri/tests/fail/data_race/write_write_race_stack.stderr b/src/tools/miri/tests/fail/data_race/write_write_race_stack.stderr
index ceb473c2a4a..c501ecd11a6 100644
--- a/src/tools/miri/tests/fail/data_race/write_write_race_stack.stderr
+++ b/src/tools/miri/tests/fail/data_race/write_write_race_stack.stderr
@@ -1,12 +1,17 @@
-error: Undefined Behavior: Data race detected between Write on thread `<unnamed>` and Write on thread `<unnamed>` at ALLOC
+error: Undefined Behavior: Data race detected between (1) Write on thread `<unnamed>` and (2) Write on thread `<unnamed>` at ALLOC. (2) just happened here
   --> $DIR/write_write_race_stack.rs:LL:CC
    |
 LL |             stack_var = 1usize;
-   |             ^^^^^^^^^^^^^^^^^^ Data race detected between Write on thread `<unnamed>` and Write on thread `<unnamed>` at ALLOC
+   |             ^^^^^^^^^^^^^^^^^^ Data race detected between (1) Write on thread `<unnamed>` and (2) Write on thread `<unnamed>` at ALLOC. (2) just happened here
    |
+help: and (1) occurred earlier here
+  --> $DIR/write_write_race_stack.rs:LL:CC
+   |
+LL |             *pointer.load(Ordering::Acquire) = 3;
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside closure at $DIR/write_write_race_stack.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/function_calls/exported_symbol_clashing.stderr b/src/tools/miri/tests/fail/function_calls/exported_symbol_clashing.stderr
index 8eb9fa4ff5c..09e4157b31f 100644
--- a/src/tools/miri/tests/fail/function_calls/exported_symbol_clashing.stderr
+++ b/src/tools/miri/tests/fail/function_calls/exported_symbol_clashing.stderr
@@ -14,7 +14,7 @@ help: then it's defined here again, in crate `exported_symbol_clashing`
    |
 LL | fn bar() {}
    | ^^^^^^^^
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside `main` at $DIR/exported_symbol_clashing.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/function_calls/exported_symbol_shim_clashing.stderr b/src/tools/miri/tests/fail/function_calls/exported_symbol_shim_clashing.stderr
index 58a996e6453..0d0055bb85c 100644
--- a/src/tools/miri/tests/fail/function_calls/exported_symbol_shim_clashing.stderr
+++ b/src/tools/miri/tests/fail/function_calls/exported_symbol_shim_clashing.stderr
@@ -12,7 +12,7 @@ LL | |
 LL | |     unreachable!()
 LL | | }
    | |_^
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside `main` at $DIR/exported_symbol_shim_clashing.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/reading_half_a_pointer.rs b/src/tools/miri/tests/fail/reading_half_a_pointer.rs
index 2d669132624..7dd98eab785 100644
--- a/src/tools/miri/tests/fail/reading_half_a_pointer.rs
+++ b/src/tools/miri/tests/fail/reading_half_a_pointer.rs
@@ -7,7 +7,7 @@ struct Data {
     ptr: &'static i32,
 }
 
-// But we need to gurantee some alignment
+// But we need to guarantee some alignment
 struct Wrapper {
     align: u64,
     data: Data,
diff --git a/src/tools/miri/tests/fail/stacked_borrows/alias_through_mutation.stderr b/src/tools/miri/tests/fail/stacked_borrows/alias_through_mutation.stderr
index 461275c3fa3..b22db3eb121 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/alias_through_mutation.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/alias_through_mutation.stderr
@@ -19,7 +19,7 @@ help: <TAG> was later invalidated at offsets [0x0..0x4] by a write access
    |
 LL |     *target = 13;
    |     ^^^^^^^^^^^^
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside `main` at $DIR/alias_through_mutation.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/stacked_borrows/aliasing_mut1.stderr b/src/tools/miri/tests/fail/stacked_borrows/aliasing_mut1.stderr
index 4514abb4ab2..3ce39968cbb 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/aliasing_mut1.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/aliasing_mut1.stderr
@@ -16,7 +16,7 @@ help: <TAG> is this argument
    |
 LL | pub fn safe(_x: &mut i32, _y: &mut i32) {}
    |             ^^
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside `safe` at $DIR/aliasing_mut1.rs:LL:CC
 note: inside `main`
   --> $DIR/aliasing_mut1.rs:LL:CC
diff --git a/src/tools/miri/tests/fail/stacked_borrows/aliasing_mut2.stderr b/src/tools/miri/tests/fail/stacked_borrows/aliasing_mut2.stderr
index 9ca9743cbd9..df4b6cf0256 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/aliasing_mut2.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/aliasing_mut2.stderr
@@ -16,7 +16,7 @@ help: <TAG> is this argument
    |
 LL | pub fn safe(_x: &i32, _y: &mut i32) {}
    |             ^^
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside `safe` at $DIR/aliasing_mut2.rs:LL:CC
 note: inside `main`
   --> $DIR/aliasing_mut2.rs:LL:CC
diff --git a/src/tools/miri/tests/fail/stacked_borrows/aliasing_mut3.stderr b/src/tools/miri/tests/fail/stacked_borrows/aliasing_mut3.stderr
index b504097a3c9..55aaed62f4f 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/aliasing_mut3.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/aliasing_mut3.stderr
@@ -19,7 +19,7 @@ help: <TAG> was later invalidated at offsets [0x0..0x4] by a Unique FnEntry reta
    |
 LL |     safe_raw(xraw, xshr);
    |     ^^^^^^^^^^^^^^^^^^^^
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside `safe` at $DIR/aliasing_mut3.rs:LL:CC
 note: inside `main`
   --> $DIR/aliasing_mut3.rs:LL:CC
diff --git a/src/tools/miri/tests/fail/stacked_borrows/aliasing_mut4.stderr b/src/tools/miri/tests/fail/stacked_borrows/aliasing_mut4.stderr
index 6fe0d709029..ddf197bc639 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/aliasing_mut4.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/aliasing_mut4.stderr
@@ -16,7 +16,7 @@ help: <TAG> is this argument
    |
 LL | pub fn safe(_x: &i32, _y: &mut Cell<i32>) {}
    |             ^^
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside `safe` at $DIR/aliasing_mut4.rs:LL:CC
 note: inside `main`
   --> $DIR/aliasing_mut4.rs:LL:CC
diff --git a/src/tools/miri/tests/fail/stacked_borrows/box_exclusive_violation1.stderr b/src/tools/miri/tests/fail/stacked_borrows/box_exclusive_violation1.stderr
index f114130f6fa..76f4e81f71b 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/box_exclusive_violation1.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/box_exclusive_violation1.stderr
@@ -19,7 +19,7 @@ help: <TAG> was later invalidated at offsets [0x0..0x4] by a write access
    |
 LL |     *our = 5;
    |     ^^^^^^^^
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside `unknown_code_2` at $DIR/box_exclusive_violation1.rs:LL:CC
 note: inside `demo_box_advanced_unique`
   --> $DIR/box_exclusive_violation1.rs:LL:CC
diff --git a/src/tools/miri/tests/fail/stacked_borrows/box_noalias_violation.stderr b/src/tools/miri/tests/fail/stacked_borrows/box_noalias_violation.stderr
index 139fcd0ca45..59377aeb971 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/box_noalias_violation.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/box_noalias_violation.stderr
@@ -16,7 +16,7 @@ help: <TAG> is this argument
    |
 LL | unsafe fn test(mut x: Box<i32>, y: *const i32) -> i32 {
    |                ^^^^^
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside `test` at $DIR/box_noalias_violation.rs:LL:CC
 note: inside `main`
   --> $DIR/box_noalias_violation.rs:LL:CC
diff --git a/src/tools/miri/tests/fail/stacked_borrows/buggy_as_mut_slice.stderr b/src/tools/miri/tests/fail/stacked_borrows/buggy_as_mut_slice.stderr
index 6aa14361287..fa3d7ca3676 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/buggy_as_mut_slice.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/buggy_as_mut_slice.stderr
@@ -19,7 +19,7 @@ help: <TAG> was later invalidated at offsets [0x0..0xc] by a Unique retag
    |
 LL |         unsafe { from_raw_parts_mut(self_.as_ptr() as *mut T, self_.len()) }
    |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside `main` at $DIR/buggy_as_mut_slice.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/stacked_borrows/buggy_split_at_mut.stderr b/src/tools/miri/tests/fail/stacked_borrows/buggy_split_at_mut.stderr
index cdeccc0855a..c75d8cab3fc 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/buggy_split_at_mut.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/buggy_split_at_mut.stderr
@@ -19,7 +19,7 @@ help: <TAG> was later invalidated at offsets [0x0..0x10] by a Unique retag
    |
 LL |                 from_raw_parts_mut(ptr.offset(mid as isize), len - mid),
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside `main` at $DIR/buggy_split_at_mut.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/stacked_borrows/disable_mut_does_not_merge_srw.stderr b/src/tools/miri/tests/fail/stacked_borrows/disable_mut_does_not_merge_srw.stderr
index e05f44fac9d..bd79b401f66 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/disable_mut_does_not_merge_srw.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/disable_mut_does_not_merge_srw.stderr
@@ -19,7 +19,7 @@ help: <TAG> was later invalidated at offsets [0x0..0x4] by a write access
    |
 LL |         *base = 1;
    |         ^^^^^^^^^
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside `main` at $DIR/disable_mut_does_not_merge_srw.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/stacked_borrows/drop_in_place_protector.rs b/src/tools/miri/tests/fail/stacked_borrows/drop_in_place_protector.rs
new file mode 100644
index 00000000000..8cf63ee700b
--- /dev/null
+++ b/src/tools/miri/tests/fail/stacked_borrows/drop_in_place_protector.rs
@@ -0,0 +1,27 @@
+//! Test that drop_in_place retags the entire place,
+//! invalidating all aliases to it.
+
+// A zero-sized drop type -- the retagging of `fn drop` itself won't
+// do anything (since it is zero-sized); we are entirely relying on the retagging
+// in `drop_in_place` here.
+#[repr(transparent)]
+struct HasDrop;
+impl Drop for HasDrop {
+    fn drop(&mut self) {
+        unsafe {
+            let _val = *P;
+            //~^ ERROR: /not granting access .* because that would remove .* which is strongly protected/
+        }
+    }
+}
+
+static mut P: *mut u8 = core::ptr::null_mut();
+
+fn main() {
+    unsafe {
+        let mut x = (HasDrop, 0u8);
+        let x = core::ptr::addr_of_mut!(x);
+        P = x.cast();
+        core::ptr::drop_in_place(x);
+    }
+}
diff --git a/src/tools/miri/tests/fail/stacked_borrows/drop_in_place_protector.stderr b/src/tools/miri/tests/fail/stacked_borrows/drop_in_place_protector.stderr
new file mode 100644
index 00000000000..3d0cef241c3
--- /dev/null
+++ b/src/tools/miri/tests/fail/stacked_borrows/drop_in_place_protector.stderr
@@ -0,0 +1,33 @@
+error: Undefined Behavior: not granting access to tag <TAG> because that would remove [Unique for <TAG>] which is strongly protected because it is an argument of call ID
+  --> $DIR/drop_in_place_protector.rs:LL:CC
+   |
+LL |             let _val = *P;
+   |                        ^^ not granting access to tag <TAG> because that would remove [Unique for <TAG>] which is strongly protected because it is an argument of call ID
+   |
+   = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental
+   = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information
+help: <TAG> was created by a SharedReadWrite retag at offsets [0x0..0x1]
+  --> $DIR/drop_in_place_protector.rs:LL:CC
+   |
+LL |         let x = core::ptr::addr_of_mut!(x);
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^
+help: <TAG> is this argument
+  --> $DIR/drop_in_place_protector.rs:LL:CC
+   |
+LL |         core::ptr::drop_in_place(x);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = note: BACKTRACE (of the first span):
+   = note: inside `<HasDrop as std::ops::Drop>::drop` at $DIR/drop_in_place_protector.rs:LL:CC
+   = note: inside `std::ptr::drop_in_place::<HasDrop> - shim(Some(HasDrop))` at RUSTLIB/core/src/ptr/mod.rs:LL:CC
+   = note: inside `std::ptr::drop_in_place::<(HasDrop, u8)> - shim(Some((HasDrop, u8)))` at RUSTLIB/core/src/ptr/mod.rs:LL:CC
+note: inside `main`
+  --> $DIR/drop_in_place_protector.rs:LL:CC
+   |
+LL |         core::ptr::drop_in_place(x);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = note: this error originates in the macro `core::ptr::addr_of_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
+
+error: aborting due to previous error
+
diff --git a/src/tools/miri/tests/fail/stacked_borrows/drop_in_place_retag.rs b/src/tools/miri/tests/fail/stacked_borrows/drop_in_place_retag.rs
new file mode 100644
index 00000000000..8180e2f03a7
--- /dev/null
+++ b/src/tools/miri/tests/fail/stacked_borrows/drop_in_place_retag.rs
@@ -0,0 +1,12 @@
+//! Test that drop_in_place mutably retags the entire place, even for a type that does not need
+//! dropping, ensuring among other things that it is writeable
+
+//@error-pattern: /retag .* for Unique permission .* only grants SharedReadOnly permission/
+
+fn main() {
+    unsafe {
+        let x = 0u8;
+        let x = core::ptr::addr_of!(x);
+        core::ptr::drop_in_place(x.cast_mut());
+    }
+}
diff --git a/src/tools/miri/tests/fail/stacked_borrows/drop_in_place_retag.stderr b/src/tools/miri/tests/fail/stacked_borrows/drop_in_place_retag.stderr
new file mode 100644
index 00000000000..7f2917e7950
--- /dev/null
+++ b/src/tools/miri/tests/fail/stacked_borrows/drop_in_place_retag.stderr
@@ -0,0 +1,29 @@
+error: Undefined Behavior: trying to retag from <TAG> for Unique permission at ALLOC[0x0], but that tag only grants SharedReadOnly permission for this location
+  --> RUSTLIB/core/src/ptr/mod.rs:LL:CC
+   |
+LL | pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   | |
+   | trying to retag from <TAG> for Unique permission at ALLOC[0x0], but that tag only grants SharedReadOnly permission for this location
+   | this error occurs as part of retag at ALLOC[0x0..0x1]
+   |
+   = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental
+   = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information
+help: <TAG> was created by a SharedReadOnly retag at offsets [0x0..0x1]
+  --> $DIR/drop_in_place_retag.rs:LL:CC
+   |
+LL |         let x = core::ptr::addr_of!(x);
+   |                 ^^^^^^^^^^^^^^^^^^^^^^
+   = note: BACKTRACE (of the first span):
+   = note: inside `std::ptr::drop_in_place::<u8> - shim(None)` at RUSTLIB/core/src/ptr/mod.rs:LL:CC
+note: inside `main`
+  --> $DIR/drop_in_place_retag.rs:LL:CC
+   |
+LL |         core::ptr::drop_in_place(x.cast_mut());
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = note: this error originates in the macro `core::ptr::addr_of` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
+
+error: aborting due to previous error
+
diff --git a/src/tools/miri/tests/fail/stacked_borrows/fnentry_invalidation.stderr b/src/tools/miri/tests/fail/stacked_borrows/fnentry_invalidation.stderr
index e81411bbdd8..e3bffde1f01 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/fnentry_invalidation.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/fnentry_invalidation.stderr
@@ -19,7 +19,7 @@ help: <TAG> was later invalidated at offsets [0x0..0x4] by a Unique FnEntry reta
    |
 LL |     x.do_bad();
    |     ^^^^^^^^^^
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside `main` at $DIR/fnentry_invalidation.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/stacked_borrows/fnentry_invalidation2.stderr b/src/tools/miri/tests/fail/stacked_borrows/fnentry_invalidation2.stderr
index d6d0084fa2a..b104de4b8d9 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/fnentry_invalidation2.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/fnentry_invalidation2.stderr
@@ -19,7 +19,7 @@ help: <TAG> was later invalidated at offsets [0x0..0xc] by a Unique FnEntry reta
    |
 LL |     let _ = t.sli.as_mut_ptr();
    |             ^^^^^^^^^^^^^^^^^^
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside `main` at $DIR/fnentry_invalidation2.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/stacked_borrows/illegal_dealloc1.stderr b/src/tools/miri/tests/fail/stacked_borrows/illegal_dealloc1.stderr
index f2f13d0d559..7fff60f25fb 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/illegal_dealloc1.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/illegal_dealloc1.stderr
@@ -16,7 +16,7 @@ help: <TAG> was later invalidated at offsets [0x0..0x1] by a write access
    |
 LL |         ptr1.write(0);
    |         ^^^^^^^^^^^^^
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside `std::alloc::dealloc` at RUSTLIB/alloc/src/alloc.rs:LL:CC
 note: inside `main`
   --> $DIR/illegal_deALLOC.rs:LL:CC
diff --git a/src/tools/miri/tests/fail/stacked_borrows/illegal_read1.stderr b/src/tools/miri/tests/fail/stacked_borrows/illegal_read1.stderr
index 95ff05d70c3..7a159c9d3fe 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/illegal_read1.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/illegal_read1.stderr
@@ -19,7 +19,7 @@ help: <TAG> was later invalidated at offsets [0x0..0x4] by a read access
    |
 LL |     let _val = unsafe { *xraw };
    |                         ^^^^^
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside `main` at $DIR/illegal_read1.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/stacked_borrows/illegal_read2.stderr b/src/tools/miri/tests/fail/stacked_borrows/illegal_read2.stderr
index 5cfdf77dee4..e3e79f6f0f0 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/illegal_read2.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/illegal_read2.stderr
@@ -19,7 +19,7 @@ help: <TAG> was later invalidated at offsets [0x0..0x4] by a SharedReadOnly reta
    |
 LL |     let shr = unsafe { &*xraw };
    |                        ^^^^^^
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside `main` at $DIR/illegal_read2.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/stacked_borrows/illegal_read3.stderr b/src/tools/miri/tests/fail/stacked_borrows/illegal_read3.stderr
index dacf71fa3ee..3a8687ad9aa 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/illegal_read3.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/illegal_read3.stderr
@@ -19,7 +19,7 @@ help: <TAG> was later invalidated at offsets [0x0..0x4] by a read access
    |
 LL |     let _val = unsafe { *xref1.r };
    |                         ^^^^^^^^
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside `main` at $DIR/illegal_read3.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/stacked_borrows/illegal_read4.stderr b/src/tools/miri/tests/fail/stacked_borrows/illegal_read4.stderr
index 5ce0cba6179..dcf37b26901 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/illegal_read4.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/illegal_read4.stderr
@@ -19,7 +19,7 @@ help: <TAG> was later invalidated at offsets [0x0..0x4] by a read access
    |
 LL |     let _val = unsafe { *xraw }; // use the raw again, this invalidates xref2 *even* with the special read except for uniq refs
    |                         ^^^^^
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside `main` at $DIR/illegal_read4.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/stacked_borrows/illegal_read5.stderr b/src/tools/miri/tests/fail/stacked_borrows/illegal_read5.stderr
index 63532f87944..1793798d15f 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/illegal_read5.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/illegal_read5.stderr
@@ -19,7 +19,7 @@ help: <TAG> was later invalidated at offsets [$HEX..$HEX] by a read access
    |
 LL |     mem::forget(unsafe { ptr::read(xshr) }); // but after reading through the shared ref
    |                          ^^^^^^^^^^^^^^^
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside `main` at $DIR/illegal_read5.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/stacked_borrows/illegal_read6.stderr b/src/tools/miri/tests/fail/stacked_borrows/illegal_read6.stderr
index 93a96ab601e..17b28dee3c7 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/illegal_read6.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/illegal_read6.stderr
@@ -19,7 +19,7 @@ help: <TAG> was later invalidated at offsets [0x0..0x4] by a Unique retag
    |
 LL |         let x = &mut *x; // kill `raw`
    |                 ^^^^^^^
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside `main` at $DIR/illegal_read6.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/stacked_borrows/illegal_read7.stderr b/src/tools/miri/tests/fail/stacked_borrows/illegal_read7.stderr
index 2e8ac207bea..b76446d60f6 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/illegal_read7.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/illegal_read7.stderr
@@ -19,7 +19,7 @@ help: <TAG> was later invalidated at offsets [0x0..0x4] by a read access
    |
 LL |         let _val = ptr::read(raw);
    |                    ^^^^^^^^^^^^^^
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside `main` at $DIR/illegal_read7.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/stacked_borrows/illegal_read8.stderr b/src/tools/miri/tests/fail/stacked_borrows/illegal_read8.stderr
index c34fa2d8955..b43079c3b7f 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/illegal_read8.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/illegal_read8.stderr
@@ -19,7 +19,7 @@ help: <TAG> was later invalidated at offsets [0x0..0x4] by a write access
    |
 LL |         *y2 += 1;
    |         ^^^^^^^^
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside `main` at $DIR/illegal_read8.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/stacked_borrows/illegal_read_despite_exposed1.stderr b/src/tools/miri/tests/fail/stacked_borrows/illegal_read_despite_exposed1.stderr
index 43b4ec2ba65..fbd5d8b956d 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/illegal_read_despite_exposed1.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/illegal_read_despite_exposed1.stderr
@@ -19,7 +19,7 @@ help: <TAG> was later invalidated at offsets [0x0..0x4] by a write access
    |
 LL |         *exposed_ptr = 0;
    |         ^^^^^^^^^^^^^^^^
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside `main` at $DIR/illegal_read_despite_exposed1.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/stacked_borrows/illegal_read_despite_exposed2.stderr b/src/tools/miri/tests/fail/stacked_borrows/illegal_read_despite_exposed2.stderr
index 832320fc202..19e4cbdb938 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/illegal_read_despite_exposed2.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/illegal_read_despite_exposed2.stderr
@@ -19,7 +19,7 @@ help: <TAG> was later invalidated at offsets [0x0..0x4] by a read access
    |
 LL |         let _val = *exposed_ptr;
    |                    ^^^^^^^^^^^^
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside `main` at $DIR/illegal_read_despite_exposed2.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/stacked_borrows/illegal_write1.stderr b/src/tools/miri/tests/fail/stacked_borrows/illegal_write1.stderr
index 3bf27f4815e..c1e49181465 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/illegal_write1.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/illegal_write1.stderr
@@ -14,7 +14,7 @@ help: <TAG> was created by a SharedReadOnly retag at offsets [0x0..0x4]
    |
 LL |         let x: *mut u32 = xref as *const _ as *mut _;
    |                           ^^^^
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside `main` at $DIR/illegal_write1.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/stacked_borrows/illegal_write2.stderr b/src/tools/miri/tests/fail/stacked_borrows/illegal_write2.stderr
index a9fe8cb6ccc..3e11e86eb81 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/illegal_write2.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/illegal_write2.stderr
@@ -19,7 +19,7 @@ help: <TAG> was later invalidated at offsets [0x0..0x4] by a Unique retag
    |
 LL |     drop(&mut *target); // reborrow
    |          ^^^^^^^^^^^^
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside `main` at $DIR/illegal_write2.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/stacked_borrows/illegal_write3.stderr b/src/tools/miri/tests/fail/stacked_borrows/illegal_write3.stderr
index d64f2ddd876..4053325821e 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/illegal_write3.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/illegal_write3.stderr
@@ -14,7 +14,7 @@ help: <TAG> was created by a SharedReadOnly retag at offsets [0x0..0x4]
    |
 LL |     let ptr = r#ref as *const _ as *mut _; // raw ptr, with raw tag
    |               ^^^^^
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside `main` at $DIR/illegal_write3.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/stacked_borrows/illegal_write4.stderr b/src/tools/miri/tests/fail/stacked_borrows/illegal_write4.stderr
index e3b8621eb74..fceda8db4ce 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/illegal_write4.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/illegal_write4.stderr
@@ -19,7 +19,7 @@ help: <TAG> was later invalidated at offsets [0x0..0x4] by a Unique retag
    |
 LL |     let _mut_ref: &mut i32 = unsafe { mem::transmute(raw) }; // &mut, with raw tag
    |                                       ^^^^^^^^^^^^^^^^^^^
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside `main` at $DIR/illegal_write4.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/stacked_borrows/illegal_write5.stderr b/src/tools/miri/tests/fail/stacked_borrows/illegal_write5.stderr
index bbeb81258bd..c71780b7e03 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/illegal_write5.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/illegal_write5.stderr
@@ -19,7 +19,7 @@ help: <TAG> was later invalidated at offsets [0x0..0x4] by a write access
    |
 LL |     unsafe { *xraw = 15 };
    |              ^^^^^^^^^^
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside `main` at $DIR/illegal_write5.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/stacked_borrows/illegal_write6.stderr b/src/tools/miri/tests/fail/stacked_borrows/illegal_write6.stderr
index 49d9050f309..3d3d2a24c28 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/illegal_write6.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/illegal_write6.stderr
@@ -16,7 +16,7 @@ help: <TAG> is this argument
    |
 LL | fn foo(a: &mut u32, y: *mut u32) -> u32 {
    |        ^
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside `foo` at $DIR/illegal_write6.rs:LL:CC
 note: inside `main`
   --> $DIR/illegal_write6.rs:LL:CC
diff --git a/src/tools/miri/tests/fail/stacked_borrows/illegal_write_despite_exposed1.stderr b/src/tools/miri/tests/fail/stacked_borrows/illegal_write_despite_exposed1.stderr
index 87ddf61d758..1bb3afe483e 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/illegal_write_despite_exposed1.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/illegal_write_despite_exposed1.stderr
@@ -19,7 +19,7 @@ help: <TAG> was later invalidated at offsets [0x0..0x4] by a write access
    |
 LL |         *exposed_ptr = 0;
    |         ^^^^^^^^^^^^^^^^
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside `main` at $DIR/illegal_write_despite_exposed1.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/stacked_borrows/interior_mut1.stderr b/src/tools/miri/tests/fail/stacked_borrows/interior_mut1.stderr
index 1d68727c82a..da55e724fd8 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/interior_mut1.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/interior_mut1.stderr
@@ -19,7 +19,7 @@ help: <TAG> was later invalidated at offsets [0x0..0x4] by a write access
    |
 LL |         *c.get() = UnsafeCell::new(1); // invalidates inner_shr
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside `main` at $DIR/interior_mut1.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/stacked_borrows/interior_mut2.stderr b/src/tools/miri/tests/fail/stacked_borrows/interior_mut2.stderr
index 8a335714226..8c8a96cbbbd 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/interior_mut2.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/interior_mut2.stderr
@@ -19,7 +19,7 @@ help: <TAG> was later invalidated at offsets [0x0..0x4] by a write access
    |
 LL |         *c.get() = UnsafeCell::new(0); // now inner_shr gets invalidated
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside `main` at $DIR/interior_mut2.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/stacked_borrows/invalidate_against_protector1.stderr b/src/tools/miri/tests/fail/stacked_borrows/invalidate_against_protector1.stderr
index a53c633c381..95fa4c51d12 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/invalidate_against_protector1.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/invalidate_against_protector1.stderr
@@ -16,7 +16,7 @@ help: <TAG> is this argument
    |
 LL | fn inner(x: *mut i32, _y: &mut i32) {
    |                       ^^
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside `inner` at $DIR/invalidate_against_protector1.rs:LL:CC
 note: inside `main`
   --> $DIR/invalidate_against_protector1.rs:LL:CC
diff --git a/src/tools/miri/tests/fail/stacked_borrows/invalidate_against_protector2.stderr b/src/tools/miri/tests/fail/stacked_borrows/invalidate_against_protector2.stderr
index 6ee78d1aac6..8f677bd547c 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/invalidate_against_protector2.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/invalidate_against_protector2.stderr
@@ -16,7 +16,7 @@ help: <TAG> is this argument
    |
 LL | fn inner(x: *mut i32, _y: &i32) {
    |                       ^^
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside `inner` at $DIR/invalidate_against_protector2.rs:LL:CC
 note: inside `main`
   --> $DIR/invalidate_against_protector2.rs:LL:CC
diff --git a/src/tools/miri/tests/fail/stacked_borrows/invalidate_against_protector3.stderr b/src/tools/miri/tests/fail/stacked_borrows/invalidate_against_protector3.stderr
index 2b38dea9dbb..1648ca9e58b 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/invalidate_against_protector3.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/invalidate_against_protector3.stderr
@@ -16,7 +16,7 @@ help: <TAG> is this argument
    |
 LL | fn inner(x: *mut i32, _y: &i32) {
    |                       ^^
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside `inner` at $DIR/invalidate_against_protector3.rs:LL:CC
 note: inside `main`
   --> $DIR/invalidate_against_protector3.rs:LL:CC
diff --git a/src/tools/miri/tests/fail/stacked_borrows/load_invalid_mut.stderr b/src/tools/miri/tests/fail/stacked_borrows/load_invalid_mut.stderr
index 08dc171c9ee..7aca065ca0d 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/load_invalid_mut.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/load_invalid_mut.stderr
@@ -19,7 +19,7 @@ help: <TAG> was later invalidated at offsets [0x0..0x4] by a read access
    |
 LL |     let _val = unsafe { *xraw }; // invalidate xref
    |                         ^^^^^
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside `main` at $DIR/load_invalid_mut.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/stacked_borrows/load_invalid_shr.stderr b/src/tools/miri/tests/fail/stacked_borrows/load_invalid_shr.stderr
index 50bbed2b295..7eb973ae7f2 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/load_invalid_shr.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/load_invalid_shr.stderr
@@ -19,7 +19,7 @@ help: <TAG> was later invalidated at offsets [0x0..0x4] by a write access
    |
 LL |     unsafe { *xraw = 42 }; // unfreeze
    |              ^^^^^^^^^^
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside `main` at $DIR/load_invalid_shr.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/stacked_borrows/mut_exclusive_violation1.stderr b/src/tools/miri/tests/fail/stacked_borrows/mut_exclusive_violation1.stderr
index 2f3900c40d7..3e7fe11b520 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/mut_exclusive_violation1.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/mut_exclusive_violation1.stderr
@@ -19,7 +19,7 @@ help: <TAG> was later invalidated at offsets [0x0..0x4] by a write access
    |
 LL |     *our = 5;
    |     ^^^^^^^^
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside `unknown_code_2` at $DIR/mut_exclusive_violation1.rs:LL:CC
 note: inside `demo_mut_advanced_unique`
   --> $DIR/mut_exclusive_violation1.rs:LL:CC
diff --git a/src/tools/miri/tests/fail/stacked_borrows/mut_exclusive_violation2.stderr b/src/tools/miri/tests/fail/stacked_borrows/mut_exclusive_violation2.stderr
index 43b5325fc54..30ce698761f 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/mut_exclusive_violation2.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/mut_exclusive_violation2.stderr
@@ -19,7 +19,7 @@ help: <TAG> was later invalidated at offsets [0x0..0x4] by a Unique retag
    |
 LL |         let _raw2 = ptr2.as_mut();
    |                     ^^^^^^^^^^^^^
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside `main` at $DIR/mut_exclusive_violation2.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/stacked_borrows/newtype_pair_retagging.stderr b/src/tools/miri/tests/fail/stacked_borrows/newtype_pair_retagging.stderr
index 90677dfaf55..0cba380ea1a 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/newtype_pair_retagging.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/newtype_pair_retagging.stderr
@@ -16,7 +16,7 @@ help: <TAG> is this argument
    |
 LL | fn dealloc_while_running(_n: Newtype<'_>, dealloc: impl FnOnce()) {
    |                          ^^
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside `std::boxed::Box::<i32>::from_raw_in` at RUSTLIB/alloc/src/boxed.rs:LL:CC
    = note: inside `std::boxed::Box::<i32>::from_raw` at RUSTLIB/alloc/src/boxed.rs:LL:CC
 note: inside closure
diff --git a/src/tools/miri/tests/fail/stacked_borrows/newtype_retagging.stderr b/src/tools/miri/tests/fail/stacked_borrows/newtype_retagging.stderr
index f189d0483d1..f76b6a57eac 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/newtype_retagging.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/newtype_retagging.stderr
@@ -16,7 +16,7 @@ help: <TAG> is this argument
    |
 LL | fn dealloc_while_running(_n: Newtype<'_>, dealloc: impl FnOnce()) {
    |                          ^^
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside `std::boxed::Box::<i32>::from_raw_in` at RUSTLIB/alloc/src/boxed.rs:LL:CC
    = note: inside `std::boxed::Box::<i32>::from_raw` at RUSTLIB/alloc/src/boxed.rs:LL:CC
 note: inside closure
diff --git a/src/tools/miri/tests/fail/stacked_borrows/outdated_local.stderr b/src/tools/miri/tests/fail/stacked_borrows/outdated_local.stderr
index 8c2bba53918..ad366bdabce 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/outdated_local.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/outdated_local.stderr
@@ -19,7 +19,7 @@ help: <TAG> was later invalidated at offsets [0x0..0x4] by a write access
    |
 LL |     x = 1; // this invalidates y by reactivating the lowermost uniq borrow for this local
    |     ^^^^^
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside `main` at $DIR/outdated_local.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/stacked_borrows/pass_invalid_mut.stderr b/src/tools/miri/tests/fail/stacked_borrows/pass_invalid_mut.stderr
index d7ab930aa37..96cec327b9d 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/pass_invalid_mut.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/pass_invalid_mut.stderr
@@ -19,7 +19,7 @@ help: <TAG> was later invalidated at offsets [0x0..0x4] by a read access
    |
 LL |     let _val = unsafe { *xraw }; // invalidate xref
    |                         ^^^^^
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside `main` at $DIR/pass_invalid_mut.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/stacked_borrows/pass_invalid_shr.stderr b/src/tools/miri/tests/fail/stacked_borrows/pass_invalid_shr.stderr
index c14b35c75c8..5243858a91a 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/pass_invalid_shr.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/pass_invalid_shr.stderr
@@ -19,7 +19,7 @@ help: <TAG> was later invalidated at offsets [0x0..0x4] by a write access
    |
 LL |     unsafe { *xraw = 42 }; // unfreeze
    |              ^^^^^^^^^^
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside `main` at $DIR/pass_invalid_shr.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/stacked_borrows/pointer_smuggling.stderr b/src/tools/miri/tests/fail/stacked_borrows/pointer_smuggling.stderr
index 7d58d1aebbe..e20b5b89a2f 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/pointer_smuggling.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/pointer_smuggling.stderr
@@ -19,7 +19,7 @@ help: <TAG> was later invalidated at offsets [0x0..0x1] by a write access
    |
 LL |     *val = 2; // this invalidates any raw ptrs `fun1` might have created.
    |     ^^^^^^^^
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside `fun2` at $DIR/pointer_smuggling.rs:LL:CC
 note: inside `main`
   --> $DIR/pointer_smuggling.rs:LL:CC
diff --git a/src/tools/miri/tests/fail/stacked_borrows/raw_tracking.stderr b/src/tools/miri/tests/fail/stacked_borrows/raw_tracking.stderr
index d75934445e6..9f7e7a058df 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/raw_tracking.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/raw_tracking.stderr
@@ -19,7 +19,7 @@ help: <TAG> was later invalidated at offsets [0x0..0x4] by a Unique retag
    |
 LL |     let raw2 = &mut l as *mut _; // invalidates raw1
    |                ^^^^^^
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside `main` at $DIR/raw_tracking.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/stacked_borrows/retag_data_race_read.rs b/src/tools/miri/tests/fail/stacked_borrows/retag_data_race_read.rs
index 309d7a22be6..a63cd03366f 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/retag_data_race_read.rs
+++ b/src/tools/miri/tests/fail/stacked_borrows/retag_data_race_read.rs
@@ -15,7 +15,7 @@ fn thread_1(p: SendPtr) {
 fn thread_2(p: SendPtr) {
     let p = p.0;
     unsafe {
-        *p = 5; //~ ERROR: Data race detected between Write on thread `<unnamed>` and Read on thread `<unnamed>`
+        *p = 5; //~ ERROR: Data race detected between (1) Read on thread `<unnamed>` and (2) Write on thread `<unnamed>`
     }
 }
 
diff --git a/src/tools/miri/tests/fail/stacked_borrows/retag_data_race_read.stderr b/src/tools/miri/tests/fail/stacked_borrows/retag_data_race_read.stderr
index 5dc936f0707..c53a495b5e1 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/retag_data_race_read.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/retag_data_race_read.stderr
@@ -1,12 +1,17 @@
-error: Undefined Behavior: Data race detected between Write on thread `<unnamed>` and Read on thread `<unnamed>` at ALLOC
+error: Undefined Behavior: Data race detected between (1) Read on thread `<unnamed>` and (2) Write on thread `<unnamed>` at ALLOC. (2) just happened here
   --> $DIR/retag_data_race_read.rs:LL:CC
    |
 LL |         *p = 5;
-   |         ^^^^^^ Data race detected between Write on thread `<unnamed>` and Read on thread `<unnamed>` at ALLOC
+   |         ^^^^^^ Data race detected between (1) Read on thread `<unnamed>` and (2) Write on thread `<unnamed>` at ALLOC. (2) just happened here
    |
+help: and (1) occurred earlier here
+  --> $DIR/retag_data_race_read.rs:LL:CC
+   |
+LL |         let _r = &*p;
+   |                  ^^^
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside `thread_2` at $DIR/retag_data_race_read.rs:LL:CC
 note: inside closure
   --> $DIR/retag_data_race_read.rs:LL:CC
diff --git a/src/tools/miri/tests/fail/stacked_borrows/retag_data_race_write.rs b/src/tools/miri/tests/fail/stacked_borrows/retag_data_race_write.rs
index 9368a0a919e..c1dded40d3c 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/retag_data_race_write.rs
+++ b/src/tools/miri/tests/fail/stacked_borrows/retag_data_race_write.rs
@@ -15,7 +15,7 @@ fn thread_1(p: SendPtr) {
 fn thread_2(p: SendPtr) {
     let p = p.0;
     unsafe {
-        *p = 5; //~ ERROR: Data race detected between Write on thread `<unnamed>` and Write on thread `<unnamed>`
+        *p = 5; //~ ERROR: Data race detected between (1) Write on thread `<unnamed>` and (2) Write on thread `<unnamed>`
     }
 }
 
diff --git a/src/tools/miri/tests/fail/stacked_borrows/retag_data_race_write.stderr b/src/tools/miri/tests/fail/stacked_borrows/retag_data_race_write.stderr
index 03c24503564..da5af600675 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/retag_data_race_write.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/retag_data_race_write.stderr
@@ -1,12 +1,17 @@
-error: Undefined Behavior: Data race detected between Write on thread `<unnamed>` and Write on thread `<unnamed>` at ALLOC
+error: Undefined Behavior: Data race detected between (1) Write on thread `<unnamed>` and (2) Write on thread `<unnamed>` at ALLOC. (2) just happened here
   --> $DIR/retag_data_race_write.rs:LL:CC
    |
 LL |         *p = 5;
-   |         ^^^^^^ Data race detected between Write on thread `<unnamed>` and Write on thread `<unnamed>` at ALLOC
+   |         ^^^^^^ Data race detected between (1) Write on thread `<unnamed>` and (2) Write on thread `<unnamed>` at ALLOC. (2) just happened here
    |
+help: and (1) occurred earlier here
+  --> $DIR/retag_data_race_write.rs:LL:CC
+   |
+LL |         let _r = &mut *p;
+   |                  ^^^^^^^
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside `thread_2` at $DIR/retag_data_race_write.rs:LL:CC
 note: inside closure
   --> $DIR/retag_data_race_write.rs:LL:CC
diff --git a/src/tools/miri/tests/fail/stacked_borrows/return_invalid_mut.stderr b/src/tools/miri/tests/fail/stacked_borrows/return_invalid_mut.stderr
index 1b28f780c1c..2bf91b676c4 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/return_invalid_mut.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/return_invalid_mut.stderr
@@ -19,7 +19,7 @@ help: <TAG> was later invalidated at offsets [0x0..0x8] by a read access
    |
 LL |     let _val = unsafe { *xraw }; // invalidate xref
    |                         ^^^^^
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside `foo` at $DIR/return_invalid_mut.rs:LL:CC
 note: inside `main`
   --> $DIR/return_invalid_mut.rs:LL:CC
diff --git a/src/tools/miri/tests/fail/stacked_borrows/return_invalid_mut_option.stderr b/src/tools/miri/tests/fail/stacked_borrows/return_invalid_mut_option.stderr
index db14dcafa00..ff00c54570c 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/return_invalid_mut_option.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/return_invalid_mut_option.stderr
@@ -19,7 +19,7 @@ help: <TAG> was later invalidated at offsets [0x0..0x8] by a read access
    |
 LL |     let _val = unsafe { *xraw }; // invalidate xref
    |                         ^^^^^
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside `foo` at $DIR/return_invalid_mut_option.rs:LL:CC
 note: inside `main`
   --> $DIR/return_invalid_mut_option.rs:LL:CC
diff --git a/src/tools/miri/tests/fail/stacked_borrows/return_invalid_mut_tuple.stderr b/src/tools/miri/tests/fail/stacked_borrows/return_invalid_mut_tuple.stderr
index 81ed4218aad..61d041a8816 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/return_invalid_mut_tuple.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/return_invalid_mut_tuple.stderr
@@ -19,7 +19,7 @@ help: <TAG> was later invalidated at offsets [0x0..0x8] by a read access
    |
 LL |     let _val = unsafe { *xraw }; // invalidate xref
    |                         ^^^^^
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside `foo` at $DIR/return_invalid_mut_tuple.rs:LL:CC
 note: inside `main`
   --> $DIR/return_invalid_mut_tuple.rs:LL:CC
diff --git a/src/tools/miri/tests/fail/stacked_borrows/return_invalid_shr.stderr b/src/tools/miri/tests/fail/stacked_borrows/return_invalid_shr.stderr
index 9c8cc50b2d7..d3a73a00fa6 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/return_invalid_shr.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/return_invalid_shr.stderr
@@ -19,7 +19,7 @@ help: <TAG> was later invalidated at offsets [0x0..0x8] by a write access
    |
 LL |     unsafe { *xraw = (42, 23) }; // unfreeze
    |              ^^^^^^^^^^^^^^^^
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside `foo` at $DIR/return_invalid_shr.rs:LL:CC
 note: inside `main`
   --> $DIR/return_invalid_shr.rs:LL:CC
diff --git a/src/tools/miri/tests/fail/stacked_borrows/return_invalid_shr_option.stderr b/src/tools/miri/tests/fail/stacked_borrows/return_invalid_shr_option.stderr
index 00ce6f6cd5f..f14e8b8532f 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/return_invalid_shr_option.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/return_invalid_shr_option.stderr
@@ -19,7 +19,7 @@ help: <TAG> was later invalidated at offsets [0x0..0x8] by a write access
    |
 LL |     unsafe { *xraw = (42, 23) }; // unfreeze
    |              ^^^^^^^^^^^^^^^^
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside `foo` at $DIR/return_invalid_shr_option.rs:LL:CC
 note: inside `main`
   --> $DIR/return_invalid_shr_option.rs:LL:CC
diff --git a/src/tools/miri/tests/fail/stacked_borrows/return_invalid_shr_tuple.stderr b/src/tools/miri/tests/fail/stacked_borrows/return_invalid_shr_tuple.stderr
index bbd17b1284c..9ddaad4d1be 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/return_invalid_shr_tuple.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/return_invalid_shr_tuple.stderr
@@ -19,7 +19,7 @@ help: <TAG> was later invalidated at offsets [0x0..0x8] by a write access
    |
 LL |     unsafe { *xraw = (42, 23) }; // unfreeze
    |              ^^^^^^^^^^^^^^^^
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside `foo` at $DIR/return_invalid_shr_tuple.rs:LL:CC
 note: inside `main`
   --> $DIR/return_invalid_shr_tuple.rs:LL:CC
diff --git a/src/tools/miri/tests/fail/stacked_borrows/shared_rw_borrows_are_weak1.stderr b/src/tools/miri/tests/fail/stacked_borrows/shared_rw_borrows_are_weak1.stderr
index 3a139c3ab21..589e1291ba7 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/shared_rw_borrows_are_weak1.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/shared_rw_borrows_are_weak1.stderr
@@ -19,7 +19,7 @@ help: <TAG> was later invalidated at offsets [0x0..0x4] by a Unique retag
    |
 LL |         shr_rw.set(1);
    |         ^^^^^^^^^^^^^
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside `main` at $DIR/shared_rw_borrows_are_weak1.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/stacked_borrows/shared_rw_borrows_are_weak2.stderr b/src/tools/miri/tests/fail/stacked_borrows/shared_rw_borrows_are_weak2.stderr
index 0609a73e793..0e37c4ffb39 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/shared_rw_borrows_are_weak2.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/shared_rw_borrows_are_weak2.stderr
@@ -19,7 +19,7 @@ help: <TAG> was later invalidated at offsets [$HEX..$HEX] by a Unique retag
    |
 LL |         shr_rw.replace(1);
    |         ^^^^^^^^^^^^^^^^^
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside `main` at $DIR/shared_rw_borrows_are_weak2.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/stacked_borrows/shr_frozen_violation1.stderr b/src/tools/miri/tests/fail/stacked_borrows/shr_frozen_violation1.stderr
index fe0ac211318..a69116f2afa 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/shr_frozen_violation1.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/shr_frozen_violation1.stderr
@@ -14,7 +14,7 @@ help: <TAG> was created by a SharedReadOnly retag at offsets [0x0..0x4]
    |
 LL |         *(x as *const i32 as *mut i32) = 7;
    |           ^
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside `unknown_code` at $DIR/shr_frozen_violation1.rs:LL:CC
 note: inside `foo`
   --> $DIR/shr_frozen_violation1.rs:LL:CC
diff --git a/src/tools/miri/tests/fail/stacked_borrows/track_caller.stderr b/src/tools/miri/tests/fail/stacked_borrows/track_caller.stderr
index 6f1d0ccd348..05be0d3f1e9 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/track_caller.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/track_caller.stderr
@@ -19,7 +19,7 @@ help: <TAG> was later invalidated at offsets [0x0..0x4] by a read access
    |
 LL |     callee(xraw);
    |     ^^^^^^^^^^^^
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside `main` at $DIR/track_caller.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/stacked_borrows/transmute-is-no-escape.stderr b/src/tools/miri/tests/fail/stacked_borrows/transmute-is-no-escape.stderr
index a2ecb07fd31..ac962311d42 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/transmute-is-no-escape.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/transmute-is-no-escape.stderr
@@ -14,7 +14,7 @@ help: <TAG> was created by a SharedReadWrite retag at offsets [0x4..0x8]
    |
 LL |     let raw = (&mut x[1] as *mut i32).wrapping_offset(-1);
    |                ^^^^^^^^^
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside `main` at $DIR/transmute-is-no-escape.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/stacked_borrows/unescaped_static.stderr b/src/tools/miri/tests/fail/stacked_borrows/unescaped_static.stderr
index 01a4bf4340c..7a40d1078b3 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/unescaped_static.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/unescaped_static.stderr
@@ -14,7 +14,7 @@ help: <TAG> was created by a SharedReadOnly retag at offsets [0x0..0x1]
    |
 LL |     let ptr_to_first = &ARRAY[0] as *const u8;
    |                        ^^^^^^^^^
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside `main` at $DIR/unescaped_static.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/stacked_borrows/zst_slice.stderr b/src/tools/miri/tests/fail/stacked_borrows/zst_slice.stderr
index e134ee2845d..950abc4cbcf 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/zst_slice.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/zst_slice.stderr
@@ -14,7 +14,7 @@ help: <TAG> would have been created here, but this is a zero-size retag ([0x0..0
    |
 LL |         assert_eq!(*s.get_unchecked(1), 2);
    |                     ^^^^^^^^^^^^^^^^^^
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside `core::slice::<impl [i32]>::get_unchecked::<usize>` at RUSTLIB/core/src/slice/mod.rs:LL:CC
 note: inside `main`
   --> $DIR/zst_slice.rs:LL:CC
diff --git a/src/tools/miri/tests/fail/unaligned_pointers/drop_in_place.rs b/src/tools/miri/tests/fail/unaligned_pointers/drop_in_place.rs
new file mode 100644
index 00000000000..cf3a558bb99
--- /dev/null
+++ b/src/tools/miri/tests/fail/unaligned_pointers/drop_in_place.rs
@@ -0,0 +1,25 @@
+#[repr(transparent)]
+struct HasDrop(u8);
+
+impl Drop for HasDrop {
+    fn drop(&mut self) {}
+}
+
+#[repr(C, align(2))]
+struct PartialDrop {
+    a: HasDrop,
+    b: u8,
+}
+
+//@error-pattern: /alignment 2 is required/
+fn main() {
+    unsafe {
+        // Create an unaligned pointer
+        let mut x = [0_u16; 2];
+        let p = core::ptr::addr_of_mut!(x).cast::<u8>();
+        let p = p.add(1);
+        let p = p.cast::<PartialDrop>();
+
+        core::ptr::drop_in_place(p);
+    }
+}
diff --git a/src/tools/miri/tests/fail/unaligned_pointers/drop_in_place.stderr b/src/tools/miri/tests/fail/unaligned_pointers/drop_in_place.stderr
new file mode 100644
index 00000000000..ef20b43c118
--- /dev/null
+++ b/src/tools/miri/tests/fail/unaligned_pointers/drop_in_place.stderr
@@ -0,0 +1,20 @@
+error: Undefined Behavior: accessing memory with alignment ALIGN, but alignment ALIGN is required
+  --> RUSTLIB/core/src/ptr/mod.rs:LL:CC
+   |
+LL | pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ accessing memory with alignment ALIGN, but alignment ALIGN is required
+   |
+   = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
+   = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
+   = note: BACKTRACE:
+   = note: inside `std::ptr::drop_in_place::<PartialDrop> - shim(Some(PartialDrop))` at RUSTLIB/core/src/ptr/mod.rs:LL:CC
+note: inside `main`
+  --> $DIR/drop_in_place.rs:LL:CC
+   |
+LL |         core::ptr::drop_in_place(p);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
+
+error: aborting due to previous error
+
diff --git a/src/tools/miri/tests/pass-dep/page_size.rs b/src/tools/miri/tests/pass-dep/page_size.rs
index cdcabf33338..fb060317538 100644
--- a/src/tools/miri/tests/pass-dep/page_size.rs
+++ b/src/tools/miri/tests/pass-dep/page_size.rs
@@ -3,4 +3,17 @@ fn main() {
 
     // In particular, this checks that it is not 0.
     assert!(page_size.is_power_of_two(), "page size not a power of two: {}", page_size);
+    // Most architectures have 4k pages by default
+    #[cfg(not(any(
+        target_arch = "wasm32",
+        target_arch = "wasm64",
+        all(target_arch = "aarch64", target_vendor = "apple")
+    )))]
+    assert!(page_size == 4 * 1024, "non-4k default page size: {}", page_size);
+    // ... except aarch64-apple with 16k
+    #[cfg(all(target_arch = "aarch64", target_vendor = "apple"))]
+    assert!(page_size == 16 * 1024, "aarch64 apple reports non-16k page size: {}", page_size);
+    // ... and wasm with 64k
+    #[cfg(any(target_arch = "wasm32", target_arch = "wasm64"))]
+    assert!(page_size == 64 * 1024, "wasm reports non-64k page size: {}", page_size);
 }
diff --git a/src/tools/miri/tests/pass-dep/page_size_override.rs b/src/tools/miri/tests/pass-dep/page_size_override.rs
new file mode 100644
index 00000000000..68858f38759
--- /dev/null
+++ b/src/tools/miri/tests/pass-dep/page_size_override.rs
@@ -0,0 +1,7 @@
+//@compile-flags: -Zmiri-force-page-size=8
+
+fn main() {
+    let page_size = page_size::get();
+
+    assert!(page_size == 8 * 1024, "8k page size override not respected: {}", page_size);
+}
diff --git a/src/tools/miri/tests/pass-dep/shims/libc-fs.rs b/src/tools/miri/tests/pass-dep/shims/libc-fs.rs
index acf16ecb7e0..ba5b269f652 100644
--- a/src/tools/miri/tests/pass-dep/shims/libc-fs.rs
+++ b/src/tools/miri/tests/pass-dep/shims/libc-fs.rs
@@ -5,8 +5,8 @@
 #![feature(io_error_uncategorized)]
 
 use std::convert::TryInto;
-use std::ffi::CString;
-use std::fs::{canonicalize, remove_file, File};
+use std::ffi::{CStr, CString};
+use std::fs::{canonicalize, remove_dir_all, remove_file, File};
 use std::io::{Error, ErrorKind, Write};
 use std::os::unix::ffi::OsStrExt;
 use std::path::PathBuf;
@@ -18,23 +18,26 @@ fn main() {
     test_file_open_unix_allow_two_args();
     test_file_open_unix_needs_three_args();
     test_file_open_unix_extra_third_arg();
+    #[cfg(target_os = "linux")]
+    test_o_tmpfile_flag();
 }
 
 fn tmp() -> PathBuf {
-    std::env::var("MIRI_TEMP")
-        .map(|tmp| {
-            // MIRI_TEMP is set outside of our emulated
-            // program, so it may have path separators that don't
-            // correspond to our target platform. We normalize them here
-            // before constructing a `PathBuf`
-
-            #[cfg(windows)]
-            return PathBuf::from(tmp.replace("/", "\\"));
-
-            #[cfg(not(windows))]
-            return PathBuf::from(tmp.replace("\\", "/"));
-        })
-        .unwrap_or_else(|_| std::env::temp_dir())
+    let path = std::env::var("MIRI_TEMP")
+        .unwrap_or_else(|_| std::env::temp_dir().into_os_string().into_string().unwrap());
+    // These are host paths. We need to convert them to the target.
+    let path = CString::new(path).unwrap();
+    let mut out = Vec::with_capacity(1024);
+
+    unsafe {
+        extern "Rust" {
+            fn miri_host_to_target_path(path: *const i8, out: *mut i8, out_size: usize) -> usize;
+        }
+        let ret = miri_host_to_target_path(path.as_ptr(), out.as_mut_ptr(), out.capacity());
+        assert_eq!(ret, 0);
+        let out = CStr::from_ptr(out.as_ptr()).to_str().unwrap();
+        PathBuf::from(out)
+    }
 }
 
 /// Prepare: compute filename and make sure the file does not exist.
@@ -45,6 +48,15 @@ fn prepare(filename: &str) -> PathBuf {
     path
 }
 
+/// Prepare directory: compute directory name and make sure it does not exist.
+#[allow(unused)]
+fn prepare_dir(dirname: &str) -> PathBuf {
+    let path = tmp().join(&dirname);
+    // Clean the directory for robustness.
+    remove_dir_all(&path).ok();
+    path
+}
+
 /// Prepare like above, and also write some initial content to the file.
 fn prepare_with_content(filename: &str, content: &[u8]) -> PathBuf {
     let path = prepare(filename);
@@ -135,3 +147,22 @@ fn test_readlink() {
     assert_eq!(res, -1);
     assert_eq!(Error::last_os_error().kind(), ErrorKind::NotFound);
 }
+
+#[cfg(target_os = "linux")]
+fn test_o_tmpfile_flag() {
+    use std::fs::{create_dir, OpenOptions};
+    use std::os::unix::fs::OpenOptionsExt;
+    let dir_path = prepare_dir("miri_test_fs_dir");
+    create_dir(&dir_path).unwrap();
+    // test that the `O_TMPFILE` custom flag gracefully errors instead of stopping execution
+    assert_eq!(
+        Some(libc::EOPNOTSUPP),
+        OpenOptions::new()
+            .read(true)
+            .write(true)
+            .custom_flags(libc::O_TMPFILE)
+            .open(dir_path)
+            .unwrap_err()
+            .raw_os_error(),
+    );
+}
diff --git a/src/tools/miri/tests/pass-dep/shims/libc-misc.rs b/src/tools/miri/tests/pass-dep/shims/libc-misc.rs
index 2a4300fcd04..20e96a92c7c 100644
--- a/src/tools/miri/tests/pass-dep/shims/libc-misc.rs
+++ b/src/tools/miri/tests/pass-dep/shims/libc-misc.rs
@@ -7,15 +7,23 @@ use std::os::unix::io::AsRawFd;
 use std::path::PathBuf;
 
 fn tmp() -> PathBuf {
-    std::env::var("MIRI_TEMP")
-        .map(|tmp| {
-            // MIRI_TEMP is set outside of our emulated
-            // program, so it may have path separators that don't
-            // correspond to our target platform. We normalize them here
-            // before constructing a `PathBuf`
-            return PathBuf::from(tmp.replace("\\", "/"));
-        })
-        .unwrap_or_else(|_| std::env::temp_dir())
+    use std::ffi::{CStr, CString};
+
+    let path = std::env::var("MIRI_TEMP")
+        .unwrap_or_else(|_| std::env::temp_dir().into_os_string().into_string().unwrap());
+    // These are host paths. We need to convert them to the target.
+    let path = CString::new(path).unwrap();
+    let mut out = Vec::with_capacity(1024);
+
+    unsafe {
+        extern "Rust" {
+            fn miri_host_to_target_path(path: *const i8, out: *mut i8, out_size: usize) -> usize;
+        }
+        let ret = miri_host_to_target_path(path.as_ptr(), out.as_mut_ptr(), out.capacity());
+        assert_eq!(ret, 0);
+        let out = CStr::from_ptr(out.as_ptr()).to_str().unwrap();
+        PathBuf::from(out)
+    }
 }
 
 /// Test allocating variant of `realpath`.
diff --git a/src/tools/miri/tests/pass-dep/tokio_mvp.rs b/src/tools/miri/tests/pass-dep/tokio_mvp.rs
new file mode 100644
index 00000000000..642168253c2
--- /dev/null
+++ b/src/tools/miri/tests/pass-dep/tokio_mvp.rs
@@ -0,0 +1,6 @@
+// Need to disable preemption to stay on the supported MVP codepath in mio.
+//@compile-flags: -Zmiri-disable-isolation -Zmiri-permissive-provenance -Zmiri-preemption-rate=0
+//@only-target-x86_64-unknown-linux: support for tokio exists only on linux and x86
+
+#[tokio::main]
+async fn main() {}
diff --git a/src/tools/miri/tests/pass/provenance.rs b/src/tools/miri/tests/pass/provenance.rs
index b18d903e36c..c411f748a06 100644
--- a/src/tools/miri/tests/pass/provenance.rs
+++ b/src/tools/miri/tests/pass/provenance.rs
@@ -10,6 +10,7 @@ fn main() {
     bytewise_ptr_methods();
     bytewise_custom_memcpy();
     bytewise_custom_memcpy_chunked();
+    int_load_strip_provenance();
 }
 
 /// Some basic smoke tests for provenance.
@@ -137,3 +138,9 @@ fn bytewise_custom_memcpy_chunked() {
         assert_eq!(*ptr, 42);
     }
 }
+
+fn int_load_strip_provenance() {
+    let ptrs = [&42];
+    let ints: [usize; 1] = unsafe { mem::transmute(ptrs) };
+    assert_eq!(ptrs[0] as *const _ as usize, ints[0]);
+}
diff --git a/src/tools/miri/tests/pass/shims/env/current_dir.rs b/src/tools/miri/tests/pass/shims/env/current_dir.rs
index 069b462ab37..ca90912eabc 100644
--- a/src/tools/miri/tests/pass/shims/env/current_dir.rs
+++ b/src/tools/miri/tests/pass/shims/env/current_dir.rs
@@ -3,8 +3,9 @@ use std::env;
 use std::io::ErrorKind;
 
 fn main() {
-    // Test that `getcwd` is available
+    // Test that `getcwd` is available and an absolute path
     let cwd = env::current_dir().unwrap();
+    assert!(cwd.is_absolute(), "cwd {:?} is not absolute", cwd);
     // Test that changing dir to `..` actually sets the current directory to the parent of `cwd`.
     // The only exception here is if `cwd` is the root directory, then changing directory must
     // keep the current directory equal to `cwd`.
diff --git a/src/tools/miri/tests/pass/shims/fs.rs b/src/tools/miri/tests/pass/shims/fs.rs
index 65cf6fe66ba..a7d4800faec 100644
--- a/src/tools/miri/tests/pass/shims/fs.rs
+++ b/src/tools/miri/tests/pass/shims/fs.rs
@@ -15,6 +15,7 @@ use std::io::{Error, ErrorKind, IsTerminal, Read, Result, Seek, SeekFrom, Write}
 use std::path::{Path, PathBuf};
 
 fn main() {
+    test_path_conversion();
     test_file();
     test_file_clone();
     test_file_create_new();
@@ -30,21 +31,28 @@ fn main() {
     test_from_raw_os_error();
 }
 
+fn host_to_target_path(path: String) -> PathBuf {
+    use std::ffi::{CStr, CString};
+
+    let path = CString::new(path).unwrap();
+    let mut out = Vec::with_capacity(1024);
+
+    unsafe {
+        extern "Rust" {
+            fn miri_host_to_target_path(path: *const i8, out: *mut i8, out_size: usize) -> usize;
+        }
+        let ret = miri_host_to_target_path(path.as_ptr(), out.as_mut_ptr(), out.capacity());
+        assert_eq!(ret, 0);
+        let out = CStr::from_ptr(out.as_ptr()).to_str().unwrap();
+        PathBuf::from(out)
+    }
+}
+
 fn tmp() -> PathBuf {
-    std::env::var("MIRI_TEMP")
-        .map(|tmp| {
-            // MIRI_TEMP is set outside of our emulated
-            // program, so it may have path separators that don't
-            // correspond to our target platform. We normalize them here
-            // before constructing a `PathBuf`
-
-            #[cfg(windows)]
-            return PathBuf::from(tmp.replace("/", "\\"));
-
-            #[cfg(not(windows))]
-            return PathBuf::from(tmp.replace("\\", "/"));
-        })
-        .unwrap_or_else(|_| std::env::temp_dir())
+    let path = std::env::var("MIRI_TEMP")
+        .unwrap_or_else(|_| std::env::temp_dir().into_os_string().into_string().unwrap());
+    // These are host paths. We need to convert them to the target.
+    host_to_target_path(path)
 }
 
 /// Prepare: compute filename and make sure the file does not exist.
@@ -71,6 +79,12 @@ fn prepare_with_content(filename: &str, content: &[u8]) -> PathBuf {
     path
 }
 
+fn test_path_conversion() {
+    let tmp = tmp();
+    assert!(tmp.is_absolute(), "{:?} is not absolute", tmp);
+    assert!(tmp.is_dir(), "{:?} is not a directory", tmp);
+}
+
 fn test_file() {
     let bytes = b"Hello, World!\n";
     let path = prepare("miri_test_fs_file.txt");
diff --git a/src/tools/miri/tests/pass/vec.rs b/src/tools/miri/tests/pass/vec.rs
index 26732cec5eb..3a6655e2ba6 100644
--- a/src/tools/miri/tests/pass/vec.rs
+++ b/src/tools/miri/tests/pass/vec.rs
@@ -1,4 +1,6 @@
 //@compile-flags: -Zmiri-strict-provenance
+#![feature(iter_advance_by, iter_next_chunk)]
+
 // Gather all references from a mutable iterator and make sure Miri notices if
 // using them is dangerous.
 fn test_all_refs<'a, T: 'a>(dummy: &mut T, iter: impl Iterator<Item = &'a mut T>) {
@@ -37,15 +39,31 @@ fn vec_into_iter() -> u8 {
 }
 
 fn vec_into_iter_rev() -> u8 {
-    vec![1, 2, 3, 4].into_iter().map(|x| x * x).fold(0, |x, y| x + y)
+    vec![1, 2, 3, 4].into_iter().rev().map(|x| x * x).fold(0, |x, y| x + y)
 }
 
-fn vec_into_iter_zst() -> usize {
-    vec![[0u64; 0], [0u64; 0]].into_iter().rev().map(|x| x.len()).sum()
+fn vec_into_iter_zst() {
+    for _ in vec![[0u64; 0]].into_iter() {}
+    let v = vec![[0u64; 0], [0u64; 0]].into_iter().map(|x| x.len()).sum::<usize>();
+    assert_eq!(v, 0);
+
+    let mut it = vec![[0u64; 0], [0u64; 0]].into_iter();
+    it.advance_by(1).unwrap();
+    drop(it);
+
+    let mut it = vec![[0u64; 0], [0u64; 0]].into_iter();
+    it.next_chunk::<1>().unwrap();
+    drop(it);
+
+    let mut it = vec![[0u64; 0], [0u64; 0]].into_iter();
+    it.next_chunk::<4>().unwrap_err();
+    drop(it);
 }
 
-fn vec_into_iter_rev_zst() -> usize {
-    vec![[0u64; 0], [0u64; 0]].into_iter().rev().map(|x| x.len()).sum()
+fn vec_into_iter_rev_zst() {
+    for _ in vec![[0u64; 0]; 5].into_iter().rev() {}
+    let v = vec![[0u64; 0], [0u64; 0]].into_iter().rev().map(|x| x.len()).sum::<usize>();
+    assert_eq!(v, 0);
 }
 
 fn vec_iter_and_mut() {
@@ -150,8 +168,8 @@ fn main() {
     assert_eq!(vec_into_iter(), 30);
     assert_eq!(vec_into_iter_rev(), 30);
     vec_iter_and_mut();
-    assert_eq!(vec_into_iter_zst(), 0);
-    assert_eq!(vec_into_iter_rev_zst(), 0);
+    vec_into_iter_zst();
+    vec_into_iter_rev_zst();
     vec_iter_and_mut_rev();
 
     assert_eq!(make_vec().capacity(), 4);
diff --git a/src/tools/remote-test-server/src/main.rs b/src/tools/remote-test-server/src/main.rs
index c1450aedc31..3d61a067559 100644
--- a/src/tools/remote-test-server/src/main.rs
+++ b/src/tools/remote-test-server/src/main.rs
@@ -365,13 +365,7 @@ fn my_copy(src: &mut dyn Read, which: u8, dst: &Mutex<dyn Write>) {
     loop {
         let n = t!(src.read(&mut b));
         let mut dst = dst.lock().unwrap();
-        t!(dst.write_all(&[
-            which,
-            (n >> 24) as u8,
-            (n >> 16) as u8,
-            (n >> 8) as u8,
-            (n >> 0) as u8,
-        ]));
+        t!(dst.write_all(&create_header(which, n as u32)));
         if n > 0 {
             t!(dst.write_all(&b[..n]));
         } else {
@@ -383,7 +377,7 @@ fn my_copy(src: &mut dyn Read, which: u8, dst: &Mutex<dyn Write>) {
 fn batch_copy(buf: &[u8], which: u8, dst: &Mutex<dyn Write>) {
     let n = buf.len();
     let mut dst = dst.lock().unwrap();
-    t!(dst.write_all(&[which, (n >> 24) as u8, (n >> 16) as u8, (n >> 8) as u8, (n >> 0) as u8,]));
+    t!(dst.write_all(&create_header(which, n as u32)));
     if n > 0 {
         t!(dst.write_all(buf));
         // Marking buf finished
@@ -391,11 +385,13 @@ fn batch_copy(buf: &[u8], which: u8, dst: &Mutex<dyn Write>) {
     }
 }
 
+const fn create_header(which: u8, n: u32) -> [u8; 5] {
+    let bytes = n.to_be_bytes();
+    [which, bytes[0], bytes[1], bytes[2], bytes[3]]
+}
+
 fn read_u32(r: &mut dyn Read) -> u32 {
     let mut len = [0; 4];
     t!(r.read_exact(&mut len));
-    ((len[0] as u32) << 24)
-        | ((len[1] as u32) << 16)
-        | ((len[2] as u32) << 8)
-        | ((len[3] as u32) << 0)
+    u32::from_be_bytes(len)
 }
diff --git a/src/tools/tidy/src/error_codes_check.rs b/src/tools/tidy/src/error_codes_check.rs
index 1b119e4113e..49fc2ceb3a2 100644
--- a/src/tools/tidy/src/error_codes_check.rs
+++ b/src/tools/tidy/src/error_codes_check.rs
@@ -11,8 +11,8 @@ use regex::Regex;
 
 // A few of those error codes can't be tested but all the others can and *should* be tested!
 const EXEMPTED_FROM_TEST: &[&str] = &[
-    "E0313", "E0461", "E0462", "E0465", "E0476", "E0490", "E0514", "E0519", "E0523", "E0554",
-    "E0640", "E0717", "E0729", "E0789",
+    "E0313", "E0461", "E0465", "E0476", "E0490", "E0514", "E0519", "E0523", "E0554", "E0640",
+    "E0717", "E0729", "E0789",
 ];
 
 // Some error codes don't have any tests apparently...
diff --git a/src/tools/tidy/src/ui_tests.rs b/src/tools/tidy/src/ui_tests.rs
index 19e2528bb24..f746bdeffd7 100644
--- a/src/tools/tidy/src/ui_tests.rs
+++ b/src/tools/tidy/src/ui_tests.rs
@@ -10,7 +10,7 @@ use std::path::Path;
 const ENTRY_LIMIT: usize = 1000;
 // FIXME: The following limits should be reduced eventually.
 const ROOT_ENTRY_LIMIT: usize = 939;
-const ISSUES_ENTRY_LIMIT: usize = 2040;
+const ISSUES_ENTRY_LIMIT: usize = 2020;
 
 fn check_entries(path: &Path, bad: &mut bool) {
     for dir in Walk::new(&path.join("test/ui")) {
diff --git a/triagebot.toml b/triagebot.toml
index 46a3bab42a1..22f09396efc 100644
--- a/triagebot.toml
+++ b/triagebot.toml
@@ -342,6 +342,10 @@ cc = ["@BoxyUwU"]
 message = "Some changes occured in `rustc_ty_utils::consts.rs`"
 cc = ["@BoxyUwU"]
 
+[mentions."compiler/rustc_trait_selection/src/solve/"]
+message = "Some changes occurred to the core trait solver"
+cc = ["@lcnr"]
+
 [mentions."compiler/rustc_trait_selection/src/traits/engine.rs"]
 message = """
 Some changes occurred in engine.rs, potentially modifying the public API \