about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock114
-rw-r--r--RELEASES.md2
-rw-r--r--compiler/rustc_abi/src/layout.rs4
-rw-r--r--compiler/rustc_ast/src/tokenstream.rs17
-rw-r--r--compiler/rustc_ast_lowering/src/item.rs10
-rw-r--r--compiler/rustc_ast_lowering/src/lib.rs39
-rw-r--r--compiler/rustc_attr/src/builtin.rs3
-rw-r--r--compiler/rustc_borrowck/src/dataflow.rs2
-rw-r--r--compiler/rustc_borrowck/src/lib.rs2
-rw-r--r--compiler/rustc_borrowck/src/nll.rs4
-rw-r--r--compiler/rustc_borrowck/src/region_infer/opaque_types.rs4
-rw-r--r--compiler/rustc_borrowck/src/type_check/mod.rs4
-rw-r--r--compiler/rustc_builtin_macros/src/asm.rs6
-rw-r--r--compiler/rustc_builtin_macros/src/cfg_eval.rs4
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/bounds.rs23
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/clone.rs8
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/generic/mod.rs2
-rw-r--r--compiler/rustc_builtin_macros/src/env.rs12
-rw-r--r--compiler/rustc_builtin_macros/src/format.rs2
-rw-r--r--compiler/rustc_builtin_macros/src/format_foreign.rs4
-rw-r--r--compiler/rustc_builtin_macros/src/lib.rs1
-rw-r--r--compiler/rustc_builtin_macros/src/source_util.rs6
-rw-r--r--compiler/rustc_codegen_cranelift/src/base.rs6
-rw-r--r--compiler/rustc_codegen_cranelift/src/pretty_clif.rs2
-rw-r--r--compiler/rustc_codegen_gcc/src/lib.rs2
-rw-r--r--compiler/rustc_codegen_llvm/Cargo.toml2
-rw-r--r--compiler/rustc_codegen_llvm/src/back/lto.rs49
-rw-r--r--compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs3
-rw-r--r--compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs3
-rw-r--r--compiler/rustc_codegen_llvm/src/lib.rs2
-rw-r--r--compiler/rustc_codegen_llvm/src/llvm/ffi.rs6
-rw-r--r--compiler/rustc_codegen_llvm/src/llvm_util.rs6
-rw-r--r--compiler/rustc_codegen_ssa/Cargo.toml4
-rw-r--r--compiler/rustc_codegen_ssa/src/back/link.rs4
-rw-r--r--compiler/rustc_codegen_ssa/src/back/metadata.rs9
-rw-r--r--compiler/rustc_codegen_ssa/src/back/symbol_export.rs2
-rw-r--r--compiler/rustc_codegen_ssa/src/base.rs21
-rw-r--r--compiler/rustc_codegen_ssa/src/codegen_attrs.rs2
-rw-r--r--compiler/rustc_codegen_ssa/src/lib.rs20
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/debuginfo.rs150
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/operand.rs26
-rw-r--r--compiler/rustc_codegen_ssa/src/target_features.rs6
-rw-r--r--compiler/rustc_codegen_ssa/src/traits/backend.rs13
-rw-r--r--compiler/rustc_const_eval/src/const_eval/error.rs7
-rw-r--r--compiler/rustc_const_eval/src/const_eval/fn_queries.rs2
-rw-r--r--compiler/rustc_const_eval/src/const_eval/machine.rs2
-rw-r--r--compiler/rustc_const_eval/src/interpret/eval_context.rs13
-rw-r--r--compiler/rustc_const_eval/src/interpret/operand.rs2
-rw-r--r--compiler/rustc_const_eval/src/lib.rs2
-rw-r--r--compiler/rustc_const_eval/src/transform/validate.rs12
-rw-r--r--compiler/rustc_data_structures/Cargo.toml1
-rw-r--r--compiler/rustc_data_structures/src/graph/dominators/mod.rs38
-rw-r--r--compiler/rustc_data_structures/src/graph/dominators/tests.rs41
-rw-r--r--compiler/rustc_data_structures/src/lib.rs2
-rw-r--r--compiler/rustc_data_structures/src/marker.rs257
-rw-r--r--compiler/rustc_data_structures/src/owned_slice.rs43
-rw-r--r--compiler/rustc_data_structures/src/owned_slice/tests.rs16
-rw-r--r--compiler/rustc_data_structures/src/sync.rs242
-rw-r--r--compiler/rustc_data_structures/src/sync/worker_local.rs7
-rw-r--r--compiler/rustc_driver_impl/src/args.rs2
-rw-r--r--compiler/rustc_driver_impl/src/lib.rs22
-rw-r--r--compiler/rustc_error_messages/src/lib.rs13
-rw-r--r--compiler/rustc_errors/src/emitter.rs35
-rw-r--r--compiler/rustc_errors/src/lib.rs20
-rw-r--r--compiler/rustc_errors/src/tests.rs10
-rw-r--r--compiler/rustc_expand/src/base.rs23
-rw-r--r--compiler/rustc_expand/src/expand.rs8
-rw-r--r--compiler/rustc_expand/src/mbe/diagnostics.rs4
-rw-r--r--compiler/rustc_expand/src/mbe/macro_check.rs13
-rw-r--r--compiler/rustc_expand/src/mbe/transcribe.rs2
-rw-r--r--compiler/rustc_feature/src/active.rs4
-rw-r--r--compiler/rustc_feature/src/builtin_attrs.rs1
-rw-r--r--compiler/rustc_hir/src/errors.rs10
-rw-r--r--compiler/rustc_hir/src/hir.rs5
-rw-r--r--compiler/rustc_hir/src/lang_items.rs8
-rw-r--r--compiler/rustc_hir/src/lib.rs1
-rw-r--r--compiler/rustc_hir/src/tests.rs6
-rw-r--r--compiler/rustc_hir_analysis/src/astconv/generics.rs4
-rw-r--r--compiler/rustc_hir_analysis/src/astconv/mod.rs15
-rw-r--r--compiler/rustc_hir_analysis/src/autoderef.rs76
-rw-r--r--compiler/rustc_hir_analysis/src/check/check.rs8
-rw-r--r--compiler/rustc_hir_analysis/src/check/dropck.rs4
-rw-r--r--compiler/rustc_hir_analysis/src/check/mod.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/check/wfcheck.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/coherence/builtin.rs4
-rw-r--r--compiler/rustc_hir_analysis/src/coherence/mod.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/coherence/orphan.rs4
-rw-r--r--compiler/rustc_hir_analysis/src/collect.rs9
-rw-r--r--compiler/rustc_hir_analysis/src/collect/generics_of.rs5
-rw-r--r--compiler/rustc_hir_analysis/src/collect/predicates_of.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs10
-rw-r--r--compiler/rustc_hir_analysis/src/collect/type_of.rs19
-rw-r--r--compiler/rustc_hir_analysis/src/hir_wf_check.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/impl_wf_check.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/lib.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/outlives/mod.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/variance/mod.rs2
-rw-r--r--compiler/rustc_hir_typeck/messages.ftl11
-rw-r--r--compiler/rustc_hir_typeck/src/errors.rs24
-rw-r--r--compiler/rustc_hir_typeck/src/expr.rs5
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs55
-rw-r--r--compiler/rustc_hir_typeck/src/lib.rs9
-rw-r--r--compiler/rustc_hir_typeck/src/method/confirm.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/method/mod.rs7
-rw-r--r--compiler/rustc_hir_typeck/src/method/probe.rs3
-rw-r--r--compiler/rustc_hir_typeck/src/method/suggest.rs166
-rw-r--r--compiler/rustc_hir_typeck/src/writeback.rs48
-rw-r--r--compiler/rustc_incremental/src/persist/file_format.rs35
-rw-r--r--compiler/rustc_incremental/src/persist/load.rs32
-rw-r--r--compiler/rustc_incremental/src/persist/save.rs2
-rw-r--r--compiler/rustc_infer/src/infer/canonical/query_response.rs28
-rw-r--r--compiler/rustc_infer/src/infer/combine.rs590
-rw-r--r--compiler/rustc_infer/src/infer/equate.rs6
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/mod.rs2
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs10
-rw-r--r--compiler/rustc_infer/src/infer/generalize.rs479
-rw-r--r--compiler/rustc_infer/src/infer/mod.rs3
-rw-r--r--compiler/rustc_infer/src/infer/nll_relate/mod.rs276
-rw-r--r--compiler/rustc_infer/src/infer/opaque_types.rs23
-rw-r--r--compiler/rustc_infer/src/infer/outlives/test_type_match.rs4
-rw-r--r--compiler/rustc_infer/src/infer/sub.rs6
-rw-r--r--compiler/rustc_interface/src/interface.rs21
-rw-r--r--compiler/rustc_interface/src/passes.rs18
-rw-r--r--compiler/rustc_interface/src/proc_macro_decls.rs2
-rw-r--r--compiler/rustc_interface/src/queries.rs2
-rw-r--r--compiler/rustc_interface/src/tests.rs3
-rw-r--r--compiler/rustc_interface/src/util.rs15
-rw-r--r--compiler/rustc_lexer/src/lib.rs28
-rw-r--r--compiler/rustc_lint/messages.ftl16
-rw-r--r--compiler/rustc_lint/src/builtin.rs12
-rw-r--r--compiler/rustc_lint/src/context.rs16
-rw-r--r--compiler/rustc_lint/src/drop_forget_useless.rs164
-rw-r--r--compiler/rustc_lint/src/expect.rs2
-rw-r--r--compiler/rustc_lint/src/late.rs4
-rw-r--r--compiler/rustc_lint/src/levels.rs2
-rw-r--r--compiler/rustc_lint/src/lib.rs5
-rw-r--r--compiler/rustc_lint/src/lints.rs37
-rw-r--r--compiler/rustc_lint/src/unused.rs4
-rw-r--r--compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp60
-rw-r--r--compiler/rustc_macros/src/query.rs6
-rw-r--r--compiler/rustc_metadata/src/creader.rs2
-rw-r--r--compiler/rustc_metadata/src/locator.rs11
-rw-r--r--compiler/rustc_metadata/src/rmeta/decoder.rs109
-rw-r--r--compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs7
-rw-r--r--compiler/rustc_metadata/src/rmeta/def_path_hash_map.rs3
-rw-r--r--compiler/rustc_metadata/src/rmeta/encoder.rs41
-rw-r--r--compiler/rustc_metadata/src/rmeta/mod.rs12
-rw-r--r--compiler/rustc_middle/Cargo.toml1
-rw-r--r--compiler/rustc_middle/messages.ftl2
-rw-r--r--compiler/rustc_middle/src/error.rs10
-rw-r--r--compiler/rustc_middle/src/hir/map/mod.rs27
-rw-r--r--compiler/rustc_middle/src/hir/mod.rs19
-rw-r--r--compiler/rustc_middle/src/infer/canonical.rs2
-rw-r--r--compiler/rustc_middle/src/lib.rs10
-rw-r--r--compiler/rustc_middle/src/middle/debugger_visualizer.rs38
-rw-r--r--compiler/rustc_middle/src/middle/lang_items.rs8
-rw-r--r--compiler/rustc_middle/src/middle/limits.rs4
-rw-r--r--compiler/rustc_middle/src/middle/mod.rs3
-rw-r--r--compiler/rustc_middle/src/middle/privacy.rs45
-rw-r--r--compiler/rustc_middle/src/mir/interpret/error.rs49
-rw-r--r--compiler/rustc_middle/src/mir/interpret/mod.rs4
-rw-r--r--compiler/rustc_middle/src/mir/interpret/queries.rs7
-rw-r--r--compiler/rustc_middle/src/mir/mod.rs53
-rw-r--r--compiler/rustc_middle/src/mir/pretty.rs9
-rw-r--r--compiler/rustc_middle/src/mir/syntax.rs23
-rw-r--r--compiler/rustc_middle/src/mir/visit.rs4
-rw-r--r--compiler/rustc_middle/src/query/erase.rs6
-rw-r--r--compiler/rustc_middle/src/query/mod.rs114
-rw-r--r--compiler/rustc_middle/src/query/plumbing.rs (renamed from compiler/rustc_middle/src/ty/query.rs)321
-rw-r--r--compiler/rustc_middle/src/traits/mod.rs26
-rw-r--r--compiler/rustc_middle/src/traits/solve.rs2
-rw-r--r--compiler/rustc_middle/src/ty/_match.rs4
-rw-r--r--compiler/rustc_middle/src/ty/abstract_const.rs2
-rw-r--r--compiler/rustc_middle/src/ty/adt.rs24
-rw-r--r--compiler/rustc_middle/src/ty/closure.rs5
-rw-r--r--compiler/rustc_middle/src/ty/consts.rs16
-rw-r--r--compiler/rustc_middle/src/ty/consts/kind.rs8
-rw-r--r--compiler/rustc_middle/src/ty/context.rs38
-rw-r--r--compiler/rustc_middle/src/ty/context/tls.rs8
-rw-r--r--compiler/rustc_middle/src/ty/erase_regions.rs5
-rw-r--r--compiler/rustc_middle/src/ty/generics.rs2
-rw-r--r--compiler/rustc_middle/src/ty/inhabitedness/mod.rs6
-rw-r--r--compiler/rustc_middle/src/ty/layout.rs11
-rw-r--r--compiler/rustc_middle/src/ty/list.rs6
-rw-r--r--compiler/rustc_middle/src/ty/mod.rs63
-rw-r--r--compiler/rustc_middle/src/ty/normalize_erasing_regions.rs2
-rw-r--r--compiler/rustc_middle/src/ty/opaque_types.rs12
-rw-r--r--compiler/rustc_middle/src/ty/parameterized.rs2
-rw-r--r--compiler/rustc_middle/src/ty/print/pretty.rs67
-rw-r--r--compiler/rustc_middle/src/ty/relate.rs31
-rw-r--r--compiler/rustc_middle/src/ty/structural_impls.rs39
-rw-r--r--compiler/rustc_middle/src/ty/sty.rs6
-rw-r--r--compiler/rustc_middle/src/ty/util.rs41
-rw-r--r--compiler/rustc_middle/src/util/bug.rs4
-rw-r--r--compiler/rustc_mir_build/src/build/custom/parse/instruction.rs1
-rw-r--r--compiler/rustc_mir_build/src/build/expr/as_constant.rs2
-rw-r--r--compiler/rustc_mir_build/src/build/matches/mod.rs2
-rw-r--r--compiler/rustc_mir_build/src/build/matches/test.rs49
-rw-r--r--compiler/rustc_mir_build/src/build/mod.rs2
-rw-r--r--compiler/rustc_mir_build/src/build/scope.rs27
-rw-r--r--compiler/rustc_mir_build/src/lib.rs2
-rw-r--r--compiler/rustc_mir_build/src/thir/cx/expr.rs1
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs65
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs8
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/usefulness.rs16
-rw-r--r--compiler/rustc_mir_dataflow/src/elaborate_drops.rs1
-rw-r--r--compiler/rustc_mir_transform/src/check_unsafety.rs2
-rw-r--r--compiler/rustc_mir_transform/src/copy_prop.rs30
-rw-r--r--compiler/rustc_mir_transform/src/coverage/debug.rs27
-rw-r--r--compiler/rustc_mir_transform/src/coverage/query.rs2
-rw-r--r--compiler/rustc_mir_transform/src/coverage/spans.rs3
-rw-r--r--compiler/rustc_mir_transform/src/coverage/tests.rs11
-rw-r--r--compiler/rustc_mir_transform/src/deduce_param_attrs.rs34
-rw-r--r--compiler/rustc_mir_transform/src/dump_mir.rs2
-rw-r--r--compiler/rustc_mir_transform/src/ffi_unwind_calls.rs2
-rw-r--r--compiler/rustc_mir_transform/src/generator.rs5
-rw-r--r--compiler/rustc_mir_transform/src/inline.rs42
-rw-r--r--compiler/rustc_mir_transform/src/instsimplify.rs13
-rw-r--r--compiler/rustc_mir_transform/src/lib.rs2
-rw-r--r--compiler/rustc_mir_transform/src/pass_manager.rs8
-rw-r--r--compiler/rustc_mir_transform/src/ref_prop.rs27
-rw-r--r--compiler/rustc_mir_transform/src/shim.rs2
-rw-r--r--compiler/rustc_mir_transform/src/simplify.rs2
-rw-r--r--compiler/rustc_mir_transform/src/ssa.rs62
-rw-r--r--compiler/rustc_monomorphize/src/collector.rs2
-rw-r--r--compiler/rustc_monomorphize/src/lib.rs2
-rw-r--r--compiler/rustc_monomorphize/src/partitioning/mod.rs32
-rw-r--r--compiler/rustc_monomorphize/src/polymorphize.rs2
-rw-r--r--compiler/rustc_parse/messages.ftl5
-rw-r--r--compiler/rustc_parse/src/errors.rs10
-rw-r--r--compiler/rustc_parse/src/lexer/mod.rs2
-rw-r--r--compiler/rustc_parse/src/parser/diagnostics.rs1
-rw-r--r--compiler/rustc_parse/src/parser/expr.rs4
-rw-r--r--compiler/rustc_parse/src/parser/generics.rs5
-rw-r--r--compiler/rustc_parse/src/parser/item.rs22
-rw-r--r--compiler/rustc_parse/src/parser/stmt.rs3
-rw-r--r--compiler/rustc_parse/src/validate_attr.rs2
-rw-r--r--compiler/rustc_passes/src/check_attr.rs55
-rw-r--r--compiler/rustc_passes/src/check_const.rs2
-rw-r--r--compiler/rustc_passes/src/dead.rs2
-rw-r--r--compiler/rustc_passes/src/debugger_visualizer.rs124
-rw-r--r--compiler/rustc_passes/src/diagnostic_items.rs2
-rw-r--r--compiler/rustc_passes/src/entry.rs2
-rw-r--r--compiler/rustc_passes/src/lang_items.rs2
-rw-r--r--compiler/rustc_passes/src/lib.rs2
-rw-r--r--compiler/rustc_passes/src/lib_features.rs2
-rw-r--r--compiler/rustc_passes/src/liveness.rs2
-rw-r--r--compiler/rustc_passes/src/loops.rs2
-rw-r--r--compiler/rustc_passes/src/naked_functions.rs2
-rw-r--r--compiler/rustc_passes/src/reachable.rs2
-rw-r--r--compiler/rustc_passes/src/stability.rs3
-rw-r--r--compiler/rustc_passes/src/upvars.rs2
-rw-r--r--compiler/rustc_privacy/src/lib.rs276
-rw-r--r--compiler/rustc_query_impl/Cargo.toml2
-rw-r--r--compiler/rustc_query_impl/src/lib.rs209
-rw-r--r--compiler/rustc_query_impl/src/plumbing.rs443
-rw-r--r--compiler/rustc_query_impl/src/profiling_support.rs6
-rw-r--r--compiler/rustc_query_system/src/query/config.rs11
-rw-r--r--compiler/rustc_query_system/src/query/mod.rs2
-rw-r--r--compiler/rustc_query_system/src/query/plumbing.rs153
-rw-r--r--compiler/rustc_resolve/src/build_reduced_graph.rs13
-rw-r--r--compiler/rustc_resolve/src/diagnostics.rs19
-rw-r--r--compiler/rustc_resolve/src/effective_visibilities.rs4
-rw-r--r--compiler/rustc_resolve/src/ident.rs8
-rw-r--r--compiler/rustc_resolve/src/imports.rs15
-rw-r--r--compiler/rustc_resolve/src/late.rs9
-rw-r--r--compiler/rustc_resolve/src/lib.rs14
-rw-r--r--compiler/rustc_serialize/src/opaque.rs44
-rw-r--r--compiler/rustc_session/src/config.rs67
-rw-r--r--compiler/rustc_session/src/cstore.rs11
-rw-r--r--compiler/rustc_session/src/options.rs6
-rw-r--r--compiler/rustc_session/src/parse.rs4
-rw-r--r--compiler/rustc_session/src/session.rs35
-rw-r--r--compiler/rustc_span/src/def_id.rs9
-rw-r--r--compiler/rustc_span/src/lib.rs24
-rw-r--r--compiler/rustc_span/src/source_map.rs39
-rw-r--r--compiler/rustc_span/src/symbol.rs4
-rw-r--r--compiler/rustc_symbol_mangling/src/lib.rs2
-rw-r--r--compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs68
-rw-r--r--compiler/rustc_target/src/asm/mod.rs4
-rw-r--r--compiler/rustc_trait_selection/src/solve/assembly/mod.rs4
-rw-r--r--compiler/rustc_trait_selection/src/solve/project_goals.rs16
-rw-r--r--compiler/rustc_trait_selection/src/traits/auto_trait.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/const_evaluatable.rs4
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs16
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs8
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs31
-rw-r--r--compiler/rustc_trait_selection/src/traits/fulfill.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/mod.rs48
-rw-r--r--compiler/rustc_trait_selection/src/traits/object_safety.rs6
-rw-r--r--compiler/rustc_trait_selection/src/traits/project.rs7
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs3
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/confirmation.rs47
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/mod.rs39
-rw-r--r--compiler/rustc_trait_selection/src/traits/structural_normalize.rs55
-rw-r--r--compiler/rustc_trait_selection/src/traits/vtable.rs5
-rw-r--r--compiler/rustc_traits/src/chalk/mod.rs2
-rw-r--r--compiler/rustc_traits/src/dropck_outlives.rs2
-rw-r--r--compiler/rustc_traits/src/evaluate_obligation.rs2
-rw-r--r--compiler/rustc_traits/src/implied_outlives_bounds.rs2
-rw-r--r--compiler/rustc_traits/src/lib.rs2
-rw-r--r--compiler/rustc_traits/src/normalize_erasing_regions.rs2
-rw-r--r--compiler/rustc_traits/src/normalize_projection_ty.rs2
-rw-r--r--compiler/rustc_traits/src/type_op.rs2
-rw-r--r--compiler/rustc_ty_utils/messages.ftl8
-rw-r--r--compiler/rustc_ty_utils/src/abi.rs5
-rw-r--r--compiler/rustc_ty_utils/src/assoc.rs5
-rw-r--r--compiler/rustc_ty_utils/src/common_traits.rs11
-rw-r--r--compiler/rustc_ty_utils/src/consts.rs9
-rw-r--r--compiler/rustc_ty_utils/src/errors.rs24
-rw-r--r--compiler/rustc_ty_utils/src/implied_bounds.rs5
-rw-r--r--compiler/rustc_ty_utils/src/instance.rs5
-rw-r--r--compiler/rustc_ty_utils/src/layout.rs5
-rw-r--r--compiler/rustc_ty_utils/src/lib.rs4
-rw-r--r--compiler/rustc_ty_utils/src/needs_drop.rs5
-rw-r--r--compiler/rustc_ty_utils/src/opaque_types.rs198
-rw-r--r--compiler/rustc_ty_utils/src/representability.rs2
-rw-r--r--compiler/rustc_ty_utils/src/structural_match.rs2
-rw-r--r--compiler/rustc_ty_utils/src/ty.rs5
-rw-r--r--compiler/rustc_type_ir/src/structural_impls.rs1
-rw-r--r--library/alloc/src/collections/btree/map.rs2
-rw-r--r--library/alloc/src/string.rs9
-rw-r--r--library/alloc/src/sync.rs25
-rw-r--r--library/alloc/src/vec/in_place_collect.rs9
-rw-r--r--library/alloc/src/vec/mod.rs12
-rw-r--r--library/core/benches/fmt.rs24
-rw-r--r--library/core/benches/iter.rs46
-rw-r--r--library/core/benches/num/dec2flt/mod.rs24
-rw-r--r--library/core/benches/num/flt2dec/mod.rs6
-rw-r--r--library/core/benches/num/mod.rs6
-rw-r--r--library/core/src/any.rs2
-rw-r--r--library/core/src/ascii.rs2
-rw-r--r--library/core/src/cell.rs23
-rw-r--r--library/core/src/char/methods.rs24
-rw-r--r--library/core/src/char/mod.rs23
-rw-r--r--library/core/src/escape.rs65
-rw-r--r--library/core/src/ffi/c_str.rs5
-rw-r--r--library/core/src/ffi/mod.rs14
-rw-r--r--library/core/src/fmt/float.rs12
-rw-r--r--library/core/src/fmt/mod.rs42
-rw-r--r--library/core/src/fmt/num.rs15
-rw-r--r--library/core/src/future/join.rs6
-rw-r--r--library/core/src/intrinsics/mir.rs3
-rw-r--r--library/core/src/iter/adapters/filter.rs55
-rw-r--r--library/core/src/iter/adapters/filter_map.rs62
-rw-r--r--library/core/src/iter/adapters/flatten.rs6
-rw-r--r--library/core/src/iter/traits/collect.rs10
-rw-r--r--library/core/src/lib.rs2
-rw-r--r--library/core/src/marker.rs53
-rw-r--r--library/core/src/mem/mod.rs1
-rw-r--r--library/core/src/num/f32.rs36
-rw-r--r--library/core/src/num/f64.rs36
-rw-r--r--library/core/src/num/int_macros.rs38
-rw-r--r--library/core/src/num/mod.rs59
-rw-r--r--library/core/src/num/nonzero.rs67
-rw-r--r--library/core/src/ops/drop.rs68
-rw-r--r--library/core/src/panic.rs40
-rw-r--r--library/core/src/panic/panic_info.rs2
-rw-r--r--library/core/src/pin.rs2
-rw-r--r--library/core/src/slice/iter.rs4
-rw-r--r--library/core/src/slice/mod.rs15
-rw-r--r--library/core/src/slice/sort.rs38
-rw-r--r--library/core/src/str/pattern.rs8
-rw-r--r--library/core/src/task/mod.rs2
-rw-r--r--library/core/src/task/poll.rs33
-rw-r--r--library/core/src/task/ready.rs61
-rw-r--r--library/core/src/task/wake.rs2
-rw-r--r--library/core/tests/lib.rs1
-rw-r--r--library/core/tests/mem.rs20
-rw-r--r--library/core/tests/num/int_macros.rs26
-rw-r--r--library/core/tests/num/mod.rs56
-rw-r--r--library/core/tests/num/uint_macros.rs26
-rw-r--r--library/portable-simd/crates/core_simd/src/masks.rs2
-rw-r--r--library/std/src/fs.rs13
-rw-r--r--library/std/src/fs/tests.rs54
-rw-r--r--library/std/src/io/copy.rs2
-rw-r--r--library/std/src/net/tcp.rs9
-rw-r--r--library/std/src/net/udp.rs9
-rw-r--r--library/std/src/os/ios/fs.rs22
-rw-r--r--library/std/src/os/macos/fs.rs22
-rw-r--r--library/std/src/os/watchos/fs.rs22
-rw-r--r--library/std/src/os/windows/fs.rs19
-rw-r--r--library/std/src/os/windows/io/handle.rs36
-rw-r--r--library/std/src/os/windows/io/socket.rs36
-rw-r--r--library/std/src/panic.rs8
-rw-r--r--library/std/src/panicking.rs2
-rw-r--r--library/std/src/path.rs11
-rw-r--r--library/std/src/sync/mpmc/error.rs2
-rw-r--r--library/std/src/sync/mpsc/mod.rs4
-rw-r--r--library/std/src/sys/sgx/waitqueue/mod.rs16
-rw-r--r--library/std/src/sys/unix/fs.rs54
-rw-r--r--library/std/src/sys/windows/fs.rs22
-rw-r--r--library/std/src/sys_common/backtrace.rs11
-rw-r--r--library/std/src/thread/local.rs4
-rw-r--r--library/std/src/thread/tests.rs4
-rw-r--r--src/bootstrap/Cargo.lock37
-rw-r--r--src/bootstrap/Cargo.toml4
-rw-r--r--src/bootstrap/bootstrap.py2
-rw-r--r--src/bootstrap/builder.rs2
-rw-r--r--src/bootstrap/builder/tests.rs16
-rw-r--r--src/bootstrap/config.rs38
-rw-r--r--src/bootstrap/download.rs2
-rw-r--r--src/bootstrap/flags.rs51
-rw-r--r--src/bootstrap/lib.rs34
-rw-r--r--src/bootstrap/render_tests.rs9
-rw-r--r--src/bootstrap/run.rs34
-rw-r--r--src/bootstrap/test.rs44
-rw-r--r--src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version2
-rw-r--r--src/ci/stage-build.py92
-rw-r--r--src/etc/completions/x.py.fish475
-rw-r--r--src/etc/completions/x.py.ps1607
-rw-r--r--src/etc/completions/x.py.sh1644
-rw-r--r--src/librustdoc/clean/utils.rs3
-rw-r--r--src/librustdoc/html/markdown.rs14
-rw-r--r--src/librustdoc/html/render/mod.rs2
-rw-r--r--src/librustdoc/lib.rs11
-rw-r--r--src/librustdoc/passes/collect_intra_doc_links.rs25
-rw-r--r--src/librustdoc/visit_ast.rs33
m---------src/llvm-project0
m---------src/tools/cargo0
-rw-r--r--src/tools/clippy/.github/workflows/clippy.yml2
-rw-r--r--src/tools/clippy/.github/workflows/clippy_bors.yml10
-rw-r--r--src/tools/clippy/.github/workflows/clippy_dev.yml2
-rw-r--r--src/tools/clippy/.github/workflows/deploy.yml4
-rw-r--r--src/tools/clippy/.github/workflows/remark.yml4
-rw-r--r--src/tools/clippy/CHANGELOG.md4
-rw-r--r--src/tools/clippy/README.md2
-rw-r--r--src/tools/clippy/book/src/development/type_checking.md6
-rw-r--r--src/tools/clippy/clippy_lints/Cargo.toml2
-rw-r--r--src/tools/clippy/clippy_lints/src/assertions_on_constants.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/attrs.rs144
-rw-r--r--src/tools/clippy/clippy_lints/src/borrow_deref_ref.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/box_default.rs9
-rw-r--r--src/tools/clippy/clippy_lints/src/casts/cast_nan_to_int.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/casts/cast_possible_truncation.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/casts/cast_sign_loss.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/dbg_macro.rs57
-rw-r--r--src/tools/clippy/clippy_lints/src/declared_lints.rs9
-rw-r--r--src/tools/clippy/clippy_lints/src/default_constructed_unit_structs.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/drop_forget_ref.rs117
-rw-r--r--src/tools/clippy/clippy_lints/src/floating_point_arithmetic.rs22
-rw-r--r--src/tools/clippy/clippy_lints/src/fn_null_check.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/implicit_saturating_add.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/index_refutable_slice.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/indexing_slicing.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/let_underscore.rs24
-rw-r--r--src/tools/clippy/clippy_lints/src/lib.rs24
-rw-r--r--src/tools/clippy/clippy_lints/src/lines_filter_map_ok.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/manual_let_else.rs61
-rw-r--r--src/tools/clippy/clippy_lints/src/manual_strip.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/match_like_matches.rs22
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/match_same_arms.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/mod.rs13
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/overlapping_arms.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/redundant_pattern_match.rs224
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/iter_nth_zero.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/iterator_step_by_zero.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/manual_next_back.rs38
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/mod.rs37
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/needless_collect.rs68
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/repeat_once.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/str_splitn.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/misc.rs11
-rw-r--r--src/tools/clippy/clippy_lints/src/needless_bool.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/operators/absurd_extreme_comparisons.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/operators/arithmetic_side_effects.rs12
-rw-r--r--src/tools/clippy/clippy_lints/src/operators/bit_mask.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/operators/cmp_nan.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/operators/duration_subsec.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/operators/float_cmp.rs57
-rw-r--r--src/tools/clippy/clippy_lints/src/operators/mod.rs27
-rw-r--r--src/tools/clippy/clippy_lints/src/operators/modulo_arithmetic.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/operators/numeric_arithmetic.rs45
-rw-r--r--src/tools/clippy/clippy_lints/src/option_if_let_else.rs12
-rw-r--r--src/tools/clippy/clippy_lints/src/ranges.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/ref_patterns.rs44
-rw-r--r--src/tools/clippy/clippy_lints/src/regex.rs25
-rw-r--r--src/tools/clippy/clippy_lints/src/renamed_lints.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/strings.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/trait_bounds.rs59
-rw-r--r--src/tools/clippy/clippy_lints/src/transmute/transmute_null_to_fn.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/transmute/transmuting_null.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/useless_conversion.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/author.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/conf.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/internal_lints/metadata_collector.rs111
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/mod.rs140
-rw-r--r--src/tools/clippy/clippy_lints/src/vec.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/wildcard_imports.rs6
-rw-r--r--src/tools/clippy/clippy_utils/src/consts.rs110
-rw-r--r--src/tools/clippy/clippy_utils/src/hir_utils.rs206
-rw-r--r--src/tools/clippy/clippy_utils/src/lib.rs50
-rw-r--r--src/tools/clippy/clippy_utils/src/source.rs52
-rw-r--r--src/tools/clippy/rust-toolchain2
-rw-r--r--src/tools/clippy/tests/ui-internal/custom_ice_message.rs1
-rw-r--r--src/tools/clippy/tests/ui-internal/custom_ice_message.stderr8
-rw-r--r--src/tools/clippy/tests/ui/arithmetic_side_effects.rs8
-rw-r--r--src/tools/clippy/tests/ui/borrow_deref_ref.fixed15
-rw-r--r--src/tools/clippy/tests/ui/borrow_deref_ref.rs15
-rw-r--r--src/tools/clippy/tests/ui/borrow_deref_ref.stderr6
-rw-r--r--src/tools/clippy/tests/ui/box_default.fixed7
-rw-r--r--src/tools/clippy/tests/ui/box_default.rs7
-rw-r--r--src/tools/clippy/tests/ui/box_default.stderr8
-rw-r--r--src/tools/clippy/tests/ui/collapsible_if.fixed7
-rw-r--r--src/tools/clippy/tests/ui/collapsible_if.rs7
-rw-r--r--src/tools/clippy/tests/ui/collapsible_if.stderr18
-rw-r--r--src/tools/clippy/tests/ui/dbg_macro.rs27
-rw-r--r--src/tools/clippy/tests/ui/dbg_macro.stderr82
-rw-r--r--src/tools/clippy/tests/ui/default_constructed_unit_structs.fixed18
-rw-r--r--src/tools/clippy/tests/ui/default_constructed_unit_structs.rs18
-rw-r--r--src/tools/clippy/tests/ui/default_constructed_unit_structs.stderr10
-rw-r--r--src/tools/clippy/tests/ui/diverging_sub_expression.stderr10
-rw-r--r--src/tools/clippy/tests/ui/drop_forget_copy.rs86
-rw-r--r--src/tools/clippy/tests/ui/drop_forget_copy.stderr112
-rw-r--r--src/tools/clippy/tests/ui/drop_ref.stderr147
-rw-r--r--src/tools/clippy/tests/ui/empty_line_after_doc_comments.rs132
-rw-r--r--src/tools/clippy/tests/ui/empty_line_after_doc_comments.stderr36
-rw-r--r--src/tools/clippy/tests/ui/float_arithmetic.rs2
-rw-r--r--src/tools/clippy/tests/ui/forget_ref.rs50
-rw-r--r--src/tools/clippy/tests/ui/forget_ref.stderr111
-rw-r--r--src/tools/clippy/tests/ui/integer_arithmetic.rs109
-rw-r--r--src/tools/clippy/tests/ui/integer_arithmetic.stderr169
-rw-r--r--src/tools/clippy/tests/ui/issue-111399.rs13
-rw-r--r--src/tools/clippy/tests/ui/let_underscore_untyped.rs15
-rw-r--r--src/tools/clippy/tests/ui/let_underscore_untyped.stderr20
-rw-r--r--src/tools/clippy/tests/ui/manual_let_else.rs15
-rw-r--r--src/tools/clippy/tests/ui/manual_let_else.stderr82
-rw-r--r--src/tools/clippy/tests/ui/manual_let_else_match.stderr4
-rw-r--r--src/tools/clippy/tests/ui/manual_next_back.fixed36
-rw-r--r--src/tools/clippy/tests/ui/manual_next_back.rs36
-rw-r--r--src/tools/clippy/tests/ui/manual_next_back.stderr16
-rw-r--r--src/tools/clippy/tests/ui/match_expr_like_matches_macro.fixed2
-rw-r--r--src/tools/clippy/tests/ui/match_expr_like_matches_macro.stderr8
-rw-r--r--src/tools/clippy/tests/ui/match_same_arms.rs82
-rw-r--r--src/tools/clippy/tests/ui/match_same_arms2.rs6
-rw-r--r--src/tools/clippy/tests/ui/match_same_arms2.stderr17
-rw-r--r--src/tools/clippy/tests/ui/mem_forget.rs2
-rw-r--r--src/tools/clippy/tests/ui/multiple_unsafe_ops_per_block.rs2
-rw-r--r--src/tools/clippy/tests/ui/needless_bool/fixable.fixed7
-rw-r--r--src/tools/clippy/tests/ui/needless_bool/fixable.rs7
-rw-r--r--src/tools/clippy/tests/ui/needless_bool/fixable.stderr24
-rw-r--r--src/tools/clippy/tests/ui/needless_collect.fixed12
-rw-r--r--src/tools/clippy/tests/ui/needless_collect.rs12
-rw-r--r--src/tools/clippy/tests/ui/needless_collect.stderr26
-rw-r--r--src/tools/clippy/tests/ui/needless_return.fixed5
-rw-r--r--src/tools/clippy/tests/ui/needless_return.rs5
-rw-r--r--src/tools/clippy/tests/ui/needless_return.stderr26
-rw-r--r--src/tools/clippy/tests/ui/non_minimal_cfg.fixed17
-rw-r--r--src/tools/clippy/tests/ui/non_minimal_cfg.rs17
-rw-r--r--src/tools/clippy/tests/ui/non_minimal_cfg.stderr28
-rw-r--r--src/tools/clippy/tests/ui/non_minimal_cfg2.rs6
-rw-r--r--src/tools/clippy/tests/ui/non_minimal_cfg2.stderr10
-rw-r--r--src/tools/clippy/tests/ui/option_if_let_else.fixed10
-rw-r--r--src/tools/clippy/tests/ui/option_if_let_else.rs10
-rw-r--r--src/tools/clippy/tests/ui/option_if_let_else.stderr39
-rw-r--r--src/tools/clippy/tests/ui/partialeq_to_none.fixed1
-rw-r--r--src/tools/clippy/tests/ui/partialeq_to_none.rs1
-rw-r--r--src/tools/clippy/tests/ui/partialeq_to_none.stderr30
-rw-r--r--src/tools/clippy/tests/ui/redundant_pattern_matching_option.fixed19
-rw-r--r--src/tools/clippy/tests/ui/redundant_pattern_matching_option.rs31
-rw-r--r--src/tools/clippy/tests/ui/redundant_pattern_matching_option.stderr60
-rw-r--r--src/tools/clippy/tests/ui/redundant_pattern_matching_result.fixed26
-rw-r--r--src/tools/clippy/tests/ui/redundant_pattern_matching_result.rs38
-rw-r--r--src/tools/clippy/tests/ui/redundant_pattern_matching_result.stderr62
-rw-r--r--src/tools/clippy/tests/ui/ref_patterns.rs19
-rw-r--r--src/tools/clippy/tests/ui/ref_patterns.stderr27
-rw-r--r--src/tools/clippy/tests/ui/regex.rs2
-rw-r--r--src/tools/clippy/tests/ui/regex.stderr40
-rw-r--r--src/tools/clippy/tests/ui/rename.fixed10
-rw-r--r--src/tools/clippy/tests/ui/rename.rs10
-rw-r--r--src/tools/clippy/tests/ui/rename.stderr118
-rw-r--r--src/tools/clippy/tests/ui/trait_duplication_in_bounds.fixed10
-rw-r--r--src/tools/clippy/tests/ui/trait_duplication_in_bounds.rs10
-rw-r--r--src/tools/clippy/tests/ui/trait_duplication_in_bounds.stderr24
-rw-r--r--src/tools/clippy/tests/ui/unknown_clippy_lints.fixed2
-rw-r--r--src/tools/clippy/tests/ui/unknown_clippy_lints.stderr2
-rw-r--r--src/tools/clippy/tests/ui/useless_conversion.fixed6
-rw-r--r--src/tools/clippy/tests/ui/useless_conversion.rs6
-rw-r--r--src/tools/clippy/tests/ui/useless_conversion.stderr32
-rw-r--r--src/tools/clippy/tests/ui/wildcard_imports_cfgtest.rs19
-rw-r--r--src/tools/clippy/triagebot.toml2
-rw-r--r--src/tools/compiletest/Cargo.toml1
-rw-r--r--src/tools/compiletest/src/common.rs89
-rw-r--r--src/tools/compiletest/src/runtest.rs7
-rw-r--r--src/tools/linkchecker/main.rs35
-rw-r--r--src/tools/miri/Cargo.lock4
-rw-r--r--src/tools/miri/Cargo.toml2
-rwxr-xr-xsrc/tools/miri/ci.sh3
-rwxr-xr-xsrc/tools/miri/miri10
-rw-r--r--src/tools/miri/rust-version2
-rw-r--r--src/tools/miri/src/bin/miri.rs4
-rw-r--r--src/tools/miri/src/borrow_tracker/stacked_borrows/stack.rs2
-rw-r--r--src/tools/miri/src/diagnostics.rs2
-rw-r--r--src/tools/miri/src/lib.rs1
-rw-r--r--src/tools/miri/src/shims/intrinsics/simd.rs26
-rw-r--r--src/tools/miri/tests/compiletest.rs63
-rw-r--r--src/tools/miri/tests/fail/intrinsics/simd-scatter.rs3
-rw-r--r--src/tools/miri/tests/fail/intrinsics/simd-scatter.stderr1
-rw-r--r--src/tools/miri/tests/fail/never_say_never.rs6
-rw-r--r--src/tools/miri/tests/fail/never_say_never.stderr4
-rw-r--r--src/tools/miri/tests/fail/stacked_borrows/illegal_write2.rs2
-rw-r--r--src/tools/miri/tests/fail/uninit_buffer.rs2
-rw-r--r--src/tools/miri/tests/fail/uninit_buffer_with_provenance.rs1
-rw-r--r--src/tools/miri/tests/pass/portable-simd-ptrs.rs12
-rw-r--r--src/tools/miri/tests/pass/stacked-borrows/zst-field-retagging-terminates.rs3
-rw-r--r--src/tools/replace-version-placeholder/src/main.rs6
-rw-r--r--src/tools/tidy/src/deps.rs3
-rw-r--r--src/tools/tidy/src/style.rs6
-rw-r--r--src/tools/tidy/src/ui_tests.rs37
-rw-r--r--tests/codegen/addr-of-mutate.rs34
-rw-r--r--tests/codegen/binary-search-index-no-bound-check.rs4
-rw-r--r--tests/codegen/fewer-names.rs4
-rw-r--r--tests/codegen/issues/issue-111603.rs28
-rw-r--r--tests/codegen/issues/issue-73396-bounds-check-after-position.rs30
-rw-r--r--tests/codegen/mem-replace-big-type.rs7
-rw-r--r--tests/codegen/sanitizer-cfi-emit-type-metadata-id-itanium-cxx-abi.rs26
-rw-r--r--tests/codegen/sanitizer-cfi-emit-type-metadata-trait-objects.rs81
-rw-r--r--tests/codegen/sanitizer-kcfi-emit-type-metadata-trait-objects.rs78
-rw-r--r--tests/codegen/slice-iter-nonnull.rs35
-rw-r--r--tests/codegen/var-names.rs4
-rw-r--r--tests/debuginfo/reference-debuginfo.rs173
-rw-r--r--tests/incremental/const-generic-type-cycle.rs17
-rw-r--r--tests/mir-opt/building/custom/projections.copy_for_deref.built.after.mir12
-rw-r--r--tests/mir-opt/building/custom/projections.rs25
-rw-r--r--tests/mir-opt/building/custom/projections.tuples.built.after.mir8
-rw-r--r--tests/mir-opt/combine_transmutes.adt_transmutes.InstSimplify.diff166
-rw-r--r--tests/mir-opt/combine_transmutes.rs22
-rw-r--r--tests/mir-opt/const_prop/transmute.unreachable_box.ConstProp.32bit.diff14
-rw-r--r--tests/mir-opt/const_prop/transmute.unreachable_box.ConstProp.64bit.diff14
-rw-r--r--tests/mir-opt/const_prop/transmute.unreachable_direct.ConstProp.32bit.diff17
-rw-r--r--tests/mir-opt/const_prop/transmute.unreachable_direct.ConstProp.64bit.diff17
-rw-r--r--tests/mir-opt/const_prop/transmute.unreachable_mut.ConstProp.32bit.diff22
-rw-r--r--tests/mir-opt/const_prop/transmute.unreachable_mut.ConstProp.64bit.diff22
-rw-r--r--tests/mir-opt/const_prop/transmute.unreachable_ref.ConstProp.32bit.diff14
-rw-r--r--tests/mir-opt/const_prop/transmute.unreachable_ref.ConstProp.64bit.diff14
-rw-r--r--tests/mir-opt/copy-prop/copy_propagation_arg.arg_src.CopyProp.diff12
-rw-r--r--tests/mir-opt/inline/inline_into_box_place.main.Inline.diff12
-rw-r--r--tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.b.Inline.after.mir14
-rw-r--r--tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.d.Inline.after.mir14
-rw-r--r--tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.Inline.diff129
-rw-r--r--tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.PreCodegen.after.mir120
-rw-r--r--tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_smaller.Inline.diff129
-rw-r--r--tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_smaller.PreCodegen.after.mir120
-rw-r--r--tests/mir-opt/inline/unsized_argument.caller.Inline.diff50
-rw-r--r--tests/mir-opt/inline/unsized_argument.rs15
-rw-r--r--tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.diff8
-rw-r--r--tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.mir8
-rw-r--r--tests/mir-opt/issue_72181_1.f.built.after.mir14
-rw-r--r--tests/mir-opt/issue_76432.test.SimplifyComparisonIntegral.diff15
-rw-r--r--tests/mir-opt/issue_99325.main.built.after.mir4
-rw-r--r--tests/mir-opt/lower_intrinsics.transmute_to_box_uninhabited.LowerIntrinsics.diff14
-rw-r--r--tests/mir-opt/lower_intrinsics.transmute_to_mut_uninhabited.LowerIntrinsics.diff14
-rw-r--r--tests/mir-opt/lower_intrinsics.transmute_to_ref_uninhabited.LowerIntrinsics.diff14
-rw-r--r--tests/mir-opt/lower_intrinsics.unreachable.LowerIntrinsics.diff11
-rw-r--r--tests/mir-opt/nll/region_subtyping_basic.main.nll.0.32bit.mir2
-rw-r--r--tests/mir-opt/nll/region_subtyping_basic.main.nll.0.64bit.mir2
-rw-r--r--tests/mir-opt/pre-codegen/mem_replace.manual_replace.PreCodegen.after.mir8
-rw-r--r--tests/mir-opt/pre-codegen/mem_replace.mem_replace.PreCodegen.after.mir42
-rw-r--r--tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.mir122
-rw-r--r--tests/mir-opt/pre-codegen/slice_index.slice_index_range.PreCodegen.after.mir12
-rw-r--r--tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.mir178
-rw-r--r--tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.mir146
-rw-r--r--tests/mir-opt/reference_prop.debuginfo.ReferencePropagation.diff175
-rw-r--r--tests/mir-opt/reference_prop.dominate_storage.ReferencePropagation.diff2
-rw-r--r--tests/mir-opt/reference_prop.maybe_dead.ReferencePropagation.diff6
-rw-r--r--tests/mir-opt/reference_prop.multiple_storage.ReferencePropagation.diff2
-rw-r--r--tests/mir-opt/reference_prop.mut_raw_then_mut_shr.ReferencePropagation.diff23
-rw-r--r--tests/mir-opt/reference_prop.reference_propagation.ReferencePropagation.diff216
-rw-r--r--tests/mir-opt/reference_prop.reference_propagation_const_ptr.ReferencePropagation.diff243
-rw-r--r--tests/mir-opt/reference_prop.reference_propagation_mut.ReferencePropagation.diff230
-rw-r--r--tests/mir-opt/reference_prop.reference_propagation_mut_ptr.ReferencePropagation.diff226
-rw-r--r--tests/mir-opt/reference_prop.rs133
-rw-r--r--tests/mir-opt/reference_prop.unique_with_copies.ReferencePropagation.diff13
-rw-r--r--tests/mir-opt/slice_filter.variant_a-{closure#0}.DestinationPropagation.diff290
-rw-r--r--tests/mir-opt/slice_filter.variant_a-{closure#0}.ReferencePropagation.diff188
-rw-r--r--tests/mir-opt/uninhabited_enum.process_void.SimplifyLocals-final.after.mir5
-rw-r--r--tests/run-make-fulldeps/obtain-borrowck/driver.rs6
-rw-r--r--tests/run-make/CURRENT_RUSTC_VERSION/Makefile6
-rw-r--r--tests/run-make/CURRENT_RUSTC_VERSION/main.rs4
-rw-r--r--tests/run-make/CURRENT_RUSTC_VERSION/stable.rs5
-rw-r--r--tests/run-make/coverage-llvmir/filecheck.testprog.txt2
-rw-r--r--tests/run-make/debugger-visualizer-dep-info/Makefile9
-rw-r--r--tests/run-make/debugger-visualizer-dep-info/foo.py1
-rw-r--r--tests/run-make/debugger-visualizer-dep-info/main.rs12
-rw-r--r--tests/run-make/debugger-visualizer-dep-info/my_visualizers/bar.natvis1
-rw-r--r--tests/run-make/incremental-debugger-visualizer/Makefile49
-rw-r--r--tests/run-make/incremental-debugger-visualizer/foo.rs6
-rw-r--r--tests/run-make/print-native-static-libs/Makefile15
-rw-r--r--tests/run-make/print-native-static-libs/bar.rs13
-rw-r--r--tests/run-make/print-native-static-libs/foo.rs15
-rw-r--r--tests/run-make/short-ice/Makefile9
-rw-r--r--tests/run-make/short-ice/check.sh36
-rw-r--r--tests/run-make/short-ice/src/lib.rs7
-rw-r--r--tests/rustdoc-gui/anchors.goml36
-rw-r--r--tests/rustdoc-gui/codeblock-tooltip.goml18
-rw-r--r--tests/rustdoc-gui/scrape-examples-color.goml42
-rw-r--r--tests/rustdoc-gui/search-result-color.goml172
-rw-r--r--tests/rustdoc-gui/source-code-page.goml22
-rw-r--r--tests/rustdoc-json/impls/impl_item_visibility.rs26
-rw-r--r--tests/rustdoc-json/impls/impl_item_visibility_show_hidden.rs28
-rw-r--r--tests/rustdoc-json/impls/impl_item_visibility_show_private.rs27
-rw-r--r--tests/rustdoc-json/type/inherent_associated_type.rs29
-rw-r--r--tests/rustdoc-json/type/inherent_associated_type_bound.rs21
-rw-r--r--tests/rustdoc-json/type/inherent_associated_type_projections.rs33
-rw-r--r--tests/rustdoc/nested-items-issue-111415.rs36
-rw-r--r--tests/rustdoc/strikethrough-in-summary.rs6
-rw-r--r--tests/ui/associated-inherent-types/inference.rs1
-rw-r--r--tests/ui/associated-types/associated-types-eq-3.stderr2
-rw-r--r--tests/ui/associated-types/associated-types-overridden-binding-2.stderr2
-rw-r--r--tests/ui/associated-types/issue-65774-1.stderr2
-rw-r--r--tests/ui/associated-types/issue-65774-2.stderr2
-rw-r--r--tests/ui/async-await/async-block-control-flow-static-semantics.stderr4
-rw-r--r--tests/ui/async-await/issue-86507.drop_tracking.stderr2
-rw-r--r--tests/ui/async-await/issue-86507.drop_tracking_mir.stderr2
-rw-r--r--tests/ui/async-await/issue-86507.no_drop_tracking.stderr2
-rw-r--r--tests/ui/async-await/multiple-lifetimes/partial-relation.rs2
-rw-r--r--tests/ui/attr-bad-crate-attr.rs (renamed from tests/ui/attr-bad-crate-attr.rc)0
-rw-r--r--tests/ui/attr-bad-crate-attr.stderr8
-rw-r--r--tests/ui/borrowck/borrowck-closures-slice-patterns-ok.rs1
-rw-r--r--tests/ui/borrowck/borrowck-field-sensitivity-rpass.rs1
-rw-r--r--tests/ui/borrowck/borrowck-use-mut-borrow-rpass.rs2
-rw-r--r--tests/ui/borrowck/erase-error-in-mir-drop-tracking.rs23
-rw-r--r--tests/ui/borrowck/erase-error-in-mir-drop-tracking.stderr24
-rw-r--r--tests/ui/cfg/cfg-stmt-recovery.rs13
-rw-r--r--tests/ui/cfg/cfg-stmt-recovery.stderr20
-rw-r--r--tests/ui/closure_context/issue-26046-fn-mut.stderr2
-rw-r--r--tests/ui/closure_context/issue-26046-fn-once.stderr2
-rw-r--r--tests/ui/closures/2229_closure_analysis/migrations/issue-78720.rs1
-rw-r--r--tests/ui/closures/2229_closure_analysis/migrations/issue-78720.stderr2
-rw-r--r--tests/ui/closures/2229_closure_analysis/optimization/edge_case_run_pass.rs1
-rw-r--r--tests/ui/closures/2229_closure_analysis/run_pass/drop_then_use_fake_reads.rs2
-rw-r--r--tests/ui/coercion/coerce-issue-49593-box-never-windows.nofallback.stderr4
-rw-r--r--tests/ui/coercion/coerce-issue-49593-box-never.nofallback.stderr4
-rw-r--r--tests/ui/const-generics/adt_const_params/const_param_ty_good.rs10
-rw-r--r--tests/ui/const-generics/adt_const_params/const_param_ty_impl_bad_field.rs4
-rw-r--r--tests/ui/const-generics/adt_const_params/const_param_ty_impl_bad_field.stderr13
-rw-r--r--tests/ui/const-generics/adt_const_params/const_param_ty_impl_no_structural_eq.rs4
-rw-r--r--tests/ui/const-generics/adt_const_params/const_param_ty_impl_no_structural_eq.stderr12
-rw-r--r--tests/ui/const-generics/adt_const_params/const_param_ty_impl_union.rs33
-rw-r--r--tests/ui/const-generics/adt_const_params/const_param_ty_impl_union.stderr8
-rw-r--r--tests/ui/const-generics/defaults/trait_objects_fail.stderr4
-rw-r--r--tests/ui/consts/const-eval/format.stderr56
-rw-r--r--tests/ui/consts/const-integer-bool-ops.rs10
-rw-r--r--tests/ui/consts/const-integer-bool-ops.stderr90
-rw-r--r--tests/ui/consts/const-mut-refs/issue-76510.32bit.stderr6
-rw-r--r--tests/ui/consts/const-mut-refs/issue-76510.64bit.stderr6
-rw-r--r--tests/ui/consts/const-mut-refs/issue-76510.rs1
-rw-r--r--tests/ui/consts/const-tup-index-span.rs1
-rw-r--r--tests/ui/consts/const-tup-index-span.stderr6
-rw-r--r--tests/ui/consts/const_forget.rs2
-rw-r--r--tests/ui/consts/issue-104155.rs3
-rw-r--r--tests/ui/consts/issue-54954.rs2
-rw-r--r--tests/ui/consts/issue-54954.stderr12
-rw-r--r--tests/ui/consts/issue-56164.stderr12
-rw-r--r--tests/ui/consts/issue-66693.stderr12
-rw-r--r--tests/ui/crate-leading-sep.rs2
-rw-r--r--tests/ui/custom_test_frameworks/mismatch.stderr2
-rw-r--r--tests/ui/diagnostic-width/E0271.stderr4
-rw-r--r--tests/ui/drop/dropck-eyepatch-manuallydrop.rs22
-rw-r--r--tests/ui/drop/issue-110682.rs92
-rw-r--r--tests/ui/drop/repeat-drop.rs2
-rw-r--r--tests/ui/dst/dst-bad-coerce1.stderr4
-rw-r--r--tests/ui/dst/dst-object-from-unsized-type.stderr8
-rw-r--r--tests/ui/dupe-first-attr.rs (renamed from tests/ui/dupe-first-attr.rc)16
-rw-r--r--tests/ui/enum-discriminant/auxiliary/discr-foreign-dep.rs7
-rw-r--r--tests/ui/enum-discriminant/discr-foreign.rs11
-rw-r--r--tests/ui/enum-discriminant/issue-41394.rs1
-rw-r--r--tests/ui/enum-discriminant/issue-41394.stderr6
-rw-r--r--tests/ui/explicit/explicit-call-to-supertrait-dtor.fixed3
-rw-r--r--tests/ui/explicit/explicit-call-to-supertrait-dtor.rs3
-rw-r--r--tests/ui/explicit/explicit-call-to-supertrait-dtor.stderr2
-rw-r--r--tests/ui/extenv/extenv-escaped-var.rs3
-rw-r--r--tests/ui/extenv/extenv-escaped-var.stderr11
-rw-r--r--tests/ui/extenv/issue-110547.stderr12
-rw-r--r--tests/ui/extern/auxiliary/invalid-utf8.txt1
-rw-r--r--tests/ui/feature-gates/auxiliary/debugger-visualizer.natvis3
-rw-r--r--tests/ui/feature-gates/feature-gate-cfg_overflow_checks.rs6
-rw-r--r--tests/ui/feature-gates/feature-gate-cfg_overflow_checks.stderr12
-rw-r--r--tests/ui/feature-gates/feature-gate-dispatch-from-dyn-missing-impl.stderr9
-rw-r--r--tests/ui/feature-gates/feature-gate-unsafe_pin_internals.rs1
-rw-r--r--tests/ui/generator/drop-env.rs1
-rw-r--r--tests/ui/generator/drop-tracking-error-body.rs18
-rw-r--r--tests/ui/generator/drop-tracking-error-body.stderr17
-rw-r--r--tests/ui/generator/issue-57017.no_drop_tracking.stderr42
-rw-r--r--tests/ui/generator/issue-57017.rs1
-rw-r--r--tests/ui/generator/non-static-is-unpin.rs1
-rw-r--r--tests/ui/generator/resume-arg-size.rs1
-rw-r--r--tests/ui/generic-associated-types/equality-bound.stderr5
-rw-r--r--tests/ui/generic-associated-types/issue-76535.base.stderr3
-rw-r--r--tests/ui/generic-associated-types/issue-79422.base.stderr3
-rw-r--r--tests/ui/generic-associated-types/issue-79422.extended.stderr2
-rw-r--r--tests/ui/generic-associated-types/issue-88595.rs1
-rw-r--r--tests/ui/generic-associated-types/issue-88595.stderr34
-rw-r--r--tests/ui/hygiene/stdlib-prelude-from-opaque-late.rs1
-rw-r--r--tests/ui/illegal-ufcs-drop.fixed3
-rw-r--r--tests/ui/illegal-ufcs-drop.rs3
-rw-r--r--tests/ui/illegal-ufcs-drop.stderr2
-rw-r--r--tests/ui/impl-trait/extra-impl-in-trait-impl.fixed19
-rw-r--r--tests/ui/impl-trait/extra-impl-in-trait-impl.rs19
-rw-r--r--tests/ui/impl-trait/extra-impl-in-trait-impl.stderr26
-rw-r--r--tests/ui/impl-trait/in-assoc-type-unconstrained.rs27
-rw-r--r--tests/ui/impl-trait/in-assoc-type-unconstrained.stderr59
-rw-r--r--tests/ui/impl-trait/in-assoc-type.rs21
-rw-r--r--tests/ui/impl-trait/in-assoc-type.stderr22
-rw-r--r--tests/ui/impl-trait/in-trait/object-safety.current.stderr3
-rw-r--r--tests/ui/impl-trait/in-trait/object-safety.next.stderr3
-rw-r--r--tests/ui/impl-trait/issue-103181-1.current.stderr (renamed from tests/ui/impl-trait/issue-103181-1.stderr)2
-rw-r--r--tests/ui/impl-trait/issue-103181-1.next.stderr12
-rw-r--r--tests/ui/impl-trait/issue-103181-1.rs2
-rw-r--r--tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.stderr5
-rw-r--r--tests/ui/imports/issue-109343.rs10
-rw-r--r--tests/ui/imports/issue-109343.stderr11
-rw-r--r--tests/ui/invalid/foo.natvis.xml1
-rw-r--r--tests/ui/invalid/invalid-debugger-visualizer-target.rs2
-rw-r--r--tests/ui/invalid/invalid-debugger-visualizer-target.stderr4
-rw-r--r--tests/ui/issues/auxiliary/issue-3136-a.rc4
-rw-r--r--tests/ui/issues/auxiliary/issue-3136-a.rs7
-rw-r--r--tests/ui/issues/issue-14366.stderr4
-rw-r--r--tests/ui/issues/issue-22034.stderr2
-rw-r--r--tests/ui/issues/issue-22872.stderr2
-rw-r--r--tests/ui/issues/issue-3136-b.rs2
-rw-r--r--tests/ui/iterators/collect-into-slice.rs6
-rw-r--r--tests/ui/iterators/collect-into-slice.stderr12
-rw-r--r--tests/ui/kindck/kindck-impl-type-params.stderr12
-rw-r--r--tests/ui/kindck/kindck-inherited-copy-bound.curr.stderr3
-rw-r--r--tests/ui/kindck/kindck-inherited-copy-bound.object_safe_for_dispatch.stderr3
-rw-r--r--tests/ui/kindck/kindck-send-unsafe.rs10
-rw-r--r--tests/ui/kindck/kindck-send-unsafe.rs~rust-lang_master12
-rw-r--r--tests/ui/kindck/kindck-send-unsafe.stderr23
-rw-r--r--tests/ui/lint/dropping_copy_types.rs79
-rw-r--r--tests/ui/lint/dropping_copy_types.stderr108
-rw-r--r--tests/ui/lint/dropping_references.rs (renamed from src/tools/clippy/tests/ui/drop_ref.rs)48
-rw-r--r--tests/ui/lint/dropping_references.stderr127
-rw-r--r--tests/ui/lint/forgetting_copy_types.rs56
-rw-r--r--tests/ui/lint/forgetting_copy_types.stderr88
-rw-r--r--tests/ui/lint/forgetting_references.rs39
-rw-r--r--tests/ui/lint/forgetting_references.stderr97
-rw-r--r--tests/ui/lint/issue-111359.rs27
-rw-r--r--tests/ui/lint/issue-111359.stderr26
-rw-r--r--tests/ui/lint/unused/auxiliary/must-use-foreign.rs12
-rw-r--r--tests/ui/lint/unused/must-use-foreign.rs15
-rw-r--r--tests/ui/lint/unused/unused-async.rs2
-rw-r--r--tests/ui/lint/unused/unused-async.stderr13
-rw-r--r--tests/ui/liveness/liveness-unused.rs2
-rw-r--r--tests/ui/macros/builtin-prelude-no-accidents.stderr15
-rw-r--r--tests/ui/macros/issue-111749.rs12
-rw-r--r--tests/ui/macros/issue-111749.stderr18
-rw-r--r--tests/ui/macros/panic-temporaries-2018.rs55
-rw-r--r--tests/ui/macros/panic-temporaries.rs43
-rw-r--r--tests/ui/macros/parse-complex-macro-invoc-op.rs1
-rw-r--r--tests/ui/macros/rfc-2011-nicer-assert-messages/non-consuming-methods-have-optimized-codegen.stdout18
-rw-r--r--tests/ui/mismatched_types/cast-rfc0401.stderr12
-rw-r--r--tests/ui/never_type/fallback-closure-wrap.fallback.stderr2
-rw-r--r--tests/ui/never_type/never-assign-dead-code.rs1
-rw-r--r--tests/ui/never_type/never-assign-dead-code.stderr8
-rw-r--r--tests/ui/nll/relate_tys/hr-fn-aba-as-aaa.rs2
-rw-r--r--tests/ui/nll/ty-outlives/projection-body.rs2
-rw-r--r--tests/ui/numbers-arithmetic/overflow-attribute-works-1.rs19
-rw-r--r--tests/ui/numbers-arithmetic/overflow-attribute-works-2.rs19
-rw-r--r--tests/ui/object-safety/issue-19538.stderr3
-rw-r--r--tests/ui/object-safety/object-safety-associated-consts.object_safe_for_dispatch.stderr3
-rw-r--r--tests/ui/object-safety/object-safety-generics.object_safe_for_dispatch.stderr6
-rw-r--r--tests/ui/object-safety/object-safety-mentions-Self.object_safe_for_dispatch.stderr6
-rw-r--r--tests/ui/object-safety/object-safety-no-static.object_safe_for_dispatch.stderr3
-rw-r--r--tests/ui/object-safety/object-safety-sized-2.object_safe_for_dispatch.stderr3
-rw-r--r--tests/ui/object-safety/object-safety-sized.object_safe_for_dispatch.stderr3
-rw-r--r--tests/ui/offset-of/offset-of-arg-count.rs5
-rw-r--r--tests/ui/offset-of/offset-of-dst-field.rs16
-rw-r--r--tests/ui/offset-of/offset-of-dst-field.stderr55
-rw-r--r--tests/ui/offset-of/offset-of-inference.rs11
-rw-r--r--tests/ui/offset-of/offset-of-inference.stderr9
-rw-r--r--tests/ui/offset-of/offset-of-output-type.rs20
-rw-r--r--tests/ui/offset-of/offset-of-output-type.stderr64
-rw-r--r--tests/ui/offset-of/offset-of-private.rs12
-rw-r--r--tests/ui/offset-of/offset-of-private.stderr43
-rw-r--r--tests/ui/offset-of/offset-of-self.rs58
-rw-r--r--tests/ui/offset-of/offset-of-self.stderr79
-rw-r--r--tests/ui/or-patterns/or-patterns-default-binding-modes.rs2
-rw-r--r--tests/ui/panics/default-backtrace-ice.stderr2
-rw-r--r--tests/ui/panics/short-ice-remove-middle-frames-2.rs61
-rw-r--r--tests/ui/panics/short-ice-remove-middle-frames-2.run.stderr11
-rw-r--r--tests/ui/panics/short-ice-remove-middle-frames.rs57
-rw-r--r--tests/ui/panics/short-ice-remove-middle-frames.run.stderr12
-rw-r--r--tests/ui/parser/dyn-trait-compatibility.stderr12
-rw-r--r--tests/ui/parser/impl-on-unsized-typo.rs6
-rw-r--r--tests/ui/parser/impl-on-unsized-typo.stderr8
-rw-r--r--tests/ui/parser/issues/issue-111416.rs3
-rw-r--r--tests/ui/parser/issues/issue-111416.stderr18
-rw-r--r--tests/ui/pattern/bindings-after-at/borrowck-pat-at-and-box-pass.rs3
-rw-r--r--tests/ui/pattern/bindings-after-at/borrowck-pat-by-copy-bindings-in-at.rs2
-rw-r--r--tests/ui/pattern/move-ref-patterns/borrowck-move-ref-pattern-pass.rs2
-rw-r--r--tests/ui/pattern/move-ref-patterns/move-ref-patterns-closure-captures-pass.rs2
-rw-r--r--tests/ui/pattern/pattern-error-continue.stderr15
-rw-r--r--tests/ui/pattern/usefulness/consts-opaque.rs18
-rw-r--r--tests/ui/pattern/usefulness/consts-opaque.stderr75
-rw-r--r--tests/ui/print_type_sizes/async.rs2
-rw-r--r--tests/ui/print_type_sizes/async.stdout8
-rw-r--r--tests/ui/print_type_sizes/generator_discr_placement.rs1
-rw-r--r--tests/ui/print_type_sizes/generator_discr_placement.stdout2
-rw-r--r--tests/ui/regions/type-param-outlives-reempty-issue-74429-2.rs6
-rw-r--r--tests/ui/regions/type-param-outlives-reempty-issue-74429.rs2
-rw-r--r--tests/ui/resolve/issue-109250.rs3
-rw-r--r--tests/ui/resolve/issue-109250.stderr14
-rw-r--r--tests/ui/resolve/issue-111312.rs11
-rw-r--r--tests/ui/resolve/issue-111312.stderr15
-rw-r--r--tests/ui/resolve/issue-111727.rs5
-rw-r--r--tests/ui/resolve/issue-111727.stderr9
-rw-r--r--tests/ui/resolve/issue-50599.rs1
-rw-r--r--tests/ui/resolve/issue-50599.stderr6
-rw-r--r--tests/ui/resolve/resolve-variant-assoc-item.stderr14
-rw-r--r--tests/ui/rfc-2008-non-exhaustive/borrowck-exhaustive.rs2
-rw-r--r--tests/ui/rfc-2361-dbg-macro/dbg-macro-expected-behavior.rs2
-rw-r--r--tests/ui/rfc-2361-dbg-macro/dbg-macro-expected-behavior.run.stderr30
-rw-r--r--tests/ui/rust-2018/remove-extern-crate.fixed1
-rw-r--r--tests/ui/rust-2018/remove-extern-crate.rs1
-rw-r--r--tests/ui/rust-2018/remove-extern-crate.stderr6
-rw-r--r--tests/ui/self/arbitrary-self-types-not-object-safe.curr.stderr3
-rw-r--r--tests/ui/self/arbitrary-self-types-not-object-safe.object_safe_for_dispatch.stderr3
-rw-r--r--tests/ui/self/self-ctor-inner-const.rs17
-rw-r--r--tests/ui/self/self-ctor-inner-const.stderr33
-rw-r--r--tests/ui/self/self-ctor-nongeneric.rs15
-rw-r--r--tests/ui/statics/issue-91050-1.rs2
-rw-r--r--tests/ui/suggestions/derive-macro-missing-bounds.stderr8
-rw-r--r--tests/ui/suggestions/issue-109854.rs12
-rw-r--r--tests/ui/suggestions/issue-109854.stderr31
-rw-r--r--tests/ui/suggestions/issue-94171.rs5
-rw-r--r--tests/ui/suggestions/issue-94171.stderr36
-rw-r--r--tests/ui/suggestions/issue-99597.rs15
-rw-r--r--tests/ui/suggestions/issue-99597.stderr15
-rw-r--r--tests/ui/suggestions/suggest-borrow-to-dyn-object.rs16
-rw-r--r--tests/ui/suggestions/suggest-borrow-to-dyn-object.stderr18
-rw-r--r--tests/ui/track-diagnostics/track6.rs3
-rw-r--r--tests/ui/track-diagnostics/track6.stderr4
-rw-r--r--tests/ui/traits/coercion-generic-bad.stderr2
-rw-r--r--tests/ui/traits/copy-guessing.rs4
-rw-r--r--tests/ui/traits/copy-guessing.stderr14
-rw-r--r--tests/ui/traits/cycle-cache-err-60010.stderr18
-rw-r--r--tests/ui/traits/impl-evaluation-order.rs2
-rw-r--r--tests/ui/traits/issue-106072.rs1
-rw-r--r--tests/ui/traits/issue-106072.stderr12
-rw-r--r--tests/ui/traits/issue-20692.stderr3
-rw-r--r--tests/ui/traits/issue-38604.stderr3
-rw-r--r--tests/ui/traits/issue-7013.stderr2
-rw-r--r--tests/ui/traits/map-types.stderr2
-rw-r--r--tests/ui/traits/new-solver/auto-with-drop_tracking_mir.fail.stderr4
-rw-r--r--tests/ui/traits/new-solver/auto-with-drop_tracking_mir.rs1
-rw-r--r--tests/ui/traits/new-solver/normalize-rcvr-for-inherent.rs25
-rw-r--r--tests/ui/traits/new-solver/structural-resolve-field.rs13
-rw-r--r--tests/ui/traits/new-solver/temporary-ambiguity.rs2
-rw-r--r--tests/ui/traits/non_lifetime_binders/supertrait-object-safety.stderr3
-rw-r--r--tests/ui/traits/non_lifetime_binders/universe-error1.rs18
-rw-r--r--tests/ui/traits/non_lifetime_binders/universe-error1.stderr27
-rw-r--r--tests/ui/traits/object/safety.stderr3
-rw-r--r--tests/ui/traits/solver-cycles/cycle-via-builtin-auto-trait-impl.rs34
-rw-r--r--tests/ui/traits/solver-cycles/cycle-via-builtin-auto-trait-impl.stderr24
-rw-r--r--tests/ui/traits/test-2.stderr3
-rw-r--r--tests/ui/traits/trait-upcasting/type-checking-test-1.stderr2
-rw-r--r--tests/ui/traits/trait-upcasting/type-checking-test-2.stderr4
-rw-r--r--tests/ui/trivial-bounds/trivial-bounds-inconsistent-copy.rs2
-rw-r--r--tests/ui/trivial-bounds/trivial-bounds-inconsistent-copy.stderr8
-rw-r--r--tests/ui/type-alias-impl-trait/associated-type-impl-trait-lifetime.rs9
-rw-r--r--tests/ui/type-alias-impl-trait/invalid_impl_trait_in_assoc_ty.rs16
-rw-r--r--tests/ui/type-alias-impl-trait/invalid_impl_trait_in_assoc_ty.stderr22
-rw-r--r--tests/ui/type-alias-impl-trait/issue-98604.stderr2
-rw-r--r--tests/ui/type-alias-impl-trait/issue-98608.stderr2
-rw-r--r--tests/ui/type/issue-58355.stderr2
-rw-r--r--tests/ui/type/type-dependent-def-issue-49241.rs1
-rw-r--r--tests/ui/type/type-dependent-def-issue-49241.stderr6
-rw-r--r--tests/ui/type/type-path-err-node-types.stderr12
-rw-r--r--tests/ui/underscore-imports/issue-110164.rs19
-rw-r--r--tests/ui/underscore-imports/issue-110164.stderr71
-rw-r--r--tests/ui/unsized-locals/align.rs30
-rw-r--r--tests/ui/unsized/unsized-fn-param.stderr16
-rw-r--r--tests/ui/use/use-self-type.stderr2
-rw-r--r--tests/ui/weird-exprs.rs30
-rw-r--r--tests/ui/wf/wf-convert-unsafe-trait-obj-box.stderr9
-rw-r--r--tests/ui/wf/wf-convert-unsafe-trait-obj.stderr9
-rw-r--r--tests/ui/wf/wf-unsafe-trait-obj-match.stderr6
-rw-r--r--triagebot.toml29
979 files changed, 18398 insertions, 7614 deletions
diff --git a/Cargo.lock b/Cargo.lock
index bb37fee98e4..04c804d19a4 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -154,11 +154,11 @@ checksum = "98161a4e3e2184da77bb14f02184cdd111e83bbbcc9979dfee3c44b9a85f5602"
 
 [[package]]
 name = "ar_archive_writer"
-version = "0.1.3"
+version = "0.1.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b0639441fd17a3197d1cbca8dc8768cc172a63b64b4bb6c372e8f41ed0acc9bb"
+checksum = "74cfb39880a59e122232cb5fb06b20b4382d58c12fa9747d16f846d38a7b094c"
 dependencies = [
- "object",
+ "object 0.31.1",
 ]
 
 [[package]]
@@ -233,7 +233,7 @@ dependencies = [
  "cfg-if",
  "libc",
  "miniz_oxide",
- "object",
+ "object 0.30.1",
  "rustc-demangle",
 ]
 
@@ -332,6 +332,12 @@ dependencies = [
 ]
 
 [[package]]
+name = "byteorder"
+version = "1.4.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
+
+[[package]]
 name = "bytes"
 version = "1.0.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -629,7 +635,7 @@ dependencies = [
  "itertools",
  "pulldown-cmark",
  "quine-mc_cluskey",
- "regex-syntax",
+ "regex-syntax 0.7.1",
  "rustc-semver",
  "semver",
  "serde",
@@ -723,6 +729,7 @@ dependencies = [
 name = "compiletest"
 version = "0.0.0"
 dependencies = [
+ "anyhow",
  "build_helper",
  "colored",
  "diff",
@@ -854,7 +861,7 @@ dependencies = [
  "autocfg",
  "cfg-if",
  "crossbeam-utils",
- "memoffset",
+ "memoffset 0.7.1",
  "scopeguard",
 ]
 
@@ -1242,6 +1249,16 @@ dependencies = [
 ]
 
 [[package]]
+name = "field-offset"
+version = "0.3.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a3cf3a800ff6e860c863ca6d4b16fd999db8b752819c1606884047b73e468535"
+dependencies = [
+ "memoffset 0.8.0",
+ "rustc_version",
+]
+
+[[package]]
 name = "filetime"
 version = "0.2.20"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2190,6 +2207,15 @@ dependencies = [
 
 [[package]]
 name = "memoffset"
+version = "0.6.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce"
+dependencies = [
+ "autocfg",
+]
+
+[[package]]
+name = "memoffset"
 version = "0.7.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "5de893c32cde5f383baa4c04c5d6dbdd735cfd4a794b0debdb2bb1b421da5ff4"
@@ -2198,6 +2224,15 @@ dependencies = [
 ]
 
 [[package]]
+name = "memoffset"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d61c719bcfbcf5d62b3a09efa6088de8c54bc0bfcd3ea7ae39fcc186108b8de1"
+dependencies = [
+ "autocfg",
+]
+
+[[package]]
 name = "mime"
 version = "0.3.16"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2336,13 +2371,23 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "8d864c91689fdc196779b98dba0aceac6118594c2df6ee5d943eb6a8df4d107a"
 dependencies = [
  "compiler_builtins",
+ "memchr",
+ "rustc-std-workspace-alloc",
+ "rustc-std-workspace-core",
+]
+
+[[package]]
+name = "object"
+version = "0.31.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8bda667d9f2b5051b8833f59f3bf748b28ef54f850f4fcb389a252aa383866d1"
+dependencies = [
  "crc32fast",
  "flate2",
  "hashbrown 0.13.1",
  "indexmap",
  "memchr",
- "rustc-std-workspace-alloc",
- "rustc-std-workspace-core",
+ "ruzstd",
 ]
 
 [[package]]
@@ -2667,9 +2712,9 @@ checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5"
 
 [[package]]
 name = "proc-macro2"
-version = "1.0.53"
+version = "1.0.56"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ba466839c78239c09faf015484e5cc04860f88242cff4d03eb038f04b4699b73"
+checksum = "2b63bdb0cd06f1f4dedf69b254734f9b45af66e4a031e42a7480257d9898b435"
 dependencies = [
  "unicode-ident",
 ]
@@ -2837,7 +2882,7 @@ checksum = "d83f127d94bdbcda4c8cc2e50f6f84f4b611f69c902699ca385a39c3a75f9ff1"
 dependencies = [
  "aho-corasick",
  "memchr",
- "regex-syntax",
+ "regex-syntax 0.6.26",
 ]
 
 [[package]]
@@ -2846,7 +2891,7 @@ version = "0.1.10"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132"
 dependencies = [
- "regex-syntax",
+ "regex-syntax 0.6.26",
 ]
 
 [[package]]
@@ -2865,6 +2910,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "49b3de9ec5dc0a3417da371aab17d729997c15010e7fd24ff707773a33bddb64"
 
 [[package]]
+name = "regex-syntax"
+version = "0.7.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a5996294f19bd3aae0453a862ad728f60e6600695733dd5df01da90c54363a3c"
+
+[[package]]
 name = "remote-test-client"
 version = "0.1.0"
 
@@ -3194,7 +3245,7 @@ dependencies = [
  "cstr",
  "libc",
  "measureme",
- "object",
+ "object 0.31.1",
  "rustc-demangle",
  "rustc_ast",
  "rustc_attr",
@@ -3230,7 +3281,7 @@ dependencies = [
  "itertools",
  "jobserver",
  "libc",
- "object",
+ "object 0.31.1",
  "pathdiff",
  "regex",
  "rustc_arena",
@@ -3306,6 +3357,7 @@ dependencies = [
  "rustc-hash",
  "rustc-rayon",
  "rustc-rayon-core",
+ "rustc_arena",
  "rustc_graphviz",
  "rustc_index",
  "rustc_macros",
@@ -3781,6 +3833,7 @@ dependencies = [
  "chalk-ir",
  "derive_more",
  "either",
+ "field-offset",
  "gsgdt",
  "measureme",
  "polonius-engine",
@@ -3995,7 +4048,9 @@ dependencies = [
 name = "rustc_query_impl"
 version = "0.0.0"
 dependencies = [
+ "field-offset",
  "measureme",
+ "memoffset 0.6.5",
  "rustc-rayon-core",
  "rustc_ast",
  "rustc_data_structures",
@@ -4386,6 +4441,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "61b3909d758bb75c79f23d4736fac9433868679d3ad2ea7a61e3c25cfda9a088"
 
 [[package]]
+name = "ruzstd"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9a15e661f0f9dac21f3494fe5d23a6338c0ac116a2d22c2b63010acd89467ffe"
+dependencies = [
+ "byteorder",
+ "thiserror",
+ "twox-hash",
+]
+
+[[package]]
 name = "ryu"
 version = "1.0.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -4445,18 +4511,18 @@ dependencies = [
 
 [[package]]
 name = "serde"
-version = "1.0.159"
+version = "1.0.160"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3c04e8343c3daeec41f58990b9d77068df31209f2af111e059e9fe9646693065"
+checksum = "bb2f3770c8bce3bcda7e149193a069a0f4365bda1fa5cd88e03bca26afc1216c"
 dependencies = [
  "serde_derive",
 ]
 
 [[package]]
 name = "serde_derive"
-version = "1.0.159"
+version = "1.0.160"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4c614d17805b093df4b147b51339e7e44bf05ef59fba1e45d83500bcfb4d8585"
+checksum = "291a097c63d8497e00160b166a967a4a79c64f3facdd01cbd7502231688d77df"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -4621,7 +4687,7 @@ dependencies = [
  "hermit-abi 0.3.0",
  "libc",
  "miniz_oxide",
- "object",
+ "object 0.30.1",
  "panic_abort",
  "panic_unwind",
  "profiler_builtins",
@@ -4893,13 +4959,13 @@ dependencies = [
 
 [[package]]
 name = "thorin-dwp"
-version = "0.4.0"
+version = "0.6.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "da8fbf660a019b6bf11ea95762041464aa9099cc293b6a66d77cea5107619671"
+checksum = "98c040e1340b889d4180c64e1d787efa9c32cb1617757e101480b61238b0d927"
 dependencies = [
  "gimli 0.26.2",
  "hashbrown 0.12.3",
- "object",
+ "object 0.31.1",
  "tracing",
 ]
 
@@ -5122,9 +5188,9 @@ checksum = "9e79c4d996edb816c91e4308506774452e55e95c3c9de07b6729e17e15a5ef81"
 
 [[package]]
 name = "ui_test"
-version = "0.9.0"
+version = "0.10.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "95033b0e41b8018013d99a6f1486c1ae5bd080378ced60c5f797e93842423b33"
+checksum = "191a442639ea102fa62671026047e51d574bfda44b7fdf32151d7314624c1cd2"
 dependencies = [
  "bstr 1.3.0",
  "cargo-platform",
diff --git a/RELEASES.md b/RELEASES.md
index e72905c15bd..85266a17550 100644
--- a/RELEASES.md
+++ b/RELEASES.md
@@ -1481,7 +1481,7 @@ and related tools.
 [is_power_of_two_usize]: https://doc.rust-lang.org/stable/core/num/struct.NonZeroUsize.html#method.is_power_of_two
 [stdarch/1266]: https://github.com/rust-lang/stdarch/pull/1266
 
-Version 1.58.1 (2022-01-19)
+Version 1.58.1 (2022-01-20)
 ===========================
 
 * Fix race condition in `std::fs::remove_dir_all` ([CVE-2022-21658])
diff --git a/compiler/rustc_abi/src/layout.rs b/compiler/rustc_abi/src/layout.rs
index 3d97d9b4895..f11c1c77f9c 100644
--- a/compiler/rustc_abi/src/layout.rs
+++ b/compiler/rustc_abi/src/layout.rs
@@ -12,7 +12,7 @@ use tracing::debug;
 pub trait LayoutCalculator {
     type TargetDataLayoutRef: Borrow<TargetDataLayout>;
 
-    fn delay_bug(&self, txt: &str);
+    fn delay_bug(&self, txt: String);
     fn current_data_layout(&self) -> Self::TargetDataLayoutRef;
 
     fn scalar_pair(&self, a: Scalar, b: Scalar) -> LayoutS {
@@ -969,7 +969,7 @@ fn univariant(
     for &i in &inverse_memory_index {
         let field = &fields[i];
         if !sized {
-            this.delay_bug(&format!(
+            this.delay_bug(format!(
                 "univariant: field #{} comes after unsized field",
                 offsets.len(),
             ));
diff --git a/compiler/rustc_ast/src/tokenstream.rs b/compiler/rustc_ast/src/tokenstream.rs
index f0a6a5e0725..db296aa44db 100644
--- a/compiler/rustc_ast/src/tokenstream.rs
+++ b/compiler/rustc_ast/src/tokenstream.rs
@@ -48,14 +48,15 @@ pub enum TokenTree {
     Delimited(DelimSpan, Delimiter, TokenStream),
 }
 
-// Ensure all fields of `TokenTree` is `Send` and `Sync`.
+// Ensure all fields of `TokenTree` are `DynSend` and `DynSync`.
 #[cfg(parallel_compiler)]
 fn _dummy()
 where
-    Token: Send + Sync,
-    DelimSpan: Send + Sync,
-    Delimiter: Send + Sync,
-    TokenStream: Send + Sync,
+    Token: sync::DynSend + sync::DynSync,
+    Spacing: sync::DynSend + sync::DynSync,
+    DelimSpan: sync::DynSend + sync::DynSync,
+    Delimiter: sync::DynSend + sync::DynSync,
+    TokenStream: sync::DynSend + sync::DynSync,
 {
 }
 
@@ -118,7 +119,7 @@ where
     }
 }
 
-pub trait ToAttrTokenStream: sync::Send + sync::Sync {
+pub trait ToAttrTokenStream: sync::DynSend + sync::DynSync {
     fn to_attr_token_stream(&self) -> AttrTokenStream;
 }
 
@@ -550,6 +551,10 @@ impl TokenStream {
             vec_mut.extend(stream_iter);
         }
     }
+
+    pub fn chunks(&self, chunk_size: usize) -> core::slice::Chunks<'_, TokenTree> {
+        self.0.chunks(chunk_size)
+    }
 }
 
 /// By-reference iterator over a [`TokenStream`], that produces `&TokenTree`
diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs
index 3d154a93fb2..08ee3761bac 100644
--- a/compiler/rustc_ast_lowering/src/item.rs
+++ b/compiler/rustc_ast_lowering/src/item.rs
@@ -305,7 +305,10 @@ impl<'hir> LoweringContext<'_, 'hir> {
                             );
                             this.arena.alloc(this.ty(span, hir::TyKind::Err(guar)))
                         }
-                        Some(ty) => this.lower_ty(ty, &ImplTraitContext::TypeAliasesOpaqueTy),
+                        Some(ty) => this.lower_ty(
+                            ty,
+                            &ImplTraitContext::TypeAliasesOpaqueTy { in_assoc_ty: false },
+                        ),
                     },
                 );
                 hir::ItemKind::TyAlias(ty, generics)
@@ -852,7 +855,10 @@ impl<'hir> LoweringContext<'_, 'hir> {
                             hir::ImplItemKind::Type(ty)
                         }
                         Some(ty) => {
-                            let ty = this.lower_ty(ty, &ImplTraitContext::TypeAliasesOpaqueTy);
+                            let ty = this.lower_ty(
+                                ty,
+                                &ImplTraitContext::TypeAliasesOpaqueTy { in_assoc_ty: true },
+                            );
                             hir::ImplItemKind::Type(ty)
                         }
                     },
diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs
index 1fd7cc66470..211f5cb0a2a 100644
--- a/compiler/rustc_ast_lowering/src/lib.rs
+++ b/compiler/rustc_ast_lowering/src/lib.rs
@@ -58,7 +58,7 @@ use rustc_errors::{
 use rustc_fluent_macro::fluent_messages;
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, LifetimeRes, Namespace, PartialRes, PerNS, Res};
-use rustc_hir::def_id::{LocalDefId, CRATE_DEF_ID};
+use rustc_hir::def_id::{LocalDefId, CRATE_DEF_ID, LOCAL_CRATE};
 use rustc_hir::definitions::DefPathData;
 use rustc_hir::{ConstArg, GenericArg, ItemLocalId, ParamName, TraitCandidate};
 use rustc_index::{Idx, IndexSlice, IndexVec};
@@ -247,7 +247,7 @@ enum ImplTraitContext {
         in_trait: bool,
     },
     /// Impl trait in type aliases.
-    TypeAliasesOpaqueTy,
+    TypeAliasesOpaqueTy { in_assoc_ty: bool },
     /// `impl Trait` is unstably accepted in this position.
     FeatureGated(ImplTraitPosition, Symbol),
     /// `impl Trait` is not accepted in this position.
@@ -435,6 +435,7 @@ pub fn lower_to_hir(tcx: TyCtxt<'_>, (): ()) -> hir::Crate<'_> {
     // Queries that borrow `resolver_for_lowering`.
     tcx.ensure_with_value().output_filenames(());
     tcx.ensure_with_value().early_lint_checks(());
+    tcx.ensure_with_value().debugger_visualizers(LOCAL_CRATE);
     let (mut resolver, krate) = tcx.resolver_for_lowering(()).steal();
 
     let ast_index = index_crate(&resolver.node_id_to_def_id, &krate);
@@ -1407,14 +1408,15 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                             *in_trait,
                             itctx,
                         ),
-                    ImplTraitContext::TypeAliasesOpaqueTy => self.lower_opaque_impl_trait(
-                        span,
-                        hir::OpaqueTyOrigin::TyAlias,
-                        *def_node_id,
-                        bounds,
-                        false,
-                        itctx,
-                    ),
+                    &ImplTraitContext::TypeAliasesOpaqueTy { in_assoc_ty } => self
+                        .lower_opaque_impl_trait(
+                            span,
+                            hir::OpaqueTyOrigin::TyAlias { in_assoc_ty },
+                            *def_node_id,
+                            bounds,
+                            false,
+                            itctx,
+                        ),
                     ImplTraitContext::Universal => {
                         let span = t.span;
                         self.create_def(
@@ -1534,13 +1536,16 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         // If this came from a TAIT (as opposed to a function that returns an RPIT), we only want
         // to capture the lifetimes that appear in the bounds. So visit the bounds to find out
         // exactly which ones those are.
-        let lifetimes_to_remap = if origin == hir::OpaqueTyOrigin::TyAlias {
-            // in a TAIT like `type Foo<'a> = impl Foo<'a>`, we don't keep all the lifetime parameters
-            Vec::new()
-        } else {
-            // in fn return position, like the `fn test<'a>() -> impl Debug + 'a` example,
-            // we only keep the lifetimes that appear in the `impl Debug` itself:
-            lifetime_collector::lifetimes_in_bounds(&self.resolver, bounds)
+        let lifetimes_to_remap = match origin {
+            hir::OpaqueTyOrigin::TyAlias { .. } => {
+                // in a TAIT like `type Foo<'a> = impl Foo<'a>`, we don't keep all the lifetime parameters
+                Vec::new()
+            }
+            hir::OpaqueTyOrigin::AsyncFn(..) | hir::OpaqueTyOrigin::FnReturn(..) => {
+                // in fn return position, like the `fn test<'a>() -> impl Debug + 'a` example,
+                // we only keep the lifetimes that appear in the `impl Debug` itself:
+                lifetime_collector::lifetimes_in_bounds(&self.resolver, bounds)
+            }
         };
         debug!(?lifetimes_to_remap);
 
diff --git a/compiler/rustc_attr/src/builtin.rs b/compiler/rustc_attr/src/builtin.rs
index 2a3092d3c7b..372a58857f3 100644
--- a/compiler/rustc_attr/src/builtin.rs
+++ b/compiler/rustc_attr/src/builtin.rs
@@ -23,8 +23,7 @@ use crate::session_diagnostics::{self, IncorrectReprFormatGenericCause};
 pub const VERSION_PLACEHOLDER: &str = "CURRENT_RUSTC_VERSION";
 
 pub fn rust_version_symbol() -> Symbol {
-    let version = option_env!("CFG_VERSION").unwrap_or("<current>");
-    let version = version.split(' ').next().unwrap();
+    let version = option_env!("CFG_RELEASE").unwrap_or("<current>");
     Symbol::intern(&version)
 }
 
diff --git a/compiler/rustc_borrowck/src/dataflow.rs b/compiler/rustc_borrowck/src/dataflow.rs
index 94939c7e4cd..167f245361a 100644
--- a/compiler/rustc_borrowck/src/dataflow.rs
+++ b/compiler/rustc_borrowck/src/dataflow.rs
@@ -328,7 +328,7 @@ impl<'tcx> rustc_mir_dataflow::AnalysisDomain<'tcx> for Borrows<'_, 'tcx> {
 
     fn bottom_value(&self, _: &mir::Body<'tcx>) -> Self::Domain {
         // bottom = nothing is reserved or activated yet;
-        BitSet::new_empty(self.borrow_set.len() * 2)
+        BitSet::new_empty(self.borrow_set.len())
     }
 
     fn initialize_start_block(&self, _: &mir::Body<'tcx>, _: &mut Self::Domain) {
diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs
index 315303b25fe..eb25d454339 100644
--- a/compiler/rustc_borrowck/src/lib.rs
+++ b/compiler/rustc_borrowck/src/lib.rs
@@ -35,7 +35,7 @@ use rustc_middle::mir::{
 use rustc_middle::mir::{AggregateKind, BasicBlock, BorrowCheckResult, BorrowKind};
 use rustc_middle::mir::{InlineAsmOperand, Terminator, TerminatorKind};
 use rustc_middle::mir::{ProjectionElem, Promoted, Rvalue, Statement, StatementKind};
-use rustc_middle::ty::query::Providers;
+use rustc_middle::query::Providers;
 use rustc_middle::ty::{self, CapturedPlace, ParamEnv, RegionVid, TyCtxt};
 use rustc_session::lint::builtin::UNUSED_MUT;
 use rustc_span::{Span, Symbol};
diff --git a/compiler/rustc_borrowck/src/nll.rs b/compiler/rustc_borrowck/src/nll.rs
index a4394ddc01c..b6ccf924a5c 100644
--- a/compiler/rustc_borrowck/src/nll.rs
+++ b/compiler/rustc_borrowck/src/nll.rs
@@ -430,7 +430,7 @@ pub(super) fn dump_annotation<'tcx>(
 fn for_each_region_constraint<'tcx>(
     tcx: TyCtxt<'tcx>,
     closure_region_requirements: &ClosureRegionRequirements<'tcx>,
-    with_msg: &mut dyn FnMut(&str) -> io::Result<()>,
+    with_msg: &mut dyn FnMut(String) -> io::Result<()>,
 ) -> io::Result<()> {
     for req in &closure_region_requirements.outlives_requirements {
         let subject = match req.subject {
@@ -439,7 +439,7 @@ fn for_each_region_constraint<'tcx>(
                 format!("{:?}", ty.instantiate(tcx, |vid| tcx.mk_re_var(vid)))
             }
         };
-        with_msg(&format!("where {}: {:?}", subject, req.outlived_free_region,))?;
+        with_msg(format!("where {}: {:?}", subject, req.outlived_free_region,))?;
     }
     Ok(())
 }
diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
index 4970ece5e7d..309f23d9226 100644
--- a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
+++ b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
@@ -265,7 +265,7 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
 
         // Only check this for TAIT. RPIT already supports `tests/ui/impl-trait/nested-return-type2.rs`
         // on stable and we'd break that.
-        let OpaqueTyOrigin::TyAlias = origin else {
+        let OpaqueTyOrigin::TyAlias { .. } = origin else {
             return definition_ty;
         };
         let def_id = opaque_type_key.def_id;
@@ -360,7 +360,7 @@ fn check_opaque_type_parameter_valid(
         // which would error here on all of the `'static` args.
         OpaqueTyOrigin::FnReturn(..) | OpaqueTyOrigin::AsyncFn(..) => return Ok(()),
         // Check these
-        OpaqueTyOrigin::TyAlias => {}
+        OpaqueTyOrigin::TyAlias { .. } => {}
     }
     let opaque_generics = tcx.generics_of(opaque_type_key.def_id);
     let mut seen_params: FxIndexMap<_, Vec<_>> = FxIndexMap::default();
diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs
index 33b24b68f7c..fa4bc926f27 100644
--- a/compiler/rustc_borrowck/src/type_check/mod.rs
+++ b/compiler/rustc_borrowck/src/type_check/mod.rs
@@ -71,7 +71,7 @@ macro_rules! span_mirbug {
         $crate::type_check::mirbug(
             $context.tcx(),
             $context.last_span,
-            &format!(
+            format!(
                 "broken MIR in {:?} ({:?}): {}",
                 $context.body().source.def_id(),
                 $elem,
@@ -274,7 +274,7 @@ fn translate_outlives_facts(typeck: &mut TypeChecker<'_, '_>) {
 }
 
 #[track_caller]
-fn mirbug(tcx: TyCtxt<'_>, span: Span, msg: &str) {
+fn mirbug(tcx: TyCtxt<'_>, span: Span, msg: String) {
     // We sometimes see MIR failures (notably predicate failures) due to
     // the fact that we check rvalue sized predicates here. So use `delay_span_bug`
     // to avoid reporting bugs in those cases.
diff --git a/compiler/rustc_builtin_macros/src/asm.rs b/compiler/rustc_builtin_macros/src/asm.rs
index bb059a120df..5217e317adf 100644
--- a/compiler/rustc_builtin_macros/src/asm.rs
+++ b/compiler/rustc_builtin_macros/src/asm.rs
@@ -550,7 +550,7 @@ fn expand_preparsed_asm(ecx: &mut ExtCtxt<'_>, args: AsmArgs) -> Option<ast::Inl
         if !parser.errors.is_empty() {
             let err = parser.errors.remove(0);
             let err_sp = template_span.from_inner(InnerSpan::new(err.span.start, err.span.end));
-            let msg = &format!("invalid asm template string: {}", err.description);
+            let msg = format!("invalid asm template string: {}", err.description);
             let mut e = ecx.struct_span_err(err_sp, msg);
             e.span_label(err_sp, err.label + " in asm template string");
             if let Some(note) = err.note {
@@ -585,7 +585,7 @@ fn expand_preparsed_asm(ecx: &mut ExtCtxt<'_>, args: AsmArgs) -> Option<ast::Inl
                                 || args.reg_args.contains(idx)
                             {
                                 let msg = format!("invalid reference to argument at index {}", idx);
-                                let mut err = ecx.struct_span_err(span, &msg);
+                                let mut err = ecx.struct_span_err(span, msg);
                                 err.span_label(span, "from here");
 
                                 let positional_args = args.operands.len()
@@ -638,7 +638,7 @@ fn expand_preparsed_asm(ecx: &mut ExtCtxt<'_>, args: AsmArgs) -> Option<ast::Inl
                                     ecx.struct_span_err(
                                         template_span
                                             .from_inner(InnerSpan::new(span.start, span.end)),
-                                        &msg,
+                                        msg,
                                     )
                                     .emit();
                                     None
diff --git a/compiler/rustc_builtin_macros/src/cfg_eval.rs b/compiler/rustc_builtin_macros/src/cfg_eval.rs
index 750f1fe121f..ed91cea4ae2 100644
--- a/compiler/rustc_builtin_macros/src/cfg_eval.rs
+++ b/compiler/rustc_builtin_macros/src/cfg_eval.rs
@@ -166,7 +166,9 @@ impl CfgEval<'_, '_> {
                     ))
                 },
                 Annotatable::Stmt(_) => |parser| {
-                    Ok(Annotatable::Stmt(P(parser.parse_stmt(ForceCollect::Yes)?.unwrap())))
+                    Ok(Annotatable::Stmt(P(parser
+                        .parse_stmt_without_recovery(false, ForceCollect::Yes)?
+                        .unwrap())))
                 },
                 Annotatable::Expr(_) => {
                     |parser| Ok(Annotatable::Expr(parser.parse_expr_force_collect()?))
diff --git a/compiler/rustc_builtin_macros/src/deriving/bounds.rs b/compiler/rustc_builtin_macros/src/deriving/bounds.rs
index 0481a118906..2c8e6f99c67 100644
--- a/compiler/rustc_builtin_macros/src/deriving/bounds.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/bounds.rs
@@ -27,3 +27,26 @@ pub fn expand_deriving_copy(
 
     trait_def.expand(cx, mitem, item, push);
 }
+
+pub fn expand_deriving_const_param_ty(
+    cx: &mut ExtCtxt<'_>,
+    span: Span,
+    mitem: &MetaItem,
+    item: &Annotatable,
+    push: &mut dyn FnMut(Annotatable),
+    is_const: bool,
+) {
+    let trait_def = TraitDef {
+        span,
+        path: path_std!(marker::ConstParamTy),
+        skip_path_as_bound: false,
+        needs_copy_as_bound_if_packed: false,
+        additional_bounds: Vec::new(),
+        supports_unions: false,
+        methods: Vec::new(),
+        associated_types: Vec::new(),
+        is_const,
+    };
+
+    trait_def.expand(cx, mitem, item, push);
+}
diff --git a/compiler/rustc_builtin_macros/src/deriving/clone.rs b/compiler/rustc_builtin_macros/src/deriving/clone.rs
index dfee2d3ce77..9883563746e 100644
--- a/compiler/rustc_builtin_macros/src/deriving/clone.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/clone.rs
@@ -145,7 +145,7 @@ fn cs_clone_simple(
             }
             _ => cx.span_bug(
                 trait_span,
-                &format!("unexpected substructure in simple `derive({})`", name),
+                format!("unexpected substructure in simple `derive({})`", name),
             ),
         }
     }
@@ -179,10 +179,10 @@ fn cs_clone(
             vdata = &variant.data;
         }
         EnumTag(..) | AllFieldlessEnum(..) => {
-            cx.span_bug(trait_span, &format!("enum tags in `derive({})`", name,))
+            cx.span_bug(trait_span, format!("enum tags in `derive({})`", name,))
         }
         StaticEnum(..) | StaticStruct(..) => {
-            cx.span_bug(trait_span, &format!("associated function in `derive({})`", name))
+            cx.span_bug(trait_span, format!("associated function in `derive({})`", name))
         }
     }
 
@@ -194,7 +194,7 @@ fn cs_clone(
                     let Some(ident) = field.name else {
                         cx.span_bug(
                             trait_span,
-                            &format!("unnamed field in normal struct in `derive({})`", name,),
+                            format!("unnamed field in normal struct in `derive({})`", name,),
                         );
                     };
                     let call = subcall(cx, field);
diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs
index caced3d6447..4ba09335cb7 100644
--- a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs
@@ -1591,7 +1591,7 @@ impl<'a> TraitDef<'a> {
                                 BYTE_SLICE_IN_PACKED_STRUCT_WITH_DERIVE,
                                 sp,
                                 ast::CRATE_NODE_ID,
-                                &format!(
+                                format!(
                                     "{} slice in a packed struct that derives a built-in trait",
                                     ty
                                 ),
diff --git a/compiler/rustc_builtin_macros/src/env.rs b/compiler/rustc_builtin_macros/src/env.rs
index 58c972738c4..8f64e332861 100644
--- a/compiler/rustc_builtin_macros/src/env.rs
+++ b/compiler/rustc_builtin_macros/src/env.rs
@@ -63,7 +63,8 @@ pub fn expand_env<'cx>(
         Some(exprs) => exprs.into_iter(),
     };
 
-    let Some((var, _style)) = expr_to_string(cx, exprs.next().unwrap(), "expected string literal") else {
+    let var_expr = exprs.next().unwrap();
+    let Some((var, _)) = expr_to_string(cx, var_expr.clone(), "expected string literal") else {
         return DummyResult::any(sp);
     };
 
@@ -71,7 +72,7 @@ pub fn expand_env<'cx>(
         None => None,
         Some(second) => match expr_to_string(cx, second, "expected string literal") {
             None => return DummyResult::any(sp),
-            Some((s, _style)) => Some(s),
+            Some((s, _)) => Some(s),
         },
     };
 
@@ -80,10 +81,15 @@ pub fn expand_env<'cx>(
     cx.sess.parse_sess.env_depinfo.borrow_mut().insert((var, value));
     let e = match value {
         None => {
+            // Use the string literal in the code in the diagnostic to avoid confusing diagnostics,
+            // e.g. when the literal contains escape sequences.
+            let ast::ExprKind::Lit(ast::token::Lit { kind: ast::token::LitKind::Str, symbol: original_var, ..}) = &var_expr.kind else {
+                unreachable!("`expr_to_string` ensures this is a string lit")
+            };
             cx.emit_err(errors::EnvNotDefined {
                 span: sp,
                 msg: custom_msg,
-                var,
+                var: *original_var,
                 help: custom_msg.is_none().then(|| help_for_missing_env_var(var.as_str())),
             });
             return DummyResult::any(sp);
diff --git a/compiler/rustc_builtin_macros/src/format.rs b/compiler/rustc_builtin_macros/src/format.rs
index adc12ec84f5..c59a733c055 100644
--- a/compiler/rustc_builtin_macros/src/format.rs
+++ b/compiler/rustc_builtin_macros/src/format.rs
@@ -814,7 +814,7 @@ fn report_invalid_references(
         };
         e = ecx.struct_span_err(
             span,
-            &format!("invalid reference to positional {} ({})", arg_list, num_args_desc),
+            format!("invalid reference to positional {} ({})", arg_list, num_args_desc),
         );
         e.note("positional arguments are zero-based");
     }
diff --git a/compiler/rustc_builtin_macros/src/format_foreign.rs b/compiler/rustc_builtin_macros/src/format_foreign.rs
index bd9e903b6ba..bd5356575ca 100644
--- a/compiler/rustc_builtin_macros/src/format_foreign.rs
+++ b/compiler/rustc_builtin_macros/src/format_foreign.rs
@@ -562,15 +562,13 @@ pub(crate) mod printf {
         }
 
         if let Type = state {
-            drop(c);
             type_ = at.slice_between(next).unwrap();
 
             // Don't use `move_to!` here, as we *can* be at the end of the input.
             at = next;
         }
 
-        drop(c);
-        drop(next);
+        let _ = c; // to avoid never used value
 
         end = at;
         let position = InnerSpan::new(start.at, end.at);
diff --git a/compiler/rustc_builtin_macros/src/lib.rs b/compiler/rustc_builtin_macros/src/lib.rs
index 4e5edb4d6b1..ebf1448f55c 100644
--- a/compiler/rustc_builtin_macros/src/lib.rs
+++ b/compiler/rustc_builtin_macros/src/lib.rs
@@ -115,6 +115,7 @@ pub fn register_builtin_macros(resolver: &mut dyn ResolverExpand) {
     register_derive! {
         Clone: clone::expand_deriving_clone,
         Copy: bounds::expand_deriving_copy,
+        ConstParamTy: bounds::expand_deriving_const_param_ty,
         Debug: debug::expand_deriving_debug,
         Default: default::expand_deriving_default,
         Eq: eq::expand_deriving_eq,
diff --git a/compiler/rustc_builtin_macros/src/source_util.rs b/compiler/rustc_builtin_macros/src/source_util.rs
index b8a24f1102d..e613b904d2e 100644
--- a/compiler/rustc_builtin_macros/src/source_util.rs
+++ b/compiler/rustc_builtin_macros/src/source_util.rs
@@ -188,12 +188,12 @@ pub fn expand_include_str(
                 base::MacEager::expr(cx.expr_str(sp, interned_src))
             }
             Err(_) => {
-                cx.span_err(sp, &format!("{} wasn't a utf-8 file", file.display()));
+                cx.span_err(sp, format!("{} wasn't a utf-8 file", file.display()));
                 DummyResult::any(sp)
             }
         },
         Err(e) => {
-            cx.span_err(sp, &format!("couldn't read {}: {}", file.display(), e));
+            cx.span_err(sp, format!("couldn't read {}: {}", file.display(), e));
             DummyResult::any(sp)
         }
     }
@@ -221,7 +221,7 @@ pub fn expand_include_bytes(
             base::MacEager::expr(expr)
         }
         Err(e) => {
-            cx.span_err(sp, &format!("couldn't read {}: {}", file.display(), e));
+            cx.span_err(sp, format!("couldn't read {}: {}", file.display(), e));
             DummyResult::any(sp)
         }
     }
diff --git a/compiler/rustc_codegen_cranelift/src/base.rs b/compiler/rustc_codegen_cranelift/src/base.rs
index e9dbea1be67..25fd5ca3ae8 100644
--- a/compiler/rustc_codegen_cranelift/src/base.rs
+++ b/compiler/rustc_codegen_cranelift/src/base.rs
@@ -966,11 +966,7 @@ fn codegen_panic_inner<'tcx>(
     args: &[Value],
     span: Span,
 ) {
-    let def_id = fx
-        .tcx
-        .lang_items()
-        .require(lang_item)
-        .unwrap_or_else(|e| fx.tcx.sess.span_fatal(span, e.to_string()));
+    let def_id = fx.tcx.require_lang_item(lang_item, Some(span));
 
     let instance = Instance::mono(fx.tcx, def_id).polymorphize(fx.tcx);
     let symbol_name = fx.tcx.symbol_name(instance).name;
diff --git a/compiler/rustc_codegen_cranelift/src/pretty_clif.rs b/compiler/rustc_codegen_cranelift/src/pretty_clif.rs
index 27e21183c55..1007b33eca4 100644
--- a/compiler/rustc_codegen_cranelift/src/pretty_clif.rs
+++ b/compiler/rustc_codegen_cranelift/src/pretty_clif.rs
@@ -227,7 +227,7 @@ pub(crate) fn write_ir_file(
         // Using early_warn as no Session is available here
         rustc_session::early_warn(
             rustc_session::config::ErrorOutputType::default(),
-            &format!("error writing ir file: {}", err),
+            format!("error writing ir file: {}", err),
         );
     }
 }
diff --git a/compiler/rustc_codegen_gcc/src/lib.rs b/compiler/rustc_codegen_gcc/src/lib.rs
index 1cabb05de97..442ce0ea542 100644
--- a/compiler/rustc_codegen_gcc/src/lib.rs
+++ b/compiler/rustc_codegen_gcc/src/lib.rs
@@ -80,8 +80,8 @@ use rustc_errors::{DiagnosticMessage, ErrorGuaranteed, Handler, SubdiagnosticMes
 use rustc_fluent_macro::fluent_messages;
 use rustc_metadata::EncodedMetadata;
 use rustc_middle::dep_graph::{WorkProduct, WorkProductId};
+use rustc_middle::query::Providers;
 use rustc_middle::ty::TyCtxt;
-use rustc_middle::ty::query::Providers;
 use rustc_session::config::{Lto, OptLevel, OutputFilenames};
 use rustc_session::Session;
 use rustc_span::Symbol;
diff --git a/compiler/rustc_codegen_llvm/Cargo.toml b/compiler/rustc_codegen_llvm/Cargo.toml
index 5e750d91b82..ad51f2d0958 100644
--- a/compiler/rustc_codegen_llvm/Cargo.toml
+++ b/compiler/rustc_codegen_llvm/Cargo.toml
@@ -11,7 +11,7 @@ bitflags = "1.0"
 cstr = "0.2"
 libc = "0.2"
 measureme = "10.0.0"
-object = { version = "0.30.1", default-features = false, features = [
+object = { version = "0.31.1", default-features = false, features = [
     "std",
     "read",
 ] }
diff --git a/compiler/rustc_codegen_llvm/src/back/lto.rs b/compiler/rustc_codegen_llvm/src/back/lto.rs
index d2e01708a37..604f68eb6a4 100644
--- a/compiler/rustc_codegen_llvm/src/back/lto.rs
+++ b/compiler/rustc_codegen_llvm/src/back/lto.rs
@@ -25,7 +25,6 @@ use std::fs::File;
 use std::io;
 use std::iter;
 use std::path::Path;
-use std::ptr;
 use std::slice;
 use std::sync::Arc;
 
@@ -709,17 +708,6 @@ pub unsafe fn optimize_thin_module(
         let llmod = module.module_llvm.llmod();
         save_temp_bitcode(cgcx, &module, "thin-lto-input");
 
-        // Before we do much else find the "main" `DICompileUnit` that we'll be
-        // using below. If we find more than one though then rustc has changed
-        // in a way we're not ready for, so generate an ICE by returning
-        // an error.
-        let mut cu1 = ptr::null_mut();
-        let mut cu2 = ptr::null_mut();
-        llvm::LLVMRustThinLTOGetDICompileUnit(llmod, &mut cu1, &mut cu2);
-        if !cu2.is_null() {
-            return Err(write::llvm_err(&diag_handler, LlvmError::MultipleSourceDiCompileUnit));
-        }
-
         // Up next comes the per-module local analyses that we do for Thin LTO.
         // Each of these functions is basically copied from the LLVM
         // implementation and then tailored to suit this implementation. Ideally
@@ -766,43 +754,6 @@ pub unsafe fn optimize_thin_module(
             save_temp_bitcode(cgcx, &module, "thin-lto-after-import");
         }
 
-        // Ok now this is a bit unfortunate. This is also something you won't
-        // find upstream in LLVM's ThinLTO passes! This is a hack for now to
-        // work around bugs in LLVM.
-        //
-        // First discovered in #45511 it was found that as part of ThinLTO
-        // importing passes LLVM will import `DICompileUnit` metadata
-        // information across modules. This means that we'll be working with one
-        // LLVM module that has multiple `DICompileUnit` instances in it (a
-        // bunch of `llvm.dbg.cu` members). Unfortunately there's a number of
-        // bugs in LLVM's backend which generates invalid DWARF in a situation
-        // like this:
-        //
-        //  https://bugs.llvm.org/show_bug.cgi?id=35212
-        //  https://bugs.llvm.org/show_bug.cgi?id=35562
-        //
-        // While the first bug there is fixed the second ended up causing #46346
-        // which was basically a resurgence of #45511 after LLVM's bug 35212 was
-        // fixed.
-        //
-        // This function below is a huge hack around this problem. The function
-        // below is defined in `PassWrapper.cpp` and will basically "merge"
-        // all `DICompileUnit` instances in a module. Basically it'll take all
-        // the objects, rewrite all pointers of `DISubprogram` to point to the
-        // first `DICompileUnit`, and then delete all the other units.
-        //
-        // This is probably mangling to the debug info slightly (but hopefully
-        // not too much) but for now at least gets LLVM to emit valid DWARF (or
-        // so it appears). Hopefully we can remove this once upstream bugs are
-        // fixed in LLVM.
-        {
-            let _timer = cgcx
-                .prof
-                .generic_activity_with_arg("LLVM_thin_lto_patch_debuginfo", thin_module.name());
-            llvm::LLVMRustThinLTOPatchDICompileUnit(llmod, cu1);
-            save_temp_bitcode(cgcx, &module, "thin-lto-after-patch");
-        }
-
         // Alright now that we've done everything related to the ThinLTO
         // analysis it's time to run some optimizations! Here we use the same
         // `run_pass_manager` as the "fat" LTO above except that we tell it to
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs b/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs
index aaf5dbd9930..37f30917609 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs
@@ -9,10 +9,9 @@ use rustc_ast::attr;
 use rustc_codegen_ssa::base::collect_debugger_visualizers_transitive;
 use rustc_codegen_ssa::traits::*;
 use rustc_hir::def_id::LOCAL_CRATE;
-use rustc_middle::bug;
+use rustc_middle::{bug, middle::debugger_visualizer::DebuggerVisualizerType};
 use rustc_session::config::{CrateType, DebugInfo};
 use rustc_span::symbol::sym;
-use rustc_span::DebuggerVisualizerType;
 
 /// Inserts a side-effect free instruction sequence that makes sure that the
 /// .debug_gdb_scripts global is referenced, so it isn't removed by the linker.
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
index 25fe3cb265d..bd2fba12602 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
@@ -806,8 +806,7 @@ pub fn build_compile_unit_di_node<'ll, 'tcx>(
     name_in_debuginfo.push(codegen_unit_name);
 
     debug!("build_compile_unit_di_node: {:?}", name_in_debuginfo);
-    let rustc_producer =
-        format!("rustc version {}", option_env!("CFG_VERSION").expect("CFG_VERSION"),);
+    let rustc_producer = format!("rustc version {}", tcx.sess.cfg_version);
     // FIXME(#41252) Remove "clang LLVM" if we can get GDB and LLVM to play nice.
     let producer = format!("clang LLVM ({})", rustc_producer);
 
diff --git a/compiler/rustc_codegen_llvm/src/lib.rs b/compiler/rustc_codegen_llvm/src/lib.rs
index 8305a0a4c28..6a86237d79e 100644
--- a/compiler/rustc_codegen_llvm/src/lib.rs
+++ b/compiler/rustc_codegen_llvm/src/lib.rs
@@ -37,7 +37,7 @@ use rustc_errors::{DiagnosticMessage, ErrorGuaranteed, FatalError, Handler, Subd
 use rustc_fluent_macro::fluent_messages;
 use rustc_metadata::EncodedMetadata;
 use rustc_middle::dep_graph::{WorkProduct, WorkProductId};
-use rustc_middle::ty::query::Providers;
+use rustc_middle::query::Providers;
 use rustc_middle::ty::TyCtxt;
 use rustc_session::config::{OptLevel, OutputFilenames, PrintRequest};
 use rustc_session::Session;
diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
index aefd5b2a13c..de93a64c0d6 100644
--- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
@@ -2484,12 +2484,6 @@ extern "C" {
         len: usize,
         out_len: &mut usize,
     ) -> *const u8;
-    pub fn LLVMRustThinLTOGetDICompileUnit(
-        M: &Module,
-        CU1: &mut *mut c_void,
-        CU2: &mut *mut c_void,
-    );
-    pub fn LLVMRustThinLTOPatchDICompileUnit(M: &Module, CU: *mut c_void);
 
     pub fn LLVMRustLinkerNew(M: &Module) -> &mut Linker<'_>;
     pub fn LLVMRustLinkerAdd(
diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs
index 2fbdab9f8ce..994addf12eb 100644
--- a/compiler/rustc_codegen_llvm/src/llvm_util.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs
@@ -155,12 +155,6 @@ pub fn to_llvm_features<'a>(sess: &Session, s: &'a str) -> SmallVec<[&'a str; 2]
         ("x86", "rdrand") => smallvec!["rdrnd"],
         ("x86", "bmi1") => smallvec!["bmi"],
         ("x86", "cmpxchg16b") => smallvec!["cx16"],
-        // FIXME: These aliases are misleading, and should be removed before avx512_target_feature is
-        // stabilized. They must remain until std::arch switches off them.
-        // rust#100752
-        ("x86", "avx512vaes") => smallvec!["vaes"],
-        ("x86", "avx512gfni") => smallvec!["gfni"],
-        ("x86", "avx512vpclmulqdq") => smallvec!["vpclmulqdq"],
         ("aarch64", "rcpc2") => smallvec!["rcpc-immo"],
         ("aarch64", "dpb") => smallvec!["ccpp"],
         ("aarch64", "dpb2") => smallvec!["ccdp"],
diff --git a/compiler/rustc_codegen_ssa/Cargo.toml b/compiler/rustc_codegen_ssa/Cargo.toml
index 02be88df103..0ac12d32be5 100644
--- a/compiler/rustc_codegen_ssa/Cargo.toml
+++ b/compiler/rustc_codegen_ssa/Cargo.toml
@@ -14,7 +14,7 @@ itertools = "0.10.1"
 tracing = "0.1"
 jobserver = "0.1.22"
 tempfile = "3.2"
-thorin-dwp = "0.4"
+thorin-dwp = "0.6"
 pathdiff = "0.2.0"
 serde_json = "1.0.59"
 snap = "1"
@@ -46,7 +46,7 @@ rustc_session = { path = "../rustc_session" }
 libc = "0.2.50"
 
 [dependencies.object]
-version = "0.30.1"
+version = "0.31.1"
 default-features = false
 features = ["read_core", "elf", "macho", "pe", "unaligned", "archive", "write"]
 
diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs
index ea06cb02d8b..8a00c42a0e8 100644
--- a/compiler/rustc_codegen_ssa/src/back/link.rs
+++ b/compiler/rustc_codegen_ssa/src/back/link.rs
@@ -9,6 +9,7 @@ use rustc_fs_util::fix_windows_verbatim_for_gcc;
 use rustc_hir::def_id::{CrateNum, LOCAL_CRATE};
 use rustc_metadata::find_native_static_library;
 use rustc_metadata::fs::{emit_wrapper_file, METADATA_FILENAME};
+use rustc_middle::middle::debugger_visualizer::DebuggerVisualizerFile;
 use rustc_middle::middle::dependency_format::Linkage;
 use rustc_middle::middle::exported_symbols::SymbolExportKind;
 use rustc_session::config::{self, CFGuard, CrateType, DebugInfo, LdImpl, Strip};
@@ -21,7 +22,6 @@ use rustc_session::utils::NativeLibKind;
 /// need out of the shared crate context before we get rid of it.
 use rustc_session::{filesearch, Session};
 use rustc_span::symbol::Symbol;
-use rustc_span::DebuggerVisualizerFile;
 use rustc_target::spec::crt_objects::{CrtObjects, LinkSelfContainedDefault};
 use rustc_target::spec::{Cc, LinkOutputKind, LinkerFlavor, LinkerFlavorCli, Lld, PanicStrategy};
 use rustc_target::spec::{RelocModel, RelroLevel, SanitizerSet, SplitDebuginfo};
@@ -574,6 +574,8 @@ fn link_staticlib<'a>(
         }
     }
 
+    all_native_libs.extend_from_slice(&codegen_results.crate_info.used_libraries);
+
     if sess.opts.prints.contains(&PrintRequest::NativeStaticLibs) {
         print_native_static_libs(sess, &all_native_libs, &all_rust_dylibs);
     }
diff --git a/compiler/rustc_codegen_ssa/src/back/metadata.rs b/compiler/rustc_codegen_ssa/src/back/metadata.rs
index 8968133bac5..8bf84772f08 100644
--- a/compiler/rustc_codegen_ssa/src/back/metadata.rs
+++ b/compiler/rustc_codegen_ssa/src/back/metadata.rs
@@ -14,8 +14,7 @@ use snap::write::FrameEncoder;
 
 use object::elf::NT_GNU_PROPERTY_TYPE_0;
 use rustc_data_structures::memmap::Mmap;
-use rustc_data_structures::owned_slice::try_slice_owned;
-use rustc_data_structures::sync::MetadataRef;
+use rustc_data_structures::owned_slice::{try_slice_owned, OwnedSlice};
 use rustc_metadata::fs::METADATA_FILENAME;
 use rustc_metadata::EncodedMetadata;
 use rustc_session::cstore::MetadataLoader;
@@ -39,7 +38,7 @@ pub struct DefaultMetadataLoader;
 fn load_metadata_with(
     path: &Path,
     f: impl for<'a> FnOnce(&'a [u8]) -> Result<&'a [u8], String>,
-) -> Result<MetadataRef, String> {
+) -> Result<OwnedSlice, String> {
     let file =
         File::open(path).map_err(|e| format!("failed to open file '{}': {}", path.display(), e))?;
 
@@ -49,7 +48,7 @@ fn load_metadata_with(
 }
 
 impl MetadataLoader for DefaultMetadataLoader {
-    fn get_rlib_metadata(&self, _target: &Target, path: &Path) -> Result<MetadataRef, String> {
+    fn get_rlib_metadata(&self, _target: &Target, path: &Path) -> Result<OwnedSlice, String> {
         load_metadata_with(path, |data| {
             let archive = object::read::archive::ArchiveFile::parse(&*data)
                 .map_err(|e| format!("failed to parse rlib '{}': {}", path.display(), e))?;
@@ -69,7 +68,7 @@ impl MetadataLoader for DefaultMetadataLoader {
         })
     }
 
-    fn get_dylib_metadata(&self, _target: &Target, path: &Path) -> Result<MetadataRef, String> {
+    fn get_dylib_metadata(&self, _target: &Target, path: &Path) -> Result<OwnedSlice, String> {
         load_metadata_with(path, |data| search_for_section(path, data, ".rustc"))
     }
 }
diff --git a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs
index 8f2f829c17c..14460efc1b0 100644
--- a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs
+++ b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs
@@ -11,7 +11,7 @@ use rustc_middle::middle::exported_symbols::{
     metadata_symbol_name, ExportedSymbol, SymbolExportInfo, SymbolExportKind, SymbolExportLevel,
 };
 use rustc_middle::query::LocalCrate;
-use rustc_middle::ty::query::{ExternProviders, Providers};
+use rustc_middle::query::{ExternProviders, Providers};
 use rustc_middle::ty::subst::{GenericArgKind, SubstsRef};
 use rustc_middle::ty::Instance;
 use rustc_middle::ty::{self, SymbolName, TyCtxt};
diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs
index ae45ae9d802..15c7847155d 100644
--- a/compiler/rustc_codegen_ssa/src/base.rs
+++ b/compiler/rustc_codegen_ssa/src/base.rs
@@ -17,28 +17,25 @@ use rustc_ast::expand::allocator::AllocatorKind;
 use rustc_attr as attr;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_data_structures::profiling::{get_resident_set_size, print_time_passes_entry};
-
-use rustc_data_structures::sync::par_iter;
-#[cfg(parallel_compiler)]
-use rustc_data_structures::sync::ParallelIterator;
+use rustc_data_structures::sync::par_map;
 use rustc_hir as hir;
 use rustc_hir::def_id::{DefId, LOCAL_CRATE};
 use rustc_hir::lang_items::LangItem;
 use rustc_metadata::EncodedMetadata;
 use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs;
+use rustc_middle::middle::debugger_visualizer::{DebuggerVisualizerFile, DebuggerVisualizerType};
 use rustc_middle::middle::exported_symbols;
 use rustc_middle::middle::exported_symbols::SymbolExportKind;
 use rustc_middle::middle::lang_items;
 use rustc_middle::mir::mono::{CodegenUnit, CodegenUnitNameBuilder, MonoItem};
+use rustc_middle::query::Providers;
 use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf, TyAndLayout};
-use rustc_middle::ty::query::Providers;
 use rustc_middle::ty::{self, Instance, Ty, TyCtxt};
 use rustc_session::cgu_reuse_tracker::CguReuse;
 use rustc_session::config::{self, CrateType, EntryFnType, OutputType};
 use rustc_session::Session;
 use rustc_span::symbol::sym;
 use rustc_span::Symbol;
-use rustc_span::{DebuggerVisualizerFile, DebuggerVisualizerType};
 use rustc_target::abi::{Align, FIRST_VARIANT};
 
 use std::collections::BTreeSet;
@@ -689,7 +686,7 @@ pub fn codegen_crate<B: ExtraBackendMethods>(
     // This likely is a temporary measure. Once we don't have to support the
     // non-parallel compiler anymore, we can compile CGUs end-to-end in
     // parallel and get rid of the complicated scheduling logic.
-    let mut pre_compiled_cgus = if cfg!(parallel_compiler) {
+    let mut pre_compiled_cgus = if tcx.sess.threads() > 1 {
         tcx.sess.time("compile_first_CGU_batch", || {
             // Try to find one CGU to compile per thread.
             let cgus: Vec<_> = cgu_reuse
@@ -702,12 +699,10 @@ pub fn codegen_crate<B: ExtraBackendMethods>(
             // Compile the found CGUs in parallel.
             let start_time = Instant::now();
 
-            let pre_compiled_cgus = par_iter(cgus)
-                .map(|(i, _)| {
-                    let module = backend.compile_codegen_unit(tcx, codegen_units[i].name());
-                    (i, module)
-                })
-                .collect();
+            let pre_compiled_cgus = par_map(cgus, |(i, _)| {
+                let module = backend.compile_codegen_unit(tcx, codegen_units[i].name());
+                (i, module)
+            });
 
             total_codegen_time += start_time.elapsed();
 
diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
index 8dae5dab429..d6c23012762 100644
--- a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
+++ b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
@@ -7,7 +7,7 @@ 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};
 use rustc_middle::mir::mono::Linkage;
-use rustc_middle::ty::query::Providers;
+use rustc_middle::query::Providers;
 use rustc_middle::ty::{self as ty, TyCtxt};
 use rustc_session::{lint, parse::feature_err};
 use rustc_span::symbol::Ident;
diff --git a/compiler/rustc_codegen_ssa/src/lib.rs b/compiler/rustc_codegen_ssa/src/lib.rs
index c3cc17c255b..31854c7f4c4 100644
--- a/compiler/rustc_codegen_ssa/src/lib.rs
+++ b/compiler/rustc_codegen_ssa/src/lib.rs
@@ -28,16 +28,17 @@ use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage};
 use rustc_fluent_macro::fluent_messages;
 use rustc_hir::def_id::CrateNum;
 use rustc_middle::dep_graph::WorkProduct;
+use rustc_middle::middle::debugger_visualizer::DebuggerVisualizerFile;
 use rustc_middle::middle::dependency_format::Dependencies;
 use rustc_middle::middle::exported_symbols::SymbolExportKind;
-use rustc_middle::ty::query::{ExternProviders, Providers};
+use rustc_middle::query::{ExternProviders, Providers};
 use rustc_serialize::opaque::{FileEncoder, MemDecoder};
 use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
 use rustc_session::config::{CrateType, OutputFilenames, OutputType, RUST_CGU_EXT};
 use rustc_session::cstore::{self, CrateSource};
 use rustc_session::utils::NativeLibKind;
+use rustc_session::Session;
 use rustc_span::symbol::Symbol;
-use rustc_span::DebuggerVisualizerFile;
 use std::collections::BTreeSet;
 use std::io;
 use std::path::{Path, PathBuf};
@@ -175,11 +176,11 @@ pub struct CodegenResults {
     pub crate_info: CrateInfo,
 }
 
-pub enum CodegenErrors<'a> {
+pub enum CodegenErrors {
     WrongFileType,
     EmptyVersionNumber,
     EncodingVersionMismatch { version_array: String, rlink_version: u32 },
-    RustcVersionMismatch { rustc_version: String, current_version: &'a str },
+    RustcVersionMismatch { rustc_version: String },
 }
 
 pub fn provide(providers: &mut Providers) {
@@ -213,10 +214,9 @@ pub fn looks_like_rust_object_file(filename: &str) -> bool {
 const RLINK_VERSION: u32 = 1;
 const RLINK_MAGIC: &[u8] = b"rustlink";
 
-const RUSTC_VERSION: Option<&str> = option_env!("CFG_VERSION");
-
 impl CodegenResults {
     pub fn serialize_rlink(
+        sess: &Session,
         rlink_file: &Path,
         codegen_results: &CodegenResults,
     ) -> Result<usize, io::Error> {
@@ -225,12 +225,12 @@ impl CodegenResults {
         // `emit_raw_bytes` is used to make sure that the version representation does not depend on
         // Encoder's inner representation of `u32`.
         encoder.emit_raw_bytes(&RLINK_VERSION.to_be_bytes());
-        encoder.emit_str(RUSTC_VERSION.unwrap());
+        encoder.emit_str(sess.cfg_version);
         Encodable::encode(codegen_results, &mut encoder);
         encoder.finish()
     }
 
-    pub fn deserialize_rlink<'a>(data: Vec<u8>) -> Result<Self, CodegenErrors<'a>> {
+    pub fn deserialize_rlink(sess: &Session, data: Vec<u8>) -> Result<Self, CodegenErrors> {
         // The Decodable machinery is not used here because it panics if the input data is invalid
         // and because its internal representation may change.
         if !data.starts_with(RLINK_MAGIC) {
@@ -252,11 +252,9 @@ impl CodegenResults {
 
         let mut decoder = MemDecoder::new(&data[4..], 0);
         let rustc_version = decoder.read_str();
-        let current_version = RUSTC_VERSION.unwrap();
-        if rustc_version != current_version {
+        if rustc_version != sess.cfg_version {
             return Err(CodegenErrors::RustcVersionMismatch {
                 rustc_version: rustc_version.to_string(),
-                current_version,
             });
         }
 
diff --git a/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs b/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs
index 4e5e2dd5d50..bba2800fb05 100644
--- a/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs
@@ -8,7 +8,7 @@ use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf};
 use rustc_session::config::DebugInfo;
 use rustc_span::symbol::{kw, Symbol};
 use rustc_span::{BytePos, Span};
-use rustc_target::abi::{Abi, FieldIdx, Size, VariantIdx};
+use rustc_target::abi::{Abi, FieldIdx, FieldsShape, Size, VariantIdx};
 
 use super::operand::{OperandRef, OperandValue};
 use super::place::PlaceRef;
@@ -41,6 +41,9 @@ pub struct PerLocalVarDebugInfo<'tcx, D> {
 
     /// `.place.projection` from `mir::VarDebugInfo`.
     pub projection: &'tcx ty::List<mir::PlaceElem<'tcx>>,
+
+    /// `references` from `mir::VarDebugInfo`.
+    pub references: u8,
 }
 
 #[derive(Clone, Copy, Debug)]
@@ -80,6 +83,7 @@ trait DebugInfoOffsetLocation<'tcx, Bx> {
     fn deref(&self, bx: &mut Bx) -> Self;
     fn layout(&self) -> TyAndLayout<'tcx>;
     fn project_field(&self, bx: &mut Bx, field: FieldIdx) -> Self;
+    fn project_constant_index(&self, bx: &mut Bx, offset: u64) -> Self;
     fn downcast(&self, bx: &mut Bx, variant: VariantIdx) -> Self;
 }
 
@@ -98,6 +102,11 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> DebugInfoOffsetLocation<'tcx, Bx>
         PlaceRef::project_field(*self, bx, field.index())
     }
 
+    fn project_constant_index(&self, bx: &mut Bx, offset: u64) -> Self {
+        let lloffset = bx.cx().const_usize(offset);
+        self.project_index(bx, lloffset)
+    }
+
     fn downcast(&self, bx: &mut Bx, variant: VariantIdx) -> Self {
         self.project_downcast(bx, variant)
     }
@@ -120,6 +129,10 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> DebugInfoOffsetLocation<'tcx, Bx>
         self.field(bx.cx(), field.index())
     }
 
+    fn project_constant_index(&self, bx: &mut Bx, index: u64) -> Self {
+        self.field(bx.cx(), index as usize)
+    }
+
     fn downcast(&self, bx: &mut Bx, variant: VariantIdx) -> Self {
         self.for_variant(bx.cx(), variant)
     }
@@ -165,6 +178,18 @@ fn calculate_debuginfo_offset<
             mir::ProjectionElem::Downcast(_, variant) => {
                 place = place.downcast(bx, variant);
             }
+            mir::ProjectionElem::ConstantIndex {
+                offset: index,
+                min_length: _,
+                from_end: false,
+            } => {
+                let offset = indirect_offsets.last_mut().unwrap_or(&mut direct_offset);
+                let FieldsShape::Array { stride, count: _ } = place.layout().fields else {
+                    span_bug!(var.source_info.span, "ConstantIndex on non-array type {:?}", place.layout())
+                };
+                *offset += stride * index;
+                place = place.project_constant_index(bx, index);
+            }
             _ => {
                 // Sanity check for `can_use_in_debuginfo`.
                 debug_assert!(!elem.can_use_in_debuginfo());
@@ -293,6 +318,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                     dbg_var,
                     fragment: None,
                     projection: ty::List::empty(),
+                    references: 0,
                 })
             }
         } else {
@@ -358,55 +384,74 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
         let vars = vars.iter().cloned().chain(fallback_var);
 
         for var in vars {
-            let Some(dbg_var) = var.dbg_var else { continue };
-            let Some(dbg_loc) = self.dbg_loc(var.source_info) else { continue };
-
-            let DebugInfoOffset { direct_offset, indirect_offsets, result: _ } =
-                calculate_debuginfo_offset(bx, local, &var, base.layout);
-
-            // When targeting MSVC, create extra allocas for arguments instead of pointing multiple
-            // dbg_var_addr() calls into the same alloca with offsets. MSVC uses CodeView records
-            // not DWARF and LLVM doesn't support translating the resulting
-            // [DW_OP_deref, DW_OP_plus_uconst, offset, DW_OP_deref] debug info to CodeView.
-            // Creating extra allocas on the stack makes the resulting debug info simple enough
-            // that LLVM can generate correct CodeView records and thus the values appear in the
-            // debugger. (#83709)
-            let should_create_individual_allocas = bx.cx().sess().target.is_like_msvc
-                && self.mir.local_kind(local) == mir::LocalKind::Arg
-                // LLVM can handle simple things but anything more complex than just a direct
-                // offset or one indirect offset of 0 is too complex for it to generate CV records
-                // correctly.
-                && (direct_offset != Size::ZERO
-                    || !matches!(&indirect_offsets[..], [Size::ZERO] | []));
-
-            if should_create_individual_allocas {
-                let DebugInfoOffset { direct_offset: _, indirect_offsets: _, result: place } =
-                    calculate_debuginfo_offset(bx, local, &var, base);
-
-                // Create a variable which will be a pointer to the actual value
-                let ptr_ty = bx
-                    .tcx()
-                    .mk_ptr(ty::TypeAndMut { mutbl: mir::Mutability::Mut, ty: place.layout.ty });
-                let ptr_layout = bx.layout_of(ptr_ty);
-                let alloca = PlaceRef::alloca(bx, ptr_layout);
-                bx.set_var_name(alloca.llval, &(var.name.to_string() + ".dbg.spill"));
-
-                // Write the pointer to the variable
-                bx.store(place.llval, alloca.llval, alloca.align);
-
-                // Point the debug info to `*alloca` for the current variable
-                bx.dbg_var_addr(dbg_var, dbg_loc, alloca.llval, Size::ZERO, &[Size::ZERO], None);
-            } else {
-                bx.dbg_var_addr(
-                    dbg_var,
-                    dbg_loc,
-                    base.llval,
-                    direct_offset,
-                    &indirect_offsets,
-                    None,
-                );
+            self.debug_introduce_local_as_var(bx, local, base, var);
+        }
+    }
+
+    fn debug_introduce_local_as_var(
+        &self,
+        bx: &mut Bx,
+        local: mir::Local,
+        mut base: PlaceRef<'tcx, Bx::Value>,
+        var: PerLocalVarDebugInfo<'tcx, Bx::DIVariable>,
+    ) {
+        let Some(dbg_var) = var.dbg_var else { return };
+        let Some(dbg_loc) = self.dbg_loc(var.source_info) else { return };
+
+        let DebugInfoOffset { mut direct_offset, indirect_offsets, result: _ } =
+            calculate_debuginfo_offset(bx, local, &var, base.layout);
+        let mut indirect_offsets = &indirect_offsets[..];
+
+        // When targeting MSVC, create extra allocas for arguments instead of pointing multiple
+        // dbg_var_addr() calls into the same alloca with offsets. MSVC uses CodeView records
+        // not DWARF and LLVM doesn't support translating the resulting
+        // [DW_OP_deref, DW_OP_plus_uconst, offset, DW_OP_deref] debug info to CodeView.
+        // Creating extra allocas on the stack makes the resulting debug info simple enough
+        // that LLVM can generate correct CodeView records and thus the values appear in the
+        // debugger. (#83709)
+        let should_create_individual_allocas = bx.cx().sess().target.is_like_msvc
+            && self.mir.local_kind(local) == mir::LocalKind::Arg
+            // LLVM can handle simple things but anything more complex than just a direct
+            // offset or one indirect offset of 0 is too complex for it to generate CV records
+            // correctly.
+            && (direct_offset != Size::ZERO || !matches!(indirect_offsets, [Size::ZERO] | []));
+
+        let create_alloca = |bx: &mut Bx, place: PlaceRef<'tcx, Bx::Value>, refcount| {
+            // Create a variable which will be a pointer to the actual value
+            let ptr_ty = bx
+                .tcx()
+                .mk_ptr(ty::TypeAndMut { mutbl: mir::Mutability::Mut, ty: place.layout.ty });
+            let ptr_layout = bx.layout_of(ptr_ty);
+            let alloca = PlaceRef::alloca(bx, ptr_layout);
+            bx.set_var_name(alloca.llval, &format!("{}.ref{}.dbg.spill", var.name, refcount));
+
+            // Write the pointer to the variable
+            bx.store(place.llval, alloca.llval, alloca.align);
+
+            // Point the debug info to `*alloca` for the current variable
+            alloca
+        };
+
+        if var.references > 0 {
+            base = calculate_debuginfo_offset(bx, local, &var, base).result;
+
+            // Point the debug info to `&...&base == alloca` for the current variable
+            for refcount in 0..var.references {
+                base = create_alloca(bx, base, refcount);
             }
+
+            direct_offset = Size::ZERO;
+            indirect_offsets = &[];
+        } else if should_create_individual_allocas {
+            let place = calculate_debuginfo_offset(bx, local, &var, base).result;
+
+            // Point the debug info to `*alloca` for the current variable
+            base = create_alloca(bx, place, 0);
+            direct_offset = Size::ZERO;
+            indirect_offsets = &[Size::ZERO];
         }
+
+        bx.dbg_var_addr(dbg_var, dbg_loc, base.llval, direct_offset, indirect_offsets, None);
     }
 
     pub fn debug_introduce_locals(&self, bx: &mut Bx) {
@@ -439,7 +484,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
             };
 
             let dbg_var = dbg_scope_and_span.map(|(dbg_scope, _, span)| {
-                let (var_ty, var_kind) = match var.value {
+                let (mut var_ty, var_kind) = match var.value {
                     mir::VarDebugInfoContents::Place(place) => {
                         let var_ty = self.monomorphized_place_ty(place.as_ref());
                         let var_kind = if let Some(arg_index) = var.argument_index
@@ -476,6 +521,11 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                     }
                 };
 
+                for _ in 0..var.references {
+                    var_ty =
+                        bx.tcx().mk_ptr(ty::TypeAndMut { mutbl: mir::Mutability::Mut, ty: var_ty });
+                }
+
                 self.cx.create_dbg_var(var.name, var_ty, dbg_scope, var_kind, span)
             });
 
@@ -487,6 +537,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                         dbg_var,
                         fragment: None,
                         projection: place.projection,
+                        references: var.references,
                     });
                 }
                 mir::VarDebugInfoContents::Const(c) => {
@@ -540,6 +591,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                                 Some(fragment_start..fragment_start + fragment_layout.size)
                             },
                             projection: place.projection,
+                            references: var.references,
                         });
                     }
                 }
diff --git a/compiler/rustc_codegen_ssa/src/mir/operand.rs b/compiler/rustc_codegen_ssa/src/mir/operand.rs
index 9efbb34b515..2301c3ef13e 100644
--- a/compiler/rustc_codegen_ssa/src/mir/operand.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/operand.rs
@@ -402,8 +402,6 @@ impl<'a, 'tcx, V: CodegenObject> OperandValue<V> {
         indirect_dest: PlaceRef<'tcx, V>,
     ) {
         debug!("OperandRef::store_unsized: operand={:?}, indirect_dest={:?}", self, indirect_dest);
-        let flags = MemFlags::empty();
-
         // `indirect_dest` must have `*mut T` type. We extract `T` out of it.
         let unsized_ty = indirect_dest
             .layout
@@ -416,17 +414,23 @@ impl<'a, 'tcx, V: CodegenObject> OperandValue<V> {
             bug!("store_unsized called with a sized value")
         };
 
-        // FIXME: choose an appropriate alignment, or use dynamic align somehow
-        let max_align = Align::from_bits(128).unwrap();
-        let min_align = Align::from_bits(8).unwrap();
-
-        // Allocate an appropriate region on the stack, and copy the value into it
-        let (llsize, _) = glue::size_and_align_of_dst(bx, unsized_ty, Some(llextra));
-        let lldst = bx.byte_array_alloca(llsize, max_align);
-        bx.memcpy(lldst, max_align, llptr, min_align, llsize, flags);
+        // Allocate an appropriate region on the stack, and copy the value into it. Since alloca
+        // doesn't support dynamic alignment, we allocate an extra align - 1 bytes, and align the
+        // pointer manually.
+        let (size, align) = glue::size_and_align_of_dst(bx, unsized_ty, Some(llextra));
+        let one = bx.const_usize(1);
+        let align_minus_1 = bx.sub(align, one);
+        let size_extra = bx.add(size, align_minus_1);
+        let min_align = Align::ONE;
+        let alloca = bx.byte_array_alloca(size_extra, min_align);
+        let address = bx.ptrtoint(alloca, bx.type_isize());
+        let neg_address = bx.neg(address);
+        let offset = bx.and(neg_address, align_minus_1);
+        let dst = bx.inbounds_gep(bx.type_i8(), alloca, &[offset]);
+        bx.memcpy(dst, min_align, llptr, min_align, size, MemFlags::empty());
 
         // Store the allocated region and the extra to the indirect place.
-        let indirect_operand = OperandValue::Pair(lldst, llextra);
+        let indirect_operand = OperandValue::Pair(dst, llextra);
         indirect_operand.store(bx, indirect_dest);
     }
 }
diff --git a/compiler/rustc_codegen_ssa/src/target_features.rs b/compiler/rustc_codegen_ssa/src/target_features.rs
index 1cfc4b933a8..c5976a65411 100644
--- a/compiler/rustc_codegen_ssa/src/target_features.rs
+++ b/compiler/rustc_codegen_ssa/src/target_features.rs
@@ -8,7 +8,7 @@ use rustc_hir::def::DefKind;
 use rustc_hir::def_id::DefId;
 use rustc_hir::def_id::LocalDefId;
 use rustc_hir::def_id::LOCAL_CRATE;
-use rustc_middle::ty::query::Providers;
+use rustc_middle::query::Providers;
 use rustc_middle::ty::TyCtxt;
 use rustc_session::parse::feature_err;
 use rustc_session::Session;
@@ -173,16 +173,13 @@ const X86_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[
     ("avx512dq", Some(sym::avx512_target_feature)),
     ("avx512er", Some(sym::avx512_target_feature)),
     ("avx512f", Some(sym::avx512_target_feature)),
-    ("avx512gfni", Some(sym::avx512_target_feature)),
     ("avx512ifma", Some(sym::avx512_target_feature)),
     ("avx512pf", Some(sym::avx512_target_feature)),
-    ("avx512vaes", Some(sym::avx512_target_feature)),
     ("avx512vbmi", Some(sym::avx512_target_feature)),
     ("avx512vbmi2", Some(sym::avx512_target_feature)),
     ("avx512vl", Some(sym::avx512_target_feature)),
     ("avx512vnni", Some(sym::avx512_target_feature)),
     ("avx512vp2intersect", Some(sym::avx512_target_feature)),
-    ("avx512vpclmulqdq", Some(sym::avx512_target_feature)),
     ("avx512vpopcntdq", Some(sym::avx512_target_feature)),
     ("bmi1", None),
     ("bmi2", None),
@@ -253,6 +250,7 @@ const RISCV_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[
     ("f", Some(sym::riscv_target_feature)),
     ("m", Some(sym::riscv_target_feature)),
     ("relax", Some(sym::riscv_target_feature)),
+    ("unaligned-scalar-mem", Some(sym::riscv_target_feature)),
     ("v", Some(sym::riscv_target_feature)),
     ("zba", Some(sym::riscv_target_feature)),
     ("zbb", Some(sym::riscv_target_feature)),
diff --git a/compiler/rustc_codegen_ssa/src/traits/backend.rs b/compiler/rustc_codegen_ssa/src/traits/backend.rs
index 64bebe50ddb..d83bfc74082 100644
--- a/compiler/rustc_codegen_ssa/src/traits/backend.rs
+++ b/compiler/rustc_codegen_ssa/src/traits/backend.rs
@@ -1,3 +1,5 @@
+use std::any::Any;
+
 use super::write::WriteBackendMethods;
 use super::CodegenObject;
 use crate::back::write::TargetMachineFactoryFn;
@@ -5,11 +7,12 @@ use crate::{CodegenResults, ModuleCodegen};
 
 use rustc_ast::expand::allocator::AllocatorKind;
 use rustc_data_structures::fx::FxHashMap;
+use rustc_data_structures::sync::{DynSend, DynSync};
 use rustc_errors::ErrorGuaranteed;
 use rustc_metadata::EncodedMetadata;
 use rustc_middle::dep_graph::{WorkProduct, WorkProductId};
+use rustc_middle::query::{ExternProviders, Providers};
 use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt, LayoutOf, TyAndLayout};
-use rustc_middle::ty::query::{ExternProviders, Providers};
 use rustc_middle::ty::{Ty, TyCtxt};
 use rustc_session::{
     config::{self, OutputFilenames, PrintRequest},
@@ -20,10 +23,6 @@ use rustc_span::symbol::Symbol;
 use rustc_target::abi::call::FnAbi;
 use rustc_target::spec::Target;
 
-pub use rustc_data_structures::sync::MetadataRef;
-
-use std::any::Any;
-
 pub trait BackendTypes {
     type Value: CodegenObject;
     type Function: CodegenObject;
@@ -117,7 +116,9 @@ pub trait CodegenBackend {
     ) -> Result<(), ErrorGuaranteed>;
 }
 
-pub trait ExtraBackendMethods: CodegenBackend + WriteBackendMethods + Sized + Send + Sync {
+pub trait ExtraBackendMethods:
+    CodegenBackend + WriteBackendMethods + Sized + Send + Sync + DynSend + DynSync
+{
     fn codegen_allocator<'tcx>(
         &self,
         tcx: TyCtxt<'tcx>,
diff --git a/compiler/rustc_const_eval/src/const_eval/error.rs b/compiler/rustc_const_eval/src/const_eval/error.rs
index cdef3fb2339..c591ff75ab8 100644
--- a/compiler/rustc_const_eval/src/const_eval/error.rs
+++ b/compiler/rustc_const_eval/src/const_eval/error.rs
@@ -3,7 +3,8 @@ use std::fmt;
 
 use rustc_errors::Diagnostic;
 use rustc_middle::mir::AssertKind;
-use rustc_middle::ty::{layout::LayoutError, query::TyCtxtAt, ConstInt};
+use rustc_middle::query::TyCtxtAt;
+use rustc_middle::ty::{layout::LayoutError, ConstInt};
 use rustc_span::{Span, Symbol};
 
 use super::InterpCx;
@@ -169,14 +170,14 @@ impl<'tcx> ConstEvalErr<'tcx> {
                 // See <https://github.com/rust-lang/rust/pull/63152>.
                 let mut err = struct_error(tcx, &self.error.to_string());
                 self.decorate(&mut err, decorate);
-                ErrorHandled::Reported(err.emit())
+                ErrorHandled::Reported(err.emit().into())
             }
             _ => {
                 // Report as hard error.
                 let mut err = struct_error(tcx, message);
                 err.span_label(self.span, self.error.to_string());
                 self.decorate(&mut err, decorate);
-                ErrorHandled::Reported(err.emit())
+                ErrorHandled::Reported(err.emit().into())
             }
         }
     }
diff --git a/compiler/rustc_const_eval/src/const_eval/fn_queries.rs b/compiler/rustc_const_eval/src/const_eval/fn_queries.rs
index 088a824fd8f..fa8253d5e49 100644
--- a/compiler/rustc_const_eval/src/const_eval/fn_queries.rs
+++ b/compiler/rustc_const_eval/src/const_eval/fn_queries.rs
@@ -2,7 +2,7 @@ use rustc_attr as attr;
 use rustc_hir as hir;
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::{DefId, LocalDefId};
-use rustc_middle::ty::query::Providers;
+use rustc_middle::query::Providers;
 use rustc_middle::ty::TyCtxt;
 use rustc_span::symbol::Symbol;
 
diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs
index 814b67b46ec..58b5755af07 100644
--- a/compiler/rustc_const_eval/src/const_eval/machine.rs
+++ b/compiler/rustc_const_eval/src/const_eval/machine.rs
@@ -382,7 +382,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
                         rustc_span::DUMMY_SP,
                         "This is likely a const item that is missing from its impl",
                     );
-                    throw_inval!(AlreadyReported(guar));
+                    throw_inval!(AlreadyReported(guar.into()));
                 } else {
                     // `find_mir_or_eval_fn` checks that this is a const fn before even calling us,
                     // so this should be unreachable.
diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs
index b2197a0aabb..040eba10eb4 100644
--- a/compiler/rustc_const_eval/src/interpret/eval_context.rs
+++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs
@@ -7,14 +7,13 @@ use either::{Either, Left, Right};
 use rustc_hir::{self as hir, def_id::DefId, definitions::DefPathData};
 use rustc_index::IndexVec;
 use rustc_middle::mir;
-use rustc_middle::mir::interpret::{ErrorHandled, InterpError};
+use rustc_middle::mir::interpret::{ErrorHandled, InterpError, ReportedErrorInfo};
+use rustc_middle::query::TyCtxtAt;
 use rustc_middle::ty::layout::{
     self, FnAbiError, FnAbiOfHelpers, FnAbiRequest, LayoutError, LayoutOf, LayoutOfHelpers,
     TyAndLayout,
 };
-use rustc_middle::ty::{
-    self, query::TyCtxtAt, subst::SubstsRef, ParamEnv, Ty, TyCtxt, TypeFoldable,
-};
+use rustc_middle::ty::{self, subst::SubstsRef, ParamEnv, Ty, TyCtxt, TypeFoldable};
 use rustc_mir_dataflow::storage::always_storage_live_locals;
 use rustc_session::Limit;
 use rustc_span::Span;
@@ -470,7 +469,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         };
         // do not continue if typeck errors occurred (can only occur in local crate)
         if let Some(err) = body.tainted_by_errors {
-            throw_inval!(AlreadyReported(err));
+            throw_inval!(AlreadyReported(ReportedErrorInfo::tainted_by_errors(err)));
         }
         Ok(body)
     }
@@ -517,7 +516,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
             Ok(None) => throw_inval!(TooGeneric),
 
             // FIXME(eddyb) this could be a bit more specific than `AlreadyReported`.
-            Err(error_reported) => throw_inval!(AlreadyReported(error_reported)),
+            Err(error_reported) => throw_inval!(AlreadyReported(error_reported.into())),
         }
     }
 
@@ -905,7 +904,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         query(self.tcx.at(span.unwrap_or_else(|| self.cur_span()))).map_err(|err| {
             match err {
                 ErrorHandled::Reported(err) => {
-                    if let Some(span) = span {
+                    if !err.is_tainted_by_errors() && let Some(span) = span {
                         // To make it easier to figure out where this error comes from, also add a note at the current location.
                         self.tcx.sess.span_note_without_error(span, "erroneous constant used");
                     }
diff --git a/compiler/rustc_const_eval/src/interpret/operand.rs b/compiler/rustc_const_eval/src/interpret/operand.rs
index a7f66071fe2..e30af165501 100644
--- a/compiler/rustc_const_eval/src/interpret/operand.rs
+++ b/compiler/rustc_const_eval/src/interpret/operand.rs
@@ -595,7 +595,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
             // FIXME(generic_const_exprs): `ConstKind::Expr` should be able to be evaluated
             ty::ConstKind::Expr(_) => throw_inval!(TooGeneric),
             ty::ConstKind::Error(reported) => {
-                throw_inval!(AlreadyReported(reported))
+                throw_inval!(AlreadyReported(reported.into()))
             }
             ty::ConstKind::Unevaluated(uv) => {
                 let instance = self.resolve(uv.def, uv.substs)?;
diff --git a/compiler/rustc_const_eval/src/lib.rs b/compiler/rustc_const_eval/src/lib.rs
index 1b66eca97a5..c36282d5ed4 100644
--- a/compiler/rustc_const_eval/src/lib.rs
+++ b/compiler/rustc_const_eval/src/lib.rs
@@ -35,8 +35,8 @@ pub mod util;
 
 use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage};
 use rustc_fluent_macro::fluent_messages;
+use rustc_middle::query::Providers;
 use rustc_middle::ty;
-use rustc_middle::ty::query::Providers;
 
 fluent_messages! { "../messages.ftl" }
 
diff --git a/compiler/rustc_const_eval/src/transform/validate.rs b/compiler/rustc_const_eval/src/transform/validate.rs
index f46c2d00fe4..3c350e25ba6 100644
--- a/compiler/rustc_const_eval/src/transform/validate.rs
+++ b/compiler/rustc_const_eval/src/transform/validate.rs
@@ -164,7 +164,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                 if let Some(root) = post_contract_node.get(&bb) {
                     break *root;
                 }
-                let parent = doms.immediate_dominator(bb);
+                let parent = doms.immediate_dominator(bb).unwrap();
                 dom_path.push(bb);
                 if !self.body.basic_blocks[parent].is_cleanup {
                     break bb;
@@ -448,7 +448,15 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
         };
         match debuginfo.value {
             VarDebugInfoContents::Const(_) => {}
-            VarDebugInfoContents::Place(place) => check_place(place),
+            VarDebugInfoContents::Place(place) => {
+                check_place(place);
+                if debuginfo.references != 0 && place.projection.last() == Some(&PlaceElem::Deref) {
+                    self.fail(
+                        START_BLOCK.start_location(),
+                        format!("debuginfo {:?}, has both ref and deref", debuginfo),
+                    );
+                }
+            }
             VarDebugInfoContents::Composite { ty, ref fragments } => {
                 for f in fragments {
                     check_place(f.contents);
diff --git a/compiler/rustc_data_structures/Cargo.toml b/compiler/rustc_data_structures/Cargo.toml
index c815bb2d197..78f73d193e3 100644
--- a/compiler/rustc_data_structures/Cargo.toml
+++ b/compiler/rustc_data_structures/Cargo.toml
@@ -16,6 +16,7 @@ libc = "0.2"
 measureme = "10.0.0"
 rustc-rayon-core = { version = "0.5.0", optional = true }
 rustc-rayon = { version = "0.5.0", optional = true }
+rustc_arena = { path = "../rustc_arena" }
 rustc_graphviz = { path = "../rustc_graphviz" }
 rustc-hash = "1.1.0"
 rustc_index = { path = "../rustc_index", package = "rustc_index" }
diff --git a/compiler/rustc_data_structures/src/graph/dominators/mod.rs b/compiler/rustc_data_structures/src/graph/dominators/mod.rs
index e76bdac2864..594ed1ad2e7 100644
--- a/compiler/rustc_data_structures/src/graph/dominators/mod.rs
+++ b/compiler/rustc_data_structures/src/graph/dominators/mod.rs
@@ -109,28 +109,27 @@ pub fn dominators<G: ControlFlowGraph>(graph: G) -> Dominators<G::Node> {
         // they have been placed in the bucket.
         //
         // We compute a partial set of immediate dominators here.
-        let z = parent[w];
-        for &v in bucket[z].iter() {
+        for &v in bucket[w].iter() {
             // This uses the result of Lemma 5 from section 2 from the original
             // 1979 paper, to compute either the immediate or relative dominator
             // for a given vertex v.
             //
             // eval returns a vertex y, for which semi[y] is minimum among
-            // vertices semi[v] +> y *> v. Note that semi[v] = z as we're in the
-            // z bucket.
+            // vertices semi[v] +> y *> v. Note that semi[v] = w as we're in the
+            // w bucket.
             //
             // Given such a vertex y, semi[y] <= semi[v] and idom[y] = idom[v].
             // If semi[y] = semi[v], though, idom[v] = semi[v].
             //
             // Using this, we can either set idom[v] to be:
-            //  * semi[v] (i.e. z), if semi[y] is z
+            //  * semi[v] (i.e. w), if semi[y] is w
             //  * idom[y], otherwise
             //
             // We don't directly set to idom[y] though as it's not necessarily
             // known yet. The second preorder traversal will cleanup by updating
             // the idom for any that were missed in this pass.
             let y = eval(&mut parent, lastlinked, &semi, &mut label, v);
-            idom[v] = if semi[y] < z { y } else { z };
+            idom[v] = if semi[y] < w { y } else { w };
         }
 
         // This loop computes the semi[w] for w.
@@ -213,10 +212,11 @@ pub fn dominators<G: ControlFlowGraph>(graph: G) -> Dominators<G::Node> {
         // If we don't yet know the idom directly, then push this vertex into
         // our semidominator's bucket, where it will get processed at a later
         // stage to compute its immediate dominator.
-        if parent[w] != semi[w] {
+        let z = parent[w];
+        if z != semi[w] {
             bucket[semi[w]].push(w);
         } else {
-            idom[w] = parent[w];
+            idom[w] = z;
         }
 
         // Optimization: We share the parent array between processed and not
@@ -242,7 +242,9 @@ pub fn dominators<G: ControlFlowGraph>(graph: G) -> Dominators<G::Node> {
         immediate_dominators[*node] = Some(pre_order_to_real[idom[idx]]);
     }
 
-    Dominators { post_order_rank, immediate_dominators }
+    let start_node = graph.start_node();
+    immediate_dominators[start_node] = None;
+    Dominators { start_node, post_order_rank, immediate_dominators }
 }
 
 /// Evaluate the link-eval virtual forest, providing the currently minimum semi
@@ -308,6 +310,7 @@ fn compress(
 /// Tracks the list of dominators for each node.
 #[derive(Clone, Debug)]
 pub struct Dominators<N: Idx> {
+    start_node: N,
     post_order_rank: IndexVec<N, usize>,
     // Even though we track only the immediate dominator of each node, it's
     // possible to get its full list of dominators by looking up the dominator
@@ -316,14 +319,14 @@ pub struct Dominators<N: Idx> {
 }
 
 impl<Node: Idx> Dominators<Node> {
-    /// Whether the given Node has an immediate dominator.
+    /// Returns true if node is reachable from the start node.
     pub fn is_reachable(&self, node: Node) -> bool {
-        self.immediate_dominators[node].is_some()
+        node == self.start_node || self.immediate_dominators[node].is_some()
     }
 
-    pub fn immediate_dominator(&self, node: Node) -> Node {
-        assert!(self.is_reachable(node), "node {node:?} is not reachable");
-        self.immediate_dominators[node].unwrap()
+    /// Returns the immediate dominator of node, if any.
+    pub fn immediate_dominator(&self, node: Node) -> Option<Node> {
+        self.immediate_dominators[node]
     }
 
     /// Provides an iterator over each dominator up the CFG, for the given Node.
@@ -357,12 +360,7 @@ impl<'dom, Node: Idx> Iterator for Iter<'dom, Node> {
 
     fn next(&mut self) -> Option<Self::Item> {
         if let Some(node) = self.node {
-            let dom = self.dominators.immediate_dominator(node);
-            if dom == node {
-                self.node = None; // reached the root
-            } else {
-                self.node = Some(dom);
-            }
+            self.node = self.dominators.immediate_dominator(node);
             Some(node)
         } else {
             None
diff --git a/compiler/rustc_data_structures/src/graph/dominators/tests.rs b/compiler/rustc_data_structures/src/graph/dominators/tests.rs
index ff31d8f7fdc..5472bb8087e 100644
--- a/compiler/rustc_data_structures/src/graph/dominators/tests.rs
+++ b/compiler/rustc_data_structures/src/graph/dominators/tests.rs
@@ -8,7 +8,7 @@ fn diamond() {
 
     let dominators = dominators(&graph);
     let immediate_dominators = &dominators.immediate_dominators;
-    assert_eq!(immediate_dominators[0], Some(0));
+    assert_eq!(immediate_dominators[0], None);
     assert_eq!(immediate_dominators[1], Some(0));
     assert_eq!(immediate_dominators[2], Some(0));
     assert_eq!(immediate_dominators[3], Some(0));
@@ -30,7 +30,7 @@ fn paper() {
     assert_eq!(immediate_dominators[3], Some(6));
     assert_eq!(immediate_dominators[4], Some(6));
     assert_eq!(immediate_dominators[5], Some(6));
-    assert_eq!(immediate_dominators[6], Some(6));
+    assert_eq!(immediate_dominators[6], None);
 }
 
 #[test]
@@ -43,3 +43,40 @@ fn paper_slt() {
 
     dominators(&graph);
 }
+
+#[test]
+fn immediate_dominator() {
+    let graph = TestGraph::new(1, &[(1, 2), (2, 3)]);
+    let dominators = dominators(&graph);
+    assert_eq!(dominators.immediate_dominator(0), None);
+    assert_eq!(dominators.immediate_dominator(1), None);
+    assert_eq!(dominators.immediate_dominator(2), Some(1));
+    assert_eq!(dominators.immediate_dominator(3), Some(2));
+}
+
+#[test]
+fn transitive_dominator() {
+    let graph = TestGraph::new(
+        0,
+        &[
+            // First tree branch.
+            (0, 1),
+            (1, 2),
+            (2, 3),
+            (3, 4),
+            // Second tree branch.
+            (1, 5),
+            (5, 6),
+            // Third tree branch.
+            (0, 7),
+            // These links make 0 the dominator for 2 and 3.
+            (7, 2),
+            (5, 3),
+        ],
+    );
+
+    let dom_tree = dominators(&graph);
+    let immediate_dominators = &dom_tree.immediate_dominators;
+    assert_eq!(immediate_dominators[2], Some(0));
+    assert_eq!(immediate_dominators[3], Some(0)); // This used to return Some(1).
+}
diff --git a/compiler/rustc_data_structures/src/lib.rs b/compiler/rustc_data_structures/src/lib.rs
index 004017ec5f3..5b9b0e106d2 100644
--- a/compiler/rustc_data_structures/src/lib.rs
+++ b/compiler/rustc_data_structures/src/lib.rs
@@ -26,6 +26,7 @@
 #![feature(test)]
 #![feature(thread_id_value)]
 #![feature(vec_into_raw_parts)]
+#![feature(allocator_api)]
 #![feature(get_mut_unchecked)]
 #![feature(lint_reasons)]
 #![feature(unwrap_infallible)]
@@ -77,6 +78,7 @@ pub mod sorted_map;
 pub mod stable_hasher;
 mod atomic_ref;
 pub mod fingerprint;
+pub mod marker;
 pub mod profiling;
 pub mod sharded;
 pub mod stack;
diff --git a/compiler/rustc_data_structures/src/marker.rs b/compiler/rustc_data_structures/src/marker.rs
new file mode 100644
index 00000000000..f8c06f9a814
--- /dev/null
+++ b/compiler/rustc_data_structures/src/marker.rs
@@ -0,0 +1,257 @@
+cfg_if!(
+    if #[cfg(not(parallel_compiler))] {
+        pub auto trait DynSend {}
+        pub auto trait DynSync {}
+
+        impl<T> DynSend for T {}
+        impl<T> DynSync for T {}
+    } else {
+        #[rustc_on_unimplemented(
+            message = "`{Self}` doesn't implement `DynSend`. \
+            Add it to `rustc_data_structures::marker` or use `IntoDynSyncSend` if it's already `Send`"
+        )]
+        // This is an auto trait for types which can be sent across threads if `sync::is_dyn_thread_safe()`
+        // is true. These types can be wrapped in a `FromDyn` to get a `Send` type. Wrapping a
+        // `Send` type in `IntoDynSyncSend` will create a `DynSend` type.
+        pub unsafe auto trait DynSend {}
+
+        #[rustc_on_unimplemented(
+            message = "`{Self}` doesn't implement `DynSync`. \
+            Add it to `rustc_data_structures::marker` or use `IntoDynSyncSend` if it's already `Sync`"
+        )]
+        // This is an auto trait for types which can be shared across threads if `sync::is_dyn_thread_safe()`
+        // is true. These types can be wrapped in a `FromDyn` to get a `Sync` type. Wrapping a
+        // `Sync` type in `IntoDynSyncSend` will create a `DynSync` type.
+        pub unsafe auto trait DynSync {}
+
+        // Same with `Sync` and `Send`.
+        unsafe impl<T: DynSync + ?Sized> DynSend for &T {}
+
+        macro_rules! impls_dyn_send_neg {
+            ($([$t1: ty $(where $($generics1: tt)*)?])*) => {
+                $(impl$(<$($generics1)*>)? !DynSend for $t1 {})*
+            };
+        }
+
+        // Consistent with `std`
+        impls_dyn_send_neg!(
+            [std::env::Args]
+            [std::env::ArgsOs]
+            [*const T where T: ?Sized]
+            [*mut T where T: ?Sized]
+            [std::ptr::NonNull<T> where T: ?Sized]
+            [std::rc::Rc<T> where T: ?Sized]
+            [std::rc::Weak<T> where T: ?Sized]
+            [std::sync::MutexGuard<'_, T> where T: ?Sized]
+            [std::sync::RwLockReadGuard<'_, T> where T: ?Sized]
+            [std::sync::RwLockWriteGuard<'_, T> where T: ?Sized]
+            [std::io::StdoutLock<'_>]
+            [std::io::StderrLock<'_>]
+        );
+        cfg_if!(
+            // Consistent with `std`
+            // `os_imp::Env` is `!Send` in these platforms
+            if #[cfg(any(unix, target_os = "hermit", target_os = "wasi", target_os = "solid_asp3"))] {
+                impl !DynSend for std::env::VarsOs {}
+            }
+        );
+
+        macro_rules! already_send {
+            ($([$ty: ty])*) => {
+                $(unsafe impl DynSend for $ty where $ty: Send {})*
+            };
+        }
+
+        // These structures are already `Send`.
+        already_send!(
+            [std::backtrace::Backtrace]
+            [std::io::Stdout]
+            [std::io::Stderr]
+            [std::io::Error]
+            [std::fs::File]
+            [rustc_arena::DroplessArena]
+            [crate::memmap::Mmap]
+            [crate::profiling::SelfProfiler]
+            [crate::owned_slice::OwnedSlice]
+        );
+
+        macro_rules! impl_dyn_send {
+            ($($($attr: meta)* [$ty: ty where $($generics2: tt)*])*) => {
+                $(unsafe impl<$($generics2)*> DynSend for $ty {})*
+            };
+        }
+
+        impl_dyn_send!(
+            [std::sync::atomic::AtomicPtr<T> where T]
+            [std::sync::Mutex<T> where T: ?Sized+ DynSend]
+            [std::sync::mpsc::Sender<T> where T: DynSend]
+            [std::sync::Arc<T> where T: ?Sized + DynSync + DynSend]
+            [std::sync::LazyLock<T, F> where T: DynSend, F: DynSend]
+            [std::collections::HashSet<K, S> where K: DynSend, S: DynSend]
+            [std::collections::HashMap<K, V, S> where K: DynSend, V: DynSend, S: DynSend]
+            [std::collections::BTreeMap<K, V, A> where K: DynSend, V: DynSend, A: std::alloc::Allocator + Clone + DynSend]
+            [Vec<T, A> where T: DynSend, A: std::alloc::Allocator + DynSend]
+            [Box<T, A> where T: ?Sized + DynSend, A: std::alloc::Allocator + DynSend]
+            [crate::sync::Lock<T> where T: DynSend]
+            [crate::sync::RwLock<T> where T: DynSend]
+            [crate::tagged_ptr::CopyTaggedPtr<P, T, CP> where P: Send + crate::tagged_ptr::Pointer, T: Send + crate::tagged_ptr::Tag, const CP: bool]
+            [rustc_arena::TypedArena<T> where T: DynSend]
+            [indexmap::IndexSet<V, S> where V: DynSend, S: DynSend]
+            [indexmap::IndexMap<K, V, S> where K: DynSend, V: DynSend, S: DynSend]
+            [thin_vec::ThinVec<T> where T: DynSend]
+            [smallvec::SmallVec<A> where A: smallvec::Array + DynSend]
+        );
+
+        macro_rules! impls_dyn_sync_neg {
+            ($([$t1: ty $(where $($generics1: tt)*)?])*) => {
+                $(impl$(<$($generics1)*>)? !DynSync for $t1 {})*
+            };
+        }
+
+        // Consistent with `std`
+        impls_dyn_sync_neg!(
+            [std::env::Args]
+            [std::env::ArgsOs]
+            [*const T where T: ?Sized]
+            [*mut T where T: ?Sized]
+            [std::cell::Cell<T> where T: ?Sized]
+            [std::cell::RefCell<T> where T: ?Sized]
+            [std::cell::UnsafeCell<T> where T: ?Sized]
+            [std::ptr::NonNull<T> where T: ?Sized]
+            [std::rc::Rc<T> where T: ?Sized]
+            [std::rc::Weak<T> where T: ?Sized]
+            [std::cell::OnceCell<T> where T]
+            [std::sync::mpsc::Receiver<T> where T]
+            [std::sync::mpsc::Sender<T> where T]
+        );
+        cfg_if!(
+            // Consistent with `std`
+            // `os_imp::Env` is `!Sync` in these platforms
+            if #[cfg(any(unix, target_os = "hermit", target_os = "wasi", target_os = "solid_asp3"))] {
+                impl !DynSync for std::env::VarsOs {}
+            }
+        );
+
+        macro_rules! already_sync {
+            ($([$ty: ty])*) => {
+                $(unsafe impl DynSync for $ty where $ty: Sync {})*
+            };
+        }
+
+        // These structures are already `Sync`.
+        already_sync!(
+            [std::sync::atomic::AtomicBool]
+            [std::sync::atomic::AtomicUsize]
+            [std::sync::atomic::AtomicU8]
+            [std::sync::atomic::AtomicU32]
+            [std::sync::atomic::AtomicU64]
+            [std::backtrace::Backtrace]
+            [std::io::Error]
+            [std::fs::File]
+            [jobserver_crate::Client]
+            [crate::memmap::Mmap]
+            [crate::profiling::SelfProfiler]
+            [crate::owned_slice::OwnedSlice]
+        );
+
+        macro_rules! impl_dyn_sync {
+            ($($($attr: meta)* [$ty: ty where $($generics2: tt)*])*) => {
+                $(unsafe impl<$($generics2)*> DynSync for $ty {})*
+            };
+        }
+
+        impl_dyn_sync!(
+            [std::sync::atomic::AtomicPtr<T> where T]
+            [std::sync::OnceLock<T> where T: DynSend + DynSync]
+            [std::sync::Mutex<T> where T: ?Sized + DynSend]
+            [std::sync::Arc<T> where T: ?Sized + DynSync + DynSend]
+            [std::sync::LazyLock<T, F> where T: DynSend + DynSync, F: DynSend]
+            [std::collections::HashSet<K, S> where K: DynSync, S: DynSync]
+            [std::collections::HashMap<K, V, S> where K: DynSync, V: DynSync, S: DynSync]
+            [std::collections::BTreeMap<K, V, A> where K: DynSync, V: DynSync, A: std::alloc::Allocator + Clone + DynSync]
+            [Vec<T, A> where T: DynSync, A: std::alloc::Allocator + DynSync]
+            [Box<T, A> where T: ?Sized + DynSync, A: std::alloc::Allocator + DynSync]
+            [crate::sync::Lock<T> where T: DynSend]
+            [crate::sync::RwLock<T> where T: DynSend + DynSync]
+            [crate::sync::OneThread<T> where T]
+            [crate::sync::WorkerLocal<T> where T: DynSend]
+            [crate::intern::Interned<'a, T> where 'a, T: DynSync]
+            [crate::tagged_ptr::CopyTaggedPtr<P, T, CP> where P: Sync + crate::tagged_ptr::Pointer, T: Sync + crate::tagged_ptr::Tag, const CP: bool]
+            [parking_lot::lock_api::Mutex<R, T> where R: DynSync, T: ?Sized + DynSend]
+            [parking_lot::lock_api::RwLock<R, T> where R: DynSync, T: ?Sized + DynSend + DynSync]
+            [indexmap::IndexSet<V, S> where V: DynSync, S: DynSync]
+            [indexmap::IndexMap<K, V, S> where K: DynSync, V: DynSync, S: DynSync]
+            [smallvec::SmallVec<A> where A: smallvec::Array + DynSync]
+            [thin_vec::ThinVec<T> where T: DynSync]
+        );
+    }
+);
+
+pub fn assert_dyn_sync<T: ?Sized + DynSync>() {}
+pub fn assert_dyn_send<T: ?Sized + DynSend>() {}
+pub fn assert_dyn_send_val<T: ?Sized + DynSend>(_t: &T) {}
+pub fn assert_dyn_send_sync_val<T: ?Sized + DynSync + DynSend>(_t: &T) {}
+
+#[derive(Copy, Clone)]
+pub struct FromDyn<T>(T);
+
+impl<T> FromDyn<T> {
+    #[inline(always)]
+    pub fn from(val: T) -> Self {
+        // Check that `sync::is_dyn_thread_safe()` is true on creation so we can
+        // implement `Send` and `Sync` for this structure when `T`
+        // implements `DynSend` and `DynSync` respectively.
+        #[cfg(parallel_compiler)]
+        assert!(crate::sync::is_dyn_thread_safe());
+        FromDyn(val)
+    }
+
+    #[inline(always)]
+    pub fn into_inner(self) -> T {
+        self.0
+    }
+}
+
+// `FromDyn` is `Send` if `T` is `DynSend`, since it ensures that sync::is_dyn_thread_safe() is true.
+#[cfg(parallel_compiler)]
+unsafe impl<T: DynSend> Send for FromDyn<T> {}
+
+// `FromDyn` is `Sync` if `T` is `DynSync`, since it ensures that sync::is_dyn_thread_safe() is true.
+#[cfg(parallel_compiler)]
+unsafe impl<T: DynSync> Sync for FromDyn<T> {}
+
+impl<T> std::ops::Deref for FromDyn<T> {
+    type Target = T;
+
+    #[inline(always)]
+    fn deref(&self) -> &Self::Target {
+        &self.0
+    }
+}
+
+// A wrapper to convert a struct that is already a `Send` or `Sync` into
+// an instance of `DynSend` and `DynSync`, since the compiler cannot infer
+// it automatically in some cases. (e.g. Box<dyn Send / Sync>)
+#[derive(Copy, Clone)]
+pub struct IntoDynSyncSend<T: ?Sized>(pub T);
+
+#[cfg(parallel_compiler)]
+unsafe impl<T: ?Sized + Send> DynSend for IntoDynSyncSend<T> {}
+#[cfg(parallel_compiler)]
+unsafe impl<T: ?Sized + Sync> DynSync for IntoDynSyncSend<T> {}
+
+impl<T> std::ops::Deref for IntoDynSyncSend<T> {
+    type Target = T;
+
+    #[inline(always)]
+    fn deref(&self) -> &T {
+        &self.0
+    }
+}
+
+impl<T> std::ops::DerefMut for IntoDynSyncSend<T> {
+    #[inline(always)]
+    fn deref_mut(&mut self) -> &mut T {
+        &mut self.0
+    }
+}
diff --git a/compiler/rustc_data_structures/src/owned_slice.rs b/compiler/rustc_data_structures/src/owned_slice.rs
index 311a42aa42a..cbb3047d884 100644
--- a/compiler/rustc_data_structures/src/owned_slice.rs
+++ b/compiler/rustc_data_structures/src/owned_slice.rs
@@ -1,5 +1,6 @@
 use std::{borrow::Borrow, ops::Deref};
 
+use crate::sync::Lrc;
 // Use our fake Send/Sync traits when on not parallel compiler,
 // so that `OwnedSlice` only implements/requires Send/Sync
 // for parallel compiler builds.
@@ -7,7 +8,7 @@ use crate::sync::{Send, Sync};
 
 /// An owned slice.
 ///
-/// This is similar to `Box<[u8]>` but allows slicing and using anything as the
+/// This is similar to `Lrc<[u8]>` but allows slicing and using anything as the
 /// backing buffer.
 ///
 /// See [`slice_owned`] for `OwnedSlice` construction and examples.
@@ -16,6 +17,7 @@ use crate::sync::{Send, Sync};
 ///
 /// This is essentially a replacement for `owning_ref` which is a lot simpler
 /// and even sound! 🌸
+#[derive(Clone)]
 pub struct OwnedSlice {
     /// This is conceptually a `&'self.owner [u8]`.
     bytes: *const [u8],
@@ -31,7 +33,7 @@ pub struct OwnedSlice {
     //       \/
     //      ⊂(´・◡・⊂ )∘˚˳° (I am the phantom remnant of #97770)
     #[expect(dead_code)]
-    owner: Box<dyn Send + Sync>,
+    owner: Lrc<dyn Send + Sync>,
 }
 
 /// Makes an [`OwnedSlice`] out of an `owner` and a `slicer` function.
@@ -72,10 +74,10 @@ where
     O: Send + Sync + 'static,
     F: FnOnce(&O) -> Result<&[u8], E>,
 {
-    // We box the owner of the bytes, so it doesn't move.
+    // We wrap the owner of the bytes in, so it doesn't move.
     //
     // Since the owner does not move and we don't access it in any way
-    // before drop, there is nothing that can invalidate the bytes pointer.
+    // before dropping, there is nothing that can invalidate the bytes pointer.
     //
     // Thus, "extending" the lifetime of the reference returned from `F` is fine.
     // We pretend that we pass it a reference that lives as long as the returned slice.
@@ -83,12 +85,39 @@ where
     // N.B. the HRTB on the `slicer` is important — without it the caller could provide
     // a short lived slice, unrelated to the owner.
 
-    let owner = Box::new(owner);
+    let owner = Lrc::new(owner);
     let bytes = slicer(&*owner)?;
 
     Ok(OwnedSlice { bytes, owner })
 }
 
+impl OwnedSlice {
+    /// Slice this slice by `slicer`.
+    ///
+    /// # Examples
+    ///
+    /// ```rust
+    /// # use rustc_data_structures::owned_slice::{OwnedSlice, slice_owned};
+    /// let vec = vec![1, 2, 3, 4];
+    ///
+    /// // Identical to slicing via `&v[1..3]` but produces an owned slice
+    /// let slice: OwnedSlice = slice_owned(vec, |v| &v[..]);
+    /// assert_eq!(&*slice, [1, 2, 3, 4]);
+    ///
+    /// let slice = slice.slice(|slice| &slice[1..][..2]);
+    /// assert_eq!(&*slice, [2, 3]);
+    /// ```
+    ///
+    pub fn slice(self, slicer: impl FnOnce(&[u8]) -> &[u8]) -> OwnedSlice {
+        // This is basically identical to `try_slice_owned`,
+        // `slicer` can only return slices of its argument or some static data,
+        // both of which are valid while `owner` is alive.
+
+        let bytes = slicer(&self);
+        OwnedSlice { bytes, ..self }
+    }
+}
+
 impl Deref for OwnedSlice {
     type Target = [u8];
 
@@ -108,11 +137,11 @@ impl Borrow<[u8]> for OwnedSlice {
     }
 }
 
-// Safety: `OwnedSlice` is conceptually `(&'self.1 [u8], Box<dyn Send + Sync>)`, which is `Send`
+// Safety: `OwnedSlice` is conceptually `(&'self.1 [u8], Arc<dyn Send + Sync>)`, which is `Send`
 #[cfg(parallel_compiler)]
 unsafe impl Send for OwnedSlice {}
 
-// Safety: `OwnedSlice` is conceptually `(&'self.1 [u8], Box<dyn Send + Sync>)`, which is `Sync`
+// Safety: `OwnedSlice` is conceptually `(&'self.1 [u8], Arc<dyn Send + Sync>)`, which is `Sync`
 #[cfg(parallel_compiler)]
 unsafe impl Sync for OwnedSlice {}
 
diff --git a/compiler/rustc_data_structures/src/owned_slice/tests.rs b/compiler/rustc_data_structures/src/owned_slice/tests.rs
index e715fb55362..1eb5378cd1a 100644
--- a/compiler/rustc_data_structures/src/owned_slice/tests.rs
+++ b/compiler/rustc_data_structures/src/owned_slice/tests.rs
@@ -26,7 +26,7 @@ fn static_storage() {
 }
 
 #[test]
-fn slice_the_slice() {
+fn slice_owned_the_slice() {
     let slice = slice_owned(vec![1, 2, 3, 4, 5, 6], Vec::as_slice);
     let slice = slice_owned(slice, |s| &s[1..][..4]);
     let slice = slice_owned(slice, |s| s);
@@ -36,6 +36,16 @@ fn slice_the_slice() {
 }
 
 #[test]
+fn slice_the_slice() {
+    let slice = slice_owned(vec![1, 2, 3, 4, 5, 6], Vec::as_slice)
+        .slice(|s| &s[1..][..4])
+        .slice(|s| s)
+        .slice(|s| &s[1..]);
+
+    assert_eq!(&*slice, &[1, 2, 3, 4, 5, 6][1..][..4][1..]);
+}
+
+#[test]
 fn try_and_fail() {
     let res = try_slice_owned(vec![0], |v| v.get(12..).ok_or(()));
 
@@ -69,6 +79,6 @@ fn drop_drops() {
 
 #[test]
 fn send_sync() {
-    crate::sync::assert_send::<OwnedSlice>();
-    crate::sync::assert_sync::<OwnedSlice>();
+    crate::sync::assert_dyn_send::<OwnedSlice>();
+    crate::sync::assert_dyn_sync::<OwnedSlice>();
 }
diff --git a/compiler/rustc_data_structures/src/sync.rs b/compiler/rustc_data_structures/src/sync.rs
index e73ca56efa0..6c3197d8ec2 100644
--- a/compiler/rustc_data_structures/src/sync.rs
+++ b/compiler/rustc_data_structures/src/sync.rs
@@ -39,7 +39,7 @@
 //!
 //! [^2] `MTLockRef` is a typedef.
 
-use crate::owned_slice::OwnedSlice;
+pub use crate::marker::*;
 use std::collections::HashMap;
 use std::hash::{BuildHasher, Hash};
 use std::ops::{Deref, DerefMut};
@@ -55,6 +55,43 @@ pub use vec::{AppendOnlyIndexVec, AppendOnlyVec};
 
 mod vec;
 
+mod mode {
+    use super::Ordering;
+    use std::sync::atomic::AtomicU8;
+
+    const UNINITIALIZED: u8 = 0;
+    const DYN_NOT_THREAD_SAFE: u8 = 1;
+    const DYN_THREAD_SAFE: u8 = 2;
+
+    static DYN_THREAD_SAFE_MODE: AtomicU8 = AtomicU8::new(UNINITIALIZED);
+
+    // Whether thread safety is enabled (due to running under multiple threads).
+    #[inline]
+    pub fn is_dyn_thread_safe() -> bool {
+        match DYN_THREAD_SAFE_MODE.load(Ordering::Relaxed) {
+            DYN_NOT_THREAD_SAFE => false,
+            DYN_THREAD_SAFE => true,
+            _ => panic!("uninitialized dyn_thread_safe mode!"),
+        }
+    }
+
+    // Only set by the `-Z threads` compile option
+    pub fn set_dyn_thread_safe_mode(mode: bool) {
+        let set: u8 = if mode { DYN_THREAD_SAFE } else { DYN_NOT_THREAD_SAFE };
+        let previous = DYN_THREAD_SAFE_MODE.compare_exchange(
+            UNINITIALIZED,
+            set,
+            Ordering::Relaxed,
+            Ordering::Relaxed,
+        );
+
+        // Check that the mode was either uninitialized or was already set to the requested mode.
+        assert!(previous.is_ok() || previous == Err(set));
+    }
+}
+
+pub use mode::{is_dyn_thread_safe, set_dyn_thread_safe_mode};
+
 cfg_if! {
     if #[cfg(not(parallel_compiler))] {
         pub unsafe auto trait Send {}
@@ -149,7 +186,7 @@ cfg_if! {
 
         #[macro_export]
         macro_rules! parallel {
-            ($($blocks:tt),*) => {
+            ($($blocks:block),*) => {
                 // We catch panics here ensuring that all the blocks execute.
                 // This makes behavior consistent with the parallel compiler.
                 let mut panic = None;
@@ -168,12 +205,6 @@ cfg_if! {
             }
         }
 
-        pub use Iterator as ParallelIterator;
-
-        pub fn par_iter<T: IntoIterator>(t: T) -> T::IntoIter {
-            t.into_iter()
-        }
-
         pub fn par_for_each_in<T: IntoIterator>(t: T, mut for_each: impl FnMut(T::Item) + Sync + Send) {
             // We catch panics here ensuring that all the loop iterations execute.
             // This makes behavior consistent with the parallel compiler.
@@ -190,7 +221,28 @@ cfg_if! {
             }
         }
 
-        pub type MetadataRef = OwnedSlice;
+        pub fn par_map<T: IntoIterator, R, C: FromIterator<R>>(
+            t: T,
+            mut map: impl FnMut(<<T as IntoIterator>::IntoIter as Iterator>::Item) -> R,
+        ) -> C {
+            // We catch panics here ensuring that all the loop iterations execute.
+            let mut panic = None;
+            let r = t.into_iter().filter_map(|i| {
+                match catch_unwind(AssertUnwindSafe(|| map(i))) {
+                    Ok(r) => Some(r),
+                    Err(p) => {
+                        if panic.is_none() {
+                            panic = Some(p);
+                        }
+                        None
+                    }
+                }
+            }).collect();
+            if let Some(panic) = panic {
+                resume_unwind(panic);
+            }
+            r
+        }
 
         pub use std::rc::Rc as Lrc;
         pub use std::rc::Weak as Weak;
@@ -302,49 +354,166 @@ cfg_if! {
         use parking_lot::RwLock as InnerRwLock;
 
         use std::thread;
-        pub use rayon::{join, scope};
+
+        #[inline]
+        pub fn join<A, B, RA: DynSend, RB: DynSend>(oper_a: A, oper_b: B) -> (RA, RB)
+        where
+            A: FnOnce() -> RA + DynSend,
+            B: FnOnce() -> RB + DynSend,
+        {
+            if mode::is_dyn_thread_safe() {
+                let oper_a = FromDyn::from(oper_a);
+                let oper_b = FromDyn::from(oper_b);
+                let (a, b) = rayon::join(move || FromDyn::from(oper_a.into_inner()()), move || FromDyn::from(oper_b.into_inner()()));
+                (a.into_inner(), b.into_inner())
+            } else {
+                (oper_a(), oper_b())
+            }
+        }
+
+        // This function only works when `mode::is_dyn_thread_safe()`.
+        pub fn scope<'scope, OP, R>(op: OP) -> R
+        where
+            OP: FnOnce(&rayon::Scope<'scope>) -> R + DynSend,
+            R: DynSend,
+        {
+            let op = FromDyn::from(op);
+            rayon::scope(|s| FromDyn::from(op.into_inner()(s))).into_inner()
+        }
 
         /// Runs a list of blocks in parallel. The first block is executed immediately on
         /// the current thread. Use that for the longest running block.
         #[macro_export]
         macro_rules! parallel {
-            (impl $fblock:tt [$($c:tt,)*] [$block:tt $(, $rest:tt)*]) => {
+            (impl $fblock:block [$($c:expr,)*] [$block:expr $(, $rest:expr)*]) => {
                 parallel!(impl $fblock [$block, $($c,)*] [$($rest),*])
             };
-            (impl $fblock:tt [$($blocks:tt,)*] []) => {
+            (impl $fblock:block [$($blocks:expr,)*] []) => {
                 ::rustc_data_structures::sync::scope(|s| {
+                    $(let block = rustc_data_structures::sync::FromDyn::from(|| $blocks);
+                    s.spawn(move |_| block.into_inner()());)*
+                    (|| $fblock)();
+                });
+            };
+            ($fblock:block, $($blocks:block),*) => {
+                if rustc_data_structures::sync::is_dyn_thread_safe() {
+                    // Reverse the order of the later blocks since Rayon executes them in reverse order
+                    // when using a single thread. This ensures the execution order matches that
+                    // of a single threaded rustc.
+                    parallel!(impl $fblock [] [$($blocks),*]);
+                } else {
+                    // We catch panics here ensuring that all the blocks execute.
+                    // This makes behavior consistent with the parallel compiler.
+                    let mut panic = None;
+                    if let Err(p) = ::std::panic::catch_unwind(
+                        ::std::panic::AssertUnwindSafe(|| $fblock)
+                    ) {
+                        if panic.is_none() {
+                            panic = Some(p);
+                        }
+                    }
                     $(
-                        s.spawn(|_| $blocks);
+                        if let Err(p) = ::std::panic::catch_unwind(
+                            ::std::panic::AssertUnwindSafe(|| $blocks)
+                        ) {
+                            if panic.is_none() {
+                                panic = Some(p);
+                            }
+                        }
                     )*
-                    $fblock;
-                })
-            };
-            ($fblock:tt, $($blocks:tt),*) => {
-                // Reverse the order of the later blocks since Rayon executes them in reverse order
-                // when using a single thread. This ensures the execution order matches that
-                // of a single threaded rustc
-                parallel!(impl $fblock [] [$($blocks),*]);
+                    if let Some(panic) = panic {
+                        ::std::panic::resume_unwind(panic);
+                    }
+                }
             };
         }
 
-        pub use rayon::iter::ParallelIterator;
-        use rayon::iter::IntoParallelIterator;
+        use rayon::iter::{FromParallelIterator, IntoParallelIterator, ParallelIterator};
 
-        pub fn par_iter<T: IntoParallelIterator>(t: T) -> T::Iter {
-            t.into_par_iter()
-        }
-
-        pub fn par_for_each_in<T: IntoParallelIterator>(
+        pub fn par_for_each_in<I, T: IntoIterator<Item = I> + IntoParallelIterator<Item = I>>(
             t: T,
-            for_each: impl Fn(T::Item) + Sync + Send,
+            for_each: impl Fn(I) + DynSync + DynSend
         ) {
-            let ps: Vec<_> = t.into_par_iter().map(|i| catch_unwind(AssertUnwindSafe(|| for_each(i)))).collect();
-            ps.into_iter().for_each(|p| if let Err(panic) = p {
-                resume_unwind(panic)
-            });
+            if mode::is_dyn_thread_safe() {
+                let for_each = FromDyn::from(for_each);
+                let panic: Lock<Option<_>> = Lock::new(None);
+                t.into_par_iter().for_each(|i| if let Err(p) = catch_unwind(AssertUnwindSafe(|| for_each(i))) {
+                    let mut l = panic.lock();
+                    if l.is_none() {
+                        *l = Some(p)
+                    }
+                });
+
+                if let Some(panic) = panic.into_inner() {
+                    resume_unwind(panic);
+                }
+            } else {
+                // We catch panics here ensuring that all the loop iterations execute.
+                // This makes behavior consistent with the parallel compiler.
+                let mut panic = None;
+                t.into_iter().for_each(|i| {
+                    if let Err(p) = catch_unwind(AssertUnwindSafe(|| for_each(i))) {
+                        if panic.is_none() {
+                            panic = Some(p);
+                        }
+                    }
+                });
+                if let Some(panic) = panic {
+                    resume_unwind(panic);
+                }
+            }
         }
 
-        pub type MetadataRef = OwnedSlice;
+        pub fn par_map<
+            I,
+            T: IntoIterator<Item = I> + IntoParallelIterator<Item = I>,
+            R: std::marker::Send,
+            C: FromIterator<R> + FromParallelIterator<R>
+        >(
+            t: T,
+            map: impl Fn(I) -> R + DynSync + DynSend
+        ) -> C {
+            if mode::is_dyn_thread_safe() {
+                let panic: Lock<Option<_>> = Lock::new(None);
+                let map = FromDyn::from(map);
+                // We catch panics here ensuring that all the loop iterations execute.
+                let r = t.into_par_iter().filter_map(|i| {
+                    match catch_unwind(AssertUnwindSafe(|| map(i))) {
+                        Ok(r) => Some(r),
+                        Err(p) => {
+                            let mut l = panic.lock();
+                            if l.is_none() {
+                                *l = Some(p);
+                            }
+                            None
+                        },
+                    }
+                }).collect();
+
+                if let Some(panic) = panic.into_inner() {
+                    resume_unwind(panic);
+                }
+                r
+            } else {
+                // We catch panics here ensuring that all the loop iterations execute.
+                let mut panic = None;
+                let r = t.into_iter().filter_map(|i| {
+                    match catch_unwind(AssertUnwindSafe(|| map(i))) {
+                        Ok(r) => Some(r),
+                        Err(p) => {
+                            if panic.is_none() {
+                                panic = Some(p);
+                            }
+                            None
+                        }
+                    }
+                }).collect();
+                if let Some(panic) = panic {
+                    resume_unwind(panic);
+                }
+                r
+            }
+        }
 
         /// This makes locks panic if they are already held.
         /// It is only useful when you are running in a single thread
@@ -352,11 +521,6 @@ cfg_if! {
     }
 }
 
-pub fn assert_sync<T: ?Sized + Sync>() {}
-pub fn assert_send<T: ?Sized + Send>() {}
-pub fn assert_send_val<T: ?Sized + Send>(_t: &T) {}
-pub fn assert_send_sync_val<T: ?Sized + Sync + Send>(_t: &T) {}
-
 #[derive(Default)]
 #[cfg_attr(parallel_compiler, repr(align(64)))]
 pub struct CacheAligned<T>(pub T);
diff --git a/compiler/rustc_data_structures/src/sync/worker_local.rs b/compiler/rustc_data_structures/src/sync/worker_local.rs
index bfb04ba8a73..d61bb55be68 100644
--- a/compiler/rustc_data_structures/src/sync/worker_local.rs
+++ b/compiler/rustc_data_structures/src/sync/worker_local.rs
@@ -154,13 +154,6 @@ impl<T> WorkerLocal<T> {
     }
 }
 
-impl<T> WorkerLocal<Vec<T>> {
-    /// Joins the elements of all the worker locals into one Vec
-    pub fn join(self) -> Vec<T> {
-        self.into_inner().into_iter().flat_map(|v| v).collect()
-    }
-}
-
 impl<T> Deref for WorkerLocal<T> {
     type Target = T;
 
diff --git a/compiler/rustc_driver_impl/src/args.rs b/compiler/rustc_driver_impl/src/args.rs
index 42c97cc6a9d..a713affa099 100644
--- a/compiler/rustc_driver_impl/src/args.rs
+++ b/compiler/rustc_driver_impl/src/args.rs
@@ -25,7 +25,7 @@ pub fn arg_expand_all(at_args: &[String]) -> Vec<String> {
             Ok(arg) => args.extend(arg),
             Err(err) => rustc_session::early_error(
                 rustc_session::config::ErrorOutputType::default(),
-                &format!("Failed to load argument file: {err}"),
+                format!("Failed to load argument file: {err}"),
             ),
         }
     }
diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs
index 9b16f246193..6c204b894a6 100644
--- a/compiler/rustc_driver_impl/src/lib.rs
+++ b/compiler/rustc_driver_impl/src/lib.rs
@@ -256,6 +256,9 @@ fn run_compiler(
 
     let sopts = config::build_session_options(&matches);
 
+    // Set parallel mode before thread pool creation, which will create `Lock`s.
+    interface::set_thread_safe_mode(&sopts.unstable_opts);
+
     if let Some(ref code) = matches.opt_str("explain") {
         handle_explain(diagnostics_registry(), code, sopts.error_format);
         return Ok(());
@@ -319,7 +322,7 @@ fn run_compiler(
             1 => panic!("make_input should have provided valid inputs"),
             _ => early_error(
                 config.opts.error_format,
-                &format!(
+                format!(
                     "multiple input filenames provided (first two filenames are `{}` and `{}`)",
                     matches.free[0], matches.free[1],
                 ),
@@ -524,7 +527,7 @@ fn handle_explain(registry: Registry, code: &str, output: ErrorOutputType) {
             }
         }
         Err(InvalidErrorCode) => {
-            early_error(output, &format!("{code} is not a valid error code"));
+            early_error(output, format!("{code} is not a valid error code"));
         }
     }
 }
@@ -569,7 +572,7 @@ pub fn try_process_rlink(sess: &Session, compiler: &interface::Compiler) -> Comp
             let rlink_data = fs::read(file).unwrap_or_else(|err| {
                 sess.emit_fatal(RlinkUnableToRead { err });
             });
-            let codegen_results = match CodegenResults::deserialize_rlink(rlink_data) {
+            let codegen_results = match CodegenResults::deserialize_rlink(sess, rlink_data) {
                 Ok(codegen) => codegen,
                 Err(err) => {
                     match err {
@@ -583,10 +586,10 @@ pub fn try_process_rlink(sess: &Session, compiler: &interface::Compiler) -> Comp
                                 rlink_version,
                             })
                         }
-                        CodegenErrors::RustcVersionMismatch { rustc_version, current_version } => {
+                        CodegenErrors::RustcVersionMismatch { rustc_version } => {
                             sess.emit_fatal(RLinkRustcVersionMismatch {
                                 rustc_version,
-                                current_version,
+                                current_version: sess.cfg_version,
                             })
                         }
                     };
@@ -1099,7 +1102,7 @@ pub fn handle_options(args: &[String]) -> Option<getopts::Matches> {
                 .map(|(flag, _)| format!("{e}. Did you mean `-{flag} {opt}`?")),
             _ => None,
         };
-        early_error(ErrorOutputType::default(), &msg.unwrap_or_else(|| e.to_string()));
+        early_error(ErrorOutputType::default(), msg.unwrap_or_else(|| e.to_string()));
     });
 
     // For all options we just parsed, we check a few aspects:
@@ -1247,7 +1250,8 @@ pub fn install_ice_hook(bug_report_url: &'static str, extra_info: fn(&Handler))
         #[cfg(windows)]
         if let Some(msg) = info.payload().downcast_ref::<String>() {
             if msg.starts_with("failed printing to stdout: ") && msg.ends_with("(os error 232)") {
-                early_error_no_abort(ErrorOutputType::default(), &msg);
+                // the error code is already going to be reported when the panic unwinds up the stack
+                let _ = early_error_no_abort(ErrorOutputType::default(), msg.as_str());
                 return;
             }
         };
@@ -1339,7 +1343,7 @@ pub fn init_rustc_env_logger() {
 /// other than `RUSTC_LOG`.
 pub fn init_env_logger(env: &str) {
     if let Err(error) = rustc_log::init_env_logger(env) {
-        early_error(ErrorOutputType::default(), &error.to_string());
+        early_error(ErrorOutputType::default(), error.to_string());
     }
 }
 
@@ -1406,7 +1410,7 @@ pub fn main() -> ! {
                 arg.into_string().unwrap_or_else(|arg| {
                     early_error(
                         ErrorOutputType::default(),
-                        &format!("argument {i} is not valid Unicode: {arg:?}"),
+                        format!("argument {i} is not valid Unicode: {arg:?}"),
                     )
                 })
             })
diff --git a/compiler/rustc_error_messages/src/lib.rs b/compiler/rustc_error_messages/src/lib.rs
index 6c3f677ab8e..0accb4ab96f 100644
--- a/compiler/rustc_error_messages/src/lib.rs
+++ b/compiler/rustc_error_messages/src/lib.rs
@@ -11,7 +11,7 @@ extern crate tracing;
 use fluent_bundle::FluentResource;
 use fluent_syntax::parser::ParserError;
 use icu_provider_adapters::fallback::{LocaleFallbackProvider, LocaleFallbacker};
-use rustc_data_structures::sync::Lrc;
+use rustc_data_structures::sync::{IntoDynSyncSend, Lrc};
 use rustc_fluent_macro::fluent_messages;
 use rustc_macros::{Decodable, Encodable};
 use rustc_span::Span;
@@ -37,16 +37,17 @@ pub use unic_langid::{langid, LanguageIdentifier};
 
 fluent_messages! { "../messages.ftl" }
 
-pub type FluentBundle = fluent_bundle::bundle::FluentBundle<FluentResource, IntlLangMemoizer>;
+pub type FluentBundle =
+    IntoDynSyncSend<fluent_bundle::bundle::FluentBundle<FluentResource, IntlLangMemoizer>>;
 
-#[cfg(parallel_compiler)]
+#[cfg(not(parallel_compiler))]
 fn new_bundle(locales: Vec<LanguageIdentifier>) -> FluentBundle {
-    FluentBundle::new_concurrent(locales)
+    IntoDynSyncSend(fluent_bundle::bundle::FluentBundle::new(locales))
 }
 
-#[cfg(not(parallel_compiler))]
+#[cfg(parallel_compiler)]
 fn new_bundle(locales: Vec<LanguageIdentifier>) -> FluentBundle {
-    FluentBundle::new(locales)
+    IntoDynSyncSend(fluent_bundle::bundle::FluentBundle::new_concurrent(locales))
 }
 
 #[derive(Debug)]
diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs
index 68e57de5e08..3e38d6afb0b 100644
--- a/compiler/rustc_errors/src/emitter.rs
+++ b/compiler/rustc_errors/src/emitter.rs
@@ -2303,22 +2303,25 @@ impl EmitterWriter {
 
         // Colorize addition/replacements with green.
         for &SubstitutionHighlight { start, end } in highlight_parts {
-            // Account for tabs when highlighting (#87972).
-            let tabs: usize = line_to_add
-                .chars()
-                .take(start)
-                .map(|ch| match ch {
-                    '\t' => 3,
-                    _ => 0,
-                })
-                .sum();
-            buffer.set_style_range(
-                *row_num,
-                max_line_num_len + 3 + start + tabs,
-                max_line_num_len + 3 + end + tabs,
-                Style::Addition,
-                true,
-            );
+            // This is a no-op for empty ranges
+            if start != end {
+                // Account for tabs when highlighting (#87972).
+                let tabs: usize = line_to_add
+                    .chars()
+                    .take(start)
+                    .map(|ch| match ch {
+                        '\t' => 3,
+                        _ => 0,
+                    })
+                    .sum();
+                buffer.set_style_range(
+                    *row_num,
+                    max_line_num_len + 3 + start + tabs,
+                    max_line_num_len + 3 + end + tabs,
+                    Style::Addition,
+                    true,
+                );
+            }
         }
         *row_num += 1;
     }
diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs
index fcbd9a53b48..5a80024f19b 100644
--- a/compiler/rustc_errors/src/lib.rs
+++ b/compiler/rustc_errors/src/lib.rs
@@ -32,7 +32,7 @@ use emitter::{is_case_difference, Emitter, EmitterWriter};
 use registry::Registry;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet};
 use rustc_data_structures::stable_hasher::{Hash128, StableHasher};
-use rustc_data_structures::sync::{self, Lock, Lrc};
+use rustc_data_structures::sync::{self, IntoDynSyncSend, Lock, Lrc};
 use rustc_data_structures::AtomicRef;
 pub use rustc_error_messages::{
     fallback_fluent_bundle, fluent_bundle, DelayDm, DiagnosticMessage, FluentBundle,
@@ -330,12 +330,11 @@ impl CodeSuggestion {
                     });
                     buf.push_str(&part.snippet);
                     let cur_hi = sm.lookup_char_pos(part.span.hi());
-                    if cur_hi.line == cur_lo.line && !part.snippet.is_empty() {
-                        // Account for the difference between the width of the current code and the
-                        // snippet being suggested, so that the *later* suggestions are correctly
-                        // aligned on the screen.
-                        acc += len - (cur_hi.col.0 - cur_lo.col.0) as isize;
-                    }
+                    // Account for the difference between the width of the current code and the
+                    // snippet being suggested, so that the *later* suggestions are correctly
+                    // aligned on the screen. Note that cur_hi and cur_lo can be on different
+                    // lines, so cur_hi.col can be smaller than cur_lo.col
+                    acc += len - (cur_hi.col.0 as isize - cur_lo.col.0 as isize);
                     prev_hi = cur_hi;
                     prev_line = sf.get_line(prev_hi.line - 1);
                     for line in part.snippet.split('\n').skip(1) {
@@ -409,7 +408,7 @@ struct HandlerInner {
     err_count: usize,
     warn_count: usize,
     deduplicated_err_count: usize,
-    emitter: Box<dyn Emitter + sync::Send>,
+    emitter: IntoDynSyncSend<Box<dyn Emitter + sync::Send>>,
     delayed_span_bugs: Vec<DelayedDiagnostic>,
     delayed_good_path_bugs: Vec<DelayedDiagnostic>,
     /// This flag indicates that an expected diagnostic was emitted and suppressed.
@@ -478,6 +477,7 @@ pub enum StashKey {
     /// FRU syntax
     MaybeFruTypo,
     CallAssocMethod,
+    TraitMissingMethod,
 }
 
 fn default_track_diagnostic(d: &mut Diagnostic, f: &mut dyn FnMut(&mut Diagnostic)) {
@@ -605,7 +605,7 @@ impl Handler {
                 warn_count: 0,
                 deduplicated_err_count: 0,
                 deduplicated_warn_count: 0,
-                emitter,
+                emitter: IntoDynSyncSend(emitter),
                 delayed_span_bugs: Vec::new(),
                 delayed_good_path_bugs: Vec::new(),
                 suppressed_expected_diag: false,
@@ -1739,7 +1739,7 @@ impl DelayedDiagnostic {
     }
 
     fn decorate(mut self) -> Diagnostic {
-        self.inner.note(format!("delayed at {}", self.note));
+        self.inner.note(format!("delayed at {}\n{}", self.inner.emitted_at, self.note));
         self.inner
     }
 }
diff --git a/compiler/rustc_errors/src/tests.rs b/compiler/rustc_errors/src/tests.rs
index 52103e46097..0e729b71680 100644
--- a/compiler/rustc_errors/src/tests.rs
+++ b/compiler/rustc_errors/src/tests.rs
@@ -2,7 +2,7 @@ use crate::error::{TranslateError, TranslateErrorKind};
 use crate::fluent_bundle::*;
 use crate::translation::Translate;
 use crate::FluentBundle;
-use rustc_data_structures::sync::Lrc;
+use rustc_data_structures::sync::{IntoDynSyncSend, Lrc};
 use rustc_error_messages::fluent_bundle::resolver::errors::{ReferenceKind, ResolverError};
 use rustc_error_messages::langid;
 use rustc_error_messages::DiagnosticMessage;
@@ -27,10 +27,14 @@ fn make_dummy(ftl: &'static str) -> Dummy {
     let langid_en = langid!("en-US");
 
     #[cfg(parallel_compiler)]
-    let mut bundle = FluentBundle::new_concurrent(vec![langid_en]);
+    let mut bundle: FluentBundle =
+        IntoDynSyncSend(crate::fluent_bundle::bundle::FluentBundle::new_concurrent(vec![
+            langid_en,
+        ]));
 
     #[cfg(not(parallel_compiler))]
-    let mut bundle = FluentBundle::new(vec![langid_en]);
+    let mut bundle: FluentBundle =
+        IntoDynSyncSend(crate::fluent_bundle::bundle::FluentBundle::new(vec![langid_en]));
 
     bundle.add_resource(resource).expect("Failed to add FTL resources to the bundle.");
 
diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs
index c1cca89df8c..fd721749066 100644
--- a/compiler/rustc_expand/src/base.rs
+++ b/compiler/rustc_expand/src/base.rs
@@ -15,7 +15,8 @@ use rustc_attr::{self as attr, Deprecation, Stability};
 use rustc_data_structures::fx::FxIndexMap;
 use rustc_data_structures::sync::{self, Lrc};
 use rustc_errors::{
-    Applicability, DiagnosticBuilder, ErrorGuaranteed, IntoDiagnostic, MultiSpan, PResult,
+    Applicability, DiagnosticBuilder, DiagnosticMessage, ErrorGuaranteed, IntoDiagnostic,
+    MultiSpan, PResult,
 };
 use rustc_lint_defs::builtin::PROC_MACRO_BACK_COMPAT;
 use rustc_lint_defs::{BufferedEarlyLint, BuiltinLintDiagnostics, RegisteredTools};
@@ -653,13 +654,13 @@ pub enum SyntaxExtensionKind {
     /// A token-based function-like macro.
     Bang(
         /// An expander with signature TokenStream -> TokenStream.
-        Box<dyn BangProcMacro + sync::Sync + sync::Send>,
+        Box<dyn BangProcMacro + sync::DynSync + sync::DynSend>,
     ),
 
     /// An AST-based function-like macro.
     LegacyBang(
         /// An expander with signature TokenStream -> AST.
-        Box<dyn TTMacroExpander + sync::Sync + sync::Send>,
+        Box<dyn TTMacroExpander + sync::DynSync + sync::DynSend>,
     ),
 
     /// A token-based attribute macro.
@@ -667,7 +668,7 @@ pub enum SyntaxExtensionKind {
         /// An expander with signature (TokenStream, TokenStream) -> TokenStream.
         /// The first TokenSteam is the attribute itself, the second is the annotated item.
         /// The produced TokenSteam replaces the input TokenSteam.
-        Box<dyn AttrProcMacro + sync::Sync + sync::Send>,
+        Box<dyn AttrProcMacro + sync::DynSync + sync::DynSend>,
     ),
 
     /// An AST-based attribute macro.
@@ -675,7 +676,7 @@ pub enum SyntaxExtensionKind {
         /// An expander with signature (AST, AST) -> AST.
         /// The first AST fragment is the attribute itself, the second is the annotated item.
         /// The produced AST fragment replaces the input AST fragment.
-        Box<dyn MultiItemModifier + sync::Sync + sync::Send>,
+        Box<dyn MultiItemModifier + sync::DynSync + sync::DynSend>,
     ),
 
     /// A trivial attribute "macro" that does nothing,
@@ -692,14 +693,14 @@ pub enum SyntaxExtensionKind {
         /// is handled identically to `LegacyDerive`. It should be migrated to
         /// a token-based representation like `Bang` and `Attr`, instead of
         /// using `MultiItemModifier`.
-        Box<dyn MultiItemModifier + sync::Sync + sync::Send>,
+        Box<dyn MultiItemModifier + sync::DynSync + sync::DynSend>,
     ),
 
     /// An AST-based derive macro.
     LegacyDerive(
         /// An expander with signature AST -> AST.
         /// The produced AST fragment is appended to the input AST fragment.
-        Box<dyn MultiItemModifier + sync::Sync + sync::Send>,
+        Box<dyn MultiItemModifier + sync::DynSync + sync::DynSend>,
     ),
 }
 
@@ -1110,7 +1111,7 @@ impl<'a> ExtCtxt<'a> {
     pub fn struct_span_err<S: Into<MultiSpan>>(
         &self,
         sp: S,
-        msg: &str,
+        msg: impl Into<DiagnosticMessage>,
     ) -> DiagnosticBuilder<'a, ErrorGuaranteed> {
         self.sess.parse_sess.span_diagnostic.struct_span_err(sp, msg)
     }
@@ -1132,14 +1133,14 @@ impl<'a> ExtCtxt<'a> {
     /// Compilation will be stopped in the near future (at the end of
     /// the macro expansion phase).
     #[rustc_lint_diagnostics]
-    pub fn span_err<S: Into<MultiSpan>>(&self, sp: S, msg: &str) {
+    pub fn span_err<S: Into<MultiSpan>>(&self, sp: S, msg: impl Into<DiagnosticMessage>) {
         self.sess.parse_sess.span_diagnostic.span_err(sp, msg);
     }
     #[rustc_lint_diagnostics]
-    pub fn span_warn<S: Into<MultiSpan>>(&self, sp: S, msg: &str) {
+    pub fn span_warn<S: Into<MultiSpan>>(&self, sp: S, msg: impl Into<DiagnosticMessage>) {
         self.sess.parse_sess.span_diagnostic.span_warn(sp, msg);
     }
-    pub fn span_bug<S: Into<MultiSpan>>(&self, sp: S, msg: &str) -> ! {
+    pub fn span_bug<S: Into<MultiSpan>>(&self, sp: S, msg: impl Into<DiagnosticMessage>) -> ! {
         self.sess.parse_sess.span_diagnostic.span_bug(sp, msg);
     }
     pub fn trace_macros_diag(&mut self) {
diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs
index 7c78970345a..5d369a1879a 100644
--- a/compiler/rustc_expand/src/expand.rs
+++ b/compiler/rustc_expand/src/expand.rs
@@ -722,7 +722,11 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
                                     });
                                 }
                             };
-                            if fragment_kind == AstFragmentKind::Expr && items.is_empty() {
+                            if matches!(
+                                fragment_kind,
+                                AstFragmentKind::Expr | AstFragmentKind::MethodReceiverExpr
+                            ) && items.is_empty()
+                            {
                                 self.cx.emit_err(RemoveExprNotSupported { span });
                                 fragment_kind.dummy(span)
                             } else {
@@ -1664,7 +1668,7 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
                         &UNUSED_ATTRIBUTES,
                         attr.span,
                         self.cx.current_expansion.lint_node_id,
-                        &format!("unused attribute `{}`", attr_name),
+                        format!("unused attribute `{}`", attr_name),
                         BuiltinLintDiagnostics::UnusedBuiltinAttribute {
                             attr_name,
                             macro_name: pprust::path_to_string(&call.path),
diff --git a/compiler/rustc_expand/src/mbe/diagnostics.rs b/compiler/rustc_expand/src/mbe/diagnostics.rs
index 35572292271..cb8b4899e48 100644
--- a/compiler/rustc_expand/src/mbe/diagnostics.rs
+++ b/compiler/rustc_expand/src/mbe/diagnostics.rs
@@ -48,7 +48,7 @@ pub(super) fn failed_to_match_macro<'cx>(
 
     let span = token.span.substitute_dummy(sp);
 
-    let mut err = cx.struct_span_err(span, &parse_failure_msg(&token));
+    let mut err = cx.struct_span_err(span, parse_failure_msg(&token));
     err.span_label(span, label);
     if !def_span.is_dummy() && !cx.source_map().is_imported(def_span) {
         err.span_label(cx.source_map().guess_head_span(def_span), "when calling this macro");
@@ -170,7 +170,7 @@ impl<'a, 'cx, 'matcher> Tracker<'matcher> for CollectTrackerAndEmitter<'a, 'cx,
             }
             Error(err_sp, msg) => {
                 let span = err_sp.substitute_dummy(self.root_span);
-                self.cx.struct_span_err(span, msg).emit();
+                self.cx.struct_span_err(span, msg.as_str()).emit();
                 self.result = Some(DummyResult::any(span));
             }
             ErrorReported(_) => self.result = Some(DummyResult::any(self.root_span)),
diff --git a/compiler/rustc_expand/src/mbe/macro_check.rs b/compiler/rustc_expand/src/mbe/macro_check.rs
index 75b6396f0be..34f998274e9 100644
--- a/compiler/rustc_expand/src/mbe/macro_check.rs
+++ b/compiler/rustc_expand/src/mbe/macro_check.rs
@@ -110,7 +110,7 @@ use crate::mbe::{KleeneToken, TokenTree};
 use rustc_ast::token::{Delimiter, Token, TokenKind};
 use rustc_ast::{NodeId, DUMMY_NODE_ID};
 use rustc_data_structures::fx::FxHashMap;
-use rustc_errors::MultiSpan;
+use rustc_errors::{DiagnosticMessage, MultiSpan};
 use rustc_session::lint::builtin::{META_VARIABLE_MISUSE, MISSING_FRAGMENT_SPECIFIER};
 use rustc_session::parse::ParseSess;
 use rustc_span::symbol::kw;
@@ -593,7 +593,7 @@ fn check_ops_is_prefix(
             return;
         }
     }
-    buffer_lint(sess, span.into(), node_id, &format!("unknown macro variable `{}`", name));
+    buffer_lint(sess, span.into(), node_id, format!("unknown macro variable `{}`", name));
 }
 
 /// Returns whether `binder_ops` is a prefix of `occurrence_ops`.
@@ -626,7 +626,7 @@ fn ops_is_prefix(
         if i >= occurrence_ops.len() {
             let mut span = MultiSpan::from_span(span);
             span.push_span_label(binder.span, "expected repetition");
-            let message = &format!("variable '{}' is still repeating at this depth", name);
+            let message = format!("variable '{}' is still repeating at this depth", name);
             buffer_lint(sess, span, node_id, message);
             return;
         }
@@ -642,7 +642,12 @@ fn ops_is_prefix(
     }
 }
 
-fn buffer_lint(sess: &ParseSess, span: MultiSpan, node_id: NodeId, message: &str) {
+fn buffer_lint(
+    sess: &ParseSess,
+    span: MultiSpan,
+    node_id: NodeId,
+    message: impl Into<DiagnosticMessage>,
+) {
     // Macros loaded from other crates have dummy node ids.
     if node_id != DUMMY_NODE_ID {
         sess.buffer_lint(&META_VARIABLE_MISUSE, span, node_id, message);
diff --git a/compiler/rustc_expand/src/mbe/transcribe.rs b/compiler/rustc_expand/src/mbe/transcribe.rs
index a07cb65170d..d523d3eacbe 100644
--- a/compiler/rustc_expand/src/mbe/transcribe.rs
+++ b/compiler/rustc_expand/src/mbe/transcribe.rs
@@ -510,7 +510,7 @@ fn out_of_bounds_err<'a>(
              must be less than {max}"
         )
     };
-    cx.struct_span_err(span, &msg)
+    cx.struct_span_err(span, msg)
 }
 
 fn transcribe_metavar_expr<'a>(
diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs
index f4615445f8e..57e55752027 100644
--- a/compiler/rustc_feature/src/active.rs
+++ b/compiler/rustc_feature/src/active.rs
@@ -321,6 +321,8 @@ declare_features! (
     (active, c_unwind, "1.52.0", Some(74990), None),
     /// Allows using C-variadics.
     (active, c_variadic, "1.34.0", Some(44930), None),
+    /// Allows the use of `#[cfg(overflow_checks)` to check if integer overflow behaviour.
+    (active, cfg_overflow_checks, "CURRENT_RUSTC_VERSION", Some(111466), None),
     /// Allows the use of `#[cfg(sanitize = "option")]`; set when -Zsanitizer is used.
     (active, cfg_sanitize, "1.41.0", Some(39699), None),
     /// Allows `cfg(target_abi = "...")`.
@@ -336,7 +338,7 @@ declare_features! (
     /// Allow conditional compilation depending on rust version
     (active, cfg_version, "1.45.0", Some(64796), None),
     /// Allows to use the `#[cfi_encoding = ""]` attribute.
-    (active, cfi_encoding, "1.69.0", Some(89653), None),
+    (active, cfi_encoding, "CURRENT_RUSTC_VERSION", Some(89653), None),
     /// Allows `for<...>` on closures and generators.
     (active, closure_lifetime_binder, "1.64.0", Some(97362), None),
     /// Allows `#[track_caller]` on closures and generators.
diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs
index fe05d4590e7..61cfbf5c5e5 100644
--- a/compiler/rustc_feature/src/builtin_attrs.rs
+++ b/compiler/rustc_feature/src/builtin_attrs.rs
@@ -24,6 +24,7 @@ pub type GatedCfg = (Symbol, Symbol, GateFn);
 /// `cfg(...)`'s that are feature gated.
 const GATED_CFGS: &[GatedCfg] = &[
     // (name in cfg, feature, function to check if the feature is enabled)
+    (sym::overflow_checks, sym::cfg_overflow_checks, cfg_fn!(cfg_overflow_checks)),
     (sym::target_abi, sym::cfg_target_abi, cfg_fn!(cfg_target_abi)),
     (sym::target_thread_local, sym::cfg_target_thread_local, cfg_fn!(cfg_target_thread_local)),
     (
diff --git a/compiler/rustc_hir/src/errors.rs b/compiler/rustc_hir/src/errors.rs
deleted file mode 100644
index e593ed1044a..00000000000
--- a/compiler/rustc_hir/src/errors.rs
+++ /dev/null
@@ -1,10 +0,0 @@
-use crate::LangItem;
-
-#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, Encodable, Decodable)]
-pub struct LangItemError(pub LangItem);
-
-impl ToString for LangItemError {
-    fn to_string(&self) -> String {
-        format!("requires `{}` lang_item", self.0.name())
-    }
-}
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index 38cd5865cc3..932f0396282 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -2662,7 +2662,10 @@ pub enum OpaqueTyOrigin {
     /// `async fn`
     AsyncFn(LocalDefId),
     /// type aliases: `type Foo = impl Trait;`
-    TyAlias,
+    TyAlias {
+        /// associated types in impl blocks for traits.
+        in_assoc_ty: bool,
+    },
 }
 
 /// The various kinds of types recognized by the compiler.
diff --git a/compiler/rustc_hir/src/lang_items.rs b/compiler/rustc_hir/src/lang_items.rs
index 1f08befb180..4b3bc816b95 100644
--- a/compiler/rustc_hir/src/lang_items.rs
+++ b/compiler/rustc_hir/src/lang_items.rs
@@ -8,7 +8,6 @@
 //! * Functions called by the compiler itself.
 
 use crate::def_id::DefId;
-use crate::errors::LangItemError;
 use crate::{MethodKind, Target};
 
 use rustc_ast as ast;
@@ -42,13 +41,6 @@ impl LanguageItems {
         self.items[item as usize] = Some(def_id);
     }
 
-    /// Requires that a given `LangItem` was bound and returns the corresponding `DefId`.
-    /// If it wasn't bound, e.g. due to a missing `#[lang = "<it.name()>"]`,
-    /// returns an error encapsulating the `LangItem`.
-    pub fn require(&self, it: LangItem) -> Result<DefId, LangItemError> {
-        self.get(it).ok_or_else(|| LangItemError(it))
-    }
-
     pub fn iter(&self) -> impl Iterator<Item = (LangItem, DefId)> + '_ {
         self.items
             .iter()
diff --git a/compiler/rustc_hir/src/lib.rs b/compiler/rustc_hir/src/lib.rs
index 98d967cc0b8..616de57dc63 100644
--- a/compiler/rustc_hir/src/lib.rs
+++ b/compiler/rustc_hir/src/lib.rs
@@ -30,7 +30,6 @@ pub mod def;
 pub mod def_path_hash_map;
 pub mod definitions;
 pub mod diagnostic_items;
-pub mod errors;
 pub use rustc_span::def_id;
 mod hir;
 pub mod hir_id;
diff --git a/compiler/rustc_hir/src/tests.rs b/compiler/rustc_hir/src/tests.rs
index c7ac01b3334..a40a0178710 100644
--- a/compiler/rustc_hir/src/tests.rs
+++ b/compiler/rustc_hir/src/tests.rs
@@ -10,13 +10,13 @@ fn def_path_hash_depends_on_crate_id() {
     // the crate-id of the defining crate. This is a desirable property
     // because the crate-id can be more easily changed than the DefPath
     // of an item, so, in the case of a crate-local DefPathHash collision,
-    // the user can simply "role the dice again" for all DefPathHashes in
+    // the user can simply "roll the dice again" for all DefPathHashes in
     // the crate by changing the crate disambiguator (e.g. via bumping the
     // crate's version number).
 
     create_session_if_not_set_then(Edition::Edition2024, |_| {
-        let id0 = StableCrateId::new(Symbol::intern("foo"), false, vec!["1".to_string()]);
-        let id1 = StableCrateId::new(Symbol::intern("foo"), false, vec!["2".to_string()]);
+        let id0 = StableCrateId::new(Symbol::intern("foo"), false, vec!["1".to_string()], "");
+        let id1 = StableCrateId::new(Symbol::intern("foo"), false, vec!["2".to_string()], "");
 
         let h0 = mk_test_hash(id0);
         let h1 = mk_test_hash(id1);
diff --git a/compiler/rustc_hir_analysis/src/astconv/generics.rs b/compiler/rustc_hir_analysis/src/astconv/generics.rs
index ed011b9086a..39d1d1f2de5 100644
--- a/compiler/rustc_hir_analysis/src/astconv/generics.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/generics.rs
@@ -24,7 +24,7 @@ fn generic_arg_mismatch_err(
     arg: &GenericArg<'_>,
     param: &GenericParamDef,
     possible_ordering_error: bool,
-    help: Option<&str>,
+    help: Option<String>,
 ) -> ErrorGuaranteed {
     let sess = tcx.sess;
     let mut err = struct_span_err!(
@@ -300,7 +300,7 @@ pub fn create_substs_for_generic_args<'tcx, 'a>(
                                     arg,
                                     param,
                                     !args_iter.clone().is_sorted_by_key(|arg| arg.to_ord()),
-                                    Some(&format!(
+                                    Some(format!(
                                         "reorder the arguments: {}: `<{}>`",
                                         param_types_present
                                             .into_iter()
diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs
index 6ac1df6a079..cf082f1ffaa 100644
--- a/compiler/rustc_hir_analysis/src/astconv/mod.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs
@@ -19,7 +19,7 @@ use rustc_ast::TraitObjectSyntax;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_errors::{
     struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, FatalError,
-    MultiSpan,
+    MultiSpan, StashKey,
 };
 use rustc_hir as hir;
 use rustc_hir::def::{CtorOf, DefKind, Namespace, Res};
@@ -38,7 +38,6 @@ use rustc_middle::ty::{self, Const, IsSuggestable, Ty, TyCtxt, TypeVisitableExt}
 use rustc_middle::ty::{DynKind, ToPredicate};
 use rustc_session::lint::builtin::{AMBIGUOUS_ASSOCIATED_ITEMS, BARE_TRAIT_OBJECTS};
 use rustc_span::edit_distance::find_best_match_for_name;
-use rustc_span::edition::Edition;
 use rustc_span::symbol::{kw, Ident, Symbol};
 use rustc_span::{sym, Span, DUMMY_SP};
 use rustc_target::spec::abi;
@@ -464,7 +463,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                             self.astconv.ct_infer(ty, Some(param), inf.span).into()
                         } else {
                             self.inferred_params.push(inf.span);
-                            tcx.const_error(ty).into()
+                            tcx.const_error_misc(ty).into()
                         }
                     }
                     _ => unreachable!(),
@@ -518,7 +517,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                             .no_bound_vars()
                             .expect("const parameter types cannot be generic");
                         if let Err(guar) = ty.error_reported() {
-                            return tcx.const_error_with_guaranteed(ty, guar).into();
+                            return tcx.const_error(ty, guar).into();
                         }
                         if !infer_args && has_default {
                             tcx.const_param_default(param.def_id).subst(tcx, substs.unwrap()).into()
@@ -527,7 +526,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                                 self.astconv.ct_infer(ty, Some(param), self.span).into()
                             } else {
                                 // We've already errored above about the mismatch.
-                                tcx.const_error(ty).into()
+                                tcx.const_error_misc(ty).into()
                             }
                         }
                     }
@@ -1387,7 +1386,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                         term = match def_kind {
                             hir::def::DefKind::AssocTy => tcx.ty_error(reported).into(),
                             hir::def::DefKind::AssocConst => tcx
-                                .const_error_with_guaranteed(
+                                .const_error(
                                     tcx.type_of(assoc_item_def_id)
                                         .subst(tcx, projection_ty.skip_binder().substs),
                                     reported,
@@ -3718,7 +3717,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                 ));
             }
 
-            if self_ty.span.edition() >= Edition::Edition2021 {
+            if self_ty.span.edition().rust_2021() {
                 let msg = "trait objects must include the `dyn` keyword";
                 let label = "add `dyn` keyword before this trait";
                 let mut diag =
@@ -3732,7 +3731,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                 }
                 // check if the impl trait that we are considering is a impl of a local trait
                 self.maybe_lint_blanket_trait_impl(&self_ty, &mut diag);
-                diag.emit();
+                diag.stash(self_ty.span, StashKey::TraitMissingMethod);
             } else {
                 let msg = "trait objects without an explicit `dyn` are deprecated";
                 tcx.struct_span_lint_hir(
diff --git a/compiler/rustc_hir_analysis/src/autoderef.rs b/compiler/rustc_hir_analysis/src/autoderef.rs
index 1cf93c86f4f..d6d1498d708 100644
--- a/compiler/rustc_hir_analysis/src/autoderef.rs
+++ b/compiler/rustc_hir_analysis/src/autoderef.rs
@@ -1,6 +1,5 @@
 use crate::errors::AutoDerefReachedRecursionLimit;
 use crate::traits::query::evaluate_obligation::InferCtxtExt;
-use crate::traits::NormalizeExt;
 use crate::traits::{self, TraitEngine, TraitEngineExt};
 use rustc_infer::infer::InferCtxt;
 use rustc_middle::ty::TypeVisitableExt;
@@ -9,6 +8,7 @@ use rustc_session::Limit;
 use rustc_span::def_id::LocalDefId;
 use rustc_span::def_id::LOCAL_CRATE;
 use rustc_span::Span;
+use rustc_trait_selection::traits::StructurallyNormalizeExt;
 
 #[derive(Copy, Clone, Debug)]
 pub enum AutoderefKind {
@@ -66,14 +66,27 @@ impl<'a, 'tcx> Iterator for Autoderef<'a, 'tcx> {
         }
 
         // Otherwise, deref if type is derefable:
-        let (kind, new_ty) =
-            if let Some(mt) = self.state.cur_ty.builtin_deref(self.include_raw_pointers) {
-                (AutoderefKind::Builtin, mt.ty)
-            } else if let Some(ty) = self.overloaded_deref_ty(self.state.cur_ty) {
-                (AutoderefKind::Overloaded, ty)
+        let (kind, new_ty) = if let Some(ty::TypeAndMut { ty, .. }) =
+            self.state.cur_ty.builtin_deref(self.include_raw_pointers)
+        {
+            debug_assert_eq!(ty, self.infcx.resolve_vars_if_possible(ty));
+            // NOTE: we may still need to normalize the built-in deref in case
+            // we have some type like `&<Ty as Trait>::Assoc`, since users of
+            // autoderef expect this type to have been structurally normalized.
+            if self.infcx.tcx.trait_solver_next()
+                && let ty::Alias(ty::Projection, _) = ty.kind()
+            {
+                let (normalized_ty, obligations) = self.structurally_normalize(ty)?;
+                self.state.obligations.extend(obligations);
+                (AutoderefKind::Builtin, normalized_ty)
             } else {
-                return None;
-            };
+                (AutoderefKind::Builtin, ty)
+            }
+        } else if let Some(ty) = self.overloaded_deref_ty(self.state.cur_ty) {
+            (AutoderefKind::Overloaded, ty)
+        } else {
+            return None;
+        };
 
         if new_ty.references_error() {
             return None;
@@ -119,14 +132,11 @@ impl<'a, 'tcx> Autoderef<'a, 'tcx> {
 
     fn overloaded_deref_ty(&mut self, ty: Ty<'tcx>) -> Option<Ty<'tcx>> {
         debug!("overloaded_deref_ty({:?})", ty);
-
         let tcx = self.infcx.tcx;
 
         // <ty as Deref>
         let trait_ref = ty::TraitRef::new(tcx, tcx.lang_items().deref_trait()?, [ty]);
-
         let cause = traits::ObligationCause::misc(self.span, self.body_id);
-
         let obligation = traits::Obligation::new(
             tcx,
             cause.clone(),
@@ -138,26 +148,48 @@ impl<'a, 'tcx> Autoderef<'a, 'tcx> {
             return None;
         }
 
-        let normalized_ty = self
+        let (normalized_ty, obligations) =
+            self.structurally_normalize(tcx.mk_projection(tcx.lang_items().deref_target()?, [ty]))?;
+        debug!("overloaded_deref_ty({:?}) = ({:?}, {:?})", ty, normalized_ty, obligations);
+        self.state.obligations.extend(obligations);
+
+        Some(self.infcx.resolve_vars_if_possible(normalized_ty))
+    }
+
+    #[instrument(level = "debug", skip(self), ret)]
+    pub fn structurally_normalize(
+        &self,
+        ty: Ty<'tcx>,
+    ) -> Option<(Ty<'tcx>, Vec<traits::PredicateObligation<'tcx>>)> {
+        let tcx = self.infcx.tcx;
+        let mut fulfill_cx = <dyn TraitEngine<'tcx>>::new_in_snapshot(tcx);
+
+        let cause = traits::ObligationCause::misc(self.span, self.body_id);
+        let normalized_ty = match self
             .infcx
             .at(&cause, self.param_env)
-            .normalize(tcx.mk_projection(tcx.lang_items().deref_target()?, trait_ref.substs));
-        let mut fulfillcx = <dyn TraitEngine<'tcx>>::new_in_snapshot(tcx);
-        let normalized_ty =
-            normalized_ty.into_value_registering_obligations(self.infcx, &mut *fulfillcx);
-        let errors = fulfillcx.select_where_possible(&self.infcx);
+            .structurally_normalize(ty, &mut *fulfill_cx)
+        {
+            Ok(normalized_ty) => normalized_ty,
+            Err(errors) => {
+                // This shouldn't happen, except for evaluate/fulfill mismatches,
+                // but that's not a reason for an ICE (`predicate_may_hold` is conservative
+                // by design).
+                debug!(?errors, "encountered errors while fulfilling");
+                return None;
+            }
+        };
+
+        let errors = fulfill_cx.select_where_possible(&self.infcx);
         if !errors.is_empty() {
             // This shouldn't happen, except for evaluate/fulfill mismatches,
             // but that's not a reason for an ICE (`predicate_may_hold` is conservative
             // by design).
-            debug!("overloaded_deref_ty: encountered errors {:?} while fulfilling", errors);
+            debug!(?errors, "encountered errors while fulfilling");
             return None;
         }
-        let obligations = fulfillcx.pending_obligations();
-        debug!("overloaded_deref_ty({:?}) = ({:?}, {:?})", ty, normalized_ty, obligations);
-        self.state.obligations.extend(obligations);
 
-        Some(self.infcx.resolve_vars_if_possible(normalized_ty))
+        Some((normalized_ty, fulfill_cx.pending_obligations()))
     }
 
     /// Returns the final type we ended up with, which may be an inference
diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs
index 5187e63f8e3..d3495d3dbd7 100644
--- a/compiler/rustc_hir_analysis/src/check/check.rs
+++ b/compiler/rustc_hir_analysis/src/check/check.rs
@@ -397,7 +397,7 @@ fn check_opaque_meets_bounds<'tcx>(
 ) {
     let defining_use_anchor = match *origin {
         hir::OpaqueTyOrigin::FnReturn(did) | hir::OpaqueTyOrigin::AsyncFn(did) => did,
-        hir::OpaqueTyOrigin::TyAlias => def_id,
+        hir::OpaqueTyOrigin::TyAlias { .. } => tcx.impl_trait_parent(def_id),
     };
     let param_env = tcx.param_env(defining_use_anchor);
 
@@ -455,10 +455,10 @@ fn check_opaque_meets_bounds<'tcx>(
         // They can only be referenced as `<Opaque<T> as Trait<&'static T>>::AssocTy`.
         // We don't have to check them here because their well-formedness follows from the WF of
         // the projection input types in the defining- and use-sites.
-        hir::OpaqueTyOrigin::TyAlias
+        hir::OpaqueTyOrigin::TyAlias { .. }
             if tcx.def_kind(tcx.parent(def_id.to_def_id())) == DefKind::OpaqueTy => {}
         // Can have different predicates to their defining use
-        hir::OpaqueTyOrigin::TyAlias => {
+        hir::OpaqueTyOrigin::TyAlias { .. } => {
             let wf_tys = ocx.assumed_wf_types(param_env, span, def_id);
             let implied_bounds = infcx.implied_bounds_tys(param_env, def_id, wf_tys);
             let outlives_env = OutlivesEnvironment::with_bounds(param_env, implied_bounds);
@@ -1514,8 +1514,8 @@ fn opaque_type_cycle_error(
                     }
                     if tcx.sess.opts.unstable_opts.drop_tracking_mir
                         && let DefKind::Generator = tcx.def_kind(closure_def_id)
+                        && let Some(generator_layout) = tcx.mir_generator_witnesses(closure_def_id)
                     {
-                        let generator_layout = tcx.mir_generator_witnesses(closure_def_id);
                         for interior_ty in &generator_layout.field_tys {
                             label_match(interior_ty.ty, interior_ty.source_info.span);
                         }
diff --git a/compiler/rustc_hir_analysis/src/check/dropck.rs b/compiler/rustc_hir_analysis/src/check/dropck.rs
index 5ba1ca1c807..e0ba255cc06 100644
--- a/compiler/rustc_hir_analysis/src/check/dropck.rs
+++ b/compiler/rustc_hir_analysis/src/check/dropck.rs
@@ -6,7 +6,7 @@ use rustc_errors::{struct_span_err, ErrorGuaranteed};
 use rustc_infer::infer::outlives::env::OutlivesEnvironment;
 use rustc_infer::infer::{RegionResolutionError, TyCtxtInferExt};
 use rustc_middle::ty::subst::SubstsRef;
-use rustc_middle::ty::util::IgnoreRegions;
+use rustc_middle::ty::util::CheckRegions;
 use rustc_middle::ty::{self, TyCtxt};
 use rustc_trait_selection::traits::{self, ObligationCtxt};
 
@@ -81,7 +81,7 @@ fn ensure_drop_params_and_item_params_correspond<'tcx>(
     self_type_did: DefId,
     adt_to_impl_substs: SubstsRef<'tcx>,
 ) -> Result<(), ErrorGuaranteed> {
-    let Err(arg) = tcx.uses_unique_generic_params(adt_to_impl_substs, IgnoreRegions::No) else {
+    let Err(arg) = tcx.uses_unique_generic_params(adt_to_impl_substs, CheckRegions::OnlyEarlyBound) else {
         return Ok(())
     };
 
diff --git a/compiler/rustc_hir_analysis/src/check/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs
index 08154cdae47..3971a4c01d6 100644
--- a/compiler/rustc_hir_analysis/src/check/mod.rs
+++ b/compiler/rustc_hir_analysis/src/check/mod.rs
@@ -78,7 +78,7 @@ use rustc_errors::{pluralize, struct_span_err, Diagnostic, DiagnosticBuilder};
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_hir::intravisit::Visitor;
 use rustc_index::bit_set::BitSet;
-use rustc_middle::ty::query::Providers;
+use rustc_middle::query::Providers;
 use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_middle::ty::{InternalSubsts, SubstsRef};
 use rustc_session::parse::feature_err;
diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
index 862f0a9b0e2..8918553e5f9 100644
--- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs
+++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
@@ -12,7 +12,7 @@ use rustc_infer::infer::outlives::env::{OutlivesEnvironment, RegionBoundPairs};
 use rustc_infer::infer::outlives::obligations::TypeOutlives;
 use rustc_infer::infer::{self, InferCtxt, TyCtxtInferExt};
 use rustc_middle::mir::ConstraintCategory;
-use rustc_middle::ty::query::Providers;
+use rustc_middle::query::Providers;
 use rustc_middle::ty::trait_def::TraitSpecializationKind;
 use rustc_middle::ty::{
     self, AdtKind, GenericParamDefKind, Ty, TyCtxt, TypeFoldable, TypeSuperVisitable,
diff --git a/compiler/rustc_hir_analysis/src/coherence/builtin.rs b/compiler/rustc_hir_analysis/src/coherence/builtin.rs
index d05d8508408..a98d8e17153 100644
--- a/compiler/rustc_hir_analysis/src/coherence/builtin.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/builtin.rs
@@ -298,9 +298,7 @@ pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: LocalDefId) -> Coe
 
     let coerce_unsized_trait = tcx.require_lang_item(LangItem::CoerceUnsized, Some(span));
 
-    let unsize_trait = tcx.lang_items().require(LangItem::Unsize).unwrap_or_else(|err| {
-        tcx.sess.fatal(format!("`CoerceUnsized` implementation {}", err.to_string()));
-    });
+    let unsize_trait = tcx.require_lang_item(LangItem::Unsize, Some(span));
 
     let source = tcx.type_of(impl_did).subst_identity();
     let trait_ref = tcx.impl_trait_ref(impl_did).unwrap().subst_identity();
diff --git a/compiler/rustc_hir_analysis/src/coherence/mod.rs b/compiler/rustc_hir_analysis/src/coherence/mod.rs
index cd2ec2bef20..4524b87a418 100644
--- a/compiler/rustc_hir_analysis/src/coherence/mod.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/mod.rs
@@ -8,7 +8,7 @@
 use crate::errors;
 use rustc_errors::{error_code, struct_span_err};
 use rustc_hir::def_id::{DefId, LocalDefId};
-use rustc_middle::ty::query::Providers;
+use rustc_middle::query::Providers;
 use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt};
 use rustc_span::sym;
 use rustc_trait_selection::traits;
diff --git a/compiler/rustc_hir_analysis/src/coherence/orphan.rs b/compiler/rustc_hir_analysis/src/coherence/orphan.rs
index 272177dfbd0..23beacd2a8c 100644
--- a/compiler/rustc_hir_analysis/src/coherence/orphan.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/orphan.rs
@@ -6,7 +6,7 @@ use rustc_errors::{struct_span_err, DelayDm};
 use rustc_errors::{Diagnostic, ErrorGuaranteed};
 use rustc_hir as hir;
 use rustc_middle::ty::subst::InternalSubsts;
-use rustc_middle::ty::util::IgnoreRegions;
+use rustc_middle::ty::util::CheckRegions;
 use rustc_middle::ty::{
     self, AliasKind, ImplPolarity, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt,
     TypeVisitor,
@@ -507,7 +507,7 @@ fn lint_auto_trait_impl<'tcx>(
     // Impls which completely cover a given root type are fine as they
     // disable auto impls entirely. So only lint if the substs
     // are not a permutation of the identity substs.
-    let Err(arg) = tcx.uses_unique_generic_params(substs, IgnoreRegions::Yes) else {
+    let Err(arg) = tcx.uses_unique_generic_params(substs, CheckRegions::No) else {
         // ok
         return;
     };
diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs
index b65817ee95e..22502bd4fdb 100644
--- a/compiler/rustc_hir_analysis/src/collect.rs
+++ b/compiler/rustc_hir_analysis/src/collect.rs
@@ -28,7 +28,7 @@ use rustc_hir::{GenericParamKind, Node};
 use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
 use rustc_infer::traits::ObligationCause;
 use rustc_middle::hir::nested_filter;
-use rustc_middle::ty::query::Providers;
+use rustc_middle::query::Providers;
 use rustc_middle::ty::util::{Discr, IntTypeExt};
 use rustc_middle::ty::{self, AdtKind, Const, IsSuggestable, ToPredicate, Ty, TyCtxt};
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
@@ -73,7 +73,6 @@ pub fn provide(providers: &mut Providers) {
         fn_sig,
         impl_trait_ref,
         impl_polarity,
-        is_foreign_item,
         generator_kind,
         collect_mod_item_types,
         is_type_alias_impl_trait,
@@ -1466,10 +1465,6 @@ fn compute_sig_of_foreign_fn_decl<'tcx>(
     fty
 }
 
-fn is_foreign_item(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
-    matches!(tcx.hir().get_by_def_id(def_id), Node::ForeignItem(..))
-}
-
 fn generator_kind(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<hir::GeneratorKind> {
     match tcx.hir().get_by_def_id(def_id) {
         Node::Expr(&rustc_hir::Expr {
@@ -1483,7 +1478,7 @@ fn generator_kind(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<hir::GeneratorK
 fn is_type_alias_impl_trait<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> bool {
     match tcx.hir().get_by_def_id(def_id) {
         Node::Item(hir::Item { kind: hir::ItemKind::OpaqueTy(opaque), .. }) => {
-            matches!(opaque.origin, hir::OpaqueTyOrigin::TyAlias)
+            matches!(opaque.origin, hir::OpaqueTyOrigin::TyAlias { .. })
         }
         _ => bug!("tried getting opaque_ty_origin for non-opaque: {:?}", def_id),
     }
diff --git a/compiler/rustc_hir_analysis/src/collect/generics_of.rs b/compiler/rustc_hir_analysis/src/collect/generics_of.rs
index ab2932bf969..ed60998ec8d 100644
--- a/compiler/rustc_hir_analysis/src/collect/generics_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/generics_of.rs
@@ -159,7 +159,10 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
                 }
                 Some(fn_def_id.to_def_id())
             }
-            ItemKind::OpaqueTy(hir::OpaqueTy { origin: hir::OpaqueTyOrigin::TyAlias, .. }) => {
+            ItemKind::OpaqueTy(hir::OpaqueTy {
+                origin: hir::OpaqueTyOrigin::TyAlias { .. },
+                ..
+            }) => {
                 let parent_id = tcx.hir().get_parent_item(hir_id);
                 assert_ne!(parent_id, hir::CRATE_OWNER_ID);
                 debug!("generics_of: parent of opaque ty {:?} is {:?}", def_id, parent_id);
diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
index e04658c8e77..a33990813b8 100644
--- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
@@ -721,7 +721,7 @@ pub(super) fn type_param_predicates(
                 | ItemKind::TyAlias(_, generics)
                 | ItemKind::OpaqueTy(OpaqueTy {
                     generics,
-                    origin: hir::OpaqueTyOrigin::TyAlias,
+                    origin: hir::OpaqueTyOrigin::TyAlias { .. },
                     ..
                 })
                 | ItemKind::Enum(_, generics)
diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
index 5c7f7f10b17..794812a5ce7 100644
--- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
+++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
@@ -17,6 +17,7 @@ use rustc_hir::{GenericArg, GenericParam, GenericParamKind, HirIdMap, LifetimeNa
 use rustc_middle::bug;
 use rustc_middle::hir::nested_filter;
 use rustc_middle::middle::resolve_bound_vars::*;
+use rustc_middle::query::Providers;
 use rustc_middle::ty::{self, TyCtxt, TypeSuperVisitable, TypeVisitor};
 use rustc_session::lint;
 use rustc_span::def_id::DefId;
@@ -232,8 +233,8 @@ impl<'a> fmt::Debug for TruncatedScopeDebug<'a> {
 
 type ScopeRef<'a> = &'a Scope<'a>;
 
-pub(crate) fn provide(providers: &mut ty::query::Providers) {
-    *providers = ty::query::Providers {
+pub(crate) fn provide(providers: &mut Providers) {
+    *providers = Providers {
         resolve_bound_vars,
 
         named_variable_map: |tcx, id| tcx.resolve_bound_vars(id).defs.get(&id),
@@ -526,7 +527,8 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
                 });
             }
             hir::ItemKind::OpaqueTy(hir::OpaqueTy {
-                origin: hir::OpaqueTyOrigin::TyAlias, ..
+                origin: hir::OpaqueTyOrigin::TyAlias { .. },
+                ..
             }) => {
                 // Opaque types are visited when we visit the
                 // `TyKind::OpaqueDef`, so that they have the lifetimes from
@@ -707,7 +709,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
                 let opaque_ty = self.tcx.hir().item(item_id);
                 match &opaque_ty.kind {
                     hir::ItemKind::OpaqueTy(hir::OpaqueTy {
-                        origin: hir::OpaqueTyOrigin::TyAlias,
+                        origin: hir::OpaqueTyOrigin::TyAlias { .. },
                         ..
                     }) => {
                         intravisit::walk_ty(self, ty);
diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs
index 8df0166f76b..ca430a5e863 100644
--- a/compiler/rustc_hir_analysis/src/collect/type_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs
@@ -164,7 +164,7 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> {
             let Some(type_dependent_def) = tables.type_dependent_def_id(parent_node_id) else {
                 return tcx.ty_error_with_message(
                     tcx.def_span(def_id),
-                    &format!("unable to find type-dependent def for {:?}", parent_node_id),
+                    format!("unable to find type-dependent def for {:?}", parent_node_id),
                 );
             };
             let idx = segment
@@ -205,14 +205,14 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> {
                     } else {
                         return tcx.ty_error_with_message(
                             tcx.def_span(def_id),
-                            &format!("unable to find const parent for {} in pat {:?}", hir_id, pat),
+                            format!("unable to find const parent for {} in pat {:?}", hir_id, pat),
                         );
                     }
                 }
                 _ => {
                     return tcx.ty_error_with_message(
                         tcx.def_span(def_id),
-                        &format!("unexpected const parent path {:?}", parent_node),
+                        format!("unexpected const parent path {:?}", parent_node),
                     );
                 }
             };
@@ -243,7 +243,7 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> {
                 None => {
                     return tcx.ty_error_with_message(
                         tcx.def_span(def_id),
-                        &format!("unexpected anon const res {:?} in path: {:?}", segment.res, path),
+                        format!("unexpected anon const res {:?} in path: {:?}", segment.res, path),
                     );
                 }
             };
@@ -253,7 +253,7 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> {
 
         _ => return tcx.ty_error_with_message(
             tcx.def_span(def_id),
-            &format!("unexpected const parent in type_of(): {parent_node:?}"),
+            format!("unexpected const parent in type_of(): {parent_node:?}"),
         ),
     };
 
@@ -279,7 +279,7 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> {
     } else {
         return tcx.ty_error_with_message(
             tcx.def_span(def_id),
-            &format!("const generic parameter not found in {generics:?} at position {arg_idx:?}"),
+            format!("const generic parameter not found in {generics:?} at position {arg_idx:?}"),
         );
     }
 }
@@ -426,9 +426,10 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<Ty
                     let substs = InternalSubsts::identity_for_item(tcx, def_id);
                     tcx.mk_adt(def, substs)
                 }
-                ItemKind::OpaqueTy(OpaqueTy { origin: hir::OpaqueTyOrigin::TyAlias, .. }) => {
-                    find_opaque_ty_constraints_for_tait(tcx, def_id)
-                }
+                ItemKind::OpaqueTy(OpaqueTy {
+                    origin: hir::OpaqueTyOrigin::TyAlias { .. },
+                    ..
+                }) => find_opaque_ty_constraints_for_tait(tcx, def_id),
                 // Opaque types desugared from `impl Trait`.
                 ItemKind::OpaqueTy(OpaqueTy {
                     origin:
diff --git a/compiler/rustc_hir_analysis/src/hir_wf_check.rs b/compiler/rustc_hir_analysis/src/hir_wf_check.rs
index 8269a6ddea5..e4c6e6e391a 100644
--- a/compiler/rustc_hir_analysis/src/hir_wf_check.rs
+++ b/compiler/rustc_hir_analysis/src/hir_wf_check.rs
@@ -4,7 +4,7 @@ use rustc_hir::intravisit::{self, Visitor};
 use rustc_hir::{ForeignItem, ForeignItemKind};
 use rustc_infer::infer::TyCtxtInferExt;
 use rustc_infer::traits::{ObligationCause, WellFormedLoc};
-use rustc_middle::ty::query::Providers;
+use rustc_middle::query::Providers;
 use rustc_middle::ty::{self, Region, TyCtxt, TypeFoldable, TypeFolder};
 use rustc_span::def_id::LocalDefId;
 use rustc_trait_selection::traits::{self, ObligationCtxt};
diff --git a/compiler/rustc_hir_analysis/src/impl_wf_check.rs b/compiler/rustc_hir_analysis/src/impl_wf_check.rs
index f070b4f9bae..612d4ff3df8 100644
--- a/compiler/rustc_hir_analysis/src/impl_wf_check.rs
+++ b/compiler/rustc_hir_analysis/src/impl_wf_check.rs
@@ -15,7 +15,7 @@ use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::struct_span_err;
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::LocalDefId;
-use rustc_middle::ty::query::Providers;
+use rustc_middle::query::Providers;
 use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt};
 use rustc_span::{Span, Symbol};
 
diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs
index 3fe34f23aef..5cd2cd50c11 100644
--- a/compiler/rustc_hir_analysis/src/lib.rs
+++ b/compiler/rustc_hir_analysis/src/lib.rs
@@ -104,7 +104,7 @@ use rustc_hir as hir;
 use rustc_hir::Node;
 use rustc_infer::infer::TyCtxtInferExt;
 use rustc_middle::middle;
-use rustc_middle::ty::query::Providers;
+use rustc_middle::query::Providers;
 use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_middle::util;
 use rustc_session::{config::EntryFnType, parse::feature_err};
diff --git a/compiler/rustc_hir_analysis/src/outlives/mod.rs b/compiler/rustc_hir_analysis/src/outlives/mod.rs
index 42612eed750..a8596c707f3 100644
--- a/compiler/rustc_hir_analysis/src/outlives/mod.rs
+++ b/compiler/rustc_hir_analysis/src/outlives/mod.rs
@@ -1,7 +1,7 @@
 use hir::Node;
 use rustc_hir as hir;
 use rustc_hir::def_id::LocalDefId;
-use rustc_middle::ty::query::Providers;
+use rustc_middle::query::Providers;
 use rustc_middle::ty::subst::GenericArgKind;
 use rustc_middle::ty::{self, CratePredicatesMap, TyCtxt};
 use rustc_span::symbol::sym;
diff --git a/compiler/rustc_hir_analysis/src/variance/mod.rs b/compiler/rustc_hir_analysis/src/variance/mod.rs
index e735b048d73..3ebd9e134bf 100644
--- a/compiler/rustc_hir_analysis/src/variance/mod.rs
+++ b/compiler/rustc_hir_analysis/src/variance/mod.rs
@@ -6,7 +6,7 @@
 use rustc_arena::DroplessArena;
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::{DefId, LocalDefId};
-use rustc_middle::ty::query::Providers;
+use rustc_middle::query::Providers;
 use rustc_middle::ty::{self, CrateVariancesMap, SubstsRef, Ty, TyCtxt};
 use rustc_middle::ty::{TypeSuperVisitable, TypeVisitable};
 use std::ops::ControlFlow;
diff --git a/compiler/rustc_hir_typeck/messages.ftl b/compiler/rustc_hir_typeck/messages.ftl
index aa664031a87..4a669e3f8b8 100644
--- a/compiler/rustc_hir_typeck/messages.ftl
+++ b/compiler/rustc_hir_typeck/messages.ftl
@@ -79,3 +79,14 @@ hir_typeck_arg_mismatch_indeterminate = argument type mismatch was detected, but
 hir_typeck_suggest_boxing_note = for more on the distinction between the stack and the heap, read https://doc.rust-lang.org/book/ch15-01-box.html, https://doc.rust-lang.org/rust-by-example/std/box.html, and https://doc.rust-lang.org/std/boxed/index.html
 
 hir_typeck_suggest_boxing_when_appropriate = store this in the heap by calling `Box::new`
+
+hir_typeck_no_associated_item = no {$item_kind} named `{$item_name}` found for {$ty_prefix} `{$ty_str}`{$trait_missing_method ->
+    [true] {""}
+    *[other] {" "}in the current scope
+}
+
+hir_typeck_candidate_trait_note = `{$trait_name}` defines an item `{$item_name}`{$action_or_ty ->
+    [NONE] {""}
+    [implement] , perhaps you need to implement it
+    *[other] , perhaps you need to restrict type parameter `{$action_or_ty}` with it
+}
diff --git a/compiler/rustc_hir_typeck/src/errors.rs b/compiler/rustc_hir_typeck/src/errors.rs
index ce30bbeca0b..102a313067f 100644
--- a/compiler/rustc_hir_typeck/src/errors.rs
+++ b/compiler/rustc_hir_typeck/src/errors.rs
@@ -1,4 +1,6 @@
 //! Errors emitted by `rustc_hir_typeck`.
+use std::borrow::Cow;
+
 use crate::fluent_generated as fluent;
 use rustc_errors::{AddToDiagnostic, Applicability, Diagnostic, MultiSpan, SubdiagnosticMessage};
 use rustc_macros::{Diagnostic, Subdiagnostic};
@@ -295,3 +297,25 @@ pub enum SuggestBoxing {
         end: Span,
     },
 }
+
+#[derive(Diagnostic)]
+#[diag(hir_typeck_no_associated_item, code = "E0599")]
+pub struct NoAssociatedItem {
+    #[primary_span]
+    pub span: Span,
+    pub item_kind: &'static str,
+    pub item_name: Ident,
+    pub ty_prefix: Cow<'static, str>,
+    pub ty_str: String,
+    pub trait_missing_method: bool,
+}
+
+#[derive(Subdiagnostic)]
+#[note(hir_typeck_candidate_trait_note)]
+pub struct CandidateTraitNote {
+    #[primary_span]
+    pub span: Span,
+    pub trait_name: String,
+    pub item_name: Ident,
+    pub action_or_ty: String,
+}
diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs
index bba049c3819..adc1b090af6 100644
--- a/compiler/rustc_hir_typeck/src/expr.rs
+++ b/compiler/rustc_hir_typeck/src/expr.rs
@@ -721,7 +721,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 // ICE this expression in particular (see #43162).
                 if let ExprKind::Path(QPath::Resolved(_, path)) = e.kind {
                     if path.segments.len() == 1 && path.segments[0].ident.name == sym::rust {
-                        fatally_break_rust(self.tcx.sess);
+                        fatally_break_rust(self.tcx);
                     }
                 }
             }
@@ -1245,6 +1245,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         error,
                         Some((rcvr, args)),
                         expected,
+                        false,
                     ) {
                         err.emit();
                     }
@@ -2468,7 +2469,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         {
             self.suggest_method_call(
                 &mut err,
-                &format!("a method `{field}` also exists, call it with parentheses"),
+                format!("a method `{field}` also exists, call it with parentheses"),
                 field,
                 expr_t,
                 expr,
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
index 9e78e6acba5..9721e3b427d 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
@@ -4,7 +4,7 @@ use crate::rvalue_scopes;
 use crate::{BreakableCtxt, Diverges, Expectation, FnCtxt, LocalTy, RawTy};
 use rustc_data_structures::captures::Captures;
 use rustc_data_structures::fx::FxHashSet;
-use rustc_errors::{Applicability, Diagnostic, ErrorGuaranteed, MultiSpan};
+use rustc_errors::{Applicability, Diagnostic, ErrorGuaranteed, MultiSpan, StashKey};
 use rustc_hir as hir;
 use rustc_hir::def::{CtorOf, DefKind, Res};
 use rustc_hir::def_id::DefId;
@@ -35,7 +35,9 @@ use rustc_span::symbol::{kw, sym, Ident};
 use rustc_span::Span;
 use rustc_target::abi::FieldIdx;
 use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt as _;
-use rustc_trait_selection::traits::{self, NormalizeExt, ObligationCauseCode, ObligationCtxt};
+use rustc_trait_selection::traits::{
+    self, NormalizeExt, ObligationCauseCode, ObligationCtxt, StructurallyNormalizeExt,
+};
 
 use std::collections::hash_map::Entry;
 use std::slice;
@@ -853,6 +855,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         let item_name = item_segment.ident;
         let result = self
             .resolve_fully_qualified_call(span, item_name, ty.normalized, qself.span, hir_id)
+            .and_then(|r| {
+                // lint bare trait if the method is found in the trait
+                if span.edition().rust_2021() && let Some(mut diag) = self.tcx.sess.diagnostic().steal_diagnostic(qself.span, StashKey::TraitMissingMethod) {
+                    diag.emit();
+                }
+                Ok(r)
+            })
             .or_else(|error| {
                 let guar = self
                     .tcx
@@ -863,17 +872,30 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     _ => Err(guar),
                 };
 
+                let trait_missing_method =
+                    matches!(error, method::MethodError::NoMatch(_)) && ty.normalized.is_trait();
                 // If we have a path like `MyTrait::missing_method`, then don't register
                 // a WF obligation for `dyn MyTrait` when method lookup fails. Otherwise,
                 // register a WF obligation so that we can detect any additional
                 // errors in the self type.
-                if !(matches!(error, method::MethodError::NoMatch(_)) && ty.normalized.is_trait()) {
+                if !trait_missing_method {
                     self.register_wf_obligation(
                         ty.raw.into(),
                         qself.span,
                         traits::WellFormed(None),
                     );
                 }
+
+                // emit or cancel the diagnostic for bare traits
+                if span.edition().rust_2021() && let Some(mut diag) = self.tcx.sess.diagnostic().steal_diagnostic(qself.span, StashKey::TraitMissingMethod) {
+                    if trait_missing_method {
+                        // cancel the diag for bare traits when meeting `MyTrait::missing_method`
+                        diag.cancel();
+                    } else {
+                        diag.emit();
+                    }
+                }
+
                 if item_name.name != kw::Empty {
                     if let Some(mut e) = self.report_method_error(
                         span,
@@ -883,10 +905,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         error,
                         None,
                         Expectation::NoExpectation,
+                        trait_missing_method && span.edition().rust_2021(), // emits missing method for trait only after edition 2021
                     ) {
                         e.emit();
                     }
                 }
+
                 result
             });
 
@@ -1438,10 +1462,33 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     }
 
     /// Resolves `typ` by a single level if `typ` is a type variable.
+    ///
+    /// When the new solver is enabled, this will also attempt to normalize
+    /// the type if it's a projection (note that it will not deeply normalize
+    /// projections within the type, just the outermost layer of the type).
+    ///
     /// If no resolution is possible, then an error is reported.
     /// Numeric inference variables may be left unresolved.
     pub fn structurally_resolved_type(&self, sp: Span, ty: Ty<'tcx>) -> Ty<'tcx> {
-        let ty = self.resolve_vars_with_obligations(ty);
+        let mut ty = self.resolve_vars_with_obligations(ty);
+
+        if self.tcx.trait_solver_next()
+            && let ty::Alias(ty::Projection, _) = ty.kind()
+        {
+            match self
+                .at(&self.misc(sp), self.param_env)
+                .structurally_normalize(ty, &mut **self.fulfillment_cx.borrow_mut())
+            {
+                Ok(normalized_ty) => {
+                    ty = normalized_ty;
+                },
+                Err(errors) => {
+                    let guar = self.err_ctxt().report_fulfillment_errors(&errors);
+                    return self.tcx.ty_error(guar);
+                }
+            }
+        }
+
         if !ty.is_ty_var() {
             ty
         } else {
diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs
index dcc323493f4..64426c4cbbb 100644
--- a/compiler/rustc_hir_typeck/src/lib.rs
+++ b/compiler/rustc_hir_typeck/src/lib.rs
@@ -68,11 +68,10 @@ use rustc_hir::{HirIdMap, Node};
 use rustc_hir_analysis::astconv::AstConv;
 use rustc_hir_analysis::check::check_abi;
 use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
+use rustc_middle::query::Providers;
 use rustc_middle::traits;
-use rustc_middle::ty::query::Providers;
 use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_session::config;
-use rustc_session::Session;
 use rustc_span::def_id::{DefId, LocalDefId};
 use rustc_span::{sym, Span};
 
@@ -438,8 +437,8 @@ enum TupleArgumentsFlag {
     TupleArguments,
 }
 
-fn fatally_break_rust(sess: &Session) {
-    let handler = sess.diagnostic();
+fn fatally_break_rust(tcx: TyCtxt<'_>) {
+    let handler = tcx.sess.diagnostic();
     handler.span_bug_no_panic(
         MultiSpan::new(),
         "It looks like you're trying to break rust; would you like some ICE?",
@@ -451,7 +450,7 @@ fn fatally_break_rust(sess: &Session) {
     );
     handler.note_without_error(format!(
         "rustc {} running on {}",
-        option_env!("CFG_VERSION").unwrap_or("unknown_version"),
+        tcx.sess.cfg_version,
         config::host_triple(),
     ));
 }
diff --git a/compiler/rustc_hir_typeck/src/method/confirm.rs b/compiler/rustc_hir_typeck/src/method/confirm.rs
index 9155a3d8daa..59bf45f0ed2 100644
--- a/compiler/rustc_hir_typeck/src/method/confirm.rs
+++ b/compiler/rustc_hir_typeck/src/method/confirm.rs
@@ -158,7 +158,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
         let Some((ty, n)) = autoderef.nth(pick.autoderefs) else {
             return self.tcx.ty_error_with_message(
                 rustc_span::DUMMY_SP,
-                &format!("failed autoderef {}", pick.autoderefs),
+                format!("failed autoderef {}", pick.autoderefs),
             );
         };
         assert_eq!(n, pick.autoderefs);
diff --git a/compiler/rustc_hir_typeck/src/method/mod.rs b/compiler/rustc_hir_typeck/src/method/mod.rs
index 5963a1632c5..6f4d674ba10 100644
--- a/compiler/rustc_hir_typeck/src/method/mod.rs
+++ b/compiler/rustc_hir_typeck/src/method/mod.rs
@@ -13,11 +13,12 @@ pub use self::MethodError::*;
 use crate::errors::OpMethodGenericParams;
 use crate::FnCtxt;
 use rustc_data_structures::sync::Lrc;
-use rustc_errors::{Applicability, Diagnostic};
+use rustc_errors::{Applicability, Diagnostic, SubdiagnosticMessage};
 use rustc_hir as hir;
 use rustc_hir::def::{CtorOf, DefKind, Namespace};
 use rustc_hir::def_id::DefId;
 use rustc_infer::infer::{self, InferOk};
+use rustc_middle::query::Providers;
 use rustc_middle::traits::ObligationCause;
 use rustc_middle::ty::subst::{InternalSubsts, SubstsRef};
 use rustc_middle::ty::{self, GenericParamDefKind, Ty, TypeVisitableExt};
@@ -28,7 +29,7 @@ use rustc_trait_selection::traits::{self, NormalizeExt};
 
 use self::probe::{IsSuggestion, ProbeScope};
 
-pub fn provide(providers: &mut ty::query::Providers) {
+pub fn provide(providers: &mut Providers) {
     probe::provide(providers);
 }
 
@@ -129,7 +130,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     pub(crate) fn suggest_method_call(
         &self,
         err: &mut Diagnostic,
-        msg: &str,
+        msg: impl Into<SubdiagnosticMessage> + std::fmt::Debug,
         method_name: Ident,
         self_ty: Ty<'tcx>,
         call_expr: &hir::Expr<'tcx>,
diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs
index 483e17460b3..f91f4f887c6 100644
--- a/compiler/rustc_hir_typeck/src/method/probe.rs
+++ b/compiler/rustc_hir_typeck/src/method/probe.rs
@@ -16,6 +16,7 @@ use rustc_infer::infer::canonical::{Canonical, QueryResponse};
 use rustc_infer::infer::DefineOpaqueTypes;
 use rustc_infer::infer::{self, InferOk, TyCtxtInferExt};
 use rustc_middle::middle::stability;
+use rustc_middle::query::Providers;
 use rustc_middle::ty::fast_reject::{simplify_type, TreatParams};
 use rustc_middle::ty::AssocItem;
 use rustc_middle::ty::GenericParamDefKind;
@@ -495,7 +496,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     }
 }
 
-pub fn provide(providers: &mut ty::query::Providers) {
+pub fn provide(providers: &mut Providers) {
     providers.method_autoderef_steps = method_autoderef_steps;
 }
 
diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs
index 486c217707e..17364509844 100644
--- a/compiler/rustc_hir_typeck/src/method/suggest.rs
+++ b/compiler/rustc_hir_typeck/src/method/suggest.rs
@@ -2,6 +2,8 @@
 //! found or is otherwise invalid.
 
 use crate::errors;
+use crate::errors::CandidateTraitNote;
+use crate::errors::NoAssociatedItem;
 use crate::Expectation;
 use crate::FnCtxt;
 use rustc_ast::ast::Mutability;
@@ -38,6 +40,7 @@ use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _
 use rustc_trait_selection::traits::{
     FulfillmentError, Obligation, ObligationCause, ObligationCauseCode,
 };
+use std::borrow::Cow;
 
 use super::probe::{AutorefOrPtrAdjustment, IsSuggestion, Mode, ProbeScope};
 use super::{CandidateSource, MethodError, NoMatchData};
@@ -112,6 +115,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         error: MethodError<'tcx>,
         args: Option<(&'tcx hir::Expr<'tcx>, &'tcx [hir::Expr<'tcx>])>,
         expected: Expectation<'tcx>,
+        trait_missing_method: bool,
     ) -> Option<DiagnosticBuilder<'_, ErrorGuaranteed>> {
         // Avoid suggestions when we don't know what's going on.
         if rcvr_ty.references_error() {
@@ -136,6 +140,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     sugg_span,
                     &mut no_match_data,
                     expected,
+                    trait_missing_method,
                 );
             }
 
@@ -278,12 +283,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         sugg_span: Span,
         no_match_data: &mut NoMatchData<'tcx>,
         expected: Expectation<'tcx>,
+        trait_missing_method: bool,
     ) -> Option<DiagnosticBuilder<'_, ErrorGuaranteed>> {
         let mode = no_match_data.mode;
         let tcx = self.tcx;
         let rcvr_ty = self.resolve_vars_if_possible(rcvr_ty);
-        let (ty_str, ty_file) = tcx.short_ty_string(rcvr_ty);
-        let short_ty_str = with_forced_trimmed_paths!(rcvr_ty.to_string());
+        let ((mut ty_str, ty_file), short_ty_str) = if trait_missing_method
+            && let ty::Dynamic(predicates, _, _) = rcvr_ty.kind() {
+                ((predicates.to_string(), None), with_forced_trimmed_paths!(predicates.to_string()))
+            } else {
+                (tcx.short_ty_string(rcvr_ty), with_forced_trimmed_paths!(rcvr_ty.to_string()))
+            };
         let is_method = mode == Mode::MethodCall;
         let unsatisfied_predicates = &no_match_data.unsatisfied_predicates;
         let similar_candidate = no_match_data.similar_candidate;
@@ -355,25 +365,28 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         {
             self.suggest_missing_writer(rcvr_ty, args)
         } else {
-            struct_span_err!(
-                tcx.sess,
+            tcx.sess.create_err(NoAssociatedItem {
                 span,
-                E0599,
-                "no {} named `{}` found for {} `{}` in the current scope",
                 item_kind,
                 item_name,
-                rcvr_ty.prefix_string(self.tcx),
-                ty_str_reported,
-            )
+                ty_prefix: if trait_missing_method {
+                    // FIXME(mu001999) E0599 maybe not suitable here because it is for types
+                    Cow::from("trait")
+                } else {
+                    rcvr_ty.prefix_string(self.tcx)
+                },
+                ty_str: ty_str_reported,
+                trait_missing_method,
+            })
         };
         if tcx.sess.source_map().is_multiline(sugg_span) {
             err.span_label(sugg_span.with_hi(span.lo()), "");
         }
-        let ty_str = if short_ty_str.len() < ty_str.len() && ty_str.len() > 10 {
-            short_ty_str
-        } else {
-            ty_str
-        };
+
+        if short_ty_str.len() < ty_str.len() && ty_str.len() > 10 {
+            ty_str = short_ty_str;
+        }
+
         if let Some(file) = ty_file {
             err.note(format!("the full type name has been written to '{}'", file.display(),));
         }
@@ -1067,6 +1080,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 &static_candidates,
                 unsatisfied_bounds,
                 expected.only_has_type(self),
+                trait_missing_method,
             );
         }
 
@@ -2375,6 +2389,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         static_candidates: &[CandidateSource],
         unsatisfied_bounds: bool,
         return_type: Option<Ty<'tcx>>,
+        trait_missing_method: bool,
     ) {
         let mut alt_rcvr_sugg = false;
         if let (SelfSource::MethodCall(rcvr), false) = (source, unsatisfied_bounds) {
@@ -2598,11 +2613,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 },
                 _ => None,
             };
-            err.help(if param_type.is_some() {
-                "items from traits can only be used if the type parameter is bounded by the trait"
-            } else {
-                "items from traits can only be used if the trait is implemented and in scope"
-            });
+            if !trait_missing_method {
+                err.help(if param_type.is_some() {
+                    "items from traits can only be used if the type parameter is bounded by the trait"
+                } else {
+                    "items from traits can only be used if the trait is implemented and in scope"
+                });
+            }
+
             let candidates_len = candidates.len();
             let message = |action| {
                 format!(
@@ -2633,47 +2651,62 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                                 Nothing,
                             }
                             let ast_generics = hir.get_generics(id.owner.def_id).unwrap();
-                            let (sp, mut introducer) = if let Some(span) =
-                                ast_generics.bounds_span_for_suggestions(def_id)
-                            {
-                                (span, Introducer::Plus)
-                            } else if let Some(colon_span) = param.colon_span {
-                                (colon_span.shrink_to_hi(), Introducer::Nothing)
-                            } else {
-                                (param.span.shrink_to_hi(), Introducer::Colon)
-                            };
-                            if matches!(
-                                param.kind,
-                                hir::GenericParamKind::Type { synthetic: true, .. },
-                            ) {
-                                introducer = Introducer::Plus
-                            }
                             let trait_def_ids: FxHashSet<DefId> = ast_generics
                                 .bounds_for_param(def_id)
                                 .flat_map(|bp| bp.bounds.iter())
                                 .filter_map(|bound| bound.trait_ref()?.trait_def_id())
                                 .collect();
-                            if !candidates.iter().any(|t| trait_def_ids.contains(&t.def_id)) {
-                                err.span_suggestions(
-                                    sp,
-                                    message(format!(
-                                        "restrict type parameter `{}` with",
-                                        param.name.ident(),
-                                    )),
+                            if candidates.iter().any(|t| trait_def_ids.contains(&t.def_id)) {
+                                return;
+                            }
+                            let msg = message(format!(
+                                "restrict type parameter `{}` with",
+                                param.name.ident(),
+                            ));
+                            let bounds_span = ast_generics.bounds_span_for_suggestions(def_id);
+                            if rcvr_ty.is_ref() && param.is_impl_trait() && bounds_span.is_some() {
+                                err.multipart_suggestions(
+                                    msg,
                                     candidates.iter().map(|t| {
-                                        format!(
-                                            "{} {}",
-                                            match introducer {
-                                                Introducer::Plus => " +",
-                                                Introducer::Colon => ":",
-                                                Introducer::Nothing => "",
-                                            },
-                                            self.tcx.def_path_str(t.def_id),
-                                        )
+                                        vec![
+                                            (param.span.shrink_to_lo(), "(".to_string()),
+                                            (
+                                                bounds_span.unwrap(),
+                                                format!(" + {})", self.tcx.def_path_str(t.def_id)),
+                                            ),
+                                        ]
                                     }),
                                     Applicability::MaybeIncorrect,
                                 );
+                                return;
                             }
+
+                            let (sp, introducer) = if let Some(span) = bounds_span {
+                                (span, Introducer::Plus)
+                            } else if let Some(colon_span) = param.colon_span {
+                                (colon_span.shrink_to_hi(), Introducer::Nothing)
+                            } else if param.is_impl_trait() {
+                                (param.span.shrink_to_hi(), Introducer::Plus)
+                            } else {
+                                (param.span.shrink_to_hi(), Introducer::Colon)
+                            };
+
+                            err.span_suggestions(
+                                sp,
+                                msg,
+                                candidates.iter().map(|t| {
+                                    format!(
+                                        "{} {}",
+                                        match introducer {
+                                            Introducer::Plus => " +",
+                                            Introducer::Colon => ":",
+                                            Introducer::Nothing => "",
+                                        },
+                                        self.tcx.def_path_str(t.def_id)
+                                    )
+                                }),
+                                Applicability::MaybeIncorrect,
+                            );
                             return;
                         }
                         Node::Item(hir::Item {
@@ -2736,27 +2769,28 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 (candidates, Vec::new())
             };
 
-            let action = if let Some(param) = param_type {
-                format!("restrict type parameter `{}` with", param)
-            } else {
-                // FIXME: it might only need to be imported into scope, not implemented.
-                "implement".to_string()
-            };
             match &potential_candidates[..] {
                 [] => {}
                 [trait_info] if trait_info.def_id.is_local() => {
-                    err.span_note(
-                        self.tcx.def_span(trait_info.def_id),
-                        format!(
-                            "`{}` defines an item `{}`, perhaps you need to {} it",
-                            self.tcx.def_path_str(trait_info.def_id),
-                            item_name,
-                            action
-                        ),
-                    );
+                    err.subdiagnostic(CandidateTraitNote {
+                        span: self.tcx.def_span(trait_info.def_id),
+                        trait_name: self.tcx.def_path_str(trait_info.def_id),
+                        item_name,
+                        action_or_ty: if trait_missing_method {
+                            "NONE".to_string()
+                        } else {
+                            param_type.map_or_else(
+                                || "implement".to_string(), // FIXME: it might only need to be imported into scope, not implemented.
+                                ToString::to_string,
+                            )
+                        },
+                    });
                 }
                 trait_infos => {
-                    let mut msg = message(action);
+                    let mut msg = message(param_type.map_or_else(
+                        || "implement".to_string(), // FIXME: it might only need to be imported into scope, not implemented.
+                        |param| format!("restrict type parameter `{}` with", param),
+                    ));
                     for (i, trait_info) in trait_infos.iter().enumerate() {
                         msg.push_str(&format!(
                             "\ncandidate #{}: `{}`",
diff --git a/compiler/rustc_hir_typeck/src/writeback.rs b/compiler/rustc_hir_typeck/src/writeback.rs
index cf95d4f04bb..2daec205cfc 100644
--- a/compiler/rustc_hir_typeck/src/writeback.rs
+++ b/compiler/rustc_hir_typeck/src/writeback.rs
@@ -9,7 +9,6 @@ use rustc_errors::ErrorGuaranteed;
 use rustc_hir as hir;
 use rustc_hir::intravisit::{self, Visitor};
 use rustc_infer::infer::error_reporting::TypeAnnotationNeeded::E0282;
-use rustc_infer::infer::InferCtxt;
 use rustc_middle::hir::place::Place as HirPlace;
 use rustc_middle::mir::FakeReadCause;
 use rustc_middle::ty::adjustment::{Adjust, Adjustment, PointerCast};
@@ -237,7 +236,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
                     // error has been emitted. (#64638)
                     self.fcx.tcx.ty_error_with_message(
                         e.span,
-                        &format!("bad index {:?} for base: `{:?}`", index, base),
+                        format!("bad index {:?} for base: `{:?}`", index, base),
                     )
                 });
                 let index_ty = self.fcx.resolve_vars_if_possible(index_ty);
@@ -692,15 +691,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
             fcx_typeck_results.offset_of_data().items_in_stable_order()
         {
             let hir_id = hir::HirId { owner: common_hir_owner, local_id };
-
-            if cfg!(debug_assertions) && container.has_infer() {
-                span_bug!(
-                    hir_id.to_span(self.fcx.tcx),
-                    "writeback: `{:?}` has inference variables",
-                    container
-                );
-            };
-
+            let container = self.resolve(container, &hir_id);
             self.typeck_results.offset_of_data_mut().insert(hir_id, (container, indices.clone()));
         }
     }
@@ -745,8 +736,7 @@ impl Locatable for hir::HirId {
 /// The Resolver. This is the type folding engine that detects
 /// unresolved types and so forth.
 struct Resolver<'cx, 'tcx> {
-    tcx: TyCtxt<'tcx>,
-    infcx: &'cx InferCtxt<'tcx>,
+    fcx: &'cx FnCtxt<'cx, 'tcx>,
     span: &'cx dyn Locatable,
     body: &'tcx hir::Body<'tcx>,
 
@@ -760,18 +750,18 @@ impl<'cx, 'tcx> Resolver<'cx, 'tcx> {
         span: &'cx dyn Locatable,
         body: &'tcx hir::Body<'tcx>,
     ) -> Resolver<'cx, 'tcx> {
-        Resolver { tcx: fcx.tcx, infcx: fcx, span, body, replaced_with_error: None }
+        Resolver { fcx, span, body, replaced_with_error: None }
     }
 
     fn report_error(&self, p: impl Into<ty::GenericArg<'tcx>>) -> ErrorGuaranteed {
-        match self.tcx.sess.has_errors() {
+        match self.fcx.tcx.sess.has_errors() {
             Some(e) => e,
             None => self
-                .infcx
+                .fcx
                 .err_ctxt()
                 .emit_inference_failure_err(
-                    self.tcx.hir().body_owner_def_id(self.body.id()),
-                    self.span.to_span(self.tcx),
+                    self.fcx.tcx.hir().body_owner_def_id(self.body.id()),
+                    self.span.to_span(self.fcx.tcx),
                     p.into(),
                     E0282,
                     false,
@@ -803,40 +793,46 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for EraseEarlyRegions<'tcx> {
 
 impl<'cx, 'tcx> TypeFolder<TyCtxt<'tcx>> for Resolver<'cx, 'tcx> {
     fn interner(&self) -> TyCtxt<'tcx> {
-        self.tcx
+        self.fcx.tcx
     }
 
     fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
-        match self.infcx.fully_resolve(t) {
+        match self.fcx.fully_resolve(t) {
+            Ok(t) if self.fcx.tcx.trait_solver_next() => {
+                // We must normalize erasing regions here, since later lints
+                // expect that types that show up in the typeck are fully
+                // normalized.
+                self.fcx.tcx.try_normalize_erasing_regions(self.fcx.param_env, t).unwrap_or(t)
+            }
             Ok(t) => {
                 // Do not anonymize late-bound regions
                 // (e.g. keep `for<'a>` named `for<'a>`).
                 // This allows NLL to generate error messages that
                 // refer to the higher-ranked lifetime names written by the user.
-                EraseEarlyRegions { tcx: self.tcx }.fold_ty(t)
+                EraseEarlyRegions { tcx: self.fcx.tcx }.fold_ty(t)
             }
             Err(_) => {
                 debug!("Resolver::fold_ty: input type `{:?}` not fully resolvable", t);
                 let e = self.report_error(t);
                 self.replaced_with_error = Some(e);
-                self.interner().ty_error(e)
+                self.fcx.tcx.ty_error(e)
             }
         }
     }
 
     fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
         debug_assert!(!r.is_late_bound(), "Should not be resolving bound region.");
-        self.tcx.lifetimes.re_erased
+        self.fcx.tcx.lifetimes.re_erased
     }
 
     fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> {
-        match self.infcx.fully_resolve(ct) {
-            Ok(ct) => self.tcx.erase_regions(ct),
+        match self.fcx.fully_resolve(ct) {
+            Ok(ct) => self.fcx.tcx.erase_regions(ct),
             Err(_) => {
                 debug!("Resolver::fold_const: input const `{:?}` not fully resolvable", ct);
                 let e = self.report_error(ct);
                 self.replaced_with_error = Some(e);
-                self.interner().const_error_with_guaranteed(ct.ty(), e)
+                self.fcx.tcx.const_error(ct.ty(), e)
             }
         }
     }
diff --git a/compiler/rustc_incremental/src/persist/file_format.rs b/compiler/rustc_incremental/src/persist/file_format.rs
index dc981c6179e..25bf83f64a0 100644
--- a/compiler/rustc_incremental/src/persist/file_format.rs
+++ b/compiler/rustc_incremental/src/persist/file_format.rs
@@ -14,6 +14,7 @@ use rustc_data_structures::memmap::Mmap;
 use rustc_serialize::opaque::{FileEncodeResult, FileEncoder};
 use rustc_serialize::Encoder;
 use rustc_session::Session;
+use std::borrow::Cow;
 use std::env;
 use std::fs;
 use std::io::{self, Read};
@@ -25,17 +26,12 @@ const FILE_MAGIC: &[u8] = b"RSIC";
 /// Change this if the header format changes.
 const HEADER_FORMAT_VERSION: u16 = 0;
 
-/// A version string that hopefully is always different for compiler versions
-/// with different encodings of incremental compilation artifacts. Contains
-/// the Git commit hash.
-const RUSTC_VERSION: Option<&str> = option_env!("CFG_VERSION");
-
-pub(crate) fn write_file_header(stream: &mut FileEncoder, nightly_build: bool) {
+pub(crate) fn write_file_header(stream: &mut FileEncoder, sess: &Session) {
     stream.emit_raw_bytes(FILE_MAGIC);
     stream
         .emit_raw_bytes(&[(HEADER_FORMAT_VERSION >> 0) as u8, (HEADER_FORMAT_VERSION >> 8) as u8]);
 
-    let rustc_version = rustc_version(nightly_build);
+    let rustc_version = rustc_version(sess.is_nightly_build(), sess.cfg_version);
     assert_eq!(rustc_version.len(), (rustc_version.len() as u8) as usize);
     stream.emit_raw_bytes(&[rustc_version.len() as u8]);
     stream.emit_raw_bytes(rustc_version.as_bytes());
@@ -73,7 +69,7 @@ where
         }
     };
 
-    write_file_header(&mut encoder, sess.is_nightly_build());
+    write_file_header(&mut encoder, sess);
 
     match encode(encoder) {
         Ok(position) => {
@@ -100,9 +96,10 @@ where
 /// - Returns `Err(..)` if some kind of IO error occurred while reading the
 ///   file.
 pub fn read_file(
-    report_incremental_info: bool,
     path: &Path,
-    nightly_build: bool,
+    report_incremental_info: bool,
+    is_nightly_build: bool,
+    cfg_version: &'static str,
 ) -> io::Result<Option<(Mmap, usize)>> {
     let file = match fs::File::open(path) {
         Ok(file) => file,
@@ -152,7 +149,7 @@ pub fn read_file(
         let mut buffer = vec![0; rustc_version_str_len];
         file.read_exact(&mut buffer)?;
 
-        if buffer != rustc_version(nightly_build).as_bytes() {
+        if buffer != rustc_version(is_nightly_build, cfg_version).as_bytes() {
             report_format_mismatch(report_incremental_info, path, "Different compiler version");
             return Ok(None);
         }
@@ -174,17 +171,15 @@ fn report_format_mismatch(report_incremental_info: bool, file: &Path, message: &
     }
 }
 
-fn rustc_version(nightly_build: bool) -> String {
+/// A version string that hopefully is always different for compiler versions
+/// with different encodings of incremental compilation artifacts. Contains
+/// the Git commit hash.
+fn rustc_version(nightly_build: bool, cfg_version: &'static str) -> Cow<'static, str> {
     if nightly_build {
-        if let Some(val) = env::var_os("RUSTC_FORCE_RUSTC_VERSION") {
-            return val.to_string_lossy().into_owned();
+        if let Ok(val) = env::var("RUSTC_FORCE_RUSTC_VERSION") {
+            return val.into();
         }
     }
 
-    RUSTC_VERSION
-        .expect(
-            "Cannot use rustc without explicit version for \
-                          incremental compilation",
-        )
-        .to_string()
+    cfg_version.into()
 }
diff --git a/compiler/rustc_incremental/src/persist/load.rs b/compiler/rustc_incremental/src/persist/load.rs
index ec7fcbdf884..a4407a93ff3 100644
--- a/compiler/rustc_incremental/src/persist/load.rs
+++ b/compiler/rustc_incremental/src/persist/load.rs
@@ -73,12 +73,22 @@ impl<T: Default> LoadResult<T> {
     }
 }
 
-fn load_data(
-    report_incremental_info: bool,
+fn load_data(path: &Path, sess: &Session) -> LoadResult<(Mmap, usize)> {
+    load_data_no_sess(
+        path,
+        sess.opts.unstable_opts.incremental_info,
+        sess.is_nightly_build(),
+        sess.cfg_version,
+    )
+}
+
+fn load_data_no_sess(
     path: &Path,
-    nightly_build: bool,
+    report_incremental_info: bool,
+    is_nightly_build: bool,
+    cfg_version: &'static str,
 ) -> LoadResult<(Mmap, usize)> {
-    match file_format::read_file(report_incremental_info, path, nightly_build) {
+    match file_format::read_file(path, report_incremental_info, is_nightly_build, cfg_version) {
         Ok(Some(data_and_pos)) => LoadResult::Ok { data: data_and_pos },
         Ok(None) => {
             // The file either didn't exist or was produced by an incompatible
@@ -138,14 +148,13 @@ pub fn load_dep_graph(sess: &Session) -> DepGraphFuture {
     let expected_hash = sess.opts.dep_tracking_hash(false);
 
     let mut prev_work_products = FxHashMap::default();
-    let nightly_build = sess.is_nightly_build();
 
     // If we are only building with -Zquery-dep-graph but without an actual
     // incr. comp. session directory, we skip this. Otherwise we'd fail
     // when trying to load work products.
     if sess.incr_comp_session_dir_opt().is_some() {
         let work_products_path = work_products_path(sess);
-        let load_result = load_data(report_incremental_info, &work_products_path, nightly_build);
+        let load_result = load_data(&work_products_path, sess);
 
         if let LoadResult::Ok { data: (work_products_data, start_pos) } = load_result {
             // Decode the list of work_products
@@ -173,10 +182,13 @@ pub fn load_dep_graph(sess: &Session) -> DepGraphFuture {
         }
     }
 
+    let is_nightly_build = sess.is_nightly_build();
+    let cfg_version = sess.cfg_version;
+
     MaybeAsync::Async(std::thread::spawn(move || {
         let _prof_timer = prof.generic_activity("incr_comp_load_dep_graph");
 
-        match load_data(report_incremental_info, &path, nightly_build) {
+        match load_data_no_sess(&path, report_incremental_info, is_nightly_build, cfg_version) {
             LoadResult::DataOutOfDate => LoadResult::DataOutOfDate,
             LoadResult::LoadDepGraph(path, err) => LoadResult::LoadDepGraph(path, err),
             LoadResult::DecodeIncrCache(err) => LoadResult::DecodeIncrCache(err),
@@ -218,11 +230,7 @@ pub fn load_query_result_cache(sess: &Session) -> Option<OnDiskCache<'_>> {
 
     let _prof_timer = sess.prof.generic_activity("incr_comp_load_query_result_cache");
 
-    match load_data(
-        sess.opts.unstable_opts.incremental_info,
-        &query_cache_path(sess),
-        sess.is_nightly_build(),
-    ) {
+    match load_data(&query_cache_path(sess), sess) {
         LoadResult::Ok { data: (bytes, start_pos) } => {
             Some(OnDiskCache::new(sess, bytes, start_pos))
         }
diff --git a/compiler/rustc_incremental/src/persist/save.rs b/compiler/rustc_incremental/src/persist/save.rs
index 1441e64e41f..7376be6be8b 100644
--- a/compiler/rustc_incremental/src/persist/save.rs
+++ b/compiler/rustc_incremental/src/persist/save.rs
@@ -164,7 +164,7 @@ pub fn build_dep_graph(
         }
     };
 
-    file_format::write_file_header(&mut encoder, sess.is_nightly_build());
+    file_format::write_file_header(&mut encoder, sess);
 
     // First encode the commandline arguments hash
     sess.opts.dep_tracking_hash(false).encode(&mut encoder);
diff --git a/compiler/rustc_infer/src/infer/canonical/query_response.rs b/compiler/rustc_infer/src/infer/canonical/query_response.rs
index 3605e10fecd..de9afbbcaab 100644
--- a/compiler/rustc_infer/src/infer/canonical/query_response.rs
+++ b/compiler/rustc_infer/src/infer/canonical/query_response.rs
@@ -153,20 +153,22 @@ impl<'tcx> InferCtxt<'tcx> {
 
     /// Used by the new solver as that one takes the opaque types at the end of a probe
     /// to deal with multiple candidates without having to recompute them.
-    pub fn clone_opaque_types_for_query_response(&self) -> Vec<(Ty<'tcx>, Ty<'tcx>)> {
+    pub fn clone_opaque_types_for_query_response(
+        &self,
+    ) -> Vec<(ty::OpaqueTypeKey<'tcx>, Ty<'tcx>)> {
         self.inner
             .borrow()
             .opaque_type_storage
             .opaque_types
             .iter()
-            .map(|(k, v)| (self.tcx.mk_opaque(k.def_id.to_def_id(), k.substs), v.hidden_type.ty))
+            .map(|(k, v)| (*k, v.hidden_type.ty))
             .collect()
     }
 
-    fn take_opaque_types_for_query_response(&self) -> Vec<(Ty<'tcx>, Ty<'tcx>)> {
+    fn take_opaque_types_for_query_response(&self) -> Vec<(ty::OpaqueTypeKey<'tcx>, Ty<'tcx>)> {
         std::mem::take(&mut self.inner.borrow_mut().opaque_type_storage.opaque_types)
             .into_iter()
-            .map(|(k, v)| (self.tcx.mk_opaque(k.def_id.to_def_id(), k.substs), v.hidden_type.ty))
+            .map(|(k, v)| (k, v.hidden_type.ty))
             .collect()
     }
 
@@ -507,8 +509,22 @@ impl<'tcx> InferCtxt<'tcx> {
             let a = substitute_value(self.tcx, &result_subst, a);
             let b = substitute_value(self.tcx, &result_subst, b);
             debug!(?a, ?b, "constrain opaque type");
-            obligations
-                .extend(self.at(cause, param_env).eq(DefineOpaqueTypes::Yes, a, b)?.obligations);
+            // We use equate here instead of, for example, just registering the
+            // opaque type's hidden value directly, because we may be instantiating
+            // a query response that was canonicalized in an InferCtxt that had
+            // a different defining anchor. In that case, we may have inferred
+            // `NonLocalOpaque := LocalOpaque` but can only instantiate it in
+            // the other direction as `LocalOpaque := NonLocalOpaque`. Using eq
+            // here allows us to try both directions (in `InferCtxt::handle_opaque_type`).
+            obligations.extend(
+                self.at(cause, param_env)
+                    .eq(
+                        DefineOpaqueTypes::Yes,
+                        self.tcx.mk_opaque(a.def_id.to_def_id(), a.substs),
+                        b,
+                    )?
+                    .obligations,
+            );
         }
 
         Ok(InferOk { value: result_subst, obligations })
diff --git a/compiler/rustc_infer/src/infer/combine.rs b/compiler/rustc_infer/src/infer/combine.rs
index 08eec0707c0..79fc02c6c79 100644
--- a/compiler/rustc_infer/src/infer/combine.rs
+++ b/compiler/rustc_infer/src/infer/combine.rs
@@ -26,24 +26,17 @@ use super::equate::Equate;
 use super::glb::Glb;
 use super::lub::Lub;
 use super::sub::Sub;
-use super::type_variable::TypeVariableValue;
-use super::{DefineOpaqueTypes, InferCtxt, MiscVariable, TypeTrace};
+use super::{DefineOpaqueTypes, InferCtxt, TypeTrace};
+use crate::infer::generalize::{self, CombineDelegate, Generalization};
 use crate::traits::{Obligation, PredicateObligations};
-use rustc_data_structures::sso::SsoHashMap;
-use rustc_hir::def_id::DefId;
 use rustc_middle::infer::canonical::OriginalQueryValues;
 use rustc_middle::infer::unify_key::{ConstVarValue, ConstVariableValue};
 use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind};
-use rustc_middle::traits::ObligationCause;
 use rustc_middle::ty::error::{ExpectedFound, TypeError};
-use rustc_middle::ty::relate::{self, Relate, RelateResult, TypeRelation};
-use rustc_middle::ty::subst::SubstsRef;
-use rustc_middle::ty::{
-    self, AliasKind, FallibleTypeFolder, InferConst, ToPredicate, Ty, TyCtxt, TypeFoldable,
-    TypeSuperFoldable, TypeVisitableExt,
-};
+use rustc_middle::ty::relate::{RelateResult, TypeRelation};
+use rustc_middle::ty::{self, AliasKind, InferConst, ToPredicate, Ty, TyCtxt, TypeVisitableExt};
 use rustc_middle::ty::{IntType, UintType};
-use rustc_span::{Span, DUMMY_SP};
+use rustc_span::DUMMY_SP;
 
 #[derive(Clone)]
 pub struct CombineFields<'infcx, 'tcx> {
@@ -55,13 +48,6 @@ pub struct CombineFields<'infcx, 'tcx> {
     pub define_opaque_types: DefineOpaqueTypes,
 }
 
-#[derive(Copy, Clone, Debug)]
-pub enum RelationDir {
-    SubtypeOf,
-    SupertypeOf,
-    EqTo,
-}
-
 impl<'tcx> InferCtxt<'tcx> {
     pub fn super_combine_tys<R>(
         &self,
@@ -152,7 +138,7 @@ impl<'tcx> InferCtxt<'tcx> {
                 Ok(a)
             }
 
-            _ => ty::relate::super_relate_tys(relation, a, b),
+            _ => ty::relate::structurally_relate_tys(relation, a, b),
         }
     }
 
@@ -209,13 +195,13 @@ impl<'tcx> InferCtxt<'tcx> {
             // HACK: equating both sides with `[const error]` eagerly prevents us
             // from leaving unconstrained inference vars during things like impl
             // matching in the solver.
-            let a_error = self.tcx.const_error_with_guaranteed(a.ty(), guar);
+            let a_error = self.tcx.const_error(a.ty(), guar);
             if let ty::ConstKind::Infer(InferConst::Var(vid)) = a.kind() {
-                return self.unify_const_variable(vid, a_error);
+                return self.unify_const_variable(vid, a_error, relation.param_env());
             }
-            let b_error = self.tcx.const_error_with_guaranteed(b.ty(), guar);
+            let b_error = self.tcx.const_error(b.ty(), guar);
             if let ty::ConstKind::Infer(InferConst::Var(vid)) = b.kind() {
-                return self.unify_const_variable(vid, b_error);
+                return self.unify_const_variable(vid, b_error, relation.param_env());
             }
 
             return Ok(if relation.a_is_expected() { a_error } else { b_error });
@@ -237,11 +223,11 @@ impl<'tcx> InferCtxt<'tcx> {
             }
 
             (ty::ConstKind::Infer(InferConst::Var(vid)), _) => {
-                return self.unify_const_variable(vid, b);
+                return self.unify_const_variable(vid, b, relation.param_env());
             }
 
             (_, ty::ConstKind::Infer(InferConst::Var(vid))) => {
-                return self.unify_const_variable(vid, a);
+                return self.unify_const_variable(vid, a, relation.param_env());
             }
             (ty::ConstKind::Unevaluated(..), _) | (_, ty::ConstKind::Unevaluated(..))
                 if self.tcx.lazy_normalization() =>
@@ -252,7 +238,7 @@ impl<'tcx> InferCtxt<'tcx> {
             _ => {}
         }
 
-        ty::relate::super_relate_consts(relation, a, b)
+        ty::relate::structurally_relate_consts(relation, a, b)
     }
 
     /// Unifies the const variable `target_vid` with the given constant.
@@ -294,24 +280,17 @@ impl<'tcx> InferCtxt<'tcx> {
         &self,
         target_vid: ty::ConstVid<'tcx>,
         ct: ty::Const<'tcx>,
+        param_env: ty::ParamEnv<'tcx>,
     ) -> RelateResult<'tcx, ty::Const<'tcx>> {
-        let (for_universe, span) = {
-            let mut inner = self.inner.borrow_mut();
-            let variable_table = &mut inner.const_unification_table();
-            let var_value = variable_table.probe_value(target_vid);
-            match var_value.val {
-                ConstVariableValue::Known { value } => {
-                    bug!("instantiating {:?} which has a known value {:?}", target_vid, value)
-                }
-                ConstVariableValue::Unknown { universe } => (universe, var_value.origin.span),
-            }
-        };
-        let value = ct.try_fold_with(&mut ConstInferUnifier {
-            infcx: self,
-            span,
-            for_universe,
+        let span =
+            self.inner.borrow_mut().const_unification_table().probe_value(target_vid).origin.span;
+        let Generalization { value, needs_wf: _ } = generalize::generalize(
+            self,
+            &mut CombineDelegate { infcx: self, span, param_env },
+            ct,
             target_vid,
-        })?;
+            ty::Variance::Invariant,
+        )?;
 
         self.inner.borrow_mut().const_unification_table().union_value(
             target_vid,
@@ -392,12 +371,10 @@ impl<'infcx, 'tcx> CombineFields<'infcx, 'tcx> {
     pub fn instantiate(
         &mut self,
         a_ty: Ty<'tcx>,
-        dir: RelationDir,
+        ambient_variance: ty::Variance,
         b_vid: ty::TyVid,
         a_is_expected: bool,
     ) -> RelateResult<'tcx, ()> {
-        use self::RelationDir::*;
-
         // Get the actual variable that b_vid has been inferred to
         debug_assert!(self.infcx.inner.borrow_mut().type_variables().probe(b_vid).is_unknown());
 
@@ -412,7 +389,18 @@ impl<'infcx, 'tcx> CombineFields<'infcx, 'tcx> {
         // `'?2` and `?3` are fresh region/type inference
         // variables. (Down below, we will relate `a_ty <: b_ty`,
         // adding constraints like `'x: '?2` and `?1 <: ?3`.)
-        let Generalization { ty: b_ty, needs_wf } = self.generalize(a_ty, b_vid, dir)?;
+        let Generalization { value: b_ty, needs_wf } = generalize::generalize(
+            self.infcx,
+            &mut CombineDelegate {
+                infcx: self.infcx,
+                param_env: self.param_env,
+                span: self.trace.span(),
+            },
+            a_ty,
+            b_vid,
+            ambient_variance,
+        )?;
+
         debug!(?b_ty);
         self.infcx.inner.borrow_mut().type_variables().instantiate(b_vid, b_ty);
 
@@ -431,78 +419,23 @@ impl<'infcx, 'tcx> CombineFields<'infcx, 'tcx> {
         // relations wind up attributed to the same spans. We need
         // to associate causes/spans with each of the relations in
         // the stack to get this right.
-        match dir {
-            EqTo => self.equate(a_is_expected).relate(a_ty, b_ty),
-            SubtypeOf => self.sub(a_is_expected).relate(a_ty, b_ty),
-            SupertypeOf => self.sub(a_is_expected).relate_with_variance(
+        match ambient_variance {
+            ty::Variance::Invariant => self.equate(a_is_expected).relate(a_ty, b_ty),
+            ty::Variance::Covariant => self.sub(a_is_expected).relate(a_ty, b_ty),
+            ty::Variance::Contravariant => self.sub(a_is_expected).relate_with_variance(
                 ty::Contravariant,
                 ty::VarianceDiagInfo::default(),
                 a_ty,
                 b_ty,
             ),
+            ty::Variance::Bivariant => {
+                unreachable!("no code should be generalizing bivariantly (currently)")
+            }
         }?;
 
         Ok(())
     }
 
-    /// Attempts to generalize `ty` for the type variable `for_vid`.
-    /// This checks for cycle -- that is, whether the type `ty`
-    /// references `for_vid`. The `dir` is the "direction" for which we
-    /// a performing the generalization (i.e., are we producing a type
-    /// that can be used as a supertype etc).
-    ///
-    /// Preconditions:
-    ///
-    /// - `for_vid` is a "root vid"
-    #[instrument(skip(self), level = "trace", ret)]
-    fn generalize(
-        &self,
-        ty: Ty<'tcx>,
-        for_vid: ty::TyVid,
-        dir: RelationDir,
-    ) -> RelateResult<'tcx, Generalization<'tcx>> {
-        // Determine the ambient variance within which `ty` appears.
-        // The surrounding equation is:
-        //
-        //     ty [op] ty2
-        //
-        // where `op` is either `==`, `<:`, or `:>`. This maps quite
-        // naturally.
-        let ambient_variance = match dir {
-            RelationDir::EqTo => ty::Invariant,
-            RelationDir::SubtypeOf => ty::Covariant,
-            RelationDir::SupertypeOf => ty::Contravariant,
-        };
-
-        trace!(?ambient_variance);
-
-        let for_universe = match self.infcx.inner.borrow_mut().type_variables().probe(for_vid) {
-            v @ TypeVariableValue::Known { .. } => {
-                bug!("instantiating {:?} which has a known value {:?}", for_vid, v,)
-            }
-            TypeVariableValue::Unknown { universe } => universe,
-        };
-
-        trace!(?for_universe);
-        trace!(?self.trace);
-
-        let mut generalize = Generalizer {
-            infcx: self.infcx,
-            cause: &self.trace.cause,
-            for_vid_sub_root: self.infcx.inner.borrow_mut().type_variables().sub_root_var(for_vid),
-            for_universe,
-            ambient_variance,
-            needs_wf: false,
-            root_ty: ty,
-            param_env: self.param_env,
-            cache: SsoHashMap::new(),
-        };
-
-        let ty = generalize.relate(ty, ty)?;
-        let needs_wf = generalize.needs_wf;
-        Ok(Generalization { ty, needs_wf })
-    }
-
     pub fn register_obligations(&mut self, obligations: PredicateObligations<'tcx>) {
         self.obligations.extend(obligations.into_iter());
     }
@@ -514,313 +447,6 @@ impl<'infcx, 'tcx> CombineFields<'infcx, 'tcx> {
     }
 }
 
-struct Generalizer<'cx, 'tcx> {
-    infcx: &'cx InferCtxt<'tcx>,
-
-    /// The span, used when creating new type variables and things.
-    cause: &'cx ObligationCause<'tcx>,
-
-    /// The vid of the type variable that is in the process of being
-    /// instantiated; if we find this within the type we are folding,
-    /// that means we would have created a cyclic type.
-    for_vid_sub_root: ty::TyVid,
-
-    /// The universe of the type variable that is in the process of
-    /// being instantiated. Any fresh variables that we create in this
-    /// process should be in that same universe.
-    for_universe: ty::UniverseIndex,
-
-    /// Track the variance as we descend into the type.
-    ambient_variance: ty::Variance,
-
-    /// See the field `needs_wf` in `Generalization`.
-    needs_wf: bool,
-
-    /// The root type that we are generalizing. Used when reporting cycles.
-    root_ty: Ty<'tcx>,
-
-    param_env: ty::ParamEnv<'tcx>,
-
-    cache: SsoHashMap<Ty<'tcx>, Ty<'tcx>>,
-}
-
-/// Result from a generalization operation. This includes
-/// not only the generalized type, but also a bool flag
-/// indicating whether further WF checks are needed.
-#[derive(Debug)]
-struct Generalization<'tcx> {
-    ty: Ty<'tcx>,
-
-    /// If true, then the generalized type may not be well-formed,
-    /// even if the source type is well-formed, so we should add an
-    /// additional check to enforce that it is. This arises in
-    /// particular around 'bivariant' type parameters that are only
-    /// constrained by a where-clause. As an example, imagine a type:
-    ///
-    ///     struct Foo<A, B> where A: Iterator<Item = B> {
-    ///         data: A
-    ///     }
-    ///
-    /// here, `A` will be covariant, but `B` is
-    /// unconstrained. However, whatever it is, for `Foo` to be WF, it
-    /// must be equal to `A::Item`. If we have an input `Foo<?A, ?B>`,
-    /// then after generalization we will wind up with a type like
-    /// `Foo<?C, ?D>`. When we enforce that `Foo<?A, ?B> <: Foo<?C,
-    /// ?D>` (or `>:`), we will wind up with the requirement that `?A
-    /// <: ?C`, but no particular relationship between `?B` and `?D`
-    /// (after all, we do not know the variance of the normalized form
-    /// of `A::Item` with respect to `A`). If we do nothing else, this
-    /// may mean that `?D` goes unconstrained (as in #41677). So, in
-    /// this scenario where we create a new type variable in a
-    /// bivariant context, we set the `needs_wf` flag to true. This
-    /// will force the calling code to check that `WF(Foo<?C, ?D>)`
-    /// holds, which in turn implies that `?C::Item == ?D`. So once
-    /// `?C` is constrained, that should suffice to restrict `?D`.
-    needs_wf: bool,
-}
-
-impl<'tcx> TypeRelation<'tcx> for Generalizer<'_, 'tcx> {
-    fn tcx(&self) -> TyCtxt<'tcx> {
-        self.infcx.tcx
-    }
-
-    fn param_env(&self) -> ty::ParamEnv<'tcx> {
-        self.param_env
-    }
-
-    fn tag(&self) -> &'static str {
-        "Generalizer"
-    }
-
-    fn a_is_expected(&self) -> bool {
-        true
-    }
-
-    fn binders<T>(
-        &mut self,
-        a: ty::Binder<'tcx, T>,
-        b: ty::Binder<'tcx, T>,
-    ) -> RelateResult<'tcx, ty::Binder<'tcx, T>>
-    where
-        T: Relate<'tcx>,
-    {
-        Ok(a.rebind(self.relate(a.skip_binder(), b.skip_binder())?))
-    }
-
-    fn relate_item_substs(
-        &mut self,
-        item_def_id: DefId,
-        a_subst: SubstsRef<'tcx>,
-        b_subst: SubstsRef<'tcx>,
-    ) -> RelateResult<'tcx, SubstsRef<'tcx>> {
-        if self.ambient_variance == ty::Variance::Invariant {
-            // Avoid fetching the variance if we are in an invariant
-            // context; no need, and it can induce dependency cycles
-            // (e.g., #41849).
-            relate::relate_substs(self, a_subst, b_subst)
-        } else {
-            let tcx = self.tcx();
-            let opt_variances = tcx.variances_of(item_def_id);
-            relate::relate_substs_with_variances(
-                self,
-                item_def_id,
-                &opt_variances,
-                a_subst,
-                b_subst,
-                true,
-            )
-        }
-    }
-
-    fn relate_with_variance<T: Relate<'tcx>>(
-        &mut self,
-        variance: ty::Variance,
-        _info: ty::VarianceDiagInfo<'tcx>,
-        a: T,
-        b: T,
-    ) -> RelateResult<'tcx, T> {
-        let old_ambient_variance = self.ambient_variance;
-        self.ambient_variance = self.ambient_variance.xform(variance);
-
-        let result = self.relate(a, b);
-        self.ambient_variance = old_ambient_variance;
-        result
-    }
-
-    fn tys(&mut self, t: Ty<'tcx>, t2: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
-        assert_eq!(t, t2); // we are abusing TypeRelation here; both LHS and RHS ought to be ==
-
-        if let Some(&result) = self.cache.get(&t) {
-            return Ok(result);
-        }
-        debug!("generalize: t={:?}", t);
-
-        // Check to see whether the type we are generalizing references
-        // any other type variable related to `vid` via
-        // subtyping. This is basically our "occurs check", preventing
-        // us from creating infinitely sized types.
-        let result = match *t.kind() {
-            ty::Infer(ty::TyVar(vid)) => {
-                let vid = self.infcx.inner.borrow_mut().type_variables().root_var(vid);
-                let sub_vid = self.infcx.inner.borrow_mut().type_variables().sub_root_var(vid);
-                if sub_vid == self.for_vid_sub_root {
-                    // If sub-roots are equal, then `for_vid` and
-                    // `vid` are related via subtyping.
-                    Err(TypeError::CyclicTy(self.root_ty))
-                } else {
-                    let probe = self.infcx.inner.borrow_mut().type_variables().probe(vid);
-                    match probe {
-                        TypeVariableValue::Known { value: u } => {
-                            debug!("generalize: known value {:?}", u);
-                            self.relate(u, u)
-                        }
-                        TypeVariableValue::Unknown { universe } => {
-                            match self.ambient_variance {
-                                // Invariant: no need to make a fresh type variable.
-                                ty::Invariant => {
-                                    if self.for_universe.can_name(universe) {
-                                        return Ok(t);
-                                    }
-                                }
-
-                                // Bivariant: make a fresh var, but we
-                                // may need a WF predicate. See
-                                // comment on `needs_wf` field for
-                                // more info.
-                                ty::Bivariant => self.needs_wf = true,
-
-                                // Co/contravariant: this will be
-                                // sufficiently constrained later on.
-                                ty::Covariant | ty::Contravariant => (),
-                            }
-
-                            let origin =
-                                *self.infcx.inner.borrow_mut().type_variables().var_origin(vid);
-                            let new_var_id = self
-                                .infcx
-                                .inner
-                                .borrow_mut()
-                                .type_variables()
-                                .new_var(self.for_universe, origin);
-                            let u = self.tcx().mk_ty_var(new_var_id);
-
-                            // Record that we replaced `vid` with `new_var_id` as part of a generalization
-                            // operation. This is needed to detect cyclic types. To see why, see the
-                            // docs in the `type_variables` module.
-                            self.infcx.inner.borrow_mut().type_variables().sub(vid, new_var_id);
-                            debug!("generalize: replacing original vid={:?} with new={:?}", vid, u);
-                            Ok(u)
-                        }
-                    }
-                }
-            }
-            ty::Infer(ty::IntVar(_) | ty::FloatVar(_)) => {
-                // No matter what mode we are in,
-                // integer/floating-point types must be equal to be
-                // relatable.
-                Ok(t)
-            }
-            ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => {
-                let s = self.relate(substs, substs)?;
-                Ok(if s == substs { t } else { self.infcx.tcx.mk_opaque(def_id, s) })
-            }
-            _ => relate::super_relate_tys(self, t, t),
-        }?;
-
-        self.cache.insert(t, result);
-        Ok(result)
-    }
-
-    fn regions(
-        &mut self,
-        r: ty::Region<'tcx>,
-        r2: ty::Region<'tcx>,
-    ) -> RelateResult<'tcx, ty::Region<'tcx>> {
-        assert_eq!(r, r2); // we are abusing TypeRelation here; both LHS and RHS ought to be ==
-
-        debug!("generalize: regions r={:?}", r);
-
-        match *r {
-            // Never make variables for regions bound within the type itself,
-            // nor for erased regions.
-            ty::ReLateBound(..) | ty::ReErased => {
-                return Ok(r);
-            }
-
-            ty::ReError(_) => {
-                return Ok(r);
-            }
-
-            ty::RePlaceholder(..)
-            | ty::ReVar(..)
-            | ty::ReStatic
-            | ty::ReEarlyBound(..)
-            | ty::ReFree(..) => {
-                // see common code below
-            }
-        }
-
-        // If we are in an invariant context, we can re-use the region
-        // as is, unless it happens to be in some universe that we
-        // can't name. (In the case of a region *variable*, we could
-        // use it if we promoted it into our universe, but we don't
-        // bother.)
-        if let ty::Invariant = self.ambient_variance {
-            let r_universe = self.infcx.universe_of_region(r);
-            if self.for_universe.can_name(r_universe) {
-                return Ok(r);
-            }
-        }
-
-        // FIXME: This is non-ideal because we don't give a
-        // very descriptive origin for this region variable.
-        Ok(self.infcx.next_region_var_in_universe(MiscVariable(self.cause.span), self.for_universe))
-    }
-
-    fn consts(
-        &mut self,
-        c: ty::Const<'tcx>,
-        c2: ty::Const<'tcx>,
-    ) -> RelateResult<'tcx, ty::Const<'tcx>> {
-        assert_eq!(c, c2); // we are abusing TypeRelation here; both LHS and RHS ought to be ==
-
-        match c.kind() {
-            ty::ConstKind::Infer(InferConst::Var(vid)) => {
-                let mut inner = self.infcx.inner.borrow_mut();
-                let variable_table = &mut inner.const_unification_table();
-                let var_value = variable_table.probe_value(vid);
-                match var_value.val {
-                    ConstVariableValue::Known { value: u } => {
-                        drop(inner);
-                        self.relate(u, u)
-                    }
-                    ConstVariableValue::Unknown { universe } => {
-                        if self.for_universe.can_name(universe) {
-                            Ok(c)
-                        } else {
-                            let new_var_id = variable_table.new_key(ConstVarValue {
-                                origin: var_value.origin,
-                                val: ConstVariableValue::Unknown { universe: self.for_universe },
-                            });
-                            Ok(self.tcx().mk_const(new_var_id, c.ty()))
-                        }
-                    }
-                }
-            }
-            ty::ConstKind::Unevaluated(ty::UnevaluatedConst { def, substs }) => {
-                let substs = self.relate_with_variance(
-                    ty::Variance::Invariant,
-                    ty::VarianceDiagInfo::default(),
-                    substs,
-                    substs,
-                )?;
-                Ok(self.tcx().mk_const(ty::UnevaluatedConst { def, substs }, c.ty()))
-            }
-            _ => relate::super_relate_consts(self, c, c),
-        }
-    }
-}
-
 pub trait ObligationEmittingRelation<'tcx>: TypeRelation<'tcx> {
     /// Register obligations that must hold in order for this relation to hold
     fn register_obligations(&mut self, obligations: PredicateObligations<'tcx>);
@@ -873,135 +499,3 @@ fn float_unification_error<'tcx>(
     let (ty::FloatVarValue(a), ty::FloatVarValue(b)) = v;
     TypeError::FloatMismatch(ExpectedFound::new(a_is_expected, a, b))
 }
-
-struct ConstInferUnifier<'cx, 'tcx> {
-    infcx: &'cx InferCtxt<'tcx>,
-
-    span: Span,
-
-    for_universe: ty::UniverseIndex,
-
-    /// The vid of the const variable that is in the process of being
-    /// instantiated; if we find this within the const we are folding,
-    /// that means we would have created a cyclic const.
-    target_vid: ty::ConstVid<'tcx>,
-}
-
-impl<'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for ConstInferUnifier<'_, 'tcx> {
-    type Error = TypeError<'tcx>;
-
-    fn interner(&self) -> TyCtxt<'tcx> {
-        self.infcx.tcx
-    }
-
-    #[instrument(level = "debug", skip(self), ret)]
-    fn try_fold_ty(&mut self, t: Ty<'tcx>) -> Result<Ty<'tcx>, TypeError<'tcx>> {
-        match t.kind() {
-            &ty::Infer(ty::TyVar(vid)) => {
-                let vid = self.infcx.inner.borrow_mut().type_variables().root_var(vid);
-                let probe = self.infcx.inner.borrow_mut().type_variables().probe(vid);
-                match probe {
-                    TypeVariableValue::Known { value: u } => {
-                        debug!("ConstOccursChecker: known value {:?}", u);
-                        u.try_fold_with(self)
-                    }
-                    TypeVariableValue::Unknown { universe } => {
-                        if self.for_universe.can_name(universe) {
-                            return Ok(t);
-                        }
-
-                        let origin =
-                            *self.infcx.inner.borrow_mut().type_variables().var_origin(vid);
-                        let new_var_id = self
-                            .infcx
-                            .inner
-                            .borrow_mut()
-                            .type_variables()
-                            .new_var(self.for_universe, origin);
-                        Ok(self.interner().mk_ty_var(new_var_id))
-                    }
-                }
-            }
-            ty::Infer(ty::IntVar(_) | ty::FloatVar(_)) => Ok(t),
-            _ => t.try_super_fold_with(self),
-        }
-    }
-
-    #[instrument(level = "debug", skip(self), ret)]
-    fn try_fold_region(
-        &mut self,
-        r: ty::Region<'tcx>,
-    ) -> Result<ty::Region<'tcx>, TypeError<'tcx>> {
-        debug!("ConstInferUnifier: r={:?}", r);
-
-        match *r {
-            // Never make variables for regions bound within the type itself,
-            // nor for erased regions.
-            ty::ReLateBound(..) | ty::ReErased | ty::ReError(_) => {
-                return Ok(r);
-            }
-
-            ty::RePlaceholder(..)
-            | ty::ReVar(..)
-            | ty::ReStatic
-            | ty::ReEarlyBound(..)
-            | ty::ReFree(..) => {
-                // see common code below
-            }
-        }
-
-        let r_universe = self.infcx.universe_of_region(r);
-        if self.for_universe.can_name(r_universe) {
-            return Ok(r);
-        } else {
-            // FIXME: This is non-ideal because we don't give a
-            // very descriptive origin for this region variable.
-            Ok(self.infcx.next_region_var_in_universe(MiscVariable(self.span), self.for_universe))
-        }
-    }
-
-    #[instrument(level = "debug", skip(self), ret)]
-    fn try_fold_const(&mut self, c: ty::Const<'tcx>) -> Result<ty::Const<'tcx>, TypeError<'tcx>> {
-        match c.kind() {
-            ty::ConstKind::Infer(InferConst::Var(vid)) => {
-                // Check if the current unification would end up
-                // unifying `target_vid` with a const which contains
-                // an inference variable which is unioned with `target_vid`.
-                //
-                // Not doing so can easily result in stack overflows.
-                if self
-                    .infcx
-                    .inner
-                    .borrow_mut()
-                    .const_unification_table()
-                    .unioned(self.target_vid, vid)
-                {
-                    return Err(TypeError::CyclicConst(c));
-                }
-
-                let var_value =
-                    self.infcx.inner.borrow_mut().const_unification_table().probe_value(vid);
-                match var_value.val {
-                    ConstVariableValue::Known { value: u } => u.try_fold_with(self),
-                    ConstVariableValue::Unknown { universe } => {
-                        if self.for_universe.can_name(universe) {
-                            Ok(c)
-                        } else {
-                            let new_var_id =
-                                self.infcx.inner.borrow_mut().const_unification_table().new_key(
-                                    ConstVarValue {
-                                        origin: var_value.origin,
-                                        val: ConstVariableValue::Unknown {
-                                            universe: self.for_universe,
-                                        },
-                                    },
-                                );
-                            Ok(self.interner().mk_const(new_var_id, c.ty()))
-                        }
-                    }
-                }
-            }
-            _ => c.try_super_fold_with(self),
-        }
-    }
-}
diff --git a/compiler/rustc_infer/src/infer/equate.rs b/compiler/rustc_infer/src/infer/equate.rs
index f90f7674b55..793505e4ab2 100644
--- a/compiler/rustc_infer/src/infer/equate.rs
+++ b/compiler/rustc_infer/src/infer/equate.rs
@@ -1,7 +1,7 @@
 use crate::infer::DefineOpaqueTypes;
 use crate::traits::PredicateObligations;
 
-use super::combine::{CombineFields, ObligationEmittingRelation, RelationDir};
+use super::combine::{CombineFields, ObligationEmittingRelation};
 use super::Subtype;
 
 use rustc_middle::ty::relate::{self, Relate, RelateResult, TypeRelation};
@@ -88,11 +88,11 @@ impl<'tcx> TypeRelation<'tcx> for Equate<'_, '_, 'tcx> {
             }
 
             (&ty::Infer(TyVar(a_id)), _) => {
-                self.fields.instantiate(b, RelationDir::EqTo, a_id, self.a_is_expected)?;
+                self.fields.instantiate(b, ty::Invariant, a_id, self.a_is_expected)?;
             }
 
             (_, &ty::Infer(TyVar(b_id))) => {
-                self.fields.instantiate(a, RelationDir::EqTo, b_id, self.a_is_expected)?;
+                self.fields.instantiate(a, ty::Invariant, b_id, self.a_is_expected)?;
             }
 
             (
diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
index ce70f39cc40..ad4f5058b5e 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
@@ -2723,7 +2723,7 @@ impl<'tcx> TypeRelation<'tcx> for SameTypeModuloInfer<'_, 'tcx> {
             | (ty::Infer(ty::InferTy::TyVar(_)), _)
             | (_, ty::Infer(ty::InferTy::TyVar(_))) => Ok(a),
             (ty::Infer(_), _) | (_, ty::Infer(_)) => Err(TypeError::Mismatch),
-            _ => relate::super_relate_tys(self, a, b),
+            _ => relate::structurally_relate_tys(self, a, b),
         }
     }
 
diff --git a/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs b/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs
index 064811bd29d..421eb807a14 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs
@@ -2,6 +2,7 @@ use super::TypeErrCtxt;
 use rustc_errors::Applicability::{MachineApplicable, MaybeIncorrect};
 use rustc_errors::{pluralize, Diagnostic, MultiSpan};
 use rustc_hir as hir;
+use rustc_hir::def::DefKind;
 use rustc_middle::traits::ObligationCauseCode;
 use rustc_middle::ty::error::ExpectedFound;
 use rustc_middle::ty::print::Printer;
@@ -256,6 +257,15 @@ impl<T> Trait<T> for X {
                             );
                         }
                     }
+                    (ty::Alias(ty::Opaque, alias), _) | (_, ty::Alias(ty::Opaque, alias)) if alias.def_id.is_local() && matches!(tcx.def_kind(body_owner_def_id), DefKind::AssocFn | DefKind::AssocConst) => {
+                        if tcx.is_type_alias_impl_trait(alias.def_id) {
+                            if !tcx.opaque_types_defined_by(body_owner_def_id.expect_local()).contains(&alias.def_id.expect_local()) {
+                                diag.span_note(tcx.def_span(body_owner_def_id), "\
+                                    this item must have the opaque type in its signature \
+                                    in order to be able to register hidden types");
+                            }
+                        }
+                    }
                     (ty::FnPtr(_), ty::FnDef(def, _))
                     if let hir::def::DefKind::Fn = tcx.def_kind(def) => {
                         diag.note(
diff --git a/compiler/rustc_infer/src/infer/generalize.rs b/compiler/rustc_infer/src/infer/generalize.rs
new file mode 100644
index 00000000000..d4a1dacde10
--- /dev/null
+++ b/compiler/rustc_infer/src/infer/generalize.rs
@@ -0,0 +1,479 @@
+use rustc_data_structures::sso::SsoHashMap;
+use rustc_hir::def_id::DefId;
+use rustc_middle::infer::unify_key::{ConstVarValue, ConstVariableValue};
+use rustc_middle::ty::error::TypeError;
+use rustc_middle::ty::relate::{self, Relate, RelateResult, TypeRelation};
+use rustc_middle::ty::{self, InferConst, Term, Ty, TyCtxt, TypeVisitableExt};
+use rustc_span::Span;
+
+use crate::infer::nll_relate::TypeRelatingDelegate;
+use crate::infer::type_variable::TypeVariableValue;
+use crate::infer::{InferCtxt, RegionVariableOrigin};
+
+/// Attempts to generalize `term` for the type variable `for_vid`.
+/// This checks for cycles -- that is, whether the type `term`
+/// references `for_vid`.
+pub(super) fn generalize<'tcx, D: GeneralizerDelegate<'tcx>, T: Into<Term<'tcx>> + Relate<'tcx>>(
+    infcx: &InferCtxt<'tcx>,
+    delegate: &mut D,
+    term: T,
+    for_vid: impl Into<ty::TermVid<'tcx>>,
+    ambient_variance: ty::Variance,
+) -> RelateResult<'tcx, Generalization<T>> {
+    let (for_universe, root_vid) = match for_vid.into() {
+        ty::TermVid::Ty(ty_vid) => (
+            infcx.probe_ty_var(ty_vid).unwrap_err(),
+            ty::TermVid::Ty(infcx.inner.borrow_mut().type_variables().sub_root_var(ty_vid)),
+        ),
+        ty::TermVid::Const(ct_vid) => (
+            infcx.probe_const_var(ct_vid).unwrap_err(),
+            ty::TermVid::Const(infcx.inner.borrow_mut().const_unification_table().find(ct_vid)),
+        ),
+    };
+
+    let mut generalizer = Generalizer {
+        infcx,
+        delegate,
+        ambient_variance,
+        root_vid,
+        for_universe,
+        root_term: term.into(),
+        needs_wf: false,
+        cache: Default::default(),
+    };
+
+    assert!(!term.has_escaping_bound_vars());
+    let value = generalizer.relate(term, term)?;
+    let needs_wf = generalizer.needs_wf;
+    Ok(Generalization { value, needs_wf })
+}
+
+/// Abstracts the handling of region vars between HIR and MIR/NLL typechecking
+/// in the generalizer code.
+pub trait GeneralizerDelegate<'tcx> {
+    fn param_env(&self) -> ty::ParamEnv<'tcx>;
+
+    fn forbid_inference_vars() -> bool;
+
+    fn generalize_region(&mut self, universe: ty::UniverseIndex) -> ty::Region<'tcx>;
+}
+
+pub struct CombineDelegate<'cx, 'tcx> {
+    pub infcx: &'cx InferCtxt<'tcx>,
+    pub param_env: ty::ParamEnv<'tcx>,
+    pub span: Span,
+}
+
+impl<'tcx> GeneralizerDelegate<'tcx> for CombineDelegate<'_, 'tcx> {
+    fn param_env(&self) -> ty::ParamEnv<'tcx> {
+        self.param_env
+    }
+
+    fn forbid_inference_vars() -> bool {
+        false
+    }
+
+    fn generalize_region(&mut self, universe: ty::UniverseIndex) -> ty::Region<'tcx> {
+        // FIXME: This is non-ideal because we don't give a
+        // very descriptive origin for this region variable.
+        self.infcx
+            .next_region_var_in_universe(RegionVariableOrigin::MiscVariable(self.span), universe)
+    }
+}
+
+impl<'tcx, T> GeneralizerDelegate<'tcx> for T
+where
+    T: TypeRelatingDelegate<'tcx>,
+{
+    fn param_env(&self) -> ty::ParamEnv<'tcx> {
+        <Self as TypeRelatingDelegate<'tcx>>::param_env(self)
+    }
+
+    fn forbid_inference_vars() -> bool {
+        <Self as TypeRelatingDelegate<'tcx>>::forbid_inference_vars()
+    }
+
+    fn generalize_region(&mut self, universe: ty::UniverseIndex) -> ty::Region<'tcx> {
+        <Self as TypeRelatingDelegate<'tcx>>::generalize_existential(self, universe)
+    }
+}
+
+/// The "generalizer" is used when handling inference variables.
+///
+/// The basic strategy for handling a constraint like `?A <: B` is to
+/// apply a "generalization strategy" to the term `B` -- this replaces
+/// all the lifetimes in the term `B` with fresh inference variables.
+/// (You can read more about the strategy in this [blog post].)
+///
+/// As an example, if we had `?A <: &'x u32`, we would generalize `&'x
+/// u32` to `&'0 u32` where `'0` is a fresh variable. This becomes the
+/// value of `A`. Finally, we relate `&'0 u32 <: &'x u32`, which
+/// establishes `'0: 'x` as a constraint.
+///
+/// [blog post]: https://is.gd/0hKvIr
+struct Generalizer<'me, 'tcx, D> {
+    infcx: &'me InferCtxt<'tcx>,
+
+    /// This is used to abstract the behaviors of the three previous
+    /// generalizer-like implementations (`Generalizer`, `TypeGeneralizer`,
+    /// and `ConstInferUnifier`). See [`GeneralizerDelegate`] for more
+    /// information.
+    delegate: &'me mut D,
+
+    /// After we generalize this type, we are going to relate it to
+    /// some other type. What will be the variance at this point?
+    ambient_variance: ty::Variance,
+
+    /// The vid of the type variable that is in the process of being
+    /// instantiated. If we find this within the value we are folding,
+    /// that means we would have created a cyclic value.
+    root_vid: ty::TermVid<'tcx>,
+
+    /// The universe of the type variable that is in the process of being
+    /// instantiated. If we find anything that this universe cannot name,
+    /// we reject the relation.
+    for_universe: ty::UniverseIndex,
+
+    /// The root term (const or type) we're generalizing. Used for cycle errors.
+    root_term: Term<'tcx>,
+
+    cache: SsoHashMap<Ty<'tcx>, Ty<'tcx>>,
+
+    /// See the field `needs_wf` in `Generalization`.
+    needs_wf: bool,
+}
+
+impl<'tcx, D> Generalizer<'_, 'tcx, D> {
+    /// Create an error that corresponds to the term kind in `root_term`
+    fn cyclic_term_error(&self) -> TypeError<'tcx> {
+        match self.root_term.unpack() {
+            ty::TermKind::Ty(ty) => TypeError::CyclicTy(ty),
+            ty::TermKind::Const(ct) => TypeError::CyclicConst(ct),
+        }
+    }
+}
+
+impl<'tcx, D> TypeRelation<'tcx> for Generalizer<'_, 'tcx, D>
+where
+    D: GeneralizerDelegate<'tcx>,
+{
+    fn tcx(&self) -> TyCtxt<'tcx> {
+        self.infcx.tcx
+    }
+
+    fn param_env(&self) -> ty::ParamEnv<'tcx> {
+        self.delegate.param_env()
+    }
+
+    fn tag(&self) -> &'static str {
+        "Generalizer"
+    }
+
+    fn a_is_expected(&self) -> bool {
+        true
+    }
+
+    fn relate_item_substs(
+        &mut self,
+        item_def_id: DefId,
+        a_subst: ty::SubstsRef<'tcx>,
+        b_subst: ty::SubstsRef<'tcx>,
+    ) -> RelateResult<'tcx, ty::SubstsRef<'tcx>> {
+        if self.ambient_variance == ty::Variance::Invariant {
+            // Avoid fetching the variance if we are in an invariant
+            // context; no need, and it can induce dependency cycles
+            // (e.g., #41849).
+            relate::relate_substs(self, a_subst, b_subst)
+        } else {
+            let tcx = self.tcx();
+            let opt_variances = tcx.variances_of(item_def_id);
+            relate::relate_substs_with_variances(
+                self,
+                item_def_id,
+                opt_variances,
+                a_subst,
+                b_subst,
+                true,
+            )
+        }
+    }
+
+    #[instrument(level = "debug", skip(self, variance, b), ret)]
+    fn relate_with_variance<T: Relate<'tcx>>(
+        &mut self,
+        variance: ty::Variance,
+        _info: ty::VarianceDiagInfo<'tcx>,
+        a: T,
+        b: T,
+    ) -> RelateResult<'tcx, T> {
+        let old_ambient_variance = self.ambient_variance;
+        self.ambient_variance = self.ambient_variance.xform(variance);
+        debug!(?self.ambient_variance, "new ambient variance");
+        let r = self.relate(a, b)?;
+        self.ambient_variance = old_ambient_variance;
+        Ok(r)
+    }
+
+    #[instrument(level = "debug", skip(self, t2), ret)]
+    fn tys(&mut self, t: Ty<'tcx>, t2: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
+        assert_eq!(t, t2); // we are misusing TypeRelation here; both LHS and RHS ought to be ==
+
+        if let Some(&result) = self.cache.get(&t) {
+            return Ok(result);
+        }
+
+        // Check to see whether the type we are generalizing references
+        // any other type variable related to `vid` via
+        // subtyping. This is basically our "occurs check", preventing
+        // us from creating infinitely sized types.
+        let g = match *t.kind() {
+            ty::Infer(ty::TyVar(_)) | ty::Infer(ty::IntVar(_)) | ty::Infer(ty::FloatVar(_))
+                if D::forbid_inference_vars() =>
+            {
+                bug!("unexpected inference variable encountered in NLL generalization: {t}");
+            }
+
+            ty::Infer(ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
+                bug!("unexpected infer type: {t}")
+            }
+
+            ty::Infer(ty::TyVar(vid)) => {
+                let mut inner = self.infcx.inner.borrow_mut();
+                let vid = inner.type_variables().root_var(vid);
+                let sub_vid = inner.type_variables().sub_root_var(vid);
+
+                if ty::TermVid::Ty(sub_vid) == self.root_vid {
+                    // If sub-roots are equal, then `root_vid` and
+                    // `vid` are related via subtyping.
+                    Err(self.cyclic_term_error())
+                } else {
+                    let probe = inner.type_variables().probe(vid);
+                    match probe {
+                        TypeVariableValue::Known { value: u } => {
+                            drop(inner);
+                            self.relate(u, u)
+                        }
+                        TypeVariableValue::Unknown { universe } => {
+                            match self.ambient_variance {
+                                // Invariant: no need to make a fresh type variable
+                                // if we can name the universe.
+                                ty::Invariant => {
+                                    if self.for_universe.can_name(universe) {
+                                        return Ok(t);
+                                    }
+                                }
+
+                                // Bivariant: make a fresh var, but we
+                                // may need a WF predicate. See
+                                // comment on `needs_wf` field for
+                                // more info.
+                                ty::Bivariant => self.needs_wf = true,
+
+                                // Co/contravariant: this will be
+                                // sufficiently constrained later on.
+                                ty::Covariant | ty::Contravariant => (),
+                            }
+
+                            let origin = *inner.type_variables().var_origin(vid);
+                            let new_var_id =
+                                inner.type_variables().new_var(self.for_universe, origin);
+                            let u = self.tcx().mk_ty_var(new_var_id);
+
+                            // Record that we replaced `vid` with `new_var_id` as part of a generalization
+                            // operation. This is needed to detect cyclic types. To see why, see the
+                            // docs in the `type_variables` module.
+                            inner.type_variables().sub(vid, new_var_id);
+                            debug!("replacing original vid={:?} with new={:?}", vid, u);
+                            Ok(u)
+                        }
+                    }
+                }
+            }
+
+            ty::Infer(ty::IntVar(_) | ty::FloatVar(_)) => {
+                // No matter what mode we are in,
+                // integer/floating-point types must be equal to be
+                // relatable.
+                Ok(t)
+            }
+
+            ty::Placeholder(placeholder) => {
+                if self.for_universe.can_name(placeholder.universe) {
+                    Ok(t)
+                } else {
+                    debug!(
+                        "root universe {:?} cannot name placeholder in universe {:?}",
+                        self.for_universe, placeholder.universe
+                    );
+                    Err(TypeError::Mismatch)
+                }
+            }
+
+            _ => relate::structurally_relate_tys(self, t, t),
+        }?;
+
+        self.cache.insert(t, g);
+        Ok(g)
+    }
+
+    #[instrument(level = "debug", skip(self, r2), ret)]
+    fn regions(
+        &mut self,
+        r: ty::Region<'tcx>,
+        r2: ty::Region<'tcx>,
+    ) -> RelateResult<'tcx, ty::Region<'tcx>> {
+        assert_eq!(r, r2); // we are misusing TypeRelation here; both LHS and RHS ought to be ==
+
+        match *r {
+            // Never make variables for regions bound within the type itself,
+            // nor for erased regions.
+            ty::ReLateBound(..) | ty::ReErased => {
+                return Ok(r);
+            }
+
+            // It doesn't really matter for correctness if we generalize ReError,
+            // since we're already on a doomed compilation path.
+            ty::ReError(_) => {
+                return Ok(r);
+            }
+
+            ty::RePlaceholder(..)
+            | ty::ReVar(..)
+            | ty::ReStatic
+            | ty::ReEarlyBound(..)
+            | ty::ReFree(..) => {
+                // see common code below
+            }
+        }
+
+        // If we are in an invariant context, we can re-use the region
+        // as is, unless it happens to be in some universe that we
+        // can't name.
+        if let ty::Invariant = self.ambient_variance {
+            let r_universe = self.infcx.universe_of_region(r);
+            if self.for_universe.can_name(r_universe) {
+                return Ok(r);
+            }
+        }
+
+        Ok(self.delegate.generalize_region(self.for_universe))
+    }
+
+    #[instrument(level = "debug", skip(self, c2), ret)]
+    fn consts(
+        &mut self,
+        c: ty::Const<'tcx>,
+        c2: ty::Const<'tcx>,
+    ) -> RelateResult<'tcx, ty::Const<'tcx>> {
+        assert_eq!(c, c2); // we are misusing TypeRelation here; both LHS and RHS ought to be ==
+
+        match c.kind() {
+            ty::ConstKind::Infer(InferConst::Var(_)) if D::forbid_inference_vars() => {
+                bug!("unexpected inference variable encountered in NLL generalization: {:?}", c);
+            }
+            ty::ConstKind::Infer(InferConst::Var(vid)) => {
+                // If root const vids are equal, then `root_vid` and
+                // `vid` are related and we'd be inferring an infinitely
+                // deep const.
+                if ty::TermVid::Const(
+                    self.infcx.inner.borrow_mut().const_unification_table().find(vid),
+                ) == self.root_vid
+                {
+                    return Err(self.cyclic_term_error());
+                }
+
+                let mut inner = self.infcx.inner.borrow_mut();
+                let variable_table = &mut inner.const_unification_table();
+                let var_value = variable_table.probe_value(vid);
+                match var_value.val {
+                    ConstVariableValue::Known { value: u } => {
+                        drop(inner);
+                        self.relate(u, u)
+                    }
+                    ConstVariableValue::Unknown { universe } => {
+                        if self.for_universe.can_name(universe) {
+                            Ok(c)
+                        } else {
+                            let new_var_id = variable_table.new_key(ConstVarValue {
+                                origin: var_value.origin,
+                                val: ConstVariableValue::Unknown { universe: self.for_universe },
+                            });
+                            Ok(self.tcx().mk_const(new_var_id, c.ty()))
+                        }
+                    }
+                }
+            }
+            // FIXME: remove this branch once `structurally_relate_consts` is fully
+            // structural.
+            ty::ConstKind::Unevaluated(ty::UnevaluatedConst { def, substs }) => {
+                let substs = self.relate_with_variance(
+                    ty::Variance::Invariant,
+                    ty::VarianceDiagInfo::default(),
+                    substs,
+                    substs,
+                )?;
+                Ok(self.tcx().mk_const(ty::UnevaluatedConst { def, substs }, c.ty()))
+            }
+            ty::ConstKind::Placeholder(placeholder) => {
+                if self.for_universe.can_name(placeholder.universe) {
+                    Ok(c)
+                } else {
+                    debug!(
+                        "root universe {:?} cannot name placeholder in universe {:?}",
+                        self.for_universe, placeholder.universe
+                    );
+                    Err(TypeError::Mismatch)
+                }
+            }
+            _ => relate::structurally_relate_consts(self, c, c),
+        }
+    }
+
+    #[instrument(level = "debug", skip(self), ret)]
+    fn binders<T>(
+        &mut self,
+        a: ty::Binder<'tcx, T>,
+        _: ty::Binder<'tcx, T>,
+    ) -> RelateResult<'tcx, ty::Binder<'tcx, T>>
+    where
+        T: Relate<'tcx>,
+    {
+        let result = self.relate(a.skip_binder(), a.skip_binder())?;
+        Ok(a.rebind(result))
+    }
+}
+
+/// Result from a generalization operation. This includes
+/// not only the generalized type, but also a bool flag
+/// indicating whether further WF checks are needed.
+#[derive(Debug)]
+pub struct Generalization<T> {
+    pub value: T,
+
+    /// If true, then the generalized type may not be well-formed,
+    /// even if the source type is well-formed, so we should add an
+    /// additional check to enforce that it is. This arises in
+    /// particular around 'bivariant' type parameters that are only
+    /// constrained by a where-clause. As an example, imagine a type:
+    ///
+    ///     struct Foo<A, B> where A: Iterator<Item = B> {
+    ///         data: A
+    ///     }
+    ///
+    /// here, `A` will be covariant, but `B` is
+    /// unconstrained. However, whatever it is, for `Foo` to be WF, it
+    /// must be equal to `A::Item`. If we have an input `Foo<?A, ?B>`,
+    /// then after generalization we will wind up with a type like
+    /// `Foo<?C, ?D>`. When we enforce that `Foo<?A, ?B> <: Foo<?C,
+    /// ?D>` (or `>:`), we will wind up with the requirement that `?A
+    /// <: ?C`, but no particular relationship between `?B` and `?D`
+    /// (after all, we do not know the variance of the normalized form
+    /// of `A::Item` with respect to `A`). If we do nothing else, this
+    /// may mean that `?D` goes unconstrained (as in #41677). So, in
+    /// this scenario where we create a new type variable in a
+    /// bivariant context, we set the `needs_wf` flag to true. This
+    /// will force the calling code to check that `WF(Foo<?C, ?D>)`
+    /// holds, which in turn implies that `?C::Item == ?D`. So once
+    /// `?C` is constrained, that should suffice to restrict `?D`.
+    pub needs_wf: bool,
+}
diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs
index 9a95a9c8375..f8329965c43 100644
--- a/compiler/rustc_infer/src/infer/mod.rs
+++ b/compiler/rustc_infer/src/infer/mod.rs
@@ -58,6 +58,7 @@ pub mod error_reporting;
 pub mod free_regions;
 mod freshen;
 mod fudge;
+mod generalize;
 mod glb;
 mod higher_ranked;
 pub mod lattice;
@@ -1533,7 +1534,7 @@ impl<'tcx> InferCtxt<'tcx> {
             if let Some(ct) = tcx.thir_abstract_const(unevaluated.def)? {
                 let ct = tcx.expand_abstract_consts(ct.subst(tcx, substs));
                 if let Err(e) = ct.error_reported() {
-                    return Err(ErrorHandled::Reported(e));
+                    return Err(ErrorHandled::Reported(e.into()));
                 } else if ct.has_non_region_infer() || ct.has_non_region_param() {
                     return Err(ErrorHandled::TooGeneric);
                 } else {
diff --git a/compiler/rustc_infer/src/infer/nll_relate/mod.rs b/compiler/rustc_infer/src/infer/nll_relate/mod.rs
index 88a0a81e276..4ae6af5f5be 100644
--- a/compiler/rustc_infer/src/infer/nll_relate/mod.rs
+++ b/compiler/rustc_infer/src/infer/nll_relate/mod.rs
@@ -21,21 +21,20 @@
 //!   thing we relate in chalk are basically domain goals and their
 //!   constituents)
 
-use crate::infer::InferCtxt;
-use crate::infer::{ConstVarValue, ConstVariableValue};
-use crate::infer::{TypeVariableOrigin, TypeVariableOriginKind};
-use crate::traits::{Obligation, PredicateObligations};
 use rustc_data_structures::fx::FxHashMap;
 use rustc_middle::traits::ObligationCause;
-use rustc_middle::ty::error::TypeError;
 use rustc_middle::ty::fold::FnMutDelegate;
-use rustc_middle::ty::relate::{self, Relate, RelateResult, TypeRelation};
+use rustc_middle::ty::relate::{Relate, RelateResult, TypeRelation};
 use rustc_middle::ty::visit::TypeVisitableExt;
 use rustc_middle::ty::{self, InferConst, Ty, TyCtxt};
 use rustc_span::{Span, Symbol};
 use std::fmt::Debug;
 
-use super::combine::ObligationEmittingRelation;
+use crate::infer::combine::ObligationEmittingRelation;
+use crate::infer::generalize::{self, Generalization};
+use crate::infer::InferCtxt;
+use crate::infer::{TypeVariableOrigin, TypeVariableOriginKind};
+use crate::traits::{Obligation, PredicateObligations};
 
 pub struct TypeRelating<'me, 'tcx, D>
 where
@@ -198,7 +197,7 @@ where
             _ => (),
         }
 
-        let generalized_ty = self.generalize_value(value_ty, vid)?;
+        let generalized_ty = self.generalize(value_ty, vid)?;
         debug!("relate_ty_var: generalized_ty = {:?}", generalized_ty);
 
         if D::forbid_inference_vars() {
@@ -217,26 +216,15 @@ where
         result
     }
 
-    fn generalize_value<T: Relate<'tcx>>(
-        &mut self,
-        value: T,
-        for_vid: ty::TyVid,
-    ) -> RelateResult<'tcx, T> {
-        let universe = self.infcx.probe_ty_var(for_vid).unwrap_err();
-
-        if value.has_escaping_bound_vars() {
-            bug!("trying to instantiate {for_vid:?} with escaping bound vars: {value:?}");
-        }
-
-        let mut generalizer = TypeGeneralizer {
-            infcx: self.infcx,
-            delegate: &mut self.delegate,
-            ambient_variance: self.ambient_variance,
-            for_vid_sub_root: self.infcx.inner.borrow_mut().type_variables().sub_root_var(for_vid),
-            universe,
-        };
-
-        generalizer.relate(value, value)
+    fn generalize(&mut self, ty: Ty<'tcx>, for_vid: ty::TyVid) -> RelateResult<'tcx, Ty<'tcx>> {
+        let Generalization { value: ty, needs_wf: _ } = generalize::generalize(
+            self.infcx,
+            &mut self.delegate,
+            ty,
+            for_vid,
+            self.ambient_variance,
+        )?;
+        Ok(ty)
     }
 
     fn relate_opaques(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
@@ -716,235 +704,3 @@ where
         })]);
     }
 }
-
-/// The "type generalizer" is used when handling inference variables.
-///
-/// The basic strategy for handling a constraint like `?A <: B` is to
-/// apply a "generalization strategy" to the type `B` -- this replaces
-/// all the lifetimes in the type `B` with fresh inference
-/// variables. (You can read more about the strategy in this [blog
-/// post].)
-///
-/// As an example, if we had `?A <: &'x u32`, we would generalize `&'x
-/// u32` to `&'0 u32` where `'0` is a fresh variable. This becomes the
-/// value of `A`. Finally, we relate `&'0 u32 <: &'x u32`, which
-/// establishes `'0: 'x` as a constraint.
-///
-/// [blog post]: https://is.gd/0hKvIr
-struct TypeGeneralizer<'me, 'tcx, D>
-where
-    D: TypeRelatingDelegate<'tcx>,
-{
-    infcx: &'me InferCtxt<'tcx>,
-
-    delegate: &'me mut D,
-
-    /// After we generalize this type, we are going to relate it to
-    /// some other type. What will be the variance at this point?
-    ambient_variance: ty::Variance,
-
-    /// The vid of the type variable that is in the process of being
-    /// instantiated. If we find this within the value we are folding,
-    /// that means we would have created a cyclic value.
-    for_vid_sub_root: ty::TyVid,
-
-    /// The universe of the type variable that is in the process of being
-    /// instantiated. If we find anything that this universe cannot name,
-    /// we reject the relation.
-    universe: ty::UniverseIndex,
-}
-
-impl<'tcx, D> TypeRelation<'tcx> for TypeGeneralizer<'_, 'tcx, D>
-where
-    D: TypeRelatingDelegate<'tcx>,
-{
-    fn tcx(&self) -> TyCtxt<'tcx> {
-        self.infcx.tcx
-    }
-
-    fn param_env(&self) -> ty::ParamEnv<'tcx> {
-        self.delegate.param_env()
-    }
-
-    fn tag(&self) -> &'static str {
-        "nll::generalizer"
-    }
-
-    fn a_is_expected(&self) -> bool {
-        true
-    }
-
-    fn relate_with_variance<T: Relate<'tcx>>(
-        &mut self,
-        variance: ty::Variance,
-        _info: ty::VarianceDiagInfo<'tcx>,
-        a: T,
-        b: T,
-    ) -> RelateResult<'tcx, T> {
-        debug!(
-            "TypeGeneralizer::relate_with_variance(variance={:?}, a={:?}, b={:?})",
-            variance, a, b
-        );
-
-        let old_ambient_variance = self.ambient_variance;
-        self.ambient_variance = self.ambient_variance.xform(variance);
-
-        debug!(
-            "TypeGeneralizer::relate_with_variance: ambient_variance = {:?}",
-            self.ambient_variance
-        );
-
-        let r = self.relate(a, b)?;
-
-        self.ambient_variance = old_ambient_variance;
-
-        debug!("TypeGeneralizer::relate_with_variance: r={:?}", r);
-
-        Ok(r)
-    }
-
-    fn tys(&mut self, a: Ty<'tcx>, _: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
-        use crate::infer::type_variable::TypeVariableValue;
-
-        debug!("TypeGeneralizer::tys(a={:?})", a);
-
-        match *a.kind() {
-            ty::Infer(ty::TyVar(_)) | ty::Infer(ty::IntVar(_)) | ty::Infer(ty::FloatVar(_))
-                if D::forbid_inference_vars() =>
-            {
-                bug!("unexpected inference variable encountered in NLL generalization: {:?}", a);
-            }
-
-            ty::Infer(ty::TyVar(vid)) => {
-                let mut inner = self.infcx.inner.borrow_mut();
-                let variables = &mut inner.type_variables();
-                let vid = variables.root_var(vid);
-                let sub_vid = variables.sub_root_var(vid);
-                if sub_vid == self.for_vid_sub_root {
-                    // If sub-roots are equal, then `for_vid` and
-                    // `vid` are related via subtyping.
-                    debug!("TypeGeneralizer::tys: occurs check failed");
-                    Err(TypeError::Mismatch)
-                } else {
-                    match variables.probe(vid) {
-                        TypeVariableValue::Known { value: u } => {
-                            drop(variables);
-                            self.relate(u, u)
-                        }
-                        TypeVariableValue::Unknown { universe: _universe } => {
-                            if self.ambient_variance == ty::Bivariant {
-                                // FIXME: we may need a WF predicate (related to #54105).
-                            }
-
-                            let origin = *variables.var_origin(vid);
-
-                            // Replacing with a new variable in the universe `self.universe`,
-                            // it will be unified later with the original type variable in
-                            // the universe `_universe`.
-                            let new_var_id = variables.new_var(self.universe, origin);
-
-                            let u = self.tcx().mk_ty_var(new_var_id);
-                            debug!("generalize: replacing original vid={:?} with new={:?}", vid, u);
-                            Ok(u)
-                        }
-                    }
-                }
-            }
-
-            ty::Infer(ty::IntVar(_) | ty::FloatVar(_)) => {
-                // No matter what mode we are in,
-                // integer/floating-point types must be equal to be
-                // relatable.
-                Ok(a)
-            }
-
-            ty::Placeholder(placeholder) => {
-                if self.universe.cannot_name(placeholder.universe) {
-                    debug!(
-                        "TypeGeneralizer::tys: root universe {:?} cannot name\
-                         placeholder in universe {:?}",
-                        self.universe, placeholder.universe
-                    );
-                    Err(TypeError::Mismatch)
-                } else {
-                    Ok(a)
-                }
-            }
-
-            _ => relate::super_relate_tys(self, a, a),
-        }
-    }
-
-    fn regions(
-        &mut self,
-        a: ty::Region<'tcx>,
-        _: ty::Region<'tcx>,
-    ) -> RelateResult<'tcx, ty::Region<'tcx>> {
-        debug!("TypeGeneralizer::regions(a={:?})", a);
-
-        if let ty::ReLateBound(..) = *a {
-            return Ok(a);
-        }
-
-        // For now, we just always create a fresh region variable to
-        // replace all the regions in the source type. In the main
-        // type checker, we special case the case where the ambient
-        // variance is `Invariant` and try to avoid creating a fresh
-        // region variable, but since this comes up so much less in
-        // NLL (only when users use `_` etc) it is much less
-        // important.
-        //
-        // As an aside, since these new variables are created in
-        // `self.universe` universe, this also serves to enforce the
-        // universe scoping rules.
-        //
-        // FIXME(#54105) -- if the ambient variance is bivariant,
-        // though, we may however need to check well-formedness or
-        // risk a problem like #41677 again.
-        let replacement_region_vid = self.delegate.generalize_existential(self.universe);
-
-        Ok(replacement_region_vid)
-    }
-
-    fn consts(
-        &mut self,
-        a: ty::Const<'tcx>,
-        _: ty::Const<'tcx>,
-    ) -> RelateResult<'tcx, ty::Const<'tcx>> {
-        match a.kind() {
-            ty::ConstKind::Infer(InferConst::Var(_)) if D::forbid_inference_vars() => {
-                bug!("unexpected inference variable encountered in NLL generalization: {:?}", a);
-            }
-            ty::ConstKind::Infer(InferConst::Var(vid)) => {
-                let mut inner = self.infcx.inner.borrow_mut();
-                let variable_table = &mut inner.const_unification_table();
-                let var_value = variable_table.probe_value(vid);
-                match var_value.val.known() {
-                    Some(u) => self.relate(u, u),
-                    None => {
-                        let new_var_id = variable_table.new_key(ConstVarValue {
-                            origin: var_value.origin,
-                            val: ConstVariableValue::Unknown { universe: self.universe },
-                        });
-                        Ok(self.tcx().mk_const(new_var_id, a.ty()))
-                    }
-                }
-            }
-            ty::ConstKind::Unevaluated(..) if self.tcx().lazy_normalization() => Ok(a),
-            _ => relate::super_relate_consts(self, a, a),
-        }
-    }
-
-    fn binders<T>(
-        &mut self,
-        a: ty::Binder<'tcx, T>,
-        _: ty::Binder<'tcx, T>,
-    ) -> RelateResult<'tcx, ty::Binder<'tcx, T>>
-    where
-        T: Relate<'tcx>,
-    {
-        debug!("TypeGeneralizer::binders(a={:?})", a);
-        let result = self.relate(a.skip_binder(), a.skip_binder())?;
-        Ok(a.rebind(result))
-    }
-}
diff --git a/compiler/rustc_infer/src/infer/opaque_types.rs b/compiler/rustc_infer/src/infer/opaque_types.rs
index 362b22b23a8..b88ba04b273 100644
--- a/compiler/rustc_infer/src/infer/opaque_types.rs
+++ b/compiler/rustc_infer/src/infer/opaque_types.rs
@@ -149,7 +149,7 @@ impl<'tcx> InferCtxt<'tcx> {
                     // no one encounters it in practice.
                     // It does occur however in `fn fut() -> impl Future<Output = i32> { async { 42 } }`,
                     // where it is of no concern, so we only check for TAITs.
-                    if let Some(OpaqueTyOrigin::TyAlias) =
+                    if let Some(OpaqueTyOrigin::TyAlias { .. }) =
                         b_def_id.as_local().and_then(|b_def_id| self.opaque_type_origin(b_def_id))
                     {
                         self.tcx.sess.emit_err(OpaqueHiddenTypeDiag {
@@ -381,8 +381,12 @@ impl<'tcx> InferCtxt<'tcx> {
             // Anonymous `impl Trait`
             hir::OpaqueTyOrigin::FnReturn(parent) => parent == parent_def_id,
             // Named `type Foo = impl Bar;`
-            hir::OpaqueTyOrigin::TyAlias => {
-                may_define_opaque_type(self.tcx, parent_def_id, opaque_hir_id)
+            hir::OpaqueTyOrigin::TyAlias { in_assoc_ty } => {
+                if in_assoc_ty {
+                    self.tcx.opaque_types_defined_by(parent_def_id).contains(&def_id)
+                } else {
+                    may_define_opaque_type(self.tcx, parent_def_id, opaque_hir_id)
+                }
             }
         };
         in_definition_scope.then_some(origin)
@@ -526,19 +530,18 @@ impl<'tcx> InferCtxt<'tcx> {
         // these are the same span, but not in cases like `-> (impl
         // Foo, impl Bar)`.
         let span = cause.span;
-
-        let mut obligations = vec![];
         let prev = self.inner.borrow_mut().opaque_types().register(
             OpaqueTypeKey { def_id, substs },
             OpaqueHiddenType { ty: hidden_ty, span },
             origin,
         );
-        if let Some(prev) = prev {
-            obligations = self
-                .at(&cause, param_env)
+        let mut obligations = if let Some(prev) = prev {
+            self.at(&cause, param_env)
                 .eq_exp(DefineOpaqueTypes::Yes, a_is_expected, prev, hidden_ty)?
-                .obligations;
-        }
+                .obligations
+        } else {
+            Vec::new()
+        };
 
         let item_bounds = tcx.explicit_item_bounds(def_id);
 
diff --git a/compiler/rustc_infer/src/infer/outlives/test_type_match.rs b/compiler/rustc_infer/src/infer/outlives/test_type_match.rs
index 75ce0f83fd6..cd2462d3c31 100644
--- a/compiler/rustc_infer/src/infer/outlives/test_type_match.rs
+++ b/compiler/rustc_infer/src/infer/outlives/test_type_match.rs
@@ -187,7 +187,7 @@ impl<'tcx> TypeRelation<'tcx> for Match<'tcx> {
         } else if pattern == value {
             Ok(pattern)
         } else {
-            relate::super_relate_tys(self, pattern, value)
+            relate::structurally_relate_tys(self, pattern, value)
         }
     }
 
@@ -201,7 +201,7 @@ impl<'tcx> TypeRelation<'tcx> for Match<'tcx> {
         if pattern == value {
             Ok(pattern)
         } else {
-            relate::super_relate_consts(self, pattern, value)
+            relate::structurally_relate_consts(self, pattern, value)
         }
     }
 
diff --git a/compiler/rustc_infer/src/infer/sub.rs b/compiler/rustc_infer/src/infer/sub.rs
index 3766c250a9c..e0f29a8de8f 100644
--- a/compiler/rustc_infer/src/infer/sub.rs
+++ b/compiler/rustc_infer/src/infer/sub.rs
@@ -1,4 +1,4 @@
-use super::combine::{CombineFields, RelationDir};
+use super::combine::CombineFields;
 use super::{DefineOpaqueTypes, ObligationEmittingRelation, SubregionOrigin};
 
 use crate::traits::{Obligation, PredicateObligations};
@@ -108,11 +108,11 @@ impl<'tcx> TypeRelation<'tcx> for Sub<'_, '_, 'tcx> {
                 Ok(a)
             }
             (&ty::Infer(TyVar(a_id)), _) => {
-                self.fields.instantiate(b, RelationDir::SupertypeOf, a_id, !self.a_is_expected)?;
+                self.fields.instantiate(b, ty::Contravariant, a_id, !self.a_is_expected)?;
                 Ok(a)
             }
             (_, &ty::Infer(TyVar(b_id))) => {
-                self.fields.instantiate(a, RelationDir::SubtypeOf, b_id, self.a_is_expected)?;
+                self.fields.instantiate(a, ty::Covariant, b_id, self.a_is_expected)?;
                 Ok(a)
             }
 
diff --git a/compiler/rustc_interface/src/interface.rs b/compiler/rustc_interface/src/interface.rs
index 51354c2b127..681819703c2 100644
--- a/compiler/rustc_interface/src/interface.rs
+++ b/compiler/rustc_interface/src/interface.rs
@@ -9,6 +9,7 @@ use rustc_data_structures::OnDrop;
 use rustc_errors::registry::Registry;
 use rustc_errors::{ErrorGuaranteed, Handler};
 use rustc_lint::LintStore;
+use rustc_middle::query::{ExternProviders, Providers};
 use rustc_middle::{bug, ty};
 use rustc_parse::maybe_new_parser_from_source_str;
 use rustc_query_impl::QueryCtxt;
@@ -37,8 +38,7 @@ pub struct Compiler {
     pub(crate) sess: Lrc<Session>,
     codegen_backend: Lrc<Box<dyn CodegenBackend>>,
     pub(crate) register_lints: Option<Box<dyn Fn(&Session, &mut LintStore) + Send + Sync>>,
-    pub(crate) override_queries:
-        Option<fn(&Session, &mut ty::query::Providers, &mut ty::query::ExternProviders)>,
+    pub(crate) override_queries: Option<fn(&Session, &mut Providers, &mut ExternProviders)>,
 }
 
 impl Compiler {
@@ -60,6 +60,11 @@ impl Compiler {
     }
 }
 
+#[allow(rustc::bad_opt_access)]
+pub fn set_thread_safe_mode(sopts: &config::UnstableOptions) {
+    rustc_data_structures::sync::set_dyn_thread_safe_mode(sopts.threads > 1);
+}
+
 /// Converts strings provided as `--cfg [cfgspec]` into a `crate_cfg`.
 pub fn parse_cfgspecs(cfgspecs: Vec<String>) -> FxHashSet<(String, Option<String>)> {
     rustc_span::create_default_session_if_not_set_then(move |_| {
@@ -75,7 +80,7 @@ pub fn parse_cfgspecs(cfgspecs: Vec<String>) -> FxHashSet<(String, Option<String
                     ($reason: expr) => {
                         early_error(
                             ErrorOutputType::default(),
-                            &format!(concat!("invalid `--cfg` argument: `{}` (", $reason, ")"), s),
+                            format!(concat!("invalid `--cfg` argument: `{}` (", $reason, ")"), s),
                         );
                     };
                 }
@@ -134,10 +139,7 @@ pub fn parse_check_cfg(specs: Vec<String>) -> CheckCfg {
                 ($reason: expr) => {
                     early_error(
                         ErrorOutputType::default(),
-                        &format!(
-                            concat!("invalid `--check-cfg` argument: `{}` (", $reason, ")"),
-                            s
-                        ),
+                        format!(concat!("invalid `--check-cfg` argument: `{}` (", $reason, ")"), s),
                     )
                 };
             }
@@ -270,8 +272,7 @@ pub struct Config {
     /// the list of queries.
     ///
     /// The second parameter is local providers and the third parameter is external providers.
-    pub override_queries:
-        Option<fn(&Session, &mut ty::query::Providers, &mut ty::query::ExternProviders)>,
+    pub override_queries: Option<fn(&Session, &mut Providers, &mut ExternProviders)>,
 
     /// This is a callback from the driver that is called to create a codegen backend.
     pub make_codegen_backend:
@@ -347,7 +348,7 @@ pub fn try_print_query_stack(handler: &Handler, num_frames: Option<usize>) {
     // state if it was responsible for triggering the panic.
     let i = ty::tls::with_context_opt(|icx| {
         if let Some(icx) = icx {
-            print_query_stack(QueryCtxt { tcx: icx.tcx }, icx.query, handler, num_frames)
+            print_query_stack(QueryCtxt::new(icx.tcx), icx.query, handler, num_frames)
         } else {
             0
         }
diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs
index 48401eabd1e..42d8d228091 100644
--- a/compiler/rustc_interface/src/passes.rs
+++ b/compiler/rustc_interface/src/passes.rs
@@ -17,7 +17,7 @@ use rustc_lint::{unerased_lint_store, BufferedEarlyLint, EarlyCheckNode, LintSto
 use rustc_metadata::creader::CStore;
 use rustc_middle::arena::Arena;
 use rustc_middle::dep_graph::DepGraph;
-use rustc_middle::ty::query::{ExternProviders, Providers};
+use rustc_middle::query::{ExternProviders, Providers};
 use rustc_middle::ty::{self, GlobalCtxt, RegisteredTools, TyCtxt};
 use rustc_mir_build as mir_build;
 use rustc_parse::{parse_crate_from_file, parse_crate_from_source_str, validate_attr};
@@ -89,6 +89,7 @@ pub fn register_plugins<'a>(
         crate_name,
         sess.crate_types().contains(&CrateType::Executable),
         sess.opts.cg.metadata.clone(),
+        sess.cfg_version,
     );
     sess.stable_crate_id.set(stable_crate_id).expect("not yet initialized");
     rustc_incremental::prepare_session_directory(sess, crate_name, stable_crate_id)?;
@@ -486,6 +487,11 @@ fn write_out_deps(tcx: TyCtxt<'_>, outputs: &OutputFilenames, out_filenames: &[P
             files.push(normalize_path(profile_sample.as_path().to_path_buf()));
         }
 
+        // Debugger visualizer files
+        for debugger_visualizer in tcx.debugger_visualizers(LOCAL_CRATE) {
+            files.push(normalize_path(debugger_visualizer.path.clone().unwrap()));
+        }
+
         if sess.binary_dep_depinfo() {
             if let Some(ref backend) = sess.opts.unstable_opts.codegen_backend {
                 if backend.contains('.') {
@@ -691,6 +697,8 @@ pub fn create_global_ctxt<'tcx>(
         callback(sess, &mut local_providers, &mut extern_providers);
     }
 
+    let incremental = dep_graph.is_fully_enabled();
+
     sess.time("setup_global_ctxt", || {
         gcx_cell.get_or_init(move || {
             TyCtxt::create_global_ctxt(
@@ -700,9 +708,13 @@ pub fn create_global_ctxt<'tcx>(
                 hir_arena,
                 untracked,
                 dep_graph,
-                query_result_on_disk_cache,
                 rustc_query_impl::query_callbacks(arena),
-                rustc_query_impl::query_system_fns(local_providers, extern_providers),
+                rustc_query_impl::query_system(
+                    local_providers,
+                    extern_providers,
+                    query_result_on_disk_cache,
+                    incremental,
+                ),
             )
         })
     })
diff --git a/compiler/rustc_interface/src/proc_macro_decls.rs b/compiler/rustc_interface/src/proc_macro_decls.rs
index 1c58caa0353..2c8014d8b3a 100644
--- a/compiler/rustc_interface/src/proc_macro_decls.rs
+++ b/compiler/rustc_interface/src/proc_macro_decls.rs
@@ -1,6 +1,6 @@
 use rustc_ast::attr;
 use rustc_hir::def_id::LocalDefId;
-use rustc_middle::ty::query::Providers;
+use rustc_middle::query::Providers;
 use rustc_middle::ty::TyCtxt;
 use rustc_span::symbol::sym;
 
diff --git a/compiler/rustc_interface/src/queries.rs b/compiler/rustc_interface/src/queries.rs
index 6483d51a0b9..c441a8ffd6f 100644
--- a/compiler/rustc_interface/src/queries.rs
+++ b/compiler/rustc_interface/src/queries.rs
@@ -369,7 +369,7 @@ impl Linker {
 
         if sess.opts.unstable_opts.no_link {
             let rlink_file = self.prepare_outputs.with_extension(config::RLINK_EXT);
-            CodegenResults::serialize_rlink(&rlink_file, &codegen_results)
+            CodegenResults::serialize_rlink(sess, &rlink_file, &codegen_results)
                 .map_err(|error| sess.emit_fatal(FailedWritingFile { path: &rlink_file, error }))?;
             return Ok(());
         }
diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs
index 1bae771e373..28e719a40e5 100644
--- a/compiler/rustc_interface/src/tests.rs
+++ b/compiler/rustc_interface/src/tests.rs
@@ -52,7 +52,8 @@ fn mk_session(matches: getopts::Matches) -> (Session, CfgSpecs) {
         output_file: None,
         temps_dir,
     };
-    let sess = build_session(sessopts, io, None, registry, vec![], Default::default(), None, None);
+    let sess =
+        build_session(sessopts, io, None, registry, vec![], Default::default(), None, None, "");
     (sess, cfg)
 }
 
diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs
index 8d37b1053d8..cb19750203e 100644
--- a/compiler/rustc_interface/src/util.rs
+++ b/compiler/rustc_interface/src/util.rs
@@ -88,7 +88,7 @@ pub fn create_session(
     ) {
         Ok(bundle) => bundle,
         Err(e) => {
-            early_error(sopts.error_format, &format!("failed to load fluent bundle: {e}"));
+            early_error(sopts.error_format, format!("failed to load fluent bundle: {e}"));
         }
     };
 
@@ -104,6 +104,7 @@ pub fn create_session(
         lint_caps,
         file_loader,
         target_override,
+        rustc_version_str().unwrap_or("unknown"),
     );
 
     codegen_backend.init(&sess);
@@ -220,13 +221,13 @@ pub(crate) fn run_in_thread_pool_with_globals<F: FnOnce() -> R + Send, R: Send>(
 fn load_backend_from_dylib(path: &Path) -> MakeBackendFn {
     let lib = unsafe { Library::new(path) }.unwrap_or_else(|err| {
         let err = format!("couldn't load codegen backend {path:?}: {err}");
-        early_error(ErrorOutputType::default(), &err);
+        early_error(ErrorOutputType::default(), err);
     });
 
     let backend_sym = unsafe { lib.get::<MakeBackendFn>(b"__rustc_codegen_backend") }
         .unwrap_or_else(|e| {
             let err = format!("couldn't load codegen backend: {e}");
-            early_error(ErrorOutputType::default(), &err);
+            early_error(ErrorOutputType::default(), err);
         });
 
     // Intentionally leak the dynamic library. We can't ever unload it
@@ -320,7 +321,7 @@ fn get_codegen_sysroot(maybe_sysroot: &Option<PathBuf>, backend_name: &str) -> M
             "failed to find a `codegen-backends` folder \
                            in the sysroot candidates:\n* {candidates}"
         );
-        early_error(ErrorOutputType::default(), &err);
+        early_error(ErrorOutputType::default(), err);
     });
     info!("probing {} for a codegen backend", sysroot.display());
 
@@ -331,7 +332,7 @@ fn get_codegen_sysroot(maybe_sysroot: &Option<PathBuf>, backend_name: &str) -> M
             sysroot.display(),
             e
         );
-        early_error(ErrorOutputType::default(), &err);
+        early_error(ErrorOutputType::default(), err);
     });
 
     let mut file: Option<PathBuf> = None;
@@ -359,7 +360,7 @@ fn get_codegen_sysroot(maybe_sysroot: &Option<PathBuf>, backend_name: &str) -> M
                 prev.display(),
                 path.display()
             );
-            early_error(ErrorOutputType::default(), &err);
+            early_error(ErrorOutputType::default(), err);
         }
         file = Some(path.clone());
     }
@@ -368,7 +369,7 @@ fn get_codegen_sysroot(maybe_sysroot: &Option<PathBuf>, backend_name: &str) -> M
         Some(ref s) => load_backend_from_dylib(s),
         None => {
             let err = format!("unsupported builtin codegen backend `{backend_name}`");
-            early_error(ErrorOutputType::default(), &err);
+            early_error(ErrorOutputType::default(), err);
         }
     }
 }
diff --git a/compiler/rustc_lexer/src/lib.rs b/compiler/rustc_lexer/src/lib.rs
index c07dc19a0ac..d511d2b1280 100644
--- a/compiler/rustc_lexer/src/lib.rs
+++ b/compiler/rustc_lexer/src/lib.rs
@@ -582,34 +582,38 @@ impl Cursor<'_> {
         let mut base = Base::Decimal;
         if first_digit == '0' {
             // Attempt to parse encoding base.
-            let has_digits = match self.first() {
+            match self.first() {
                 'b' => {
                     base = Base::Binary;
                     self.bump();
-                    self.eat_decimal_digits()
+                    if !self.eat_decimal_digits() {
+                        return Int { base, empty_int: true };
+                    }
                 }
                 'o' => {
                     base = Base::Octal;
                     self.bump();
-                    self.eat_decimal_digits()
+                    if !self.eat_decimal_digits() {
+                        return Int { base, empty_int: true };
+                    }
                 }
                 'x' => {
                     base = Base::Hexadecimal;
                     self.bump();
-                    self.eat_hexadecimal_digits()
+                    if !self.eat_hexadecimal_digits() {
+                        return Int { base, empty_int: true };
+                    }
                 }
-                // Not a base prefix.
-                '0'..='9' | '_' | '.' | 'e' | 'E' => {
+                // Not a base prefix; consume additional digits.
+                '0'..='9' | '_' => {
                     self.eat_decimal_digits();
-                    true
                 }
+
+                // Also not a base prefix; nothing more to do here.
+                '.' | 'e' | 'E' => {}
+
                 // Just a 0.
                 _ => return Int { base, empty_int: false },
-            };
-            // Base prefix was provided, but there were no digits
-            // after it, e.g. "0x".
-            if !has_digits {
-                return Int { base, empty_int: true };
             }
         } else {
             // No base prefix, parse number in the usual way.
diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl
index 71cf644eb50..e1658d3ff82 100644
--- a/compiler/rustc_lint/messages.ftl
+++ b/compiler/rustc_lint/messages.ftl
@@ -520,3 +520,19 @@ lint_opaque_hidden_inferred_bound = opaque type `{$ty}` does not satisfy its ass
     .specifically = this associated type bound is unsatisfied for `{$proj_ty}`
 
 lint_opaque_hidden_inferred_bound_sugg = add this bound
+
+lint_dropping_references = calls to `std::mem::drop` with a reference instead of an owned value does nothing
+    .label = argument has type `{$arg_ty}`
+    .note = use `let _ = ...` to ignore the expression or result
+
+lint_dropping_copy_types = calls to `std::mem::drop` with a value that implements `Copy` does nothing
+    .label = argument has type `{$arg_ty}`
+    .note = use `let _ = ...` to ignore the expression or result
+
+lint_forgetting_references = calls to `std::mem::forget` with a reference instead of an owned value does nothing
+    .label = argument has type `{$arg_ty}`
+    .note = use `let _ = ...` to ignore the expression or result
+
+lint_forgetting_copy_types = calls to `std::mem::forget` with a value that implements `Copy` does nothing
+    .label = argument has type `{$arg_ty}`
+    .note = use `let _ = ...` to ignore the expression or result
diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs
index b1c45eaf601..6601a80920b 100644
--- a/compiler/rustc_lint/src/builtin.rs
+++ b/compiler/rustc_lint/src/builtin.rs
@@ -611,7 +611,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc {
 
 declare_lint! {
     /// The `missing_copy_implementations` lint detects potentially-forgotten
-    /// implementations of [`Copy`].
+    /// implementations of [`Copy`] for public types.
     ///
     /// [`Copy`]: https://doc.rust-lang.org/std/marker/trait.Copy.html
     ///
@@ -647,7 +647,9 @@ declare_lint_pass!(MissingCopyImplementations => [MISSING_COPY_IMPLEMENTATIONS])
 
 impl<'tcx> LateLintPass<'tcx> for MissingCopyImplementations {
     fn check_item(&mut self, cx: &LateContext<'_>, item: &hir::Item<'_>) {
-        if !cx.effective_visibilities.is_reachable(item.owner_id.def_id) {
+        if !(cx.effective_visibilities.is_reachable(item.owner_id.def_id)
+            && cx.tcx.local_visibility(item.owner_id.def_id).is_public())
+        {
             return;
         }
         let (def, ty) = match item.kind {
@@ -727,7 +729,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingCopyImplementations {
 
 declare_lint! {
     /// The `missing_debug_implementations` lint detects missing
-    /// implementations of [`fmt::Debug`].
+    /// implementations of [`fmt::Debug`] for public types.
     ///
     /// [`fmt::Debug`]: https://doc.rust-lang.org/std/fmt/trait.Debug.html
     ///
@@ -766,7 +768,9 @@ impl_lint_pass!(MissingDebugImplementations => [MISSING_DEBUG_IMPLEMENTATIONS]);
 
 impl<'tcx> LateLintPass<'tcx> for MissingDebugImplementations {
     fn check_item(&mut self, cx: &LateContext<'_>, item: &hir::Item<'_>) {
-        if !cx.effective_visibilities.is_reachable(item.owner_id.def_id) {
+        if !(cx.effective_visibilities.is_reachable(item.owner_id.def_id)
+            && cx.tcx.local_visibility(item.owner_id.def_id).is_public())
+        {
             return;
         }
 
diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs
index 53d7cf74cde..1d0c43e95e0 100644
--- a/compiler/rustc_lint/src/context.rs
+++ b/compiler/rustc_lint/src/context.rs
@@ -49,9 +49,9 @@ use std::cell::Cell;
 use std::iter;
 use std::slice;
 
-type EarlyLintPassFactory = dyn Fn() -> EarlyLintPassObject + sync::Send + sync::Sync;
+type EarlyLintPassFactory = dyn Fn() -> EarlyLintPassObject + sync::DynSend + sync::DynSync;
 type LateLintPassFactory =
-    dyn for<'tcx> Fn(TyCtxt<'tcx>) -> LateLintPassObject<'tcx> + sync::Send + sync::Sync;
+    dyn for<'tcx> Fn(TyCtxt<'tcx>) -> LateLintPassObject<'tcx> + sync::DynSend + sync::DynSync;
 
 /// Information about the registered lints.
 ///
@@ -169,7 +169,7 @@ impl LintStore {
 
     pub fn register_early_pass(
         &mut self,
-        pass: impl Fn() -> EarlyLintPassObject + 'static + sync::Send + sync::Sync,
+        pass: impl Fn() -> EarlyLintPassObject + 'static + sync::DynSend + sync::DynSync,
     ) {
         self.early_passes.push(Box::new(pass));
     }
@@ -182,7 +182,7 @@ impl LintStore {
     /// * See [rust-clippy#5518](https://github.com/rust-lang/rust-clippy/pull/5518)
     pub fn register_pre_expansion_pass(
         &mut self,
-        pass: impl Fn() -> EarlyLintPassObject + 'static + sync::Send + sync::Sync,
+        pass: impl Fn() -> EarlyLintPassObject + 'static + sync::DynSend + sync::DynSync,
     ) {
         self.pre_expansion_passes.push(Box::new(pass));
     }
@@ -191,8 +191,8 @@ impl LintStore {
         &mut self,
         pass: impl for<'tcx> Fn(TyCtxt<'tcx>) -> LateLintPassObject<'tcx>
         + 'static
-        + sync::Send
-        + sync::Sync,
+        + sync::DynSend
+        + sync::DynSync,
     ) {
         self.late_passes.push(Box::new(pass));
     }
@@ -201,8 +201,8 @@ impl LintStore {
         &mut self,
         pass: impl for<'tcx> Fn(TyCtxt<'tcx>) -> LateLintPassObject<'tcx>
         + 'static
-        + sync::Send
-        + sync::Sync,
+        + sync::DynSend
+        + sync::DynSync,
     ) {
         self.late_module_passes.push(Box::new(pass));
     }
diff --git a/compiler/rustc_lint/src/drop_forget_useless.rs b/compiler/rustc_lint/src/drop_forget_useless.rs
new file mode 100644
index 00000000000..ed2b384805e
--- /dev/null
+++ b/compiler/rustc_lint/src/drop_forget_useless.rs
@@ -0,0 +1,164 @@
+use rustc_hir::{Arm, Expr, ExprKind, Node};
+use rustc_span::sym;
+
+use crate::{
+    lints::{DropCopyDiag, DropRefDiag, ForgetCopyDiag, ForgetRefDiag},
+    LateContext, LateLintPass, LintContext,
+};
+
+declare_lint! {
+    /// The `dropping_references` lint checks for calls to `std::mem::drop` with a reference
+    /// instead of an owned value.
+    ///
+    /// ### Example
+    ///
+    /// ```rust
+    /// # fn operation_that_requires_mutex_to_be_unlocked() {} // just to make it compile
+    /// # let mutex = std::sync::Mutex::new(1); // just to make it compile
+    /// let mut lock_guard = mutex.lock();
+    /// std::mem::drop(&lock_guard); // Should have been drop(lock_guard), mutex
+    /// // still locked
+    /// operation_that_requires_mutex_to_be_unlocked();
+    /// ```
+    ///
+    /// {{produces}}
+    ///
+    /// ### Explanation
+    ///
+    /// Calling `drop` on a reference will only drop the
+    /// reference itself, which is a no-op. It will not call the `drop` method (from
+    /// the `Drop` trait implementation) on the underlying referenced value, which
+    /// is likely what was intended.
+    pub DROPPING_REFERENCES,
+    Warn,
+    "calls to `std::mem::drop` with a reference instead of an owned value"
+}
+
+declare_lint! {
+    /// The `forgetting_references` lint checks for calls to `std::mem::forget` with a reference
+    /// instead of an owned value.
+    ///
+    /// ### Example
+    ///
+    /// ```rust
+    /// let x = Box::new(1);
+    /// std::mem::forget(&x); // Should have been forget(x), x will still be dropped
+    /// ```
+    ///
+    /// {{produces}}
+    ///
+    /// ### Explanation
+    ///
+    /// Calling `forget` on a reference will only forget the
+    /// reference itself, which is a no-op. It will not forget the underlying
+    /// referenced value, which is likely what was intended.
+    pub FORGETTING_REFERENCES,
+    Warn,
+    "calls to `std::mem::forget` with a reference instead of an owned value"
+}
+
+declare_lint! {
+    /// The `dropping_copy_types` lint checks for calls to `std::mem::drop` with a value
+    /// that derives the Copy trait.
+    ///
+    /// ### Example
+    ///
+    /// ```rust
+    /// let x: i32 = 42; // i32 implements Copy
+    /// std::mem::drop(x); // A copy of x is passed to the function, leaving the
+    ///                    // original unaffected
+    /// ```
+    ///
+    /// {{produces}}
+    ///
+    /// ### Explanation
+    ///
+    /// Calling `std::mem::drop` [does nothing for types that
+    /// implement Copy](https://doc.rust-lang.org/std/mem/fn.drop.html), since the
+    /// value will be copied and moved into the function on invocation.
+    pub DROPPING_COPY_TYPES,
+    Warn,
+    "calls to `std::mem::drop` with a value that implements Copy"
+}
+
+declare_lint! {
+    /// The `forgetting_copy_types` lint checks for calls to `std::mem::forget` with a value
+    /// that derives the Copy trait.
+    ///
+    /// ### Example
+    ///
+    /// ```rust
+    /// let x: i32 = 42; // i32 implements Copy
+    /// std::mem::forget(x); // A copy of x is passed to the function, leaving the
+    ///                      // original unaffected
+    /// ```
+    ///
+    /// {{produces}}
+    ///
+    /// ### Explanation
+    ///
+    /// Calling `std::mem::forget` [does nothing for types that
+    /// implement Copy](https://doc.rust-lang.org/std/mem/fn.drop.html) since the
+    /// value will be copied and moved into the function on invocation.
+    ///
+    /// An alternative, but also valid, explanation is that Copy types do not
+    /// implement the Drop trait, which means they have no destructors. Without a
+    /// destructor, there is nothing for `std::mem::forget` to ignore.
+    pub FORGETTING_COPY_TYPES,
+    Warn,
+    "calls to `std::mem::forget` with a value that implements Copy"
+}
+
+declare_lint_pass!(DropForgetUseless => [DROPPING_REFERENCES, FORGETTING_REFERENCES, DROPPING_COPY_TYPES, FORGETTING_COPY_TYPES]);
+
+impl<'tcx> LateLintPass<'tcx> for DropForgetUseless {
+    fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
+        if let ExprKind::Call(path, [arg]) = expr.kind
+            && let ExprKind::Path(ref qpath) = path.kind
+            && let Some(def_id) = cx.qpath_res(qpath, path.hir_id).opt_def_id()
+            && let Some(fn_name) = cx.tcx.get_diagnostic_name(def_id)
+        {
+            let arg_ty = cx.typeck_results().expr_ty(arg);
+            let is_copy = arg_ty.is_copy_modulo_regions(cx.tcx, cx.param_env);
+            let drop_is_single_call_in_arm = is_single_call_in_arm(cx, arg, expr);
+            match fn_name {
+                sym::mem_drop if arg_ty.is_ref() && !drop_is_single_call_in_arm => {
+                    cx.emit_spanned_lint(DROPPING_REFERENCES, expr.span, DropRefDiag { arg_ty, label: arg.span });
+                },
+                sym::mem_forget if arg_ty.is_ref() => {
+                    cx.emit_spanned_lint(FORGETTING_REFERENCES, expr.span, ForgetRefDiag { arg_ty, label: arg.span });
+                },
+                sym::mem_drop if is_copy && !drop_is_single_call_in_arm => {
+                    cx.emit_spanned_lint(DROPPING_COPY_TYPES, expr.span, DropCopyDiag { arg_ty, label: arg.span });
+                }
+                sym::mem_forget if is_copy => {
+                    cx.emit_spanned_lint(FORGETTING_COPY_TYPES, expr.span, ForgetCopyDiag { arg_ty, label: arg.span });
+                }
+                _ => return,
+            };
+        }
+    }
+}
+
+// Dropping returned value of a function, as in the following snippet is considered idiomatic, see
+// rust-lang/rust-clippy#9482 for examples.
+//
+// ```
+// match <var> {
+//     <pat> => drop(fn_with_side_effect_and_returning_some_value()),
+//     ..
+// }
+// ```
+fn is_single_call_in_arm<'tcx>(
+    cx: &LateContext<'tcx>,
+    arg: &'tcx Expr<'_>,
+    drop_expr: &'tcx Expr<'_>,
+) -> bool {
+    if matches!(arg.kind, ExprKind::Call(..) | ExprKind::MethodCall(..)) {
+        let parent_node = cx.tcx.hir().find_parent(drop_expr.hir_id);
+        if let Some(Node::Arm(Arm { body, .. })) = &parent_node {
+            return body.hir_id == drop_expr.hir_id;
+        }
+    }
+    false
+}
diff --git a/compiler/rustc_lint/src/expect.rs b/compiler/rustc_lint/src/expect.rs
index e9eb14ea188..b1266b58a61 100644
--- a/compiler/rustc_lint/src/expect.rs
+++ b/compiler/rustc_lint/src/expect.rs
@@ -1,5 +1,5 @@
 use crate::lints::{Expectation, ExpectationNote};
-use rustc_middle::ty::query::Providers;
+use rustc_middle::query::Providers;
 use rustc_middle::ty::TyCtxt;
 use rustc_session::lint::builtin::UNFULFILLED_LINT_EXPECTATIONS;
 use rustc_session::lint::LintExpectationId;
diff --git a/compiler/rustc_lint/src/late.rs b/compiler/rustc_lint/src/late.rs
index b42878a02ee..c9781a72704 100644
--- a/compiler/rustc_lint/src/late.rs
+++ b/compiler/rustc_lint/src/late.rs
@@ -16,7 +16,7 @@
 
 use crate::{passes::LateLintPassObject, LateContext, LateLintPass, LintStore};
 use rustc_ast as ast;
-use rustc_data_structures::sync::join;
+use rustc_data_structures::sync::{join, DynSend};
 use rustc_hir as hir;
 use rustc_hir::def_id::LocalDefId;
 use rustc_hir::intravisit as hir_visit;
@@ -429,7 +429,7 @@ fn late_lint_crate_inner<'tcx, T: LateLintPass<'tcx>>(
 /// Performs lint checking on a crate.
 pub fn check_crate<'tcx, T: LateLintPass<'tcx> + 'tcx>(
     tcx: TyCtxt<'tcx>,
-    builtin_lints: impl FnOnce() -> T + Send,
+    builtin_lints: impl FnOnce() -> T + Send + DynSend,
 ) {
     join(
         || {
diff --git a/compiler/rustc_lint/src/levels.rs b/compiler/rustc_lint/src/levels.rs
index a43c09a7939..b92ed11f38a 100644
--- a/compiler/rustc_lint/src/levels.rs
+++ b/compiler/rustc_lint/src/levels.rs
@@ -20,7 +20,7 @@ use rustc_middle::lint::{
     reveal_actual_level, struct_lint_level, LevelAndSource, LintExpectation, LintLevelSource,
     ShallowLintLevelMap,
 };
-use rustc_middle::ty::query::Providers;
+use rustc_middle::query::Providers;
 use rustc_middle::ty::{RegisteredTools, TyCtxt};
 use rustc_session::lint::builtin::{RENAMED_AND_REMOVED_LINTS, UNKNOWN_LINTS, UNUSED_ATTRIBUTES};
 use rustc_session::lint::{
diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs
index 319eb2ea445..dfddfe09ab3 100644
--- a/compiler/rustc_lint/src/lib.rs
+++ b/compiler/rustc_lint/src/lib.rs
@@ -52,6 +52,7 @@ mod array_into_iter;
 pub mod builtin;
 mod context;
 mod deref_into_dyn_supertrait;
+mod drop_forget_useless;
 mod early;
 mod enum_intrinsics_non_enums;
 mod errors;
@@ -85,7 +86,7 @@ use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage};
 use rustc_fluent_macro::fluent_messages;
 use rustc_hir as hir;
 use rustc_hir::def_id::LocalDefId;
-use rustc_middle::ty::query::Providers;
+use rustc_middle::query::Providers;
 use rustc_middle::ty::TyCtxt;
 use rustc_session::lint::builtin::{
     BARE_TRAIT_OBJECTS, ELIDED_LIFETIMES_IN_PATHS, EXPLICIT_OUTLIVES_REQUIREMENTS,
@@ -96,6 +97,7 @@ use rustc_span::Span;
 use array_into_iter::ArrayIntoIter;
 use builtin::*;
 use deref_into_dyn_supertrait::*;
+use drop_forget_useless::*;
 use enum_intrinsics_non_enums::EnumIntrinsicsNonEnums;
 use for_loops_over_fallibles::*;
 use hidden_unicode_codepoints::*;
@@ -201,6 +203,7 @@ late_lint_methods!(
         [
             ForLoopsOverFallibles: ForLoopsOverFallibles,
             DerefIntoDynSupertrait: DerefIntoDynSupertrait,
+            DropForgetUseless: DropForgetUseless,
             HardwiredLints: HardwiredLints,
             ImproperCTypesDeclarations: ImproperCTypesDeclarations,
             ImproperCTypesDefinitions: ImproperCTypesDefinitions,
diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs
index d7bacc6485f..de1c2be2875 100644
--- a/compiler/rustc_lint/src/lints.rs
+++ b/compiler/rustc_lint/src/lints.rs
@@ -662,6 +662,43 @@ pub struct ForLoopsOverFalliblesSuggestion<'a> {
     pub end_span: Span,
 }
 
+// drop_forget_useless.rs
+#[derive(LintDiagnostic)]
+#[diag(lint_dropping_references)]
+#[note]
+pub struct DropRefDiag<'a> {
+    pub arg_ty: Ty<'a>,
+    #[label]
+    pub label: Span,
+}
+
+#[derive(LintDiagnostic)]
+#[diag(lint_dropping_copy_types)]
+#[note]
+pub struct DropCopyDiag<'a> {
+    pub arg_ty: Ty<'a>,
+    #[label]
+    pub label: Span,
+}
+
+#[derive(LintDiagnostic)]
+#[diag(lint_forgetting_references)]
+#[note]
+pub struct ForgetRefDiag<'a> {
+    pub arg_ty: Ty<'a>,
+    #[label]
+    pub label: Span,
+}
+
+#[derive(LintDiagnostic)]
+#[diag(lint_forgetting_copy_types)]
+#[note]
+pub struct ForgetCopyDiag<'a> {
+    pub arg_ty: Ty<'a>,
+    #[label]
+    pub label: Span,
+}
+
 // hidden_unicode_codepoints.rs
 #[derive(LintDiagnostic)]
 #[diag(lint_hidden_unicode_codepoints)]
diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs
index eb175e96997..0fe140e08d2 100644
--- a/compiler/rustc_lint/src/unused.rs
+++ b/compiler/rustc_lint/src/unused.rs
@@ -103,8 +103,10 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
             && let ty = cx.typeck_results().expr_ty(&await_expr)
             && let ty::Alias(ty::Opaque, ty::AliasTy { def_id: future_def_id, .. }) = ty.kind()
             && cx.tcx.ty_is_opaque_future(ty)
-            // FIXME: This also includes non-async fns that return `impl Future`.
             && let async_fn_def_id = cx.tcx.parent(*future_def_id)
+            && matches!(cx.tcx.def_kind(async_fn_def_id), DefKind::Fn | DefKind::AssocFn)
+            // Check that this `impl Future` actually comes from an `async fn`
+            && cx.tcx.asyncness(async_fn_def_id).is_async()
             && check_must_use_def(
                 cx,
                 async_fn_def_id,
diff --git a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
index 5ec3b95225d..c43a0272477 100644
--- a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
+++ b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
@@ -745,6 +745,9 @@ LLVMRustOptimize(
         if (InstrProfileOutput) {
           Options.InstrProfileOutput = InstrProfileOutput;
         }
+        // cargo run tests in multhreading mode by default
+        // so use atomics for coverage counters
+        Options.Atomic = true;
         MPM.addPass(InstrProfiling(Options, false));
       }
     );
@@ -1460,63 +1463,6 @@ LLVMRustGetBitcodeSliceFromObjectData(const char *data,
   return BitcodeOrError->getBufferStart();
 }
 
-// Rewrite all `DICompileUnit` pointers to the `DICompileUnit` specified. See
-// the comment in `back/lto.rs` for why this exists.
-extern "C" void
-LLVMRustThinLTOGetDICompileUnit(LLVMModuleRef Mod,
-                                DICompileUnit **A,
-                                DICompileUnit **B) {
-  Module *M = unwrap(Mod);
-  DICompileUnit **Cur = A;
-  DICompileUnit **Next = B;
-  for (DICompileUnit *CU : M->debug_compile_units()) {
-    *Cur = CU;
-    Cur = Next;
-    Next = nullptr;
-    if (Cur == nullptr)
-      break;
-  }
-}
-
-// Rewrite all `DICompileUnit` pointers to the `DICompileUnit` specified. See
-// the comment in `back/lto.rs` for why this exists.
-extern "C" void
-LLVMRustThinLTOPatchDICompileUnit(LLVMModuleRef Mod, DICompileUnit *Unit) {
-  Module *M = unwrap(Mod);
-
-  // If the original source module didn't have a `DICompileUnit` then try to
-  // merge all the existing compile units. If there aren't actually any though
-  // then there's not much for us to do so return.
-  if (Unit == nullptr) {
-    for (DICompileUnit *CU : M->debug_compile_units()) {
-      Unit = CU;
-      break;
-    }
-    if (Unit == nullptr)
-      return;
-  }
-
-  // Use LLVM's built-in `DebugInfoFinder` to find a bunch of debuginfo and
-  // process it recursively. Note that we used to specifically iterate over
-  // instructions to ensure we feed everything into it, but `processModule`
-  // started doing this the same way in LLVM 7 (commit d769eb36ab2b8).
-  DebugInfoFinder Finder;
-  Finder.processModule(*M);
-
-  // After we've found all our debuginfo, rewrite all subprograms to point to
-  // the same `DICompileUnit`.
-  for (auto &F : Finder.subprograms()) {
-    F->replaceUnit(Unit);
-  }
-
-  // Erase any other references to other `DICompileUnit` instances, the verifier
-  // will later ensure that we don't actually have any other stale references to
-  // worry about.
-  auto *MD = M->getNamedMetadata("llvm.dbg.cu");
-  MD->clearOperands();
-  MD->addOperand(Unit);
-}
-
 // Computes the LTO cache key for the provided 'ModId' in the given 'Data',
 // storing the result in 'KeyOut'.
 // Currently, this cache key is a SHA-1 hash of anything that could affect
diff --git a/compiler/rustc_macros/src/query.rs b/compiler/rustc_macros/src/query.rs
index a8b25ff66d7..d0d41c614d6 100644
--- a/compiler/rustc_macros/src/query.rs
+++ b/compiler/rustc_macros/src/query.rs
@@ -253,7 +253,7 @@ fn add_query_desc_cached_impl(
         quote! {
             #[allow(unused_variables, unused_braces, rustc::pass_by_value)]
             #[inline]
-            pub fn #name<'tcx>(#tcx: TyCtxt<'tcx>, #key: &crate::ty::query::query_keys::#name<'tcx>) -> bool {
+            pub fn #name<'tcx>(#tcx: TyCtxt<'tcx>, #key: &crate::query::queries::#name::Key<'tcx>) -> bool {
                 #expr
             }
         }
@@ -262,7 +262,7 @@ fn add_query_desc_cached_impl(
             // we're taking `key` by reference, but some rustc types usually prefer being passed by value
             #[allow(rustc::pass_by_value)]
             #[inline]
-            pub fn #name<'tcx>(_: TyCtxt<'tcx>, _: &crate::ty::query::query_keys::#name<'tcx>) -> bool {
+            pub fn #name<'tcx>(_: TyCtxt<'tcx>, _: &crate::query::queries::#name::Key<'tcx>) -> bool {
                 false
             }
         }
@@ -273,7 +273,7 @@ fn add_query_desc_cached_impl(
 
     let desc = quote! {
         #[allow(unused_variables)]
-        pub fn #name<'tcx>(tcx: TyCtxt<'tcx>, key: crate::ty::query::query_keys::#name<'tcx>) -> String {
+        pub fn #name<'tcx>(tcx: TyCtxt<'tcx>, key: crate::query::queries::#name::Key<'tcx>) -> String {
             let (#tcx, #key) = (tcx, key);
             ::rustc_middle::ty::print::with_no_trimmed_paths!(
                 format!(#desc)
diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs
index e6e7d25773e..98ea9dc7501 100644
--- a/compiler/rustc_metadata/src/creader.rs
+++ b/compiler/rustc_metadata/src/creader.rs
@@ -943,7 +943,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
                     lint::builtin::UNUSED_CRATE_DEPENDENCIES,
                     span,
                     ast::CRATE_NODE_ID,
-                    &format!(
+                    format!(
                         "external crate `{}` unused in `{}`: remove the dependency or add `use {} as _;`",
                         name,
                         self.tcx.crate_name(LOCAL_CRATE),
diff --git a/compiler/rustc_metadata/src/locator.rs b/compiler/rustc_metadata/src/locator.rs
index c6af8d63289..6ec691f73b7 100644
--- a/compiler/rustc_metadata/src/locator.rs
+++ b/compiler/rustc_metadata/src/locator.rs
@@ -220,7 +220,6 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_data_structures::memmap::Mmap;
 use rustc_data_structures::owned_slice::slice_owned;
 use rustc_data_structures::svh::Svh;
-use rustc_data_structures::sync::MetadataRef;
 use rustc_errors::{DiagnosticArgValue, FatalError, IntoDiagnosticArg};
 use rustc_fs_util::try_canonicalize;
 use rustc_session::config::{self, CrateType};
@@ -246,6 +245,7 @@ pub(crate) struct CrateLocator<'a> {
     only_needs_metadata: bool,
     sysroot: &'a Path,
     metadata_loader: &'a dyn MetadataLoader,
+    cfg_version: &'static str,
 
     // Immutable per-search configuration.
     crate_name: Symbol,
@@ -323,6 +323,7 @@ impl<'a> CrateLocator<'a> {
             only_needs_metadata,
             sysroot: &sess.sysroot,
             metadata_loader,
+            cfg_version: sess.cfg_version,
             crate_name,
             exact_paths: if hash.is_none() {
                 sess.opts
@@ -655,7 +656,7 @@ impl<'a> CrateLocator<'a> {
     }
 
     fn crate_matches(&mut self, metadata: &MetadataBlob, libpath: &Path) -> Option<Svh> {
-        let rustc_version = rustc_version();
+        let rustc_version = rustc_version(self.cfg_version);
         let found_version = metadata.get_rustc_version();
         if found_version != rustc_version {
             info!("Rejecting via version: expected {} got {}", rustc_version, found_version);
@@ -782,7 +783,7 @@ fn get_metadata_section<'p>(
     if !filename.exists() {
         return Err(MetadataError::NotPresent(filename));
     }
-    let raw_bytes: MetadataRef = match flavor {
+    let raw_bytes = match flavor {
         CrateFlavor::Rlib => {
             loader.get_rlib_metadata(target, filename).map_err(MetadataError::LoadFailure)?
         }
@@ -843,7 +844,7 @@ fn get_metadata_section<'p>(
             slice_owned(mmap, Deref::deref)
         }
     };
-    let blob = MetadataBlob::new(raw_bytes);
+    let blob = MetadataBlob(raw_bytes);
     if blob.is_compatible() {
         Ok(blob)
     } else {
@@ -1097,7 +1098,7 @@ impl CrateError {
                         crate_name,
                         add_info,
                         found_crates,
-                        rustc_version: rustc_version(),
+                        rustc_version: rustc_version(sess.cfg_version),
                     });
                 } else if !locator.crate_rejections.via_invalid.is_empty() {
                     let mut crate_rejections = Vec::new();
diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs
index a310cbb8029..834e2453ee0 100644
--- a/compiler/rustc_metadata/src/rmeta/decoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/decoder.rs
@@ -7,6 +7,7 @@ use crate::rmeta::*;
 use rustc_ast as ast;
 use rustc_data_structures::captures::Captures;
 use rustc_data_structures::fx::FxHashMap;
+use rustc_data_structures::owned_slice::OwnedSlice;
 use rustc_data_structures::svh::Svh;
 use rustc_data_structures::sync::{AppendOnlyVec, Lock, Lrc, OnceCell};
 use rustc_data_structures::unhash::UnhashMap;
@@ -18,6 +19,7 @@ use rustc_hir::definitions::{DefKey, DefPath, DefPathData, DefPathHash};
 use rustc_hir::diagnostic_items::DiagnosticItems;
 use rustc_index::{Idx, IndexVec};
 use rustc_middle::metadata::ModChild;
+use rustc_middle::middle::debugger_visualizer::DebuggerVisualizerFile;
 use rustc_middle::middle::exported_symbols::{ExportedSymbol, SymbolExportInfo};
 use rustc_middle::mir::interpret::{AllocDecodingSession, AllocDecodingState};
 use rustc_middle::ty::codec::TyDecoder;
@@ -50,7 +52,7 @@ mod cstore_impl;
 /// A `MetadataBlob` internally is just a reference counted pointer to
 /// the actual data, so cloning it is cheap.
 #[derive(Clone)]
-pub(crate) struct MetadataBlob(Lrc<MetadataRef>);
+pub(crate) struct MetadataBlob(pub(crate) OwnedSlice);
 
 impl std::ops::Deref for MetadataBlob {
     type Target = [u8];
@@ -660,10 +662,6 @@ impl<'a, 'tcx, I: Idx, T> Decodable<DecodeContext<'a, 'tcx>> for LazyTable<I, T>
 implement_ty_decoder!(DecodeContext<'a, 'tcx>);
 
 impl MetadataBlob {
-    pub(crate) fn new(metadata_ref: MetadataRef) -> MetadataBlob {
-        MetadataBlob(Lrc::new(metadata_ref))
-    }
-
     pub(crate) fn is_compatible(&self) -> bool {
         self.blob().starts_with(METADATA_HEADER)
     }
@@ -856,7 +854,12 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
         ty::EarlyBinder(&*output)
     }
 
-    fn get_variant(self, kind: &DefKind, index: DefIndex, parent_did: DefId) -> ty::VariantDef {
+    fn get_variant(
+        self,
+        kind: DefKind,
+        index: DefIndex,
+        parent_did: DefId,
+    ) -> (VariantIdx, ty::VariantDef) {
         let adt_kind = match kind {
             DefKind::Variant => ty::AdtKind::Enum,
             DefKind::Struct => ty::AdtKind::Struct,
@@ -870,22 +873,25 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
             if adt_kind == ty::AdtKind::Enum { Some(self.local_def_id(index)) } else { None };
         let ctor = data.ctor.map(|(kind, index)| (kind, self.local_def_id(index)));
 
-        ty::VariantDef::new(
-            self.item_name(index),
-            variant_did,
-            ctor,
-            data.discr,
-            self.get_associated_item_or_field_def_ids(index)
-                .map(|did| ty::FieldDef {
-                    did,
-                    name: self.item_name(did.index),
-                    vis: self.get_visibility(did.index),
-                })
-                .collect(),
-            adt_kind,
-            parent_did,
-            false,
-            data.is_non_exhaustive,
+        (
+            data.idx,
+            ty::VariantDef::new(
+                self.item_name(index),
+                variant_did,
+                ctor,
+                data.discr,
+                self.get_associated_item_or_field_def_ids(index)
+                    .map(|did| ty::FieldDef {
+                        did,
+                        name: self.item_name(did.index),
+                        vis: self.get_visibility(did.index),
+                    })
+                    .collect(),
+                adt_kind,
+                parent_did,
+                false,
+                data.is_non_exhaustive,
+            ),
         )
     }
 
@@ -901,7 +907,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
         };
         let repr = self.root.tables.repr_options.get(self, item_id).unwrap().decode(self);
 
-        let variants = if let ty::AdtKind::Enum = adt_kind {
+        let mut variants: Vec<_> = if let ty::AdtKind::Enum = adt_kind {
             self.root
                 .tables
                 .module_children_non_reexports
@@ -912,15 +918,22 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
                     let kind = self.def_kind(index);
                     match kind {
                         DefKind::Ctor(..) => None,
-                        _ => Some(self.get_variant(&kind, index, did)),
+                        _ => Some(self.get_variant(kind, index, did)),
                     }
                 })
                 .collect()
         } else {
-            std::iter::once(self.get_variant(&kind, item_id, did)).collect()
+            std::iter::once(self.get_variant(kind, item_id, did)).collect()
         };
 
-        tcx.mk_adt_def(did, adt_kind, variants, repr)
+        variants.sort_by_key(|(idx, _)| *idx);
+
+        tcx.mk_adt_def(
+            did,
+            adt_kind,
+            variants.into_iter().map(|(_, variant)| variant).collect(),
+            repr,
+        )
     }
 
     fn get_visibility(self, id: DefIndex) -> Visibility<DefId> {
@@ -946,7 +959,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
             .decode((self, sess))
     }
 
-    fn get_debugger_visualizers(self) -> Vec<rustc_span::DebuggerVisualizerFile> {
+    fn get_debugger_visualizers(self) -> Vec<DebuggerVisualizerFile> {
         self.root.debugger_visualizers.decode(self).collect::<Vec<_>>()
     }
 
@@ -1239,14 +1252,6 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
         }
     }
 
-    fn is_foreign_item(self, id: DefIndex) -> bool {
-        if let Some(parent) = self.def_key(id).parent {
-            matches!(self.def_kind(parent), DefKind::ForeignMod)
-        } else {
-            false
-        }
-    }
-
     #[inline]
     fn def_key(self, index: DefIndex) -> DefKey {
         *self
@@ -1457,28 +1462,30 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
                     ..
                 } = source_file_to_import;
 
-                // If this file is under $sysroot/lib/rustlib/src/ but has not been remapped
-                // during rust bootstrapping by `remap-debuginfo = true`, and the user
-                // wish to simulate that behaviour by -Z simulate-remapped-rust-src-base,
+                // If this file is under $sysroot/lib/rustlib/src/
+                // and the user wish to simulate remapping with -Z simulate-remapped-rust-src-base,
                 // then we change `name` to a similar state as if the rust was bootstrapped
                 // with `remap-debuginfo = true`.
                 // This is useful for testing so that tests about the effects of
                 // `try_to_translate_virtual_to_real` don't have to worry about how the
                 // compiler is bootstrapped.
                 if let Some(virtual_dir) = &sess.opts.unstable_opts.simulate_remapped_rust_src_base
-                {
-                    if let Some(real_dir) = &sess.opts.real_rust_source_base_dir {
-                        for subdir in ["library", "compiler"] {
-                            if let rustc_span::FileName::Real(ref mut old_name) = name {
-                                if let rustc_span::RealFileName::LocalPath(local) = old_name {
-                                    if let Ok(rest) = local.strip_prefix(real_dir.join(subdir)) {
-                                        *old_name = rustc_span::RealFileName::Remapped {
-                                            local_path: None,
-                                            virtual_name: virtual_dir.join(subdir).join(rest),
-                                        };
-                                    }
-                                }
-                            }
+                && let Some(real_dir) = &sess.opts.real_rust_source_base_dir
+                && let rustc_span::FileName::Real(ref mut old_name) = name {
+                    let relative_path = match old_name {
+                        rustc_span::RealFileName::LocalPath(local) => local.strip_prefix(real_dir).ok(),
+                        rustc_span::RealFileName::Remapped { virtual_name, .. } => {
+                            option_env!("CFG_VIRTUAL_RUST_SOURCE_BASE_DIR").and_then(|virtual_dir| virtual_name.strip_prefix(virtual_dir).ok())
+                        }
+                    };
+                    debug!(?relative_path, ?virtual_dir, "simulate_remapped_rust_src_base");
+                    for subdir in ["library", "compiler"] {
+                        if let Some(rest) = relative_path.and_then(|p| p.strip_prefix(subdir).ok()) {
+                            *old_name = rustc_span::RealFileName::Remapped {
+                                local_path: None, // FIXME: maybe we should preserve this?
+                                virtual_name: virtual_dir.join(subdir).join(rest),
+                            };
+                            break;
                         }
                     }
                 }
diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
index 4a3b783c636..364269095e0 100644
--- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
+++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
@@ -14,8 +14,8 @@ use rustc_middle::metadata::ModChild;
 use rustc_middle::middle::exported_symbols::ExportedSymbol;
 use rustc_middle::middle::stability::DeprecationEntry;
 use rustc_middle::query::LocalCrate;
+use rustc_middle::query::{ExternProviders, Providers};
 use rustc_middle::ty::fast_reject::SimplifiedType;
-use rustc_middle::ty::query::{ExternProviders, Providers};
 use rustc_middle::ty::{self, TyCtxt};
 use rustc_session::cstore::CrateStore;
 use rustc_session::{Session, StableCrateId};
@@ -114,8 +114,8 @@ macro_rules! provide_one {
     ($tcx:ident, $def_id:ident, $other:ident, $cdata:ident, $name:ident => $compute:block) => {
         fn $name<'tcx>(
             $tcx: TyCtxt<'tcx>,
-            def_id_arg: ty::query::query_keys::$name<'tcx>,
-        ) -> ty::query::query_provided::$name<'tcx> {
+            def_id_arg: rustc_middle::query::queries::$name::Key<'tcx>,
+        ) -> rustc_middle::query::queries::$name::ProvidedValue<'tcx> {
             let _prof_timer =
                 $tcx.prof.generic_activity(concat!("metadata_decode_entry_", stringify!($name)));
 
@@ -280,7 +280,6 @@ provide! { tcx, def_id, other, cdata,
     }
     associated_item => { cdata.get_associated_item(def_id.index, tcx.sess) }
     inherent_impls => { cdata.get_inherent_implementations_for_type(tcx, def_id.index) }
-    is_foreign_item => { cdata.is_foreign_item(def_id.index) }
     item_attrs => { tcx.arena.alloc_from_iter(cdata.get_item_attrs(def_id.index, tcx.sess)) }
     is_mir_available => { cdata.is_item_mir_available(def_id.index) }
     is_ctfe_mir_available => { cdata.is_ctfe_mir_available(def_id.index) }
diff --git a/compiler/rustc_metadata/src/rmeta/def_path_hash_map.rs b/compiler/rustc_metadata/src/rmeta/def_path_hash_map.rs
index 05402a58701..4f280bb9d80 100644
--- a/compiler/rustc_metadata/src/rmeta/def_path_hash_map.rs
+++ b/compiler/rustc_metadata/src/rmeta/def_path_hash_map.rs
@@ -1,6 +1,5 @@
 use crate::rmeta::DecodeContext;
 use crate::rmeta::EncodeContext;
-use rustc_data_structures::owned_slice::slice_owned;
 use rustc_data_structures::owned_slice::OwnedSlice;
 use rustc_hir::def_path_hash_map::{Config as HashMapConfig, DefPathHashMap};
 use rustc_middle::parameterized_over_tcx;
@@ -47,7 +46,7 @@ impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for DefPathHashMapRef<'static>
     fn decode(d: &mut DecodeContext<'a, 'tcx>) -> DefPathHashMapRef<'static> {
         let len = d.read_usize();
         let pos = d.position();
-        let o = slice_owned(d.blob().clone(), |blob| &blob[pos..pos + len]);
+        let o = d.blob().clone().0.slice(|blob| &blob[pos..pos + len]);
 
         // Although we already have the data we need via the `OwnedSlice`, we still need
         // to advance the `DecodeContext`'s position so it's in a valid state after
diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs
index 29cf432b8f9..40723f41959 100644
--- a/compiler/rustc_metadata/src/rmeta/encoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/encoder.rs
@@ -8,7 +8,7 @@ use rustc_data_structures::fingerprint::Fingerprint;
 use rustc_data_structures::fx::{FxHashMap, FxIndexSet};
 use rustc_data_structures::memmap::{Mmap, MmapMut};
 use rustc_data_structures::stable_hasher::{Hash128, HashStable, StableHasher};
-use rustc_data_structures::sync::{join, par_iter, Lrc, ParallelIterator};
+use rustc_data_structures::sync::{join, par_for_each_in, Lrc};
 use rustc_data_structures::temp_dir::MaybeTempDir;
 use rustc_hir as hir;
 use rustc_hir::def::DefKind;
@@ -19,16 +19,17 @@ use rustc_hir::definitions::DefPathData;
 use rustc_hir::intravisit::{self, Visitor};
 use rustc_hir::lang_items::LangItem;
 use rustc_middle::hir::nested_filter;
+use rustc_middle::middle::debugger_visualizer::DebuggerVisualizerFile;
 use rustc_middle::middle::dependency_format::Linkage;
 use rustc_middle::middle::exported_symbols::{
     metadata_symbol_name, ExportedSymbol, SymbolExportInfo,
 };
 use rustc_middle::mir::interpret;
 use rustc_middle::query::LocalCrate;
+use rustc_middle::query::Providers;
 use rustc_middle::traits::specialization_graph;
 use rustc_middle::ty::codec::TyEncoder;
 use rustc_middle::ty::fast_reject::{self, SimplifiedType, TreatParams};
-use rustc_middle::ty::query::Providers;
 use rustc_middle::ty::{self, SymbolName, Ty, TyCtxt};
 use rustc_middle::util::common::to_readable_str;
 use rustc_serialize::{opaque, Decodable, Decoder, Encodable, Encoder};
@@ -36,9 +37,7 @@ use rustc_session::config::{CrateType, OptLevel};
 use rustc_session::cstore::{ForeignModule, LinkagePreference, NativeLib};
 use rustc_span::hygiene::{ExpnIndex, HygieneEncodeContext, MacroKind};
 use rustc_span::symbol::{sym, Symbol};
-use rustc_span::{
-    self, DebuggerVisualizerFile, ExternalSource, FileName, SourceFile, Span, SyntaxContext,
-};
+use rustc_span::{self, ExternalSource, FileName, SourceFile, Span, SyntaxContext};
 use std::borrow::Borrow;
 use std::collections::hash_map::Entry;
 use std::hash::Hash;
@@ -1375,9 +1374,10 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
             // Therefore, the loop over variants will encode its fields as the adt's children.
         }
 
-        for variant in adt_def.variants().iter() {
+        for (idx, variant) in adt_def.variants().iter_enumerated() {
             let data = VariantData {
                 discr: variant.discr,
+                idx,
                 ctor: variant.ctor.map(|(kind, def_id)| (kind, def_id.index)),
                 is_non_exhaustive: variant.is_field_list_non_exhaustive(),
             };
@@ -1515,8 +1515,11 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
             if encode_opt {
                 record!(self.tables.optimized_mir[def_id.to_def_id()] <- tcx.optimized_mir(def_id));
 
-                if tcx.sess.opts.unstable_opts.drop_tracking_mir && let DefKind::Generator = self.tcx.def_kind(def_id) {
-                    record!(self.tables.mir_generator_witnesses[def_id.to_def_id()] <- tcx.mir_generator_witnesses(def_id));
+                if tcx.sess.opts.unstable_opts.drop_tracking_mir
+                    && let DefKind::Generator = self.tcx.def_kind(def_id)
+                    && let Some(witnesses) = tcx.mir_generator_witnesses(def_id)
+                {
+                    record!(self.tables.mir_generator_witnesses[def_id.to_def_id()] <- witnesses);
                 }
             }
             if encode_const {
@@ -1641,9 +1644,10 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
             }
             hir::ItemKind::OpaqueTy(ref opaque) => {
                 self.encode_explicit_item_bounds(def_id);
-                self.tables
-                    .is_type_alias_impl_trait
-                    .set(def_id.index, matches!(opaque.origin, hir::OpaqueTyOrigin::TyAlias));
+                self.tables.is_type_alias_impl_trait.set(
+                    def_id.index,
+                    matches!(opaque.origin, hir::OpaqueTyOrigin::TyAlias { .. }),
+                );
             }
             hir::ItemKind::Impl(hir::Impl { defaultness, constness, .. }) => {
                 self.tables.impl_defaultness.set_some(def_id.index, *defaultness);
@@ -1850,7 +1854,16 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
 
     fn encode_debugger_visualizers(&mut self) -> LazyArray<DebuggerVisualizerFile> {
         empty_proc_macro!(self);
-        self.lazy_array(self.tcx.debugger_visualizers(LOCAL_CRATE).iter())
+        self.lazy_array(
+            self.tcx
+                .debugger_visualizers(LOCAL_CRATE)
+                .iter()
+                // Erase the path since it may contain privacy sensitive data
+                // that we don't want to end up in crate metadata.
+                // The path is only needed for the local crate because of
+                // `--emit dep-info`.
+                .map(DebuggerVisualizerFile::path_erased),
+        )
     }
 
     fn encode_crate_deps(&mut self) -> LazyArray<CrateDep> {
@@ -2129,7 +2142,7 @@ fn prefetch_mir(tcx: TyCtxt<'_>) {
         return;
     }
 
-    par_iter(tcx.mir_keys(())).for_each(|&def_id| {
+    par_for_each_in(tcx.mir_keys(()), |&def_id| {
         let (encode_const, encode_opt) = should_encode_mir(tcx, def_id);
 
         if encode_const {
@@ -2271,7 +2284,7 @@ fn encode_metadata_impl(tcx: TyCtxt<'_>, path: &Path) {
     };
 
     // Encode the rustc version string in a predictable location.
-    rustc_version().encode(&mut ecx);
+    rustc_version(tcx.sess.cfg_version).encode(&mut ecx);
 
     // Encode all the entries and extra information in the crate,
     // culminating in the `CrateRoot` which points to all of it.
diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs
index e2f6acb186b..97e67fcf8fd 100644
--- a/compiler/rustc_metadata/src/rmeta/mod.rs
+++ b/compiler/rustc_metadata/src/rmeta/mod.rs
@@ -2,12 +2,12 @@ use crate::creader::CrateMetadataRef;
 use decoder::Metadata;
 use def_path_hash_map::DefPathHashMapRef;
 use rustc_data_structures::fx::FxHashMap;
+use rustc_middle::middle::debugger_visualizer::DebuggerVisualizerFile;
 use table::TableBuilder;
 
 use rustc_ast as ast;
 use rustc_attr as attr;
 use rustc_data_structures::svh::Svh;
-use rustc_data_structures::sync::MetadataRef;
 use rustc_hir as hir;
 use rustc_hir::def::{CtorKind, DefKind, DocLinkResMap};
 use rustc_hir::def_id::{CrateNum, DefId, DefIndex, DefPathHash, StableCrateId};
@@ -20,8 +20,8 @@ use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs;
 use rustc_middle::middle::exported_symbols::{ExportedSymbol, SymbolExportInfo};
 use rustc_middle::middle::resolve_bound_vars::ObjectLifetimeDefault;
 use rustc_middle::mir;
+use rustc_middle::query::Providers;
 use rustc_middle::ty::fast_reject::SimplifiedType;
-use rustc_middle::ty::query::Providers;
 use rustc_middle::ty::{self, ReprOptions, Ty, UnusedGenericParams};
 use rustc_middle::ty::{DeducedParamAttrs, GeneratorDiagnosticData, ParameterizedOverTcx, TyCtxt};
 use rustc_serialize::opaque::FileEncoder;
@@ -31,6 +31,7 @@ use rustc_span::edition::Edition;
 use rustc_span::hygiene::{ExpnIndex, MacroKind};
 use rustc_span::symbol::{Ident, Symbol};
 use rustc_span::{self, ExpnData, ExpnHash, ExpnId, Span};
+use rustc_target::abi::VariantIdx;
 use rustc_target::spec::{PanicStrategy, TargetTriple};
 
 use std::marker::PhantomData;
@@ -48,8 +49,8 @@ mod def_path_hash_map;
 mod encoder;
 mod table;
 
-pub(crate) fn rustc_version() -> String {
-    format!("rustc {}", option_env!("CFG_VERSION").unwrap_or("unknown version"))
+pub(crate) fn rustc_version(cfg_version: &'static str) -> String {
+    format!("rustc {}", cfg_version)
 }
 
 /// Metadata encoding version.
@@ -245,7 +246,7 @@ pub(crate) struct CrateRoot {
     proc_macro_data: Option<ProcMacroData>,
 
     tables: LazyTables,
-    debugger_visualizers: LazyArray<rustc_span::DebuggerVisualizerFile>,
+    debugger_visualizers: LazyArray<DebuggerVisualizerFile>,
 
     exported_symbols: LazyArray<(ExportedSymbol<'static>, SymbolExportInfo)>,
 
@@ -430,6 +431,7 @@ define_tables! {
 
 #[derive(TyEncodable, TyDecodable)]
 struct VariantData {
+    idx: VariantIdx,
     discr: ty::VariantDiscr,
     /// If this is unit or tuple-variant/struct, then this is the index of the ctor id.
     ctor: Option<(CtorKind, DefIndex)>,
diff --git a/compiler/rustc_middle/Cargo.toml b/compiler/rustc_middle/Cargo.toml
index a7d97bd3cf5..7c56af1da41 100644
--- a/compiler/rustc_middle/Cargo.toml
+++ b/compiler/rustc_middle/Cargo.toml
@@ -11,6 +11,7 @@ chalk-ir = "0.87.0"
 derive_more = "0.99.17"
 either = "1.5.0"
 gsgdt = "0.1.2"
+field-offset = "0.3.5"
 measureme = "10.0.0"
 polonius-engine = "0.13.0"
 rustc_apfloat = { path = "../rustc_apfloat" }
diff --git a/compiler/rustc_middle/messages.ftl b/compiler/rustc_middle/messages.ftl
index c6bbf2ef0cd..64d511c261a 100644
--- a/compiler/rustc_middle/messages.ftl
+++ b/compiler/rustc_middle/messages.ftl
@@ -39,5 +39,7 @@ middle_strict_coherence_needs_negative_coherence =
     to use `strict_coherence` on this trait, the `with_negative_coherence` feature must be enabled
     .label = due to this attribute
 
+middle_requires_lang_item = requires `{$name}` lang_item
+
 middle_const_not_used_in_type_alias =
     const parameter `{$ct}` is part of concrete type but not used in parameter list for the `impl Trait` type alias
diff --git a/compiler/rustc_middle/src/error.rs b/compiler/rustc_middle/src/error.rs
index dc4aa18640f..046186d274c 100644
--- a/compiler/rustc_middle/src/error.rs
+++ b/compiler/rustc_middle/src/error.rs
@@ -1,5 +1,5 @@
 use rustc_macros::Diagnostic;
-use rustc_span::Span;
+use rustc_span::{Span, Symbol};
 
 use crate::ty::Ty;
 
@@ -74,6 +74,14 @@ pub(crate) struct StrictCoherenceNeedsNegativeCoherence {
 }
 
 #[derive(Diagnostic)]
+#[diag(middle_requires_lang_item)]
+pub(crate) struct RequiresLangItem {
+    #[primary_span]
+    pub span: Option<Span>,
+    pub name: Symbol,
+}
+
+#[derive(Diagnostic)]
 #[diag(middle_const_not_used_in_type_alias)]
 pub(super) struct ConstNotUsedTraitAlias {
     pub ct: String,
diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs
index 15d672c1408..3b59df778dc 100644
--- a/compiler/rustc_middle/src/hir/map/mod.rs
+++ b/compiler/rustc_middle/src/hir/map/mod.rs
@@ -1,11 +1,12 @@
 use crate::hir::{ModuleItems, Owner};
+use crate::middle::debugger_visualizer::DebuggerVisualizerFile;
 use crate::query::LocalCrate;
 use crate::ty::TyCtxt;
 use rustc_ast as ast;
 use rustc_data_structures::fingerprint::Fingerprint;
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc_data_structures::svh::Svh;
-use rustc_data_structures::sync::{par_for_each_in, Send, Sync};
+use rustc_data_structures::sync::{par_for_each_in, DynSend, DynSync};
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID, LOCAL_CRATE};
 use rustc_hir::definitions::{DefKey, DefPath, DefPathData, DefPathHash};
@@ -150,11 +151,6 @@ impl<'hir> Map<'hir> {
         self.tcx.hir_module_items(module).items()
     }
 
-    #[inline]
-    pub fn par_for_each_item(self, f: impl Fn(ItemId) + Sync + Send) {
-        par_for_each_in(&self.tcx.hir_crate_items(()).items[..], |id| f(*id));
-    }
-
     pub fn def_key(self, def_id: LocalDefId) -> DefKey {
         // Accessing the DefKey is ok, since it is part of DefPathHash.
         self.tcx.definitions_untracked().def_key(def_id)
@@ -502,7 +498,7 @@ impl<'hir> Map<'hir> {
     }
 
     #[inline]
-    pub fn par_body_owners(self, f: impl Fn(LocalDefId) + Sync + Send) {
+    pub fn par_body_owners(self, f: impl Fn(LocalDefId) + DynSend + DynSync) {
         par_for_each_in(&self.tcx.hir_crate_items(()).body_owners[..], |&def_id| f(def_id));
     }
 
@@ -640,7 +636,7 @@ impl<'hir> Map<'hir> {
     }
 
     #[inline]
-    pub fn par_for_each_module(self, f: impl Fn(LocalDefId) + Sync + Send) {
+    pub fn par_for_each_module(self, f: impl Fn(LocalDefId) + DynSend + DynSync) {
         let crate_items = self.tcx.hir_crate_items(());
         par_for_each_in(&crate_items.submodules[..], |module| f(module.def_id))
     }
@@ -1170,11 +1166,26 @@ pub(super) fn crate_hash(tcx: TyCtxt<'_>, _: LocalCrate) -> Svh {
 
     source_file_names.sort_unstable();
 
+    // We have to take care of debugger visualizers explicitly. The HIR (and
+    // thus `hir_body_hash`) contains the #[debugger_visualizer] attributes but
+    // these attributes only store the file path to the visualizer file, not
+    // their content. Yet that content is exported into crate metadata, so any
+    // changes to it need to be reflected in the crate hash.
+    let debugger_visualizers: Vec<_> = tcx
+        .debugger_visualizers(LOCAL_CRATE)
+        .iter()
+        // We ignore the path to the visualizer file since it's not going to be
+        // encoded in crate metadata and we already hash the full contents of
+        // the file.
+        .map(DebuggerVisualizerFile::path_erased)
+        .collect();
+
     let crate_hash: Fingerprint = tcx.with_stable_hashing_context(|mut hcx| {
         let mut stable_hasher = StableHasher::new();
         hir_body_hash.hash_stable(&mut hcx, &mut stable_hasher);
         upstream_crates.hash_stable(&mut hcx, &mut stable_hasher);
         source_file_names.hash_stable(&mut hcx, &mut stable_hasher);
+        debugger_visualizers.hash_stable(&mut hcx, &mut stable_hasher);
         if tcx.sess.opts.incremental_relative_spans() {
             let definitions = tcx.definitions_untracked();
             let mut owner_spans: Vec<_> = krate
diff --git a/compiler/rustc_middle/src/hir/mod.rs b/compiler/rustc_middle/src/hir/mod.rs
index 7770a5e4764..ac0b2844177 100644
--- a/compiler/rustc_middle/src/hir/mod.rs
+++ b/compiler/rustc_middle/src/hir/mod.rs
@@ -6,10 +6,11 @@ pub mod map;
 pub mod nested_filter;
 pub mod place;
 
-use crate::ty::query::Providers;
+use crate::query::Providers;
 use crate::ty::{EarlyBinder, ImplSubject, TyCtxt};
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
-use rustc_data_structures::sync::{par_for_each_in, Send, Sync};
+use rustc_data_structures::sync::{par_for_each_in, DynSend, DynSync};
+use rustc_hir::def::DefKind;
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_hir::*;
 use rustc_query_system::ich::StableHashingContext;
@@ -77,19 +78,19 @@ impl ModuleItems {
         self.owners().map(|id| id.def_id)
     }
 
-    pub fn par_items(&self, f: impl Fn(ItemId) + Send + Sync) {
+    pub fn par_items(&self, f: impl Fn(ItemId) + DynSend + DynSync) {
         par_for_each_in(&self.items[..], |&id| f(id))
     }
 
-    pub fn par_trait_items(&self, f: impl Fn(TraitItemId) + Send + Sync) {
+    pub fn par_trait_items(&self, f: impl Fn(TraitItemId) + DynSend + DynSync) {
         par_for_each_in(&self.trait_items[..], |&id| f(id))
     }
 
-    pub fn par_impl_items(&self, f: impl Fn(ImplItemId) + Send + Sync) {
+    pub fn par_impl_items(&self, f: impl Fn(ImplItemId) + DynSend + DynSync) {
         par_for_each_in(&self.impl_items[..], |&id| f(id))
     }
 
-    pub fn par_foreign_items(&self, f: impl Fn(ForeignItemId) + Send + Sync) {
+    pub fn par_foreign_items(&self, f: impl Fn(ForeignItemId) + DynSend + DynSync) {
         par_for_each_in(&self.foreign_items[..], |&id| f(id))
     }
 }
@@ -110,6 +111,12 @@ impl<'tcx> TyCtxt<'tcx> {
             None => self.type_of(def_id).map_bound(ImplSubject::Inherent),
         }
     }
+
+    /// Returns `true` if this is a foreign item (i.e., linked via `extern { ... }`).
+    pub fn is_foreign_item(self, def_id: impl Into<DefId>) -> bool {
+        self.opt_parent(def_id.into())
+            .map_or(false, |parent| matches!(self.def_kind(parent), DefKind::ForeignMod))
+    }
 }
 
 pub fn provide(providers: &mut Providers) {
diff --git a/compiler/rustc_middle/src/infer/canonical.rs b/compiler/rustc_middle/src/infer/canonical.rs
index c4e41e00520..56171314944 100644
--- a/compiler/rustc_middle/src/infer/canonical.rs
+++ b/compiler/rustc_middle/src/infer/canonical.rs
@@ -280,7 +280,7 @@ pub struct QueryResponse<'tcx, R> {
     /// should get its hidden type inferred. So we bubble the opaque type
     /// and the type it was compared against upwards and let the query caller
     /// handle it.
-    pub opaque_types: Vec<(Ty<'tcx>, Ty<'tcx>)>,
+    pub opaque_types: Vec<(ty::OpaqueTypeKey<'tcx>, Ty<'tcx>)>,
     pub value: R,
 }
 
diff --git a/compiler/rustc_middle/src/lib.rs b/compiler/rustc_middle/src/lib.rs
index e9172e767e0..22ee2a8c5e5 100644
--- a/compiler/rustc_middle/src/lib.rs
+++ b/compiler/rustc_middle/src/lib.rs
@@ -85,12 +85,7 @@ mod tests;
 mod macros;
 
 #[macro_use]
-pub mod query;
-
-#[macro_use]
 pub mod arena;
-#[macro_use]
-pub mod dep_graph;
 pub(crate) mod error;
 pub mod hir;
 pub mod infer;
@@ -104,6 +99,11 @@ pub mod ty;
 pub mod util;
 mod values;
 
+#[macro_use]
+pub mod query;
+#[macro_use]
+pub mod dep_graph;
+
 // Allows macros to refer to this crate as `::rustc_middle`
 extern crate self as rustc_middle;
 
diff --git a/compiler/rustc_middle/src/middle/debugger_visualizer.rs b/compiler/rustc_middle/src/middle/debugger_visualizer.rs
new file mode 100644
index 00000000000..a0497d805da
--- /dev/null
+++ b/compiler/rustc_middle/src/middle/debugger_visualizer.rs
@@ -0,0 +1,38 @@
+use rustc_data_structures::sync::Lrc;
+use std::path::PathBuf;
+
+#[derive(HashStable)]
+#[derive(Copy, PartialEq, PartialOrd, Clone, Ord, Eq, Hash, Debug, Encodable, Decodable)]
+pub enum DebuggerVisualizerType {
+    Natvis,
+    GdbPrettyPrinter,
+}
+
+/// A single debugger visualizer file.
+#[derive(HashStable)]
+#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord, Encodable, Decodable)]
+pub struct DebuggerVisualizerFile {
+    /// The complete debugger visualizer source.
+    pub src: Lrc<[u8]>,
+    /// Indicates which visualizer type this targets.
+    pub visualizer_type: DebuggerVisualizerType,
+    /// The file path to the visualizer file. This is used for reporting
+    /// visualizer files in dep-info. Before it is written to crate metadata,
+    /// the path is erased to `None`, so as not to emit potentially privacy
+    /// sensitive data.
+    pub path: Option<PathBuf>,
+}
+
+impl DebuggerVisualizerFile {
+    pub fn new(src: Lrc<[u8]>, visualizer_type: DebuggerVisualizerType, path: PathBuf) -> Self {
+        DebuggerVisualizerFile { src, visualizer_type, path: Some(path) }
+    }
+
+    pub fn path_erased(&self) -> Self {
+        DebuggerVisualizerFile {
+            src: self.src.clone(),
+            visualizer_type: self.visualizer_type,
+            path: None,
+        }
+    }
+}
diff --git a/compiler/rustc_middle/src/middle/lang_items.rs b/compiler/rustc_middle/src/middle/lang_items.rs
index 343ea1f00f5..9a633e04ce7 100644
--- a/compiler/rustc_middle/src/middle/lang_items.rs
+++ b/compiler/rustc_middle/src/middle/lang_items.rs
@@ -18,12 +18,8 @@ impl<'tcx> TyCtxt<'tcx> {
     /// Returns the `DefId` for a given `LangItem`.
     /// If not found, fatally aborts compilation.
     pub fn require_lang_item(self, lang_item: LangItem, span: Option<Span>) -> DefId {
-        self.lang_items().require(lang_item).unwrap_or_else(|err| {
-            if let Some(span) = span {
-                self.sess.span_fatal(span, err.to_string())
-            } else {
-                self.sess.fatal(err.to_string())
-            }
+        self.lang_items().get(lang_item).unwrap_or_else(|| {
+            self.sess.emit_fatal(crate::error::RequiresLangItem { span, name: lang_item.name() });
         })
     }
 
diff --git a/compiler/rustc_middle/src/middle/limits.rs b/compiler/rustc_middle/src/middle/limits.rs
index 12aef66bcf9..bd859d4d61b 100644
--- a/compiler/rustc_middle/src/middle/limits.rs
+++ b/compiler/rustc_middle/src/middle/limits.rs
@@ -11,7 +11,7 @@
 
 use crate::bug;
 use crate::error::LimitInvalid;
-use crate::ty;
+use crate::query::Providers;
 use rustc_ast::Attribute;
 use rustc_session::Session;
 use rustc_session::{Limit, Limits};
@@ -19,7 +19,7 @@ use rustc_span::symbol::{sym, Symbol};
 
 use std::num::IntErrorKind;
 
-pub fn provide(providers: &mut ty::query::Providers) {
+pub fn provide(providers: &mut Providers) {
     providers.limits = |tcx, ()| Limits {
         recursion_limit: get_recursion_limit(tcx.hir().krate_attrs(), tcx.sess),
         move_size_limit: get_limit(
diff --git a/compiler/rustc_middle/src/middle/mod.rs b/compiler/rustc_middle/src/middle/mod.rs
index 9c25f3009ba..85c5af9ca13 100644
--- a/compiler/rustc_middle/src/middle/mod.rs
+++ b/compiler/rustc_middle/src/middle/mod.rs
@@ -1,4 +1,5 @@
 pub mod codegen_fn_attrs;
+pub mod debugger_visualizer;
 pub mod dependency_format;
 pub mod exported_symbols;
 pub mod lang_items;
@@ -32,6 +33,6 @@ pub mod region;
 pub mod resolve_bound_vars;
 pub mod stability;
 
-pub fn provide(providers: &mut crate::ty::query::Providers) {
+pub fn provide(providers: &mut crate::query::Providers) {
     limits::provide(providers);
 }
diff --git a/compiler/rustc_middle/src/middle/privacy.rs b/compiler/rustc_middle/src/middle/privacy.rs
index 967fed687b6..aeb6a1601fc 100644
--- a/compiler/rustc_middle/src/middle/privacy.rs
+++ b/compiler/rustc_middle/src/middle/privacy.rs
@@ -64,7 +64,7 @@ impl EffectiveVisibility {
         self.at_level(level).is_public()
     }
 
-    pub fn from_vis(vis: Visibility) -> EffectiveVisibility {
+    pub const fn from_vis(vis: Visibility) -> EffectiveVisibility {
         EffectiveVisibility {
             direct: vis,
             reexported: vis,
@@ -72,6 +72,18 @@ impl EffectiveVisibility {
             reachable_through_impl_trait: vis,
         }
     }
+
+    #[must_use]
+    pub fn min(mut self, lhs: EffectiveVisibility, tcx: TyCtxt<'_>) -> Self {
+        for l in Level::all_levels() {
+            let rhs_vis = self.at_level_mut(l);
+            let lhs_vis = *lhs.at_level(l);
+            if rhs_vis.is_at_least(lhs_vis, tcx) {
+                *rhs_vis = lhs_vis;
+            };
+        }
+        self
+    }
 }
 
 /// Holds a map of effective visibilities for reachable HIR nodes.
@@ -137,24 +149,6 @@ impl EffectiveVisibilities {
         };
     }
 
-    pub fn set_public_at_level(
-        &mut self,
-        id: LocalDefId,
-        lazy_private_vis: impl FnOnce() -> Visibility,
-        level: Level,
-    ) {
-        let mut effective_vis = self
-            .effective_vis(id)
-            .copied()
-            .unwrap_or_else(|| EffectiveVisibility::from_vis(lazy_private_vis()));
-        for l in Level::all_levels() {
-            if l <= level {
-                *effective_vis.at_level_mut(l) = Visibility::Public;
-            }
-        }
-        self.map.insert(id, effective_vis);
-    }
-
     pub fn check_invariants(&self, tcx: TyCtxt<'_>, early: bool) {
         if !cfg!(debug_assertions) {
             return;
@@ -219,7 +213,7 @@ impl<Id: Eq + Hash> EffectiveVisibilities<Id> {
     pub fn update(
         &mut self,
         id: Id,
-        nominal_vis: Visibility,
+        nominal_vis: Option<Visibility>,
         lazy_private_vis: impl FnOnce() -> Visibility,
         inherited_effective_vis: EffectiveVisibility,
         level: Level,
@@ -243,12 +237,11 @@ impl<Id: Eq + Hash> EffectiveVisibilities<Id> {
                 if !(inherited_effective_vis_at_prev_level == inherited_effective_vis_at_level
                     && level != l)
                 {
-                    calculated_effective_vis =
-                        if nominal_vis.is_at_least(inherited_effective_vis_at_level, tcx) {
-                            inherited_effective_vis_at_level
-                        } else {
-                            nominal_vis
-                        };
+                    calculated_effective_vis = if let Some(nominal_vis) = nominal_vis && !nominal_vis.is_at_least(inherited_effective_vis_at_level, tcx) {
+                        nominal_vis
+                    } else {
+                        inherited_effective_vis_at_level
+                    }
                 }
                 // effective visibility can't be decreased at next update call for the
                 // same id
diff --git a/compiler/rustc_middle/src/mir/interpret/error.rs b/compiler/rustc_middle/src/mir/interpret/error.rs
index e45284ca506..055d8e9a352 100644
--- a/compiler/rustc_middle/src/mir/interpret/error.rs
+++ b/compiler/rustc_middle/src/mir/interpret/error.rs
@@ -1,7 +1,8 @@
 use super::{AllocId, AllocRange, ConstAlloc, Pointer, Scalar};
 
 use crate::mir::interpret::ConstValue;
-use crate::ty::{layout, query::TyCtxtAt, tls, Ty, ValTree};
+use crate::query::TyCtxtAt;
+use crate::ty::{layout, tls, Ty, ValTree};
 
 use rustc_data_structures::sync::Lock;
 use rustc_errors::{pluralize, struct_span_err, DiagnosticBuilder, ErrorGuaranteed};
@@ -15,15 +16,49 @@ use std::{any::Any, backtrace::Backtrace, fmt};
 pub enum ErrorHandled {
     /// Already reported an error for this evaluation, and the compilation is
     /// *guaranteed* to fail. Warnings/lints *must not* produce `Reported`.
-    Reported(ErrorGuaranteed),
+    Reported(ReportedErrorInfo),
     /// Don't emit an error, the evaluation failed because the MIR was generic
     /// and the substs didn't fully monomorphize it.
     TooGeneric,
 }
 
 impl From<ErrorGuaranteed> for ErrorHandled {
-    fn from(err: ErrorGuaranteed) -> ErrorHandled {
-        ErrorHandled::Reported(err)
+    #[inline]
+    fn from(error: ErrorGuaranteed) -> ErrorHandled {
+        ErrorHandled::Reported(error.into())
+    }
+}
+
+#[derive(Debug, Copy, Clone, PartialEq, Eq, HashStable, TyEncodable, TyDecodable)]
+pub struct ReportedErrorInfo {
+    error: ErrorGuaranteed,
+    is_tainted_by_errors: bool,
+}
+
+impl ReportedErrorInfo {
+    #[inline]
+    pub fn tainted_by_errors(error: ErrorGuaranteed) -> ReportedErrorInfo {
+        ReportedErrorInfo { is_tainted_by_errors: true, error }
+    }
+
+    /// Returns true if evaluation failed because MIR was tainted by errors.
+    #[inline]
+    pub fn is_tainted_by_errors(self) -> bool {
+        self.is_tainted_by_errors
+    }
+}
+
+impl From<ErrorGuaranteed> for ReportedErrorInfo {
+    #[inline]
+    fn from(error: ErrorGuaranteed) -> ReportedErrorInfo {
+        ReportedErrorInfo { is_tainted_by_errors: false, error }
+    }
+}
+
+impl Into<ErrorGuaranteed> for ReportedErrorInfo {
+    #[inline]
+    fn into(self) -> ErrorGuaranteed {
+        self.error
     }
 }
 
@@ -89,7 +124,7 @@ fn print_backtrace(backtrace: &Backtrace) {
 
 impl From<ErrorGuaranteed> for InterpErrorInfo<'_> {
     fn from(err: ErrorGuaranteed) -> Self {
-        InterpError::InvalidProgram(InvalidProgramInfo::AlreadyReported(err)).into()
+        InterpError::InvalidProgram(InvalidProgramInfo::AlreadyReported(err.into())).into()
     }
 }
 
@@ -125,7 +160,7 @@ pub enum InvalidProgramInfo<'tcx> {
     /// Resolution can fail if we are in a too generic context.
     TooGeneric,
     /// Abort in case errors are already reported.
-    AlreadyReported(ErrorGuaranteed),
+    AlreadyReported(ReportedErrorInfo),
     /// An error occurred during layout computation.
     Layout(layout::LayoutError<'tcx>),
     /// An error occurred during FnAbi computation: the passed --target lacks FFI support
@@ -144,7 +179,7 @@ impl fmt::Display for InvalidProgramInfo<'_> {
         use InvalidProgramInfo::*;
         match self {
             TooGeneric => write!(f, "encountered overly generic constant"),
-            AlreadyReported(ErrorGuaranteed { .. }) => {
+            AlreadyReported(_) => {
                 write!(
                     f,
                     "an error has already been reported elsewhere (this should not usually be printed)"
diff --git a/compiler/rustc_middle/src/mir/interpret/mod.rs b/compiler/rustc_middle/src/mir/interpret/mod.rs
index e5a9766c84d..3620385fab1 100644
--- a/compiler/rustc_middle/src/mir/interpret/mod.rs
+++ b/compiler/rustc_middle/src/mir/interpret/mod.rs
@@ -120,8 +120,8 @@ use crate::ty::{self, Instance, Ty, TyCtxt};
 pub use self::error::{
     struct_error, CheckInAllocMsg, ErrorHandled, EvalToAllocationRawResult, EvalToConstValueResult,
     EvalToValTreeResult, InterpError, InterpErrorInfo, InterpResult, InvalidProgramInfo,
-    MachineStopType, ResourceExhaustionInfo, ScalarSizeMismatch, UndefinedBehaviorInfo,
-    UninitBytesAccess, UnsupportedOpInfo,
+    MachineStopType, ReportedErrorInfo, ResourceExhaustionInfo, ScalarSizeMismatch,
+    UndefinedBehaviorInfo, UninitBytesAccess, UnsupportedOpInfo,
 };
 
 pub use self::value::{get_slice_bytes, ConstAlloc, ConstValue, Scalar};
diff --git a/compiler/rustc_middle/src/mir/interpret/queries.rs b/compiler/rustc_middle/src/mir/interpret/queries.rs
index ed4ee93e97d..f53dc8cb0ec 100644
--- a/compiler/rustc_middle/src/mir/interpret/queries.rs
+++ b/compiler/rustc_middle/src/mir/interpret/queries.rs
@@ -1,9 +1,10 @@
 use super::{ErrorHandled, EvalToConstValueResult, EvalToValTreeResult, GlobalId};
 
 use crate::mir;
+use crate::query::{TyCtxtAt, TyCtxtEnsure};
 use crate::ty::subst::InternalSubsts;
 use crate::ty::visit::TypeVisitableExt;
-use crate::ty::{self, query::TyCtxtAt, query::TyCtxtEnsure, TyCtxt};
+use crate::ty::{self, TyCtxt};
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::DefId;
 use rustc_session::lint;
@@ -61,7 +62,7 @@ impl<'tcx> TyCtxt<'tcx> {
                 self.const_eval_global_id(param_env, cid, span)
             }
             Ok(None) => Err(ErrorHandled::TooGeneric),
-            Err(error_reported) => Err(ErrorHandled::Reported(error_reported)),
+            Err(err) => Err(ErrorHandled::Reported(err.into())),
         }
     }
 
@@ -110,7 +111,7 @@ impl<'tcx> TyCtxt<'tcx> {
                 })
             }
             Ok(None) => Err(ErrorHandled::TooGeneric),
-            Err(error_reported) => Err(ErrorHandled::Reported(error_reported)),
+            Err(err) => Err(ErrorHandled::Reported(err.into())),
         }
     }
 
diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs
index 55991facd89..5c71910a955 100644
--- a/compiler/rustc_middle/src/mir/mod.rs
+++ b/compiler/rustc_middle/src/mir/mod.rs
@@ -101,7 +101,7 @@ impl<'tcx> HasLocalDecls<'tcx> for Body<'tcx> {
 /// pass will be named after the type, and it will consist of a main
 /// loop that goes over each available MIR and applies `run_pass`.
 pub trait MirPass<'tcx> {
-    fn name(&self) -> &str {
+    fn name(&self) -> &'static str {
         let name = std::any::type_name::<Self>();
         if let Some((_, tail)) = name.rsplit_once(':') { tail } else { name }
     }
@@ -1111,6 +1111,10 @@ pub struct VarDebugInfo<'tcx> {
     /// originated from (starting from 1). Note, if MIR inlining is enabled, then this is the
     /// argument number in the original function before it was inlined.
     pub argument_index: Option<u16>,
+
+    /// The data represents `name` dereferenced `references` times,
+    /// and not the direct value.
+    pub references: u8,
 }
 
 ///////////////////////////////////////////////////////////////////////////
@@ -1550,8 +1554,11 @@ impl<V, T> ProjectionElem<V, T> {
     /// Returns `true` if this is accepted inside `VarDebugInfoContents::Place`.
     pub fn can_use_in_debuginfo(&self) -> bool {
         match self {
-            Self::Deref | Self::Downcast(_, _) | Self::Field(_, _) => true,
-            Self::ConstantIndex { .. }
+            Self::ConstantIndex { from_end: false, .. }
+            | Self::Deref
+            | Self::Downcast(_, _)
+            | Self::Field(_, _) => true,
+            Self::ConstantIndex { from_end: true, .. }
             | Self::Index(_)
             | Self::OpaqueCast(_)
             | Self::Subslice { .. } => false,
@@ -1639,18 +1646,7 @@ impl<'tcx> Place<'tcx> {
             return self;
         }
 
-        let mut v: Vec<PlaceElem<'tcx>>;
-
-        let new_projections = if self.projection.is_empty() {
-            more_projections
-        } else {
-            v = Vec::with_capacity(self.projection.len() + more_projections.len());
-            v.extend(self.projection);
-            v.extend(more_projections);
-            &v
-        };
-
-        Place { local: self.local, projection: tcx.mk_place_elems(new_projections) }
+        self.as_ref().project_deeper(more_projections, tcx)
     }
 }
 
@@ -1721,6 +1717,27 @@ impl<'tcx> PlaceRef<'tcx> {
             (base, *proj)
         })
     }
+
+    /// Generates a new place by appending `more_projections` to the existing ones
+    /// and interning the result.
+    pub fn project_deeper(
+        self,
+        more_projections: &[PlaceElem<'tcx>],
+        tcx: TyCtxt<'tcx>,
+    ) -> Place<'tcx> {
+        let mut v: Vec<PlaceElem<'tcx>>;
+
+        let new_projections = if self.projection.is_empty() {
+            more_projections
+        } else {
+            v = Vec::with_capacity(self.projection.len() + more_projections.len());
+            v.extend(self.projection);
+            v.extend(more_projections);
+            &v
+        };
+
+        Place { local: self.local, projection: tcx.mk_place_elems(new_projections) }
+    }
 }
 
 impl Debug for Place<'_> {
@@ -2313,7 +2330,7 @@ impl<'tcx> ConstantKind<'tcx> {
                 if let Some(val) = c.kind().try_eval_for_mir(tcx, param_env) {
                     match val {
                         Ok(val) => Self::Val(val, c.ty()),
-                        Err(_) => Self::Ty(tcx.const_error(self.ty())),
+                        Err(guar) => Self::Ty(tcx.const_error(self.ty(), guar)),
                     }
                 } else {
                     self
@@ -2325,9 +2342,7 @@ impl<'tcx> ConstantKind<'tcx> {
                 match tcx.const_eval_resolve(param_env, uneval, None) {
                     Ok(val) => Self::Val(val, ty),
                     Err(ErrorHandled::TooGeneric) => self,
-                    Err(ErrorHandled::Reported(guar)) => {
-                        Self::Ty(tcx.const_error_with_guaranteed(ty, guar))
-                    }
+                    Err(ErrorHandled::Reported(guar)) => Self::Ty(tcx.const_error(ty, guar.into())),
                 }
             }
         }
diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs
index fa8a339631e..62c3d8cf239 100644
--- a/compiler/rustc_middle/src/mir/pretty.rs
+++ b/compiler/rustc_middle/src/mir/pretty.rs
@@ -551,8 +551,13 @@ fn write_scope_tree(
         }
 
         let indented_debug_info = format!(
-            "{0:1$}debug {2} => {3:?};",
-            INDENT, indent, var_debug_info.name, var_debug_info.value,
+            "{0:1$}debug {2} => {3:&<4$}{5:?};",
+            INDENT,
+            indent,
+            var_debug_info.name,
+            "",
+            var_debug_info.references as usize,
+            var_debug_info.value,
         );
 
         writeln!(
diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs
index 33b7fe0c2dc..21faf1958e9 100644
--- a/compiler/rustc_middle/src/mir/syntax.rs
+++ b/compiler/rustc_middle/src/mir/syntax.rs
@@ -749,6 +749,29 @@ pub enum TerminatorKind<'tcx> {
     },
 }
 
+impl TerminatorKind<'_> {
+    /// Returns a simple string representation of a `TerminatorKind` variant, independent of any
+    /// values it might hold (e.g. `TerminatorKind::Call` always returns `"Call"`).
+    pub const fn name(&self) -> &'static str {
+        match self {
+            TerminatorKind::Goto { .. } => "Goto",
+            TerminatorKind::SwitchInt { .. } => "SwitchInt",
+            TerminatorKind::Resume => "Resume",
+            TerminatorKind::Terminate => "Terminate",
+            TerminatorKind::Return => "Return",
+            TerminatorKind::Unreachable => "Unreachable",
+            TerminatorKind::Drop { .. } => "Drop",
+            TerminatorKind::Call { .. } => "Call",
+            TerminatorKind::Assert { .. } => "Assert",
+            TerminatorKind::Yield { .. } => "Yield",
+            TerminatorKind::GeneratorDrop => "GeneratorDrop",
+            TerminatorKind::FalseEdge { .. } => "FalseEdge",
+            TerminatorKind::FalseUnwind { .. } => "FalseUnwind",
+            TerminatorKind::InlineAsm { .. } => "InlineAsm",
+        }
+    }
+}
+
 /// Action to be taken when a stack unwind happens.
 #[derive(Copy, Clone, Debug, PartialEq, Eq, TyEncodable, TyDecodable, Hash, HashStable)]
 #[derive(TypeFoldable, TypeVisitable)]
diff --git a/compiler/rustc_middle/src/mir/visit.rs b/compiler/rustc_middle/src/mir/visit.rs
index 4b7014e3109..596dd80bf48 100644
--- a/compiler/rustc_middle/src/mir/visit.rs
+++ b/compiler/rustc_middle/src/mir/visit.rs
@@ -842,6 +842,7 @@ macro_rules! make_mir_visitor {
                     source_info,
                     value,
                     argument_index: _,
+                    references: _,
                 } = var_debug_info;
 
                 self.visit_source_info(source_info);
@@ -880,12 +881,11 @@ macro_rules! make_mir_visitor {
             ) {
                 let Constant {
                     span,
-                    user_ty,
+                    user_ty: _, // no visit method for this
                     literal,
                 } = constant;
 
                 self.visit_span($(& $mutability)? *span);
-                drop(user_ty); // no visit method for this
                 match literal {
                     ConstantKind::Ty(ct) => self.visit_ty_const($(&$mutability)? *ct, location),
                     ConstantKind::Val(_, ty) => self.visit_ty($(& $mutability)? *ty, TyContext::Location(location)),
diff --git a/compiler/rustc_middle/src/query/erase.rs b/compiler/rustc_middle/src/query/erase.rs
index 28a9c1eef1a..fd02a16130f 100644
--- a/compiler/rustc_middle/src/query/erase.rs
+++ b/compiler/rustc_middle/src/query/erase.rs
@@ -28,7 +28,7 @@ pub fn erase<T: EraseType>(src: T) -> Erase<T> {
     };
 
     Erased::<<T as EraseType>::Result> {
-        // SAFETY: Is it safe to transmute to MaybeUninit for types with the same sizes.
+        // SAFETY: It is safe to transmute to MaybeUninit for types with the same sizes.
         data: unsafe { transmute_copy(&src) },
     }
 }
@@ -172,6 +172,10 @@ impl EraseType for ty::Binder<'_, ty::FnSig<'_>> {
     type Result = [u8; size_of::<ty::Binder<'static, ty::FnSig<'static>>>()];
 }
 
+impl EraseType for ty::Binder<'_, &'_ ty::List<Ty<'_>>> {
+    type Result = [u8; size_of::<ty::Binder<'static, &'static ty::List<Ty<'static>>>>()];
+}
+
 impl<T0, T1> EraseType for (&'_ T0, &'_ T1) {
     type Result = [u8; size_of::<(&'static (), &'static ())>()];
 }
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index 9fad2816b0d..f5b42c80487 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -4,13 +4,95 @@
 //! ["Queries: demand-driven compilation"](https://rustc-dev-guide.rust-lang.org/query.html).
 //! This chapter includes instructions for adding new queries.
 
-use crate::ty::{self, print::describe_as_module, TyCtxt};
+#![allow(unused_parens)]
+
+use crate::dep_graph;
+use crate::dep_graph::DepKind;
+use crate::infer::canonical::{self, Canonical};
+use crate::lint::LintExpectation;
+use crate::metadata::ModChild;
+use crate::middle::codegen_fn_attrs::CodegenFnAttrs;
+use crate::middle::debugger_visualizer::DebuggerVisualizerFile;
+use crate::middle::exported_symbols::{ExportedSymbol, SymbolExportInfo};
+use crate::middle::lib_features::LibFeatures;
+use crate::middle::privacy::EffectiveVisibilities;
+use crate::middle::resolve_bound_vars::{ObjectLifetimeDefault, ResolveBoundVars, ResolvedArg};
+use crate::middle::stability::{self, DeprecationEntry};
+use crate::mir;
+use crate::mir::interpret::GlobalId;
+use crate::mir::interpret::{
+    ConstValue, EvalToAllocationRawResult, EvalToConstValueResult, EvalToValTreeResult,
+};
+use crate::mir::interpret::{LitToConstError, LitToConstInput};
+use crate::mir::mono::CodegenUnit;
+use crate::query::erase::{erase, restore, Erase};
+use crate::query::plumbing::{query_ensure, query_get_at, DynamicQuery};
+use crate::thir;
+use crate::traits::query::{
+    CanonicalPredicateGoal, CanonicalProjectionGoal, CanonicalTyGoal,
+    CanonicalTypeOpAscribeUserTypeGoal, CanonicalTypeOpEqGoal, CanonicalTypeOpNormalizeGoal,
+    CanonicalTypeOpProvePredicateGoal, CanonicalTypeOpSubtypeGoal, NoSolution,
+};
+use crate::traits::query::{
+    DropckConstraint, DropckOutlivesResult, MethodAutoderefStepsResult, NormalizationResult,
+    OutlivesBound,
+};
+use crate::traits::specialization_graph;
+use crate::traits::{self, ImplSource};
+use crate::ty::fast_reject::SimplifiedType;
+use crate::ty::layout::ValidityRequirement;
+use crate::ty::subst::{GenericArg, SubstsRef};
+use crate::ty::util::AlwaysRequiresDrop;
+use crate::ty::GeneratorDiagnosticData;
+use crate::ty::TyCtxtFeed;
+use crate::ty::{
+    self, print::describe_as_module, CrateInherentImpls, ParamEnvAnd, Ty, TyCtxt,
+    UnusedGenericParams,
+};
+use rustc_arena::TypedArena;
+use rustc_ast as ast;
+use rustc_ast::expand::allocator::AllocatorKind;
+use rustc_attr as attr;
+use rustc_data_structures::fingerprint::Fingerprint;
+use rustc_data_structures::fx::{FxHashMap, FxIndexMap, FxIndexSet};
+use rustc_data_structures::steal::Steal;
+use rustc_data_structures::svh::Svh;
+use rustc_data_structures::sync::Lrc;
+use rustc_data_structures::sync::WorkerLocal;
+use rustc_data_structures::unord::UnordSet;
+use rustc_errors::ErrorGuaranteed;
+use rustc_hir as hir;
+use rustc_hir::def::{DefKind, DocLinkResMap};
+use rustc_hir::def_id::{
+    CrateNum, DefId, DefIdMap, DefIdSet, LocalDefId, LocalDefIdMap, LocalDefIdSet,
+};
+use rustc_hir::lang_items::{LangItem, LanguageItems};
+use rustc_hir::{Crate, ItemLocalId, TraitCandidate};
+use rustc_index::IndexVec;
+use rustc_query_system::ich::StableHashingContext;
+use rustc_query_system::query::{try_get_cached, CacheSelector, QueryCache, QueryMode, QueryState};
+use rustc_session::config::{EntryFnType, OptLevel, OutputFilenames, SymbolManglingVersion};
+use rustc_session::cstore::{CrateDepKind, CrateSource};
+use rustc_session::cstore::{ExternCrate, ForeignModule, LinkagePreference, NativeLib};
+use rustc_session::lint::LintExpectationId;
+use rustc_session::Limits;
 use rustc_span::def_id::LOCAL_CRATE;
+use rustc_span::symbol::Symbol;
+use rustc_span::{Span, DUMMY_SP};
+use rustc_target::abi;
+use rustc_target::spec::PanicStrategy;
+use std::mem;
+use std::ops::Deref;
+use std::path::PathBuf;
+use std::sync::Arc;
 
 pub mod erase;
 mod keys;
-pub mod on_disk_cache;
 pub use keys::{AsLocalKey, Key, LocalCrate};
+pub mod on_disk_cache;
+#[macro_use]
+pub mod plumbing;
+pub use plumbing::{IntoQueryParam, TyCtxtAt, TyCtxtEnsure, TyCtxtEnsureWithValue};
 
 // Each of these queries corresponds to a function pointer field in the
 // `Providers` struct for requesting a value of that type, and a method
@@ -236,6 +318,15 @@ rustc_queries! {
         cache_on_disk_if { key.is_local() }
     }
 
+    query opaque_types_defined_by(
+        key: LocalDefId
+    ) -> &'tcx [LocalDefId] {
+        desc {
+            |tcx| "computing the opaque types defined by `{}`",
+            tcx.def_path_str(key.to_def_id())
+        }
+    }
+
     /// Returns the list of bounds that can be used for
     /// `SelectionCandidate::ProjectionCandidate(_)` and
     /// `ProjectionTyCandidate::TraitDef`.
@@ -437,7 +528,7 @@ rustc_queries! {
         }
     }
 
-    query mir_generator_witnesses(key: DefId) -> &'tcx mir::GeneratorLayout<'tcx> {
+    query mir_generator_witnesses(key: DefId) -> &'tcx Option<mir::GeneratorLayout<'tcx>> {
         arena_cache
         desc { |tcx| "generator witness types for `{}`", tcx.def_path_str(key) }
         cache_on_disk_if { key.is_local() }
@@ -636,12 +727,6 @@ rustc_queries! {
         desc { |tcx| "checking if item is promotable: `{}`", tcx.def_path_str(key) }
     }
 
-    /// Returns `true` if this is a foreign item (i.e., linked via `extern { ... }`).
-    query is_foreign_item(key: DefId) -> bool {
-        desc { |tcx| "checking if `{}` is a foreign item", tcx.def_path_str(key) }
-        separate_provide_extern
-    }
-
     /// Returns `Some(generator_kind)` if the node pointed to by `def_id` is a generator.
     query generator_kind(def_id: DefId) -> Option<hir::GeneratorKind> {
         desc { |tcx| "looking up generator kind of `{}`", tcx.def_path_str(def_id) }
@@ -1700,12 +1785,18 @@ rustc_queries! {
         desc { "looking at the source for a crate" }
         separate_provide_extern
     }
+
     /// Returns the debugger visualizers defined for this crate.
-    query debugger_visualizers(_: CrateNum) -> &'tcx Vec<rustc_span::DebuggerVisualizerFile> {
+    /// NOTE: This query has to be marked `eval_always` because it reads data
+    ///       directly from disk that is not tracked anywhere else. I.e. it
+    ///       represents a genuine input to the query system.
+    query debugger_visualizers(_: CrateNum) -> &'tcx Vec<DebuggerVisualizerFile> {
         arena_cache
         desc { "looking up the debugger visualizers for this crate" }
         separate_provide_extern
+        eval_always
     }
+
     query postorder_cnums(_: ()) -> &'tcx [CrateNum] {
         eval_always
         desc { "generating a postorder list of CrateNums" }
@@ -2093,3 +2184,6 @@ rustc_queries! {
         desc { "check whether two const param are definitely not equal to eachother"}
     }
 }
+
+rustc_query_append! { define_callbacks! }
+rustc_feedable_queries! { define_feedable! }
diff --git a/compiler/rustc_middle/src/ty/query.rs b/compiler/rustc_middle/src/query/plumbing.rs
index 07d47cae5ee..97edfc2fca2 100644
--- a/compiler/rustc_middle/src/ty/query.rs
+++ b/compiler/rustc_middle/src/query/plumbing.rs
@@ -1,89 +1,26 @@
-#![allow(unused_parens)]
-
 use crate::dep_graph;
 use crate::dep_graph::DepKind;
-use crate::infer::canonical::{self, Canonical};
-use crate::lint::LintExpectation;
-use crate::metadata::ModChild;
-use crate::middle::codegen_fn_attrs::CodegenFnAttrs;
-use crate::middle::exported_symbols::{ExportedSymbol, SymbolExportInfo};
-use crate::middle::lib_features::LibFeatures;
-use crate::middle::privacy::EffectiveVisibilities;
-use crate::middle::resolve_bound_vars::{ObjectLifetimeDefault, ResolveBoundVars, ResolvedArg};
-use crate::middle::stability::{self, DeprecationEntry};
-use crate::mir;
-use crate::mir::interpret::GlobalId;
-use crate::mir::interpret::{
-    ConstValue, EvalToAllocationRawResult, EvalToConstValueResult, EvalToValTreeResult,
-};
-use crate::mir::interpret::{LitToConstError, LitToConstInput};
-use crate::mir::mono::CodegenUnit;
-
-use crate::query::erase::{erase, restore, Erase};
 use crate::query::on_disk_cache::CacheEncoder;
 use crate::query::on_disk_cache::EncodedDepNodeIndex;
 use crate::query::on_disk_cache::OnDiskCache;
-use crate::query::{AsLocalKey, Key};
-use crate::thir;
-use crate::traits::query::{
-    CanonicalPredicateGoal, CanonicalProjectionGoal, CanonicalTyGoal,
-    CanonicalTypeOpAscribeUserTypeGoal, CanonicalTypeOpEqGoal, CanonicalTypeOpNormalizeGoal,
-    CanonicalTypeOpProvePredicateGoal, CanonicalTypeOpSubtypeGoal, NoSolution,
+use crate::query::{
+    DynamicQueries, ExternProviders, Providers, QueryArenas, QueryCaches, QueryEngine, QueryStates,
 };
-use crate::traits::query::{
-    DropckConstraint, DropckOutlivesResult, MethodAutoderefStepsResult, NormalizationResult,
-    OutlivesBound,
-};
-use crate::traits::specialization_graph;
-use crate::traits::{self, ImplSource};
-use crate::ty::context::TyCtxtFeed;
-use crate::ty::fast_reject::SimplifiedType;
-use crate::ty::layout::ValidityRequirement;
-use crate::ty::subst::{GenericArg, SubstsRef};
-use crate::ty::util::AlwaysRequiresDrop;
-use crate::ty::GeneratorDiagnosticData;
-use crate::ty::{self, CrateInherentImpls, ParamEnvAnd, Ty, TyCtxt, UnusedGenericParams};
+use crate::ty::TyCtxt;
+use field_offset::FieldOffset;
 use measureme::StringId;
-use rustc_arena::TypedArena;
-use rustc_ast as ast;
-use rustc_ast::expand::allocator::AllocatorKind;
-use rustc_attr as attr;
-use rustc_data_structures::fingerprint::Fingerprint;
-use rustc_data_structures::fx::{FxHashMap, FxIndexMap, FxIndexSet};
-use rustc_data_structures::steal::Steal;
-use rustc_data_structures::svh::Svh;
+use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::sync::AtomicU64;
-use rustc_data_structures::sync::Lrc;
-use rustc_data_structures::sync::WorkerLocal;
-use rustc_data_structures::unord::UnordSet;
-use rustc_errors::ErrorGuaranteed;
-use rustc_hir as hir;
-use rustc_hir::def::{DefKind, DocLinkResMap};
-use rustc_hir::def_id::{
-    CrateNum, DefId, DefIdMap, DefIdSet, LocalDefId, LocalDefIdMap, LocalDefIdSet,
-};
+use rustc_hir::def::DefKind;
+use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_hir::hir_id::OwnerId;
-use rustc_hir::lang_items::{LangItem, LanguageItems};
-use rustc_hir::{Crate, ItemLocalId, TraitCandidate};
-use rustc_index::IndexVec;
-use rustc_query_system::ich::StableHashingContext;
+use rustc_query_system::dep_graph::DepNodeIndex;
+use rustc_query_system::dep_graph::SerializedDepNodeIndex;
 pub(crate) use rustc_query_system::query::QueryJobId;
 use rustc_query_system::query::*;
-use rustc_session::config::{EntryFnType, OptLevel, OutputFilenames, SymbolManglingVersion};
-use rustc_session::cstore::{CrateDepKind, CrateSource};
-use rustc_session::cstore::{ExternCrate, ForeignModule, LinkagePreference, NativeLib};
-use rustc_session::lint::LintExpectationId;
-use rustc_session::Limits;
-use rustc_span::symbol::Symbol;
+use rustc_query_system::HandleCycleError;
 use rustc_span::{Span, DUMMY_SP};
-use rustc_target::abi;
-use rustc_target::spec::PanicStrategy;
-
-use std::marker::PhantomData;
-use std::mem;
 use std::ops::Deref;
-use std::path::PathBuf;
-use std::sync::Arc;
 
 pub struct QueryKeyStringCache {
     pub def_id_cache: FxHashMap<DefId, StringId>,
@@ -95,19 +32,34 @@ impl QueryKeyStringCache {
     }
 }
 
-#[derive(Clone, Copy)]
-pub struct QueryStruct<'tcx> {
-    pub try_collect_active_jobs: fn(TyCtxt<'tcx>, &mut QueryMap<DepKind>) -> Option<()>,
-    pub alloc_self_profile_query_strings: fn(TyCtxt<'tcx>, &mut QueryKeyStringCache),
-    pub encode_query_results:
-        Option<fn(TyCtxt<'tcx>, &mut CacheEncoder<'_, 'tcx>, &mut EncodedDepNodeIndex)>,
+pub struct DynamicQuery<'tcx, C: QueryCache> {
+    pub name: &'static str,
+    pub eval_always: bool,
+    pub dep_kind: DepKind,
+    pub handle_cycle_error: HandleCycleError,
+    pub query_state: FieldOffset<QueryStates<'tcx>, QueryState<C::Key, DepKind>>,
+    pub query_cache: FieldOffset<QueryCaches<'tcx>, C>,
+    pub cache_on_disk: fn(tcx: TyCtxt<'tcx>, key: &C::Key) -> bool,
+    pub execute_query: fn(tcx: TyCtxt<'tcx>, k: C::Key) -> C::Value,
+    pub compute: fn(tcx: TyCtxt<'tcx>, key: C::Key) -> C::Value,
+    pub can_load_from_disk: bool,
+    pub try_load_from_disk: fn(
+        tcx: TyCtxt<'tcx>,
+        key: &C::Key,
+        prev_index: SerializedDepNodeIndex,
+        index: DepNodeIndex,
+    ) -> Option<C::Value>,
+    pub loadable_from_disk:
+        fn(tcx: TyCtxt<'tcx>, key: &C::Key, index: SerializedDepNodeIndex) -> bool,
+    pub hash_result: HashResult<C::Value>,
+    pub value_from_cycle_error: fn(tcx: TyCtxt<'tcx>, cycle: &[QueryInfo<DepKind>]) -> C::Value,
+    pub format_value: fn(&C::Value) -> String,
 }
 
 pub struct QuerySystemFns<'tcx> {
     pub engine: QueryEngine,
     pub local_providers: Providers,
     pub extern_providers: ExternProviders,
-    pub query_structs: Vec<QueryStruct<'tcx>>,
     pub encode_query_results: fn(
         tcx: TyCtxt<'tcx>,
         encoder: &mut CacheEncoder<'_, 'tcx>,
@@ -120,6 +72,7 @@ pub struct QuerySystem<'tcx> {
     pub states: QueryStates<'tcx>,
     pub arenas: QueryArenas<'tcx>,
     pub caches: QueryCaches<'tcx>,
+    pub dynamic_queries: DynamicQueries<'tcx>,
 
     /// This provides access to the incremental compilation on-disk cache for query results.
     /// Do not access this directly. It is only meant to be used by
@@ -130,23 +83,6 @@ pub struct QuerySystem<'tcx> {
     pub fns: QuerySystemFns<'tcx>,
 
     pub jobs: AtomicU64,
-
-    // Since we erase query value types we tell the typesystem about them with `PhantomData`.
-    _phantom_values: QueryPhantomValues<'tcx>,
-}
-
-impl<'tcx> QuerySystem<'tcx> {
-    pub fn new(fns: QuerySystemFns<'tcx>, on_disk_cache: Option<OnDiskCache<'tcx>>) -> Self {
-        QuerySystem {
-            states: Default::default(),
-            arenas: Default::default(),
-            caches: Default::default(),
-            on_disk_cache,
-            fns,
-            jobs: AtomicU64::new(1),
-            _phantom_values: Default::default(),
-        }
-    }
 }
 
 #[derive(Copy, Clone)]
@@ -203,7 +139,7 @@ impl<'tcx> TyCtxt<'tcx> {
 }
 
 #[inline]
-fn query_get_at<'tcx, Cache>(
+pub fn query_get_at<'tcx, Cache>(
     tcx: TyCtxt<'tcx>,
     execute_query: fn(TyCtxt<'tcx>, Span, Cache::Key, QueryMode) -> Option<Cache::Value>,
     query_cache: &Cache,
@@ -221,7 +157,7 @@ where
 }
 
 #[inline]
-fn query_ensure<'tcx, Cache>(
+pub fn query_ensure<'tcx, Cache>(
     tcx: TyCtxt<'tcx>,
     execute_query: fn(TyCtxt<'tcx>, Span, Cache::Key, QueryMode) -> Option<Cache::Value>,
     query_cache: &Cache,
@@ -275,8 +211,8 @@ macro_rules! separate_provide_extern_decl {
     ([(separate_provide_extern) $($rest:tt)*][$name:ident]) => {
         for<'tcx> fn(
             TyCtxt<'tcx>,
-            query_keys::$name<'tcx>,
-        ) -> query_provided::$name<'tcx>
+            queries::$name::Key<'tcx>,
+        ) -> queries::$name::ProvidedValue<'tcx>
     };
     ([$other:tt $($modifiers:tt)*][$($args:tt)*]) => {
         separate_provide_extern_decl!([$($modifiers)*][$($args)*])
@@ -306,60 +242,37 @@ macro_rules! define_callbacks {
      $($(#[$attr:meta])*
         [$($modifiers:tt)*] fn $name:ident($($K:tt)*) -> $V:ty,)*) => {
 
-        // HACK(eddyb) this is like the `impl QueryConfig for queries::$name`
-        // below, but using type aliases instead of associated types, to bypass
-        // the limitations around normalizing under HRTB - for example, this:
-        // `for<'tcx> fn(...) -> <queries::$name<'tcx> as QueryConfig<TyCtxt<'tcx>>>::Value`
-        // doesn't currently normalize to `for<'tcx> fn(...) -> query_values::$name<'tcx>`.
-        // This is primarily used by the `provide!` macro in `rustc_metadata`.
-        #[allow(nonstandard_style, unused_lifetimes)]
-        pub mod query_keys {
-            use super::*;
-
-            $(pub type $name<'tcx> = $($K)*;)*
-        }
-        #[allow(nonstandard_style, unused_lifetimes)]
-        pub mod query_keys_local {
-            use super::*;
-
-            $(pub type $name<'tcx> = local_key_if_separate_extern!([$($modifiers)*] $($K)*);)*
-        }
-        #[allow(nonstandard_style, unused_lifetimes)]
-        pub mod query_values {
-            use super::*;
+        #[allow(unused_lifetimes)]
+        pub mod queries {
+            $(pub mod $name {
+                use super::super::*;
 
-            $(pub type $name<'tcx> = $V;)*
-        }
+                pub type Key<'tcx> = $($K)*;
+                pub type Value<'tcx> = $V;
 
-        /// This module specifies the type returned from query providers and the type used for
-        /// decoding. For regular queries this is the declared returned type `V`, but
-        /// `arena_cache` will use `<V as Deref>::Target` instead.
-        #[allow(nonstandard_style, unused_lifetimes)]
-        pub mod query_provided {
-            use super::*;
+                pub type LocalKey<'tcx> = local_key_if_separate_extern!([$($modifiers)*] $($K)*);
 
-            $(
-                pub type $name<'tcx> = query_if_arena!([$($modifiers)*] (<$V as Deref>::Target) ($V));
-            )*
-        }
-
-        /// This module has a function per query which takes a `query_provided` value and coverts
-        /// it to a regular `V` value by allocating it on an arena if the query has the
-        /// `arena_cache` modifier. This will happen when computing the query using a provider or
-        /// decoding a stored result.
-        #[allow(nonstandard_style, unused_lifetimes)]
-        pub mod query_provided_to_value {
-            use super::*;
+                /// This type alias specifies the type returned from query providers and the type
+                /// used for decoding. For regular queries this is the declared returned type `V`,
+                /// but `arena_cache` will use `<V as Deref>::Target` instead.
+                pub type ProvidedValue<'tcx> = query_if_arena!(
+                    [$($modifiers)*]
+                    (<$V as Deref>::Target)
+                    ($V)
+                );
 
-            $(
+                /// This function takes `ProvidedValue` and coverts it to an erased `Value` by
+                /// allocating it on an arena if the query has the `arena_cache` modifier. The
+                /// value is then erased and returned. This will happen when computing the query
+                /// using a provider or decoding a stored result.
                 #[inline(always)]
-                pub fn $name<'tcx>(
+                pub fn provided_to_erased<'tcx>(
                     _tcx: TyCtxt<'tcx>,
-                    value: query_provided::$name<'tcx>,
-                ) -> Erase<query_values::$name<'tcx>> {
+                    value: ProvidedValue<'tcx>,
+                ) -> Erase<Value<'tcx>> {
                     erase(query_if_arena!([$($modifiers)*]
                         {
-                            if mem::needs_drop::<query_provided::$name<'tcx>>() {
+                            if mem::needs_drop::<ProvidedValue<'tcx>>() {
                                 &*_tcx.query_system.arenas.$name.alloc(value)
                             } else {
                                 &*_tcx.arena.dropless.alloc(value)
@@ -368,47 +281,41 @@ macro_rules! define_callbacks {
                         (value)
                     ))
                 }
-            )*
-        }
-        #[allow(nonstandard_style, unused_lifetimes)]
-        pub mod query_storage {
-            use super::*;
 
-            $(
-                pub type $name<'tcx> = <<$($K)* as Key>::CacheSelector as CacheSelector<'tcx, Erase<$V>>>::Cache;
-            )*
+                pub type Storage<'tcx> = <
+                    <$($K)* as keys::Key>::CacheSelector as CacheSelector<'tcx, Erase<$V>>
+                >::Cache;
+
+                // Ensure that keys grow no larger than 64 bytes
+                #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
+                const _: () = {
+                    if mem::size_of::<Key<'static>>() > 64 {
+                        panic!("{}", concat!(
+                            "the query `",
+                            stringify!($name),
+                            "` has a key type `",
+                            stringify!($($K)*),
+                            "` that is too large"
+                        ));
+                    }
+                };
+
+                // Ensure that values grow no larger than 64 bytes
+                #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
+                const _: () = {
+                    if mem::size_of::<Value<'static>>() > 64 {
+                        panic!("{}", concat!(
+                            "the query `",
+                            stringify!($name),
+                            "` has a value type `",
+                            stringify!($V),
+                            "` that is too large"
+                        ));
+                    }
+                };
+            })*
         }
 
-        $(
-            // Ensure that keys grow no larger than 64 bytes
-            #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
-            const _: () = {
-                if mem::size_of::<query_keys::$name<'static>>() > 64 {
-                    panic!("{}", concat!(
-                        "the query `",
-                        stringify!($name),
-                        "` has a key type `",
-                        stringify!($($K)*),
-                        "` that is too large"
-                    ));
-                }
-            };
-
-            // Ensure that values grow no larger than 64 bytes
-            #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
-            const _: () = {
-                if mem::size_of::<query_values::$name<'static>>() > 64 {
-                    panic!("{}", concat!(
-                        "the query `",
-                        stringify!($name),
-                        "` has a value type `",
-                        stringify!($V),
-                        "` that is too large"
-                    ));
-                }
-            };
-        )*
-
         pub struct QueryArenas<'tcx> {
             $($(#[$attr])* pub $name: query_if_arena!([$($modifiers)*]
                 (WorkerLocal<TypedArena<<$V as Deref>::Target>>)
@@ -428,13 +335,8 @@ macro_rules! define_callbacks {
         }
 
         #[derive(Default)]
-        pub struct QueryPhantomValues<'tcx> {
-            $($(#[$attr])* pub $name: PhantomData<query_values::$name<'tcx>>,)*
-        }
-
-        #[derive(Default)]
         pub struct QueryCaches<'tcx> {
-            $($(#[$attr])* pub $name: query_storage::$name<'tcx>,)*
+            $($(#[$attr])* pub $name: queries::$name::Storage<'tcx>,)*
         }
 
         impl<'tcx> TyCtxtEnsure<'tcx> {
@@ -490,6 +392,12 @@ macro_rules! define_callbacks {
             })*
         }
 
+        pub struct DynamicQueries<'tcx> {
+            $(
+                pub $name: DynamicQuery<'tcx, queries::$name::Storage<'tcx>>,
+            )*
+        }
+
         #[derive(Default)]
         pub struct QueryStates<'tcx> {
             $(
@@ -500,8 +408,8 @@ macro_rules! define_callbacks {
         pub struct Providers {
             $(pub $name: for<'tcx> fn(
                 TyCtxt<'tcx>,
-                query_keys_local::$name<'tcx>,
-            ) -> query_provided::$name<'tcx>,)*
+                queries::$name::LocalKey<'tcx>,
+            ) -> queries::$name::ProvidedValue<'tcx>,)*
         }
 
         pub struct ExternProviders {
@@ -546,7 +454,7 @@ macro_rules! define_callbacks {
             $(pub $name: for<'tcx> fn(
                 TyCtxt<'tcx>,
                 Span,
-                query_keys::$name<'tcx>,
+                queries::$name::Key<'tcx>,
                 QueryMode,
             ) -> Option<Erase<$V>>,)*
         }
@@ -570,11 +478,11 @@ macro_rules! define_feedable {
         $(impl<'tcx, K: IntoQueryParam<$($K)*> + Copy> TyCtxtFeed<'tcx, K> {
             $(#[$attr])*
             #[inline(always)]
-            pub fn $name(self, value: query_provided::$name<'tcx>) {
+            pub fn $name(self, value: queries::$name::ProvidedValue<'tcx>) {
                 let key = self.key().into_query_param();
 
                 let tcx = self.tcx;
-                let erased = query_provided_to_value::$name(tcx, value);
+                let erased = queries::$name::provided_to_erased(tcx, value);
                 let value = restore::<$V>(erased);
                 let cache = &tcx.query_system.caches.$name;
 
@@ -586,12 +494,20 @@ macro_rules! define_feedable {
                             let (value_hash, old_hash): (Fingerprint, Fingerprint) = tcx.with_stable_hashing_context(|mut hcx|
                                 (hasher(&mut hcx, &value), hasher(&mut hcx, &old))
                             );
-                            assert_eq!(
-                                old_hash, value_hash,
-                                "Trying to feed an already recorded value for query {} key={key:?}:\nold value: {old:?}\nnew value: {value:?}",
-                                stringify!($name),
-                            )
+                            if old_hash != value_hash {
+                                // We have an inconsistency. This can happen if one of the two
+                                // results is tainted by errors. In this case, delay a bug to
+                                // ensure compilation is doomed, and keep the `old` value.
+                                tcx.sess.delay_span_bug(DUMMY_SP, format!(
+                                    "Trying to feed an already recorded value for query {} key={key:?}:\n\
+                                    old value: {old:?}\nnew value: {value:?}",
+                                    stringify!($name),
+                                ));
+                            }
                         } else {
+                            // The query is `no_hash`, so we have no way to perform a sanity check.
+                            // If feeding the same value multiple times needs to be supported,
+                            // the query should not be marked `no_hash`.
                             bug!(
                                 "Trying to feed an already recorded value for query {} key={key:?}:\nold value: {old:?}\nnew value: {value:?}",
                                 stringify!($name),
@@ -627,9 +543,6 @@ macro_rules! define_feedable {
 // Queries marked with `fatal_cycle` do not need the latter implementation,
 // as they will raise an fatal error on query cycles instead.
 
-rustc_query_append! { define_callbacks! }
-rustc_feedable_queries! { define_feedable! }
-
 mod sealed {
     use super::{DefId, LocalDefId, OwnerId};
 
diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs
index 449c453555e..5b0b40cbfd9 100644
--- a/compiler/rustc_middle/src/traits/mod.rs
+++ b/compiler/rustc_middle/src/traits/mod.rs
@@ -281,9 +281,6 @@ pub enum ObligationCauseCode<'tcx> {
     /// A type like `Box<Foo<'a> + 'b>` is WF only if `'b: 'a`.
     ObjectTypeBound(Ty<'tcx>, ty::Region<'tcx>),
 
-    /// Obligation incurred due to an object cast.
-    ObjectCastObligation(/* Concrete type */ Ty<'tcx>, /* Object type */ Ty<'tcx>),
-
     /// Obligation incurred due to a coercion.
     Coercion {
         source: Ty<'tcx>,
@@ -704,9 +701,9 @@ impl<'tcx, N> ImplSource<'tcx, N> {
     }
 
     pub fn borrow_nested_obligations(&self) -> &[N] {
-        match &self {
-            ImplSource::UserDefined(i) => &i.nested[..],
-            ImplSource::Param(n, _) => &n,
+        match self {
+            ImplSource::UserDefined(i) => &i.nested,
+            ImplSource::Param(n, _) => n,
             ImplSource::Builtin(i) => &i.nested,
             ImplSource::AutoImpl(d) => &d.nested,
             ImplSource::Closure(c) => &c.nested,
@@ -720,6 +717,23 @@ impl<'tcx, N> ImplSource<'tcx, N> {
         }
     }
 
+    pub fn borrow_nested_obligations_mut(&mut self) -> &mut [N] {
+        match self {
+            ImplSource::UserDefined(i) => &mut i.nested,
+            ImplSource::Param(n, _) => n,
+            ImplSource::Builtin(i) => &mut i.nested,
+            ImplSource::AutoImpl(d) => &mut d.nested,
+            ImplSource::Closure(c) => &mut c.nested,
+            ImplSource::Generator(c) => &mut c.nested,
+            ImplSource::Future(c) => &mut c.nested,
+            ImplSource::Object(d) => &mut d.nested,
+            ImplSource::FnPointer(d) => &mut d.nested,
+            ImplSource::TraitAlias(d) => &mut d.nested,
+            ImplSource::TraitUpcasting(d) => &mut d.nested,
+            ImplSource::ConstDestruct(i) => &mut i.nested,
+        }
+    }
+
     pub fn map<M, F>(self, f: F) -> ImplSource<'tcx, M>
     where
         F: FnMut(N) -> M,
diff --git a/compiler/rustc_middle/src/traits/solve.rs b/compiler/rustc_middle/src/traits/solve.rs
index 6b7b910a59b..1511c906d1e 100644
--- a/compiler/rustc_middle/src/traits/solve.rs
+++ b/compiler/rustc_middle/src/traits/solve.rs
@@ -124,7 +124,7 @@ impl<'tcx> std::ops::Deref for ExternalConstraints<'tcx> {
 pub struct ExternalConstraintsData<'tcx> {
     // FIXME: implement this.
     pub region_constraints: QueryRegionConstraints<'tcx>,
-    pub opaque_types: Vec<(Ty<'tcx>, Ty<'tcx>)>,
+    pub opaque_types: Vec<(ty::OpaqueTypeKey<'tcx>, Ty<'tcx>)>,
 }
 
 // FIXME: Having to clone `region_constraints` for folding feels bad and
diff --git a/compiler/rustc_middle/src/ty/_match.rs b/compiler/rustc_middle/src/ty/_match.rs
index 468c2c818b2..cbc68fde9d9 100644
--- a/compiler/rustc_middle/src/ty/_match.rs
+++ b/compiler/rustc_middle/src/ty/_match.rs
@@ -83,7 +83,7 @@ impl<'tcx> TypeRelation<'tcx> for Match<'tcx> {
 
             (&ty::Error(guar), _) | (_, &ty::Error(guar)) => Ok(self.tcx().ty_error(guar)),
 
-            _ => relate::super_relate_tys(self, a, b),
+            _ => relate::structurally_relate_tys(self, a, b),
         }
     }
 
@@ -109,7 +109,7 @@ impl<'tcx> TypeRelation<'tcx> for Match<'tcx> {
             _ => {}
         }
 
-        relate::super_relate_consts(self, a, b)
+        relate::structurally_relate_consts(self, a, b)
     }
 
     fn binders<T>(
diff --git a/compiler/rustc_middle/src/ty/abstract_const.rs b/compiler/rustc_middle/src/ty/abstract_const.rs
index 972c417cbba..a39631da936 100644
--- a/compiler/rustc_middle/src/ty/abstract_const.rs
+++ b/compiler/rustc_middle/src/ty/abstract_const.rs
@@ -53,7 +53,7 @@ impl<'tcx> TyCtxt<'tcx> {
             fn fold_const(&mut self, c: Const<'tcx>) -> Const<'tcx> {
                 let ct = match c.kind() {
                     ty::ConstKind::Unevaluated(uv) => match self.tcx.thir_abstract_const(uv.def) {
-                        Err(e) => self.tcx.const_error_with_guaranteed(c.ty(), e),
+                        Err(e) => self.tcx.const_error(c.ty(), e),
                         Ok(Some(bac)) => {
                             let substs = self.tcx.erase_regions(uv.substs);
                             let bac = bac.subst(self.tcx, substs);
diff --git a/compiler/rustc_middle/src/ty/adt.rs b/compiler/rustc_middle/src/ty/adt.rs
index ad9891a5dca..7c5c030c276 100644
--- a/compiler/rustc_middle/src/ty/adt.rs
+++ b/compiler/rustc_middle/src/ty/adt.rs
@@ -111,12 +111,30 @@ impl Ord for AdtDefData {
     }
 }
 
-/// There should be only one AdtDef for each `did`, therefore
-/// it is fine to implement `PartialEq` only based on `did`.
 impl PartialEq for AdtDefData {
     #[inline]
     fn eq(&self, other: &Self) -> bool {
-        self.did == other.did
+        // There should be only one `AdtDefData` for each `def_id`, therefore
+        // it is fine to implement `PartialEq` only based on `def_id`.
+        //
+        // Below, we exhaustively destructure `self` and `other` so that if the
+        // definition of `AdtDefData` changes, a compile-error will be produced,
+        // reminding us to revisit this assumption.
+
+        let Self { did: self_def_id, variants: _, flags: _, repr: _ } = self;
+        let Self { did: other_def_id, variants: _, flags: _, repr: _ } = other;
+
+        let res = self_def_id == other_def_id;
+
+        // Double check that implicit assumption detailed above.
+        if cfg!(debug_assertions) && res {
+            let deep = self.flags == other.flags
+                && self.repr == other.repr
+                && self.variants == other.variants;
+            assert!(deep, "AdtDefData for the same def-id has differing data");
+        }
+
+        res
     }
 }
 
diff --git a/compiler/rustc_middle/src/ty/closure.rs b/compiler/rustc_middle/src/ty/closure.rs
index f29bf92b0ed..be7b2b7ec67 100644
--- a/compiler/rustc_middle/src/ty/closure.rs
+++ b/compiler/rustc_middle/src/ty/closure.rs
@@ -5,6 +5,7 @@ use crate::{mir, ty};
 
 use std::fmt::Write;
 
+use crate::query::Providers;
 use rustc_data_structures::fx::{FxHashMap, FxIndexMap};
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_hir::{self as hir, LangItem};
@@ -457,6 +458,6 @@ impl BorrowKind {
     }
 }
 
-pub fn provide(providers: &mut ty::query::Providers) {
-    *providers = ty::query::Providers { closure_typeinfo, ..*providers }
+pub fn provide(providers: &mut Providers) {
+    *providers = Providers { closure_typeinfo, ..*providers }
 }
diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs
index e7107c28bf4..1a4bd14815f 100644
--- a/compiler/rustc_middle/src/ty/consts.rs
+++ b/compiler/rustc_middle/src/ty/consts.rs
@@ -6,7 +6,6 @@ use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::LocalDefId;
 use rustc_macros::HashStable;
-use std::fmt;
 
 mod int;
 mod kind;
@@ -21,15 +20,6 @@ pub use valtree::*;
 #[rustc_pass_by_value]
 pub struct Const<'tcx>(pub(super) Interned<'tcx, ConstData<'tcx>>);
 
-impl<'tcx> fmt::Debug for Const<'tcx> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        // This reflects what `Const` looked liked before `Interned` was
-        // introduced. We print it like this to avoid having to update expected
-        // output in a lot of tests.
-        write!(f, "Const {{ ty: {:?}, kind: {:?} }}", self.ty(), self.kind())
-    }
-}
-
 /// Typed constant value.
 #[derive(PartialEq, Eq, PartialOrd, Ord, Hash, HashStable, TyEncodable, TyDecodable)]
 pub struct ConstData<'tcx> {
@@ -142,9 +132,7 @@ impl<'tcx> Const<'tcx> {
                         ty::ConstKind::Bound(debruijn, ty::BoundVar::from_u32(index)),
                         param_ty,
                     )),
-                    Some(rbv::ResolvedArg::Error(guar)) => {
-                        Some(tcx.const_error_with_guaranteed(param_ty, guar))
-                    }
+                    Some(rbv::ResolvedArg::Error(guar)) => Some(tcx.const_error(param_ty, guar)),
                     arg => bug!("unexpected bound var resolution for {:?}: {arg:?}", expr.hir_id),
                 }
             }
@@ -228,7 +216,7 @@ impl<'tcx> Const<'tcx> {
         if let Some(val) = self.kind().try_eval_for_typeck(tcx, param_env) {
             match val {
                 Ok(val) => tcx.mk_const(val, self.ty()),
-                Err(guar) => tcx.const_error_with_guaranteed(self.ty(), guar),
+                Err(guar) => tcx.const_error(self.ty(), guar),
             }
         } else {
             // Either the constant isn't evaluatable or ValTree creation failed.
diff --git a/compiler/rustc_middle/src/ty/consts/kind.rs b/compiler/rustc_middle/src/ty/consts/kind.rs
index 1ac2cd13982..1dd4f8a2437 100644
--- a/compiler/rustc_middle/src/ty/consts/kind.rs
+++ b/compiler/rustc_middle/src/ty/consts/kind.rs
@@ -42,7 +42,7 @@ impl<'tcx> UnevaluatedConst<'tcx> {
 }
 
 /// Represents a constant in Rust.
-#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, TyEncodable, TyDecodable)]
+#[derive(Copy, Clone, Eq, PartialEq, PartialOrd, Ord, TyEncodable, TyDecodable)]
 #[derive(Hash, HashStable, TypeFoldable, TypeVisitable)]
 #[derive(derive_more::From)]
 pub enum ConstKind<'tcx> {
@@ -128,7 +128,7 @@ impl<'tcx> ConstKind<'tcx> {
 }
 
 /// An inference variable for a const, for use in const generics.
-#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, TyEncodable, TyDecodable, Hash)]
+#[derive(Copy, Clone, Eq, PartialEq, PartialOrd, Ord, TyEncodable, TyDecodable, Hash)]
 pub enum InferConst<'tcx> {
     /// Infer the value of the const.
     Var(ty::ConstVid<'tcx>),
@@ -245,7 +245,7 @@ impl<'tcx> ConstKind<'tcx> {
                         // can leak through `val` into the const we return.
                         Ok(val) => Some(Ok(EvalResult::ValTree(val?))),
                         Err(ErrorHandled::TooGeneric) => None,
-                        Err(ErrorHandled::Reported(e)) => Some(Err(e)),
+                        Err(ErrorHandled::Reported(e)) => Some(Err(e.into())),
                     }
                 }
                 EvalMode::Mir => {
@@ -256,7 +256,7 @@ impl<'tcx> ConstKind<'tcx> {
                         // can leak through `val` into the const we return.
                         Ok(val) => Some(Ok(EvalResult::ConstVal(val))),
                         Err(ErrorHandled::TooGeneric) => None,
-                        Err(ErrorHandled::Reported(e)) => Some(Err(e)),
+                        Err(ErrorHandled::Reported(e)) => Some(Err(e.into())),
                     }
                 }
             }
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index 8aea2d8aedf..bbea3e1412b 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -14,15 +14,14 @@ use crate::middle::resolve_bound_vars;
 use crate::middle::stability;
 use crate::mir::interpret::{self, Allocation, ConstAllocation};
 use crate::mir::{Body, Local, Place, PlaceElem, ProjectionKind, Promoted};
-use crate::query::on_disk_cache::OnDiskCache;
+use crate::query::plumbing::QuerySystem;
 use crate::query::LocalCrate;
+use crate::query::Providers;
+use crate::query::{IntoQueryParam, TyCtxtAt};
 use crate::thir::Thir;
 use crate::traits;
 use crate::traits::solve;
 use crate::traits::solve::{ExternalConstraints, ExternalConstraintsData};
-use crate::ty::query::QuerySystem;
-use crate::ty::query::QuerySystemFns;
-use crate::ty::query::{self, TyCtxtAt};
 use crate::ty::{
     self, AdtDef, AdtDefData, AdtKind, Binder, Const, ConstData, FloatTy, FloatVar, FloatVid,
     GenericParamDefKind, ImplPolarity, InferTy, IntTy, IntVar, IntVid, List, ParamConst, ParamTy,
@@ -81,8 +80,6 @@ use std::iter;
 use std::mem;
 use std::ops::{Bound, Deref};
 
-use super::query::IntoQueryParam;
-
 const TINY_CONST_EVAL_LIMIT: Limit = Limit(20);
 
 #[allow(rustc::usage_of_ty_tykind)]
@@ -496,7 +493,7 @@ pub struct GlobalCtxt<'tcx> {
     ///
     /// FIXME(Centril): consider `dyn LintStoreMarker` once
     /// we can upcast to `Any` for some additional type safety.
-    pub lint_store: Lrc<dyn Any + sync::Sync + sync::Send>,
+    pub lint_store: Lrc<dyn Any + sync::DynSync + sync::DynSend>,
 
     pub dep_graph: DepGraph,
 
@@ -513,7 +510,7 @@ pub struct GlobalCtxt<'tcx> {
 
     untracked: Untracked,
 
-    pub query_system: query::QuerySystem<'tcx>,
+    pub query_system: QuerySystem<'tcx>,
     pub(crate) query_kinds: &'tcx [DepKindStruct<'tcx>],
 
     // Internal caches for metadata decoding. No need to track deps on this.
@@ -648,14 +645,13 @@ impl<'tcx> TyCtxt<'tcx> {
     /// reference to the context, to allow formatting values that need it.
     pub fn create_global_ctxt(
         s: &'tcx Session,
-        lint_store: Lrc<dyn Any + sync::Send + sync::Sync>,
+        lint_store: Lrc<dyn Any + sync::DynSend + sync::DynSync>,
         arena: &'tcx WorkerLocal<Arena<'tcx>>,
         hir_arena: &'tcx WorkerLocal<hir::Arena<'tcx>>,
         untracked: Untracked,
         dep_graph: DepGraph,
-        on_disk_cache: Option<OnDiskCache<'tcx>>,
         query_kinds: &'tcx [DepKindStruct<'tcx>],
-        query_system_fns: QuerySystemFns<'tcx>,
+        query_system: QuerySystem<'tcx>,
     ) -> GlobalCtxt<'tcx> {
         let data_layout = s.target.parse_data_layout().unwrap_or_else(|err| {
             s.emit_fatal(err);
@@ -677,7 +673,7 @@ impl<'tcx> TyCtxt<'tcx> {
             lifetimes: common_lifetimes,
             consts: common_consts,
             untracked,
-            query_system: QuerySystem::new(query_system_fns, on_disk_cache),
+            query_system,
             query_kinds,
             ty_rcache: Default::default(),
             pred_rcache: Default::default(),
@@ -704,7 +700,11 @@ impl<'tcx> TyCtxt<'tcx> {
     /// Constructs a `TyKind::Error` type and registers a `delay_span_bug` with the given `msg` to
     /// ensure it gets used.
     #[track_caller]
-    pub fn ty_error_with_message<S: Into<MultiSpan>>(self, span: S, msg: &str) -> Ty<'tcx> {
+    pub fn ty_error_with_message<S: Into<MultiSpan>>(
+        self,
+        span: S,
+        msg: impl Into<DiagnosticMessage>,
+    ) -> Ty<'tcx> {
         let reported = self.sess.delay_span_bug(span, msg);
         self.mk_ty_from_kind(Error(reported))
     }
@@ -735,17 +735,13 @@ impl<'tcx> TyCtxt<'tcx> {
 
     /// Like [TyCtxt::ty_error] but for constants, with current `ErrorGuaranteed`
     #[track_caller]
-    pub fn const_error_with_guaranteed(
-        self,
-        ty: Ty<'tcx>,
-        reported: ErrorGuaranteed,
-    ) -> Const<'tcx> {
+    pub fn const_error(self, ty: Ty<'tcx>, reported: ErrorGuaranteed) -> Const<'tcx> {
         self.mk_const(ty::ConstKind::Error(reported), ty)
     }
 
     /// Like [TyCtxt::ty_error] but for constants.
     #[track_caller]
-    pub fn const_error(self, ty: Ty<'tcx>) -> Const<'tcx> {
+    pub fn const_error_misc(self, ty: Ty<'tcx>) -> Const<'tcx> {
         self.const_error_with_message(
             ty,
             DUMMY_SP,
@@ -2441,7 +2437,7 @@ impl<'tcx> TyCtxtAt<'tcx> {
     /// Constructs a `TyKind::Error` type and registers a `delay_span_bug` with the given `msg` to
     /// ensure it gets used.
     #[track_caller]
-    pub fn ty_error_with_message(self, msg: &str) -> Ty<'tcx> {
+    pub fn ty_error_with_message(self, msg: impl Into<DiagnosticMessage>) -> Ty<'tcx> {
         self.tcx.ty_error_with_message(self.span, msg)
     }
 }
@@ -2461,7 +2457,7 @@ pub struct DeducedParamAttrs {
     pub read_only: bool,
 }
 
-pub fn provide(providers: &mut ty::query::Providers) {
+pub fn provide(providers: &mut Providers) {
     providers.maybe_unused_trait_imports =
         |tcx, ()| &tcx.resolutions(()).maybe_unused_trait_imports;
     providers.names_imported_by_glob_use = |tcx, id| {
diff --git a/compiler/rustc_middle/src/ty/context/tls.rs b/compiler/rustc_middle/src/ty/context/tls.rs
index fb0d909307e..5c1c419811e 100644
--- a/compiler/rustc_middle/src/ty/context/tls.rs
+++ b/compiler/rustc_middle/src/ty/context/tls.rs
@@ -1,7 +1,7 @@
 use super::{GlobalCtxt, TyCtxt};
 
 use crate::dep_graph::TaskDepsRef;
-use crate::ty::query;
+use crate::query::plumbing::QueryJobId;
 use rustc_data_structures::sync::{self, Lock};
 use rustc_errors::Diagnostic;
 #[cfg(not(parallel_compiler))]
@@ -22,7 +22,7 @@ pub struct ImplicitCtxt<'a, 'tcx> {
 
     /// The current query job, if any. This is updated by `JobOwner::start` in
     /// `ty::query::plumbing` when executing a query.
-    pub query: Option<query::QueryJobId>,
+    pub query: Option<QueryJobId>,
 
     /// Where to store diagnostics for the current query job, if any.
     /// This is updated by `JobOwner::start` in `ty::query::plumbing` when executing a query.
@@ -94,8 +94,8 @@ where
         f(None)
     } else {
         // We could get an `ImplicitCtxt` pointer from another thread.
-        // Ensure that `ImplicitCtxt` is `Sync`.
-        sync::assert_sync::<ImplicitCtxt<'_, '_>>();
+        // Ensure that `ImplicitCtxt` is `DynSync`.
+        sync::assert_dyn_sync::<ImplicitCtxt<'_, '_>>();
 
         unsafe { f(Some(downcast(context))) }
     }
diff --git a/compiler/rustc_middle/src/ty/erase_regions.rs b/compiler/rustc_middle/src/ty/erase_regions.rs
index ad930d1e6b6..7895993ccff 100644
--- a/compiler/rustc_middle/src/ty/erase_regions.rs
+++ b/compiler/rustc_middle/src/ty/erase_regions.rs
@@ -1,8 +1,9 @@
+use crate::query::Providers;
 use crate::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable};
 use crate::ty::{self, Ty, TyCtxt, TypeFlags, TypeVisitableExt};
 
-pub(super) fn provide(providers: &mut ty::query::Providers) {
-    *providers = ty::query::Providers { erase_regions_ty, ..*providers };
+pub(super) fn provide(providers: &mut Providers) {
+    *providers = Providers { erase_regions_ty, ..*providers };
 }
 
 fn erase_regions_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> {
diff --git a/compiler/rustc_middle/src/ty/generics.rs b/compiler/rustc_middle/src/ty/generics.rs
index baef4ffeda7..99174bae3f6 100644
--- a/compiler/rustc_middle/src/ty/generics.rs
+++ b/compiler/rustc_middle/src/ty/generics.rs
@@ -103,7 +103,7 @@ impl GenericParamDef {
             ty::GenericParamDefKind::Lifetime => tcx.mk_re_error_misc().into(),
             ty::GenericParamDefKind::Type { .. } => tcx.ty_error_misc().into(),
             ty::GenericParamDefKind::Const { .. } => {
-                tcx.const_error(tcx.type_of(self.def_id).subst(tcx, preceding_substs)).into()
+                tcx.const_error_misc(tcx.type_of(self.def_id).subst(tcx, preceding_substs)).into()
             }
         }
     }
diff --git a/compiler/rustc_middle/src/ty/inhabitedness/mod.rs b/compiler/rustc_middle/src/ty/inhabitedness/mod.rs
index 9e672004cf9..4223502848e 100644
--- a/compiler/rustc_middle/src/ty/inhabitedness/mod.rs
+++ b/compiler/rustc_middle/src/ty/inhabitedness/mod.rs
@@ -43,6 +43,7 @@
 //! This code should only compile in modules where the uninhabitedness of `Foo`
 //! is visible.
 
+use crate::query::Providers;
 use crate::ty::context::TyCtxt;
 use crate::ty::{self, DefId, Ty, VariantDef, Visibility};
 
@@ -52,9 +53,8 @@ pub mod inhabited_predicate;
 
 pub use inhabited_predicate::InhabitedPredicate;
 
-pub(crate) fn provide(providers: &mut ty::query::Providers) {
-    *providers =
-        ty::query::Providers { inhabited_predicate_adt, inhabited_predicate_type, ..*providers };
+pub(crate) fn provide(providers: &mut Providers) {
+    *providers = Providers { inhabited_predicate_adt, inhabited_predicate_type, ..*providers };
 }
 
 /// Returns an `InhabitedPredicate` that is generic over type parameters and
diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs
index 47cf48f46cf..b5a743cfe34 100644
--- a/compiler/rustc_middle/src/ty/layout.rs
+++ b/compiler/rustc_middle/src/ty/layout.rs
@@ -1,5 +1,6 @@
 use crate::fluent_generated as fluent;
 use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags;
+use crate::query::TyCtxtAt;
 use crate::ty::normalize_erasing_regions::NormalizationError;
 use crate::ty::{self, ReprOptions, Ty, TyCtxt, TypeVisitableExt};
 use rustc_errors::{DiagnosticBuilder, Handler, IntoDiagnostic};
@@ -268,7 +269,7 @@ pub struct LayoutCx<'tcx, C> {
 impl<'tcx> LayoutCalculator for LayoutCx<'tcx, TyCtxt<'tcx>> {
     type TargetDataLayoutRef = &'tcx TargetDataLayout;
 
-    fn delay_bug(&self, txt: &str) {
+    fn delay_bug(&self, txt: String) {
         self.tcx.sess.delay_span_bug(DUMMY_SP, txt);
     }
 
@@ -543,20 +544,20 @@ impl<'tcx> HasTyCtxt<'tcx> for TyCtxt<'tcx> {
     }
 }
 
-impl<'tcx> HasDataLayout for ty::query::TyCtxtAt<'tcx> {
+impl<'tcx> HasDataLayout for TyCtxtAt<'tcx> {
     #[inline]
     fn data_layout(&self) -> &TargetDataLayout {
         &self.data_layout
     }
 }
 
-impl<'tcx> HasTargetSpec for ty::query::TyCtxtAt<'tcx> {
+impl<'tcx> HasTargetSpec for TyCtxtAt<'tcx> {
     fn target_spec(&self) -> &Target {
         &self.sess.target
     }
 }
 
-impl<'tcx> HasTyCtxt<'tcx> for ty::query::TyCtxtAt<'tcx> {
+impl<'tcx> HasTyCtxt<'tcx> for TyCtxtAt<'tcx> {
     #[inline]
     fn tcx(&self) -> TyCtxt<'tcx> {
         **self
@@ -683,7 +684,7 @@ impl<'tcx> LayoutOfHelpers<'tcx> for LayoutCx<'tcx, TyCtxt<'tcx>> {
     }
 }
 
-impl<'tcx> LayoutOfHelpers<'tcx> for LayoutCx<'tcx, ty::query::TyCtxtAt<'tcx>> {
+impl<'tcx> LayoutOfHelpers<'tcx> for LayoutCx<'tcx, TyCtxtAt<'tcx>> {
     type LayoutOfResult = Result<TyAndLayout<'tcx>, LayoutError<'tcx>>;
 
     #[inline]
diff --git a/compiler/rustc_middle/src/ty/list.rs b/compiler/rustc_middle/src/ty/list.rs
index 30f036e471c..71911a5a618 100644
--- a/compiler/rustc_middle/src/ty/list.rs
+++ b/compiler/rustc_middle/src/ty/list.rs
@@ -199,6 +199,12 @@ impl<'a, T: Copy> IntoIterator for &'a List<T> {
 
 unsafe impl<T: Sync> Sync for List<T> {}
 
+// We need this since `List` uses extern type `OpaqueListContents`.
+#[cfg(parallel_compiler)]
+use rustc_data_structures::sync::DynSync;
+#[cfg(parallel_compiler)]
+unsafe impl<T: DynSync> DynSync for List<T> {}
+
 // Safety:
 // Layouts of `Equivalent<T>` and `List<T>` are the same, modulo opaque tail,
 // thus aligns of `Equivalent<T>` and `List<T>` must be the same.
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index f882f54d628..ecb191676c2 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -21,6 +21,7 @@ use crate::error::{OpaqueHiddenTypeMismatch, TypeMismatchReason};
 use crate::metadata::ModChild;
 use crate::middle::privacy::EffectiveVisibilities;
 use crate::mir::{Body, GeneratorLayout};
+use crate::query::Providers;
 use crate::traits::{self, Reveal};
 use crate::ty;
 use crate::ty::fast_reject::SimplifiedType;
@@ -121,7 +122,6 @@ pub mod inhabitedness;
 pub mod layout;
 pub mod normalize_erasing_regions;
 pub mod print;
-pub mod query;
 pub mod relate;
 pub mod subst;
 pub mod trait_def;
@@ -1070,6 +1070,24 @@ impl ParamTerm {
     }
 }
 
+#[derive(Copy, Clone, Eq, PartialEq, Debug)]
+pub enum TermVid<'tcx> {
+    Ty(ty::TyVid),
+    Const(ty::ConstVid<'tcx>),
+}
+
+impl From<ty::TyVid> for TermVid<'_> {
+    fn from(value: ty::TyVid) -> Self {
+        TermVid::Ty(value)
+    }
+}
+
+impl<'tcx> From<ty::ConstVid<'tcx>> for TermVid<'tcx> {
+    fn from(value: ty::ConstVid<'tcx>) -> Self {
+        TermVid::Const(value)
+    }
+}
+
 /// This kind of predicate has no *direct* correspondent in the
 /// syntax, but it roughly corresponds to the syntactic forms:
 ///
@@ -1864,7 +1882,20 @@ impl PartialEq for VariantDef {
 
         let Self { def_id: lhs_def_id, ctor: _, name: _, discr: _, fields: _, flags: _ } = &self;
         let Self { def_id: rhs_def_id, ctor: _, name: _, discr: _, fields: _, flags: _ } = other;
-        lhs_def_id == rhs_def_id
+
+        let res = lhs_def_id == rhs_def_id;
+
+        // Double check that implicit assumption detailed above.
+        if cfg!(debug_assertions) && res {
+            let deep = self.ctor == other.ctor
+                && self.name == other.name
+                && self.discr == other.discr
+                && self.fields == other.fields
+                && self.flags == other.flags;
+            assert!(deep, "VariantDef for the same def-id has differing data");
+        }
+
+        res
     }
 }
 
@@ -1919,7 +1950,15 @@ impl PartialEq for FieldDef {
 
         let Self { did: rhs_did, name: _, vis: _ } = other;
 
-        lhs_did == rhs_did
+        let res = lhs_did == rhs_did;
+
+        // Double check that implicit assumption detailed above.
+        if cfg!(debug_assertions) && res {
+            let deep = self.name == other.name && self.vis == other.vis;
+            assert!(deep, "FieldDef for the same def-id has differing data");
+        }
+
+        res
     }
 }
 
@@ -2476,6 +2515,18 @@ impl<'tcx> TyCtxt<'tcx> {
         }
     }
 
+    /// Returns the `DefId` of the item within which the `impl Trait` is declared.
+    /// For type-alias-impl-trait this is the `type` alias.
+    /// For impl-trait-in-assoc-type this is the assoc type.
+    /// For return-position-impl-trait this is the function.
+    pub fn impl_trait_parent(self, mut def_id: LocalDefId) -> LocalDefId {
+        // Find the surrounding item (type alias or assoc type)
+        while let DefKind::OpaqueTy = self.def_kind(def_id) {
+            def_id = self.local_parent(def_id);
+        }
+        def_id
+    }
+
     pub fn impl_method_has_trait_impl_trait_tys(self, def_id: DefId) -> bool {
         if self.def_kind(def_id) != DefKind::AssocFn {
             return false;
@@ -2520,7 +2571,7 @@ pub fn is_impl_trait_defn(tcx: TyCtxt<'_>, def_id: DefId) -> Option<LocalDefId>
                 hir::OpaqueTyOrigin::FnReturn(parent) | hir::OpaqueTyOrigin::AsyncFn(parent) => {
                     Some(parent)
                 }
-                hir::OpaqueTyOrigin::TyAlias => None,
+                hir::OpaqueTyOrigin::TyAlias { .. } => None,
             };
         }
     }
@@ -2578,7 +2629,7 @@ pub fn ast_uint_ty(uty: UintTy) -> ast::UintTy {
     }
 }
 
-pub fn provide(providers: &mut ty::query::Providers) {
+pub fn provide(providers: &mut Providers) {
     closure::provide(providers);
     context::provide(providers);
     erase_regions::provide(providers);
@@ -2587,7 +2638,7 @@ pub fn provide(providers: &mut ty::query::Providers) {
     print::provide(providers);
     super::util::bug::provide(providers);
     super::middle::provide(providers);
-    *providers = ty::query::Providers {
+    *providers = Providers {
         trait_impls_of: trait_def::trait_impls_of_provider,
         incoherent_impls: trait_def::incoherent_impls_provider,
         const_param_default: consts::const_param_default,
diff --git a/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs b/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs
index 9332b0430ff..a0c8d299f48 100644
--- a/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs
+++ b/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs
@@ -32,7 +32,7 @@ impl<'tcx> TyCtxt<'tcx> {
     ///
     /// This should only be used outside of type inference. For example,
     /// it assumes that normalization will succeed.
-    #[tracing::instrument(level = "debug", skip(self, param_env))]
+    #[tracing::instrument(level = "debug", skip(self, param_env), ret)]
     pub fn normalize_erasing_regions<T>(self, param_env: ty::ParamEnv<'tcx>, value: T) -> T
     where
         T: TypeFoldable<TyCtxt<'tcx>>,
diff --git a/compiler/rustc_middle/src/ty/opaque_types.rs b/compiler/rustc_middle/src/ty/opaque_types.rs
index 72710b78c93..1b336b7bfc6 100644
--- a/compiler/rustc_middle/src/ty/opaque_types.rs
+++ b/compiler/rustc_middle/src/ty/opaque_types.rs
@@ -207,14 +207,16 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ReverseMapper<'tcx> {
                     Some(GenericArgKind::Const(c1)) => c1,
                     Some(u) => panic!("const mapped to unexpected kind: {:?}", u),
                     None => {
-                        if !self.ignore_errors {
-                            self.tcx.sess.emit_err(ConstNotUsedTraitAlias {
+                        let guar = self
+                            .tcx
+                            .sess
+                            .create_err(ConstNotUsedTraitAlias {
                                 ct: ct.to_string(),
                                 span: self.span,
-                            });
-                        }
+                            })
+                            .emit_unless(self.ignore_errors);
 
-                        self.interner().const_error(ct.ty())
+                        self.interner().const_error(ct.ty(), guar)
                     }
                 }
             }
diff --git a/compiler/rustc_middle/src/ty/parameterized.rs b/compiler/rustc_middle/src/ty/parameterized.rs
index 810c388ebbe..a2e77d9cdfe 100644
--- a/compiler/rustc_middle/src/ty/parameterized.rs
+++ b/compiler/rustc_middle/src/ty/parameterized.rs
@@ -56,6 +56,7 @@ trivially_parameterized_over_tcx! {
     std::string::String,
     crate::metadata::ModChild,
     crate::middle::codegen_fn_attrs::CodegenFnAttrs,
+    crate::middle::debugger_visualizer::DebuggerVisualizerFile,
     crate::middle::exported_symbols::SymbolExportInfo,
     crate::middle::resolve_bound_vars::ObjectLifetimeDefault,
     crate::mir::ConstQualifs,
@@ -91,7 +92,6 @@ trivially_parameterized_over_tcx! {
     rustc_session::cstore::ForeignModule,
     rustc_session::cstore::LinkagePreference,
     rustc_session::cstore::NativeLib,
-    rustc_span::DebuggerVisualizerFile,
     rustc_span::ExpnData,
     rustc_span::ExpnHash,
     rustc_span::ExpnId,
diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs
index 926172ff828..4491d78648f 100644
--- a/compiler/rustc_middle/src/ty/print/pretty.rs
+++ b/compiler/rustc_middle/src/ty/print/pretty.rs
@@ -1,5 +1,6 @@
 use crate::mir::interpret::{AllocRange, GlobalAlloc, Pointer, Provenance, Scalar};
-use crate::ty::query::IntoQueryParam;
+use crate::query::IntoQueryParam;
+use crate::query::Providers;
 use crate::ty::{
     self, ConstInt, ParamConst, ScalarInt, Term, TermKind, Ty, TyCtxt, TypeFoldable,
     TypeSuperFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitableExt,
@@ -702,7 +703,7 @@ pub trait PrettyPrinter<'tcx>:
             ty::Error(_) => p!("[type error]"),
             ty::Param(ref param_ty) => p!(print(param_ty)),
             ty::Bound(debruijn, bound_ty) => match bound_ty.kind {
-                ty::BoundTyKind::Anon => self.pretty_print_bound_var(debruijn, bound_ty.var)?,
+                ty::BoundTyKind::Anon => debug_bound_var(&mut self, debruijn, bound_ty.var)?,
                 ty::BoundTyKind::Param(_, s) => match self.should_print_verbose() {
                     true if debruijn == ty::INNERMOST => p!(write("^{}", s)),
                     true => p!(write("^{}_{}", debruijn.index(), s)),
@@ -740,7 +741,7 @@ pub trait PrettyPrinter<'tcx>:
             }
             ty::Placeholder(placeholder) => match placeholder.bound.kind {
                 ty::BoundTyKind::Anon => {
-                    self.pretty_print_placeholder_var(placeholder.universe, placeholder.bound.var)?
+                    debug_placeholder_var(&mut self, placeholder.universe, placeholder.bound.var)?;
                 }
                 ty::BoundTyKind::Param(_, name) => p!(write("{}", name)),
             },
@@ -1163,30 +1164,6 @@ pub trait PrettyPrinter<'tcx>:
         traits.entry(trait_ref).or_default().extend(proj_ty);
     }
 
-    fn pretty_print_bound_var(
-        &mut self,
-        debruijn: ty::DebruijnIndex,
-        var: ty::BoundVar,
-    ) -> Result<(), Self::Error> {
-        if debruijn == ty::INNERMOST {
-            write!(self, "^{}", var.index())
-        } else {
-            write!(self, "^{}_{}", debruijn.index(), var.index())
-        }
-    }
-
-    fn pretty_print_placeholder_var(
-        &mut self,
-        ui: ty::UniverseIndex,
-        var: ty::BoundVar,
-    ) -> Result<(), Self::Error> {
-        if ui == ty::UniverseIndex::ROOT {
-            write!(self, "!{}", var.index())
-        } else {
-            write!(self, "!{}_{}", ui.index(), var.index())
-        }
-    }
-
     fn ty_infer_name(&self, _: ty::TyVid) -> Option<Symbol> {
         None
     }
@@ -1320,7 +1297,7 @@ pub trait PrettyPrinter<'tcx>:
         define_scoped_cx!(self);
 
         if self.should_print_verbose() {
-            p!(write("Const({:?}: {:?})", ct.kind(), ct.ty()));
+            p!(write("{:?}", ct));
             return Ok(self);
         }
 
@@ -1379,9 +1356,11 @@ pub trait PrettyPrinter<'tcx>:
             }
 
             ty::ConstKind::Bound(debruijn, bound_var) => {
-                self.pretty_print_bound_var(debruijn, bound_var)?
+                debug_bound_var(&mut self, debruijn, bound_var)?
             }
-            ty::ConstKind::Placeholder(placeholder) => p!(write("Placeholder({:?})", placeholder)),
+            ty::ConstKind::Placeholder(placeholder) => {
+                debug_placeholder_var(&mut self, placeholder.universe, placeholder.bound)?;
+            },
             // FIXME(generic_const_exprs):
             // write out some legible representation of an abstract const?
             ty::ConstKind::Expr(_) => p!("[const expr]"),
@@ -3054,8 +3033,8 @@ fn trimmed_def_paths(tcx: TyCtxt<'_>, (): ()) -> FxHashMap<DefId, Symbol> {
     map
 }
 
-pub fn provide(providers: &mut ty::query::Providers) {
-    *providers = ty::query::Providers { trimmed_def_paths, ..*providers };
+pub fn provide(providers: &mut Providers) {
+    *providers = Providers { trimmed_def_paths, ..*providers };
 }
 
 #[derive(Default)]
@@ -3066,3 +3045,27 @@ pub struct OpaqueFnEntry<'tcx> {
     fn_trait_ref: Option<ty::PolyTraitRef<'tcx>>,
     return_ty: Option<ty::Binder<'tcx, Term<'tcx>>>,
 }
+
+pub fn debug_bound_var<T: std::fmt::Write>(
+    fmt: &mut T,
+    debruijn: ty::DebruijnIndex,
+    var: ty::BoundVar,
+) -> Result<(), std::fmt::Error> {
+    if debruijn == ty::INNERMOST {
+        write!(fmt, "^{}", var.index())
+    } else {
+        write!(fmt, "^{}_{}", debruijn.index(), var.index())
+    }
+}
+
+pub fn debug_placeholder_var<T: std::fmt::Write>(
+    fmt: &mut T,
+    universe: ty::UniverseIndex,
+    bound: ty::BoundVar,
+) -> Result<(), std::fmt::Error> {
+    if universe == ty::UniverseIndex::ROOT {
+        write!(fmt, "!{}", bound.index())
+    } else {
+        write!(fmt, "!{}_{}", universe.index(), bound.index())
+    }
+}
diff --git a/compiler/rustc_middle/src/ty/relate.rs b/compiler/rustc_middle/src/ty/relate.rs
index da43475941e..3bbe6a23b66 100644
--- a/compiler/rustc_middle/src/ty/relate.rs
+++ b/compiler/rustc_middle/src/ty/relate.rs
@@ -388,24 +388,24 @@ impl<'tcx> Relate<'tcx> for Ty<'tcx> {
     }
 }
 
-/// The main "type relation" routine. Note that this does not handle
-/// inference artifacts, so you should filter those out before calling
-/// it.
-pub fn super_relate_tys<'tcx, R: TypeRelation<'tcx>>(
+/// Relates `a` and `b` structurally, calling the relation for all nested values.
+/// Any semantic equality, e.g. of projections, and inference variables have to be
+/// handled by the caller.
+pub fn structurally_relate_tys<'tcx, R: TypeRelation<'tcx>>(
     relation: &mut R,
     a: Ty<'tcx>,
     b: Ty<'tcx>,
 ) -> RelateResult<'tcx, Ty<'tcx>> {
     let tcx = relation.tcx();
-    debug!("super_relate_tys: a={:?} b={:?}", a, b);
+    debug!("structurally_relate_tys: a={:?} b={:?}", a, b);
     match (a.kind(), b.kind()) {
         (&ty::Infer(_), _) | (_, &ty::Infer(_)) => {
             // The caller should handle these cases!
-            bug!("var types encountered in super_relate_tys")
+            bug!("var types encountered in structurally_relate_tys")
         }
 
         (ty::Bound(..), _) | (_, ty::Bound(..)) => {
-            bug!("bound types encountered in super_relate_tys")
+            bug!("bound types encountered in structurally_relate_tys")
         }
 
         (&ty::Error(guar), _) | (_, &ty::Error(guar)) => Ok(tcx.ty_error(guar)),
@@ -575,15 +575,18 @@ pub fn super_relate_tys<'tcx, R: TypeRelation<'tcx>>(
     }
 }
 
-/// The main "const relation" routine. Note that this does not handle
-/// inference artifacts, so you should filter those out before calling
-/// it.
-pub fn super_relate_consts<'tcx, R: TypeRelation<'tcx>>(
+/// Relates `a` and `b` structurally, calling the relation for all nested values.
+/// Any semantic equality, e.g. of unevaluated consts, and inference variables have
+/// to be handled by the caller.
+///
+/// FIXME: This is not totally structual, which probably should be fixed.
+/// See the HACKs below.
+pub fn structurally_relate_consts<'tcx, R: TypeRelation<'tcx>>(
     relation: &mut R,
     mut a: ty::Const<'tcx>,
     mut b: ty::Const<'tcx>,
 ) -> RelateResult<'tcx, ty::Const<'tcx>> {
-    debug!("{}.super_relate_consts(a = {:?}, b = {:?})", relation.tag(), a, b);
+    debug!("{}.structurally_relate_consts(a = {:?}, b = {:?})", relation.tag(), a, b);
     let tcx = relation.tcx();
 
     // HACK(const_generics): We still need to eagerly evaluate consts when
@@ -602,7 +605,7 @@ pub fn super_relate_consts<'tcx, R: TypeRelation<'tcx>>(
         b = tcx.expand_abstract_consts(b);
     }
 
-    debug!("{}.super_relate_consts(normed_a = {:?}, normed_b = {:?})", relation.tag(), a, b);
+    debug!("{}.structurally_relate_consts(normed_a = {:?}, normed_b = {:?})", relation.tag(), a, b);
 
     // Currently, the values that can be unified are primitive types,
     // and those that derive both `PartialEq` and `Eq`, corresponding
@@ -610,7 +613,7 @@ pub fn super_relate_consts<'tcx, R: TypeRelation<'tcx>>(
     let is_match = match (a.kind(), b.kind()) {
         (ty::ConstKind::Infer(_), _) | (_, ty::ConstKind::Infer(_)) => {
             // The caller should handle these cases!
-            bug!("var types encountered in super_relate_consts: {:?} {:?}", a, b)
+            bug!("var types encountered in structurally_relate_consts: {:?} {:?}", a, b)
         }
 
         (ty::ConstKind::Error(_), _) => return Ok(a),
diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs
index 29a3bc8bb97..16cb6c91046 100644
--- a/compiler/rustc_middle/src/ty/structural_impls.rs
+++ b/compiler/rustc_middle/src/ty/structural_impls.rs
@@ -192,6 +192,44 @@ impl<'tcx> fmt::Debug for AliasTy<'tcx> {
     }
 }
 
+impl<'tcx> fmt::Debug for ty::InferConst<'tcx> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        match self {
+            InferConst::Var(var) => write!(f, "{var:?}"),
+            InferConst::Fresh(var) => write!(f, "Fresh({var:?})"),
+        }
+    }
+}
+
+impl<'tcx> fmt::Debug for ty::Const<'tcx> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        // This reflects what `Const` looked liked before `Interned` was
+        // introduced. We print it like this to avoid having to update expected
+        // output in a lot of tests.
+        write!(f, "Const {{ ty: {:?}, kind: {:?} }}", self.ty(), self.kind())
+    }
+}
+
+impl<'tcx> fmt::Debug for ty::ConstKind<'tcx> {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        use ty::ConstKind::*;
+        match self {
+            Param(param) => write!(f, "{param:?}"),
+            Infer(var) => write!(f, "{var:?}"),
+            Bound(debruijn, var) => ty::print::debug_bound_var(f, *debruijn, *var),
+            Placeholder(placeholder) => {
+                ty::print::debug_placeholder_var(f, placeholder.universe, placeholder.bound)
+            }
+            Unevaluated(uv) => {
+                f.debug_tuple("Unevaluated").field(&uv.substs).field(&uv.def).finish()
+            }
+            Value(valtree) => write!(f, "{valtree:?}"),
+            Error(_) => write!(f, "[const error]"),
+            Expr(expr) => write!(f, "{expr:?}"),
+        }
+    }
+}
+
 ///////////////////////////////////////////////////////////////////////////
 // Atomic structs
 //
@@ -204,6 +242,7 @@ CloneLiftImpls! {
     (),
     bool,
     usize,
+    u8,
     u16,
     u32,
     u64,
diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs
index 488d83b5f67..e6d51c4ec97 100644
--- a/compiler/rustc_middle/src/ty/sty.rs
+++ b/compiler/rustc_middle/src/ty/sty.rs
@@ -1265,7 +1265,7 @@ impl<'tcx> AliasTy<'tcx> {
 
     /// Extracts the underlying trait reference and own substs from this projection.
     /// 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
+    /// then this function would return a `T: StreamingIterator` trait reference and `['a]` as the own substs
     pub fn trait_ref_and_own_substs(
         self,
         tcx: TyCtxt<'tcx>,
@@ -1708,7 +1708,9 @@ impl<'tcx> Region<'tcx> {
             ty::ReErased => {
                 flags = flags | TypeFlags::HAS_RE_ERASED;
             }
-            ty::ReError(_) => {}
+            ty::ReError(_) => {
+                flags = flags | TypeFlags::HAS_FREE_REGIONS;
+            }
         }
 
         debug!("type_flags({:?}) = {:?}", self, flags);
diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs
index bcb51db9bcf..eb903ebfd99 100644
--- a/compiler/rustc_middle/src/ty/util.rs
+++ b/compiler/rustc_middle/src/ty/util.rs
@@ -2,6 +2,7 @@
 
 use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags;
 use crate::mir;
+use crate::query::Providers;
 use crate::ty::layout::IntegerExt;
 use crate::ty::{
     self, FallibleTypeFolder, ToPredicate, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable,
@@ -34,9 +35,14 @@ pub struct Discr<'tcx> {
 
 /// Used as an input to [`TyCtxt::uses_unique_generic_params`].
 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
-pub enum IgnoreRegions {
-    Yes,
+pub enum CheckRegions {
     No,
+    /// Only permit early bound regions. This is useful for Adts which
+    /// can never have late bound regions.
+    OnlyEarlyBound,
+    /// Permit both late bound and early bound regions. Use this for functions,
+    /// which frequently have late bound regions.
+    Bound,
 }
 
 #[derive(Copy, Clone, Debug)]
@@ -468,21 +474,28 @@ impl<'tcx> TyCtxt<'tcx> {
     pub fn uses_unique_generic_params(
         self,
         substs: SubstsRef<'tcx>,
-        ignore_regions: IgnoreRegions,
+        ignore_regions: CheckRegions,
     ) -> Result<(), NotUniqueParam<'tcx>> {
         let mut seen = GrowableBitSet::default();
+        let mut seen_late = FxHashSet::default();
         for arg in substs {
             match arg.unpack() {
-                GenericArgKind::Lifetime(lt) => {
-                    if ignore_regions == IgnoreRegions::No {
-                        let ty::ReEarlyBound(p) = lt.kind() else {
-                            return Err(NotUniqueParam::NotParam(lt.into()))
-                        };
+                GenericArgKind::Lifetime(lt) => match (ignore_regions, lt.kind()) {
+                    (CheckRegions::Bound, ty::ReLateBound(di, reg)) => {
+                        if !seen_late.insert((di, reg)) {
+                            return Err(NotUniqueParam::DuplicateParam(lt.into()));
+                        }
+                    }
+                    (CheckRegions::OnlyEarlyBound | CheckRegions::Bound, ty::ReEarlyBound(p)) => {
                         if !seen.insert(p.index) {
                             return Err(NotUniqueParam::DuplicateParam(lt.into()));
                         }
                     }
-                }
+                    (CheckRegions::OnlyEarlyBound | CheckRegions::Bound, _) => {
+                        return Err(NotUniqueParam::NotParam(lt.into()));
+                    }
+                    (CheckRegions::No, _) => {}
+                },
                 GenericArgKind::Type(t) => match t.kind() {
                     ty::Param(p) => {
                         if !seen.insert(p.index) {
@@ -655,10 +668,10 @@ impl<'tcx> TyCtxt<'tcx> {
         self,
         def_id: DefId,
     ) -> impl Iterator<Item = ty::EarlyBinder<Ty<'tcx>>> {
-        let generator_layout = &self.mir_generator_witnesses(def_id);
+        let generator_layout = self.mir_generator_witnesses(def_id);
         generator_layout
-            .field_tys
-            .iter()
+            .as_ref()
+            .map_or_else(|| [].iter(), |l| l.field_tys.iter())
             .filter(|decl| !decl.ignore_for_traits)
             .map(|decl| ty::EarlyBinder(decl.ty))
     }
@@ -1472,8 +1485,8 @@ pub fn is_intrinsic(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
     matches!(tcx.fn_sig(def_id).skip_binder().abi(), Abi::RustIntrinsic | Abi::PlatformIntrinsic)
 }
 
-pub fn provide(providers: &mut ty::query::Providers) {
-    *providers = ty::query::Providers {
+pub fn provide(providers: &mut Providers) {
+    *providers = Providers {
         reveal_opaque_types_in_bounds,
         is_doc_hidden,
         is_doc_notable_trait,
diff --git a/compiler/rustc_middle/src/util/bug.rs b/compiler/rustc_middle/src/util/bug.rs
index 3dfd0824f98..43ee0343f5a 100644
--- a/compiler/rustc_middle/src/util/bug.rs
+++ b/compiler/rustc_middle/src/util/bug.rs
@@ -48,6 +48,6 @@ pub fn trigger_delay_span_bug(tcx: TyCtxt<'_>, key: rustc_hir::def_id::DefId) {
     );
 }
 
-pub fn provide(providers: &mut crate::ty::query::Providers) {
-    *providers = crate::ty::query::Providers { trigger_delay_span_bug, ..*providers };
+pub fn provide(providers: &mut crate::query::Providers) {
+    *providers = crate::query::Providers { trigger_delay_span_bug, ..*providers };
 }
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 931fe1b2433..b74422708ce 100644
--- a/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs
+++ b/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs
@@ -154,6 +154,7 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> {
                 Ok(Rvalue::BinaryOp(BinOp::Offset, Box::new((ptr, offset))))
             },
             @call("mir_len", args) => Ok(Rvalue::Len(self.parse_place(args[0])?)),
+            @call("mir_copy_for_deref", args) => Ok(Rvalue::CopyForDeref(self.parse_place(args[0])?)),
             ExprKind::Borrow { borrow_kind, arg } => Ok(
                 Rvalue::Ref(self.tcx.lifetimes.re_erased, *borrow_kind, self.parse_place(*arg)?)
             ),
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 59549435233..4d99ab4b0ec 100644
--- a/compiler/rustc_mir_build/src/build/expr/as_constant.rs
+++ b/compiler/rustc_mir_build/src/build/expr/as_constant.rs
@@ -52,7 +52,7 @@ pub fn as_constant_inner<'tcx>(
                 match lit_to_mir_constant(tcx, LitToConstInput { lit: &lit.node, ty, neg }) {
                     Ok(c) => c,
                     Err(LitToConstError::Reported(guar)) => {
-                        ConstantKind::Ty(tcx.const_error_with_guaranteed(ty, guar))
+                        ConstantKind::Ty(tcx.const_error(ty, guar))
                     }
                     Err(LitToConstError::TypeError) => {
                         bug!("encountered type error in `lit_to_mir_constant`")
diff --git a/compiler/rustc_mir_build/src/build/matches/mod.rs b/compiler/rustc_mir_build/src/build/matches/mod.rs
index 4926ff85de3..6df06df5c60 100644
--- a/compiler/rustc_mir_build/src/build/matches/mod.rs
+++ b/compiler/rustc_mir_build/src/build/matches/mod.rs
@@ -2241,6 +2241,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         self.var_debug_info.push(VarDebugInfo {
             name,
             source_info: debug_source_info,
+            references: 0,
             value: VarDebugInfoContents::Place(for_arm_body.into()),
             argument_index: None,
         });
@@ -2260,6 +2261,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             self.var_debug_info.push(VarDebugInfo {
                 name,
                 source_info: debug_source_info,
+                references: 0,
                 value: VarDebugInfoContents::Place(ref_for_guard.into()),
                 argument_index: None,
             });
diff --git a/compiler/rustc_mir_build/src/build/matches/test.rs b/compiler/rustc_mir_build/src/build/matches/test.rs
index 4536ecf17b8..dbdb5b4a9a1 100644
--- a/compiler/rustc_mir_build/src/build/matches/test.rs
+++ b/compiler/rustc_mir_build/src/build/matches/test.rs
@@ -380,18 +380,19 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         );
     }
 
-    /// Compare two `&T` values using `<T as std::compare::PartialEq>::eq`
+    /// Compare two values using `<T as std::compare::PartialEq>::eq`.
+    /// If the values are already references, just call it directly, otherwise
+    /// take a reference to the values first and then call it.
     fn non_scalar_compare(
         &mut self,
         block: BasicBlock,
         make_target_blocks: impl FnOnce(&mut Self) -> Vec<BasicBlock>,
         source_info: SourceInfo,
         value: ConstantKind<'tcx>,
-        place: Place<'tcx>,
+        mut val: Place<'tcx>,
         mut ty: Ty<'tcx>,
     ) {
         let mut expect = self.literal_operand(source_info.span, value);
-        let mut val = Operand::Copy(place);
 
         // If we're using `b"..."` as a pattern, we need to insert an
         // unsizing coercion, as the byte string has the type `&[u8; N]`.
@@ -421,9 +422,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                         block,
                         source_info,
                         temp,
-                        Rvalue::Cast(CastKind::Pointer(PointerCast::Unsize), val, ty),
+                        Rvalue::Cast(
+                            CastKind::Pointer(PointerCast::Unsize),
+                            Operand::Copy(val),
+                            ty,
+                        ),
                     );
-                    val = Operand::Move(temp);
+                    val = temp;
                 }
                 if opt_ref_test_ty.is_some() {
                     let slice = self.temp(ty, source_info.span);
@@ -438,12 +443,36 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             }
         }
 
-        let ty::Ref(_, deref_ty, _) = *ty.kind() else {
-            bug!("non_scalar_compare called on non-reference type: {}", ty);
-        };
+        match *ty.kind() {
+            ty::Ref(_, deref_ty, _) => ty = deref_ty,
+            _ => {
+                // non_scalar_compare called on non-reference type
+                let temp = self.temp(ty, source_info.span);
+                self.cfg.push_assign(block, source_info, temp, Rvalue::Use(expect));
+                let ref_ty = self.tcx.mk_imm_ref(self.tcx.lifetimes.re_erased, ty);
+                let ref_temp = self.temp(ref_ty, source_info.span);
+
+                self.cfg.push_assign(
+                    block,
+                    source_info,
+                    ref_temp,
+                    Rvalue::Ref(self.tcx.lifetimes.re_erased, BorrowKind::Shared, temp),
+                );
+                expect = Operand::Move(ref_temp);
+
+                let ref_temp = self.temp(ref_ty, source_info.span);
+                self.cfg.push_assign(
+                    block,
+                    source_info,
+                    ref_temp,
+                    Rvalue::Ref(self.tcx.lifetimes.re_erased, BorrowKind::Shared, val),
+                );
+                val = ref_temp;
+            }
+        }
 
         let eq_def_id = self.tcx.require_lang_item(LangItem::PartialEq, Some(source_info.span));
-        let method = trait_method(self.tcx, eq_def_id, sym::eq, [deref_ty, deref_ty]);
+        let method = trait_method(self.tcx, eq_def_id, sym::eq, [ty, ty]);
 
         let bool_ty = self.tcx.types.bool;
         let eq_result = self.temp(bool_ty, source_info.span);
@@ -463,7 +492,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
 
                     literal: method,
                 })),
-                args: vec![val, expect],
+                args: vec![Operand::Copy(val), expect],
                 destination: eq_result,
                 target: Some(eq_block),
                 unwind: UnwindAction::Continue,
diff --git a/compiler/rustc_mir_build/src/build/mod.rs b/compiler/rustc_mir_build/src/build/mod.rs
index 20d381eddb1..4e3e98b56e7 100644
--- a/compiler/rustc_mir_build/src/build/mod.rs
+++ b/compiler/rustc_mir_build/src/build/mod.rs
@@ -798,6 +798,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 };
                 self.var_debug_info.push(VarDebugInfo {
                     name,
+                    references: 0,
                     source_info: SourceInfo::outermost(captured_place.var_ident.span),
                     value: VarDebugInfoContents::Place(use_place),
                     argument_index: None,
@@ -828,6 +829,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 self.var_debug_info.push(VarDebugInfo {
                     name,
                     source_info,
+                    references: 0,
                     value: VarDebugInfoContents::Place(arg_local.into()),
                     argument_index: Some(argument_index as u16 + 1),
                 });
diff --git a/compiler/rustc_mir_build/src/build/scope.rs b/compiler/rustc_mir_build/src/build/scope.rs
index 56c87c402fe..b01b6fbf222 100644
--- a/compiler/rustc_mir_build/src/build/scope.rs
+++ b/compiler/rustc_mir_build/src/build/scope.rs
@@ -644,24 +644,27 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             }
         };
 
-        if let Some(destination) = destination {
-            if let Some(value) = value {
+        match (destination, value) {
+            (Some(destination), Some(value)) => {
                 debug!("stmt_expr Break val block_context.push(SubExpr)");
                 self.block_context.push(BlockFrame::SubExpr);
                 unpack!(block = self.expr_into_dest(destination, block, value));
                 self.block_context.pop();
-            } else {
+            }
+            (Some(destination), None) => {
                 self.cfg.push_assign_unit(block, source_info, destination, self.tcx)
             }
-        } else {
-            assert!(value.is_none(), "`return` and `break` should have a destination");
-            if self.tcx.sess.instrument_coverage() {
+            (None, Some(_)) => {
+                panic!("`return`, `become` and `break` with value and must have a destination")
+            }
+            (None, None) if self.tcx.sess.instrument_coverage() => {
                 // Unlike `break` and `return`, which push an `Assign` statement to MIR, from which
                 // a Coverage code region can be generated, `continue` needs no `Assign`; but
                 // without one, the `InstrumentCoverage` MIR pass cannot generate a code region for
                 // `continue`. Coverage will be missing unless we add a dummy `Assign` to MIR.
                 self.add_dummy_assignment(span, block, source_info);
             }
+            (None, None) => {}
         }
 
         let region_scope = self.scopes.breakable_scopes[break_index].region_scope;
@@ -671,12 +674,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         } else {
             self.scopes.breakable_scopes[break_index].continue_drops.as_mut().unwrap()
         };
-        let mut drop_idx = ROOT_NODE;
-        for scope in &self.scopes.scopes[scope_index + 1..] {
-            for drop in &scope.drops {
-                drop_idx = drops.add_drop(*drop, drop_idx);
-            }
-        }
+
+        let drop_idx = self.scopes.scopes[scope_index + 1..]
+            .iter()
+            .flat_map(|scope| &scope.drops)
+            .fold(ROOT_NODE, |drop_idx, &drop| drops.add_drop(drop, drop_idx));
+
         drops.add_entry(block, drop_idx);
 
         // `build_drop_trees` doesn't have access to our source_info, so we
diff --git a/compiler/rustc_mir_build/src/lib.rs b/compiler/rustc_mir_build/src/lib.rs
index 2765a107cf0..c964e62c9d0 100644
--- a/compiler/rustc_mir_build/src/lib.rs
+++ b/compiler/rustc_mir_build/src/lib.rs
@@ -22,7 +22,7 @@ mod errors;
 mod lints;
 pub mod thir;
 
-use rustc_middle::ty::query::Providers;
+use rustc_middle::query::Providers;
 
 use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage};
 use rustc_fluent_macro::fluent_messages;
diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs
index f46eb5a0ce1..c8648224ac1 100644
--- a/compiler/rustc_mir_build/src/thir/cx/expr.rs
+++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs
@@ -130,6 +130,7 @@ impl<'tcx> Cx<'tcx> {
                 ExprKind::Pointer { cast: PointerCast::Unsize, source: self.thir.exprs.push(expr) }
             }
             Adjust::Pointer(cast) => ExprKind::Pointer { cast, source: self.thir.exprs.push(expr) },
+            Adjust::NeverToAny if adjustment.target.is_never() => return expr,
             Adjust::NeverToAny => ExprKind::NeverToAny { source: self.thir.exprs.push(expr) },
             Adjust::Deref(None) => {
                 adjust_span(&mut expr);
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 c73f8284ca5..b243f1dc8d0 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
@@ -62,21 +62,13 @@ struct ConstToPat<'tcx> {
     treat_byte_string_as_slice: bool,
 }
 
-mod fallback_to_const_ref {
-    #[derive(Debug)]
-    /// This error type signals that we encountered a non-struct-eq situation behind a reference.
-    /// We bubble this up in order to get back to the reference destructuring and make that emit
-    /// a const pattern instead of a deref pattern. This allows us to simply call `PartialEq::eq`
-    /// on such patterns (since that function takes a reference) and not have to jump through any
-    /// hoops to get a reference to the value.
-    pub(super) struct FallbackToConstRef(());
-
-    pub(super) fn fallback_to_const_ref(c2p: &super::ConstToPat<'_>) -> FallbackToConstRef {
-        assert!(c2p.behind_reference.get());
-        FallbackToConstRef(())
-    }
-}
-use fallback_to_const_ref::{fallback_to_const_ref, FallbackToConstRef};
+/// This error type signals that we encountered a non-struct-eq situation.
+/// We bubble this up in order to get back to the reference destructuring and make that emit
+/// a const pattern instead of a deref pattern. This allows us to simply call `PartialEq::eq`
+/// on such patterns (since that function takes a reference) and not have to jump through any
+/// hoops to get a reference to the value.
+#[derive(Debug)]
+struct FallbackToConstRef;
 
 impl<'tcx> ConstToPat<'tcx> {
     fn new(
@@ -236,13 +228,13 @@ impl<'tcx> ConstToPat<'tcx> {
 
         let kind = match cv.ty().kind() {
             ty::Float(_) => {
-                    tcx.emit_spanned_lint(
-                        lint::builtin::ILLEGAL_FLOATING_POINT_LITERAL_PATTERN,
-                        id,
-                        span,
-                        FloatPattern,
-                    );
-                PatKind::Constant { value: cv }
+                tcx.emit_spanned_lint(
+                    lint::builtin::ILLEGAL_FLOATING_POINT_LITERAL_PATTERN,
+                    id,
+                    span,
+                    FloatPattern,
+                );
+                return Err(FallbackToConstRef);
             }
             ty::Adt(adt_def, _) if adt_def.is_union() => {
                 // Matching on union fields is unsafe, we can't hide it in constants
@@ -289,7 +281,7 @@ impl<'tcx> ConstToPat<'tcx> {
                 // Since we are behind a reference, we can just bubble the error up so we get a
                 // constant at reference type, making it easy to let the fallback call
                 // `PartialEq::eq` on it.
-                return Err(fallback_to_const_ref(self));
+                return Err(FallbackToConstRef);
             }
             ty::Adt(adt_def, _) if !self.type_marked_structural(cv.ty()) => {
                 debug!(
@@ -393,11 +385,11 @@ impl<'tcx> ConstToPat<'tcx> {
                     self.behind_reference.set(old);
                     val
                 }
-                // Backwards compatibility hack: support references to non-structural types.
-                // We'll lower
-                // this pattern to a `PartialEq::eq` comparison and `PartialEq::eq` takes a
-                // reference. This makes the rest of the matching logic simpler as it doesn't have
-                // to figure out how to get a reference again.
+                // Backwards compatibility hack: support references to non-structural types,
+                // but hard error if we aren't behind a double reference. We could just use
+                // the fallback code path below, but that would allow *more* of this fishy
+                // code to compile, as then it only goes through the future incompat lint
+                // instead of a hard error.
                 ty::Adt(_, _) if !self.type_marked_structural(*pointee_ty) => {
                     if self.behind_reference.get() {
                         if !self.saw_const_match_error.get()
@@ -411,7 +403,7 @@ impl<'tcx> ConstToPat<'tcx> {
                                 IndirectStructuralMatch { non_sm_ty: *pointee_ty },
                             );
                         }
-                        PatKind::Constant { value: cv }
+                        return Err(FallbackToConstRef);
                     } else {
                         if !self.saw_const_match_error.get() {
                             self.saw_const_match_error.set(true);
@@ -435,16 +427,9 @@ impl<'tcx> ConstToPat<'tcx> {
                         PatKind::Wild
                     } else {
                         let old = self.behind_reference.replace(true);
-                        // In case there are structural-match violations somewhere in this subpattern,
-                        // we fall back to a const pattern. If we do not do this, we may end up with
-                        // a !structural-match constant that is not of reference type, which makes it
-                        // very hard to invoke `PartialEq::eq` on it as a fallback.
-                        let val = match self.recur(tcx.deref_mir_constant(self.param_env.and(cv)), false) {
-                            Ok(subpattern) => PatKind::Deref { subpattern },
-                            Err(_) => PatKind::Constant { value: cv },
-                        };
+                        let subpattern = self.recur(tcx.deref_mir_constant(self.param_env.and(cv)), false)?;
                         self.behind_reference.set(old);
-                        val
+                        PatKind::Deref { subpattern }
                     }
                 }
             },
@@ -452,7 +437,7 @@ impl<'tcx> ConstToPat<'tcx> {
                 PatKind::Constant { value: cv }
             }
             ty::RawPtr(pointee) if pointee.ty.is_sized(tcx, param_env) => {
-                PatKind::Constant { value: cv }
+                return Err(FallbackToConstRef);
             }
             // FIXME: these can have very surprising behaviour where optimization levels or other
             // compilation choices change the runtime behaviour of the match.
@@ -469,7 +454,7 @@ impl<'tcx> ConstToPat<'tcx> {
                         PointerPattern
                     );
                 }
-                PatKind::Constant { value: cv }
+                return Err(FallbackToConstRef);
             }
             _ => {
                 self.saw_const_match_error.set(true);
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 9af13781312..6a77146138b 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs
@@ -844,8 +844,8 @@ impl<'tcx> Constructor<'tcx> {
     }
 
     /// Faster version of `is_covered_by` when applied to many constructors. `used_ctors` is
-    /// assumed to be built from `matrix.head_ctors()` with wildcards filtered out, and `self` is
-    /// assumed to have been split from a wildcard.
+    /// assumed to be built from `matrix.head_ctors()` with wildcards and opaques filtered out,
+    /// and `self` is assumed to have been split from a wildcard.
     fn is_covered_by_any<'p>(
         &self,
         pcx: &PatCtxt<'_, 'p, 'tcx>,
@@ -894,7 +894,7 @@ impl<'tcx> Constructor<'tcx> {
 /// in `to_ctors`: in some cases we only return `Missing`.
 #[derive(Debug)]
 pub(super) struct SplitWildcard<'tcx> {
-    /// Constructors seen in the matrix.
+    /// Constructors (other than wildcards and opaques) seen in the matrix.
     matrix_ctors: Vec<Constructor<'tcx>>,
     /// All the constructors for this type
     all_ctors: SmallVec<[Constructor<'tcx>; 1]>,
@@ -1037,7 +1037,7 @@ impl<'tcx> SplitWildcard<'tcx> {
         // Since `all_ctors` never contains wildcards, this won't recurse further.
         self.all_ctors =
             self.all_ctors.iter().flat_map(|ctor| ctor.split(pcx, ctors.clone())).collect();
-        self.matrix_ctors = ctors.filter(|c| !c.is_wildcard()).cloned().collect();
+        self.matrix_ctors = ctors.filter(|c| !matches!(c, Wildcard | Opaque)).cloned().collect();
     }
 
     /// Whether there are any value constructors for this type that are not present in the matrix.
diff --git a/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs b/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs
index f229b10c447..e5b63506906 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs
@@ -288,6 +288,22 @@
 //!
 //! The details are not necessary to understand this file, so we explain them in
 //! [`super::deconstruct_pat`]. Splitting is done by the [`Constructor::split`] function.
+//!
+//! # Constants in patterns
+//!
+//! There are two kinds of constants in patterns:
+//!
+//! * literals (`1`, `true`, `"foo"`)
+//! * named or inline consts (`FOO`, `const { 5 + 6 }`)
+//!
+//! The latter are converted into other patterns with literals at the leaves. For example
+//! `const_to_pat(const { [1, 2, 3] })` becomes an `Array(vec![Const(1), Const(2), Const(3)])`
+//! pattern. This gets problematic when comparing the constant via `==` would behave differently
+//! from matching on the constant converted to a pattern. Situations like that can occur, when
+//! the user implements `PartialEq` manually, and thus could make `==` behave arbitrarily different.
+//! In order to honor the `==` implementation, constants of types that implement `PartialEq` manually
+//! stay as a full constant and become an `Opaque` pattern. These `Opaque` patterns do not participate
+//! in exhaustiveness, specialization or overlap checking.
 
 use self::ArmType::*;
 use self::Usefulness::*;
diff --git a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs
index 2e68c794356..18895072c3b 100644
--- a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs
+++ b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs
@@ -276,6 +276,7 @@ where
                 assert_eq!(self.elaborator.param_env().reveal(), Reveal::All);
                 let field_ty =
                     tcx.normalize_erasing_regions(self.elaborator.param_env(), f.ty(tcx, substs));
+
                 (tcx.mk_place_field(base_place, field, field_ty), subpath)
             })
             .collect()
diff --git a/compiler/rustc_mir_transform/src/check_unsafety.rs b/compiler/rustc_mir_transform/src/check_unsafety.rs
index bdb4f20da10..069514d8a3b 100644
--- a/compiler/rustc_mir_transform/src/check_unsafety.rs
+++ b/compiler/rustc_mir_transform/src/check_unsafety.rs
@@ -7,7 +7,7 @@ use rustc_hir::intravisit;
 use rustc_hir::{BlockCheckMode, ExprKind, Node};
 use rustc_middle::mir::visit::{MutatingUseContext, PlaceContext, Visitor};
 use rustc_middle::mir::*;
-use rustc_middle::ty::query::Providers;
+use rustc_middle::query::Providers;
 use rustc_middle::ty::{self, TyCtxt};
 use rustc_session::lint::builtin::{UNSAFE_OP_IN_UNSAFE_FN, UNUSED_UNSAFE};
 use rustc_session::lint::Level;
diff --git a/compiler/rustc_mir_transform/src/copy_prop.rs b/compiler/rustc_mir_transform/src/copy_prop.rs
index c565d6f13b1..319f3a79705 100644
--- a/compiler/rustc_mir_transform/src/copy_prop.rs
+++ b/compiler/rustc_mir_transform/src/copy_prop.rs
@@ -162,20 +162,22 @@ impl<'tcx> MutVisitor<'tcx> for Replacer<'_, 'tcx> {
     }
 
     fn visit_statement(&mut self, stmt: &mut Statement<'tcx>, loc: Location) {
-        match stmt.kind {
-            // When removing storage statements, we need to remove both (#107511).
-            StatementKind::StorageLive(l) | StatementKind::StorageDead(l)
-                if self.storage_to_remove.contains(l) =>
-            {
-                stmt.make_nop()
-            }
-            StatementKind::Assign(box (ref place, ref mut rvalue))
-                if place.as_local().is_some() =>
-            {
-                // Do not replace assignments.
-                self.visit_rvalue(rvalue, loc)
-            }
-            _ => self.super_statement(stmt, loc),
+        // When removing storage statements, we need to remove both (#107511).
+        if let StatementKind::StorageLive(l) | StatementKind::StorageDead(l) = stmt.kind
+            && self.storage_to_remove.contains(l)
+        {
+            stmt.make_nop();
+            return
+        }
+
+        self.super_statement(stmt, loc);
+
+        // Do not leave tautological assignments around.
+        if let StatementKind::Assign(box (lhs, ref rhs)) = stmt.kind
+            && let Rvalue::Use(Operand::Copy(rhs) | Operand::Move(rhs)) | Rvalue::CopyForDeref(rhs) = *rhs
+            && lhs == rhs
+        {
+            stmt.make_nop();
         }
     }
 }
diff --git a/compiler/rustc_mir_transform/src/coverage/debug.rs b/compiler/rustc_mir_transform/src/coverage/debug.rs
index e554c470646..35e4c24dc46 100644
--- a/compiler/rustc_mir_transform/src/coverage/debug.rs
+++ b/compiler/rustc_mir_transform/src/coverage/debug.rs
@@ -118,7 +118,7 @@ use rustc_middle::mir::spanview::{self, SpanViewable};
 
 use rustc_data_structures::fx::FxHashMap;
 use rustc_middle::mir::coverage::*;
-use rustc_middle::mir::{self, BasicBlock, TerminatorKind};
+use rustc_middle::mir::{self, BasicBlock};
 use rustc_middle::ty::TyCtxt;
 use rustc_span::Span;
 
@@ -796,7 +796,7 @@ fn bcb_to_string_sections<'tcx>(
     }
     let non_term_blocks = bcb_data.basic_blocks[0..len - 1]
         .iter()
-        .map(|&bb| format!("{:?}: {}", bb, term_type(&mir_body[bb].terminator().kind)))
+        .map(|&bb| format!("{:?}: {}", bb, mir_body[bb].terminator().kind.name()))
         .collect::<Vec<_>>();
     if non_term_blocks.len() > 0 {
         sections.push(non_term_blocks.join("\n"));
@@ -804,28 +804,7 @@ fn bcb_to_string_sections<'tcx>(
     sections.push(format!(
         "{:?}: {}",
         bcb_data.basic_blocks.last().unwrap(),
-        term_type(&bcb_data.terminator(mir_body).kind)
+        bcb_data.terminator(mir_body).kind.name(),
     ));
     sections
 }
-
-/// Returns a simple string representation of a `TerminatorKind` variant, independent of any
-/// values it might hold.
-pub(super) fn term_type(kind: &TerminatorKind<'_>) -> &'static str {
-    match kind {
-        TerminatorKind::Goto { .. } => "Goto",
-        TerminatorKind::SwitchInt { .. } => "SwitchInt",
-        TerminatorKind::Resume => "Resume",
-        TerminatorKind::Terminate => "Terminate",
-        TerminatorKind::Return => "Return",
-        TerminatorKind::Unreachable => "Unreachable",
-        TerminatorKind::Drop { .. } => "Drop",
-        TerminatorKind::Call { .. } => "Call",
-        TerminatorKind::Assert { .. } => "Assert",
-        TerminatorKind::Yield { .. } => "Yield",
-        TerminatorKind::GeneratorDrop => "GeneratorDrop",
-        TerminatorKind::FalseEdge { .. } => "FalseEdge",
-        TerminatorKind::FalseUnwind { .. } => "FalseUnwind",
-        TerminatorKind::InlineAsm { .. } => "InlineAsm",
-    }
-}
diff --git a/compiler/rustc_mir_transform/src/coverage/query.rs b/compiler/rustc_mir_transform/src/coverage/query.rs
index bf01b45eb40..74b4b4a07c5 100644
--- a/compiler/rustc_mir_transform/src/coverage/query.rs
+++ b/compiler/rustc_mir_transform/src/coverage/query.rs
@@ -2,7 +2,7 @@ use super::*;
 
 use rustc_middle::mir::coverage::*;
 use rustc_middle::mir::{self, Body, Coverage, CoverageInfo};
-use rustc_middle::ty::query::Providers;
+use rustc_middle::query::Providers;
 use rustc_middle::ty::{self, TyCtxt};
 use rustc_span::def_id::DefId;
 
diff --git a/compiler/rustc_mir_transform/src/coverage/spans.rs b/compiler/rustc_mir_transform/src/coverage/spans.rs
index 287ae217087..14937912cc5 100644
--- a/compiler/rustc_mir_transform/src/coverage/spans.rs
+++ b/compiler/rustc_mir_transform/src/coverage/spans.rs
@@ -1,4 +1,3 @@
-use super::debug::term_type;
 use super::graph::{BasicCoverageBlock, BasicCoverageBlockData, CoverageGraph, START_BCB};
 
 use itertools::Itertools;
@@ -40,7 +39,7 @@ impl CoverageStatement {
                     "{}: @{}.{}: {:?}",
                     source_range_no_file(tcx, span),
                     bb.index(),
-                    term_type(&term.kind),
+                    term.kind.name(),
                     term.kind
                 )
             }
diff --git a/compiler/rustc_mir_transform/src/coverage/tests.rs b/compiler/rustc_mir_transform/src/coverage/tests.rs
index 83a335197b3..90b58933df7 100644
--- a/compiler/rustc_mir_transform/src/coverage/tests.rs
+++ b/compiler/rustc_mir_transform/src/coverage/tests.rs
@@ -25,7 +25,6 @@
 //! to: `rustc_span::create_default_session_globals_then(|| { test_here(); })`.
 
 use super::counters;
-use super::debug;
 use super::graph;
 use super::spans;
 
@@ -188,12 +187,12 @@ fn debug_basic_blocks(mir_body: &Body<'_>) -> String {
                     | TerminatorKind::Goto { target }
                     | TerminatorKind::InlineAsm { destination: Some(target), .. }
                     | TerminatorKind::Yield { resume: target, .. } => {
-                        format!("{}{:?}:{} -> {:?}", sp, bb, debug::term_type(kind), target)
+                        format!("{}{:?}:{} -> {:?}", sp, bb, kind.name(), target)
                     }
                     TerminatorKind::SwitchInt { targets, .. } => {
-                        format!("{}{:?}:{} -> {:?}", sp, bb, debug::term_type(kind), targets)
+                        format!("{}{:?}:{} -> {:?}", sp, bb, kind.name(), targets)
                     }
-                    _ => format!("{}{:?}:{}", sp, bb, debug::term_type(kind)),
+                    _ => format!("{}{:?}:{}", sp, bb, kind.name()),
                 }
             })
             .collect::<Vec<_>>()
@@ -215,7 +214,7 @@ fn print_mir_graphviz(name: &str, mir_body: &Body<'_>) {
                         "    {:?} [label=\"{:?}: {}\"];\n{}",
                         bb,
                         bb,
-                        debug::term_type(&data.terminator().kind),
+                        data.terminator().kind.name(),
                         mir_body
                             .basic_blocks
                             .successors(bb)
@@ -244,7 +243,7 @@ fn print_coverage_graphviz(
                         "    {:?} [label=\"{:?}: {}\"];\n{}",
                         bcb,
                         bcb,
-                        debug::term_type(&bcb_data.terminator(mir_body).kind),
+                        bcb_data.terminator(mir_body).kind.name(),
                         basic_coverage_blocks
                             .successors(bcb)
                             .map(|successor| { format!("    {:?} -> {:?};", bcb, successor) })
diff --git a/compiler/rustc_mir_transform/src/deduce_param_attrs.rs b/compiler/rustc_mir_transform/src/deduce_param_attrs.rs
index 8ee08c5be34..a133c9d4782 100644
--- a/compiler/rustc_mir_transform/src/deduce_param_attrs.rs
+++ b/compiler/rustc_mir_transform/src/deduce_param_attrs.rs
@@ -8,7 +8,7 @@
 use rustc_hir::def_id::LocalDefId;
 use rustc_index::bit_set::BitSet;
 use rustc_middle::mir::visit::{NonMutatingUseContext, PlaceContext, Visitor};
-use rustc_middle::mir::{Body, Local, Location, Operand, Terminator, TerminatorKind, RETURN_PLACE};
+use rustc_middle::mir::{Body, Location, Operand, Place, Terminator, TerminatorKind, RETURN_PLACE};
 use rustc_middle::ty::{self, DeducedParamAttrs, Ty, TyCtxt};
 use rustc_session::config::OptLevel;
 
@@ -29,31 +29,31 @@ impl DeduceReadOnly {
 }
 
 impl<'tcx> Visitor<'tcx> for DeduceReadOnly {
-    fn visit_local(&mut self, local: Local, mut context: PlaceContext, _: Location) {
+    fn visit_place(&mut self, place: &Place<'tcx>, context: PlaceContext, _location: Location) {
         // We're only interested in arguments.
-        if local == RETURN_PLACE || local.index() > self.mutable_args.domain_size() {
+        if place.local == RETURN_PLACE || place.local.index() > self.mutable_args.domain_size() {
             return;
         }
 
-        // Replace place contexts that are moves with copies. This is safe in all cases except
-        // function argument position, which we already handled in `visit_terminator()` by using the
-        // ArgumentChecker. See the comment in that method for more details.
-        //
-        // In the future, we might want to move this out into a separate pass, but for now let's
-        // just do it on the fly because that's faster.
-        if matches!(context, PlaceContext::NonMutatingUse(NonMutatingUseContext::Move)) {
-            context = PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy);
-        }
-
-        match context {
-            PlaceContext::MutatingUse(..)
-            | PlaceContext::NonMutatingUse(NonMutatingUseContext::Move) => {
+        let mark_as_mutable = match context {
+            PlaceContext::MutatingUse(..) => {
                 // This is a mutation, so mark it as such.
-                self.mutable_args.insert(local.index() - 1);
+                true
+            }
+            PlaceContext::NonMutatingUse(NonMutatingUseContext::AddressOf) => {
+                // Whether mutating though a `&raw const` is allowed is still undecided, so we
+                // disable any sketchy `readonly` optimizations for now.
+                // But we only need to do this if the pointer would point into the argument.
+                !place.is_indirect()
             }
             PlaceContext::NonMutatingUse(..) | PlaceContext::NonUse(..) => {
                 // Not mutating, so it's fine.
+                false
             }
+        };
+
+        if mark_as_mutable {
+            self.mutable_args.insert(place.local.index() - 1);
         }
     }
 
diff --git a/compiler/rustc_mir_transform/src/dump_mir.rs b/compiler/rustc_mir_transform/src/dump_mir.rs
index 594cbd8977e..746e3d9652d 100644
--- a/compiler/rustc_mir_transform/src/dump_mir.rs
+++ b/compiler/rustc_mir_transform/src/dump_mir.rs
@@ -12,7 +12,7 @@ use rustc_session::config::OutputType;
 pub struct Marker(pub &'static str);
 
 impl<'tcx> MirPass<'tcx> for Marker {
-    fn name(&self) -> &str {
+    fn name(&self) -> &'static str {
         self.0
     }
 
diff --git a/compiler/rustc_mir_transform/src/ffi_unwind_calls.rs b/compiler/rustc_mir_transform/src/ffi_unwind_calls.rs
index ac1de989a72..58cc161ddcc 100644
--- a/compiler/rustc_mir_transform/src/ffi_unwind_calls.rs
+++ b/compiler/rustc_mir_transform/src/ffi_unwind_calls.rs
@@ -1,8 +1,8 @@
 use rustc_hir::def_id::{LocalDefId, LOCAL_CRATE};
 use rustc_middle::mir::*;
 use rustc_middle::query::LocalCrate;
+use rustc_middle::query::Providers;
 use rustc_middle::ty::layout;
-use rustc_middle::ty::query::Providers;
 use rustc_middle::ty::{self, TyCtxt};
 use rustc_session::lint::builtin::FFI_UNWIND_CALLS;
 use rustc_target::spec::abi::Abi;
diff --git a/compiler/rustc_mir_transform/src/generator.rs b/compiler/rustc_mir_transform/src/generator.rs
index c9144729145..891e446942e 100644
--- a/compiler/rustc_mir_transform/src/generator.rs
+++ b/compiler/rustc_mir_transform/src/generator.rs
@@ -1397,7 +1397,7 @@ fn create_cases<'tcx>(
 pub(crate) fn mir_generator_witnesses<'tcx>(
     tcx: TyCtxt<'tcx>,
     def_id: LocalDefId,
-) -> GeneratorLayout<'tcx> {
+) -> Option<GeneratorLayout<'tcx>> {
     assert!(tcx.sess.opts.unstable_opts.drop_tracking_mir);
 
     let (body, _) = tcx.mir_promoted(def_id);
@@ -1410,6 +1410,7 @@ pub(crate) fn mir_generator_witnesses<'tcx>(
     // Get the interior types and substs which typeck computed
     let movable = match *gen_ty.kind() {
         ty::Generator(_, _, movability) => movability == hir::Movability::Movable,
+        ty::Error(_) => return None,
         _ => span_bug!(body.span, "unexpected generator type {}", gen_ty),
     };
 
@@ -1425,7 +1426,7 @@ pub(crate) fn mir_generator_witnesses<'tcx>(
 
     check_suspend_tys(tcx, &generator_layout, &body);
 
-    generator_layout
+    Some(generator_layout)
 }
 
 impl<'tcx> MirPass<'tcx> for StateTransform {
diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs
index ece20d8d3e6..6c2e22a70b9 100644
--- a/compiler/rustc_mir_transform/src/inline.rs
+++ b/compiler/rustc_mir_transform/src/inline.rs
@@ -7,6 +7,7 @@ use rustc_index::Idx;
 use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs};
 use rustc_middle::mir::visit::*;
 use rustc_middle::mir::*;
+use rustc_middle::ty::TypeVisitableExt;
 use rustc_middle::ty::{self, Instance, InstanceDef, ParamEnv, Ty, TyCtxt};
 use rustc_session::config::OptLevel;
 use rustc_span::{hygiene::ExpnKind, ExpnData, LocalExpnId, Span};
@@ -167,8 +168,20 @@ impl<'tcx> Inliner<'tcx> {
     ) -> Result<std::ops::Range<BasicBlock>, &'static str> {
         let callee_attrs = self.tcx.codegen_fn_attrs(callsite.callee.def_id());
         self.check_codegen_attributes(callsite, callee_attrs)?;
+
+        let terminator = caller_body[callsite.block].terminator.as_ref().unwrap();
+        let TerminatorKind::Call { args, destination, .. } = &terminator.kind else { bug!() };
+        let destination_ty = destination.ty(&caller_body.local_decls, self.tcx).ty;
+        for arg in args {
+            if !arg.ty(&caller_body.local_decls, self.tcx).is_sized(self.tcx, self.param_env) {
+                // We do not allow inlining functions with unsized params. Inlining these functions
+                // could create unsized locals, which are unsound and being phased out.
+                return Err("Call has unsized argument");
+            }
+        }
+
         self.check_mir_is_available(caller_body, &callsite.callee)?;
-        let callee_body = self.tcx.instance_mir(callsite.callee.def);
+        let callee_body = try_instance_mir(self.tcx, callsite.callee.def)?;
         self.check_mir_body(callsite, callee_body, callee_attrs)?;
 
         if !self.tcx.consider_optimizing(|| {
@@ -188,9 +201,6 @@ impl<'tcx> Inliner<'tcx> {
         // Check call signature compatibility.
         // Normally, this shouldn't be required, but trait normalization failure can create a
         // validation ICE.
-        let terminator = caller_body[callsite.block].terminator.as_ref().unwrap();
-        let TerminatorKind::Call { args, destination, .. } = &terminator.kind else { bug!() };
-        let destination_ty = destination.ty(&caller_body.local_decls, self.tcx).ty;
         let output_type = callee_body.return_ty();
         if !util::is_subtype(self.tcx, self.param_env, output_type, destination_ty) {
             trace!(?output_type, ?destination_ty);
@@ -1128,3 +1138,27 @@ impl<'tcx> MutVisitor<'tcx> for Integrator<'_, 'tcx> {
         }
     }
 }
+
+#[instrument(skip(tcx), level = "debug")]
+fn try_instance_mir<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    instance: InstanceDef<'tcx>,
+) -> Result<&'tcx Body<'tcx>, &'static str> {
+    match instance {
+        ty::InstanceDef::DropGlue(_, Some(ty)) => match ty.kind() {
+            ty::Adt(def, substs) => {
+                let fields = def.all_fields();
+                for field in fields {
+                    let field_ty = field.ty(tcx, substs);
+                    if field_ty.has_param() && field_ty.has_projections() {
+                        return Err("cannot build drop shim for polymorphic type");
+                    }
+                }
+
+                Ok(tcx.instance_mir(instance))
+            }
+            _ => Ok(tcx.instance_mir(instance)),
+        },
+        _ => Ok(tcx.instance_mir(instance)),
+    }
+}
diff --git a/compiler/rustc_mir_transform/src/instsimplify.rs b/compiler/rustc_mir_transform/src/instsimplify.rs
index 6bff535586a..e4dc617620e 100644
--- a/compiler/rustc_mir_transform/src/instsimplify.rs
+++ b/compiler/rustc_mir_transform/src/instsimplify.rs
@@ -5,7 +5,6 @@ use crate::MirPass;
 use rustc_hir::Mutability;
 use rustc_middle::mir::*;
 use rustc_middle::ty::layout::ValidityRequirement;
-use rustc_middle::ty::util::IntTypeExt;
 use rustc_middle::ty::{self, ParamEnv, SubstsRef, Ty, TyCtxt};
 use rustc_span::symbol::Symbol;
 use rustc_target::abi::FieldIdx;
@@ -163,18 +162,6 @@ impl<'tcx> InstSimplifyContext<'tcx, '_> {
                     return;
                 }
 
-                // Transmuting a fieldless enum to its repr is a discriminant read
-                if let ty::Adt(adt_def, ..) = operand_ty.kind()
-                    && adt_def.is_enum()
-                    && adt_def.is_payloadfree()
-                    && let Some(place) = operand.place()
-                    && let Some(repr_int) = adt_def.repr().int
-                    && repr_int.to_ty(self.tcx) == *cast_ty
-                {
-                    *rvalue = Rvalue::Discriminant(place);
-                    return;
-                }
-
                 // Transmuting a transparent struct/union to a field's type is a projection
                 if let ty::Adt(adt_def, substs) = operand_ty.kind()
                     && adt_def.repr().transparent()
diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs
index 277237a5515..65864dc016f 100644
--- a/compiler/rustc_mir_transform/src/lib.rs
+++ b/compiler/rustc_mir_transform/src/lib.rs
@@ -34,7 +34,7 @@ use rustc_middle::mir::{
     MirPhase, Operand, Place, ProjectionElem, Promoted, RuntimePhase, Rvalue, SourceInfo,
     Statement, StatementKind, TerminatorKind, START_BLOCK,
 };
-use rustc_middle::ty::query::Providers;
+use rustc_middle::query::Providers;
 use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt};
 use rustc_span::sym;
 use rustc_trait_selection::traits;
diff --git a/compiler/rustc_mir_transform/src/pass_manager.rs b/compiler/rustc_mir_transform/src/pass_manager.rs
index e1b65823a5a..710eed3ed38 100644
--- a/compiler/rustc_mir_transform/src/pass_manager.rs
+++ b/compiler/rustc_mir_transform/src/pass_manager.rs
@@ -6,7 +6,7 @@ use crate::{validate, MirPass};
 
 /// Just like `MirPass`, except it cannot mutate `Body`.
 pub trait MirLint<'tcx> {
-    fn name(&self) -> &str {
+    fn name(&self) -> &'static str {
         let name = std::any::type_name::<Self>();
         if let Some((_, tail)) = name.rsplit_once(':') { tail } else { name }
     }
@@ -26,7 +26,7 @@ impl<'tcx, T> MirPass<'tcx> for Lint<T>
 where
     T: MirLint<'tcx>,
 {
-    fn name(&self) -> &str {
+    fn name(&self) -> &'static str {
         self.0.name()
     }
 
@@ -49,7 +49,7 @@ impl<'tcx, T> MirPass<'tcx> for WithMinOptLevel<T>
 where
     T: MirPass<'tcx>,
 {
-    fn name(&self) -> &str {
+    fn name(&self) -> &'static str {
         self.1.name()
     }
 
@@ -121,7 +121,7 @@ fn run_passes_inner<'tcx>(
                 validate_body(tcx, body, format!("before pass {}", name));
             }
 
-            pass.run_pass(tcx, body);
+            tcx.sess.time(name, || pass.run_pass(tcx, body));
 
             if dump_enabled {
                 dump_mir_for_pass(tcx, body, &name, true);
diff --git a/compiler/rustc_mir_transform/src/ref_prop.rs b/compiler/rustc_mir_transform/src/ref_prop.rs
index d1bc9ee9153..bbd9f76ba5c 100644
--- a/compiler/rustc_mir_transform/src/ref_prop.rs
+++ b/compiler/rustc_mir_transform/src/ref_prop.rs
@@ -77,11 +77,11 @@ impl<'tcx> MirPass<'tcx> for ReferencePropagation {
     #[instrument(level = "trace", skip(self, tcx, body))]
     fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
         debug!(def_id = ?body.source.def_id());
-        propagate_ssa(tcx, body);
+        while propagate_ssa(tcx, body) {}
     }
 }
 
-fn propagate_ssa<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
+fn propagate_ssa<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) -> bool {
     let ssa = SsaLocals::new(body);
 
     let mut replacer = compute_replacement(tcx, body, &ssa);
@@ -94,6 +94,8 @@ fn propagate_ssa<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
     if replacer.any_replacement {
         crate::simplify::remove_unused_definitions(body);
     }
+
+    replacer.any_replacement
 }
 
 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
@@ -263,6 +265,7 @@ fn compute_replacement<'tcx>(
         targets,
         storage_to_remove,
         allowed_replacements,
+        fully_replacable_locals,
         any_replacement: false,
     };
 
@@ -343,6 +346,7 @@ struct Replacer<'tcx> {
     storage_to_remove: BitSet<Local>,
     allowed_replacements: FxHashSet<(Local, Location)>,
     any_replacement: bool,
+    fully_replacable_locals: BitSet<Local>,
 }
 
 impl<'tcx> MutVisitor<'tcx> for Replacer<'tcx> {
@@ -350,6 +354,25 @@ impl<'tcx> MutVisitor<'tcx> for Replacer<'tcx> {
         self.tcx
     }
 
+    fn visit_var_debug_info(&mut self, debuginfo: &mut VarDebugInfo<'tcx>) {
+        if let VarDebugInfoContents::Place(ref mut place) = debuginfo.value
+            && place.projection.is_empty()
+            && let Value::Pointer(target, _) = self.targets[place.local]
+            && target.projection.iter().all(|p| p.can_use_in_debuginfo())
+        {
+            if let Some((&PlaceElem::Deref, rest)) = target.projection.split_last() {
+                *place = Place::from(target.local).project_deeper(rest, self.tcx);
+                self.any_replacement = true;
+            } else if self.fully_replacable_locals.contains(place.local)
+                && let Some(references) = debuginfo.references.checked_add(1)
+            {
+                debuginfo.references = references;
+                *place = target;
+                self.any_replacement = true;
+            }
+        }
+    }
+
     fn visit_place(&mut self, place: &mut Place<'tcx>, ctxt: PlaceContext, loc: Location) {
         if place.projection.first() != Some(&PlaceElem::Deref) {
             return;
diff --git a/compiler/rustc_mir_transform/src/shim.rs b/compiler/rustc_mir_transform/src/shim.rs
index 19d07fab0b9..7c47d8814db 100644
--- a/compiler/rustc_mir_transform/src/shim.rs
+++ b/compiler/rustc_mir_transform/src/shim.rs
@@ -2,7 +2,7 @@ use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
 use rustc_hir::lang_items::LangItem;
 use rustc_middle::mir::*;
-use rustc_middle::ty::query::Providers;
+use rustc_middle::query::Providers;
 use rustc_middle::ty::InternalSubsts;
 use rustc_middle::ty::{self, EarlyBinder, GeneratorSubsts, Ty, TyCtxt};
 use rustc_target::abi::{FieldIdx, VariantIdx, FIRST_VARIANT};
diff --git a/compiler/rustc_mir_transform/src/simplify.rs b/compiler/rustc_mir_transform/src/simplify.rs
index 1b96df3aed5..e59219321b7 100644
--- a/compiler/rustc_mir_transform/src/simplify.rs
+++ b/compiler/rustc_mir_transform/src/simplify.rs
@@ -74,7 +74,7 @@ pub fn simplify_cfg<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
 }
 
 impl<'tcx> MirPass<'tcx> for SimplifyCfg {
-    fn name(&self) -> &str {
+    fn name(&self) -> &'static str {
         &self.name()
     }
 
diff --git a/compiler/rustc_mir_transform/src/ssa.rs b/compiler/rustc_mir_transform/src/ssa.rs
index a7b45366662..2b404efccc7 100644
--- a/compiler/rustc_mir_transform/src/ssa.rs
+++ b/compiler/rustc_mir_transform/src/ssa.rs
@@ -101,14 +101,15 @@ impl SsaLocals {
             .retain(|&local| matches!(visitor.assignments[local], Set1::One(_)));
         debug!(?visitor.assignment_order);
 
-        let copy_classes = compute_copy_classes(&mut visitor, body);
-
-        SsaLocals {
+        let mut ssa = SsaLocals {
             assignments: visitor.assignments,
             assignment_order: visitor.assignment_order,
             direct_uses: visitor.direct_uses,
-            copy_classes,
-        }
+            // This is filled by `compute_copy_classes`.
+            copy_classes: IndexVec::default(),
+        };
+        compute_copy_classes(&mut ssa, body);
+        ssa
     }
 
     pub fn num_locals(&self) -> usize {
@@ -261,49 +262,54 @@ impl<'tcx> Visitor<'tcx> for SsaVisitor {
 }
 
 #[instrument(level = "trace", skip(ssa, body))]
-fn compute_copy_classes(ssa: &mut SsaVisitor, body: &Body<'_>) -> IndexVec<Local, Local> {
+fn compute_copy_classes(ssa: &mut SsaLocals, body: &Body<'_>) {
+    let mut direct_uses = std::mem::take(&mut ssa.direct_uses);
     let mut copies = IndexVec::from_fn_n(|l| l, body.local_decls.len());
 
-    for &local in &ssa.assignment_order {
-        debug!(?local);
-
-        if local == RETURN_PLACE {
-            // `_0` is special, we cannot rename it.
-            continue;
-        }
-
-        // This is not SSA: mark that we don't know the value.
-        debug!(assignments = ?ssa.assignments[local]);
-        let Set1::One(LocationExtended::Plain(loc)) = ssa.assignments[local] else { continue };
-
-        // `loc` must point to a direct assignment to `local`.
-        let Either::Left(stmt) = body.stmt_at(loc) else { bug!() };
-        let Some((_target, rvalue)) = stmt.kind.as_assign() else { bug!() };
-        assert_eq!(_target.as_local(), Some(local));
-
+    for (local, rvalue, _) in ssa.assignments(body) {
         let (Rvalue::Use(Operand::Copy(place) | Operand::Move(place)) | Rvalue::CopyForDeref(place))
             = rvalue
         else { continue };
 
         let Some(rhs) = place.as_local() else { continue };
-        let Set1::One(_) = ssa.assignments[rhs] else { continue };
+        if !ssa.is_ssa(rhs) {
+            continue;
+        }
 
         // We visit in `assignment_order`, ie. reverse post-order, so `rhs` has been
         // visited before `local`, and we just have to copy the representing local.
-        copies[local] = copies[rhs];
-        ssa.direct_uses[rhs] -= 1;
+        let head = copies[rhs];
+
+        if local == RETURN_PLACE {
+            // `_0` is special, we cannot rename it. Instead, rename the class of `rhs` to
+            // `RETURN_PLACE`. This is only possible if the class head is a temporary, not an
+            // argument.
+            if body.local_kind(head) != LocalKind::Temp {
+                continue;
+            }
+            for h in copies.iter_mut() {
+                if *h == head {
+                    *h = RETURN_PLACE;
+                }
+            }
+        } else {
+            copies[local] = head;
+        }
+        direct_uses[rhs] -= 1;
     }
 
     debug!(?copies);
-    debug!(?ssa.direct_uses);
+    debug!(?direct_uses);
 
     // Invariant: `copies` must point to the head of an equivalence class.
     #[cfg(debug_assertions)]
     for &head in copies.iter() {
         assert_eq!(copies[head], head);
     }
+    debug_assert_eq!(copies[RETURN_PLACE], RETURN_PLACE);
 
-    copies
+    ssa.direct_uses = direct_uses;
+    ssa.copy_classes = copies;
 }
 
 #[derive(Debug)]
diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs
index 55c937b305a..35b154b7b34 100644
--- a/compiler/rustc_monomorphize/src/collector.rs
+++ b/compiler/rustc_monomorphize/src/collector.rs
@@ -185,9 +185,9 @@ use rustc_middle::mir::interpret::{ErrorHandled, GlobalAlloc, Scalar};
 use rustc_middle::mir::mono::{InstantiationMode, MonoItem};
 use rustc_middle::mir::visit::Visitor as MirVisitor;
 use rustc_middle::mir::{self, Local, Location};
+use rustc_middle::query::TyCtxtAt;
 use rustc_middle::ty::adjustment::{CustomCoerceUnsized, PointerCast};
 use rustc_middle::ty::print::with_no_trimmed_paths;
-use rustc_middle::ty::query::TyCtxtAt;
 use rustc_middle::ty::subst::{GenericArgKind, InternalSubsts};
 use rustc_middle::ty::{
     self, GenericParamDefKind, Instance, InstanceDef, Ty, TyCtxt, TypeFoldable, TypeVisitableExt,
diff --git a/compiler/rustc_monomorphize/src/lib.rs b/compiler/rustc_monomorphize/src/lib.rs
index 7253acf61e6..ecc50c3f664 100644
--- a/compiler/rustc_monomorphize/src/lib.rs
+++ b/compiler/rustc_monomorphize/src/lib.rs
@@ -12,9 +12,9 @@ extern crate rustc_middle;
 use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage};
 use rustc_fluent_macro::fluent_messages;
 use rustc_hir::lang_items::LangItem;
+use rustc_middle::query::{Providers, TyCtxtAt};
 use rustc_middle::traits;
 use rustc_middle::ty::adjustment::CustomCoerceUnsized;
-use rustc_middle::ty::query::{Providers, TyCtxtAt};
 use rustc_middle::ty::{self, Ty};
 
 mod collector;
diff --git a/compiler/rustc_monomorphize/src/partitioning/mod.rs b/compiler/rustc_monomorphize/src/partitioning/mod.rs
index 993e35c7fd2..eafe57a0c02 100644
--- a/compiler/rustc_monomorphize/src/partitioning/mod.rs
+++ b/compiler/rustc_monomorphize/src/partitioning/mod.rs
@@ -106,8 +106,8 @@ use rustc_hir::def_id::{DefIdSet, LOCAL_CRATE};
 use rustc_middle::mir;
 use rustc_middle::mir::mono::MonoItem;
 use rustc_middle::mir::mono::{CodegenUnit, Linkage};
+use rustc_middle::query::Providers;
 use rustc_middle::ty::print::with_no_trimmed_paths;
-use rustc_middle::ty::query::Providers;
 use rustc_middle::ty::TyCtxt;
 use rustc_session::config::{DumpMonoStatsFormat, SwitchWithOptPath};
 use rustc_span::symbol::Symbol;
@@ -250,13 +250,13 @@ where
         cgu.create_size_estimate(tcx);
     }
 
-    debug_dump(tcx, "INITIAL PARTITIONING:", initial_partitioning.codegen_units.iter());
+    debug_dump(tcx, "INITIAL PARTITIONING", &initial_partitioning.codegen_units);
 
     // Merge until we have at most `max_cgu_count` codegen units.
     {
         let _prof_timer = tcx.prof.generic_activity("cgu_partitioning_merge_cgus");
         partitioner.merge_codegen_units(cx, &mut initial_partitioning);
-        debug_dump(tcx, "POST MERGING:", initial_partitioning.codegen_units.iter());
+        debug_dump(tcx, "POST MERGING", &initial_partitioning.codegen_units);
     }
 
     // In the next step, we use the inlining map to determine which additional
@@ -272,7 +272,7 @@ where
         cgu.create_size_estimate(tcx);
     }
 
-    debug_dump(tcx, "POST INLINING:", post_inlining.codegen_units.iter());
+    debug_dump(tcx, "POST INLINING", &post_inlining.codegen_units);
 
     // Next we try to make as many symbols "internal" as possible, so LLVM has
     // more freedom to optimize.
@@ -322,6 +322,8 @@ where
 
     result.sort_by(|a, b| a.name().as_str().cmp(b.name().as_str()));
 
+    debug_dump(tcx, "FINAL", &result);
+
     result
 }
 
@@ -346,33 +348,37 @@ struct PostInliningPartitioning<'tcx> {
     internalization_candidates: FxHashSet<MonoItem<'tcx>>,
 }
 
-fn debug_dump<'a, 'tcx, I>(tcx: TyCtxt<'tcx>, label: &str, cgus: I)
-where
-    I: Iterator<Item = &'a CodegenUnit<'tcx>>,
-    'tcx: 'a,
-{
+fn debug_dump<'a, 'tcx: 'a>(tcx: TyCtxt<'tcx>, label: &str, cgus: &[CodegenUnit<'tcx>]) {
     let dump = move || {
         use std::fmt::Write;
 
+        let num_cgus = cgus.len();
+        let max = cgus.iter().map(|cgu| cgu.size_estimate()).max().unwrap();
+        let min = cgus.iter().map(|cgu| cgu.size_estimate()).min().unwrap();
+        let ratio = max as f64 / min as f64;
+
         let s = &mut String::new();
-        let _ = writeln!(s, "{label}");
+        let _ = writeln!(
+            s,
+            "{label} ({num_cgus} CodegenUnits, max={max}, min={min}, max/min={ratio:.1}):"
+        );
         for cgu in cgus {
             let _ =
-                writeln!(s, "CodegenUnit {} estimated size {} :", cgu.name(), cgu.size_estimate());
+                writeln!(s, "CodegenUnit {} estimated size {}:", cgu.name(), cgu.size_estimate());
 
             for (mono_item, linkage) in cgu.items() {
                 let symbol_name = mono_item.symbol_name(tcx).name;
                 let symbol_hash_start = symbol_name.rfind('h');
                 let symbol_hash = symbol_hash_start.map_or("<no hash>", |i| &symbol_name[i..]);
 
-                let _ = writeln!(
+                let _ = with_no_trimmed_paths!(writeln!(
                     s,
                     " - {} [{:?}] [{}] estimated size {}",
                     mono_item,
                     linkage,
                     symbol_hash,
                     mono_item.size_estimate(tcx)
-                );
+                ));
             }
 
             let _ = writeln!(s);
diff --git a/compiler/rustc_monomorphize/src/polymorphize.rs b/compiler/rustc_monomorphize/src/polymorphize.rs
index ddc62d9c390..88a3e028527 100644
--- a/compiler/rustc_monomorphize/src/polymorphize.rs
+++ b/compiler/rustc_monomorphize/src/polymorphize.rs
@@ -11,9 +11,9 @@ use rustc_middle::mir::{
     visit::{TyContext, Visitor},
     Constant, ConstantKind, Local, LocalDecl, Location,
 };
+use rustc_middle::query::Providers;
 use rustc_middle::ty::{
     self,
-    query::Providers,
     subst::SubstsRef,
     visit::{TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor},
     Const, Ty, TyCtxt, UnusedGenericParams,
diff --git a/compiler/rustc_parse/messages.ftl b/compiler/rustc_parse/messages.ftl
index 1bbf833e3cd..2d0f466e236 100644
--- a/compiler/rustc_parse/messages.ftl
+++ b/compiler/rustc_parse/messages.ftl
@@ -478,6 +478,11 @@ parse_missing_for_in_trait_impl = missing `for` in a trait impl
 
 parse_expected_trait_in_trait_impl_found_type = expected a trait, found type
 
+parse_extra_impl_keyword_in_trait_impl = unexpected `impl` keyword
+    .suggestion = remove the extra `impl`
+    .note = this is parsed as an `impl Trait` type, but a trait is expected at this position
+
+
 parse_non_item_in_item_list = non-item in item list
     .suggestion_use_const_not_let = consider using `const` instead of `let` for associated const
     .label_list_start = item list starts here
diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs
index b6aeaf3d59f..84494eab855 100644
--- a/compiler/rustc_parse/src/errors.rs
+++ b/compiler/rustc_parse/src/errors.rs
@@ -1520,6 +1520,16 @@ pub(crate) struct ExpectedTraitInTraitImplFoundType {
 }
 
 #[derive(Diagnostic)]
+#[diag(parse_extra_impl_keyword_in_trait_impl)]
+pub(crate) struct ExtraImplKeywordInTraitImpl {
+    #[primary_span]
+    #[suggestion(code = "", applicability = "maybe-incorrect")]
+    pub extra_impl_kw: Span,
+    #[note]
+    pub impl_trait_span: Span,
+}
+
+#[derive(Diagnostic)]
 #[diag(parse_bounds_not_allowed_on_trait_aliases)]
 pub(crate) struct BoundsNotAllowedOnTraitAliases {
     #[primary_span]
diff --git a/compiler/rustc_parse/src/lexer/mod.rs b/compiler/rustc_parse/src/lexer/mod.rs
index 51e90489002..c6e6b46e455 100644
--- a/compiler/rustc_parse/src/lexer/mod.rs
+++ b/compiler/rustc_parse/src/lexer/mod.rs
@@ -662,7 +662,7 @@ impl<'a> StringReader<'a> {
                 &RUST_2021_PREFIXES_INCOMPATIBLE_SYNTAX,
                 prefix_span,
                 ast::CRATE_NODE_ID,
-                &format!("prefix `{prefix}` is unknown"),
+                format!("prefix `{prefix}` is unknown"),
                 BuiltinLintDiagnostics::ReservedPrefix(prefix_span),
             );
         }
diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs
index 3002f23da75..bcef0f7185f 100644
--- a/compiler/rustc_parse/src/parser/diagnostics.rs
+++ b/compiler/rustc_parse/src/parser/diagnostics.rs
@@ -238,6 +238,7 @@ impl<'a> DerefMut for SnapshotParser<'a> {
 
 impl<'a> Parser<'a> {
     #[rustc_lint_diagnostics]
+    #[track_caller]
     pub fn struct_span_err<S: Into<MultiSpan>>(
         &self,
         sp: S,
diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs
index 887e155426f..ee712a8e1b5 100644
--- a/compiler/rustc_parse/src/parser/expr.rs
+++ b/compiler/rustc_parse/src/parser/expr.rs
@@ -1180,6 +1180,10 @@ impl<'a> Parser<'a> {
                         self.restore_snapshot(snapshot);
                         let close_paren = self.prev_token.span;
                         let span = lo.to(close_paren);
+                        // filter shorthand fields
+                        let fields: Vec<_> =
+                            fields.into_iter().filter(|field| !field.is_shorthand).collect();
+
                         if !fields.is_empty() &&
                             // `token.kind` should not be compared here.
                             // This is because the `snapshot.token.kind` is treated as the same as
diff --git a/compiler/rustc_parse/src/parser/generics.rs b/compiler/rustc_parse/src/parser/generics.rs
index e6d0f9fbc76..cd779b0b43e 100644
--- a/compiler/rustc_parse/src/parser/generics.rs
+++ b/compiler/rustc_parse/src/parser/generics.rs
@@ -453,6 +453,8 @@ impl<'a> Parser<'a> {
         //     `<` (LIFETIME|IDENT) `:` - generic parameter with bounds
         //     `<` (LIFETIME|IDENT) `=` - generic parameter with a default
         //     `<` const                - generic const parameter
+        //     `<` IDENT `?`            - RECOVERY for `impl<T ?Bound` missing a `:`, meant to
+        //                                avoid the `T?` to `Option<T>` recovery for types.
         // The only truly ambiguous case is
         //     `<` IDENT `>` `::` IDENT ...
         // we disambiguate it in favor of generics (`impl<T> ::absolute::Path<T> { ... }`)
@@ -463,6 +465,9 @@ impl<'a> Parser<'a> {
                 || self.look_ahead(start + 1, |t| t.is_lifetime() || t.is_ident())
                     && self.look_ahead(start + 2, |t| {
                         matches!(t.kind, token::Gt | token::Comma | token::Colon | token::Eq)
+                        // Recovery-only branch -- this could be removed,
+                        // since it only affects diagnostics currently.
+                            || matches!(t.kind, token::Question)
                     })
                 || self.is_keyword_ahead(start + 1, &[kw::Const]))
     }
diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs
index 840cfe90899..dc18d400f1e 100644
--- a/compiler/rustc_parse/src/parser/item.rs
+++ b/compiler/rustc_parse/src/parser/item.rs
@@ -603,10 +603,24 @@ impl<'a> Parser<'a> {
                 let path = match ty_first.kind {
                     // This notably includes paths passed through `ty` macro fragments (#46438).
                     TyKind::Path(None, path) => path,
-                    _ => {
-                        self.sess.emit_err(errors::ExpectedTraitInTraitImplFoundType {
-                            span: ty_first.span,
-                        });
+                    other => {
+                        if let TyKind::ImplTrait(_, bounds) = other
+                            && let [bound] = bounds.as_slice()
+                        {
+                            // Suggest removing extra `impl` keyword:
+                            // `impl<T: Default> impl Default for Wrapper<T>`
+                            //                   ^^^^^
+                            let extra_impl_kw = ty_first.span.until(bound.span());
+                            self.sess
+                                .emit_err(errors::ExtraImplKeywordInTraitImpl {
+                                    extra_impl_kw,
+                                    impl_trait_span: ty_first.span
+                                });
+                        } else {
+                            self.sess.emit_err(errors::ExpectedTraitInTraitImplFoundType {
+                                span: ty_first.span,
+                            });
+                        }
                         err_path(ty_first.span)
                     }
                 };
diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs
index 03279124177..54f9fc5d2b9 100644
--- a/compiler/rustc_parse/src/parser/stmt.rs
+++ b/compiler/rustc_parse/src/parser/stmt.rs
@@ -40,7 +40,8 @@ impl<'a> Parser<'a> {
 
     /// If `force_collect` is [`ForceCollect::Yes`], forces collection of tokens regardless of whether
     /// or not we have attributes
-    pub(crate) fn parse_stmt_without_recovery(
+    // Public for `cfg_eval` macro expansion.
+    pub fn parse_stmt_without_recovery(
         &mut self,
         capture_semi: bool,
         force_collect: ForceCollect,
diff --git a/compiler/rustc_parse/src/validate_attr.rs b/compiler/rustc_parse/src/validate_attr.rs
index 982c4615aff..928fdce313d 100644
--- a/compiler/rustc_parse/src/validate_attr.rs
+++ b/compiler/rustc_parse/src/validate_attr.rs
@@ -186,7 +186,7 @@ fn emit_malformed_attribute(
         suggestions.push(code);
     }
     if should_warn(name) {
-        sess.buffer_lint(&ILL_FORMED_ATTRIBUTE_INPUT, span, ast::CRATE_NODE_ID, &msg);
+        sess.buffer_lint(&ILL_FORMED_ATTRIBUTE_INPUT, span, ast::CRATE_NODE_ID, msg);
     } else {
         sess.span_diagnostic
             .struct_span_err(span, error_msg)
diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs
index 06aa2737915..41f92227e7c 100644
--- a/compiler/rustc_passes/src/check_attr.rs
+++ b/compiler/rustc_passes/src/check_attr.rs
@@ -8,7 +8,6 @@ use crate::{errors, fluent_generated as fluent};
 use rustc_ast::{ast, AttrStyle, Attribute, LitKind, MetaItemKind, MetaItemLit, NestedMetaItem};
 use rustc_data_structures::fx::FxHashMap;
 use rustc_errors::{Applicability, IntoDiagnosticArg, MultiSpan};
-use rustc_expand::base::resolve_path;
 use rustc_feature::{AttributeDuplicates, AttributeType, BuiltinAttribute, BUILTIN_ATTRIBUTE_MAP};
 use rustc_hir as hir;
 use rustc_hir::def_id::LocalDefId;
@@ -19,9 +18,9 @@ use rustc_hir::{
 use rustc_hir::{MethodKind, Target, Unsafety};
 use rustc_middle::hir::nested_filter;
 use rustc_middle::middle::resolve_bound_vars::ObjectLifetimeDefault;
+use rustc_middle::query::Providers;
 use rustc_middle::traits::ObligationCause;
 use rustc_middle::ty::error::{ExpectedFound, TypeError};
-use rustc_middle::ty::query::Providers;
 use rustc_middle::ty::{self, TyCtxt};
 use rustc_session::lint::builtin::{
     CONFLICTING_REPR_HINTS, INVALID_DOC_ATTRIBUTES, INVALID_MACRO_EXPORT_ARGUMENTS,
@@ -1916,6 +1915,10 @@ impl CheckAttrVisitor<'_> {
 
     /// Checks if the items on the `#[debugger_visualizer]` attribute are valid.
     fn check_debugger_visualizer(&self, attr: &Attribute, target: Target) -> bool {
+        // Here we only check that the #[debugger_visualizer] attribute is attached
+        // to nothing other than a module. All other checks are done in the
+        // `debugger_visualizer` query where they need to be done for decoding
+        // anyway.
         match target {
             Target::Mod => {}
             _ => {
@@ -1924,53 +1927,7 @@ impl CheckAttrVisitor<'_> {
             }
         }
 
-        let Some(hints) = attr.meta_item_list() else {
-            self.tcx.sess.emit_err(errors::DebugVisualizerInvalid { span: attr.span });
-            return false;
-        };
-
-        let hint = match hints.len() {
-            1 => &hints[0],
-            _ => {
-                self.tcx.sess.emit_err(errors::DebugVisualizerInvalid { span: attr.span });
-                return false;
-            }
-        };
-
-        let Some(meta_item) = hint.meta_item() else {
-            self.tcx.sess.emit_err(errors::DebugVisualizerInvalid { span: attr.span });
-            return false;
-        };
-
-        let visualizer_path = match (meta_item.name_or_empty(), meta_item.value_str()) {
-            (sym::natvis_file, Some(value)) => value,
-            (sym::gdb_script_file, Some(value)) => value,
-            (_, _) => {
-                self.tcx.sess.emit_err(errors::DebugVisualizerInvalid { span: meta_item.span });
-                return false;
-            }
-        };
-
-        let file =
-            match resolve_path(&self.tcx.sess.parse_sess, visualizer_path.as_str(), attr.span) {
-                Ok(file) => file,
-                Err(mut err) => {
-                    err.emit();
-                    return false;
-                }
-            };
-
-        match std::fs::File::open(&file) {
-            Ok(_) => true,
-            Err(error) => {
-                self.tcx.sess.emit_err(errors::DebugVisualizerUnreadable {
-                    span: meta_item.span,
-                    file: &file,
-                    error,
-                });
-                false
-            }
-        }
+        true
     }
 
     /// Outputs an error for `#[allow_internal_unstable]` which can only be applied to macros.
diff --git a/compiler/rustc_passes/src/check_const.rs b/compiler/rustc_passes/src/check_const.rs
index 6742722ce52..2357b0aadef 100644
--- a/compiler/rustc_passes/src/check_const.rs
+++ b/compiler/rustc_passes/src/check_const.rs
@@ -12,7 +12,7 @@ use rustc_hir as hir;
 use rustc_hir::def_id::LocalDefId;
 use rustc_hir::intravisit::{self, Visitor};
 use rustc_middle::hir::nested_filter;
-use rustc_middle::ty::query::Providers;
+use rustc_middle::query::Providers;
 use rustc_middle::ty::TyCtxt;
 use rustc_session::parse::feature_err;
 use rustc_span::{sym, Span, Symbol};
diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs
index 3ae5b45d330..7812dcde44c 100644
--- a/compiler/rustc_passes/src/dead.rs
+++ b/compiler/rustc_passes/src/dead.rs
@@ -12,7 +12,7 @@ use rustc_hir::intravisit::{self, Visitor};
 use rustc_hir::{Node, PatKind, TyKind};
 use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
 use rustc_middle::middle::privacy::Level;
-use rustc_middle::ty::query::Providers;
+use rustc_middle::query::Providers;
 use rustc_middle::ty::{self, TyCtxt};
 use rustc_session::lint;
 use rustc_span::symbol::{sym, Symbol};
diff --git a/compiler/rustc_passes/src/debugger_visualizer.rs b/compiler/rustc_passes/src/debugger_visualizer.rs
index 72371b9950b..3483f7da528 100644
--- a/compiler/rustc_passes/src/debugger_visualizer.rs
+++ b/compiler/rustc_passes/src/debugger_visualizer.rs
@@ -1,60 +1,69 @@
 //! Detecting usage of the `#[debugger_visualizer]` attribute.
 
-use hir::CRATE_HIR_ID;
-use rustc_data_structures::fx::FxHashSet;
+use rustc_ast::Attribute;
 use rustc_data_structures::sync::Lrc;
 use rustc_expand::base::resolve_path;
-use rustc_hir as hir;
-use rustc_hir::HirId;
-use rustc_middle::ty::TyCtxt;
-use rustc_middle::{query::LocalCrate, ty::query::Providers};
-use rustc_span::{sym, DebuggerVisualizerFile, DebuggerVisualizerType};
+use rustc_middle::{
+    middle::debugger_visualizer::{DebuggerVisualizerFile, DebuggerVisualizerType},
+    query::{LocalCrate, Providers},
+    ty::TyCtxt,
+};
+use rustc_session::Session;
+use rustc_span::sym;
 
-use crate::errors::DebugVisualizerUnreadable;
+use crate::errors::{DebugVisualizerInvalid, DebugVisualizerUnreadable};
 
-fn check_for_debugger_visualizer(
-    tcx: TyCtxt<'_>,
-    hir_id: HirId,
-    debugger_visualizers: &mut FxHashSet<DebuggerVisualizerFile>,
-) {
-    let attrs = tcx.hir().attrs(hir_id);
-    for attr in attrs {
+impl DebuggerVisualizerCollector<'_> {
+    fn check_for_debugger_visualizer(&mut self, attr: &Attribute) {
         if attr.has_name(sym::debugger_visualizer) {
-            let Some(list) = attr.meta_item_list() else {
-                continue
+            let Some(hints) = attr.meta_item_list() else {
+                self.sess.emit_err(DebugVisualizerInvalid { span: attr.span });
+                return;
             };
 
-            let meta_item = match list.len() {
-                1 => match list[0].meta_item() {
-                    Some(meta_item) => meta_item,
-                    _ => continue,
-                },
-                _ => continue,
+            let hint = if hints.len() == 1 {
+                &hints[0]
+            } else {
+                self.sess.emit_err(DebugVisualizerInvalid { span: attr.span });
+                return;
             };
 
-            let visualizer_type = match meta_item.name_or_empty() {
-                sym::natvis_file => DebuggerVisualizerType::Natvis,
-                sym::gdb_script_file => DebuggerVisualizerType::GdbPrettyPrinter,
-                _ => continue,
+            let Some(meta_item) = hint.meta_item() else {
+                self.sess.emit_err(DebugVisualizerInvalid { span: attr.span });
+                return;
             };
 
-            let file = match meta_item.value_str() {
-                Some(value) => {
-                    match resolve_path(&tcx.sess.parse_sess, value.as_str(), attr.span) {
-                        Ok(file) => file,
-                        _ => continue,
+            let (visualizer_type, visualizer_path) =
+                match (meta_item.name_or_empty(), meta_item.value_str()) {
+                    (sym::natvis_file, Some(value)) => (DebuggerVisualizerType::Natvis, value),
+                    (sym::gdb_script_file, Some(value)) => {
+                        (DebuggerVisualizerType::GdbPrettyPrinter, value)
                     }
-                }
-                None => continue,
-            };
+                    (_, _) => {
+                        self.sess.emit_err(DebugVisualizerInvalid { span: meta_item.span });
+                        return;
+                    }
+                };
+
+            let file =
+                match resolve_path(&self.sess.parse_sess, visualizer_path.as_str(), attr.span) {
+                    Ok(file) => file,
+                    Err(mut err) => {
+                        err.emit();
+                        return;
+                    }
+                };
 
             match std::fs::read(&file) {
                 Ok(contents) => {
-                    debugger_visualizers
-                        .insert(DebuggerVisualizerFile::new(Lrc::from(contents), visualizer_type));
+                    self.visualizers.push(DebuggerVisualizerFile::new(
+                        Lrc::from(contents),
+                        visualizer_type,
+                        file,
+                    ));
                 }
                 Err(error) => {
-                    tcx.sess.emit_err(DebugVisualizerUnreadable {
+                    self.sess.emit_err(DebugVisualizerUnreadable {
                         span: meta_item.span,
                         file: &file,
                         error,
@@ -65,29 +74,30 @@ fn check_for_debugger_visualizer(
     }
 }
 
-/// Traverses and collects the debugger visualizers for a specific crate.
-fn debugger_visualizers(tcx: TyCtxt<'_>, _: LocalCrate) -> Vec<DebuggerVisualizerFile> {
-    // Initialize the collector.
-    let mut debugger_visualizers = FxHashSet::default();
+struct DebuggerVisualizerCollector<'a> {
+    sess: &'a Session,
+    visualizers: Vec<DebuggerVisualizerFile>,
+}
 
-    // Collect debugger visualizers in this crate.
-    tcx.hir().for_each_module(|id| {
-        check_for_debugger_visualizer(
-            tcx,
-            tcx.hir().local_def_id_to_hir_id(id),
-            &mut debugger_visualizers,
-        )
-    });
+impl<'ast> rustc_ast::visit::Visitor<'ast> for DebuggerVisualizerCollector<'_> {
+    fn visit_attribute(&mut self, attr: &'ast Attribute) {
+        self.check_for_debugger_visualizer(attr);
+        rustc_ast::visit::walk_attribute(self, attr);
+    }
+}
 
-    // Collect debugger visualizers on the crate attributes.
-    check_for_debugger_visualizer(tcx, CRATE_HIR_ID, &mut debugger_visualizers);
+/// Traverses and collects the debugger visualizers for a specific crate.
+fn debugger_visualizers(tcx: TyCtxt<'_>, _: LocalCrate) -> Vec<DebuggerVisualizerFile> {
+    let resolver_and_krate = tcx.resolver_for_lowering(()).borrow();
+    let krate = &*resolver_and_krate.1;
 
-    // Extract out the found debugger_visualizer items.
-    let mut visualizers = debugger_visualizers.into_iter().collect::<Vec<_>>();
+    let mut visitor = DebuggerVisualizerCollector { sess: tcx.sess, visualizers: Vec::new() };
+    rustc_ast::visit::Visitor::visit_crate(&mut visitor, krate);
 
-    // Sort the visualizers so we always get a deterministic query result.
-    visualizers.sort();
-    visualizers
+    // We are collecting visualizers in AST-order, which is deterministic,
+    // so we don't need to do any explicit sorting in order to get a
+    // deterministic query result
+    visitor.visualizers
 }
 
 pub fn provide(providers: &mut Providers) {
diff --git a/compiler/rustc_passes/src/diagnostic_items.rs b/compiler/rustc_passes/src/diagnostic_items.rs
index eb6ea673c85..d8b9f4fae87 100644
--- a/compiler/rustc_passes/src/diagnostic_items.rs
+++ b/compiler/rustc_passes/src/diagnostic_items.rs
@@ -13,7 +13,7 @@ use rustc_ast as ast;
 use rustc_hir::diagnostic_items::DiagnosticItems;
 use rustc_hir::OwnerId;
 use rustc_middle::query::LocalCrate;
-use rustc_middle::ty::query::Providers;
+use rustc_middle::query::Providers;
 use rustc_middle::ty::TyCtxt;
 use rustc_span::def_id::{DefId, LOCAL_CRATE};
 use rustc_span::symbol::{sym, Symbol};
diff --git a/compiler/rustc_passes/src/entry.rs b/compiler/rustc_passes/src/entry.rs
index e3e4b73efa3..ffd8f77b78b 100644
--- a/compiler/rustc_passes/src/entry.rs
+++ b/compiler/rustc_passes/src/entry.rs
@@ -4,7 +4,7 @@ use rustc_errors::error_code;
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID, LOCAL_CRATE};
 use rustc_hir::{ItemId, Node, CRATE_HIR_ID};
-use rustc_middle::ty::query::Providers;
+use rustc_middle::query::Providers;
 use rustc_middle::ty::TyCtxt;
 use rustc_session::config::{sigpipe, CrateType, EntryFnType};
 use rustc_session::parse::feature_err;
diff --git a/compiler/rustc_passes/src/lang_items.rs b/compiler/rustc_passes/src/lang_items.rs
index fdd0e5dab70..476394f30cc 100644
--- a/compiler/rustc_passes/src/lang_items.rs
+++ b/compiler/rustc_passes/src/lang_items.rs
@@ -22,7 +22,7 @@ use rustc_middle::ty::TyCtxt;
 use rustc_session::cstore::ExternCrate;
 use rustc_span::{symbol::kw::Empty, Span};
 
-use rustc_middle::ty::query::Providers;
+use rustc_middle::query::Providers;
 
 pub(crate) enum Duplicate {
     Plain,
diff --git a/compiler/rustc_passes/src/lib.rs b/compiler/rustc_passes/src/lib.rs
index 8b7338e29aa..0da4b294648 100644
--- a/compiler/rustc_passes/src/lib.rs
+++ b/compiler/rustc_passes/src/lib.rs
@@ -22,7 +22,7 @@ extern crate tracing;
 
 use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage};
 use rustc_fluent_macro::fluent_messages;
-use rustc_middle::ty::query::Providers;
+use rustc_middle::query::Providers;
 
 mod check_attr;
 mod check_const;
diff --git a/compiler/rustc_passes/src/lib_features.rs b/compiler/rustc_passes/src/lib_features.rs
index f4da1aaec11..44174b1b89d 100644
--- a/compiler/rustc_passes/src/lib_features.rs
+++ b/compiler/rustc_passes/src/lib_features.rs
@@ -9,7 +9,7 @@ use rustc_attr::{rust_version_symbol, VERSION_PLACEHOLDER};
 use rustc_hir::intravisit::Visitor;
 use rustc_middle::hir::nested_filter;
 use rustc_middle::middle::lib_features::LibFeatures;
-use rustc_middle::ty::query::Providers;
+use rustc_middle::query::Providers;
 use rustc_middle::ty::TyCtxt;
 use rustc_span::symbol::Symbol;
 use rustc_span::{sym, Span};
diff --git a/compiler/rustc_passes/src/liveness.rs b/compiler/rustc_passes/src/liveness.rs
index 6758024419d..63b1578d43f 100644
--- a/compiler/rustc_passes/src/liveness.rs
+++ b/compiler/rustc_passes/src/liveness.rs
@@ -94,7 +94,7 @@ use rustc_hir::def_id::LocalDefId;
 use rustc_hir::intravisit::{self, Visitor};
 use rustc_hir::{Expr, HirId, HirIdMap, HirIdSet};
 use rustc_index::IndexVec;
-use rustc_middle::ty::query::Providers;
+use rustc_middle::query::Providers;
 use rustc_middle::ty::{self, RootVariableMinCaptureList, Ty, TyCtxt};
 use rustc_session::lint;
 use rustc_span::symbol::{kw, sym, Symbol};
diff --git a/compiler/rustc_passes/src/loops.rs b/compiler/rustc_passes/src/loops.rs
index b4cf19e4a34..73cfe68e7f2 100644
--- a/compiler/rustc_passes/src/loops.rs
+++ b/compiler/rustc_passes/src/loops.rs
@@ -6,7 +6,7 @@ use rustc_hir::intravisit::{self, Visitor};
 use rustc_hir::{Destination, Movability, Node};
 use rustc_middle::hir::map::Map;
 use rustc_middle::hir::nested_filter;
-use rustc_middle::ty::query::Providers;
+use rustc_middle::query::Providers;
 use rustc_middle::ty::TyCtxt;
 use rustc_session::Session;
 use rustc_span::hygiene::DesugaringKind;
diff --git a/compiler/rustc_passes/src/naked_functions.rs b/compiler/rustc_passes/src/naked_functions.rs
index cf8d9300a11..a849d61edfe 100644
--- a/compiler/rustc_passes/src/naked_functions.rs
+++ b/compiler/rustc_passes/src/naked_functions.rs
@@ -6,7 +6,7 @@ use rustc_hir::def::DefKind;
 use rustc_hir::def_id::LocalDefId;
 use rustc_hir::intravisit::Visitor;
 use rustc_hir::{ExprKind, InlineAsmOperand, StmtKind};
-use rustc_middle::ty::query::Providers;
+use rustc_middle::query::Providers;
 use rustc_middle::ty::TyCtxt;
 use rustc_session::lint::builtin::UNDEFINED_NAKED_FUNCTION_ABI;
 use rustc_span::symbol::sym;
diff --git a/compiler/rustc_passes/src/reachable.rs b/compiler/rustc_passes/src/reachable.rs
index a5f7b07fe52..160528e4074 100644
--- a/compiler/rustc_passes/src/reachable.rs
+++ b/compiler/rustc_passes/src/reachable.rs
@@ -13,7 +13,7 @@ use rustc_hir::intravisit::{self, Visitor};
 use rustc_hir::Node;
 use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs};
 use rustc_middle::middle::privacy::{self, Level};
-use rustc_middle::ty::query::Providers;
+use rustc_middle::query::Providers;
 use rustc_middle::ty::{self, TyCtxt};
 use rustc_session::config::CrateType;
 use rustc_target::spec::abi::Abi;
diff --git a/compiler/rustc_passes/src/stability.rs b/compiler/rustc_passes/src/stability.rs
index 9615f283ff4..f9060328f48 100644
--- a/compiler/rustc_passes/src/stability.rs
+++ b/compiler/rustc_passes/src/stability.rs
@@ -16,7 +16,8 @@ use rustc_hir::{FieldDef, Item, ItemKind, TraitRef, Ty, TyKind, Variant};
 use rustc_middle::hir::nested_filter;
 use rustc_middle::middle::privacy::EffectiveVisibilities;
 use rustc_middle::middle::stability::{AllowUnstable, DeprecationEntry, Index};
-use rustc_middle::ty::{query::Providers, TyCtxt};
+use rustc_middle::query::Providers;
+use rustc_middle::ty::TyCtxt;
 use rustc_session::lint;
 use rustc_session::lint::builtin::{INEFFECTIVE_UNSTABLE_TRAIT_IMPL, USELESS_DEPRECATED};
 use rustc_span::symbol::{sym, Symbol};
diff --git a/compiler/rustc_passes/src/upvars.rs b/compiler/rustc_passes/src/upvars.rs
index 605cf0a93b8..d87df706cc8 100644
--- a/compiler/rustc_passes/src/upvars.rs
+++ b/compiler/rustc_passes/src/upvars.rs
@@ -5,7 +5,7 @@ use rustc_hir as hir;
 use rustc_hir::def::Res;
 use rustc_hir::intravisit::{self, Visitor};
 use rustc_hir::{self, HirId};
-use rustc_middle::ty::query::Providers;
+use rustc_middle::query::Providers;
 use rustc_middle::ty::TyCtxt;
 use rustc_span::Span;
 
diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs
index d6eb5463870..7b39cb0a068 100644
--- a/compiler/rustc_privacy/src/lib.rs
+++ b/compiler/rustc_privacy/src/lib.rs
@@ -25,9 +25,9 @@ use rustc_hir::intravisit::{self, Visitor};
 use rustc_hir::{AssocItemKind, HirIdSet, ItemId, Node, PatKind};
 use rustc_middle::bug;
 use rustc_middle::hir::nested_filter;
-use rustc_middle::middle::privacy::{EffectiveVisibilities, Level};
+use rustc_middle::middle::privacy::{EffectiveVisibilities, EffectiveVisibility, Level};
+use rustc_middle::query::Providers;
 use rustc_middle::span_bug;
-use rustc_middle::ty::query::Providers;
 use rustc_middle::ty::subst::InternalSubsts;
 use rustc_middle::ty::{self, Const, GenericParamDefKind};
 use rustc_middle::ty::{TraitRef, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor};
@@ -38,7 +38,7 @@ use rustc_span::Span;
 
 use std::marker::PhantomData;
 use std::ops::ControlFlow;
-use std::{cmp, fmt, mem};
+use std::{fmt, mem};
 
 use errors::{
     FieldIsPrivate, FieldIsPrivateLabel, FromPrivateDependencyInPublicInterface, InPublicInterface,
@@ -408,8 +408,9 @@ impl VisibilityLike for ty::Visibility {
         min(find.tcx.local_visibility(def_id), find.min, find.tcx)
     }
 }
-impl VisibilityLike for Option<Level> {
-    const MAX: Self = Some(Level::Direct);
+
+impl VisibilityLike for Option<EffectiveVisibility> {
+    const MAX: Self = Some(EffectiveVisibility::from_vis(ty::Visibility::Public));
     // Type inference is very smart sometimes.
     // It can make an impl reachable even some components of its type or trait are unreachable.
     // E.g. methods of `impl ReachableTrait<UnreachableTy> for ReachableTy<UnreachableTy> { ... }`
@@ -421,7 +422,13 @@ impl VisibilityLike for Option<Level> {
     // (which require reaching the `DefId`s in them).
     const SHALLOW: bool = true;
     fn new_min(find: &FindMin<'_, '_, Self>, def_id: LocalDefId) -> Self {
-        cmp::min(find.effective_visibilities.public_at_level(def_id), find.min)
+        if let Some(min) = find.min {
+            return find
+                .effective_visibilities
+                .effective_vis(def_id)
+                .map(|eff_vis| min.min(*eff_vis, find.tcx));
+        }
+        None
     }
 }
 
@@ -447,49 +454,79 @@ struct EmbargoVisitor<'tcx> {
     ///     n::p::f()
     /// }
     macro_reachable: FxHashSet<(LocalDefId, LocalDefId)>,
-    /// Previous visibility level; `None` means unreachable.
-    prev_level: Option<Level>,
     /// Has something changed in the level map?
     changed: bool,
 }
 
 struct ReachEverythingInTheInterfaceVisitor<'a, 'tcx> {
-    level: Option<Level>,
+    effective_vis: Option<EffectiveVisibility>,
     item_def_id: LocalDefId,
     ev: &'a mut EmbargoVisitor<'tcx>,
+    level: Level,
 }
 
 impl<'tcx> EmbargoVisitor<'tcx> {
-    fn get(&self, def_id: LocalDefId) -> Option<Level> {
-        self.effective_visibilities.public_at_level(def_id)
-    }
-
-    /// Updates node level and returns the updated level.
-    fn update(&mut self, def_id: LocalDefId, level: Option<Level>) -> Option<Level> {
-        let old_level = self.get(def_id);
-        // Visibility levels can only grow.
-        if level > old_level {
-            self.effective_visibilities.set_public_at_level(
-                def_id,
-                || ty::Visibility::Restricted(self.tcx.parent_module_from_def_id(def_id)),
-                level.unwrap(),
-            );
-            self.changed = true;
-            level
-        } else {
-            old_level
+    fn get(&self, def_id: LocalDefId) -> Option<EffectiveVisibility> {
+        self.effective_visibilities.effective_vis(def_id).copied()
+    }
+
+    // Updates node effective visibility.
+    fn update(
+        &mut self,
+        def_id: LocalDefId,
+        inherited_effective_vis: Option<EffectiveVisibility>,
+        level: Level,
+    ) {
+        let nominal_vis = self.tcx.local_visibility(def_id);
+        self.update_eff_vis(def_id, inherited_effective_vis, Some(nominal_vis), level);
+    }
+
+    fn update_eff_vis(
+        &mut self,
+        def_id: LocalDefId,
+        inherited_effective_vis: Option<EffectiveVisibility>,
+        nominal_vis: Option<ty::Visibility>,
+        level: Level,
+    ) {
+        if let Some(inherited_effective_vis) = inherited_effective_vis {
+            let private_vis =
+                ty::Visibility::Restricted(self.tcx.parent_module_from_def_id(def_id));
+            if Some(private_vis) != nominal_vis {
+                self.changed |= self.effective_visibilities.update(
+                    def_id,
+                    nominal_vis,
+                    || private_vis,
+                    inherited_effective_vis,
+                    level,
+                    self.tcx,
+                );
+            }
         }
     }
 
     fn reach(
         &mut self,
         def_id: LocalDefId,
-        level: Option<Level>,
+        effective_vis: Option<EffectiveVisibility>,
     ) -> ReachEverythingInTheInterfaceVisitor<'_, 'tcx> {
         ReachEverythingInTheInterfaceVisitor {
-            level: cmp::min(level, Some(Level::Reachable)),
+            effective_vis,
             item_def_id: def_id,
             ev: self,
+            level: Level::Reachable,
+        }
+    }
+
+    fn reach_through_impl_trait(
+        &mut self,
+        def_id: LocalDefId,
+        effective_vis: Option<EffectiveVisibility>,
+    ) -> ReachEverythingInTheInterfaceVisitor<'_, 'tcx> {
+        ReachEverythingInTheInterfaceVisitor {
+            effective_vis,
+            item_def_id: def_id,
+            ev: self,
+            level: Level::ReachableThroughImplTrait,
         }
     }
 
@@ -510,16 +547,18 @@ impl<'tcx> EmbargoVisitor<'tcx> {
             return;
         }
 
-        if self.get(local_def_id).is_none() {
+        if self.effective_visibilities.public_at_level(local_def_id).is_none() {
             return;
         }
 
         // Since we are starting from an externally visible module,
         // all the parents in the loop below are also guaranteed to be modules.
         let mut module_def_id = macro_module_def_id;
+        let macro_ev = self.get(local_def_id);
+        assert!(macro_ev.is_some());
         loop {
             let changed_reachability =
-                self.update_macro_reachable(module_def_id, macro_module_def_id);
+                self.update_macro_reachable(module_def_id, macro_module_def_id, macro_ev);
             if changed_reachability || module_def_id == CRATE_DEF_ID {
                 break;
             }
@@ -533,21 +572,33 @@ impl<'tcx> EmbargoVisitor<'tcx> {
         &mut self,
         module_def_id: LocalDefId,
         defining_mod: LocalDefId,
+        macro_ev: Option<EffectiveVisibility>,
     ) -> bool {
         if self.macro_reachable.insert((module_def_id, defining_mod)) {
-            self.update_macro_reachable_mod(module_def_id, defining_mod);
+            self.update_macro_reachable_mod(module_def_id, defining_mod, macro_ev);
             true
         } else {
             false
         }
     }
 
-    fn update_macro_reachable_mod(&mut self, module_def_id: LocalDefId, defining_mod: LocalDefId) {
+    fn update_macro_reachable_mod(
+        &mut self,
+        module_def_id: LocalDefId,
+        defining_mod: LocalDefId,
+        macro_ev: Option<EffectiveVisibility>,
+    ) {
         let module = self.tcx.hir().get_module(module_def_id).0;
         for item_id in module.item_ids {
             let def_kind = self.tcx.def_kind(item_id.owner_id);
             let vis = self.tcx.local_visibility(item_id.owner_id.def_id);
-            self.update_macro_reachable_def(item_id.owner_id.def_id, def_kind, vis, defining_mod);
+            self.update_macro_reachable_def(
+                item_id.owner_id.def_id,
+                def_kind,
+                vis,
+                defining_mod,
+                macro_ev,
+            );
         }
         for child in self.tcx.module_children_local(module_def_id) {
             // FIXME: Use module children for the logic above too.
@@ -556,7 +607,7 @@ impl<'tcx> EmbargoVisitor<'tcx> {
                 && let Res::Def(def_kind, def_id) = child.res
                 && let Some(def_id) = def_id.as_local() {
                 let vis = self.tcx.local_visibility(def_id);
-                self.update_macro_reachable_def(def_id, def_kind, vis, defining_mod);
+                self.update_macro_reachable_def(def_id, def_kind, vis, defining_mod, macro_ev);
             }
         }
     }
@@ -567,16 +618,14 @@ impl<'tcx> EmbargoVisitor<'tcx> {
         def_kind: DefKind,
         vis: ty::Visibility,
         module: LocalDefId,
+        macro_ev: Option<EffectiveVisibility>,
     ) {
-        let level = Some(Level::Reachable);
-        if vis.is_public() {
-            self.update(def_id, level);
-        }
+        self.update(def_id, macro_ev, Level::Reachable);
         match def_kind {
             // No type privacy, so can be directly marked as reachable.
             DefKind::Const | DefKind::Static(_) | DefKind::TraitAlias | DefKind::TyAlias => {
                 if vis.is_accessible_from(module, self.tcx) {
-                    self.update(def_id, level);
+                    self.update(def_id, macro_ev, Level::Reachable);
                 }
             }
 
@@ -588,7 +637,7 @@ impl<'tcx> EmbargoVisitor<'tcx> {
                 let item = self.tcx.hir().expect_item(def_id);
                 if let hir::ItemKind::Macro(MacroDef { macro_rules: false, .. }, _) = item.kind {
                     if vis.is_accessible_from(module, self.tcx) {
-                        self.update(def_id, level);
+                        self.update(def_id, macro_ev, Level::Reachable);
                     }
                 }
             }
@@ -599,26 +648,24 @@ impl<'tcx> EmbargoVisitor<'tcx> {
             // the module, however may be reachable.
             DefKind::Mod => {
                 if vis.is_accessible_from(module, self.tcx) {
-                    self.update_macro_reachable(def_id, module);
+                    self.update_macro_reachable(def_id, module, macro_ev);
                 }
             }
 
             DefKind::Struct | DefKind::Union => {
                 // While structs and unions have type privacy, their fields do not.
-                if vis.is_public() {
-                    let item = self.tcx.hir().expect_item(def_id);
-                    if let hir::ItemKind::Struct(ref struct_def, _)
-                    | hir::ItemKind::Union(ref struct_def, _) = item.kind
-                    {
-                        for field in struct_def.fields() {
-                            let field_vis = self.tcx.local_visibility(field.def_id);
-                            if field_vis.is_accessible_from(module, self.tcx) {
-                                self.reach(field.def_id, level).ty();
-                            }
+                let item = self.tcx.hir().expect_item(def_id);
+                if let hir::ItemKind::Struct(ref struct_def, _)
+                | hir::ItemKind::Union(ref struct_def, _) = item.kind
+                {
+                    for field in struct_def.fields() {
+                        let field_vis = self.tcx.local_visibility(field.def_id);
+                        if field_vis.is_accessible_from(module, self.tcx) {
+                            self.reach(field.def_id, macro_ev).ty();
                         }
-                    } else {
-                        bug!("item {:?} with DefKind {:?}", item, def_kind);
                     }
+                } else {
+                    bug!("item {:?} with DefKind {:?}", item, def_kind);
                 }
             }
 
@@ -662,14 +709,16 @@ impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> {
     }
 
     fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
-        let item_level = match item.kind {
+        let item_ev = match item.kind {
             hir::ItemKind::Impl { .. } => {
-                let impl_level = Option::<Level>::of_impl(
+                let impl_ev = Option::<EffectiveVisibility>::of_impl(
                     item.owner_id.def_id,
                     self.tcx,
                     &self.effective_visibilities,
                 );
-                self.update(item.owner_id.def_id, impl_level)
+
+                self.update_eff_vis(item.owner_id.def_id, impl_ev, None, Level::Direct);
+                impl_ev
             }
             _ => self.get(item.owner_id.def_id),
         };
@@ -678,38 +727,35 @@ impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> {
         match item.kind {
             hir::ItemKind::Enum(ref def, _) => {
                 for variant in def.variants {
-                    let variant_level = self.update(variant.def_id, item_level);
+                    self.update(variant.def_id, item_ev, Level::Reachable);
+                    let variant_ev = self.get(variant.def_id);
                     if let Some(ctor_def_id) = variant.data.ctor_def_id() {
-                        self.update(ctor_def_id, item_level);
+                        self.update(ctor_def_id, variant_ev, Level::Reachable);
                     }
                     for field in variant.data.fields() {
-                        self.update(field.def_id, variant_level);
+                        self.update(field.def_id, variant_ev, Level::Reachable);
                     }
                 }
             }
             hir::ItemKind::Impl(ref impl_) => {
                 for impl_item_ref in impl_.items {
-                    if impl_.of_trait.is_some()
-                        || self.tcx.visibility(impl_item_ref.id.owner_id).is_public()
-                    {
-                        self.update(impl_item_ref.id.owner_id.def_id, item_level);
-                    }
+                    let def_id = impl_item_ref.id.owner_id.def_id;
+                    let nominal_vis =
+                        impl_.of_trait.is_none().then(|| self.tcx.local_visibility(def_id));
+                    self.update_eff_vis(def_id, item_ev, nominal_vis, Level::Direct);
                 }
             }
             hir::ItemKind::Trait(.., trait_item_refs) => {
                 for trait_item_ref in trait_item_refs {
-                    self.update(trait_item_ref.id.owner_id.def_id, item_level);
+                    self.update(trait_item_ref.id.owner_id.def_id, item_ev, Level::Reachable);
                 }
             }
             hir::ItemKind::Struct(ref def, _) | hir::ItemKind::Union(ref def, _) => {
                 if let Some(ctor_def_id) = def.ctor_def_id() {
-                    self.update(ctor_def_id, item_level);
+                    self.update(ctor_def_id, item_ev, Level::Reachable);
                 }
                 for field in def.fields() {
-                    let vis = self.tcx.visibility(field.def_id);
-                    if vis.is_public() {
-                        self.update(field.def_id, item_level);
-                    }
+                    self.update(field.def_id, item_ev, Level::Reachable);
                 }
             }
             hir::ItemKind::Macro(ref macro_def, _) => {
@@ -717,9 +763,7 @@ impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> {
             }
             hir::ItemKind::ForeignMod { items, .. } => {
                 for foreign_item in items {
-                    if self.tcx.visibility(foreign_item.id.owner_id).is_public() {
-                        self.update(foreign_item.id.owner_id.def_id, item_level);
-                    }
+                    self.update(foreign_item.id.owner_id.def_id, item_ev, Level::Reachable);
                 }
             }
 
@@ -754,8 +798,11 @@ impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> {
                     // FIXME: This is some serious pessimization intended to workaround deficiencies
                     // in the reachability pass (`middle/reachable.rs`). Types are marked as link-time
                     // reachable if they are returned via `impl Trait`, even from private functions.
-                    let exist_level = cmp::max(item_level, Some(Level::ReachableThroughImplTrait));
-                    self.reach(item.owner_id.def_id, exist_level).generics().predicates().ty();
+                    let exist_ev = Some(EffectiveVisibility::from_vis(ty::Visibility::Public));
+                    self.reach_through_impl_trait(item.owner_id.def_id, exist_ev)
+                        .generics()
+                        .predicates()
+                        .ty();
                 }
             }
             // Visit everything.
@@ -763,17 +810,18 @@ impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> {
             | hir::ItemKind::Static(..)
             | hir::ItemKind::Fn(..)
             | hir::ItemKind::TyAlias(..) => {
-                if item_level.is_some() {
-                    self.reach(item.owner_id.def_id, item_level).generics().predicates().ty();
+                if item_ev.is_some() {
+                    self.reach(item.owner_id.def_id, item_ev).generics().predicates().ty();
                 }
             }
             hir::ItemKind::Trait(.., trait_item_refs) => {
-                if item_level.is_some() {
-                    self.reach(item.owner_id.def_id, item_level).generics().predicates();
+                if item_ev.is_some() {
+                    self.reach(item.owner_id.def_id, item_ev).generics().predicates();
 
                     for trait_item_ref in trait_item_refs {
                         let tcx = self.tcx;
-                        let mut reach = self.reach(trait_item_ref.id.owner_id.def_id, item_level);
+                        let mut reach = self.reach(trait_item_ref.id.owner_id.def_id, item_ev);
+
                         reach.generics().predicates();
 
                         if trait_item_ref.kind == AssocItemKind::Type
@@ -787,23 +835,24 @@ impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> {
                 }
             }
             hir::ItemKind::TraitAlias(..) => {
-                if item_level.is_some() {
-                    self.reach(item.owner_id.def_id, item_level).generics().predicates();
+                if item_ev.is_some() {
+                    self.reach(item.owner_id.def_id, item_ev).generics().predicates();
                 }
             }
             // Visit everything except for private impl items.
             hir::ItemKind::Impl(ref impl_) => {
-                if item_level.is_some() {
-                    self.reach(item.owner_id.def_id, item_level)
+                if item_ev.is_some() {
+                    self.reach(item.owner_id.def_id, item_ev)
                         .generics()
                         .predicates()
                         .ty()
                         .trait_ref();
 
                     for impl_item_ref in impl_.items {
-                        let impl_item_level = self.get(impl_item_ref.id.owner_id.def_id);
-                        if impl_item_level.is_some() {
-                            self.reach(impl_item_ref.id.owner_id.def_id, impl_item_level)
+                        let impl_item_ev = self.get(impl_item_ref.id.owner_id.def_id);
+
+                        if impl_item_ev.is_some() {
+                            self.reach(impl_item_ref.id.owner_id.def_id, impl_item_ev)
                                 .generics()
                                 .predicates()
                                 .ty();
@@ -814,23 +863,23 @@ impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> {
 
             // Visit everything, but enum variants have their own levels.
             hir::ItemKind::Enum(ref def, _) => {
-                if item_level.is_some() {
-                    self.reach(item.owner_id.def_id, item_level).generics().predicates();
+                if item_ev.is_some() {
+                    self.reach(item.owner_id.def_id, item_ev).generics().predicates();
                 }
                 for variant in def.variants {
-                    let variant_level = self.get(variant.def_id);
-                    if variant_level.is_some() {
+                    let variant_ev = self.get(variant.def_id);
+                    if variant_ev.is_some() {
                         for field in variant.data.fields() {
-                            self.reach(field.def_id, variant_level).ty();
+                            self.reach(field.def_id, variant_ev).ty();
                         }
                         // Corner case: if the variant is reachable, but its
                         // enum is not, make the enum reachable as well.
-                        self.reach(item.owner_id.def_id, variant_level).ty();
+                        self.reach(item.owner_id.def_id, variant_ev).ty();
                     }
                     if let Some(ctor_def_id) = variant.data.ctor_def_id() {
-                        let ctor_level = self.get(ctor_def_id);
-                        if ctor_level.is_some() {
-                            self.reach(item.owner_id.def_id, ctor_level).ty();
+                        let ctor_ev = self.get(ctor_def_id);
+                        if ctor_ev.is_some() {
+                            self.reach(item.owner_id.def_id, ctor_ev).ty();
                         }
                     }
                 }
@@ -838,9 +887,9 @@ impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> {
             // Visit everything, but foreign items have their own levels.
             hir::ItemKind::ForeignMod { items, .. } => {
                 for foreign_item in items {
-                    let foreign_item_level = self.get(foreign_item.id.owner_id.def_id);
-                    if foreign_item_level.is_some() {
-                        self.reach(foreign_item.id.owner_id.def_id, foreign_item_level)
+                    let foreign_item_ev = self.get(foreign_item.id.owner_id.def_id);
+                    if foreign_item_ev.is_some() {
+                        self.reach(foreign_item.id.owner_id.def_id, foreign_item_ev)
                             .generics()
                             .predicates()
                             .ty();
@@ -849,36 +898,32 @@ impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> {
             }
             // Visit everything except for private fields.
             hir::ItemKind::Struct(ref struct_def, _) | hir::ItemKind::Union(ref struct_def, _) => {
-                if item_level.is_some() {
-                    self.reach(item.owner_id.def_id, item_level).generics().predicates();
+                if item_ev.is_some() {
+                    self.reach(item.owner_id.def_id, item_ev).generics().predicates();
                     for field in struct_def.fields() {
-                        let field_level = self.get(field.def_id);
-                        if field_level.is_some() {
-                            self.reach(field.def_id, field_level).ty();
+                        let field_ev = self.get(field.def_id);
+                        if field_ev.is_some() {
+                            self.reach(field.def_id, field_ev).ty();
                         }
                     }
                 }
                 if let Some(ctor_def_id) = struct_def.ctor_def_id() {
-                    let ctor_level = self.get(ctor_def_id);
-                    if ctor_level.is_some() {
-                        self.reach(item.owner_id.def_id, ctor_level).ty();
+                    let ctor_ev = self.get(ctor_def_id);
+                    if ctor_ev.is_some() {
+                        self.reach(item.owner_id.def_id, ctor_ev).ty();
                     }
                 }
             }
         }
 
-        let orig_level = mem::replace(&mut self.prev_level, item_level);
         intravisit::walk_item(self, item);
-        self.prev_level = orig_level;
     }
 
     fn visit_block(&mut self, b: &'tcx hir::Block<'tcx>) {
         // Blocks can have public items, for example impls, but they always
         // start as completely private regardless of publicity of a function,
         // constant, type, field, etc., in which this block resides.
-        let orig_level = mem::replace(&mut self.prev_level, None);
         intravisit::walk_block(self, b);
-        self.prev_level = orig_level;
     }
 }
 
@@ -932,11 +977,7 @@ impl<'tcx> DefIdVisitor<'tcx> for ReachEverythingInTheInterfaceVisitor<'_, 'tcx>
         _descr: &dyn fmt::Display,
     ) -> ControlFlow<Self::BreakTy> {
         if let Some(def_id) = def_id.as_local() {
-            if let (ty::Visibility::Public, _) | (_, Some(Level::ReachableThroughImplTrait)) =
-                (self.tcx().visibility(def_id.to_def_id()), self.level)
-            {
-                self.ev.update(def_id, self.level);
-            }
+            self.ev.update_eff_vis(def_id, self.effective_vis, None, self.level);
         }
         ControlFlow::Continue(())
     }
@@ -2164,7 +2205,6 @@ fn effective_visibilities(tcx: TyCtxt<'_>, (): ()) -> &EffectiveVisibilities {
         tcx,
         effective_visibilities: tcx.resolutions(()).effective_visibilities.clone(),
         macro_reachable: Default::default(),
-        prev_level: Some(Level::Direct),
         changed: false,
     };
 
diff --git a/compiler/rustc_query_impl/Cargo.toml b/compiler/rustc_query_impl/Cargo.toml
index b107a3f03fe..e596993465c 100644
--- a/compiler/rustc_query_impl/Cargo.toml
+++ b/compiler/rustc_query_impl/Cargo.toml
@@ -7,6 +7,8 @@ edition = "2021"
 
 
 [dependencies]
+memoffset = { version = "0.6.0", features = ["unstable_const"] }
+field-offset = "0.3.5"
 measureme = "10.0.0"
 rustc_ast = { path = "../rustc_ast" }
 rustc_data_structures = { path = "../rustc_data_structures" }
diff --git a/compiler/rustc_query_impl/src/lib.rs b/compiler/rustc_query_impl/src/lib.rs
index 82b335f4b4b..4cf0f1305a7 100644
--- a/compiler/rustc_query_impl/src/lib.rs
+++ b/compiler/rustc_query_impl/src/lib.rs
@@ -3,28 +3,42 @@
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
 // this shouldn't be necessary, but the check for `&mut _` is too naive and denies returning a function pointer that takes a mut ref
 #![feature(const_mut_refs)]
+#![feature(const_refs_to_cell)]
 #![feature(min_specialization)]
 #![feature(never_type)]
 #![feature(rustc_attrs)]
 #![recursion_limit = "256"]
-#![allow(rustc::potential_query_instability)]
+#![allow(rustc::potential_query_instability, unused_parens)]
 #![deny(rustc::untranslatable_diagnostic)]
 #![deny(rustc::diagnostic_outside_of_impl)]
 
 #[macro_use]
 extern crate rustc_middle;
 
-use crate::plumbing::{encode_all_query_results, try_mark_green};
+use crate::plumbing::{__rust_begin_short_backtrace, encode_all_query_results, try_mark_green};
+use field_offset::offset_of;
+use rustc_data_structures::stable_hasher::HashStable;
+use rustc_data_structures::sync::AtomicU64;
 use rustc_middle::arena::Arena;
+use rustc_middle::dep_graph::DepNodeIndex;
 use rustc_middle::dep_graph::{self, DepKind, DepKindStruct};
 use rustc_middle::query::erase::{erase, restore, Erase};
+use rustc_middle::query::on_disk_cache::{CacheEncoder, EncodedDepNodeIndex, OnDiskCache};
+use rustc_middle::query::plumbing::{
+    DynamicQuery, QueryKeyStringCache, QuerySystem, QuerySystemFns,
+};
 use rustc_middle::query::AsLocalKey;
-use rustc_middle::ty::query::{
-    query_keys, query_provided, query_provided_to_value, query_storage, query_values,
+use rustc_middle::query::{
+    queries, DynamicQueries, ExternProviders, Providers, QueryCaches, QueryEngine, QueryStates,
 };
-use rustc_middle::ty::query::{ExternProviders, Providers, QueryEngine, QuerySystemFns};
 use rustc_middle::ty::TyCtxt;
 use rustc_query_system::dep_graph::SerializedDepNodeIndex;
+use rustc_query_system::ich::StableHashingContext;
+use rustc_query_system::query::{
+    get_query_incr, get_query_non_incr, HashResult, QueryCache, QueryConfig, QueryInfo, QueryMap,
+    QueryMode, QueryState,
+};
+use rustc_query_system::HandleCycleError;
 use rustc_query_system::Value;
 use rustc_span::Span;
 
@@ -32,31 +46,182 @@ use rustc_span::Span;
 mod plumbing;
 pub use crate::plumbing::QueryCtxt;
 
-pub use rustc_query_system::query::QueryConfig;
-use rustc_query_system::query::*;
-
 mod profiling_support;
 pub use self::profiling_support::alloc_self_profile_query_strings;
 
-/// This is implemented per query and restoring query values from their erased state.
-trait QueryConfigRestored<'tcx>: QueryConfig<QueryCtxt<'tcx>> + Default {
-    type RestoredValue;
+struct DynamicConfig<
+    'tcx,
+    C: QueryCache,
+    const ANON: bool,
+    const DEPTH_LIMIT: bool,
+    const FEEDABLE: bool,
+> {
+    dynamic: &'tcx DynamicQuery<'tcx, C>,
+}
 
-    fn restore(value: <Self as QueryConfig<QueryCtxt<'tcx>>>::Value) -> Self::RestoredValue;
+impl<'tcx, C: QueryCache, const ANON: bool, const DEPTH_LIMIT: bool, const FEEDABLE: bool> Copy
+    for DynamicConfig<'tcx, C, ANON, DEPTH_LIMIT, FEEDABLE>
+{
+}
+impl<'tcx, C: QueryCache, const ANON: bool, const DEPTH_LIMIT: bool, const FEEDABLE: bool> Clone
+    for DynamicConfig<'tcx, C, ANON, DEPTH_LIMIT, FEEDABLE>
+{
+    fn clone(&self) -> Self {
+        DynamicConfig { dynamic: self.dynamic }
+    }
 }
 
-rustc_query_append! { define_queries! }
+impl<'tcx, C: QueryCache, const ANON: bool, const DEPTH_LIMIT: bool, const FEEDABLE: bool>
+    QueryConfig<QueryCtxt<'tcx>> for DynamicConfig<'tcx, C, ANON, DEPTH_LIMIT, FEEDABLE>
+where
+    for<'a> C::Key: HashStable<StableHashingContext<'a>>,
+{
+    type Key = C::Key;
+    type Value = C::Value;
+    type Cache = C;
+
+    #[inline(always)]
+    fn name(self) -> &'static str {
+        self.dynamic.name
+    }
 
-pub fn query_system_fns<'tcx>(
+    #[inline(always)]
+    fn cache_on_disk(self, tcx: TyCtxt<'tcx>, key: &Self::Key) -> bool {
+        (self.dynamic.cache_on_disk)(tcx, key)
+    }
+
+    #[inline(always)]
+    fn query_state<'a>(self, qcx: QueryCtxt<'tcx>) -> &'a QueryState<Self::Key, DepKind>
+    where
+        QueryCtxt<'tcx>: 'a,
+    {
+        self.dynamic.query_state.apply(&qcx.tcx.query_system.states)
+    }
+
+    #[inline(always)]
+    fn query_cache<'a>(self, qcx: QueryCtxt<'tcx>) -> &'a Self::Cache
+    where
+        'tcx: 'a,
+    {
+        self.dynamic.query_cache.apply(&qcx.tcx.query_system.caches)
+    }
+
+    #[inline(always)]
+    fn execute_query(self, tcx: TyCtxt<'tcx>, key: Self::Key) -> Self::Value {
+        (self.dynamic.execute_query)(tcx, key)
+    }
+
+    #[inline(always)]
+    fn compute(self, qcx: QueryCtxt<'tcx>, key: Self::Key) -> Self::Value {
+        (self.dynamic.compute)(qcx.tcx, key)
+    }
+
+    #[inline(always)]
+    fn try_load_from_disk(
+        self,
+        qcx: QueryCtxt<'tcx>,
+        key: &Self::Key,
+        prev_index: SerializedDepNodeIndex,
+        index: DepNodeIndex,
+    ) -> Option<Self::Value> {
+        if self.dynamic.can_load_from_disk {
+            (self.dynamic.try_load_from_disk)(qcx.tcx, key, prev_index, index)
+        } else {
+            None
+        }
+    }
+
+    #[inline]
+    fn loadable_from_disk(
+        self,
+        qcx: QueryCtxt<'tcx>,
+        key: &Self::Key,
+        index: SerializedDepNodeIndex,
+    ) -> bool {
+        (self.dynamic.loadable_from_disk)(qcx.tcx, key, index)
+    }
+
+    fn value_from_cycle_error(
+        self,
+        tcx: TyCtxt<'tcx>,
+        cycle: &[QueryInfo<DepKind>],
+    ) -> Self::Value {
+        (self.dynamic.value_from_cycle_error)(tcx, cycle)
+    }
+
+    #[inline(always)]
+    fn format_value(self) -> fn(&Self::Value) -> String {
+        self.dynamic.format_value
+    }
+
+    #[inline(always)]
+    fn anon(self) -> bool {
+        ANON
+    }
+
+    #[inline(always)]
+    fn eval_always(self) -> bool {
+        self.dynamic.eval_always
+    }
+
+    #[inline(always)]
+    fn depth_limit(self) -> bool {
+        DEPTH_LIMIT
+    }
+
+    #[inline(always)]
+    fn feedable(self) -> bool {
+        FEEDABLE
+    }
+
+    #[inline(always)]
+    fn dep_kind(self) -> DepKind {
+        self.dynamic.dep_kind
+    }
+
+    #[inline(always)]
+    fn handle_cycle_error(self) -> HandleCycleError {
+        self.dynamic.handle_cycle_error
+    }
+
+    #[inline(always)]
+    fn hash_result(self) -> HashResult<Self::Value> {
+        self.dynamic.hash_result
+    }
+}
+
+/// This is implemented per query. It allows restoring query values from their erased state
+/// and constructing a QueryConfig.
+trait QueryConfigRestored<'tcx> {
+    type RestoredValue;
+    type Config: QueryConfig<QueryCtxt<'tcx>>;
+
+    fn config(tcx: TyCtxt<'tcx>) -> Self::Config;
+    fn restore(value: <Self::Config as QueryConfig<QueryCtxt<'tcx>>>::Value)
+    -> Self::RestoredValue;
+}
+
+pub fn query_system<'tcx>(
     local_providers: Providers,
     extern_providers: ExternProviders,
-) -> QuerySystemFns<'tcx> {
-    QuerySystemFns {
-        engine: engine(),
-        local_providers,
-        extern_providers,
-        query_structs: make_dep_kind_array!(query_structs).to_vec(),
-        encode_query_results: encode_all_query_results,
-        try_mark_green: try_mark_green,
+    on_disk_cache: Option<OnDiskCache<'tcx>>,
+    incremental: bool,
+) -> QuerySystem<'tcx> {
+    QuerySystem {
+        states: Default::default(),
+        arenas: Default::default(),
+        caches: Default::default(),
+        dynamic_queries: dynamic_queries(),
+        on_disk_cache,
+        fns: QuerySystemFns {
+            engine: engine(incremental),
+            local_providers,
+            extern_providers,
+            encode_query_results: encode_all_query_results,
+            try_mark_green: try_mark_green,
+        },
+        jobs: AtomicU64::new(1),
     }
 }
+
+rustc_query_append! { define_queries! }
diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs
index 9f8ac7ccd0b..244f0e84b43 100644
--- a/compiler/rustc_query_impl/src/plumbing.rs
+++ b/compiler/rustc_query_impl/src/plumbing.rs
@@ -4,6 +4,7 @@
 
 use crate::rustc_middle::dep_graph::DepContext;
 use crate::rustc_middle::ty::TyEncoder;
+use crate::QueryConfigRestored;
 use rustc_data_structures::stable_hasher::{Hash64, HashStable, StableHasher};
 use rustc_data_structures::sync::Lock;
 use rustc_errors::Diagnostic;
@@ -80,8 +81,8 @@ impl QueryContext for QueryCtxt<'_> {
     fn try_collect_active_jobs(self) -> Option<QueryMap<DepKind>> {
         let mut jobs = QueryMap::default();
 
-        for query in &self.query_system.fns.query_structs {
-            (query.try_collect_active_jobs)(self.tcx, &mut jobs);
+        for collect in super::TRY_COLLECT_ACTIVE_JOBS.iter() {
+            collect(self.tcx, &mut jobs);
         }
 
         Some(jobs)
@@ -182,10 +183,8 @@ pub(super) fn encode_all_query_results<'tcx>(
     encoder: &mut CacheEncoder<'_, 'tcx>,
     query_result_index: &mut EncodedDepNodeIndex,
 ) {
-    for query in &tcx.query_system.fns.query_structs {
-        if let Some(encode) = query.encode_query_results {
-            encode(tcx, encoder, query_result_index);
-        }
+    for encode in super::ENCODE_QUERY_RESULTS.iter().copied().filter_map(|e| e) {
+        encode(tcx, encoder, query_result_index);
     }
 }
 
@@ -265,14 +264,14 @@ macro_rules! hash_result {
 }
 
 macro_rules! call_provider {
-    ([][$qcx:expr, $name:ident, $key:expr]) => {{
-        ($qcx.query_system.fns.local_providers.$name)($qcx, $key)
+    ([][$tcx:expr, $name:ident, $key:expr]) => {{
+        ($tcx.query_system.fns.local_providers.$name)($tcx, $key)
     }};
-    ([(separate_provide_extern) $($rest:tt)*][$qcx:expr, $name:ident, $key:expr]) => {{
+    ([(separate_provide_extern) $($rest:tt)*][$tcx:expr, $name:ident, $key:expr]) => {{
         if let Some(key) = $key.as_local_key() {
-            ($qcx.query_system.fns.local_providers.$name)($qcx, key)
+            ($tcx.query_system.fns.local_providers.$name)($tcx, key)
         } else {
-            ($qcx.query_system.fns.extern_providers.$name)($qcx, $key)
+            ($tcx.query_system.fns.extern_providers.$name)($tcx, $key)
         }
     }};
     ([$other:tt $($modifiers:tt)*][$($args:tt)*]) => {
@@ -341,7 +340,7 @@ pub(crate) fn create_query_frame<
 }
 
 pub(crate) fn encode_query_results<'a, 'tcx, Q>(
-    query: Q,
+    query: Q::Config,
     qcx: QueryCtxt<'tcx>,
     encoder: &mut CacheEncoder<'a, 'tcx>,
     query_result_index: &mut EncodedDepNodeIndex,
@@ -392,12 +391,26 @@ pub(crate) fn loadable_from_disk<'tcx>(tcx: TyCtxt<'tcx>, id: SerializedDepNodeI
 
 pub(crate) fn try_load_from_disk<'tcx, V>(
     tcx: TyCtxt<'tcx>,
-    id: SerializedDepNodeIndex,
+    prev_index: SerializedDepNodeIndex,
+    index: DepNodeIndex,
 ) -> Option<V>
 where
     V: for<'a> Decodable<CacheDecoder<'a, 'tcx>>,
 {
-    tcx.query_system.on_disk_cache.as_ref()?.try_load_query_result(tcx, id)
+    let on_disk_cache = tcx.query_system.on_disk_cache.as_ref()?;
+
+    let prof_timer = tcx.prof.incr_cache_loading();
+
+    // The call to `with_query_deserialization` enforces that no new `DepNodes`
+    // are created during deserialization. See the docs of that method for more
+    // details.
+    let value = tcx
+        .dep_graph
+        .with_query_deserialization(|| on_disk_cache.try_load_query_result(tcx, prev_index));
+
+    prof_timer.finish_with_query_invocation_id(index.into());
+
+    value
 }
 
 fn force_from_dep_node<'tcx, Q>(query: Q, tcx: TyCtxt<'tcx>, dep_node: DepNode) -> bool
@@ -434,10 +447,9 @@ where
 
 pub(crate) fn query_callback<'tcx, Q>(is_anon: bool, is_eval_always: bool) -> DepKindStruct<'tcx>
 where
-    Q: QueryConfig<QueryCtxt<'tcx>> + Default,
-    Q::Key: DepNodeParams<TyCtxt<'tcx>>,
+    Q: QueryConfigRestored<'tcx>,
 {
-    let fingerprint_style = Q::Key::fingerprint_style();
+    let fingerprint_style = <Q::Config as QueryConfig<QueryCtxt<'tcx>>>::Key::fingerprint_style();
 
     if is_anon || !fingerprint_style.reconstructible() {
         return DepKindStruct {
@@ -453,13 +465,25 @@ where
         is_anon,
         is_eval_always,
         fingerprint_style,
-        force_from_dep_node: Some(|tcx, dep_node| force_from_dep_node(Q::default(), tcx, dep_node)),
+        force_from_dep_node: Some(|tcx, dep_node| {
+            force_from_dep_node(Q::config(tcx), tcx, dep_node)
+        }),
         try_load_from_on_disk_cache: Some(|tcx, dep_node| {
-            try_load_from_on_disk_cache(Q::default(), tcx, dep_node)
+            try_load_from_on_disk_cache(Q::config(tcx), tcx, dep_node)
         }),
     }
 }
 
+macro_rules! item_if_cached {
+    ([] $tokens:tt) => {};
+    ([(cache) $($rest:tt)*] { $($tokens:tt)* }) => {
+        $($tokens)*
+    };
+    ([$other:tt $($modifiers:tt)*] $tokens:tt) => {
+        item_if_cached! { [$($modifiers)*] $tokens }
+    };
+}
+
 macro_rules! expand_if_cached {
     ([], $tokens:expr) => {{
         None
@@ -472,193 +496,226 @@ macro_rules! expand_if_cached {
     };
 }
 
+/// Don't show the backtrace for query system by default
+/// use `RUST_BACKTRACE=full` to show all the backtraces
+#[inline(never)]
+pub fn __rust_begin_short_backtrace<F, T>(f: F) -> T
+where
+    F: FnOnce() -> T,
+{
+    let result = f();
+    std::hint::black_box(());
+    result
+}
+
 // NOTE: `$V` isn't used here, but we still need to match on it so it can be passed to other macros
 // invoked by `rustc_query_append`.
 macro_rules! define_queries {
     (
      $($(#[$attr:meta])*
         [$($modifiers:tt)*] fn $name:ident($($K:tt)*) -> $V:ty,)*) => {
-        mod get_query {
-            use super::*;
 
-            $(
-                #[inline(always)]
-                #[tracing::instrument(level = "trace", skip(tcx))]
-                pub(super) fn $name<'tcx>(
+        pub(crate) mod query_impl { $(pub mod $name {
+            use super::super::*;
+            use std::marker::PhantomData;
+
+            pub mod get_query_incr {
+                use super::*;
+
+                // Adding `__rust_end_short_backtrace` marker to backtraces so that we emit the frames
+                // when `RUST_BACKTRACE=1`, add a new mod with `$name` here is to allow duplicate naming
+                #[inline(never)]
+                pub fn __rust_end_short_backtrace<'tcx>(
                     tcx: TyCtxt<'tcx>,
                     span: Span,
-                    key: query_keys::$name<'tcx>,
+                    key: queries::$name::Key<'tcx>,
                     mode: QueryMode,
-                ) -> Option<Erase<query_values::$name<'tcx>>> {
-                    get_query(
-                        queries::$name::default(),
+                ) -> Option<Erase<queries::$name::Value<'tcx>>> {
+                    get_query_incr(
+                        QueryType::config(tcx),
                         QueryCtxt::new(tcx),
                         span,
                         key,
                         mode
                     )
                 }
-            )*
-        }
-
-        pub(crate) fn engine() -> QueryEngine {
-            QueryEngine {
-                $($name: get_query::$name,)*
             }
-        }
 
-        #[allow(nonstandard_style)]
-        mod queries {
-            use std::marker::PhantomData;
+            pub mod get_query_non_incr {
+                use super::*;
 
-            $(
-                #[derive(Copy, Clone, Default)]
-                pub struct $name<'tcx> {
-                    data: PhantomData<&'tcx ()>
+                #[inline(never)]
+                pub fn __rust_end_short_backtrace<'tcx>(
+                    tcx: TyCtxt<'tcx>,
+                    span: Span,
+                    key: queries::$name::Key<'tcx>,
+                    __mode: QueryMode,
+                ) -> Option<Erase<queries::$name::Value<'tcx>>> {
+                    Some(get_query_non_incr(
+                        QueryType::config(tcx),
+                        QueryCtxt::new(tcx),
+                        span,
+                        key,
+                    ))
                 }
-            )*
-        }
-
-        $(impl<'tcx> QueryConfig<QueryCtxt<'tcx>> for queries::$name<'tcx> {
-            type Key = query_keys::$name<'tcx>;
-            type Value = Erase<query_values::$name<'tcx>>;
-
-            #[inline(always)]
-            fn name(self) -> &'static str {
-                stringify!($name)
-            }
-
-            #[inline]
-            fn format_value(self) -> fn(&Self::Value) -> String {
-                |value| format!("{:?}", restore::<query_values::$name<'tcx>>(*value))
-            }
-
-            #[inline]
-            fn cache_on_disk(self, tcx: TyCtxt<'tcx>, key: &Self::Key) -> bool {
-                ::rustc_middle::query::cached::$name(tcx, key)
             }
 
-            type Cache = query_storage::$name<'tcx>;
-
-            #[inline(always)]
-            fn query_state<'a>(self, tcx: QueryCtxt<'tcx>) -> &'a QueryState<Self::Key, crate::dep_graph::DepKind>
-                where QueryCtxt<'tcx>: 'a
-            {
-                &tcx.query_system.states.$name
+            pub fn dynamic_query<'tcx>() -> DynamicQuery<'tcx, queries::$name::Storage<'tcx>> {
+                DynamicQuery {
+                    name: stringify!($name),
+                    eval_always: is_eval_always!([$($modifiers)*]),
+                    dep_kind: dep_graph::DepKind::$name,
+                    handle_cycle_error: handle_cycle_error!([$($modifiers)*]),
+                    query_state: offset_of!(QueryStates<'tcx> => $name),
+                    query_cache: offset_of!(QueryCaches<'tcx> => $name),
+                    cache_on_disk: |tcx, key| ::rustc_middle::query::cached::$name(tcx, key),
+                    execute_query: |tcx, key| erase(tcx.$name(key)),
+                    compute: |tcx, key| {
+                        __rust_begin_short_backtrace(||
+                            queries::$name::provided_to_erased(
+                                tcx,
+                                call_provider!([$($modifiers)*][tcx, $name, key])
+                            )
+                        )
+                    },
+                    can_load_from_disk: should_ever_cache_on_disk!([$($modifiers)*] true false),
+                    try_load_from_disk: should_ever_cache_on_disk!([$($modifiers)*] {
+                        |tcx, key, prev_index, index| {
+                            if ::rustc_middle::query::cached::$name(tcx, key) {
+                                let value = $crate::plumbing::try_load_from_disk::<
+                                    queries::$name::ProvidedValue<'tcx>
+                                >(
+                                    tcx,
+                                    prev_index,
+                                    index,
+                                );
+                                value.map(|value| queries::$name::provided_to_erased(tcx, value))
+                            } else {
+                                None
+                            }
+                        }
+                    } {
+                        |_tcx, _key, _prev_index, _index| None
+                    }),
+                    value_from_cycle_error: |tcx, cycle| {
+                        let result: queries::$name::Value<'tcx> = Value::from_cycle_error(tcx, cycle);
+                        erase(result)
+                    },
+                    loadable_from_disk: |_tcx, _key, _index| {
+                        should_ever_cache_on_disk!([$($modifiers)*] {
+                            ::rustc_middle::query::cached::$name(_tcx, _key) &&
+                                $crate::plumbing::loadable_from_disk(_tcx, _index)
+                        } {
+                            false
+                        })
+                    },
+                    hash_result: hash_result!([$($modifiers)*][queries::$name::Value<'tcx>]),
+                    format_value: |value| format!("{:?}", restore::<queries::$name::Value<'tcx>>(*value)),
+                }
             }
 
-            #[inline(always)]
-            fn query_cache<'a>(self, tcx: QueryCtxt<'tcx>) -> &'a Self::Cache
-                where 'tcx:'a
-            {
-                &tcx.query_system.caches.$name
+            #[derive(Copy, Clone, Default)]
+            pub struct QueryType<'tcx> {
+                data: PhantomData<&'tcx ()>
             }
 
-            fn execute_query(self, tcx: TyCtxt<'tcx>, key: Self::Key) -> Self::Value {
-                erase(tcx.$name(key))
-            }
+            impl<'tcx> QueryConfigRestored<'tcx> for QueryType<'tcx> {
+                type RestoredValue = queries::$name::Value<'tcx>;
+                type Config = DynamicConfig<
+                    'tcx,
+                    queries::$name::Storage<'tcx>,
+                    { is_anon!([$($modifiers)*]) },
+                    { depth_limit!([$($modifiers)*]) },
+                    { feedable!([$($modifiers)*]) },
+                >;
 
-            #[inline]
-            #[allow(unused_variables)]
-            fn compute(self, qcx: QueryCtxt<'tcx>, key: Self::Key) -> Self::Value {
-                query_provided_to_value::$name(
-                    qcx.tcx,
-                    call_provider!([$($modifiers)*][qcx.tcx, $name, key])
-                )
-            }
-
-            #[inline]
-            fn try_load_from_disk(
-                self,
-                _qcx: QueryCtxt<'tcx>,
-                _key: &Self::Key
-            ) -> rustc_query_system::query::TryLoadFromDisk<QueryCtxt<'tcx>, Self::Value> {
-                should_ever_cache_on_disk!([$($modifiers)*] {
-                    if ::rustc_middle::query::cached::$name(_qcx.tcx, _key) {
-                        Some(|qcx: QueryCtxt<'tcx>, dep_node| {
-                            let value = $crate::plumbing::try_load_from_disk::<query_provided::$name<'tcx>>(
-                                qcx.tcx,
-                                dep_node
-                            );
-                            value.map(|value| query_provided_to_value::$name(qcx.tcx, value))
-                        })
-                    } else {
-                        None
+                #[inline(always)]
+                fn config(tcx: TyCtxt<'tcx>) -> Self::Config {
+                    DynamicConfig {
+                        dynamic: &tcx.query_system.dynamic_queries.$name,
                     }
-                } {
-                    None
-                })
-            }
-
-            #[inline]
-            fn loadable_from_disk(
-                self,
-                _qcx: QueryCtxt<'tcx>,
-                _key: &Self::Key,
-                _index: SerializedDepNodeIndex,
-            ) -> bool {
-                should_ever_cache_on_disk!([$($modifiers)*] {
-                    self.cache_on_disk(_qcx.tcx, _key) &&
-                        $crate::plumbing::loadable_from_disk(_qcx.tcx, _index)
-                } {
-                    false
-                })
-            }
+                }
 
-            #[inline]
-            fn value_from_cycle_error(
-                self,
-                tcx: TyCtxt<'tcx>,
-                cycle: &[QueryInfo<DepKind>],
-            ) -> Self::Value {
-                let result: query_values::$name<'tcx> = Value::from_cycle_error(tcx, cycle);
-                erase(result)
+                #[inline(always)]
+                fn restore(value: <Self::Config as QueryConfig<QueryCtxt<'tcx>>>::Value) -> Self::RestoredValue {
+                    restore::<queries::$name::Value<'tcx>>(value)
+                }
             }
 
-            #[inline(always)]
-            fn anon(self) -> bool {
-                is_anon!([$($modifiers)*])
+            pub fn try_collect_active_jobs<'tcx>(tcx: TyCtxt<'tcx>, qmap: &mut QueryMap<DepKind>) {
+                let make_query = |tcx, key| {
+                    let kind = rustc_middle::dep_graph::DepKind::$name;
+                    let name = stringify!($name);
+                    $crate::plumbing::create_query_frame(tcx, rustc_middle::query::descs::$name, key, kind, name)
+                };
+                tcx.query_system.states.$name.try_collect_active_jobs(
+                    tcx,
+                    make_query,
+                    qmap,
+                ).unwrap();
             }
 
-            #[inline(always)]
-            fn eval_always(self) -> bool {
-                is_eval_always!([$($modifiers)*])
+            pub fn alloc_self_profile_query_strings<'tcx>(tcx: TyCtxt<'tcx>, string_cache: &mut QueryKeyStringCache) {
+                $crate::profiling_support::alloc_self_profile_query_strings_for_query_cache(
+                    tcx,
+                    stringify!($name),
+                    &tcx.query_system.caches.$name,
+                    string_cache,
+                )
             }
 
-            #[inline(always)]
-            fn depth_limit(self) -> bool {
-                depth_limit!([$($modifiers)*])
-            }
+            item_if_cached! { [$($modifiers)*] {
+                pub fn encode_query_results<'tcx>(
+                    tcx: TyCtxt<'tcx>,
+                    encoder: &mut CacheEncoder<'_, 'tcx>,
+                    query_result_index: &mut EncodedDepNodeIndex
+                ) {
+                    $crate::plumbing::encode_query_results::<query_impl::$name::QueryType<'tcx>>(
+                        query_impl::$name::QueryType::config(tcx),
+                        QueryCtxt::new(tcx),
+                        encoder,
+                        query_result_index,
+                    )
+                }
+            }}
+        })*}
 
-            #[inline(always)]
-            fn feedable(self) -> bool {
-                feedable!([$($modifiers)*])
+        pub(crate) fn engine(incremental: bool) -> QueryEngine {
+            if incremental {
+                QueryEngine {
+                    $($name: query_impl::$name::get_query_incr::__rust_end_short_backtrace,)*
+                }
+            } else {
+                QueryEngine {
+                    $($name: query_impl::$name::get_query_non_incr::__rust_end_short_backtrace,)*
+                }
             }
+        }
 
-            #[inline(always)]
-            fn dep_kind(self) -> rustc_middle::dep_graph::DepKind {
-                dep_graph::DepKind::$name
+        pub fn dynamic_queries<'tcx>() -> DynamicQueries<'tcx> {
+            DynamicQueries {
+                $(
+                    $name: query_impl::$name::dynamic_query(),
+                )*
             }
+        }
 
-            #[inline(always)]
-            fn handle_cycle_error(self) -> rustc_query_system::HandleCycleError {
-                handle_cycle_error!([$($modifiers)*])
-            }
+        // These arrays are used for iteration and can't be indexed by `DepKind`.
 
-            #[inline(always)]
-            fn hash_result(self) -> rustc_query_system::query::HashResult<Self::Value> {
-                hash_result!([$($modifiers)*][query_values::$name<'tcx>])
-            }
-        })*
+        const TRY_COLLECT_ACTIVE_JOBS: &[for<'tcx> fn(TyCtxt<'tcx>, &mut QueryMap<DepKind>)] =
+            &[$(query_impl::$name::try_collect_active_jobs),*];
 
-        $(impl<'tcx> QueryConfigRestored<'tcx> for queries::$name<'tcx> {
-            type RestoredValue = query_values::$name<'tcx>;
+        const ALLOC_SELF_PROFILE_QUERY_STRINGS: &[
+            for<'tcx> fn(TyCtxt<'tcx>, &mut QueryKeyStringCache)
+        ] = &[$(query_impl::$name::alloc_self_profile_query_strings),*];
 
-            #[inline(always)]
-            fn restore(value: <Self as QueryConfig<QueryCtxt<'tcx>>>::Value) -> Self::RestoredValue {
-                restore::<query_values::$name<'tcx>>(value)
-            }
-        })*
+        const ENCODE_QUERY_RESULTS: &[
+            Option<for<'tcx> fn(
+                TyCtxt<'tcx>,
+                &mut CacheEncoder<'_, 'tcx>,
+                &mut EncodedDepNodeIndex)
+            >
+        ] = &[$(expand_if_cached!([$($modifiers)*], query_impl::$name::encode_query_results)),*];
 
         #[allow(nonstandard_style)]
         mod query_callbacks {
@@ -718,71 +775,13 @@ macro_rules! define_queries {
             }
 
             $(pub(crate) fn $name<'tcx>()-> DepKindStruct<'tcx> {
-                $crate::plumbing::query_callback::<queries::$name<'tcx>>(
+                $crate::plumbing::query_callback::<query_impl::$name::QueryType<'tcx>>(
                     is_anon!([$($modifiers)*]),
                     is_eval_always!([$($modifiers)*]),
                 )
             })*
         }
 
-        mod query_structs {
-            use super::*;
-            use rustc_middle::ty::query::QueryStruct;
-            use rustc_middle::ty::query::QueryKeyStringCache;
-            use rustc_middle::dep_graph::DepKind;
-
-            pub(super) const fn dummy_query_struct<'tcx>() -> QueryStruct<'tcx> {
-                fn noop_try_collect_active_jobs(_: TyCtxt<'_>, _: &mut QueryMap<DepKind>) -> Option<()> {
-                    None
-                }
-                fn noop_alloc_self_profile_query_strings(_: TyCtxt<'_>, _: &mut QueryKeyStringCache) {}
-
-                QueryStruct {
-                    try_collect_active_jobs: noop_try_collect_active_jobs,
-                    alloc_self_profile_query_strings: noop_alloc_self_profile_query_strings,
-                    encode_query_results: None,
-                }
-            }
-
-            pub(super) use dummy_query_struct as Null;
-            pub(super) use dummy_query_struct as Red;
-            pub(super) use dummy_query_struct as TraitSelect;
-            pub(super) use dummy_query_struct as CompileCodegenUnit;
-            pub(super) use dummy_query_struct as CompileMonoItem;
-
-            $(
-            pub(super) const fn $name<'tcx>() -> QueryStruct<'tcx> { QueryStruct {
-                try_collect_active_jobs: |tcx, qmap| {
-                    let make_query = |tcx, key| {
-                        let kind = rustc_middle::dep_graph::DepKind::$name;
-                        let name = stringify!($name);
-                        $crate::plumbing::create_query_frame(tcx, rustc_middle::query::descs::$name, key, kind, name)
-                    };
-                    tcx.query_system.states.$name.try_collect_active_jobs(
-                        tcx,
-                        make_query,
-                        qmap,
-                    )
-                },
-                alloc_self_profile_query_strings: |tcx, string_cache| {
-                    $crate::profiling_support::alloc_self_profile_query_strings_for_query_cache(
-                        tcx,
-                        stringify!($name),
-                        &tcx.query_system.caches.$name,
-                        string_cache,
-                    )
-                },
-                encode_query_results: expand_if_cached!([$($modifiers)*], |tcx, encoder, query_result_index|
-                    $crate::plumbing::encode_query_results::<super::queries::$name<'tcx>>(
-                        super::queries::$name::default(),
-                        QueryCtxt::new(tcx),
-                        encoder,
-                        query_result_index,
-                    )
-                ),
-            }})*
-        }
-
         pub fn query_callbacks<'tcx>(arena: &'tcx Arena<'tcx>) -> &'tcx [DepKindStruct<'tcx>] {
             arena.alloc_from_iter(make_dep_kind_array!(query_callbacks))
         }
diff --git a/compiler/rustc_query_impl/src/profiling_support.rs b/compiler/rustc_query_impl/src/profiling_support.rs
index 7d9306f8087..fbc6db93e01 100644
--- a/compiler/rustc_query_impl/src/profiling_support.rs
+++ b/compiler/rustc_query_impl/src/profiling_support.rs
@@ -2,7 +2,7 @@ use measureme::{StringComponent, StringId};
 use rustc_data_structures::profiling::SelfProfiler;
 use rustc_hir::def_id::{CrateNum, DefId, DefIndex, LocalDefId, LOCAL_CRATE};
 use rustc_hir::definitions::DefPathData;
-use rustc_middle::ty::query::QueryKeyStringCache;
+use rustc_middle::query::plumbing::QueryKeyStringCache;
 use rustc_middle::ty::TyCtxt;
 use rustc_query_system::query::QueryCache;
 use std::fmt::Debug;
@@ -243,7 +243,7 @@ pub fn alloc_self_profile_query_strings(tcx: TyCtxt<'_>) {
 
     let mut string_cache = QueryKeyStringCache::new();
 
-    for query in &tcx.query_system.fns.query_structs {
-        (query.alloc_self_profile_query_strings)(tcx, &mut string_cache);
+    for alloc in super::ALLOC_SELF_PROFILE_QUERY_STRINGS.iter() {
+        alloc(tcx, &mut string_cache)
     }
 }
diff --git a/compiler/rustc_query_system/src/query/config.rs b/compiler/rustc_query_system/src/query/config.rs
index bb9ea50a1ea..7e47d701205 100644
--- a/compiler/rustc_query_system/src/query/config.rs
+++ b/compiler/rustc_query_system/src/query/config.rs
@@ -4,6 +4,7 @@ use crate::dep_graph::{DepNode, DepNodeParams, SerializedDepNodeIndex};
 use crate::error::HandleCycleError;
 use crate::ich::StableHashingContext;
 use crate::query::caches::QueryCache;
+use crate::query::DepNodeIndex;
 use crate::query::{QueryContext, QueryInfo, QueryState};
 
 use rustc_data_structures::fingerprint::Fingerprint;
@@ -12,8 +13,6 @@ use std::hash::Hash;
 
 pub type HashResult<V> = Option<fn(&mut StableHashingContext<'_>, &V) -> Fingerprint>;
 
-pub type TryLoadFromDisk<Qcx, V> = Option<fn(Qcx, SerializedDepNodeIndex) -> Option<V>>;
-
 pub trait QueryConfig<Qcx: QueryContext>: Copy {
     fn name(self) -> &'static str;
 
@@ -43,7 +42,13 @@ pub trait QueryConfig<Qcx: QueryContext>: Copy {
 
     fn compute(self, tcx: Qcx, key: Self::Key) -> Self::Value;
 
-    fn try_load_from_disk(self, qcx: Qcx, idx: &Self::Key) -> TryLoadFromDisk<Qcx, Self::Value>;
+    fn try_load_from_disk(
+        self,
+        tcx: Qcx,
+        key: &Self::Key,
+        prev_index: SerializedDepNodeIndex,
+        index: DepNodeIndex,
+    ) -> Option<Self::Value>;
 
     fn loadable_from_disk(self, qcx: Qcx, key: &Self::Key, idx: SerializedDepNodeIndex) -> bool;
 
diff --git a/compiler/rustc_query_system/src/query/mod.rs b/compiler/rustc_query_system/src/query/mod.rs
index fa1f51b04da..f7619d75be7 100644
--- a/compiler/rustc_query_system/src/query/mod.rs
+++ b/compiler/rustc_query_system/src/query/mod.rs
@@ -12,7 +12,7 @@ pub use self::caches::{
 };
 
 mod config;
-pub use self::config::{HashResult, QueryConfig, TryLoadFromDisk};
+pub use self::config::{HashResult, QueryConfig};
 
 use crate::dep_graph::DepKind;
 use crate::dep_graph::{DepNodeIndex, HasDepContext, SerializedDepNodeIndex};
diff --git a/compiler/rustc_query_system/src/query/plumbing.rs b/compiler/rustc_query_system/src/query/plumbing.rs
index 3b17c665fb7..730e4c8d30d 100644
--- a/compiler/rustc_query_system/src/query/plumbing.rs
+++ b/compiler/rustc_query_system/src/query/plumbing.rs
@@ -312,7 +312,7 @@ where
 }
 
 #[inline(never)]
-fn try_execute_query<Q, Qcx>(
+fn try_execute_query<Q, Qcx, const INCR: bool>(
     query: Q,
     qcx: Qcx,
     span: Span,
@@ -355,7 +355,7 @@ where
             // Drop the lock before we start executing the query
             drop(state_lock);
 
-            execute_job(query, qcx, state, key, id, dep_node)
+            execute_job::<_, _, INCR>(query, qcx, state, key, id, dep_node)
         }
         Entry::Occupied(mut entry) => {
             match entry.get_mut() {
@@ -383,7 +383,7 @@ where
 }
 
 #[inline(always)]
-fn execute_job<Q, Qcx>(
+fn execute_job<Q, Qcx, const INCR: bool>(
     query: Q,
     qcx: Qcx,
     state: &QueryState<Q::Key, Qcx::DepKind>,
@@ -398,9 +398,19 @@ where
     // Use `JobOwner` so the query will be poisoned if executing it panics.
     let job_owner = JobOwner { state, key };
 
-    let (result, dep_node_index) = match qcx.dep_context().dep_graph().data() {
-        None => execute_job_non_incr(query, qcx, key, id),
-        Some(data) => execute_job_incr(query, qcx, data, key, dep_node, id),
+    debug_assert_eq!(qcx.dep_context().dep_graph().is_fully_enabled(), INCR);
+
+    let (result, dep_node_index) = if INCR {
+        execute_job_incr(
+            query,
+            qcx,
+            qcx.dep_context().dep_graph().data().unwrap(),
+            key,
+            dep_node,
+            id,
+        )
+    } else {
+        execute_job_non_incr(query, qcx, key, id)
     };
 
     let cache = query.query_cache(qcx);
@@ -423,16 +433,22 @@ where
                 (hasher(&mut hcx, &cached_result), hasher(&mut hcx, &result))
             });
             let formatter = query.format_value();
-            debug_assert_eq!(
-                old_hash,
-                new_hash,
-                "Computed query value for {:?}({:?}) is inconsistent with fed value,\n\
-                computed={:#?}\nfed={:#?}",
-                query.dep_kind(),
-                key,
-                formatter(&result),
-                formatter(&cached_result),
-            );
+            if old_hash != new_hash {
+                // We have an inconsistency. This can happen if one of the two
+                // results is tainted by errors. In this case, delay a bug to
+                // ensure compilation is doomed.
+                qcx.dep_context().sess().delay_span_bug(
+                    DUMMY_SP,
+                    format!(
+                        "Computed query value for {:?}({:?}) is inconsistent with fed value,\n\
+                        computed={:#?}\nfed={:#?}",
+                        query.dep_kind(),
+                        key,
+                        formatter(&result),
+                        formatter(&cached_result),
+                    ),
+                );
+            }
         }
     }
     job_owner.complete(cache, result, dep_node_index);
@@ -564,59 +580,44 @@ where
 
     // First we try to load the result from the on-disk cache.
     // Some things are never cached on disk.
-    if let Some(try_load_from_disk) = query.try_load_from_disk(qcx, &key) {
-        let prof_timer = qcx.dep_context().profiler().incr_cache_loading();
-
-        // The call to `with_query_deserialization` enforces that no new `DepNodes`
-        // are created during deserialization. See the docs of that method for more
-        // details.
-        let result = qcx
-            .dep_context()
-            .dep_graph()
-            .with_query_deserialization(|| try_load_from_disk(qcx, prev_dep_node_index));
-
-        prof_timer.finish_with_query_invocation_id(dep_node_index.into());
-
-        if let Some(result) = result {
-            if std::intrinsics::unlikely(
-                qcx.dep_context().sess().opts.unstable_opts.query_dep_graph,
-            ) {
-                dep_graph_data.mark_debug_loaded_from_disk(*dep_node)
-            }
-
-            let prev_fingerprint = dep_graph_data.prev_fingerprint_of(prev_dep_node_index);
-            // If `-Zincremental-verify-ich` is specified, re-hash results from
-            // the cache and make sure that they have the expected fingerprint.
-            //
-            // If not, we still seek to verify a subset of fingerprints loaded
-            // from disk. Re-hashing results is fairly expensive, so we can't
-            // currently afford to verify every hash. This subset should still
-            // give us some coverage of potential bugs though.
-            let try_verify = prev_fingerprint.split().1.as_u64() % 32 == 0;
-            if std::intrinsics::unlikely(
-                try_verify || qcx.dep_context().sess().opts.unstable_opts.incremental_verify_ich,
-            ) {
-                incremental_verify_ich(
-                    *qcx.dep_context(),
-                    dep_graph_data,
-                    &result,
-                    prev_dep_node_index,
-                    query.hash_result(),
-                    query.format_value(),
-                );
-            }
+    if let Some(result) = query.try_load_from_disk(qcx, key, prev_dep_node_index, dep_node_index) {
+        if std::intrinsics::unlikely(qcx.dep_context().sess().opts.unstable_opts.query_dep_graph) {
+            dep_graph_data.mark_debug_loaded_from_disk(*dep_node)
+        }
 
-            return Some((result, dep_node_index));
+        let prev_fingerprint = dep_graph_data.prev_fingerprint_of(prev_dep_node_index);
+        // If `-Zincremental-verify-ich` is specified, re-hash results from
+        // the cache and make sure that they have the expected fingerprint.
+        //
+        // If not, we still seek to verify a subset of fingerprints loaded
+        // from disk. Re-hashing results is fairly expensive, so we can't
+        // currently afford to verify every hash. This subset should still
+        // give us some coverage of potential bugs though.
+        let try_verify = prev_fingerprint.split().1.as_u64() % 32 == 0;
+        if std::intrinsics::unlikely(
+            try_verify || qcx.dep_context().sess().opts.unstable_opts.incremental_verify_ich,
+        ) {
+            incremental_verify_ich(
+                *qcx.dep_context(),
+                dep_graph_data,
+                &result,
+                prev_dep_node_index,
+                query.hash_result(),
+                query.format_value(),
+            );
         }
 
-        // We always expect to find a cached result for things that
-        // can be forced from `DepNode`.
-        debug_assert!(
-            !qcx.dep_context().fingerprint_style(dep_node.kind).reconstructible(),
-            "missing on-disk cache entry for reconstructible {dep_node:?}"
-        );
+        return Some((result, dep_node_index));
     }
 
+    // We always expect to find a cached result for things that
+    // can be forced from `DepNode`.
+    debug_assert!(
+        !query.cache_on_disk(*qcx.dep_context(), key)
+            || !qcx.dep_context().fingerprint_style(dep_node.kind).reconstructible(),
+        "missing on-disk cache entry for {dep_node:?}"
+    );
+
     // Sanity check for the logic in `ensure`: if the node is green and the result loadable,
     // we should actually be able to load it.
     debug_assert!(
@@ -799,7 +800,18 @@ pub enum QueryMode {
 }
 
 #[inline(always)]
-pub fn get_query<Q, Qcx>(
+pub fn get_query_non_incr<Q, Qcx>(query: Q, qcx: Qcx, span: Span, key: Q::Key) -> Q::Value
+where
+    Q: QueryConfig<Qcx>,
+    Qcx: QueryContext,
+{
+    debug_assert!(!qcx.dep_context().dep_graph().is_fully_enabled());
+
+    ensure_sufficient_stack(|| try_execute_query::<Q, Qcx, false>(query, qcx, span, key, None).0)
+}
+
+#[inline(always)]
+pub fn get_query_incr<Q, Qcx>(
     query: Q,
     qcx: Qcx,
     span: Span,
@@ -810,6 +822,8 @@ where
     Q: QueryConfig<Qcx>,
     Qcx: QueryContext,
 {
+    debug_assert!(qcx.dep_context().dep_graph().is_fully_enabled());
+
     let dep_node = if let QueryMode::Ensure { check_cache } = mode {
         let (must_run, dep_node) = ensure_must_run(query, qcx, &key, check_cache);
         if !must_run {
@@ -820,8 +834,9 @@ where
         None
     };
 
-    let (result, dep_node_index) =
-        ensure_sufficient_stack(|| try_execute_query(query, qcx, span, key, dep_node));
+    let (result, dep_node_index) = ensure_sufficient_stack(|| {
+        try_execute_query::<_, _, true>(query, qcx, span, key, dep_node)
+    });
     if let Some(dep_node_index) = dep_node_index {
         qcx.dep_context().dep_graph().read_index(dep_node_index)
     }
@@ -846,5 +861,7 @@ pub fn force_query<Q, Qcx>(
 
     debug_assert!(!query.anon());
 
-    ensure_sufficient_stack(|| try_execute_query(query, qcx, DUMMY_SP, key, Some(dep_node)));
+    ensure_sufficient_stack(|| {
+        try_execute_query::<_, _, true>(query, qcx, DUMMY_SP, key, Some(dep_node))
+    });
 }
diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs
index 2438b3a38ed..08b73ebb694 100644
--- a/compiler/rustc_resolve/src/build_reduced_graph.rs
+++ b/compiler/rustc_resolve/src/build_reduced_graph.rs
@@ -9,12 +9,9 @@ use crate::def_collector::collect_definitions;
 use crate::imports::{Import, ImportKind};
 use crate::macros::{MacroRulesBinding, MacroRulesScope, MacroRulesScopeRef};
 use crate::Namespace::{self, MacroNS, TypeNS, ValueNS};
-use crate::{
-    errors, Determinacy, ExternPreludeEntry, Finalize, Module, ModuleKind, ModuleOrUniformRoot,
-};
-use crate::{
-    MacroData, NameBinding, NameBindingKind, ParentScope, PathResult, PerNS, ResolutionError,
-};
+use crate::{errors, BindingKey, MacroData};
+use crate::{Determinacy, ExternPreludeEntry, Finalize, Module, ModuleKind, ModuleOrUniformRoot};
+use crate::{NameBinding, NameBindingKind, ParentScope, PathResult, PerNS, ResolutionError};
 use crate::{Resolver, ResolverArenas, Segment, ToNameBinding, VisResolutionError};
 
 use rustc_ast::visit::{self, AssocCtxt, Visitor};
@@ -72,7 +69,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
         T: ToNameBinding<'a>,
     {
         let binding = def.to_name_binding(self.arenas);
-        let key = self.new_key(ident, ns);
+        let key = self.new_disambiguated_key(ident, ns);
         if let Err(old_binding) = self.try_define(parent, key, binding) {
             self.report_conflict(parent, ident, ns, old_binding, &binding);
         }
@@ -379,7 +376,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> {
             ImportKind::Single { target, type_ns_only, .. } => {
                 self.r.per_ns(|this, ns| {
                     if !type_ns_only || ns == TypeNS {
-                        let key = this.new_key(target, ns);
+                        let key = BindingKey::new(target, ns);
                         let mut resolution = this.resolution(current_module, key).borrow_mut();
                         resolution.add_single_import(import);
                     }
diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs
index 6675b8ed59b..ed0a792d387 100644
--- a/compiler/rustc_resolve/src/diagnostics.rs
+++ b/compiler/rustc_resolve/src/diagnostics.rs
@@ -28,10 +28,10 @@ use rustc_span::symbol::{kw, sym, Ident, Symbol};
 use rustc_span::{BytePos, Span, SyntaxContext};
 use thin_vec::ThinVec;
 
-use crate::errors as errs;
 use crate::imports::{Import, ImportKind};
 use crate::late::{PatternSource, Rib};
 use crate::path_names_to_string;
+use crate::{errors as errs, BindingKey};
 use crate::{AmbiguityError, AmbiguityErrorMisc, AmbiguityKind, BindingError, Finalize};
 use crate::{HasGenericParams, MacroRulesScope, Module, ModuleKind, ModuleOrUniformRoot};
 use crate::{LexicalScopeBinding, NameBinding, NameBindingKind, PrivacyError, VisResolutionError};
@@ -550,7 +550,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
 
                 let sm = self.tcx.sess.source_map();
                 let def_id = match outer_res {
-                    Res::SelfTyParam { .. } | Res::SelfCtor(_) => {
+                    Res::SelfTyParam { .. } => {
                         err.span_label(span, "can't use `Self` here");
                         return err;
                     }
@@ -1832,7 +1832,17 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
             }
             (msg, None)
         } else if ident.name == kw::SelfUpper {
-            ("`Self` is only available in impls, traits, and type definitions".to_string(), None)
+            // As mentioned above, `opt_ns` being `None` indicates a module path in import.
+            // We can use this to improve a confusing error for, e.g. `use Self::Variant` in an
+            // impl
+            if opt_ns.is_none() {
+                ("`Self` cannot be used in imports".to_string(), None)
+            } else {
+                (
+                    "`Self` is only available in impls, traits, and type definitions".to_string(),
+                    None,
+                )
+            }
         } else if ident.name.as_str().chars().next().map_or(false, |c| c.is_ascii_uppercase()) {
             // Check whether the name refers to an item in the value namespace.
             let binding = if let Some(ribs) = ribs {
@@ -2081,7 +2091,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
         }
 
         let resolutions = self.resolutions(crate_module).borrow();
-        let resolution = resolutions.get(&self.new_key(ident, MacroNS))?;
+        let binding_key = BindingKey::new(ident, MacroNS);
+        let resolution = resolutions.get(&binding_key)?;
         let binding = resolution.borrow().binding()?;
         if let Res::Def(DefKind::Macro(MacroKind::Bang), _) = binding.res() {
             let module_name = crate_module.kind.name().unwrap();
diff --git a/compiler/rustc_resolve/src/effective_visibilities.rs b/compiler/rustc_resolve/src/effective_visibilities.rs
index 87067189a77..7393bdb388a 100644
--- a/compiler/rustc_resolve/src/effective_visibilities.rs
+++ b/compiler/rustc_resolve/src/effective_visibilities.rs
@@ -199,7 +199,7 @@ impl<'r, 'a, 'tcx> EffectiveVisibilitiesVisitor<'r, 'a, 'tcx> {
         let tcx = self.r.tcx;
         self.changed |= self.import_effective_visibilities.update(
             binding,
-            nominal_vis,
+            Some(nominal_vis),
             || cheap_private_vis.unwrap_or_else(|| self.r.private_vis_import(binding)),
             inherited_eff_vis,
             parent_id.level(),
@@ -213,7 +213,7 @@ impl<'r, 'a, 'tcx> EffectiveVisibilitiesVisitor<'r, 'a, 'tcx> {
         let tcx = self.r.tcx;
         self.changed |= self.def_effective_visibilities.update(
             def_id,
-            nominal_vis,
+            Some(nominal_vis),
             || cheap_private_vis.unwrap_or_else(|| self.r.private_vis_def(def_id)),
             inherited_eff_vis,
             parent_id.level(),
diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs
index 755acdd81fe..945c7ce3a9b 100644
--- a/compiler/rustc_resolve/src/ident.rs
+++ b/compiler/rustc_resolve/src/ident.rs
@@ -18,6 +18,7 @@ use crate::late::{
     ConstantHasGenerics, HasGenericParams, NoConstantGenericsReason, PathSource, Rib, RibKind,
 };
 use crate::macros::{sub_namespace_match, MacroRulesScope};
+use crate::BindingKey;
 use crate::{errors, AmbiguityError, AmbiguityErrorMisc, AmbiguityKind, Determinacy, Finalize};
 use crate::{Import, ImportKind, LexicalScopeBinding, Module, ModuleKind, ModuleOrUniformRoot};
 use crate::{NameBinding, NameBindingKind, ParentScope, PathResult, PrivacyError, Res};
@@ -865,7 +866,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
             }
         };
 
-        let key = self.new_key(ident, ns);
+        let key = BindingKey::new(ident, ns);
         let resolution =
             self.resolution(module, key).try_borrow_mut().map_err(|_| (Determined, Weak::No))?; // This happens when there is a cycle of imports.
 
@@ -1174,10 +1175,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                     return Res::Err;
                 }
             }
-            Res::Def(DefKind::TyParam, _)
-            | Res::SelfTyParam { .. }
-            | Res::SelfTyAlias { .. }
-            | Res::SelfCtor(_) => {
+            Res::Def(DefKind::TyParam, _) | Res::SelfTyParam { .. } | Res::SelfTyAlias { .. } => {
                 for rib in ribs {
                     let has_generic_params: HasGenericParams = match rib.kind {
                         RibKind::Normal
diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs
index 9e4429507b1..7c4c05d4b94 100644
--- a/compiler/rustc_resolve/src/imports.rs
+++ b/compiler/rustc_resolve/src/imports.rs
@@ -405,17 +405,18 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
         t
     }
 
-    // Define a dummy resolution containing a `Res::Err` as a placeholder for a failed resolution,
-    // also mark such failed imports as used to avoid duplicate diagnostics.
-    fn import_dummy_binding(&mut self, import: &'a Import<'a>) {
+    // Define a dummy resolution containing a `Res::Err` as a placeholder for a failed
+    // or indeterminate resolution, also mark such failed imports as used to avoid duplicate diagnostics.
+    fn import_dummy_binding(&mut self, import: &'a Import<'a>, is_indeterminate: bool) {
         if let ImportKind::Single { target, ref target_bindings, .. } = import.kind {
-            if target_bindings.iter().any(|binding| binding.get().is_some()) {
+            if !(is_indeterminate || target_bindings.iter().all(|binding| binding.get().is_none()))
+            {
                 return; // Has resolution, do not create the dummy binding
             }
             let dummy_binding = self.dummy_binding;
             let dummy_binding = self.import(dummy_binding, import);
             self.per_ns(|this, ns| {
-                let key = this.new_key(target, ns);
+                let key = BindingKey::new(target, ns);
                 let _ = this.try_define(import.parent_scope.module, key, dummy_binding);
             });
             self.record_use(target, dummy_binding, false);
@@ -474,7 +475,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
 
             // If this import is unresolved then create a dummy import
             // resolution for it so that later resolve stages won't complain.
-            self.import_dummy_binding(import);
+            self.import_dummy_binding(import, is_indeterminate);
 
             if let Some(err) = unresolved_import_error {
                 if let ImportKind::Single { source, ref source_bindings, .. } = import.kind {
@@ -712,7 +713,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                                 .span_label(import.span, "cannot be imported directly")
                                 .emit();
                         }
-                        let key = this.new_key(target, ns);
+                        let key = BindingKey::new(target, ns);
                         this.update_resolution(parent, key, |_, resolution| {
                             resolution.single_imports.remove(&Interned::new_unchecked(import));
                         });
diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs
index 44e277c99b9..a1077615d95 100644
--- a/compiler/rustc_resolve/src/late.rs
+++ b/compiler/rustc_resolve/src/late.rs
@@ -6,6 +6,7 @@
 //! If you wonder why there's no `early.rs`, that's because it's split into three files -
 //! `build_reduced_graph.rs`, `macros.rs` and `imports.rs`.
 
+use crate::BindingKey;
 use crate::{path_names_to_string, rustdoc, BindingError, Finalize, LexicalScopeBinding};
 use crate::{Module, ModuleOrUniformRoot, NameBinding, ParentScope, PathResult};
 use crate::{ResolutionError, Resolver, Segment, UseError};
@@ -2967,7 +2968,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
         // If there is a TraitRef in scope for an impl, then the method must be in the trait.
         let Some((module, _)) = &self.current_trait_ref else { return; };
         ident.span.normalize_to_macros_2_0_and_adjust(module.expansion);
-        let key = self.r.new_key(ident, ns);
+        let key = BindingKey::new(ident, ns);
         let mut binding = self.r.resolution(module, key).try_borrow().ok().and_then(|r| r.binding);
         debug!(?binding);
         if binding.is_none() {
@@ -2978,7 +2979,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
                 TypeNS => ValueNS,
                 _ => ns,
             };
-            let key = self.r.new_key(ident, ns);
+            let key = BindingKey::new(ident, ns);
             binding = self.r.resolution(module, key).try_borrow().ok().and_then(|r| r.binding);
             debug!(?binding);
         }
@@ -3543,10 +3544,6 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
         //
         // Similar thing, for types, happens in `report_errors` above.
         let report_errors_for_call = |this: &mut Self, parent_err: Spanned<ResolutionError<'a>>| {
-            if !source.is_call() {
-                return Some(parent_err);
-            }
-
             // Before we start looking for candidates, we have to get our hands
             // on the type user is trying to perform invocation on; basically:
             // we're transforming `HashMap::new` into just `HashMap`.
diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs
index c12dc2f5d92..3cdc3f0ecf8 100644
--- a/compiler/rustc_resolve/src/lib.rs
+++ b/compiler/rustc_resolve/src/lib.rs
@@ -47,6 +47,7 @@ use rustc_index::IndexVec;
 use rustc_metadata::creader::{CStore, CrateLoader};
 use rustc_middle::metadata::ModChild;
 use rustc_middle::middle::privacy::EffectiveVisibilities;
+use rustc_middle::query::Providers;
 use rustc_middle::span_bug;
 use rustc_middle::ty::{self, MainDefinition, RegisteredTools, TyCtxt};
 use rustc_middle::ty::{ResolverGlobalCtxt, ResolverOutputs};
@@ -84,6 +85,7 @@ pub mod rustdoc;
 
 fluent_messages! { "../messages.ftl" }
 
+#[derive(Debug)]
 enum Weak {
     Yes,
     No,
@@ -468,6 +470,13 @@ struct BindingKey {
     disambiguator: u32,
 }
 
+impl BindingKey {
+    fn new(ident: Ident, ns: Namespace) -> Self {
+        let ident = ident.normalize_to_macros_2_0();
+        BindingKey { ident, ns, disambiguator: 0 }
+    }
+}
+
 type Resolutions<'a> = RefCell<FxIndexMap<BindingKey, &'a RefCell<NameResolution<'a>>>>;
 
 /// One node in the tree of modules.
@@ -942,6 +951,7 @@ pub struct Resolver<'a, 'tcx> {
     empty_module: Module<'a>,
     module_map: FxHashMap<DefId, Module<'a>>,
     binding_parent_modules: FxHashMap<Interned<'a, NameBinding<'a>>, Module<'a>>,
+
     underscore_disambiguator: u32,
 
     /// Maps glob imports to the names of items actually imported.
@@ -1594,7 +1604,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
         import_ids
     }
 
-    fn new_key(&mut self, ident: Ident, ns: Namespace) -> BindingKey {
+    fn new_disambiguated_key(&mut self, ident: Ident, ns: Namespace) -> BindingKey {
         let ident = ident.normalize_to_macros_2_0();
         let disambiguator = if ident.name == kw::Underscore {
             self.underscore_disambiguator += 1;
@@ -2026,6 +2036,6 @@ impl Finalize {
     }
 }
 
-pub fn provide(providers: &mut ty::query::Providers) {
+pub fn provide(providers: &mut Providers) {
     providers.registered_tools = macros::registered_tools;
 }
diff --git a/compiler/rustc_serialize/src/opaque.rs b/compiler/rustc_serialize/src/opaque.rs
index 6b559cb5b2f..0ffc537eee0 100644
--- a/compiler/rustc_serialize/src/opaque.rs
+++ b/compiler/rustc_serialize/src/opaque.rs
@@ -1,4 +1,4 @@
-use crate::leb128::{self, largest_max_leb128_len};
+use crate::leb128;
 use crate::serialize::{Decodable, Decoder, Encodable, Encoder};
 use std::fs::File;
 use std::io::{self, Write};
@@ -14,6 +14,9 @@ use std::ptr;
 
 pub type FileEncodeResult = Result<usize, io::Error>;
 
+/// The size of the buffer in `FileEncoder`.
+const BUF_SIZE: usize = 8192;
+
 /// `FileEncoder` encodes data to file via fixed-size buffer.
 ///
 /// There used to be a `MemEncoder` type that encoded all the data into a
@@ -35,26 +38,12 @@ pub struct FileEncoder {
 
 impl FileEncoder {
     pub fn new<P: AsRef<Path>>(path: P) -> io::Result<Self> {
-        const DEFAULT_BUF_SIZE: usize = 8192;
-        FileEncoder::with_capacity(path, DEFAULT_BUF_SIZE)
-    }
-
-    pub fn with_capacity<P: AsRef<Path>>(path: P, capacity: usize) -> io::Result<Self> {
-        // Require capacity at least as large as the largest LEB128 encoding
-        // here, so that we don't have to check or handle this on every write.
-        assert!(capacity >= largest_max_leb128_len());
-
-        // Require capacity small enough such that some capacity checks can be
-        // done using guaranteed non-overflowing add rather than sub, which
-        // shaves an instruction off those code paths (on x86 at least).
-        assert!(capacity <= usize::MAX - largest_max_leb128_len());
-
         // Create the file for reading and writing, because some encoders do both
         // (e.g. the metadata encoder when -Zmeta-stats is enabled)
         let file = File::options().read(true).write(true).create(true).truncate(true).open(path)?;
 
         Ok(FileEncoder {
-            buf: Box::new_uninit_slice(capacity),
+            buf: Box::new_uninit_slice(BUF_SIZE),
             buffered: 0,
             flushed: 0,
             file,
@@ -160,18 +149,10 @@ impl FileEncoder {
     }
 
     #[inline]
-    fn capacity(&self) -> usize {
-        self.buf.len()
-    }
-
-    #[inline]
     fn write_one(&mut self, value: u8) {
-        // We ensure this during `FileEncoder` construction.
-        debug_assert!(self.capacity() >= 1);
-
         let mut buffered = self.buffered;
 
-        if std::intrinsics::unlikely(buffered >= self.capacity()) {
+        if std::intrinsics::unlikely(buffered + 1 > BUF_SIZE) {
             self.flush();
             buffered = 0;
         }
@@ -187,13 +168,12 @@ impl FileEncoder {
 
     #[inline]
     fn write_all(&mut self, buf: &[u8]) {
-        let capacity = self.capacity();
         let buf_len = buf.len();
 
-        if std::intrinsics::likely(buf_len <= capacity) {
+        if std::intrinsics::likely(buf_len <= BUF_SIZE) {
             let mut buffered = self.buffered;
 
-            if std::intrinsics::unlikely(buf_len > capacity - buffered) {
+            if std::intrinsics::unlikely(buffered + buf_len > BUF_SIZE) {
                 self.flush();
                 buffered = 0;
             }
@@ -271,13 +251,11 @@ macro_rules! write_leb128 {
         fn $this_fn(&mut self, v: $int_ty) {
             const MAX_ENCODED_LEN: usize = $crate::leb128::max_leb128_len::<$int_ty>();
 
-            // We ensure this during `FileEncoder` construction.
-            debug_assert!(self.capacity() >= MAX_ENCODED_LEN);
-
             let mut buffered = self.buffered;
 
-            // This can't overflow. See assertion in `FileEncoder::with_capacity`.
-            if std::intrinsics::unlikely(buffered + MAX_ENCODED_LEN > self.capacity()) {
+            // This can't overflow because BUF_SIZE and MAX_ENCODED_LEN are both
+            // quite small.
+            if std::intrinsics::unlikely(buffered + MAX_ENCODED_LEN > BUF_SIZE) {
                 self.flush();
                 buffered = 0;
             }
diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs
index aa3cb03bad8..a328447aca9 100644
--- a/compiler/rustc_session/src/config.rs
+++ b/compiler/rustc_session/src/config.rs
@@ -421,7 +421,7 @@ pub enum TrimmedDefPaths {
     GoodPath,
 }
 
-#[derive(Clone, Hash)]
+#[derive(Clone, Hash, Debug)]
 pub enum ResolveDocLinks {
     /// Do not resolve doc links.
     None,
@@ -1060,6 +1060,9 @@ fn default_configuration(sess: &Session) -> CrateConfig {
     if sess.opts.debug_assertions {
         ret.insert((sym::debug_assertions, None));
     }
+    if sess.overflow_checks() {
+        ret.insert((sym::overflow_checks, None));
+    }
     // JUSTIFICATION: before wrapper fn is available
     #[allow(rustc::bad_opt_access)]
     if sess.opts.crate_types.contains(&CrateType::ProcMacro) {
@@ -1209,6 +1212,7 @@ impl CrateCheckConfig {
             sym::windows,
             sym::proc_macro,
             sym::debug_assertions,
+            sym::overflow_checks,
             sym::target_thread_local,
         ] {
             self.expecteds.entry(name).or_insert_with(no_values);
@@ -1315,7 +1319,7 @@ pub(super) fn build_target_config(
     let (target, target_warnings) = target_result.unwrap_or_else(|e| {
         early_error(
             opts.error_format,
-            &format!(
+            format!(
                 "Error loading target specification: {}. \
                  Run `rustc --print target-list` for a list of built-in targets",
                 e
@@ -1323,15 +1327,14 @@ pub(super) fn build_target_config(
         )
     });
     for warning in target_warnings.warning_messages() {
-        early_warn(opts.error_format, &warning)
+        early_warn(opts.error_format, warning)
     }
 
     if !matches!(target.pointer_width, 16 | 32 | 64) {
         early_error(
             opts.error_format,
-            &format!(
-                "target specification was invalid: \
-             unrecognized target-pointer-width {}",
+            format!(
+                "target specification was invalid: unrecognized target-pointer-width {}",
                 target.pointer_width
             ),
         )
@@ -1595,7 +1598,7 @@ pub fn get_cmd_lint_options(
 
     let lint_cap = matches.opt_str("cap-lints").map(|cap| {
         lint::Level::from_str(&cap)
-            .unwrap_or_else(|| early_error(error_format, &format!("unknown lint level: `{cap}`")))
+            .unwrap_or_else(|| early_error(error_format, format!("unknown lint level: `{cap}`")))
     });
 
     (lint_opts, describe_lints, lint_cap)
@@ -1612,7 +1615,7 @@ pub fn parse_color(matches: &getopts::Matches) -> ColorConfig {
 
         Some(arg) => early_error(
             ErrorOutputType::default(),
-            &format!(
+            format!(
                 "argument for `--color` must be auto, \
                  always or never (instead was `{arg}`)"
             ),
@@ -1687,7 +1690,7 @@ pub fn parse_json(matches: &getopts::Matches) -> JsonConfig {
                 "future-incompat" => json_future_incompat = true,
                 s => early_error(
                     ErrorOutputType::default(),
-                    &format!("unknown `--json` option `{s}`"),
+                    format!("unknown `--json` option `{s}`"),
                 ),
             }
         }
@@ -1725,7 +1728,7 @@ pub fn parse_error_format(
 
             Some(arg) => early_error(
                 ErrorOutputType::HumanReadable(HumanReadableErrorType::Default(color)),
-                &format!(
+                format!(
                     "argument for `--error-format` must be `human`, `json` or \
                      `short` (instead was `{arg}`)"
                 ),
@@ -1759,7 +1762,7 @@ pub fn parse_crate_edition(matches: &getopts::Matches) -> Edition {
         Some(arg) => Edition::from_str(&arg).unwrap_or_else(|_| {
             early_error(
                 ErrorOutputType::default(),
-                &format!(
+                format!(
                     "argument for `--edition` must be one of: \
                      {EDITION_NAME_LIST}. (instead was `{arg}`)"
                 ),
@@ -1778,7 +1781,7 @@ pub fn parse_crate_edition(matches: &getopts::Matches) -> Edition {
         } else {
             format!("edition {edition} is unstable and only available with -Z unstable-options")
         };
-        early_error(ErrorOutputType::default(), &msg)
+        early_error(ErrorOutputType::default(), msg)
     }
 
     edition
@@ -1823,7 +1826,7 @@ fn parse_output_types(
                 let output_type = OutputType::from_shorthand(shorthand).unwrap_or_else(|| {
                     early_error(
                         error_format,
-                        &format!(
+                        format!(
                             "unknown emission type: `{shorthand}` - expected one of: {display}",
                             display = OutputType::shorthands_display(),
                         ),
@@ -1862,7 +1865,7 @@ fn should_override_cgus_and_disable_thinlto(
                     for ot in &incompatible {
                         early_warn(
                             error_format,
-                            &format!(
+                            format!(
                                 "`--emit={ot}` with `-o` incompatible with \
                                  `-C codegen-units=N` for N > 1",
                             ),
@@ -1966,7 +1969,7 @@ fn collect_print_requests(
                 let prints = prints.join(", ");
                 early_error(
                     error_format,
-                    &format!("unknown print request `{req}`. Valid print requests are: {prints}"),
+                    format!("unknown print request `{req}`. Valid print requests are: {prints}"),
                 );
             }
         }
@@ -1983,7 +1986,7 @@ pub fn parse_target_triple(
         Some(target) if target.ends_with(".json") => {
             let path = Path::new(&target);
             TargetTriple::from_path(path).unwrap_or_else(|_| {
-                early_error(error_format, &format!("target file {path:?} does not exist"))
+                early_error(error_format, format!("target file {path:?} does not exist"))
             })
         }
         Some(target) => TargetTriple::TargetTriple(target),
@@ -2024,7 +2027,7 @@ fn parse_opt_level(
             arg => {
                 early_error(
                     error_format,
-                    &format!(
+                    format!(
                         "optimization level needs to be \
                             between 0-3, s or z (instead was `{arg}`)"
                     ),
@@ -2055,7 +2058,7 @@ pub(crate) fn parse_assert_incr_state(
         Some(s) if s.as_str() == "loaded" => Some(IncrementalStateAssertion::Loaded),
         Some(s) if s.as_str() == "not-loaded" => Some(IncrementalStateAssertion::NotLoaded),
         Some(s) => {
-            early_error(error_format, &format!("unexpected incremental state assertion value: {s}"))
+            early_error(error_format, format!("unexpected incremental state assertion value: {s}"))
         }
         None => None,
     }
@@ -2082,13 +2085,13 @@ fn parse_native_lib_kind(
                 } else {
                     ", the `-Z unstable-options` flag must also be passed to use it"
                 };
-                early_error(error_format, &format!("library kind `link-arg` is unstable{why}"))
+                early_error(error_format, format!("library kind `link-arg` is unstable{why}"))
             }
             NativeLibKind::LinkArg
         }
         _ => early_error(
             error_format,
-            &format!(
+            format!(
                 "unknown library kind `{kind}`, expected one of: static, dylib, framework, link-arg"
             ),
         ),
@@ -2123,16 +2126,13 @@ fn parse_native_lib_modifiers(
                 } else {
                     ", the `-Z unstable-options` flag must also be passed to use it"
                 };
-                early_error(
-                    error_format,
-                    &format!("linking modifier `{modifier}` is unstable{why}"),
-                )
+                early_error(error_format, format!("linking modifier `{modifier}` is unstable{why}"))
             }
         };
         let assign_modifier = |dst: &mut Option<bool>| {
             if dst.is_some() {
                 let msg = format!("multiple `{modifier}` modifiers in a single `-l` option");
-                early_error(error_format, &msg)
+                early_error(error_format, msg)
             } else {
                 *dst = Some(value);
             }
@@ -2169,7 +2169,7 @@ fn parse_native_lib_modifiers(
             // string, like `modifiers = ""`.
             _ => early_error(
                 error_format,
-                &format!(
+                format!(
                     "unknown linking modifier `{modifier}`, expected one \
                      of: bundle, verbatim, whole-archive, as-needed"
                 ),
@@ -2299,7 +2299,7 @@ pub fn parse_externs(
                     }
                     "nounused" => nounused_dep = true,
                     "force" => force = true,
-                    _ => early_error(error_format, &format!("unknown --extern option `{opt}`")),
+                    _ => early_error(error_format, format!("unknown --extern option `{opt}`")),
                 }
             }
         }
@@ -2365,7 +2365,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
 
     let unparsed_crate_types = matches.opt_strs("crate-type");
     let crate_types = parse_crate_types_from_list(unparsed_crate_types)
-        .unwrap_or_else(|e| early_error(error_format, &e));
+        .unwrap_or_else(|e| early_error(error_format, e));
 
     let mut unstable_opts = UnstableOptions::build(matches, error_format);
     let (lint_opts, describe_lints, lint_cap) = get_cmd_lint_options(matches, error_format);
@@ -2593,7 +2593,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
     };
 
     let working_dir = std::env::current_dir().unwrap_or_else(|e| {
-        early_error(error_format, &format!("Current directory is invalid: {e}"));
+        early_error(error_format, format!("Current directory is invalid: {e}"));
     });
 
     let remap = FilePathMapping::new(remap_path_prefix.clone());
@@ -2665,7 +2665,7 @@ fn parse_pretty(unstable_opts: &UnstableOptions, efmt: ErrorOutputType) -> Optio
         "mir-cfg" => MirCFG,
         name => early_error(
             efmt,
-            &format!(
+            format!(
                 "argument to `unpretty` must be one of `normal`, `identified`, \
                             `expanded`, `expanded,identified`, `expanded,hygiene`, \
                             `ast-tree`, `ast-tree,expanded`, `hir`, `hir,identified`, \
@@ -2743,7 +2743,7 @@ pub mod nightly_options {
             if opt.name != "Z" && !has_z_unstable_option {
                 early_error(
                     ErrorOutputType::default(),
-                    &format!(
+                    format!(
                         "the `-Z unstable-options` flag must also be passed to enable \
                          the flag `{}`",
                         opt.name
@@ -2756,11 +2756,10 @@ pub mod nightly_options {
             match opt.stability {
                 OptionStability::Unstable => {
                     let msg = format!(
-                        "the option `{}` is only accepted on the \
-                         nightly compiler",
+                        "the option `{}` is only accepted on the nightly compiler",
                         opt.name
                     );
-                    early_error(ErrorOutputType::default(), &msg);
+                    early_error(ErrorOutputType::default(), msg);
                 }
                 OptionStability::Stable => {}
             }
diff --git a/compiler/rustc_session/src/cstore.rs b/compiler/rustc_session/src/cstore.rs
index dd1721801f3..dc475e8c6d5 100644
--- a/compiler/rustc_session/src/cstore.rs
+++ b/compiler/rustc_session/src/cstore.rs
@@ -6,7 +6,8 @@ use crate::search_paths::PathKind;
 use crate::utils::NativeLibKind;
 use crate::Session;
 use rustc_ast as ast;
-use rustc_data_structures::sync::{self, AppendOnlyIndexVec, MetadataRef, RwLock};
+use rustc_data_structures::owned_slice::OwnedSlice;
+use rustc_data_structures::sync::{self, AppendOnlyIndexVec, RwLock};
 use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, StableCrateId, LOCAL_CRATE};
 use rustc_hir::definitions::{DefKey, DefPath, DefPathHash, Definitions};
 use rustc_span::hygiene::{ExpnHash, ExpnId};
@@ -203,11 +204,11 @@ pub enum ExternCrateSource {
 /// metadata in library -- this trait just serves to decouple rustc_metadata from
 /// the archive reader, which depends on LLVM.
 pub trait MetadataLoader: std::fmt::Debug {
-    fn get_rlib_metadata(&self, target: &Target, filename: &Path) -> Result<MetadataRef, String>;
-    fn get_dylib_metadata(&self, target: &Target, filename: &Path) -> Result<MetadataRef, String>;
+    fn get_rlib_metadata(&self, target: &Target, filename: &Path) -> Result<OwnedSlice, String>;
+    fn get_dylib_metadata(&self, target: &Target, filename: &Path) -> Result<OwnedSlice, String>;
 }
 
-pub type MetadataLoaderDyn = dyn MetadataLoader + Send + Sync;
+pub type MetadataLoaderDyn = dyn MetadataLoader + Send + Sync + sync::DynSend + sync::DynSync;
 
 /// A store of Rust crates, through which their metadata can be accessed.
 ///
@@ -252,7 +253,7 @@ pub trait CrateStore: std::fmt::Debug {
     fn import_source_files(&self, sess: &Session, cnum: CrateNum);
 }
 
-pub type CrateStoreDyn = dyn CrateStore + sync::Sync + sync::Send;
+pub type CrateStoreDyn = dyn CrateStore + sync::DynSync + sync::DynSend;
 
 pub struct Untracked {
     pub cstore: RwLock<Box<CrateStoreDyn>>,
diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs
index 5976b9aa3e7..2c4c4a7a6ce 100644
--- a/compiler/rustc_session/src/options.rs
+++ b/compiler/rustc_session/src/options.rs
@@ -329,21 +329,21 @@ fn build_options<O: Default>(
                     match value {
                         None => early_error(
                             error_format,
-                            &format!(
+                            format!(
                                 "{0} option `{1}` requires {2} ({3} {1}=<value>)",
                                 outputname, key, type_desc, prefix
                             ),
                         ),
                         Some(value) => early_error(
                             error_format,
-                            &format!(
+                            format!(
                                 "incorrect value `{value}` for {outputname} option `{key}` - {type_desc} was expected"
                             ),
                         ),
                     }
                 }
             }
-            None => early_error(error_format, &format!("unknown {outputname} option: `{key}`")),
+            None => early_error(error_format, format!("unknown {outputname} option: `{key}`")),
         }
     }
     return op;
diff --git a/compiler/rustc_session/src/parse.rs b/compiler/rustc_session/src/parse.rs
index 5cc9c62617d..7b396dde91b 100644
--- a/compiler/rustc_session/src/parse.rs
+++ b/compiler/rustc_session/src/parse.rs
@@ -289,7 +289,7 @@ impl ParseSess {
         lint: &'static Lint,
         span: impl Into<MultiSpan>,
         node_id: NodeId,
-        msg: &str,
+        msg: impl Into<DiagnosticMessage>,
     ) {
         self.buffered_lints.with_lock(|buffered_lints| {
             buffered_lints.push(BufferedEarlyLint {
@@ -307,7 +307,7 @@ impl ParseSess {
         lint: &'static Lint,
         span: impl Into<MultiSpan>,
         node_id: NodeId,
-        msg: &str,
+        msg: impl Into<DiagnosticMessage>,
         diagnostic: BuiltinLintDiagnostics,
     ) {
         self.buffered_lints.with_lock(|buffered_lints| {
diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs
index a988d7f28e6..4f593083b6f 100644
--- a/compiler/rustc_session/src/session.rs
+++ b/compiler/rustc_session/src/session.rs
@@ -211,6 +211,9 @@ pub struct Session {
 
     /// Set of enabled features for the current target, including unstable ones.
     pub unstable_target_features: FxIndexSet<Symbol>,
+
+    /// The version of the rustc process, possibly including a commit hash and description.
+    pub cfg_version: &'static str,
 }
 
 pub struct PerfStats {
@@ -490,20 +493,6 @@ impl Session {
     }
     #[rustc_lint_diagnostics]
     #[track_caller]
-    pub fn span_err_or_warn<S: Into<MultiSpan>>(
-        &self,
-        is_warning: bool,
-        sp: S,
-        msg: impl Into<DiagnosticMessage>,
-    ) {
-        if is_warning {
-            self.span_warn(sp, msg);
-        } else {
-            self.span_err(sp, msg);
-        }
-    }
-    #[rustc_lint_diagnostics]
-    #[track_caller]
     pub fn span_err<S: Into<MultiSpan>>(
         &self,
         sp: S,
@@ -1380,6 +1369,7 @@ pub fn build_session(
     driver_lint_caps: FxHashMap<lint::LintId, lint::Level>,
     file_loader: Option<Box<dyn FileLoader + Send + Sync + 'static>>,
     target_override: Option<Target>,
+    cfg_version: &'static str,
 ) -> Session {
     // FIXME: This is not general enough to make the warning lint completely override
     // normal diagnostic warnings, since the warning lint can also be denied and changed
@@ -1400,10 +1390,10 @@ pub fn build_session(
     let target_cfg = config::build_target_config(&sopts, target_override, &sysroot);
     let host_triple = TargetTriple::from_triple(config::host_triple());
     let (host, target_warnings) = Target::search(&host_triple, &sysroot).unwrap_or_else(|e| {
-        early_error(sopts.error_format, &format!("Error loading host specification: {e}"))
+        early_error(sopts.error_format, format!("Error loading host specification: {e}"))
     });
     for warning in target_warnings.warning_messages() {
-        early_warn(sopts.error_format, &warning)
+        early_warn(sopts.error_format, warning)
     }
 
     let loader = file_loader.unwrap_or_else(|| Box::new(RealFileLoader));
@@ -1445,7 +1435,7 @@ pub fn build_session(
         match profiler {
             Ok(profiler) => Some(Arc::new(profiler)),
             Err(e) => {
-                early_warn(sopts.error_format, &format!("failed to create profiler: {e}"));
+                early_warn(sopts.error_format, format!("failed to create profiler: {e}"));
                 None
             }
         }
@@ -1524,6 +1514,7 @@ pub fn build_session(
         asm_arch,
         target_features: Default::default(),
         unstable_target_features: Default::default(),
+        cfg_version,
     };
 
     validate_commandline_args_with_session_available(&sess);
@@ -1741,18 +1732,22 @@ fn early_error_handler(output: config::ErrorOutputType) -> rustc_errors::Handler
 
 #[allow(rustc::untranslatable_diagnostic)]
 #[allow(rustc::diagnostic_outside_of_impl)]
-pub fn early_error_no_abort(output: config::ErrorOutputType, msg: &str) -> ErrorGuaranteed {
+#[must_use = "ErrorGuaranteed must be returned from `run_compiler` in order to exit with a non-zero status code"]
+pub fn early_error_no_abort(
+    output: config::ErrorOutputType,
+    msg: impl Into<DiagnosticMessage>,
+) -> ErrorGuaranteed {
     early_error_handler(output).struct_err(msg).emit()
 }
 
 #[allow(rustc::untranslatable_diagnostic)]
 #[allow(rustc::diagnostic_outside_of_impl)]
-pub fn early_error(output: config::ErrorOutputType, msg: &str) -> ! {
+pub fn early_error(output: config::ErrorOutputType, msg: impl Into<DiagnosticMessage>) -> ! {
     early_error_handler(output).struct_fatal(msg).emit()
 }
 
 #[allow(rustc::untranslatable_diagnostic)]
 #[allow(rustc::diagnostic_outside_of_impl)]
-pub fn early_warn(output: config::ErrorOutputType, msg: &str) {
+pub fn early_warn(output: config::ErrorOutputType, msg: impl Into<DiagnosticMessage>) {
     early_error_handler(output).struct_warn(msg).emit()
 }
diff --git a/compiler/rustc_span/src/def_id.rs b/compiler/rustc_span/src/def_id.rs
index 8c58b52a5dc..f65a6aa4fb2 100644
--- a/compiler/rustc_span/src/def_id.rs
+++ b/compiler/rustc_span/src/def_id.rs
@@ -146,7 +146,12 @@ pub struct StableCrateId(pub(crate) Hash64);
 impl StableCrateId {
     /// Computes the stable ID for a crate with the given name and
     /// `-Cmetadata` arguments.
-    pub fn new(crate_name: Symbol, is_exe: bool, mut metadata: Vec<String>) -> StableCrateId {
+    pub fn new(
+        crate_name: Symbol,
+        is_exe: bool,
+        mut metadata: Vec<String>,
+        cfg_version: &'static str,
+    ) -> StableCrateId {
         let mut hasher = StableHasher::new();
         // We must hash the string text of the crate name, not the id, as the id is not stable
         // across builds.
@@ -180,7 +185,7 @@ impl StableCrateId {
         if let Some(val) = std::env::var_os("RUSTC_FORCE_RUSTC_VERSION") {
             hasher.write(val.to_string_lossy().into_owned().as_bytes())
         } else {
-            hasher.write(option_env!("CFG_VERSION").unwrap_or("unknown version").as_bytes());
+            hasher.write(cfg_version.as_bytes())
         }
 
         StableCrateId(hasher.finish())
diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs
index 7bbab34c69a..8d70aa47f78 100644
--- a/compiler/rustc_span/src/lib.rs
+++ b/compiler/rustc_span/src/lib.rs
@@ -20,6 +20,7 @@
 #![feature(min_specialization)]
 #![feature(rustc_attrs)]
 #![feature(let_chains)]
+#![feature(round_char_boundary)]
 #![deny(rustc::untranslatable_diagnostic)]
 #![deny(rustc::diagnostic_outside_of_impl)]
 
@@ -1256,29 +1257,6 @@ impl SourceFileHash {
     }
 }
 
-#[derive(HashStable_Generic)]
-#[derive(Copy, PartialEq, PartialOrd, Clone, Ord, Eq, Hash, Debug, Encodable, Decodable)]
-pub enum DebuggerVisualizerType {
-    Natvis,
-    GdbPrettyPrinter,
-}
-
-/// A single debugger visualizer file.
-#[derive(HashStable_Generic)]
-#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord, Encodable, Decodable)]
-pub struct DebuggerVisualizerFile {
-    /// The complete debugger visualizer source.
-    pub src: Lrc<[u8]>,
-    /// Indicates which visualizer type this targets.
-    pub visualizer_type: DebuggerVisualizerType,
-}
-
-impl DebuggerVisualizerFile {
-    pub fn new(src: Lrc<[u8]>, visualizer_type: DebuggerVisualizerType) -> Self {
-        DebuggerVisualizerFile { src, visualizer_type }
-    }
-}
-
 #[derive(Clone)]
 pub enum SourceFileLines {
     /// The source file lines, in decoded (random-access) form.
diff --git a/compiler/rustc_span/src/source_map.rs b/compiler/rustc_span/src/source_map.rs
index 1294a8b8e6b..11ea5fe4ddf 100644
--- a/compiler/rustc_span/src/source_map.rs
+++ b/compiler/rustc_span/src/source_map.rs
@@ -14,7 +14,9 @@ pub use crate::*;
 
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::stable_hasher::{Hash128, Hash64, StableHasher};
-use rustc_data_structures::sync::{AtomicU32, Lrc, MappedReadGuard, ReadGuard, RwLock};
+use rustc_data_structures::sync::{
+    AtomicU32, IntoDynSyncSend, Lrc, MappedReadGuard, ReadGuard, RwLock,
+};
 use std::cmp;
 use std::hash::Hash;
 use std::path::{self, Path, PathBuf};
@@ -176,7 +178,7 @@ pub struct SourceMap {
     used_address_space: AtomicU32,
 
     files: RwLock<SourceMapFiles>,
-    file_loader: Box<dyn FileLoader + Sync + Send>,
+    file_loader: IntoDynSyncSend<Box<dyn FileLoader + Sync + Send>>,
     // This is used to apply the file path remapping as specified via
     // `--remap-path-prefix` to all `SourceFile`s allocated within this `SourceMap`.
     path_mapping: FilePathMapping,
@@ -202,7 +204,7 @@ impl SourceMap {
         SourceMap {
             used_address_space: AtomicU32::new(0),
             files: Default::default(),
-            file_loader,
+            file_loader: IntoDynSyncSend(file_loader),
             path_mapping,
             hash_kind,
         }
@@ -1017,36 +1019,19 @@ impl SourceMap {
 
         let src = local_begin.sf.external_src.borrow();
 
-        // We need to extend the snippet to the end of the src rather than to end_index so when
-        // searching forwards for boundaries we've got somewhere to search.
-        let snippet = if let Some(ref src) = local_begin.sf.src {
-            &src[start_index..]
+        let snippet = if let Some(src) = &local_begin.sf.src {
+            src
         } else if let Some(src) = src.get_source() {
-            &src[start_index..]
+            src
         } else {
             return 1;
         };
-        debug!("snippet=`{:?}`", snippet);
 
-        let mut target = if forwards { end_index + 1 } else { end_index - 1 };
-        debug!("initial target=`{:?}`", target);
-
-        while !snippet.is_char_boundary(target - start_index) && target < source_len {
-            target = if forwards {
-                target + 1
-            } else {
-                match target.checked_sub(1) {
-                    Some(target) => target,
-                    None => {
-                        break;
-                    }
-                }
-            };
-            debug!("target=`{:?}`", target);
+        if forwards {
+            (snippet.ceil_char_boundary(end_index + 1) - end_index) as u32
+        } else {
+            (end_index - snippet.floor_char_boundary(end_index - 1)) as u32
         }
-        debug!("final target=`{:?}`", target);
-
-        if forwards { (target - end_index) as u32 } else { (end_index - target) as u32 }
     }
 
     pub fn get_source_file(&self, filename: &FileName) -> Option<Lrc<SourceFile>> {
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 60efcb768cb..874d578fe1d 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -164,6 +164,7 @@ symbols! {
         Capture,
         Center,
         Clone,
+        ConstParamTy,
         Context,
         Continue,
         Copy,
@@ -463,6 +464,7 @@ symbols! {
         cfg_doctest,
         cfg_eval,
         cfg_hide,
+        cfg_overflow_checks,
         cfg_panic,
         cfg_sanitize,
         cfg_target_abi,
@@ -1065,6 +1067,7 @@ symbols! {
         or_patterns,
         other,
         out,
+        overflow_checks,
         overlapping_marker_traits,
         owned_box,
         packed,
@@ -1581,6 +1584,7 @@ symbols! {
         unrestricted_attribute_tokens,
         unsafe_block_in_unsafe_fn,
         unsafe_cell,
+        unsafe_cell_from_mut,
         unsafe_no_drop_flag,
         unsafe_pin_internals,
         unsize,
diff --git a/compiler/rustc_symbol_mangling/src/lib.rs b/compiler/rustc_symbol_mangling/src/lib.rs
index c97406868b6..692542da78e 100644
--- a/compiler/rustc_symbol_mangling/src/lib.rs
+++ b/compiler/rustc_symbol_mangling/src/lib.rs
@@ -107,7 +107,7 @@ use rustc_hir::def_id::{CrateNum, LOCAL_CRATE};
 use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
 use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs;
 use rustc_middle::mir::mono::{InstantiationMode, MonoItem};
-use rustc_middle::ty::query::Providers;
+use rustc_middle::query::Providers;
 use rustc_middle::ty::subst::SubstsRef;
 use rustc_middle::ty::{self, Instance, TyCtxt};
 use rustc_session::config::SymbolManglingVersion;
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 c281aa7e83a..51d508a580b 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
@@ -673,6 +673,14 @@ fn encode_ty<'tcx>(
             typeid.push_str(&s);
         }
 
+        // Type parameters
+        ty::Param(..) => {
+            // u5param as vendor extended type
+            let mut s = String::from("u5param");
+            compress(dict, DictKey::Ty(ty, TyQ::None), &mut s);
+            typeid.push_str(&s);
+        }
+
         // Unexpected types
         ty::Bound(..)
         | ty::Error(..)
@@ -680,7 +688,6 @@ fn encode_ty<'tcx>(
         | ty::GeneratorWitnessMIR(..)
         | ty::Infer(..)
         | ty::Alias(..)
-        | ty::Param(..)
         | ty::Placeholder(..) => {
             bug!("encode_ty: unexpected `{:?}`", ty.kind());
         }
@@ -689,6 +696,41 @@ fn encode_ty<'tcx>(
     typeid
 }
 
+/// Transforms predicates for being encoded and used in the substitution dictionary.
+fn transform_predicates<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    predicates: &List<ty::PolyExistentialPredicate<'tcx>>,
+    _options: EncodeTyOptions,
+) -> &'tcx List<ty::PolyExistentialPredicate<'tcx>> {
+    let predicates: Vec<ty::PolyExistentialPredicate<'tcx>> = predicates
+        .iter()
+        .map(|predicate| match predicate.skip_binder() {
+            ty::ExistentialPredicate::Trait(trait_ref) => {
+                let trait_ref = ty::TraitRef::identity(tcx, trait_ref.def_id);
+                ty::Binder::dummy(ty::ExistentialPredicate::Trait(
+                    ty::ExistentialTraitRef::erase_self_ty(tcx, trait_ref),
+                ))
+            }
+            _ => predicate,
+        })
+        .collect();
+    tcx.mk_poly_existential_predicates(&predicates)
+}
+
+/// Transforms substs for being encoded and used in the substitution dictionary.
+fn transform_substs<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    substs: SubstsRef<'tcx>,
+    options: TransformTyOptions,
+) -> SubstsRef<'tcx> {
+    let substs = substs.iter().map(|subst| match subst.unpack() {
+        GenericArgKind::Type(ty) if ty.is_c_void(tcx) => tcx.mk_unit().into(),
+        GenericArgKind::Type(ty) => transform_ty(tcx, ty, options).into(),
+        _ => subst,
+    });
+    tcx.mk_substs_from_iter(substs)
+}
+
 // Transforms a ty:Ty for being encoded and used in the substitution dictionary. It transforms all
 // c_void types into unit types unconditionally, generalizes pointers if
 // TransformTyOptions::GENERALIZE_POINTERS option is set, and normalizes integers if
@@ -697,7 +739,7 @@ fn transform_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, options: TransformTyOptio
     let mut ty = ty;
 
     match ty.kind() {
-        ty::Float(..) | ty::Char | ty::Str | ty::Never | ty::Foreign(..) | ty::Dynamic(..) => {}
+        ty::Float(..) | ty::Char | ty::Str | ty::Never | ty::Foreign(..) => {}
 
         ty::Bool => {
             if options.contains(EncodeTyOptions::NORMALIZE_INTEGERS) {
@@ -870,6 +912,14 @@ fn transform_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, options: TransformTyOptio
             }
         }
 
+        ty::Dynamic(predicates, _region, kind) => {
+            ty = tcx.mk_dynamic(
+                transform_predicates(tcx, predicates, options),
+                tcx.lifetimes.re_erased,
+                *kind,
+            );
+        }
+
         ty::Bound(..)
         | ty::Error(..)
         | ty::GeneratorWitness(..)
@@ -885,20 +935,6 @@ fn transform_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, options: TransformTyOptio
     ty
 }
 
-/// Transforms substs for being encoded and used in the substitution dictionary.
-fn transform_substs<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    substs: SubstsRef<'tcx>,
-    options: TransformTyOptions,
-) -> SubstsRef<'tcx> {
-    let substs = substs.iter().map(|subst| match subst.unpack() {
-        GenericArgKind::Type(ty) if ty.is_c_void(tcx) => tcx.mk_unit().into(),
-        GenericArgKind::Type(ty) => transform_ty(tcx, ty, options).into(),
-        _ => subst,
-    });
-    tcx.mk_substs_from_iter(substs)
-}
-
 /// Returns a type metadata identifier for the specified FnAbi using the Itanium C++ ABI with vendor
 /// extended type qualifiers and types for Rust types that are not used at the FFI boundary.
 #[instrument(level = "trace", skip(tcx))]
diff --git a/compiler/rustc_target/src/asm/mod.rs b/compiler/rustc_target/src/asm/mod.rs
index 705966f5237..e60b8e78e5d 100644
--- a/compiler/rustc_target/src/asm/mod.rs
+++ b/compiler/rustc_target/src/asm/mod.rs
@@ -882,8 +882,8 @@ impl InlineAsmClobberAbi {
                 _ => Err(&["C", "system", "efiapi"]),
             },
             InlineAsmArch::LoongArch64 => match name {
-                "C" | "system" | "efiapi" => Ok(InlineAsmClobberAbi::LoongArch),
-                _ => Err(&["C", "system", "efiapi"]),
+                "C" | "system" => Ok(InlineAsmClobberAbi::LoongArch),
+                _ => Err(&["C", "system"]),
             },
             _ => Err(&[]),
         }
diff --git a/compiler/rustc_trait_selection/src/solve/assembly/mod.rs b/compiler/rustc_trait_selection/src/solve/assembly/mod.rs
index 25cc82f01d5..d14e6244f7d 100644
--- a/compiler/rustc_trait_selection/src/solve/assembly/mod.rs
+++ b/compiler/rustc_trait_selection/src/solve/assembly/mod.rs
@@ -506,10 +506,12 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
             | ty::Param(_)
             | ty::Placeholder(..)
             | ty::Infer(ty::IntVar(_) | ty::FloatVar(_))
+            | ty::Alias(ty::Inherent, _)
             | ty::Error(_) => return,
             ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_))
             | ty::Bound(..) => bug!("unexpected self type for `{goal:?}`"),
-            ty::Alias(_, alias_ty) => alias_ty,
+            // Excluding IATs here as they don't have meaningful item bounds.
+            ty::Alias(ty::Projection | ty::Opaque, alias_ty) => alias_ty,
         };
 
         for assumption in self.tcx().item_bounds(alias_ty.def_id).subst(self.tcx(), alias_ty.substs)
diff --git a/compiler/rustc_trait_selection/src/solve/project_goals.rs b/compiler/rustc_trait_selection/src/solve/project_goals.rs
index 20ce2d9416e..d3228074421 100644
--- a/compiler/rustc_trait_selection/src/solve/project_goals.rs
+++ b/compiler/rustc_trait_selection/src/solve/project_goals.rs
@@ -124,10 +124,24 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> {
             };
 
             if !assoc_def.item.defaultness(tcx).has_value() {
-                tcx.sess.delay_span_bug(
+                let guar = tcx.sess.delay_span_bug(
                     tcx.def_span(assoc_def.item.def_id),
                     "missing value for assoc item in impl",
                 );
+                let error_term = match assoc_def.item.kind {
+                    ty::AssocKind::Const => tcx
+                        .const_error(
+                            tcx.type_of(goal.predicate.def_id())
+                                .subst(tcx, goal.predicate.projection_ty.substs),
+                            guar,
+                        )
+                        .into(),
+                    ty::AssocKind::Type => tcx.ty_error(guar).into(),
+                    ty::AssocKind::Fn => unreachable!(),
+                };
+                ecx.eq(goal.param_env, goal.predicate.term, error_term)
+                    .expect("expected goal term to be fully unconstrained");
+                return ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes);
             }
 
             // Getting the right substitutions here is complex, e.g. given:
diff --git a/compiler/rustc_trait_selection/src/traits/auto_trait.rs b/compiler/rustc_trait_selection/src/traits/auto_trait.rs
index 6b080a132f3..183c2401fc3 100644
--- a/compiler/rustc_trait_selection/src/traits/auto_trait.rs
+++ b/compiler/rustc_trait_selection/src/traits/auto_trait.rs
@@ -801,7 +801,7 @@ impl<'tcx> AutoTraitFinder<'tcx> {
                                             span: tcx.def_span(unevaluated.def),
                                             unevaluated: unevaluated,
                                         });
-                                    Err(ErrorHandled::Reported(reported))
+                                    Err(ErrorHandled::Reported(reported.into()))
                                 }
                                 Err(err) => Err(err),
                             }
diff --git a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
index 9d99d30d45c..bd1ea43a78e 100644
--- a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
+++ b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
@@ -79,7 +79,7 @@ pub fn is_const_evaluatable<'tcx>(
                             "Missing value for constant, but no error reported?",
                         )))
                     }
-                    Err(ErrorHandled::Reported(e)) => Err(NotConstEvaluatable::Error(e)),
+                    Err(ErrorHandled::Reported(e)) => Err(NotConstEvaluatable::Error(e.into())),
                     Ok(_) => Ok(()),
                 }
             }
@@ -147,7 +147,7 @@ pub fn is_const_evaluatable<'tcx>(
 
                 Err(err)
             }
-            Err(ErrorHandled::Reported(e)) => Err(NotConstEvaluatable::Error(e)),
+            Err(ErrorHandled::Reported(e)) => Err(NotConstEvaluatable::Error(e.into())),
             Ok(_) => Ok(()),
         }
     }
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
index 98365223923..f5f2fe54217 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
@@ -797,9 +797,17 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                             err.span_label(span, explanation);
                         }
 
-                        if let ObligationCauseCode::ObjectCastObligation(concrete_ty, obj_ty) = obligation.cause.code().peel_derives() &&
-                            Some(trait_ref.def_id()) == self.tcx.lang_items().sized_trait() {
-                            self.suggest_borrowing_for_object_cast(&mut err, &root_obligation, *concrete_ty, *obj_ty);
+                        if let ObligationCauseCode::Coercion { source, target } =
+                            *obligation.cause.code().peel_derives()
+                        {
+                            if Some(trait_ref.def_id()) == self.tcx.lang_items().sized_trait() {
+                                self.suggest_borrowing_for_object_cast(
+                                    &mut err,
+                                    &root_obligation,
+                                    source,
+                                    target,
+                                );
+                            }
                         }
 
                         let UnsatisfiedConst(unsatisfied_const) = self
@@ -1510,7 +1518,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                         | ObligationCauseCode::BindingObligation(_, _)
                         | ObligationCauseCode::ExprItemObligation(..)
                         | ObligationCauseCode::ExprBindingObligation(..)
-                        | ObligationCauseCode::ObjectCastObligation(..)
+                        | ObligationCauseCode::Coercion { .. }
                         | ObligationCauseCode::OpaqueType
                 );
 
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs
index 88525e1b720..10bd027b684 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs
@@ -306,6 +306,14 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                     }
                 }
             }
+
+            // `&[{integral}]` - `FromIterator` needs that.
+            if let ty::Ref(_, ref_ty, rustc_ast::Mutability::Not) = self_ty.kind()
+                && let ty::Slice(sty) = ref_ty.kind()
+                && sty.is_integral()
+            {
+                flags.push((sym::_Self, Some("&[{integral}]".to_owned())));
+            }
         });
 
         if let Ok(Some(command)) = OnUnimplementedDirective::of_item(self.tcx, def_id) {
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 53bf38c0a34..ea17f23434b 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
@@ -1442,8 +1442,9 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
         err: &mut Diagnostic,
         obligation: &PredicateObligation<'tcx>,
         self_ty: Ty<'tcx>,
-        object_ty: Ty<'tcx>,
+        target_ty: Ty<'tcx>,
     ) {
+        let ty::Ref(_, object_ty, hir::Mutability::Not) = target_ty.kind() else { return; };
         let ty::Dynamic(predicates, _, ty::Dyn) = object_ty.kind() else { return; };
         let self_ref_ty = self.tcx.mk_imm_ref(self.tcx.lifetimes.re_erased, self_ty);
 
@@ -1458,7 +1459,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
         err.span_suggestion(
             obligation.cause.span.shrink_to_lo(),
             format!(
-                "consider borrowing the value, since `&{self_ty}` can be coerced into `{object_ty}`"
+                "consider borrowing the value, since `&{self_ty}` can be coerced into `{target_ty}`"
             ),
             "&",
             Applicability::MaybeIncorrect,
@@ -2446,10 +2447,9 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
             && generator_did.is_local()
             // Try to avoid cycles.
             && !generator_within_in_progress_typeck
+            && let Some(generator_info) = self.tcx.mir_generator_witnesses(generator_did)
         {
-            let generator_info = &self.tcx.mir_generator_witnesses(generator_did);
             debug!(?generator_info);
-
             'find_source: for (variant, source_info) in
                 generator_info.variant_fields.iter().zip(&generator_info.variant_source_info)
             {
@@ -2851,30 +2851,27 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                     err.span_note(tcx.def_span(item_def_id), descr);
                 }
             }
-            ObligationCauseCode::ObjectCastObligation(concrete_ty, object_ty) => {
-                let (concrete_ty, concrete_file) =
-                    self.tcx.short_ty_string(self.resolve_vars_if_possible(concrete_ty));
-                let (object_ty, object_file) =
-                    self.tcx.short_ty_string(self.resolve_vars_if_possible(object_ty));
+            ObligationCauseCode::Coercion { source, target } => {
+                let (source, source_file) =
+                    self.tcx.short_ty_string(self.resolve_vars_if_possible(source));
+                let (target, target_file) =
+                    self.tcx.short_ty_string(self.resolve_vars_if_possible(target));
                 err.note(with_forced_trimmed_paths!(format!(
-                    "required for the cast from `{concrete_ty}` to the object type `{object_ty}`",
+                    "required for the cast from `{source}` to `{target}`",
                 )));
-                if let Some(file) = concrete_file {
+                if let Some(file) = source_file {
                     err.note(format!(
-                        "the full name for the casted type has been written to '{}'",
+                        "the full name for the source type has been written to '{}'",
                         file.display(),
                     ));
                 }
-                if let Some(file) = object_file {
+                if let Some(file) = target_file {
                     err.note(format!(
-                        "the full name for the object type has been written to '{}'",
+                        "the full name for the target type has been written to '{}'",
                         file.display(),
                     ));
                 }
             }
-            ObligationCauseCode::Coercion { source: _, target } => {
-                err.note(format!("required by cast to type `{}`", self.ty_to_string(target)));
-            }
             ObligationCauseCode::RepeatElementCopy { is_const_fn } => {
                 err.note(
                     "the `Copy` trait is required because this value will be copied for each element of the array",
diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs
index 43196d1e629..2f85c32b575 100644
--- a/compiler/rustc_trait_selection/src/traits/fulfill.rs
+++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs
@@ -615,7 +615,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
                         (Err(ErrorHandled::Reported(reported)), _)
                         | (_, Err(ErrorHandled::Reported(reported))) => ProcessResult::Error(
                             CodeSelectionError(SelectionError::NotConstEvaluatable(
-                                NotConstEvaluatable::Error(reported),
+                                NotConstEvaluatable::Error(reported.into()),
                             )),
                         ),
                         (Err(ErrorHandled::TooGeneric), _) | (_, Err(ErrorHandled::TooGeneric)) => {
diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs
index 38daca5377a..f265230ff77 100644
--- a/compiler/rustc_trait_selection/src/traits/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/mod.rs
@@ -17,6 +17,7 @@ pub mod query;
 mod select;
 mod specialize;
 mod structural_match;
+mod structural_normalize;
 mod util;
 mod vtable;
 pub mod wf;
@@ -26,6 +27,7 @@ use crate::infer::{InferCtxt, TyCtxtInferExt};
 use crate::traits::error_reporting::TypeErrCtxtExt as _;
 use crate::traits::query::evaluate_obligation::InferCtxtExt as _;
 use rustc_errors::ErrorGuaranteed;
+use rustc_middle::query::Providers;
 use rustc_middle::ty::fold::TypeFoldable;
 use rustc_middle::ty::visit::{TypeVisitable, TypeVisitableExt};
 use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt, TypeSuperVisitable};
@@ -61,6 +63,7 @@ pub use self::specialize::{
 pub use self::structural_match::{
     search_for_adt_const_param_violation, search_for_structural_match_violation,
 };
+pub use self::structural_normalize::StructurallyNormalizeExt;
 pub use self::util::elaborate;
 pub use self::util::{expand_trait_aliases, TraitAliasExpander};
 pub use self::util::{get_vtable_index_of_object_method, impl_item_is_final, upcast_choices};
@@ -142,35 +145,36 @@ pub fn type_known_to_meet_bound_modulo_regions<'tcx>(
 fn pred_known_to_hold_modulo_regions<'tcx>(
     infcx: &InferCtxt<'tcx>,
     param_env: ty::ParamEnv<'tcx>,
-    pred: impl ToPredicate<'tcx> + TypeVisitable<TyCtxt<'tcx>>,
+    pred: impl ToPredicate<'tcx>,
 ) -> bool {
-    let has_non_region_infer = pred.has_non_region_infer();
     let obligation = Obligation::new(infcx.tcx, ObligationCause::dummy(), param_env, pred);
 
     let result = infcx.evaluate_obligation_no_overflow(&obligation);
     debug!(?result);
 
-    if result.must_apply_modulo_regions() && !has_non_region_infer {
+    if result.must_apply_modulo_regions() {
         true
     } else if result.may_apply() {
-        // Because of inference "guessing", selection can sometimes claim
-        // to succeed while the success requires a guess. To ensure
-        // this function's result remains infallible, we must confirm
-        // that guess. While imperfect, I believe this is sound.
-
-        // The handling of regions in this area of the code is terrible,
-        // see issue #29149. We should be able to improve on this with
-        // NLL.
-        let ocx = ObligationCtxt::new(infcx);
-        ocx.register_obligation(obligation);
-        let errors = ocx.select_all_or_error();
-        match errors.as_slice() {
-            [] => true,
-            errors => {
-                debug!(?errors);
-                false
+        // Sometimes obligations are ambiguous because the recursive evaluator
+        // is not smart enough, so we fall back to fulfillment when we're not certain
+        // that an obligation holds or not. Even still, we must make sure that
+        // the we do no inference in the process of checking this obligation.
+        let goal = infcx.resolve_vars_if_possible((obligation.predicate, obligation.param_env));
+        infcx.probe(|_| {
+            let ocx = ObligationCtxt::new_in_snapshot(infcx);
+            ocx.register_obligation(obligation);
+
+            let errors = ocx.select_all_or_error();
+            match errors.as_slice() {
+                // Only known to hold if we did no inference.
+                [] => infcx.shallow_resolve(goal) == goal,
+
+                errors => {
+                    debug!(?errors);
+                    false
+                }
             }
-        }
+        })
     } else {
         false
     }
@@ -498,10 +502,10 @@ fn is_impossible_method(tcx: TyCtxt<'_>, (impl_def_id, trait_item_def_id): (DefI
     false
 }
 
-pub fn provide(providers: &mut ty::query::Providers) {
+pub fn provide(providers: &mut Providers) {
     object_safety::provide(providers);
     vtable::provide(providers);
-    *providers = ty::query::Providers {
+    *providers = Providers {
         specialization_graph_of: specialize::specialization_graph_provider,
         specializes: specialize::specializes,
         subst_and_check_impossible_predicates,
diff --git a/compiler/rustc_trait_selection/src/traits/object_safety.rs b/compiler/rustc_trait_selection/src/traits/object_safety.rs
index 06d9c10386e..c81bf6ebc2e 100644
--- a/compiler/rustc_trait_selection/src/traits/object_safety.rs
+++ b/compiler/rustc_trait_selection/src/traits/object_safety.rs
@@ -16,6 +16,7 @@ use crate::traits::{self, Obligation, ObligationCause};
 use rustc_errors::{DelayDm, FatalError, MultiSpan};
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
+use rustc_middle::query::Providers;
 use rustc_middle::ty::subst::{GenericArg, InternalSubsts};
 use rustc_middle::ty::{
     self, EarlyBinder, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor,
@@ -947,7 +948,6 @@ pub fn contains_illegal_impl_trait_in_trait<'tcx>(
     })
 }
 
-pub fn provide(providers: &mut ty::query::Providers) {
-    *providers =
-        ty::query::Providers { object_safety_violations, check_is_object_safe, ..*providers };
+pub fn provide(providers: &mut Providers) {
+    *providers = Providers { object_safety_violations, check_is_object_safe, ..*providers };
 }
diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs
index 8e684b7ac23..51069897120 100644
--- a/compiler/rustc_trait_selection/src/traits/project.rs
+++ b/compiler/rustc_trait_selection/src/traits/project.rs
@@ -1543,7 +1543,10 @@ fn assemble_candidates_from_trait_def<'cx, 'tcx>(
     // Check whether the self-type is itself a projection.
     // If so, extract what we know from the trait and try to come up with a good answer.
     let bounds = match *obligation.predicate.self_ty().kind() {
-        ty::Alias(_, ref data) => tcx.item_bounds(data.def_id).subst(tcx, data.substs),
+        // Excluding IATs here as they don't have meaningful item bounds.
+        ty::Alias(ty::Projection | ty::Opaque, ref data) => {
+            tcx.item_bounds(data.def_id).subst(tcx, data.substs)
+        }
         ty::Infer(ty::TyVar(_)) => {
             // If the self-type is an inference variable, then it MAY wind up
             // being a projected type, so induce an ambiguity.
@@ -2260,7 +2263,7 @@ fn confirm_param_env_candidate<'cx, 'tcx>(
                 obligation, poly_cache_entry, e,
             );
             debug!("confirm_param_env_candidate: {}", msg);
-            let err = infcx.tcx.ty_error_with_message(obligation.cause.span, &msg);
+            let err = infcx.tcx.ty_error_with_message(obligation.cause.span, msg);
             Progress { term: err.into(), obligations: vec![] }
         }
     }
diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
index a8fb55df2d3..aa230936903 100644
--- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
@@ -143,7 +143,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         // Before we go into the whole placeholder thing, just
         // quickly check if the self-type is a projection at all.
         match obligation.predicate.skip_binder().trait_ref.self_ty().kind() {
-            ty::Alias(..) => {}
+            // Excluding IATs here as they don't have meaningful item bounds.
+            ty::Alias(ty::Projection | ty::Opaque, _) => {}
             ty::Infer(ty::TyVar(_)) => {
                 span_bug!(
                     obligation.cause.span,
diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
index 4dc84e0ad10..0d9f55d4c2e 100644
--- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
@@ -29,9 +29,9 @@ use crate::traits::{
     ImplSourceAutoImplData, ImplSourceBuiltinData, ImplSourceClosureData,
     ImplSourceConstDestructData, ImplSourceFnPointerData, ImplSourceFutureData,
     ImplSourceGeneratorData, ImplSourceObjectData, ImplSourceTraitAliasData,
-    ImplSourceTraitUpcastingData, ImplSourceUserDefinedData, Normalized, ObjectCastObligation,
-    Obligation, ObligationCause, OutputTypeParameterMismatch, PredicateObligation, Selection,
-    SelectionError, TraitNotObjectSafe, TraitObligation, Unimplemented,
+    ImplSourceTraitUpcastingData, ImplSourceUserDefinedData, Normalized, Obligation,
+    ObligationCause, OutputTypeParameterMismatch, PredicateObligation, Selection, SelectionError,
+    TraitNotObjectSafe, TraitObligation, Unimplemented,
 };
 
 use super::BuiltinImplConditions;
@@ -132,6 +132,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             }
         };
 
+        // The obligations returned by confirmation are recursively evaluated
+        // so we need to make sure they have the correct depth.
+        for subobligation in impl_src.borrow_nested_obligations_mut() {
+            subobligation.set_depth_from_parent(obligation.recursion_depth);
+        }
+
         if !obligation.predicate.is_const_if_const() {
             // normalize nested predicates according to parent predicate's constness.
             impl_src = impl_src.map(|mut o| {
@@ -156,7 +162,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         let placeholder_self_ty = placeholder_trait_predicate.self_ty();
         let placeholder_trait_predicate = ty::Binder::dummy(placeholder_trait_predicate);
         let (def_id, substs) = match *placeholder_self_ty.kind() {
-            ty::Alias(_, ty::AliasTy { def_id, substs, .. }) => (def_id, substs),
+            // Excluding IATs here as they don't have meaningful item bounds.
+            ty::Alias(ty::Projection | ty::Opaque, ty::AliasTy { def_id, substs, .. }) => {
+                (def_id, substs)
+            }
             _ => bug!("projection candidate for unexpected type: {:?}", placeholder_self_ty),
         };
 
@@ -905,16 +914,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                     .map_err(|_| Unimplemented)?;
                 nested.extend(obligations);
 
-                // Register one obligation for 'a: 'b.
-                let cause = ObligationCause::new(
-                    obligation.cause.span,
-                    obligation.cause.body_id,
-                    ObjectCastObligation(source, target),
-                );
                 let outlives = ty::OutlivesPredicate(r_a, r_b);
                 nested.push(Obligation::with_depth(
                     tcx,
-                    cause,
+                    obligation.cause.clone(),
                     obligation.recursion_depth + 1,
                     obligation.param_env,
                     obligation.predicate.rebind(outlives),
@@ -1005,15 +1008,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 nested.extend(obligations);
 
                 // Register one obligation for 'a: 'b.
-                let cause = ObligationCause::new(
-                    obligation.cause.span,
-                    obligation.cause.body_id,
-                    ObjectCastObligation(source, target),
-                );
                 let outlives = ty::OutlivesPredicate(r_a, r_b);
                 nested.push(Obligation::with_depth(
                     tcx,
-                    cause,
+                    obligation.cause.clone(),
                     obligation.recursion_depth + 1,
                     obligation.param_env,
                     obligation.predicate.rebind(outlives),
@@ -1027,16 +1025,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                     return Err(TraitNotObjectSafe(did));
                 }
 
-                let cause = ObligationCause::new(
-                    obligation.cause.span,
-                    obligation.cause.body_id,
-                    ObjectCastObligation(source, target),
-                );
-
                 let predicate_to_obligation = |predicate| {
                     Obligation::with_depth(
                         tcx,
-                        cause.clone(),
+                        obligation.cause.clone(),
                         obligation.recursion_depth + 1,
                         obligation.param_env,
                         predicate,
@@ -1056,7 +1048,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 );
 
                 // We can only make objects from sized types.
-                let tr = ty::TraitRef::from_lang_item(tcx, LangItem::Sized, cause.span, [source]);
+                let tr = ty::TraitRef::from_lang_item(
+                    tcx,
+                    LangItem::Sized,
+                    obligation.cause.span,
+                    [source],
+                );
                 nested.push(predicate_to_obligation(tr.without_const().to_predicate(tcx)));
 
                 // If the type is `Foo + 'a`, ensure that the type
diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs
index e4f5a84f424..b366bbd531b 100644
--- a/compiler/rustc_trait_selection/src/traits/select/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs
@@ -537,14 +537,22 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         obligation: &PredicateObligation<'tcx>,
     ) -> Result<EvaluationResult, OverflowError> {
         self.evaluation_probe(|this| {
-            if this.tcx().trait_solver_next() {
-                this.evaluate_predicates_recursively_in_new_solver([obligation.clone()])
+            let goal =
+                this.infcx.resolve_vars_if_possible((obligation.predicate, obligation.param_env));
+            let mut result = if this.tcx().trait_solver_next() {
+                this.evaluate_predicates_recursively_in_new_solver([obligation.clone()])?
             } else {
                 this.evaluate_predicate_recursively(
                     TraitObligationStackList::empty(&ProvisionalEvaluationCache::default()),
                     obligation.clone(),
-                )
+                )?
+            };
+            // If the predicate has done any inference, then downgrade the
+            // result to ambiguous.
+            if this.infcx.shallow_resolve(goal) != goal {
+                result = result.max(EvaluatedToAmbig);
             }
+            Ok(result)
         })
     }
 
@@ -1645,7 +1653,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
 
         let tcx = self.infcx.tcx;
         let (def_id, substs) = match *placeholder_trait_predicate.trait_ref.self_ty().kind() {
-            ty::Alias(_, ty::AliasTy { def_id, substs, .. }) => (def_id, substs),
+            ty::Alias(ty::Projection | ty::Opaque, ty::AliasTy { def_id, substs, .. }) => {
+                (def_id, substs)
+            }
             _ => {
                 span_bug!(
                     obligation.cause.span,
@@ -2647,14 +2657,19 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
         let predicates = predicates.instantiate_own(tcx, substs);
         let mut obligations = Vec::with_capacity(predicates.len());
         for (index, (predicate, span)) in predicates.into_iter().enumerate() {
-            let cause = cause.clone().derived_cause(parent_trait_pred, |derived| {
-                ImplDerivedObligation(Box::new(ImplDerivedObligationCause {
-                    derived,
-                    impl_or_alias_def_id: def_id,
-                    impl_def_predicate_index: Some(index),
-                    span,
-                }))
-            });
+            let cause =
+                if Some(parent_trait_pred.def_id()) == tcx.lang_items().coerce_unsized_trait() {
+                    cause.clone()
+                } else {
+                    cause.clone().derived_cause(parent_trait_pred, |derived| {
+                        ImplDerivedObligation(Box::new(ImplDerivedObligationCause {
+                            derived,
+                            impl_or_alias_def_id: def_id,
+                            impl_def_predicate_index: Some(index),
+                            span,
+                        }))
+                    })
+                };
             let predicate = normalize_with_depth_to(
                 self,
                 param_env,
diff --git a/compiler/rustc_trait_selection/src/traits/structural_normalize.rs b/compiler/rustc_trait_selection/src/traits/structural_normalize.rs
new file mode 100644
index 00000000000..af8dd0da579
--- /dev/null
+++ b/compiler/rustc_trait_selection/src/traits/structural_normalize.rs
@@ -0,0 +1,55 @@
+use rustc_infer::infer::at::At;
+use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
+use rustc_infer::traits::{FulfillmentError, TraitEngine};
+use rustc_middle::ty::{self, Ty};
+
+use crate::traits::{query::evaluate_obligation::InferCtxtExt, NormalizeExt, Obligation};
+
+pub trait StructurallyNormalizeExt<'tcx> {
+    fn structurally_normalize(
+        &self,
+        ty: Ty<'tcx>,
+        fulfill_cx: &mut dyn TraitEngine<'tcx>,
+    ) -> Result<Ty<'tcx>, Vec<FulfillmentError<'tcx>>>;
+}
+
+impl<'tcx> StructurallyNormalizeExt<'tcx> for At<'_, 'tcx> {
+    fn structurally_normalize(
+        &self,
+        mut ty: Ty<'tcx>,
+        fulfill_cx: &mut dyn TraitEngine<'tcx>,
+    ) -> Result<Ty<'tcx>, Vec<FulfillmentError<'tcx>>> {
+        assert!(!ty.is_ty_var(), "should have resolved vars before calling");
+
+        if self.infcx.tcx.trait_solver_next() {
+            while let ty::Alias(ty::Projection, projection_ty) = *ty.kind() {
+                let new_infer_ty = self.infcx.next_ty_var(TypeVariableOrigin {
+                    kind: TypeVariableOriginKind::NormalizeProjectionType,
+                    span: self.cause.span,
+                });
+                let obligation = Obligation::new(
+                    self.infcx.tcx,
+                    self.cause.clone(),
+                    self.param_env,
+                    ty::Binder::dummy(ty::ProjectionPredicate {
+                        projection_ty,
+                        term: new_infer_ty.into(),
+                    }),
+                );
+                if self.infcx.predicate_may_hold(&obligation) {
+                    fulfill_cx.register_predicate_obligation(self.infcx, obligation);
+                    let errors = fulfill_cx.select_where_possible(self.infcx);
+                    if !errors.is_empty() {
+                        return Err(errors);
+                    }
+                    ty = self.infcx.resolve_vars_if_possible(new_infer_ty);
+                } else {
+                    break;
+                }
+            }
+            Ok(ty)
+        } else {
+            Ok(self.normalize(ty).into_value_registering_obligations(self.infcx, fulfill_cx))
+        }
+    }
+}
diff --git a/compiler/rustc_trait_selection/src/traits/vtable.rs b/compiler/rustc_trait_selection/src/traits/vtable.rs
index f7a3126b4aa..cc674ceee3d 100644
--- a/compiler/rustc_trait_selection/src/traits/vtable.rs
+++ b/compiler/rustc_trait_selection/src/traits/vtable.rs
@@ -4,6 +4,7 @@ use rustc_hir::def_id::DefId;
 use rustc_hir::lang_items::LangItem;
 use rustc_infer::traits::util::PredicateSet;
 use rustc_infer::traits::ImplSource;
+use rustc_middle::query::Providers;
 use rustc_middle::ty::visit::TypeVisitableExt;
 use rustc_middle::ty::InternalSubsts;
 use rustc_middle::ty::{self, GenericParamDefKind, ToPredicate, Ty, TyCtxt, VtblEntry};
@@ -379,8 +380,8 @@ pub(crate) fn count_own_vtable_entries<'tcx>(
     tcx.own_existential_vtable_entries(trait_ref.def_id()).len()
 }
 
-pub(super) fn provide(providers: &mut ty::query::Providers) {
-    *providers = ty::query::Providers {
+pub(super) fn provide(providers: &mut Providers) {
+    *providers = Providers {
         own_existential_vtable_entries,
         vtable_entries,
         vtable_trait_upcasting_coercion_new_vptr_slot,
diff --git a/compiler/rustc_traits/src/chalk/mod.rs b/compiler/rustc_traits/src/chalk/mod.rs
index a5ebc26a8bc..8834449c9a4 100644
--- a/compiler/rustc_traits/src/chalk/mod.rs
+++ b/compiler/rustc_traits/src/chalk/mod.rs
@@ -7,8 +7,8 @@ pub(crate) mod db;
 pub(crate) mod lowering;
 
 use rustc_middle::infer::canonical::{CanonicalTyVarKind, CanonicalVarKind};
+use rustc_middle::query::Providers;
 use rustc_middle::traits::ChalkRustInterner;
-use rustc_middle::ty::query::Providers;
 use rustc_middle::ty::{self, TyCtxt, TypeFoldable, TypeVisitable};
 
 use rustc_infer::infer::canonical::{
diff --git a/compiler/rustc_traits/src/dropck_outlives.rs b/compiler/rustc_traits/src/dropck_outlives.rs
index fcdffc7468b..83f6c7d07fe 100644
--- a/compiler/rustc_traits/src/dropck_outlives.rs
+++ b/compiler/rustc_traits/src/dropck_outlives.rs
@@ -2,7 +2,7 @@ use rustc_data_structures::fx::FxHashSet;
 use rustc_hir::def_id::DefId;
 use rustc_infer::infer::canonical::{Canonical, QueryResponse};
 use rustc_infer::infer::TyCtxtInferExt;
-use rustc_middle::ty::query::Providers;
+use rustc_middle::query::Providers;
 use rustc_middle::ty::InternalSubsts;
 use rustc_middle::ty::{self, EarlyBinder, ParamEnvAnd, Ty, TyCtxt};
 use rustc_span::source_map::{Span, DUMMY_SP};
diff --git a/compiler/rustc_traits/src/evaluate_obligation.rs b/compiler/rustc_traits/src/evaluate_obligation.rs
index e94c8efe69a..149dffc7e31 100644
--- a/compiler/rustc_traits/src/evaluate_obligation.rs
+++ b/compiler/rustc_traits/src/evaluate_obligation.rs
@@ -1,5 +1,5 @@
 use rustc_infer::infer::{DefiningAnchor, TyCtxtInferExt};
-use rustc_middle::ty::query::Providers;
+use rustc_middle::query::Providers;
 use rustc_middle::ty::{ParamEnvAnd, TyCtxt};
 use rustc_span::source_map::DUMMY_SP;
 use rustc_trait_selection::traits::query::CanonicalPredicateGoal;
diff --git a/compiler/rustc_traits/src/implied_outlives_bounds.rs b/compiler/rustc_traits/src/implied_outlives_bounds.rs
index f5bba14d2fb..0c2bb863e1f 100644
--- a/compiler/rustc_traits/src/implied_outlives_bounds.rs
+++ b/compiler/rustc_traits/src/implied_outlives_bounds.rs
@@ -6,7 +6,7 @@ use rustc_infer::infer::canonical::{self, Canonical};
 use rustc_infer::infer::outlives::components::{push_outlives_components, Component};
 use rustc_infer::infer::TyCtxtInferExt;
 use rustc_infer::traits::query::OutlivesBound;
-use rustc_middle::ty::query::Providers;
+use rustc_middle::query::Providers;
 use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt};
 use rustc_span::def_id::CRATE_DEF_ID;
 use rustc_span::source_map::DUMMY_SP;
diff --git a/compiler/rustc_traits/src/lib.rs b/compiler/rustc_traits/src/lib.rs
index 8bea5588ae7..b0f9c57154f 100644
--- a/compiler/rustc_traits/src/lib.rs
+++ b/compiler/rustc_traits/src/lib.rs
@@ -23,7 +23,7 @@ mod type_op;
 
 pub use type_op::{type_op_ascribe_user_type_with_span, type_op_prove_predicate_with_cause};
 
-use rustc_middle::ty::query::Providers;
+use rustc_middle::query::Providers;
 
 pub fn provide(p: &mut Providers) {
     dropck_outlives::provide(p);
diff --git a/compiler/rustc_traits/src/normalize_erasing_regions.rs b/compiler/rustc_traits/src/normalize_erasing_regions.rs
index 5da0f16c2bf..94c33efaeff 100644
--- a/compiler/rustc_traits/src/normalize_erasing_regions.rs
+++ b/compiler/rustc_traits/src/normalize_erasing_regions.rs
@@ -1,6 +1,6 @@
 use rustc_infer::infer::TyCtxtInferExt;
+use rustc_middle::query::Providers;
 use rustc_middle::traits::query::NoSolution;
-use rustc_middle::ty::query::Providers;
 use rustc_middle::ty::{self, ParamEnvAnd, TyCtxt, TypeFoldable, TypeVisitableExt};
 use rustc_trait_selection::traits::query::normalize::QueryNormalizeExt;
 use rustc_trait_selection::traits::{Normalized, ObligationCause};
diff --git a/compiler/rustc_traits/src/normalize_projection_ty.rs b/compiler/rustc_traits/src/normalize_projection_ty.rs
index 36d80a06ee7..b552ba41acd 100644
--- a/compiler/rustc_traits/src/normalize_projection_ty.rs
+++ b/compiler/rustc_traits/src/normalize_projection_ty.rs
@@ -1,6 +1,6 @@
 use rustc_infer::infer::canonical::{Canonical, QueryResponse};
 use rustc_infer::infer::TyCtxtInferExt;
-use rustc_middle::ty::query::Providers;
+use rustc_middle::query::Providers;
 use rustc_middle::ty::{ParamEnvAnd, TyCtxt};
 use rustc_trait_selection::infer::InferCtxtBuilderExt;
 use rustc_trait_selection::traits::query::{
diff --git a/compiler/rustc_traits/src/type_op.rs b/compiler/rustc_traits/src/type_op.rs
index 19622112f2a..70dc7ccec63 100644
--- a/compiler/rustc_traits/src/type_op.rs
+++ b/compiler/rustc_traits/src/type_op.rs
@@ -2,7 +2,7 @@ use rustc_hir as hir;
 use rustc_infer::infer::canonical::{Canonical, QueryResponse};
 use rustc_infer::infer::{DefiningAnchor, TyCtxtInferExt};
 use rustc_infer::traits::ObligationCauseCode;
-use rustc_middle::ty::query::Providers;
+use rustc_middle::query::Providers;
 use rustc_middle::ty::{self, FnSig, Lift, PolyFnSig, Ty, TyCtxt, TypeFoldable};
 use rustc_middle::ty::{ParamEnvAnd, Predicate};
 use rustc_middle::ty::{UserSelfTy, UserSubsts, UserType};
diff --git a/compiler/rustc_ty_utils/messages.ftl b/compiler/rustc_ty_utils/messages.ftl
index 15a14112f4a..5bc3e3c00c9 100644
--- a/compiler/rustc_ty_utils/messages.ftl
+++ b/compiler/rustc_ty_utils/messages.ftl
@@ -55,3 +55,11 @@ ty_utils_multiple_array_fields_simd_type = monomorphising SIMD type `{$ty}` with
 ty_utils_oversized_simd_type = monomorphising SIMD type `{$ty}` of length greater than {$max_lanes}
 
 ty_utils_non_primitive_simd_type = monomorphising SIMD type `{$ty}` with a non-primitive-scalar (integer/float/pointer) element type `{$e_ty}`
+
+ty_utils_impl_trait_duplicate_arg = non-defining opaque type use in defining scope
+    .label = generic argument `{$arg}` used twice
+    .note = for this opaque type
+
+ty_utils_impl_trait_not_param = non-defining opaque type use in defining scope
+    .label = argument `{$arg}` is not a generic parameter
+    .note = for this opaque type
diff --git a/compiler/rustc_ty_utils/src/abi.rs b/compiler/rustc_ty_utils/src/abi.rs
index 271284b2d81..442d041a8a7 100644
--- a/compiler/rustc_ty_utils/src/abi.rs
+++ b/compiler/rustc_ty_utils/src/abi.rs
@@ -1,5 +1,6 @@
 use rustc_hir as hir;
 use rustc_hir::lang_items::LangItem;
+use rustc_middle::query::Providers;
 use rustc_middle::ty::layout::{
     fn_can_unwind, FnAbiError, HasParamEnv, HasTyCtxt, LayoutCx, LayoutOf, TyAndLayout,
 };
@@ -14,8 +15,8 @@ use rustc_target::spec::abi::Abi as SpecAbi;
 
 use std::iter;
 
-pub fn provide(providers: &mut ty::query::Providers) {
-    *providers = ty::query::Providers { fn_abi_of_fn_ptr, fn_abi_of_instance, ..*providers };
+pub fn provide(providers: &mut Providers) {
+    *providers = Providers { fn_abi_of_fn_ptr, fn_abi_of_instance, ..*providers };
 }
 
 // NOTE(eddyb) this is private to avoid using it from outside of
diff --git a/compiler/rustc_ty_utils/src/assoc.rs b/compiler/rustc_ty_utils/src/assoc.rs
index 9029ba2a51a..ed574f22e61 100644
--- a/compiler/rustc_ty_utils/src/assoc.rs
+++ b/compiler/rustc_ty_utils/src/assoc.rs
@@ -4,11 +4,12 @@ use rustc_hir::def::DefKind;
 use rustc_hir::def_id::{DefId, DefIdMap, LocalDefId};
 use rustc_hir::definitions::DefPathData;
 use rustc_hir::intravisit::{self, Visitor};
+use rustc_middle::query::Providers;
 use rustc_middle::ty::{self, ImplTraitInTraitData, InternalSubsts, TyCtxt};
 use rustc_span::symbol::kw;
 
-pub fn provide(providers: &mut ty::query::Providers) {
-    *providers = ty::query::Providers {
+pub fn provide(providers: &mut Providers) {
+    *providers = Providers {
         associated_item,
         associated_item_def_ids,
         associated_items,
diff --git a/compiler/rustc_ty_utils/src/common_traits.rs b/compiler/rustc_ty_utils/src/common_traits.rs
index 3b1abdcb24f..51b908881eb 100644
--- a/compiler/rustc_ty_utils/src/common_traits.rs
+++ b/compiler/rustc_ty_utils/src/common_traits.rs
@@ -2,6 +2,7 @@
 
 use rustc_hir::lang_items::LangItem;
 use rustc_infer::infer::TyCtxtInferExt;
+use rustc_middle::query::Providers;
 use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_trait_selection::traits;
 
@@ -32,12 +33,6 @@ fn is_item_raw<'tcx>(
     traits::type_known_to_meet_bound_modulo_regions(&infcx, param_env, ty, trait_def_id)
 }
 
-pub(crate) fn provide(providers: &mut ty::query::Providers) {
-    *providers = ty::query::Providers {
-        is_copy_raw,
-        is_sized_raw,
-        is_freeze_raw,
-        is_unpin_raw,
-        ..*providers
-    };
+pub(crate) fn provide(providers: &mut Providers) {
+    *providers = Providers { is_copy_raw, is_sized_raw, is_freeze_raw, is_unpin_raw, ..*providers };
 }
diff --git a/compiler/rustc_ty_utils/src/consts.rs b/compiler/rustc_ty_utils/src/consts.rs
index 3dd1d056be2..1219bb40098 100644
--- a/compiler/rustc_ty_utils/src/consts.rs
+++ b/compiler/rustc_ty_utils/src/consts.rs
@@ -2,6 +2,7 @@ use rustc_errors::ErrorGuaranteed;
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::LocalDefId;
 use rustc_middle::mir::interpret::{LitToConstError, LitToConstInput};
+use rustc_middle::query::Providers;
 use rustc_middle::thir::visit;
 use rustc_middle::thir::visit::Visitor;
 use rustc_middle::ty::abstract_const::CastKind;
@@ -115,9 +116,7 @@ fn recurse_build<'tcx>(
             let sp = node.span;
             match tcx.at(sp).lit_to_const(LitToConstInput { lit: &lit.node, ty: node.ty, neg }) {
                 Ok(c) => c,
-                Err(LitToConstError::Reported(guar)) => {
-                    tcx.const_error_with_guaranteed(node.ty, guar)
-                }
+                Err(LitToConstError::Reported(guar)) => tcx.const_error(node.ty, guar),
                 Err(LitToConstError::TypeError) => {
                     bug!("encountered type error in lit_to_const")
                 }
@@ -423,6 +422,6 @@ pub fn thir_abstract_const(
     Ok(Some(ty::EarlyBinder(recurse_build(tcx, body, body_id, root_span)?)))
 }
 
-pub fn provide(providers: &mut ty::query::Providers) {
-    *providers = ty::query::Providers { destructure_const, thir_abstract_const, ..*providers };
+pub fn provide(providers: &mut Providers) {
+    *providers = Providers { destructure_const, thir_abstract_const, ..*providers };
 }
diff --git a/compiler/rustc_ty_utils/src/errors.rs b/compiler/rustc_ty_utils/src/errors.rs
index 3d3fc50e6e5..553bf40ef3a 100644
--- a/compiler/rustc_ty_utils/src/errors.rs
+++ b/compiler/rustc_ty_utils/src/errors.rs
@@ -1,7 +1,7 @@
 //! Errors emitted by ty_utils
 
 use rustc_macros::{Diagnostic, Subdiagnostic};
-use rustc_middle::ty::Ty;
+use rustc_middle::ty::{GenericArg, Ty};
 use rustc_span::Span;
 
 #[derive(Diagnostic)]
@@ -100,3 +100,25 @@ pub struct NonPrimitiveSimdType<'tcx> {
     pub ty: Ty<'tcx>,
     pub e_ty: Ty<'tcx>,
 }
+
+#[derive(Diagnostic)]
+#[diag(ty_utils_impl_trait_duplicate_arg)]
+pub struct DuplicateArg<'tcx> {
+    pub arg: GenericArg<'tcx>,
+    #[primary_span]
+    #[label]
+    pub span: Span,
+    #[note]
+    pub opaque_span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(ty_utils_impl_trait_not_param)]
+pub struct NotParam<'tcx> {
+    pub arg: GenericArg<'tcx>,
+    #[primary_span]
+    #[label]
+    pub span: Span,
+    #[note]
+    pub opaque_span: Span,
+}
diff --git a/compiler/rustc_ty_utils/src/implied_bounds.rs b/compiler/rustc_ty_utils/src/implied_bounds.rs
index 5ca5d14337c..081be065864 100644
--- a/compiler/rustc_ty_utils/src/implied_bounds.rs
+++ b/compiler/rustc_ty_utils/src/implied_bounds.rs
@@ -1,8 +1,9 @@
 use rustc_hir::{def::DefKind, def_id::DefId};
+use rustc_middle::query::Providers;
 use rustc_middle::ty::{self, Ty, TyCtxt};
 
-pub fn provide(providers: &mut ty::query::Providers) {
-    *providers = ty::query::Providers { assumed_wf_types, ..*providers };
+pub fn provide(providers: &mut Providers) {
+    *providers = Providers { assumed_wf_types, ..*providers };
 }
 
 fn assumed_wf_types(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::List<Ty<'_>> {
diff --git a/compiler/rustc_ty_utils/src/instance.rs b/compiler/rustc_ty_utils/src/instance.rs
index eb3c21163ab..36a20c78fcc 100644
--- a/compiler/rustc_ty_utils/src/instance.rs
+++ b/compiler/rustc_ty_utils/src/instance.rs
@@ -1,6 +1,7 @@
 use rustc_errors::ErrorGuaranteed;
 use rustc_hir::def_id::DefId;
 use rustc_infer::infer::TyCtxtInferExt;
+use rustc_middle::query::Providers;
 use rustc_middle::traits::CodegenObligationError;
 use rustc_middle::ty::subst::SubstsRef;
 use rustc_middle::ty::{self, Instance, TyCtxt, TypeVisitableExt};
@@ -319,6 +320,6 @@ fn resolve_associated_item<'tcx>(
     })
 }
 
-pub fn provide(providers: &mut ty::query::Providers) {
-    *providers = ty::query::Providers { resolve_instance, ..*providers };
+pub fn provide(providers: &mut Providers) {
+    *providers = Providers { resolve_instance, ..*providers };
 }
diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs
index f7c75583f60..16cd8bc8e69 100644
--- a/compiler/rustc_ty_utils/src/layout.rs
+++ b/compiler/rustc_ty_utils/src/layout.rs
@@ -3,6 +3,7 @@ use rustc_hir as hir;
 use rustc_index::bit_set::BitSet;
 use rustc_index::{IndexSlice, IndexVec};
 use rustc_middle::mir::{GeneratorLayout, GeneratorSavedLocal};
+use rustc_middle::query::Providers;
 use rustc_middle::ty::layout::{
     IntegerExt, LayoutCx, LayoutError, LayoutOf, TyAndLayout, MAX_SIMD_LANES,
 };
@@ -22,8 +23,8 @@ use crate::errors::{
 };
 use crate::layout_sanity_check::sanity_check_layout;
 
-pub fn provide(providers: &mut ty::query::Providers) {
-    *providers = ty::query::Providers { layout_of, ..*providers };
+pub fn provide(providers: &mut Providers) {
+    *providers = Providers { layout_of, ..*providers };
 }
 
 #[instrument(skip(tcx, query), level = "debug")]
diff --git a/compiler/rustc_ty_utils/src/lib.rs b/compiler/rustc_ty_utils/src/lib.rs
index 73a2f6af579..55b8857ed39 100644
--- a/compiler/rustc_ty_utils/src/lib.rs
+++ b/compiler/rustc_ty_utils/src/lib.rs
@@ -21,7 +21,7 @@ extern crate tracing;
 
 use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage};
 use rustc_fluent_macro::fluent_messages;
-use rustc_middle::ty::query::Providers;
+use rustc_middle::query::Providers;
 
 mod abi;
 mod assoc;
@@ -33,6 +33,7 @@ pub mod instance;
 mod layout;
 mod layout_sanity_check;
 mod needs_drop;
+mod opaque_types;
 pub mod representability;
 mod structural_match;
 mod ty;
@@ -47,6 +48,7 @@ pub fn provide(providers: &mut Providers) {
     implied_bounds::provide(providers);
     layout::provide(providers);
     needs_drop::provide(providers);
+    opaque_types::provide(providers);
     representability::provide(providers);
     ty::provide(providers);
     instance::provide(providers);
diff --git a/compiler/rustc_ty_utils/src/needs_drop.rs b/compiler/rustc_ty_utils/src/needs_drop.rs
index a04f85afb9e..1f9701b9322 100644
--- a/compiler/rustc_ty_utils/src/needs_drop.rs
+++ b/compiler/rustc_ty_utils/src/needs_drop.rs
@@ -2,6 +2,7 @@
 
 use rustc_data_structures::fx::FxHashSet;
 use rustc_hir::def_id::DefId;
+use rustc_middle::query::Providers;
 use rustc_middle::ty::subst::SubstsRef;
 use rustc_middle::ty::util::{needs_drop_components, AlwaysRequiresDrop};
 use rustc_middle::ty::{self, EarlyBinder, Ty, TyCtxt};
@@ -323,8 +324,8 @@ fn adt_significant_drop_tys(
     .map(|components| tcx.mk_type_list(&components))
 }
 
-pub(crate) fn provide(providers: &mut ty::query::Providers) {
-    *providers = ty::query::Providers {
+pub(crate) fn provide(providers: &mut Providers) {
+    *providers = Providers {
         needs_drop_raw,
         has_significant_drop_raw,
         adt_drop_tys,
diff --git a/compiler/rustc_ty_utils/src/opaque_types.rs b/compiler/rustc_ty_utils/src/opaque_types.rs
new file mode 100644
index 00000000000..4e91dd380e8
--- /dev/null
+++ b/compiler/rustc_ty_utils/src/opaque_types.rs
@@ -0,0 +1,198 @@
+use rustc_data_structures::fx::FxHashSet;
+use rustc_errors::ErrorGuaranteed;
+use rustc_hir::{def::DefKind, def_id::LocalDefId};
+use rustc_middle::query::Providers;
+use rustc_middle::ty::util::{CheckRegions, NotUniqueParam};
+use rustc_middle::ty::{self, Ty, TyCtxt};
+use rustc_middle::ty::{TypeSuperVisitable, TypeVisitable, TypeVisitor};
+use rustc_span::Span;
+use rustc_type_ir::AliasKind;
+use std::ops::ControlFlow;
+
+use crate::errors::{DuplicateArg, NotParam};
+
+struct OpaqueTypeCollector<'tcx> {
+    tcx: TyCtxt<'tcx>,
+    opaques: Vec<LocalDefId>,
+    /// The `DefId` of the item which we are collecting opaque types for.
+    item: LocalDefId,
+
+    /// Avoid infinite recursion due to recursive declarations.
+    seen: FxHashSet<LocalDefId>,
+}
+
+impl<'tcx> OpaqueTypeCollector<'tcx> {
+    fn collect(
+        tcx: TyCtxt<'tcx>,
+        item: LocalDefId,
+        val: ty::Binder<'tcx, impl TypeVisitable<TyCtxt<'tcx>>>,
+    ) -> Vec<LocalDefId> {
+        let mut collector = Self { tcx, opaques: Vec::new(), item, seen: Default::default() };
+        val.skip_binder().visit_with(&mut collector);
+        collector.opaques
+    }
+
+    fn span(&self) -> Span {
+        self.tcx.def_span(self.item)
+    }
+
+    fn parent(&self) -> Option<LocalDefId> {
+        match self.tcx.def_kind(self.item) {
+            DefKind::Fn => None,
+            DefKind::AssocFn | DefKind::AssocTy | DefKind::AssocConst => {
+                Some(self.tcx.local_parent(self.item))
+            }
+            other => span_bug!(
+                self.tcx.def_span(self.item),
+                "unhandled item with opaque types: {other:?}"
+            ),
+        }
+    }
+}
+
+impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for OpaqueTypeCollector<'tcx> {
+    type BreakTy = ErrorGuaranteed;
+
+    #[instrument(skip(self), ret, level = "trace")]
+    fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<ErrorGuaranteed> {
+        match t.kind() {
+            ty::Alias(AliasKind::Opaque, alias_ty) if alias_ty.def_id.is_local() => {
+                if !self.seen.insert(alias_ty.def_id.expect_local()) {
+                    return ControlFlow::Continue(());
+                }
+                match self.tcx.uses_unique_generic_params(alias_ty.substs, CheckRegions::Bound) {
+                    Ok(()) => {
+                        // FIXME: implement higher kinded lifetime bounds on nested opaque types. They are not
+                        // supported at all, so this is sound to do, but once we want to support them, you'll
+                        // start seeing the error below.
+
+                        self.opaques.push(alias_ty.def_id.expect_local());
+
+                        // Collect opaque types nested within the associated type bounds of this opaque type.
+                        for (pred, _span) in self
+                            .tcx
+                            .explicit_item_bounds(alias_ty.def_id)
+                            .subst_iter_copied(self.tcx, alias_ty.substs)
+                        {
+                            trace!(?pred);
+                            pred.visit_with(self)?;
+                        }
+
+                        ControlFlow::Continue(())
+                    }
+                    Err(NotUniqueParam::NotParam(arg)) => {
+                        let err = self.tcx.sess.emit_err(NotParam {
+                            arg,
+                            span: self.span(),
+                            opaque_span: self.tcx.def_span(alias_ty.def_id),
+                        });
+                        ControlFlow::Break(err)
+                    }
+                    Err(NotUniqueParam::DuplicateParam(arg)) => {
+                        let err = self.tcx.sess.emit_err(DuplicateArg {
+                            arg,
+                            span: self.span(),
+                            opaque_span: self.tcx.def_span(alias_ty.def_id),
+                        });
+                        ControlFlow::Break(err)
+                    }
+                }
+            }
+            ty::Alias(AliasKind::Projection, alias_ty) => {
+                if let Some(parent) = self.parent() {
+                    trace!(?alias_ty);
+                    let (trait_ref, own_substs) = alias_ty.trait_ref_and_own_substs(self.tcx);
+
+                    trace!(?trait_ref, ?own_substs);
+                    // This avoids having to do normalization of `Self::AssocTy` by only
+                    // supporting the case of a method defining opaque types from assoc types
+                    // in the same impl block.
+                    if trait_ref.self_ty() == self.tcx.type_of(parent).subst_identity() {
+                        for assoc in self.tcx.associated_items(parent).in_definition_order() {
+                            trace!(?assoc);
+                            if assoc.trait_item_def_id == Some(alias_ty.def_id) {
+                                // We reconstruct the generic args of the associated type within the impl
+                                // from the impl's generics and the generic args passed to the type via the
+                                // projection.
+                                let substs = ty::InternalSubsts::identity_for_item(
+                                    self.tcx,
+                                    parent.to_def_id(),
+                                );
+                                trace!(?substs);
+                                let substs: Vec<_> =
+                                    substs.iter().chain(own_substs.iter().copied()).collect();
+                                trace!(?substs);
+                                // Find opaque types in this associated type.
+                                return self
+                                    .tcx
+                                    .type_of(assoc.def_id)
+                                    .subst(self.tcx, &substs)
+                                    .visit_with(self);
+                            }
+                        }
+                    }
+                }
+                t.super_visit_with(self)
+            }
+            _ => t.super_visit_with(self),
+        }
+    }
+}
+
+fn opaque_types_defined_by<'tcx>(tcx: TyCtxt<'tcx>, item: LocalDefId) -> &'tcx [LocalDefId] {
+    let kind = tcx.def_kind(item);
+    trace!(?kind);
+    // FIXME(type_alias_impl_trait): This is definitely still wrong except for RPIT and impl trait in assoc types.
+    match kind {
+        // We're also doing this for `AssocTy` for the wf checks in `check_opaque_meets_bounds`
+        DefKind::Fn | DefKind::AssocFn | DefKind::AssocTy | DefKind::AssocConst => {
+            let defined_opaques = match kind {
+                DefKind::Fn => {
+                    OpaqueTypeCollector::collect(tcx, item, tcx.fn_sig(item).subst_identity())
+                }
+                DefKind::AssocFn => {
+                    OpaqueTypeCollector::collect(tcx, item, tcx.fn_sig(item).subst_identity())
+                }
+                DefKind::AssocTy | DefKind::AssocConst => OpaqueTypeCollector::collect(
+                    tcx,
+                    item,
+                    ty::Binder::dummy(tcx.type_of(item).subst_identity()),
+                ),
+                _ => unreachable!(),
+            };
+            tcx.arena.alloc_from_iter(defined_opaques)
+        }
+        DefKind::Mod
+        | DefKind::Struct
+        | DefKind::Union
+        | DefKind::Enum
+        | DefKind::Variant
+        | DefKind::Trait
+        | DefKind::TyAlias
+        | DefKind::ForeignTy
+        | DefKind::TraitAlias
+        | DefKind::TyParam
+        | DefKind::Const
+        | DefKind::ConstParam
+        | DefKind::Static(_)
+        | DefKind::Ctor(_, _)
+        | DefKind::Macro(_)
+        | DefKind::ExternCrate
+        | DefKind::Use
+        | DefKind::ForeignMod
+        | DefKind::AnonConst
+        | DefKind::InlineConst
+        | DefKind::OpaqueTy
+        | DefKind::ImplTraitPlaceholder
+        | DefKind::Field
+        | DefKind::LifetimeParam
+        | DefKind::GlobalAsm
+        | DefKind::Impl { .. }
+        | DefKind::Closure
+        | DefKind::Generator => &[],
+    }
+}
+
+pub(super) fn provide(providers: &mut Providers) {
+    *providers = Providers { opaque_types_defined_by, ..*providers };
+}
diff --git a/compiler/rustc_ty_utils/src/representability.rs b/compiler/rustc_ty_utils/src/representability.rs
index 26d6deab883..0b5e27c2c74 100644
--- a/compiler/rustc_ty_utils/src/representability.rs
+++ b/compiler/rustc_ty_utils/src/representability.rs
@@ -2,7 +2,7 @@
 
 use rustc_hir::def::DefKind;
 use rustc_index::bit_set::BitSet;
-use rustc_middle::ty::query::Providers;
+use rustc_middle::query::Providers;
 use rustc_middle::ty::{self, Representability, Ty, TyCtxt};
 use rustc_span::def_id::LocalDefId;
 
diff --git a/compiler/rustc_ty_utils/src/structural_match.rs b/compiler/rustc_ty_utils/src/structural_match.rs
index 9cb0fc10594..215acbe2c8f 100644
--- a/compiler/rustc_ty_utils/src/structural_match.rs
+++ b/compiler/rustc_ty_utils/src/structural_match.rs
@@ -1,5 +1,5 @@
 use rustc_hir::lang_items::LangItem;
-use rustc_middle::ty::query::Providers;
+use rustc_middle::query::Providers;
 use rustc_middle::ty::{self, Ty, TyCtxt};
 
 use rustc_infer::infer::TyCtxtInferExt;
diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs
index 78efcce572d..65dc3c39c6a 100644
--- a/compiler/rustc_ty_utils/src/ty.rs
+++ b/compiler/rustc_ty_utils/src/ty.rs
@@ -2,6 +2,7 @@ use rustc_data_structures::fx::{FxHashSet, FxIndexSet};
 use rustc_hir as hir;
 use rustc_hir::def::DefKind;
 use rustc_index::bit_set::BitSet;
+use rustc_middle::query::Providers;
 use rustc_middle::ty::{
     self, Binder, EarlyBinder, ImplTraitInTraitData, Predicate, PredicateKind, ToPredicate, Ty,
     TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor,
@@ -566,8 +567,8 @@ fn unsizing_params_for_adt<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> BitSet<u32
     unsizing_params
 }
 
-pub fn provide(providers: &mut ty::query::Providers) {
-    *providers = ty::query::Providers {
+pub fn provide(providers: &mut Providers) {
+    *providers = Providers {
         asyncness,
         adt_sized_constraint,
         param_env,
diff --git a/compiler/rustc_type_ir/src/structural_impls.rs b/compiler/rustc_type_ir/src/structural_impls.rs
index c9675f93f95..45a2e9023c9 100644
--- a/compiler/rustc_type_ir/src/structural_impls.rs
+++ b/compiler/rustc_type_ir/src/structural_impls.rs
@@ -21,6 +21,7 @@ TrivialTypeTraversalImpls! {
     (),
     bool,
     usize,
+    u8,
     u16,
     u32,
     u64,
diff --git a/library/alloc/src/collections/btree/map.rs b/library/alloc/src/collections/btree/map.rs
index 2daef82d6f1..1f8a1ecba6e 100644
--- a/library/alloc/src/collections/btree/map.rs
+++ b/library/alloc/src/collections/btree/map.rs
@@ -3021,7 +3021,7 @@ impl<'a, K, V, A> CursorMut<'a, K, V, A> {
         })
     }
 
-    /// Returns a mutable reference to the of the element that the cursor is
+    /// Returns a mutable reference to the key of the element that the cursor is
     /// currently pointing to.
     ///
     /// This returns `None` if the cursor is currently pointing to the
diff --git a/library/alloc/src/string.rs b/library/alloc/src/string.rs
index 088139a6907..498fbd93288 100644
--- a/library/alloc/src/string.rs
+++ b/library/alloc/src/string.rs
@@ -2623,6 +2623,15 @@ impl ToString for String {
     }
 }
 
+#[cfg(not(no_global_oom_handling))]
+#[stable(feature = "fmt_arguments_to_string_specialization", since = "CURRENT_RUSTC_VERSION")]
+impl ToString for fmt::Arguments<'_> {
+    #[inline]
+    fn to_string(&self) -> String {
+        crate::fmt::format(*self)
+    }
+}
+
 #[stable(feature = "rust1", since = "1.0.0")]
 impl AsRef<str> for String {
     #[inline]
diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs
index 7347980abbc..bfdb7a92bef 100644
--- a/library/alloc/src/sync.rs
+++ b/library/alloc/src/sync.rs
@@ -502,6 +502,7 @@ impl<T> Arc<T> {
     /// assert_eq!(*five, 5)
     /// ```
     #[cfg(not(no_global_oom_handling))]
+    #[inline]
     #[unstable(feature = "new_uninit", issue = "63291")]
     #[must_use]
     pub fn new_uninit() -> Arc<mem::MaybeUninit<T>> {
@@ -535,6 +536,7 @@ impl<T> Arc<T> {
     ///
     /// [zeroed]: mem::MaybeUninit::zeroed
     #[cfg(not(no_global_oom_handling))]
+    #[inline]
     #[unstable(feature = "new_uninit", issue = "63291")]
     #[must_use]
     pub fn new_zeroed() -> Arc<mem::MaybeUninit<T>> {
@@ -844,6 +846,7 @@ impl<T> Arc<[T]> {
     /// assert_eq!(*values, [1, 2, 3])
     /// ```
     #[cfg(not(no_global_oom_handling))]
+    #[inline]
     #[unstable(feature = "new_uninit", issue = "63291")]
     #[must_use]
     pub fn new_uninit_slice(len: usize) -> Arc<[mem::MaybeUninit<T>]> {
@@ -871,6 +874,7 @@ impl<T> Arc<[T]> {
     ///
     /// [zeroed]: mem::MaybeUninit::zeroed
     #[cfg(not(no_global_oom_handling))]
+    #[inline]
     #[unstable(feature = "new_uninit", issue = "63291")]
     #[must_use]
     pub fn new_zeroed_slice(len: usize) -> Arc<[mem::MaybeUninit<T>]> {
@@ -1300,10 +1304,10 @@ impl<T: ?Sized> Arc<T> {
         mem_to_arcinner: impl FnOnce(*mut u8) -> *mut ArcInner<T>,
     ) -> *mut ArcInner<T> {
         let layout = arcinner_layout_for_value_layout(value_layout);
-        unsafe {
-            Arc::try_allocate_for_layout(value_layout, allocate, mem_to_arcinner)
-                .unwrap_or_else(|_| handle_alloc_error(layout))
-        }
+
+        let ptr = allocate(layout).unwrap_or_else(|_| handle_alloc_error(layout));
+
+        unsafe { Self::initialize_arcinner(ptr, layout, mem_to_arcinner) }
     }
 
     /// Allocates an `ArcInner<T>` with sufficient space for
@@ -1321,7 +1325,16 @@ impl<T: ?Sized> Arc<T> {
 
         let ptr = allocate(layout)?;
 
-        // Initialize the ArcInner
+        let inner = unsafe { Self::initialize_arcinner(ptr, layout, mem_to_arcinner) };
+
+        Ok(inner)
+    }
+
+    unsafe fn initialize_arcinner(
+        ptr: NonNull<[u8]>,
+        layout: Layout,
+        mem_to_arcinner: impl FnOnce(*mut u8) -> *mut ArcInner<T>,
+    ) -> *mut ArcInner<T> {
         let inner = mem_to_arcinner(ptr.as_non_null_ptr().as_ptr());
         debug_assert_eq!(unsafe { Layout::for_value(&*inner) }, layout);
 
@@ -1330,7 +1343,7 @@ impl<T: ?Sized> Arc<T> {
             ptr::write(&mut (*inner).weak, atomic::AtomicUsize::new(1));
         }
 
-        Ok(inner)
+        inner
     }
 
     /// Allocates an `ArcInner<T>` with sufficient space for an unsized inner value.
diff --git a/library/alloc/src/vec/in_place_collect.rs b/library/alloc/src/vec/in_place_collect.rs
index 2f1ee8b0353..5ecd0479971 100644
--- a/library/alloc/src/vec/in_place_collect.rs
+++ b/library/alloc/src/vec/in_place_collect.rs
@@ -178,7 +178,8 @@ where
             )
         };
 
-        let len = SpecInPlaceCollect::collect_in_place(&mut iterator, dst_buf, dst_end);
+        // SAFETY: `dst_buf` and `dst_end` are the start and end of the buffer.
+        let len = unsafe { SpecInPlaceCollect::collect_in_place(&mut iterator, dst_buf, dst_end) };
 
         let src = unsafe { iterator.as_inner().as_into_iter() };
         // check if SourceIter contract was upheld
@@ -239,7 +240,7 @@ trait SpecInPlaceCollect<T, I>: Iterator<Item = T> {
     /// `Iterator::__iterator_get_unchecked` calls with a `TrustedRandomAccessNoCoerce` bound
     /// on `I` which means the caller of this method must take the safety conditions
     /// of that trait into consideration.
-    fn collect_in_place(&mut self, dst: *mut T, end: *const T) -> usize;
+    unsafe fn collect_in_place(&mut self, dst: *mut T, end: *const T) -> usize;
 }
 
 impl<T, I> SpecInPlaceCollect<T, I> for I
@@ -247,7 +248,7 @@ where
     I: Iterator<Item = T>,
 {
     #[inline]
-    default fn collect_in_place(&mut self, dst_buf: *mut T, end: *const T) -> usize {
+    default unsafe fn collect_in_place(&mut self, dst_buf: *mut T, end: *const T) -> usize {
         // use try-fold since
         // - it vectorizes better for some iterator adapters
         // - unlike most internal iteration methods, it only takes a &mut self
@@ -265,7 +266,7 @@ where
     I: Iterator<Item = T> + TrustedRandomAccessNoCoerce,
 {
     #[inline]
-    fn collect_in_place(&mut self, dst_buf: *mut T, end: *const T) -> usize {
+    unsafe fn collect_in_place(&mut self, dst_buf: *mut T, end: *const T) -> usize {
         let len = self.size();
         let mut drop_guard = InPlaceDrop { inner: dst_buf, dst: dst_buf };
         for i in 0..len {
diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs
index 97da6f06b70..82f30a26d41 100644
--- a/library/alloc/src/vec/mod.rs
+++ b/library/alloc/src/vec/mod.rs
@@ -646,14 +646,14 @@ impl<T, A: Allocator> Vec<T, A> {
     ///
     /// // The vector contains no items, even though it has capacity for more
     /// assert_eq!(vec.len(), 0);
-    /// assert_eq!(vec.capacity(), 10);
+    /// assert!(vec.capacity() >= 10);
     ///
     /// // These are all done without reallocating...
     /// for i in 0..10 {
     ///     vec.push(i);
     /// }
     /// assert_eq!(vec.len(), 10);
-    /// assert_eq!(vec.capacity(), 10);
+    /// assert!(vec.capacity() >= 10);
     ///
     /// // ...but this may make the vector reallocate
     /// vec.push(11);
@@ -877,7 +877,7 @@ impl<T, A: Allocator> Vec<T, A> {
     /// ```
     /// let mut vec: Vec<i32> = Vec::with_capacity(10);
     /// vec.push(42);
-    /// assert_eq!(vec.capacity(), 10);
+    /// assert!(vec.capacity() >= 10);
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -1028,7 +1028,7 @@ impl<T, A: Allocator> Vec<T, A> {
     /// ```
     /// let mut vec = Vec::with_capacity(10);
     /// vec.extend([1, 2, 3]);
-    /// assert_eq!(vec.capacity(), 10);
+    /// assert!(vec.capacity() >= 10);
     /// vec.shrink_to_fit();
     /// assert!(vec.capacity() >= 3);
     /// ```
@@ -1055,7 +1055,7 @@ impl<T, A: Allocator> Vec<T, A> {
     /// ```
     /// let mut vec = Vec::with_capacity(10);
     /// vec.extend([1, 2, 3]);
-    /// assert_eq!(vec.capacity(), 10);
+    /// assert!(vec.capacity() >= 10);
     /// vec.shrink_to(4);
     /// assert!(vec.capacity() >= 4);
     /// vec.shrink_to(0);
@@ -1090,7 +1090,7 @@ impl<T, A: Allocator> Vec<T, A> {
     /// let mut vec = Vec::with_capacity(10);
     /// vec.extend([1, 2, 3]);
     ///
-    /// assert_eq!(vec.capacity(), 10);
+    /// assert!(vec.capacity() >= 10);
     /// let slice = vec.into_boxed_slice();
     /// assert_eq!(slice.into_vec().capacity(), 3);
     /// ```
diff --git a/library/core/benches/fmt.rs b/library/core/benches/fmt.rs
index ff726ff7559..d1cdb12e50f 100644
--- a/library/core/benches/fmt.rs
+++ b/library/core/benches/fmt.rs
@@ -1,13 +1,13 @@
 use std::fmt::{self, Write as FmtWrite};
 use std::io::{self, Write as IoWrite};
-use test::Bencher;
+use test::{black_box, Bencher};
 
 #[bench]
 fn write_vec_value(bh: &mut Bencher) {
     bh.iter(|| {
         let mut mem = Vec::new();
         for _ in 0..1000 {
-            mem.write_all("abc".as_bytes()).unwrap();
+            mem.write_all(black_box("abc").as_bytes()).unwrap();
         }
     });
 }
@@ -18,7 +18,7 @@ fn write_vec_ref(bh: &mut Bencher) {
         let mut mem = Vec::new();
         let wr = &mut mem as &mut dyn io::Write;
         for _ in 0..1000 {
-            wr.write_all("abc".as_bytes()).unwrap();
+            wr.write_all(black_box("abc").as_bytes()).unwrap();
         }
     });
 }
@@ -29,7 +29,7 @@ fn write_vec_macro1(bh: &mut Bencher) {
         let mut mem = Vec::new();
         let wr = &mut mem as &mut dyn io::Write;
         for _ in 0..1000 {
-            write!(wr, "abc").unwrap();
+            write!(wr, "{}", black_box("abc")).unwrap();
         }
     });
 }
@@ -40,7 +40,7 @@ fn write_vec_macro2(bh: &mut Bencher) {
         let mut mem = Vec::new();
         let wr = &mut mem as &mut dyn io::Write;
         for _ in 0..1000 {
-            write!(wr, "{}", "abc").unwrap();
+            write!(wr, "{}", black_box("abc")).unwrap();
         }
     });
 }
@@ -51,7 +51,7 @@ fn write_vec_macro_debug(bh: &mut Bencher) {
         let mut mem = Vec::new();
         let wr = &mut mem as &mut dyn io::Write;
         for _ in 0..1000 {
-            write!(wr, "{:?}", "☃").unwrap();
+            write!(wr, "{:?}", black_box("☃")).unwrap();
         }
     });
 }
@@ -61,7 +61,7 @@ fn write_str_value(bh: &mut Bencher) {
     bh.iter(|| {
         let mut mem = String::new();
         for _ in 0..1000 {
-            mem.write_str("abc").unwrap();
+            mem.write_str(black_box("abc")).unwrap();
         }
     });
 }
@@ -72,7 +72,7 @@ fn write_str_ref(bh: &mut Bencher) {
         let mut mem = String::new();
         let wr = &mut mem as &mut dyn fmt::Write;
         for _ in 0..1000 {
-            wr.write_str("abc").unwrap();
+            wr.write_str(black_box("abc")).unwrap();
         }
     });
 }
@@ -82,7 +82,7 @@ fn write_str_macro1(bh: &mut Bencher) {
     bh.iter(|| {
         let mut mem = String::new();
         for _ in 0..1000 {
-            write!(mem, "abc").unwrap();
+            write!(mem, "{}", black_box("abc")).unwrap();
         }
     });
 }
@@ -93,7 +93,7 @@ fn write_str_macro2(bh: &mut Bencher) {
         let mut mem = String::new();
         let wr = &mut mem as &mut dyn fmt::Write;
         for _ in 0..1000 {
-            write!(wr, "{}", "abc").unwrap();
+            write!(wr, "{}", black_box("abc")).unwrap();
         }
     });
 }
@@ -104,7 +104,7 @@ fn write_str_macro_debug(bh: &mut Bencher) {
         let mut mem = String::new();
         let wr = &mut mem as &mut dyn fmt::Write;
         for _ in 0..1000 {
-            write!(wr, "{:?}", "☃").unwrap();
+            write!(wr, "{:?}", black_box("☃")).unwrap();
         }
     });
 }
@@ -115,7 +115,7 @@ fn write_str_macro_debug_ascii(bh: &mut Bencher) {
         let mut mem = String::new();
         let wr = &mut mem as &mut dyn fmt::Write;
         for _ in 0..1000 {
-            write!(wr, "{:?}", "Hello, World!").unwrap();
+            write!(wr, "{:?}", black_box("Hello, World!")).unwrap();
         }
     });
 }
diff --git a/library/core/benches/iter.rs b/library/core/benches/iter.rs
index 9193c79bee8..60ef83223d1 100644
--- a/library/core/benches/iter.rs
+++ b/library/core/benches/iter.rs
@@ -404,7 +404,7 @@ fn bench_trusted_random_access_adapters(b: &mut Bencher) {
 
 /// Exercises the iter::Copied specialization for slice::Iter
 #[bench]
-fn bench_copied_chunks(b: &mut Bencher) {
+fn bench_next_chunk_copied(b: &mut Bencher) {
     let v = vec![1u8; 1024];
 
     b.iter(|| {
@@ -421,7 +421,7 @@ fn bench_copied_chunks(b: &mut Bencher) {
 
 /// Exercises the TrustedRandomAccess specialization in ArrayChunks
 #[bench]
-fn bench_trusted_random_access_chunks(b: &mut Bencher) {
+fn bench_next_chunk_trusted_random_access(b: &mut Bencher) {
     let v = vec![1u8; 1024];
 
     b.iter(|| {
@@ -437,3 +437,45 @@ fn bench_trusted_random_access_chunks(b: &mut Bencher) {
             .sum::<Wrapping<u64>>()
     })
 }
+
+#[bench]
+fn bench_next_chunk_filter_even(b: &mut Bencher) {
+    let a = (0..1024).next_chunk::<1024>().unwrap();
+
+    b.iter(|| black_box(&a).iter().filter(|&&i| i % 2 == 0).next_chunk::<32>())
+}
+
+#[bench]
+fn bench_next_chunk_filter_predictably_true(b: &mut Bencher) {
+    let a = (0..1024).next_chunk::<1024>().unwrap();
+
+    b.iter(|| black_box(&a).iter().filter(|&&i| i < 100).next_chunk::<32>())
+}
+
+#[bench]
+fn bench_next_chunk_filter_mostly_false(b: &mut Bencher) {
+    let a = (0..1024).next_chunk::<1024>().unwrap();
+
+    b.iter(|| black_box(&a).iter().filter(|&&i| i > 900).next_chunk::<32>())
+}
+
+#[bench]
+fn bench_next_chunk_filter_map_even(b: &mut Bencher) {
+    let a = (0..1024).next_chunk::<1024>().unwrap();
+
+    b.iter(|| black_box(&a).iter().filter_map(|&i| (i % 2 == 0).then(|| i)).next_chunk::<32>())
+}
+
+#[bench]
+fn bench_next_chunk_filter_map_predictably_true(b: &mut Bencher) {
+    let a = (0..1024).next_chunk::<1024>().unwrap();
+
+    b.iter(|| black_box(&a).iter().filter_map(|&i| (i < 100).then(|| i)).next_chunk::<32>())
+}
+
+#[bench]
+fn bench_next_chunk_filter_map_mostly_false(b: &mut Bencher) {
+    let a = (0..1024).next_chunk::<1024>().unwrap();
+
+    b.iter(|| black_box(&a).iter().filter_map(|&i| (i > 900).then(|| i)).next_chunk::<32>())
+}
diff --git a/library/core/benches/num/dec2flt/mod.rs b/library/core/benches/num/dec2flt/mod.rs
index 305baa68729..fb4a786b27e 100644
--- a/library/core/benches/num/dec2flt/mod.rs
+++ b/library/core/benches/num/dec2flt/mod.rs
@@ -1,57 +1,57 @@
-use test::Bencher;
+use test::{black_box, Bencher};
 
 #[bench]
 fn bench_0(b: &mut Bencher) {
-    b.iter(|| "0.0".parse::<f64>());
+    b.iter(|| black_box("0.0").parse::<f64>());
 }
 
 #[bench]
 fn bench_42(b: &mut Bencher) {
-    b.iter(|| "42".parse::<f64>());
+    b.iter(|| black_box("42").parse::<f64>());
 }
 
 #[bench]
 fn bench_huge_int(b: &mut Bencher) {
     // 2^128 - 1
-    b.iter(|| "170141183460469231731687303715884105727".parse::<f64>());
+    b.iter(|| black_box("170141183460469231731687303715884105727").parse::<f64>());
 }
 
 #[bench]
 fn bench_short_decimal(b: &mut Bencher) {
-    b.iter(|| "1234.5678".parse::<f64>());
+    b.iter(|| black_box("1234.5678").parse::<f64>());
 }
 
 #[bench]
 fn bench_pi_long(b: &mut Bencher) {
-    b.iter(|| "3.14159265358979323846264338327950288".parse::<f64>());
+    b.iter(|| black_box("3.14159265358979323846264338327950288").parse::<f64>());
 }
 
 #[bench]
 fn bench_pi_short(b: &mut Bencher) {
-    b.iter(|| "3.141592653589793".parse::<f64>())
+    b.iter(|| black_box("3.141592653589793").parse::<f64>())
 }
 
 #[bench]
 fn bench_1e150(b: &mut Bencher) {
-    b.iter(|| "1e150".parse::<f64>());
+    b.iter(|| black_box("1e150").parse::<f64>());
 }
 
 #[bench]
 fn bench_long_decimal_and_exp(b: &mut Bencher) {
-    b.iter(|| "727501488517303786137132964064381141071e-123".parse::<f64>());
+    b.iter(|| black_box("727501488517303786137132964064381141071e-123").parse::<f64>());
 }
 
 #[bench]
 fn bench_min_subnormal(b: &mut Bencher) {
-    b.iter(|| "5e-324".parse::<f64>());
+    b.iter(|| black_box("5e-324").parse::<f64>());
 }
 
 #[bench]
 fn bench_min_normal(b: &mut Bencher) {
-    b.iter(|| "2.2250738585072014e-308".parse::<f64>());
+    b.iter(|| black_box("2.2250738585072014e-308").parse::<f64>());
 }
 
 #[bench]
 fn bench_max(b: &mut Bencher) {
-    b.iter(|| "1.7976931348623157e308".parse::<f64>());
+    b.iter(|| black_box("1.7976931348623157e308").parse::<f64>());
 }
diff --git a/library/core/benches/num/flt2dec/mod.rs b/library/core/benches/num/flt2dec/mod.rs
index 32fd5e626bc..1a330ef5fe5 100644
--- a/library/core/benches/num/flt2dec/mod.rs
+++ b/library/core/benches/num/flt2dec/mod.rs
@@ -7,7 +7,7 @@ use core::num::flt2dec::MAX_SIG_DIGITS;
 use core::num::flt2dec::{decode, DecodableFloat, Decoded, FullDecoded};
 use std::io::Write;
 use std::vec::Vec;
-use test::Bencher;
+use test::{black_box, Bencher};
 
 pub fn decode_finite<T: DecodableFloat>(v: T) -> Decoded {
     match decode(v).1 {
@@ -22,7 +22,7 @@ fn bench_small_shortest(b: &mut Bencher) {
 
     b.iter(|| {
         buf.clear();
-        write!(&mut buf, "{}", 3.1415926f64).unwrap()
+        write!(black_box(&mut buf), "{}", black_box(3.1415926f64)).unwrap()
     });
 }
 
@@ -32,6 +32,6 @@ fn bench_big_shortest(b: &mut Bencher) {
 
     b.iter(|| {
         buf.clear();
-        write!(&mut buf, "{}", f64::MAX).unwrap()
+        write!(black_box(&mut buf), "{}", black_box(f64::MAX)).unwrap()
     });
 }
diff --git a/library/core/benches/num/mod.rs b/library/core/benches/num/mod.rs
index 2f9cad2725d..b97014d9bf9 100644
--- a/library/core/benches/num/mod.rs
+++ b/library/core/benches/num/mod.rs
@@ -3,7 +3,7 @@ mod flt2dec;
 mod int_log;
 
 use std::str::FromStr;
-use test::Bencher;
+use test::{black_box, Bencher};
 
 const ASCII_NUMBERS: [&str; 19] = [
     "0",
@@ -36,7 +36,7 @@ macro_rules! from_str_bench {
                     .iter()
                     .cycle()
                     .take(5_000)
-                    .filter_map(|s| <$t>::from_str(s).ok())
+                    .filter_map(|s| <$t>::from_str(black_box(s)).ok())
                     .max()
             })
         }
@@ -52,7 +52,7 @@ macro_rules! from_str_radix_bench {
                     .iter()
                     .cycle()
                     .take(5_000)
-                    .filter_map(|s| <$t>::from_str_radix(s, $radix).ok())
+                    .filter_map(|s| <$t>::from_str_radix(black_box(s), $radix).ok())
                     .max()
             })
         }
diff --git a/library/core/src/any.rs b/library/core/src/any.rs
index bb93ea509d8..d1c1ae6526b 100644
--- a/library/core/src/any.rs
+++ b/library/core/src/any.rs
@@ -866,7 +866,7 @@ where
 ///
 /// A data provider provides values by calling this type's provide methods.
 #[unstable(feature = "provide_any", issue = "96024")]
-#[repr(transparent)]
+#[cfg_attr(not(doc), repr(transparent))] // work around https://github.com/rust-lang/rust/issues/90435
 pub struct Demand<'a>(dyn Erased<'a> + 'a);
 
 impl<'a> Demand<'a> {
diff --git a/library/core/src/ascii.rs b/library/core/src/ascii.rs
index 7fd14a7e1ea..ef8e4d098ed 100644
--- a/library/core/src/ascii.rs
+++ b/library/core/src/ascii.rs
@@ -91,7 +91,7 @@ pub struct EscapeDefault(escape::EscapeIterInner<4>);
 /// ```
 #[stable(feature = "rust1", since = "1.0.0")]
 pub fn escape_default(c: u8) -> EscapeDefault {
-    let mut data = [0; 4];
+    let mut data = [Char::Null; 4];
     let range = escape::escape_ascii_into(&mut data, c);
     EscapeDefault(escape::EscapeIterInner::new(data, range))
 }
diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs
index a96dfafd9c4..744767aae44 100644
--- a/library/core/src/cell.rs
+++ b/library/core/src/cell.rs
@@ -2030,6 +2030,27 @@ impl<T> UnsafeCell<T> {
 }
 
 impl<T: ?Sized> UnsafeCell<T> {
+    /// Converts from `&mut T` to `&mut UnsafeCell<T>`.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// # #![feature(unsafe_cell_from_mut)]
+    /// use std::cell::UnsafeCell;
+    ///
+    /// let mut val = 42;
+    /// let uc = UnsafeCell::from_mut(&mut val);
+    ///
+    /// *uc.get_mut() -= 1;
+    /// assert_eq!(*uc.get_mut(), 41);
+    /// ```
+    #[inline(always)]
+    #[unstable(feature = "unsafe_cell_from_mut", issue = "111645")]
+    pub const fn from_mut(value: &mut T) -> &mut UnsafeCell<T> {
+        // SAFETY: `UnsafeCell<T>` has the same memory layout as `T` due to #[repr(transparent)].
+        unsafe { &mut *(value as *mut T as *mut UnsafeCell<T>) }
+    }
+
     /// Gets a mutable pointer to the wrapped value.
     ///
     /// This can be cast to a pointer of any kind.
@@ -2100,6 +2121,8 @@ impl<T: ?Sized> UnsafeCell<T> {
     ///
     /// let m = MaybeUninit::<UnsafeCell<i32>>::uninit();
     /// unsafe { UnsafeCell::raw_get(m.as_ptr()).write(5); }
+    /// // avoid below which references to uninitialized data
+    /// // unsafe { UnsafeCell::get(&*m.as_ptr()).write(5); }
     /// let uc = unsafe { m.assume_init() };
     ///
     /// assert_eq!(uc.into_inner(), 5);
diff --git a/library/core/src/char/methods.rs b/library/core/src/char/methods.rs
index 1dfa9c34db1..515b8d20ead 100644
--- a/library/core/src/char/methods.rs
+++ b/library/core/src/char/methods.rs
@@ -392,13 +392,13 @@ impl char {
     #[inline]
     pub(crate) fn escape_debug_ext(self, args: EscapeDebugExtArgs) -> EscapeDebug {
         match self {
-            '\0' => EscapeDebug::backslash(b'0'),
-            '\t' => EscapeDebug::backslash(b't'),
-            '\r' => EscapeDebug::backslash(b'r'),
-            '\n' => EscapeDebug::backslash(b'n'),
-            '\\' => EscapeDebug::backslash(b'\\'),
-            '"' if args.escape_double_quote => EscapeDebug::backslash(b'"'),
-            '\'' if args.escape_single_quote => EscapeDebug::backslash(b'\''),
+            '\0' => EscapeDebug::backslash(ascii::Char::Digit0),
+            '\t' => EscapeDebug::backslash(ascii::Char::SmallT),
+            '\r' => EscapeDebug::backslash(ascii::Char::SmallR),
+            '\n' => EscapeDebug::backslash(ascii::Char::SmallN),
+            '\\' => EscapeDebug::backslash(ascii::Char::ReverseSolidus),
+            '\"' if args.escape_double_quote => EscapeDebug::backslash(ascii::Char::QuotationMark),
+            '\'' if args.escape_single_quote => EscapeDebug::backslash(ascii::Char::Apostrophe),
             _ if args.escape_grapheme_extended && self.is_grapheme_extended() => {
                 EscapeDebug::from_unicode(self.escape_unicode())
             }
@@ -503,11 +503,11 @@ impl char {
     #[inline]
     pub fn escape_default(self) -> EscapeDefault {
         match self {
-            '\t' => EscapeDefault::backslash(b't'),
-            '\r' => EscapeDefault::backslash(b'r'),
-            '\n' => EscapeDefault::backslash(b'n'),
-            '\\' | '\'' | '"' => EscapeDefault::backslash(self as u8),
-            '\x20'..='\x7e' => EscapeDefault::printable(self as u8),
+            '\t' => EscapeDefault::backslash(ascii::Char::SmallT),
+            '\r' => EscapeDefault::backslash(ascii::Char::SmallR),
+            '\n' => EscapeDefault::backslash(ascii::Char::SmallN),
+            '\\' | '\'' | '"' => EscapeDefault::backslash(self.as_ascii().unwrap()),
+            '\x20'..='\x7e' => EscapeDefault::printable(self.as_ascii().unwrap()),
             _ => EscapeDefault::from_unicode(self.escape_unicode()),
         }
     }
diff --git a/library/core/src/char/mod.rs b/library/core/src/char/mod.rs
index e186db7052c..5c42912874c 100644
--- a/library/core/src/char/mod.rs
+++ b/library/core/src/char/mod.rs
@@ -38,6 +38,7 @@ pub use self::methods::encode_utf16_raw;
 #[unstable(feature = "char_internals", reason = "exposed only for libstd", issue = "none")]
 pub use self::methods::encode_utf8_raw;
 
+use crate::ascii;
 use crate::error::Error;
 use crate::escape;
 use crate::fmt::{self, Write};
@@ -152,7 +153,7 @@ pub struct EscapeUnicode(escape::EscapeIterInner<10>);
 
 impl EscapeUnicode {
     fn new(chr: char) -> Self {
-        let mut data = [0; 10];
+        let mut data = [ascii::Char::Null; 10];
         let range = escape::escape_unicode_into(&mut data, chr);
         Self(escape::EscapeIterInner::new(data, range))
     }
@@ -218,14 +219,14 @@ impl fmt::Display for EscapeUnicode {
 pub struct EscapeDefault(escape::EscapeIterInner<10>);
 
 impl EscapeDefault {
-    fn printable(chr: u8) -> Self {
-        let data = [chr, 0, 0, 0, 0, 0, 0, 0, 0, 0];
-        Self(escape::EscapeIterInner::new(data, 0..1))
+    fn printable(chr: ascii::Char) -> Self {
+        let data = [chr];
+        Self(escape::EscapeIterInner::from_array(data))
     }
 
-    fn backslash(chr: u8) -> Self {
-        let data = [b'\\', chr, 0, 0, 0, 0, 0, 0, 0, 0];
-        Self(escape::EscapeIterInner::new(data, 0..2))
+    fn backslash(chr: ascii::Char) -> Self {
+        let data = [ascii::Char::ReverseSolidus, chr];
+        Self(escape::EscapeIterInner::from_array(data))
     }
 
     fn from_unicode(esc: EscapeUnicode) -> Self {
@@ -307,9 +308,9 @@ impl EscapeDebug {
         Self(EscapeDebugInner::Char(chr))
     }
 
-    fn backslash(chr: u8) -> Self {
-        let data = [b'\\', chr, 0, 0, 0, 0, 0, 0, 0, 0];
-        let iter = escape::EscapeIterInner::new(data, 0..2);
+    fn backslash(chr: ascii::Char) -> Self {
+        let data = [ascii::Char::ReverseSolidus, chr];
+        let iter = escape::EscapeIterInner::from_array(data);
         Self(EscapeDebugInner::Bytes(iter))
     }
 
@@ -318,7 +319,7 @@ impl EscapeDebug {
     }
 
     fn clear(&mut self) {
-        let bytes = escape::EscapeIterInner::new([0; 10], 0..0);
+        let bytes = escape::EscapeIterInner::from_array([]);
         self.0 = EscapeDebugInner::Bytes(bytes);
     }
 }
diff --git a/library/core/src/escape.rs b/library/core/src/escape.rs
index 20ac3cf027f..3d471419bb8 100644
--- a/library/core/src/escape.rs
+++ b/library/core/src/escape.rs
@@ -1,34 +1,41 @@
 //! Helper code for character escaping.
 
+use crate::ascii;
 use crate::num::NonZeroUsize;
 use crate::ops::Range;
 
-const HEX_DIGITS: [u8; 16] = *b"0123456789abcdef";
+const HEX_DIGITS: [ascii::Char; 16] = *b"0123456789abcdef".as_ascii().unwrap();
 
 /// Escapes a byte into provided buffer; returns length of escaped
 /// representation.
-pub(crate) fn escape_ascii_into(output: &mut [u8; 4], byte: u8) -> Range<u8> {
+pub(crate) fn escape_ascii_into(output: &mut [ascii::Char; 4], byte: u8) -> Range<u8> {
+    #[inline]
+    fn backslash(a: ascii::Char) -> ([ascii::Char; 4], u8) {
+        ([ascii::Char::ReverseSolidus, a, ascii::Char::Null, ascii::Char::Null], 2)
+    }
+
     let (data, len) = match byte {
-        b'\t' => ([b'\\', b't', 0, 0], 2),
-        b'\r' => ([b'\\', b'r', 0, 0], 2),
-        b'\n' => ([b'\\', b'n', 0, 0], 2),
-        b'\\' => ([b'\\', b'\\', 0, 0], 2),
-        b'\'' => ([b'\\', b'\'', 0, 0], 2),
-        b'"' => ([b'\\', b'"', 0, 0], 2),
-        b'\x20'..=b'\x7e' => ([byte, 0, 0, 0], 1),
-        _ => {
+        b'\t' => backslash(ascii::Char::SmallT),
+        b'\r' => backslash(ascii::Char::SmallR),
+        b'\n' => backslash(ascii::Char::SmallN),
+        b'\\' => backslash(ascii::Char::ReverseSolidus),
+        b'\'' => backslash(ascii::Char::Apostrophe),
+        b'\"' => backslash(ascii::Char::QuotationMark),
+        _ => if let Some(a) = byte.as_ascii() && !byte.is_ascii_control() {
+            ([a, ascii::Char::Null, ascii::Char::Null, ascii::Char::Null], 1)
+        } else {
             let hi = HEX_DIGITS[usize::from(byte >> 4)];
             let lo = HEX_DIGITS[usize::from(byte & 0xf)];
-            ([b'\\', b'x', hi, lo], 4)
+            ([ascii::Char::ReverseSolidus, ascii::Char::SmallX, hi, lo], 4)
         }
     };
     *output = data;
-    0..(len as u8)
+    0..len
 }
 
 /// Escapes a character into provided buffer using `\u{NNNN}` representation.
-pub(crate) fn escape_unicode_into(output: &mut [u8; 10], ch: char) -> Range<u8> {
-    output[9] = b'}';
+pub(crate) fn escape_unicode_into(output: &mut [ascii::Char; 10], ch: char) -> Range<u8> {
+    output[9] = ascii::Char::RightCurlyBracket;
 
     let ch = ch as u32;
     output[3] = HEX_DIGITS[((ch >> 20) & 15) as usize];
@@ -41,7 +48,8 @@ pub(crate) fn escape_unicode_into(output: &mut [u8; 10], ch: char) -> Range<u8>
     // or-ing 1 ensures that for ch==0 the code computes that one digit should
     // be printed.
     let start = (ch | 1).leading_zeros() as usize / 4 - 2;
-    output[start..start + 3].copy_from_slice(b"\\u{");
+    const UNICODE_ESCAPE_PREFIX: &[ascii::Char; 3] = b"\\u{".as_ascii().unwrap();
+    output[start..][..3].copy_from_slice(UNICODE_ESCAPE_PREFIX);
 
     (start as u8)..10
 }
@@ -52,29 +60,34 @@ pub(crate) fn escape_unicode_into(output: &mut [u8; 10], ch: char) -> Range<u8>
 /// limited to u8 to reduce size of the structure.
 #[derive(Clone, Debug)]
 pub(crate) struct EscapeIterInner<const N: usize> {
-    // Invariant: data[alive] is all ASCII.
-    pub(crate) data: [u8; N],
+    // The element type ensures this is always ASCII, and thus also valid UTF-8.
+    pub(crate) data: [ascii::Char; N],
 
     // Invariant: alive.start <= alive.end <= N.
     pub(crate) alive: Range<u8>,
 }
 
 impl<const N: usize> EscapeIterInner<N> {
-    pub fn new(data: [u8; N], alive: Range<u8>) -> Self {
+    pub fn new(data: [ascii::Char; N], alive: Range<u8>) -> Self {
         const { assert!(N < 256) };
         debug_assert!(alive.start <= alive.end && usize::from(alive.end) <= N, "{alive:?}");
-        let this = Self { data, alive };
-        debug_assert!(this.as_bytes().is_ascii(), "Expected ASCII, got {:?}", this.as_bytes());
-        this
+        Self { data, alive }
+    }
+
+    pub fn from_array<const M: usize>(array: [ascii::Char; M]) -> Self {
+        const { assert!(M <= N) };
+
+        let mut data = [ascii::Char::Null; N];
+        data[..M].copy_from_slice(&array);
+        Self::new(data, 0..M as u8)
     }
 
-    fn as_bytes(&self) -> &[u8] {
+    pub fn as_ascii(&self) -> &[ascii::Char] {
         &self.data[usize::from(self.alive.start)..usize::from(self.alive.end)]
     }
 
     pub fn as_str(&self) -> &str {
-        // SAFETY: self.data[self.alive] is all ASCII characters.
-        unsafe { crate::str::from_utf8_unchecked(self.as_bytes()) }
+        self.as_ascii().as_str()
     }
 
     pub fn len(&self) -> usize {
@@ -82,11 +95,11 @@ impl<const N: usize> EscapeIterInner<N> {
     }
 
     pub fn next(&mut self) -> Option<u8> {
-        self.alive.next().map(|i| self.data[usize::from(i)])
+        self.alive.next().map(|i| self.data[usize::from(i)].as_u8())
     }
 
     pub fn next_back(&mut self) -> Option<u8> {
-        self.alive.next_back().map(|i| self.data[usize::from(i)])
+        self.alive.next_back().map(|i| self.data[usize::from(i)].as_u8())
     }
 
     pub fn advance_by(&mut self, n: usize) -> Result<(), NonZeroUsize> {
diff --git a/library/core/src/ffi/c_str.rs b/library/core/src/ffi/c_str.rs
index 07b11814f96..201bacb28c7 100644
--- a/library/core/src/ffi/c_str.rs
+++ b/library/core/src/ffi/c_str.rs
@@ -517,8 +517,6 @@ impl CStr {
     /// # Examples
     ///
     /// ```
-    /// #![feature(cstr_is_empty)]
-    ///
     /// use std::ffi::CStr;
     /// # use std::ffi::FromBytesWithNulError;
     ///
@@ -533,7 +531,8 @@ impl CStr {
     /// # }
     /// ```
     #[inline]
-    #[unstable(feature = "cstr_is_empty", issue = "102444")]
+    #[stable(feature = "cstr_is_empty", since = "CURRENT_RUSTC_VERSION")]
+    #[rustc_const_stable(feature = "cstr_is_empty", since = "CURRENT_RUSTC_VERSION")]
     pub const fn is_empty(&self) -> bool {
         // SAFETY: We know there is at least one byte; for empty strings it
         // is the NUL terminator.
diff --git a/library/core/src/ffi/mod.rs b/library/core/src/ffi/mod.rs
index b85894259f1..b73abbbaca7 100644
--- a/library/core/src/ffi/mod.rs
+++ b/library/core/src/ffi/mod.rs
@@ -203,7 +203,7 @@ mod c_long_definition {
 //     be UB.
 #[doc = include_str!("c_void.md")]
 #[cfg_attr(not(bootstrap), lang = "c_void")]
-#[repr(u8)]
+#[cfg_attr(not(doc), repr(u8))] // work around https://github.com/rust-lang/rust/issues/90435
 #[stable(feature = "core_c_void", since = "1.30.0")]
 pub enum c_void {
     #[unstable(
@@ -244,7 +244,7 @@ impl fmt::Debug for c_void {
     target_os = "uefi",
     windows,
 ))]
-#[repr(transparent)]
+#[cfg_attr(not(doc), repr(transparent))] // work around https://github.com/rust-lang/rust/issues/90435
 #[unstable(
     feature = "c_variadic",
     reason = "the `c_variadic` feature has not been properly tested on \
@@ -296,7 +296,7 @@ impl<'f> fmt::Debug for VaListImpl<'f> {
     not(target_os = "uefi"),
     not(windows),
 ))]
-#[repr(C)]
+#[cfg_attr(not(doc), repr(C))] // work around https://github.com/rust-lang/rust/issues/66401
 #[derive(Debug)]
 #[unstable(
     feature = "c_variadic",
@@ -316,7 +316,7 @@ pub struct VaListImpl<'f> {
 
 /// PowerPC ABI implementation of a `va_list`.
 #[cfg(all(target_arch = "powerpc", not(target_os = "uefi"), not(windows)))]
-#[repr(C)]
+#[cfg_attr(not(doc), repr(C))] // work around https://github.com/rust-lang/rust/issues/66401
 #[derive(Debug)]
 #[unstable(
     feature = "c_variadic",
@@ -336,7 +336,7 @@ pub struct VaListImpl<'f> {
 
 /// s390x ABI implementation of a `va_list`.
 #[cfg(target_arch = "s390x")]
-#[repr(C)]
+#[cfg_attr(not(doc), repr(C))] // work around https://github.com/rust-lang/rust/issues/66401
 #[derive(Debug)]
 #[unstable(
     feature = "c_variadic",
@@ -355,7 +355,7 @@ pub struct VaListImpl<'f> {
 
 /// x86_64 ABI implementation of a `va_list`.
 #[cfg(all(target_arch = "x86_64", not(target_os = "uefi"), not(windows)))]
-#[repr(C)]
+#[cfg_attr(not(doc), repr(C))] // work around https://github.com/rust-lang/rust/issues/66401
 #[derive(Debug)]
 #[unstable(
     feature = "c_variadic",
@@ -373,7 +373,7 @@ pub struct VaListImpl<'f> {
 }
 
 /// A wrapper for a `va_list`
-#[repr(transparent)]
+#[cfg_attr(not(doc), repr(transparent))] // work around https://github.com/rust-lang/rust/issues/90435
 #[derive(Debug)]
 #[unstable(
     feature = "c_variadic",
diff --git a/library/core/src/fmt/float.rs b/library/core/src/fmt/float.rs
index 89d5fac30d3..3bbf5d8770b 100644
--- a/library/core/src/fmt/float.rs
+++ b/library/core/src/fmt/float.rs
@@ -45,7 +45,8 @@ where
         &mut buf,
         &mut parts,
     );
-    fmt.pad_formatted_parts(&formatted)
+    // SAFETY: `to_exact_fixed_str` and `format_exact` produce only ASCII characters.
+    unsafe { fmt.pad_formatted_parts(&formatted) }
 }
 
 // Don't inline this so callers that call both this and the above won't wind
@@ -71,7 +72,8 @@ where
         &mut buf,
         &mut parts,
     );
-    fmt.pad_formatted_parts(&formatted)
+    // SAFETY: `to_shortest_str` and `format_shortest` produce only ASCII characters.
+    unsafe { fmt.pad_formatted_parts(&formatted) }
 }
 
 fn float_to_decimal_display<T>(fmt: &mut Formatter<'_>, num: &T) -> Result
@@ -116,7 +118,8 @@ where
         &mut buf,
         &mut parts,
     );
-    fmt.pad_formatted_parts(&formatted)
+    // SAFETY: `to_exact_exp_str` and `format_exact` produce only ASCII characters.
+    unsafe { fmt.pad_formatted_parts(&formatted) }
 }
 
 // Don't inline this so callers that call both this and the above won't wind
@@ -143,7 +146,8 @@ where
         &mut buf,
         &mut parts,
     );
-    fmt.pad_formatted_parts(&formatted)
+    // SAFETY: `to_shortest_exp_str` and `format_shortest` produce only ASCII characters.
+    unsafe { fmt.pad_formatted_parts(&formatted) }
 }
 
 // Common code of floating point LowerExp and UpperExp.
diff --git a/library/core/src/fmt/mod.rs b/library/core/src/fmt/mod.rs
index bac2f31878b..1786b309c5b 100644
--- a/library/core/src/fmt/mod.rs
+++ b/library/core/src/fmt/mod.rs
@@ -1415,7 +1415,11 @@ impl<'a> Formatter<'a> {
     /// Takes the formatted parts and applies the padding.
     /// Assumes that the caller already has rendered the parts with required precision,
     /// so that `self.precision` can be ignored.
-    fn pad_formatted_parts(&mut self, formatted: &numfmt::Formatted<'_>) -> Result {
+    ///
+    /// # Safety
+    ///
+    /// Any `numfmt::Part::Copy` parts in `formatted` must contain valid UTF-8.
+    unsafe fn pad_formatted_parts(&mut self, formatted: &numfmt::Formatted<'_>) -> Result {
         if let Some(mut width) = self.width {
             // for the sign-aware zero padding, we render the sign first and
             // behave as if we had no sign from the beginning.
@@ -1438,10 +1442,14 @@ impl<'a> Formatter<'a> {
             let len = formatted.len();
             let ret = if width <= len {
                 // no padding
-                self.write_formatted_parts(&formatted)
+                // SAFETY: Per the precondition.
+                unsafe { self.write_formatted_parts(&formatted) }
             } else {
                 let post_padding = self.padding(width - len, Alignment::Right)?;
-                self.write_formatted_parts(&formatted)?;
+                // SAFETY: Per the precondition.
+                unsafe {
+                    self.write_formatted_parts(&formatted)?;
+                }
                 post_padding.write(self)
             };
             self.fill = old_fill;
@@ -1449,20 +1457,20 @@ impl<'a> Formatter<'a> {
             ret
         } else {
             // this is the common case and we take a shortcut
-            self.write_formatted_parts(formatted)
+            // SAFETY: Per the precondition.
+            unsafe { self.write_formatted_parts(formatted) }
         }
     }
 
-    fn write_formatted_parts(&mut self, formatted: &numfmt::Formatted<'_>) -> Result {
-        fn write_bytes(buf: &mut dyn Write, s: &[u8]) -> Result {
+    /// # Safety
+    ///
+    /// Any `numfmt::Part::Copy` parts in `formatted` must contain valid UTF-8.
+    unsafe fn write_formatted_parts(&mut self, formatted: &numfmt::Formatted<'_>) -> Result {
+        unsafe fn write_bytes(buf: &mut dyn Write, s: &[u8]) -> Result {
             // SAFETY: This is used for `numfmt::Part::Num` and `numfmt::Part::Copy`.
             // It's safe to use for `numfmt::Part::Num` since every char `c` is between
-            // `b'0'` and `b'9'`, which means `s` is valid UTF-8.
-            // It's also probably safe in practice to use for `numfmt::Part::Copy(buf)`
-            // since `buf` should be plain ASCII, but it's possible for someone to pass
-            // in a bad value for `buf` into `numfmt::to_shortest_str` since it is a
-            // public function.
-            // FIXME: Determine whether this could result in UB.
+            // `b'0'` and `b'9'`, which means `s` is valid UTF-8. It's safe to use for
+            // `numfmt::Part::Copy` due to this function's precondition.
             buf.write_str(unsafe { str::from_utf8_unchecked(s) })
         }
 
@@ -1489,11 +1497,15 @@ impl<'a> Formatter<'a> {
                         *c = b'0' + (v % 10) as u8;
                         v /= 10;
                     }
-                    write_bytes(self.buf, &s[..len])?;
+                    // SAFETY: Per the precondition.
+                    unsafe {
+                        write_bytes(self.buf, &s[..len])?;
+                    }
                 }
-                numfmt::Part::Copy(buf) => {
+                // SAFETY: Per the precondition.
+                numfmt::Part::Copy(buf) => unsafe {
                     write_bytes(self.buf, buf)?;
-                }
+                },
             }
         }
         Ok(())
diff --git a/library/core/src/fmt/num.rs b/library/core/src/fmt/num.rs
index d8365ae9bf9..4f42f73ebba 100644
--- a/library/core/src/fmt/num.rs
+++ b/library/core/src/fmt/num.rs
@@ -52,8 +52,12 @@ impl_int! { i8 i16 i32 i64 i128 isize }
 impl_uint! { u8 u16 u32 u64 u128 usize }
 
 /// A type that represents a specific radix
+///
+/// # Safety
+///
+/// `digit` must return an ASCII character.
 #[doc(hidden)]
-trait GenericRadix: Sized {
+unsafe trait GenericRadix: Sized {
     /// The number of digits.
     const BASE: u8;
 
@@ -129,7 +133,7 @@ struct UpperHex;
 
 macro_rules! radix {
     ($T:ident, $base:expr, $prefix:expr, $($x:pat => $conv:expr),+) => {
-        impl GenericRadix for $T {
+        unsafe impl GenericRadix for $T {
             const BASE: u8 = $base;
             const PREFIX: &'static str = $prefix;
             fn digit(x: u8) -> u8 {
@@ -407,7 +411,7 @@ macro_rules! impl_Exp {
             let parts = &[
                 numfmt::Part::Copy(buf_slice),
                 numfmt::Part::Zero(added_precision),
-                numfmt::Part::Copy(exp_slice)
+                numfmt::Part::Copy(exp_slice),
             ];
             let sign = if !is_nonnegative {
                 "-"
@@ -416,8 +420,9 @@ macro_rules! impl_Exp {
             } else {
                 ""
             };
-            let formatted = numfmt::Formatted{sign, parts};
-            f.pad_formatted_parts(&formatted)
+            let formatted = numfmt::Formatted { sign, parts };
+            // SAFETY: `buf_slice` and `exp_slice` contain only ASCII characters.
+            unsafe { f.pad_formatted_parts(&formatted) }
         }
 
         $(
diff --git a/library/core/src/future/join.rs b/library/core/src/future/join.rs
index 35f0dea062e..3f35179ddc2 100644
--- a/library/core/src/future/join.rs
+++ b/library/core/src/future/join.rs
@@ -4,7 +4,7 @@ use crate::cell::UnsafeCell;
 use crate::future::{poll_fn, Future};
 use crate::mem;
 use crate::pin::Pin;
-use crate::task::{Context, Poll};
+use crate::task::{ready, Context, Poll};
 
 /// Polls multiple futures simultaneously, returning a tuple
 /// of all results once complete.
@@ -118,7 +118,7 @@ macro join_internal {
                             fut
                         })
                     };
-                    // Despite how tempting it may be to `let () = fut.poll(cx).ready()?;`
+                    // Despite how tempting it may be to `let () = ready!(fut.poll(cx));`
                     // doing so would defeat the point of `join!`: to start polling eagerly all
                     // of the futures, to allow parallelizing the waits.
                     done &= fut.poll(cx).is_ready();
@@ -180,7 +180,7 @@ impl<F: Future> Future for MaybeDone<F> {
             // Do not mix match ergonomics with unsafe.
             match *self.as_mut().get_unchecked_mut() {
                 MaybeDone::Future(ref mut f) => {
-                    let val = Pin::new_unchecked(f).poll(cx).ready()?;
+                    let val = ready!(Pin::new_unchecked(f).poll(cx));
                     self.set(Self::Done(val));
                 }
                 MaybeDone::Done(_) => {}
diff --git a/library/core/src/intrinsics/mir.rs b/library/core/src/intrinsics/mir.rs
index 19f8b944c1f..5944a0de1a4 100644
--- a/library/core/src/intrinsics/mir.rs
+++ b/library/core/src/intrinsics/mir.rs
@@ -228,7 +228,7 @@
 //!
 //!  - Operands implicitly convert to `Use` rvalues.
 //!  - `&`, `&mut`, `addr_of!`, and `addr_of_mut!` all work to create their associated rvalue.
-//!  - [`Discriminant`] and [`Len`] have associated functions.
+//!  - [`Discriminant`], [`Len`], and [`CopyForDeref`] have associated functions.
 //!  - Unary and binary operations use their normal Rust syntax - `a * b`, `!c`, etc.
 //!  - The binary operation `Offset` can be created via [`Offset`].
 //!  - Checked binary operations are represented by wrapping the associated binop in [`Checked`].
@@ -279,6 +279,7 @@ define!("mir_storage_dead", fn StorageDead<T>(local: T));
 define!("mir_deinit", fn Deinit<T>(place: T));
 define!("mir_checked", fn Checked<T>(binop: T) -> (T, bool));
 define!("mir_len", fn Len<T>(place: T) -> usize);
+define!("mir_copy_for_deref", fn CopyForDeref<T>(place: T) -> T);
 define!("mir_retag", fn Retag<T>(place: T));
 define!("mir_move", fn Move<T>(place: T) -> T);
 define!("mir_static", fn Static<T>(s: T) -> &'static T);
diff --git a/library/core/src/iter/adapters/filter.rs b/library/core/src/iter/adapters/filter.rs
index a0afaa326ad..723657b9e43 100644
--- a/library/core/src/iter/adapters/filter.rs
+++ b/library/core/src/iter/adapters/filter.rs
@@ -1,6 +1,9 @@
 use crate::fmt;
 use crate::iter::{adapters::SourceIter, FusedIterator, InPlaceIterable};
 use crate::ops::Try;
+use core::array;
+use core::mem::{ManuallyDrop, MaybeUninit};
+use core::ops::ControlFlow;
 
 /// An iterator that filters the elements of `iter` with `predicate`.
 ///
@@ -57,6 +60,58 @@ where
     }
 
     #[inline]
+    fn next_chunk<const N: usize>(
+        &mut self,
+    ) -> Result<[Self::Item; N], array::IntoIter<Self::Item, N>> {
+        let mut array: [MaybeUninit<Self::Item>; N] = MaybeUninit::uninit_array();
+
+        struct Guard<'a, T> {
+            array: &'a mut [MaybeUninit<T>],
+            initialized: usize,
+        }
+
+        impl<T> Drop for Guard<'_, T> {
+            #[inline]
+            fn drop(&mut self) {
+                if const { crate::mem::needs_drop::<T>() } {
+                    // SAFETY: self.initialized is always <= N, which also is the length of the array.
+                    unsafe {
+                        core::ptr::drop_in_place(MaybeUninit::slice_assume_init_mut(
+                            self.array.get_unchecked_mut(..self.initialized),
+                        ));
+                    }
+                }
+            }
+        }
+
+        let mut guard = Guard { array: &mut array, initialized: 0 };
+
+        let result = self.iter.try_for_each(|element| {
+            let idx = guard.initialized;
+            guard.initialized = idx + (self.predicate)(&element) as usize;
+
+            // SAFETY: Loop conditions ensure the index is in bounds.
+            unsafe { guard.array.get_unchecked_mut(idx) }.write(element);
+
+            if guard.initialized < N { ControlFlow::Continue(()) } else { ControlFlow::Break(()) }
+        });
+
+        let guard = ManuallyDrop::new(guard);
+
+        match result {
+            ControlFlow::Break(()) => {
+                // SAFETY: The loop above is only explicitly broken when the array has been fully initialized
+                Ok(unsafe { MaybeUninit::array_assume_init(array) })
+            }
+            ControlFlow::Continue(()) => {
+                let initialized = guard.initialized;
+                // SAFETY: The range is in bounds since the loop breaks when reaching N elements.
+                Err(unsafe { array::IntoIter::new_unchecked(array, 0..initialized) })
+            }
+        }
+    }
+
+    #[inline]
     fn size_hint(&self) -> (usize, Option<usize>) {
         let (_, upper) = self.iter.size_hint();
         (0, upper) // can't know a lower bound, due to the predicate
diff --git a/library/core/src/iter/adapters/filter_map.rs b/library/core/src/iter/adapters/filter_map.rs
index 6bdf53f7fc9..693479977db 100644
--- a/library/core/src/iter/adapters/filter_map.rs
+++ b/library/core/src/iter/adapters/filter_map.rs
@@ -1,6 +1,7 @@
-use crate::fmt;
 use crate::iter::{adapters::SourceIter, FusedIterator, InPlaceIterable};
+use crate::mem::{ManuallyDrop, MaybeUninit};
 use crate::ops::{ControlFlow, Try};
+use crate::{array, fmt};
 
 /// An iterator that uses `f` to both filter and map elements from `iter`.
 ///
@@ -62,6 +63,65 @@ where
     }
 
     #[inline]
+    fn next_chunk<const N: usize>(
+        &mut self,
+    ) -> Result<[Self::Item; N], array::IntoIter<Self::Item, N>> {
+        let mut array: [MaybeUninit<Self::Item>; N] = MaybeUninit::uninit_array();
+
+        struct Guard<'a, T> {
+            array: &'a mut [MaybeUninit<T>],
+            initialized: usize,
+        }
+
+        impl<T> Drop for Guard<'_, T> {
+            #[inline]
+            fn drop(&mut self) {
+                if const { crate::mem::needs_drop::<T>() } {
+                    // SAFETY: self.initialized is always <= N, which also is the length of the array.
+                    unsafe {
+                        core::ptr::drop_in_place(MaybeUninit::slice_assume_init_mut(
+                            self.array.get_unchecked_mut(..self.initialized),
+                        ));
+                    }
+                }
+            }
+        }
+
+        let mut guard = Guard { array: &mut array, initialized: 0 };
+
+        let result = self.iter.try_for_each(|element| {
+            let idx = guard.initialized;
+            let val = (self.f)(element);
+            guard.initialized = idx + val.is_some() as usize;
+
+            // SAFETY: Loop conditions ensure the index is in bounds.
+
+            unsafe {
+                let opt_payload_at = core::intrinsics::option_payload_ptr(&val);
+                let dst = guard.array.as_mut_ptr().add(idx);
+                crate::ptr::copy_nonoverlapping(opt_payload_at.cast(), dst, 1);
+                crate::mem::forget(val);
+            };
+
+            if guard.initialized < N { ControlFlow::Continue(()) } else { ControlFlow::Break(()) }
+        });
+
+        let guard = ManuallyDrop::new(guard);
+
+        match result {
+            ControlFlow::Break(()) => {
+                // SAFETY: The loop above is only explicitly broken when the array has been fully initialized
+                Ok(unsafe { MaybeUninit::array_assume_init(array) })
+            }
+            ControlFlow::Continue(()) => {
+                let initialized = guard.initialized;
+                // SAFETY: The range is in bounds since the loop breaks when reaching N elements.
+                Err(unsafe { array::IntoIter::new_unchecked(array, 0..initialized) })
+            }
+        }
+    }
+
+    #[inline]
     fn size_hint(&self) -> (usize, Option<usize>) {
         let (_, upper) = self.iter.size_hint();
         (0, upper) // can't know a lower bound, due to the predicate
diff --git a/library/core/src/iter/adapters/flatten.rs b/library/core/src/iter/adapters/flatten.rs
index 520ec9abcf0..2568aaf34f3 100644
--- a/library/core/src/iter/adapters/flatten.rs
+++ b/library/core/src/iter/adapters/flatten.rs
@@ -310,6 +310,7 @@ where
 /// Real logic of both `Flatten` and `FlatMap` which simply delegate to
 /// this type.
 #[derive(Clone, Debug)]
+#[unstable(feature = "trusted_len", issue = "37572")]
 struct FlattenCompat<I, U> {
     iter: Fuse<I>,
     frontiter: Option<U>,
@@ -463,6 +464,7 @@ where
     }
 }
 
+#[unstable(feature = "trusted_len", issue = "37572")]
 impl<I, U> Iterator for FlattenCompat<I, U>
 where
     I: Iterator<Item: IntoIterator<IntoIter = U, Item = U::Item>>,
@@ -577,6 +579,7 @@ where
     }
 }
 
+#[unstable(feature = "trusted_len", issue = "37572")]
 impl<I, U> DoubleEndedIterator for FlattenCompat<I, U>
 where
     I: DoubleEndedIterator<Item: IntoIterator<IntoIter = U, Item = U::Item>>,
@@ -646,6 +649,7 @@ where
     }
 }
 
+#[unstable(feature = "trusted_len", issue = "37572")]
 unsafe impl<const N: usize, I, T> TrustedLen
     for FlattenCompat<I, <[T; N] as IntoIterator>::IntoIter>
 where
@@ -653,6 +657,7 @@ where
 {
 }
 
+#[unstable(feature = "trusted_len", issue = "37572")]
 unsafe impl<'a, const N: usize, I, T> TrustedLen
     for FlattenCompat<I, <&'a [T; N] as IntoIterator>::IntoIter>
 where
@@ -660,6 +665,7 @@ where
 {
 }
 
+#[unstable(feature = "trusted_len", issue = "37572")]
 unsafe impl<'a, const N: usize, I, T> TrustedLen
     for FlattenCompat<I, <&'a mut [T; N] as IntoIterator>::IntoIter>
 where
diff --git a/library/core/src/iter/traits/collect.rs b/library/core/src/iter/traits/collect.rs
index 76b3a32880d..0675e56358f 100644
--- a/library/core/src/iter/traits/collect.rs
+++ b/library/core/src/iter/traits/collect.rs
@@ -95,6 +95,16 @@
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_on_unimplemented(
     on(
+        _Self = "&[{A}]",
+        message = "a slice of type `{Self}` cannot be built since we need to store the elements somewhere",
+        label = "try explicitly collecting into a `Vec<{A}>`",
+    ),
+    on(
+        all(A = "{integer}", any(_Self = "&[{integral}]",)),
+        message = "a slice of type `{Self}` cannot be built since we need to store the elements somewhere",
+        label = "try explicitly collecting into a `Vec<{A}>`",
+    ),
+    on(
         _Self = "[{A}]",
         message = "a slice of type `{Self}` cannot be built since `{Self}` has no definite size",
         label = "try explicitly collecting into a `Vec<{A}>`",
diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs
index 26c51e84035..6c419eb16f3 100644
--- a/library/core/src/lib.rs
+++ b/library/core/src/lib.rs
@@ -133,6 +133,7 @@
 #![feature(const_maybe_uninit_assume_init)]
 #![feature(const_maybe_uninit_uninit_array)]
 #![feature(const_nonnull_new)]
+#![feature(const_num_midpoint)]
 #![feature(const_option)]
 #![feature(const_option_ext)]
 #![feature(const_pin)]
@@ -215,6 +216,7 @@
 #![feature(intra_doc_pointers)]
 #![feature(intrinsics)]
 #![feature(lang_items)]
+#![feature(let_chains)]
 #![feature(link_llvm_intrinsics)]
 #![feature(macro_metavar_expr)]
 #![feature(min_specialization)]
diff --git a/library/core/src/marker.rs b/library/core/src/marker.rs
index 97f9d01e016..8dab8d1a692 100644
--- a/library/core/src/marker.rs
+++ b/library/core/src/marker.rs
@@ -43,27 +43,17 @@ use crate::hash::Hasher;
 /// ```
 #[unstable(feature = "internal_impls_macro", issue = "none")]
 macro marker_impls {
-    ( $(#[$($meta:tt)*])* $Trait:ident for $( $({$($bounds:tt)*})? $T:ty ),+ $(,)?) => {
-        // This inner macro is needed because... idk macros are weird.
-        // It allows repeating `meta` on all impls.
-        #[unstable(feature = "internal_impls_macro", issue = "none")]
-        macro _impl {
-            ( $$({$$($$bounds_:tt)*})? $$T_:ty ) => {
-                $(#[$($meta)*])* impl<$$($$($$bounds_)*)?> $Trait for $$T_ {}
-            }
-        }
-        $( _impl! { $({$($bounds)*})? $T } )+
+    ( $(#[$($meta:tt)*])* $Trait:ident for $({$($bounds:tt)*})? $T:ty $(, $($rest:tt)*)? ) => {
+        $(#[$($meta)*])* impl< $($($bounds)*)? > $Trait for $T {}
+        marker_impls! { $(#[$($meta)*])* $Trait for $($($rest)*)? }
     },
-    ( $(#[$($meta:tt)*])* unsafe $Trait:ident for $( $({$($bounds:tt)*})? $T:ty ),+ $(,)?) => {
-        #[unstable(feature = "internal_impls_macro", issue = "none")]
-        macro _impl {
-            ( $$({$$($$bounds_:tt)*})? $$T_:ty ) => {
-                $(#[$($meta)*])* unsafe impl<$$($$($$bounds_)*)?> $Trait for $$T_ {}
-            }
-        }
-
-        $( _impl! { $({$($bounds)*})? $T } )+
+    ( $(#[$($meta:tt)*])* $Trait:ident for ) => {},
+
+    ( $(#[$($meta:tt)*])* unsafe $Trait:ident for $({$($bounds:tt)*})? $T:ty $(, $($rest:tt)*)? ) => {
+        $(#[$($meta)*])* unsafe impl< $($($bounds)*)? > $Trait for $T {}
+        marker_impls! { $(#[$($meta)*])* unsafe $Trait for $($($rest)*)? }
     },
+    ( $(#[$($meta:tt)*])* unsafe $Trait:ident for ) => {},
 }
 
 /// Types that can be transferred across thread boundaries.
@@ -695,7 +685,7 @@ impl<T: ?Sized> !Sync for *mut T {}
 /// }
 /// ```
 ///
-/// This also in turn requires the annotation `T: 'a`, indicating
+/// This also in turn infers the lifetime bound `T: 'a`, indicating
 /// that any references in `T` are valid over the lifetime `'a`.
 ///
 /// When initializing a `Slice` you simply provide the value
@@ -766,16 +756,11 @@ impl<T: ?Sized> !Sync for *mut T {}
 ///
 /// ## Ownership and the drop check
 ///
-/// Adding a field of type `PhantomData<T>` indicates that your
-/// type owns data of type `T`. This in turn implies that when your
-/// type is dropped, it may drop one or more instances of the type
-/// `T`. This has bearing on the Rust compiler's [drop check]
-/// analysis.
+/// The exact interaction of `PhantomData` with drop check **may change in the future**.
 ///
-/// If your struct does not in fact *own* the data of type `T`, it is
-/// better to use a reference type, like `PhantomData<&'a T>`
-/// (ideally) or `PhantomData<*const T>` (if no lifetime applies), so
-/// as not to indicate ownership.
+/// Currently, adding a field of type `PhantomData<T>` indicates that your type *owns* data of type
+/// `T` in very rare circumstances. This in turn has effects on the Rust compiler's [drop check]
+/// analysis. For the exact rules, see the [drop check] documentation.
 ///
 /// ## Layout
 ///
@@ -783,7 +768,7 @@ impl<T: ?Sized> !Sync for *mut T {}
 /// * `size_of::<PhantomData<T>>() == 0`
 /// * `align_of::<PhantomData<T>>() == 1`
 ///
-/// [drop check]: ../../nomicon/dropck.html
+/// [drop check]: Drop#drop-check
 #[lang = "phantom_data"]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct PhantomData<T: ?Sized>;
@@ -991,6 +976,14 @@ pub trait PointerLike {}
 #[rustc_on_unimplemented(message = "`{Self}` can't be used as a const parameter type")]
 pub trait ConstParamTy: StructuralEq {}
 
+/// Derive macro generating an impl of the trait `ConstParamTy`.
+#[rustc_builtin_macro]
+#[unstable(feature = "adt_const_params", issue = "95174")]
+#[cfg(not(bootstrap))]
+pub macro ConstParamTy($item:item) {
+    /* compiler built-in */
+}
+
 // FIXME(generic_const_parameter_types): handle `ty::FnDef`/`ty::Closure`
 // FIXME(generic_const_parameter_types): handle `ty::Tuple`
 marker_impls! {
diff --git a/library/core/src/mem/mod.rs b/library/core/src/mem/mod.rs
index 4913a6de918..afbfd6d362d 100644
--- a/library/core/src/mem/mod.rs
+++ b/library/core/src/mem/mod.rs
@@ -968,6 +968,7 @@ pub const fn replace<T>(dest: &mut T, src: T) -> T {
 /// Integers and other types implementing [`Copy`] are unaffected by `drop`.
 ///
 /// ```
+/// # #![cfg_attr(not(bootstrap), allow(dropping_copy_types))]
 /// #[derive(Copy, Clone)]
 /// struct Foo(u8);
 ///
diff --git a/library/core/src/num/f32.rs b/library/core/src/num/f32.rs
index 1c6819b547d..4a035ad61e1 100644
--- a/library/core/src/num/f32.rs
+++ b/library/core/src/num/f32.rs
@@ -940,6 +940,42 @@ impl f32 {
         }
     }
 
+    /// Calculates the middle point of `self` and `rhs`.
+    ///
+    /// This returns NaN when *either* argument is NaN or if a combination of
+    /// +inf and -inf is provided as arguments.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(num_midpoint)]
+    /// assert_eq!(1f32.midpoint(4.0), 2.5);
+    /// assert_eq!((-5.5f32).midpoint(8.0), 1.25);
+    /// ```
+    #[unstable(feature = "num_midpoint", issue = "110840")]
+    pub fn midpoint(self, other: f32) -> f32 {
+        const LO: f32 = f32::MIN_POSITIVE * 2.;
+        const HI: f32 = f32::MAX / 2.;
+
+        let (a, b) = (self, other);
+        let abs_a = a.abs_private();
+        let abs_b = b.abs_private();
+
+        if abs_a <= HI && abs_b <= HI {
+            // Overflow is impossible
+            (a + b) / 2.
+        } else if abs_a < LO {
+            // Not safe to halve a
+            a + (b / 2.)
+        } else if abs_b < LO {
+            // Not safe to halve b
+            (a / 2.) + b
+        } else {
+            // Not safe to halve a and b
+            (a / 2.) + (b / 2.)
+        }
+    }
+
     /// Rounds toward zero and converts to any primitive integer type,
     /// assuming that the value is finite and fits in that type.
     ///
diff --git a/library/core/src/num/f64.rs b/library/core/src/num/f64.rs
index 1e7387217cb..3aafc435f1e 100644
--- a/library/core/src/num/f64.rs
+++ b/library/core/src/num/f64.rs
@@ -951,6 +951,42 @@ impl f64 {
         }
     }
 
+    /// Calculates the middle point of `self` and `rhs`.
+    ///
+    /// This returns NaN when *either* argument is NaN or if a combination of
+    /// +inf and -inf is provided as arguments.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(num_midpoint)]
+    /// assert_eq!(1f64.midpoint(4.0), 2.5);
+    /// assert_eq!((-5.5f64).midpoint(8.0), 1.25);
+    /// ```
+    #[unstable(feature = "num_midpoint", issue = "110840")]
+    pub fn midpoint(self, other: f64) -> f64 {
+        const LO: f64 = f64::MIN_POSITIVE * 2.;
+        const HI: f64 = f64::MAX / 2.;
+
+        let (a, b) = (self, other);
+        let abs_a = a.abs_private();
+        let abs_b = b.abs_private();
+
+        if abs_a <= HI && abs_b <= HI {
+            // Overflow is impossible
+            (a + b) / 2.
+        } else if abs_a < LO {
+            // Not safe to halve a
+            a + (b / 2.)
+        } else if abs_b < LO {
+            // Not safe to halve b
+            (a / 2.) + b
+        } else {
+            // Not safe to halve a and b
+            (a / 2.) + (b / 2.)
+        }
+    }
+
     /// Rounds toward zero and converts to any primitive integer type,
     /// assuming that the value is finite and fits in that type.
     ///
diff --git a/library/core/src/num/int_macros.rs b/library/core/src/num/int_macros.rs
index 17715c9291f..1199d09b563 100644
--- a/library/core/src/num/int_macros.rs
+++ b/library/core/src/num/int_macros.rs
@@ -2332,6 +2332,44 @@ macro_rules! int_impl {
             }
         }
 
+        /// Calculates the middle point of `self` and `rhs`.
+        ///
+        /// `midpoint(a, b)` is `(a + b) >> 1` as if it were performed in a
+        /// sufficiently-large signed integral type. This implies that the result is
+        /// always rounded towards negative infinity and that no overflow will ever occur.
+        ///
+        /// # Examples
+        ///
+        /// ```
+        /// #![feature(num_midpoint)]
+        #[doc = concat!("assert_eq!(0", stringify!($SelfT), ".midpoint(4), 2);")]
+        #[doc = concat!("assert_eq!(0", stringify!($SelfT), ".midpoint(-1), -1);")]
+        #[doc = concat!("assert_eq!((-1", stringify!($SelfT), ").midpoint(0), -1);")]
+        /// ```
+        #[unstable(feature = "num_midpoint", issue = "110840")]
+        #[rustc_const_unstable(feature = "const_num_midpoint", issue = "110840")]
+        #[rustc_allow_const_fn_unstable(const_num_midpoint)]
+        #[must_use = "this returns the result of the operation, \
+                      without modifying the original"]
+        #[inline]
+        pub const fn midpoint(self, rhs: Self) -> Self {
+            const U: $UnsignedT = <$SelfT>::MIN.unsigned_abs();
+
+            // Map an $SelfT to an $UnsignedT
+            // ex: i8 [-128; 127] to [0; 255]
+            const fn map(a: $SelfT) -> $UnsignedT {
+                (a as $UnsignedT) ^ U
+            }
+
+            // Map an $UnsignedT to an $SelfT
+            // ex: u8 [0; 255] to [-128; 127]
+            const fn demap(a: $UnsignedT) -> $SelfT {
+                (a ^ U) as $SelfT
+            }
+
+            demap(<$UnsignedT>::midpoint(map(self), map(rhs)))
+        }
+
         /// Returns the logarithm of the number with respect to an arbitrary base,
         /// rounded down.
         ///
diff --git a/library/core/src/num/mod.rs b/library/core/src/num/mod.rs
index 08444421dca..c9baa09f407 100644
--- a/library/core/src/num/mod.rs
+++ b/library/core/src/num/mod.rs
@@ -95,6 +95,57 @@ depending on the target pointer size.
     };
 }
 
+macro_rules! midpoint_impl {
+    ($SelfT:ty, unsigned) => {
+        /// Calculates the middle point of `self` and `rhs`.
+        ///
+        /// `midpoint(a, b)` is `(a + b) >> 1` as if it were performed in a
+        /// sufficiently-large signed integral type. This implies that the result is
+        /// always rounded towards negative infinity and that no overflow will ever occur.
+        ///
+        /// # Examples
+        ///
+        /// ```
+        /// #![feature(num_midpoint)]
+        #[doc = concat!("assert_eq!(0", stringify!($SelfT), ".midpoint(4), 2);")]
+        #[doc = concat!("assert_eq!(1", stringify!($SelfT), ".midpoint(4), 2);")]
+        /// ```
+        #[unstable(feature = "num_midpoint", issue = "110840")]
+        #[rustc_const_unstable(feature = "const_num_midpoint", issue = "110840")]
+        #[must_use = "this returns the result of the operation, \
+                      without modifying the original"]
+        #[inline]
+        pub const fn midpoint(self, rhs: $SelfT) -> $SelfT {
+            // Use the well known branchless algorthim from Hacker's Delight to compute
+            // `(a + b) / 2` without overflowing: `((a ^ b) >> 1) + (a & b)`.
+            ((self ^ rhs) >> 1) + (self & rhs)
+        }
+    };
+    ($SelfT:ty, $WideT:ty, unsigned) => {
+        /// Calculates the middle point of `self` and `rhs`.
+        ///
+        /// `midpoint(a, b)` is `(a + b) >> 1` as if it were performed in a
+        /// sufficiently-large signed integral type. This implies that the result is
+        /// always rounded towards negative infinity and that no overflow will ever occur.
+        ///
+        /// # Examples
+        ///
+        /// ```
+        /// #![feature(num_midpoint)]
+        #[doc = concat!("assert_eq!(0", stringify!($SelfT), ".midpoint(4), 2);")]
+        #[doc = concat!("assert_eq!(1", stringify!($SelfT), ".midpoint(4), 2);")]
+        /// ```
+        #[unstable(feature = "num_midpoint", issue = "110840")]
+        #[rustc_const_unstable(feature = "const_num_midpoint", issue = "110840")]
+        #[must_use = "this returns the result of the operation, \
+                      without modifying the original"]
+        #[inline]
+        pub const fn midpoint(self, rhs: $SelfT) -> $SelfT {
+            ((self as $WideT + rhs as $WideT) / 2) as $SelfT
+        }
+    };
+}
+
 macro_rules! widening_impl {
     ($SelfT:ty, $WideT:ty, $BITS:literal, unsigned) => {
         /// Calculates the complete product `self * rhs` without the possibility to overflow.
@@ -455,6 +506,7 @@ impl u8 {
         bound_condition = "",
     }
     widening_impl! { u8, u16, 8, unsigned }
+    midpoint_impl! { u8, u16, unsigned }
 
     /// Checks if the value is within the ASCII range.
     ///
@@ -1066,6 +1118,7 @@ impl u16 {
         bound_condition = "",
     }
     widening_impl! { u16, u32, 16, unsigned }
+    midpoint_impl! { u16, u32, unsigned }
 
     /// Checks if the value is a Unicode surrogate code point, which are disallowed values for [`char`].
     ///
@@ -1114,6 +1167,7 @@ impl u32 {
         bound_condition = "",
     }
     widening_impl! { u32, u64, 32, unsigned }
+    midpoint_impl! { u32, u64, unsigned }
 }
 
 impl u64 {
@@ -1137,6 +1191,7 @@ impl u64 {
         bound_condition = "",
     }
     widening_impl! { u64, u128, 64, unsigned }
+    midpoint_impl! { u64, u128, unsigned }
 }
 
 impl u128 {
@@ -1161,6 +1216,7 @@ impl u128 {
         from_xe_bytes_doc = "",
         bound_condition = "",
     }
+    midpoint_impl! { u128, unsigned }
 }
 
 #[cfg(target_pointer_width = "16")]
@@ -1185,6 +1241,7 @@ impl usize {
         bound_condition = " on 16-bit targets",
     }
     widening_impl! { usize, u32, 16, unsigned }
+    midpoint_impl! { usize, u32, unsigned }
 }
 
 #[cfg(target_pointer_width = "32")]
@@ -1209,6 +1266,7 @@ impl usize {
         bound_condition = " on 32-bit targets",
     }
     widening_impl! { usize, u64, 32, unsigned }
+    midpoint_impl! { usize, u64, unsigned }
 }
 
 #[cfg(target_pointer_width = "64")]
@@ -1233,6 +1291,7 @@ impl usize {
         bound_condition = " on 64-bit targets",
     }
     widening_impl! { usize, u128, 64, unsigned }
+    midpoint_impl! { usize, u128, unsigned }
 }
 
 impl usize {
diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs
index 74a325b89d4..38a1c42d9e8 100644
--- a/library/core/src/num/nonzero.rs
+++ b/library/core/src/num/nonzero.rs
@@ -493,6 +493,43 @@ macro_rules! nonzero_unsigned_operations {
                 pub const fn ilog10(self) -> u32 {
                     super::int_log10::$Int(self.0)
                 }
+
+                /// Calculates the middle point of `self` and `rhs`.
+                ///
+                /// `midpoint(a, b)` is `(a + b) >> 1` as if it were performed in a
+                /// sufficiently-large signed integral type. This implies that the result is
+                /// always rounded towards negative infinity and that no overflow will ever occur.
+                ///
+                /// # Examples
+                ///
+                /// ```
+                /// #![feature(num_midpoint)]
+                #[doc = concat!("# use std::num::", stringify!($Ty), ";")]
+                ///
+                /// # fn main() { test().unwrap(); }
+                /// # fn test() -> Option<()> {
+                #[doc = concat!("let one = ", stringify!($Ty), "::new(1)?;")]
+                #[doc = concat!("let two = ", stringify!($Ty), "::new(2)?;")]
+                #[doc = concat!("let four = ", stringify!($Ty), "::new(4)?;")]
+                ///
+                /// assert_eq!(one.midpoint(four), two);
+                /// assert_eq!(four.midpoint(one), two);
+                /// # Some(())
+                /// # }
+                /// ```
+                #[unstable(feature = "num_midpoint", issue = "110840")]
+                #[rustc_const_unstable(feature = "const_num_midpoint", issue = "110840")]
+                #[rustc_allow_const_fn_unstable(const_num_midpoint)]
+                #[must_use = "this returns the result of the operation, \
+                              without modifying the original"]
+                #[inline]
+                pub const fn midpoint(self, rhs: Self) -> Self {
+                    // SAFETY: The only way to get `0` with midpoint is to have two opposite or
+                    // near opposite numbers: (-5, 5), (0, 1), (0, 0) which is impossible because
+                    // of the unsignedness of this number and also because $Ty is guaranteed to
+                    // never being 0.
+                    unsafe { $Ty::new_unchecked(self.get().midpoint(rhs.get())) }
+                }
             }
         )+
     }
@@ -719,8 +756,6 @@ macro_rules! nonzero_signed_operations {
                 /// # Example
                 ///
                 /// ```
-                /// #![feature(nonzero_negation_ops)]
-                ///
                 #[doc = concat!("# use std::num::", stringify!($Ty), ";")]
                 /// # fn main() { test().unwrap(); }
                 /// # fn test() -> Option<()> {
@@ -734,7 +769,8 @@ macro_rules! nonzero_signed_operations {
                 /// ```
                 #[must_use]
                 #[inline]
-                #[unstable(feature = "nonzero_negation_ops", issue = "102443")]
+                #[stable(feature = "nonzero_negation_ops", since = "CURRENT_RUSTC_VERSION")]
+                #[rustc_const_stable(feature = "nonzero_negation_ops", since = "CURRENT_RUSTC_VERSION")]
                 pub const fn is_positive(self) -> bool {
                     self.get().is_positive()
                 }
@@ -745,8 +781,6 @@ macro_rules! nonzero_signed_operations {
                 /// # Example
                 ///
                 /// ```
-                /// #![feature(nonzero_negation_ops)]
-                ///
                 #[doc = concat!("# use std::num::", stringify!($Ty), ";")]
                 /// # fn main() { test().unwrap(); }
                 /// # fn test() -> Option<()> {
@@ -760,7 +794,8 @@ macro_rules! nonzero_signed_operations {
                 /// ```
                 #[must_use]
                 #[inline]
-                #[unstable(feature = "nonzero_negation_ops", issue = "102443")]
+                #[stable(feature = "nonzero_negation_ops", since = "CURRENT_RUSTC_VERSION")]
+                #[rustc_const_stable(feature = "nonzero_negation_ops", since = "CURRENT_RUSTC_VERSION")]
                 pub const fn is_negative(self) -> bool {
                     self.get().is_negative()
                 }
@@ -770,8 +805,6 @@ macro_rules! nonzero_signed_operations {
                 /// # Example
                 ///
                 /// ```
-                /// #![feature(nonzero_negation_ops)]
-                ///
                 #[doc = concat!("# use std::num::", stringify!($Ty), ";")]
                 /// # fn main() { test().unwrap(); }
                 /// # fn test() -> Option<()> {
@@ -786,7 +819,8 @@ macro_rules! nonzero_signed_operations {
                 /// # }
                 /// ```
                 #[inline]
-                #[unstable(feature = "nonzero_negation_ops", issue = "102443")]
+                #[stable(feature = "nonzero_negation_ops", since = "CURRENT_RUSTC_VERSION")]
+                #[rustc_const_stable(feature = "nonzero_negation_ops", since = "CURRENT_RUSTC_VERSION")]
                 pub const fn checked_neg(self) -> Option<$Ty> {
                     if let Some(result) = self.get().checked_neg() {
                         // SAFETY: negation of nonzero cannot yield zero values.
@@ -803,8 +837,6 @@ macro_rules! nonzero_signed_operations {
                 /// # Example
                 ///
                 /// ```
-                /// #![feature(nonzero_negation_ops)]
-                ///
                 #[doc = concat!("# use std::num::", stringify!($Ty), ";")]
                 /// # fn main() { test().unwrap(); }
                 /// # fn test() -> Option<()> {
@@ -819,7 +851,8 @@ macro_rules! nonzero_signed_operations {
                 /// # }
                 /// ```
                 #[inline]
-                #[unstable(feature = "nonzero_negation_ops", issue = "102443")]
+                #[stable(feature = "nonzero_negation_ops", since = "CURRENT_RUSTC_VERSION")]
+                #[rustc_const_stable(feature = "nonzero_negation_ops", since = "CURRENT_RUSTC_VERSION")]
                 pub const fn overflowing_neg(self) -> ($Ty, bool) {
                     let (result, overflow) = self.get().overflowing_neg();
                     // SAFETY: negation of nonzero cannot yield zero values.
@@ -832,8 +865,6 @@ macro_rules! nonzero_signed_operations {
                 /// # Example
                 ///
                 /// ```
-                /// #![feature(nonzero_negation_ops)]
-                ///
                 #[doc = concat!("# use std::num::", stringify!($Ty), ";")]
                 /// # fn main() { test().unwrap(); }
                 /// # fn test() -> Option<()> {
@@ -853,7 +884,8 @@ macro_rules! nonzero_signed_operations {
                 /// # }
                 /// ```
                 #[inline]
-                #[unstable(feature = "nonzero_negation_ops", issue = "102443")]
+                #[stable(feature = "nonzero_negation_ops", since = "CURRENT_RUSTC_VERSION")]
+                #[rustc_const_stable(feature = "nonzero_negation_ops", since = "CURRENT_RUSTC_VERSION")]
                 pub const fn saturating_neg(self) -> $Ty {
                     if let Some(result) = self.checked_neg() {
                         return result;
@@ -870,8 +902,6 @@ macro_rules! nonzero_signed_operations {
                 /// # Example
                 ///
                 /// ```
-                /// #![feature(nonzero_negation_ops)]
-                ///
                 #[doc = concat!("# use std::num::", stringify!($Ty), ";")]
                 /// # fn main() { test().unwrap(); }
                 /// # fn test() -> Option<()> {
@@ -886,7 +916,8 @@ macro_rules! nonzero_signed_operations {
                 /// # }
                 /// ```
                 #[inline]
-                #[unstable(feature = "nonzero_negation_ops", issue = "102443")]
+                #[stable(feature = "nonzero_negation_ops", since = "CURRENT_RUSTC_VERSION")]
+                #[rustc_const_stable(feature = "nonzero_negation_ops", since = "CURRENT_RUSTC_VERSION")]
                 pub const fn wrapping_neg(self) -> $Ty {
                     let result = self.get().wrapping_neg();
                     // SAFETY: negation of nonzero cannot yield zero values.
diff --git a/library/core/src/ops/drop.rs b/library/core/src/ops/drop.rs
index a2c3d978cc4..9ebf426be95 100644
--- a/library/core/src/ops/drop.rs
+++ b/library/core/src/ops/drop.rs
@@ -132,6 +132,74 @@
 /// are `Copy` get implicitly duplicated by the compiler, making it very
 /// hard to predict when, and how often destructors will be executed. As such,
 /// these types cannot have destructors.
+///
+/// ## Drop check
+///
+/// Dropping interacts with the borrow checker in subtle ways: when a type `T` is being implicitly
+/// dropped as some variable of this type goes out of scope, the borrow checker needs to ensure that
+/// calling `T`'s destructor at this moment is safe. In particular, it also needs to be safe to
+/// recursively drop all the fields of `T`. For example, it is crucial that code like the following
+/// is being rejected:
+///
+/// ```compile_fail,E0597
+/// use std::cell::Cell;
+///
+/// struct S<'a>(Cell<Option<&'a S<'a>>>, Box<i32>);
+/// impl Drop for S<'_> {
+///     fn drop(&mut self) {
+///         if let Some(r) = self.0.get() {
+///             // Print the contents of the `Box` in `r`.
+///             println!("{}", r.1);
+///         }
+///     }
+/// }
+///
+/// fn main() {
+///     // Set up two `S` that point to each other.
+///     let s1 = S(Cell::new(None), Box::new(42));
+///     let s2 = S(Cell::new(Some(&s1)), Box::new(42));
+///     s1.0.set(Some(&s2));
+///     // Now they both get dropped. But whichever is the 2nd one
+///     // to be dropped will access the `Box` in the first one,
+///     // which is a use-after-free!
+/// }
+/// ```
+///
+/// The Nomicon discusses the need for [drop check in more detail][drop check].
+///
+/// To reject such code, the "drop check" analysis determines which types and lifetimes need to
+/// still be live when `T` gets dropped. The exact details of this analysis are not yet
+/// stably guaranteed and **subject to change**. Currently, the analysis works as follows:
+/// - If `T` has no drop glue, then trivially nothing is required to be live. This is the case if
+///   neither `T` nor any of its (recursive) fields have a destructor (`impl Drop`). [`PhantomData`]
+///   and [`ManuallyDrop`] are considered to never have a destructor, no matter their field type.
+/// - If `T` has drop glue, then, for all types `U` that are *owned* by any field of `T`,
+///   recursively add the types and lifetimes that need to be live when `U` gets dropped. The set of
+///   owned types is determined by recursively traversing `T`:
+///   - Recursively descend through `PhantomData`, `Box`, tuples, and arrays (including arrays of
+///     length 0).
+///   - Stop at reference and raw pointer types as well as function pointers and function items;
+///     they do not own anything.
+///   - Stop at non-composite types (type parameters that remain generic in the current context and
+///     base types such as integers and `bool`); these types are owned.
+///   - When hitting an ADT with `impl Drop`, stop there; this type is owned.
+///   - When hitting an ADT without `impl Drop`, recursively descend to its fields. (For an `enum`,
+///     consider all fields of all variants.)
+/// - Furthermore, if `T` implements `Drop`, then all generic (lifetime and type) parameters of `T`
+///   must be live.
+///
+/// In the above example, the last clause implies that `'a` must be live when `S<'a>` is dropped,
+/// and hence the example is rejected. If we remove the `impl Drop`, the liveness requirement
+/// disappears and the example is accepted.
+///
+/// There exists an unstable way for a type to opt-out of the last clause; this is called "drop
+/// check eyepatch" or `may_dangle`. For more details on this nightly-only feature, see the
+/// [discussion in the Nomicon][nomicon].
+///
+/// [`ManuallyDrop`]: crate::mem::ManuallyDrop
+/// [`PhantomData`]: crate::marker::PhantomData
+/// [drop check]: ../../nomicon/dropck.html
+/// [nomicon]: ../../nomicon/phantom-data.html#an-exception-the-special-case-of-the-standard-library-and-its-unstable-may_dangle
 #[lang = "drop"]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[const_trait]
diff --git a/library/core/src/panic.rs b/library/core/src/panic.rs
index 8338a5d7e5a..20be60d3535 100644
--- a/library/core/src/panic.rs
+++ b/library/core/src/panic.rs
@@ -28,16 +28,18 @@ pub macro panic_2015 {
         $crate::panicking::panic($msg)
     ),
     // Use `panic_str` instead of `panic_display::<&str>` for non_fmt_panic lint.
-    ($msg:expr $(,)?) => (
-        $crate::panicking::panic_str($msg)
-    ),
+    ($msg:expr $(,)?) => ({
+        $crate::panicking::panic_str($msg);
+    }),
     // Special-case the single-argument case for const_panic.
-    ("{}", $arg:expr $(,)?) => (
-        $crate::panicking::panic_display(&$arg)
-    ),
-    ($fmt:expr, $($arg:tt)+) => (
-        $crate::panicking::panic_fmt($crate::const_format_args!($fmt, $($arg)+))
-    ),
+    ("{}", $arg:expr $(,)?) => ({
+        $crate::panicking::panic_display(&$arg);
+    }),
+    ($fmt:expr, $($arg:tt)+) => ({
+        // Semicolon to prevent temporaries inside the formatting machinery from
+        // being considered alive in the caller after the panic_fmt call.
+        $crate::panicking::panic_fmt($crate::const_format_args!($fmt, $($arg)+));
+    }),
 }
 
 #[doc(hidden)]
@@ -50,12 +52,14 @@ pub macro panic_2021 {
         $crate::panicking::panic("explicit panic")
     ),
     // Special-case the single-argument case for const_panic.
-    ("{}", $arg:expr $(,)?) => (
-        $crate::panicking::panic_display(&$arg)
-    ),
-    ($($t:tt)+) => (
-        $crate::panicking::panic_fmt($crate::const_format_args!($($t)+))
-    ),
+    ("{}", $arg:expr $(,)?) => ({
+        $crate::panicking::panic_display(&$arg);
+    }),
+    ($($t:tt)+) => ({
+        // Semicolon to prevent temporaries inside the formatting machinery from
+        // being considered alive in the caller after the panic_fmt call.
+        $crate::panicking::panic_fmt($crate::const_format_args!($($t)+));
+    }),
 }
 
 #[doc(hidden)]
@@ -69,9 +73,9 @@ pub macro unreachable_2015 {
     ),
     // Use of `unreachable_display` for non_fmt_panic lint.
     // NOTE: the message ("internal error ...") is embedded directly in unreachable_display
-    ($msg:expr $(,)?) => (
-        $crate::panicking::unreachable_display(&$msg)
-    ),
+    ($msg:expr $(,)?) => ({
+        $crate::panicking::unreachable_display(&$msg);
+    }),
     ($fmt:expr, $($arg:tt)*) => (
         $crate::panic!($crate::concat!("internal error: entered unreachable code: ", $fmt), $($arg)*)
     ),
diff --git a/library/core/src/panic/panic_info.rs b/library/core/src/panic/panic_info.rs
index 06fbe083ca1..5576adde84b 100644
--- a/library/core/src/panic/panic_info.rs
+++ b/library/core/src/panic/panic_info.rs
@@ -134,7 +134,7 @@ impl<'a> PanicInfo<'a> {
     /// whose ABI does not support unwinding.
     ///
     /// It is safe for a panic handler to unwind even when this function returns
-    /// true, however this will simply cause the panic handler to be called
+    /// false, however this will simply cause the panic handler to be called
     /// again.
     #[must_use]
     #[unstable(feature = "panic_can_unwind", issue = "92988")]
diff --git a/library/core/src/pin.rs b/library/core/src/pin.rs
index c4b89a63019..6b319b4355c 100644
--- a/library/core/src/pin.rs
+++ b/library/core/src/pin.rs
@@ -393,6 +393,8 @@ use crate::ops::{CoerceUnsized, Deref, DerefMut, DispatchFromDyn, Receiver};
 /// value in place, preventing the value referenced by that pointer from being moved
 /// unless it implements [`Unpin`].
 ///
+/// `Pin<P>` is guaranteed to have the same memory layout and ABI as `P`.
+///
 /// *See the [`pin` module] documentation for an explanation of pinning.*
 ///
 /// [`pin` module]: self
diff --git a/library/core/src/slice/iter.rs b/library/core/src/slice/iter.rs
index 67fcef0f466..5369fe0a9a9 100644
--- a/library/core/src/slice/iter.rs
+++ b/library/core/src/slice/iter.rs
@@ -90,8 +90,6 @@ impl<'a, T> Iter<'a, T> {
         let ptr = slice.as_ptr();
         // SAFETY: Similar to `IterMut::new`.
         unsafe {
-            assume(!ptr.is_null());
-
             let end = if T::IS_ZST { invalid(slice.len()) } else { ptr.add(slice.len()) };
 
             Self { ptr: NonNull::new_unchecked(ptr as *mut T), end, _marker: PhantomData }
@@ -228,8 +226,6 @@ impl<'a, T> IterMut<'a, T> {
         // See the `next_unchecked!` and `is_empty!` macros as well as the
         // `post_inc_start` method for more information.
         unsafe {
-            assume(!ptr.is_null());
-
             let end = if T::IS_ZST { invalid_mut(slice.len()) } else { ptr.add(slice.len()) };
 
             Self { ptr: NonNull::new_unchecked(ptr), end, _marker: PhantomData }
diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs
index c2e9ba273a5..5ece1b78c03 100644
--- a/library/core/src/slice/mod.rs
+++ b/library/core/src/slice/mod.rs
@@ -995,7 +995,7 @@ impl<T> [T] {
     #[unstable(feature = "slice_as_chunks", issue = "74985")]
     #[inline]
     #[must_use]
-    pub unsafe fn as_chunks_unchecked<const N: usize>(&self) -> &[[T; N]] {
+    pub const unsafe fn as_chunks_unchecked<const N: usize>(&self) -> &[[T; N]] {
         let this = self;
         // SAFETY: Caller must guarantee that `N` is nonzero and exactly divides the slice length
         let new_len = unsafe {
@@ -1043,7 +1043,7 @@ impl<T> [T] {
     #[inline]
     #[track_caller]
     #[must_use]
-    pub fn as_chunks<const N: usize>(&self) -> (&[[T; N]], &[T]) {
+    pub const fn as_chunks<const N: usize>(&self) -> (&[[T; N]], &[T]) {
         assert!(N != 0, "chunk size must be non-zero");
         let len = self.len() / N;
         let (multiple_of_n, remainder) = self.split_at(len * N);
@@ -1075,7 +1075,7 @@ impl<T> [T] {
     #[inline]
     #[track_caller]
     #[must_use]
-    pub fn as_rchunks<const N: usize>(&self) -> (&[T], &[[T; N]]) {
+    pub const fn as_rchunks<const N: usize>(&self) -> (&[T], &[[T; N]]) {
         assert!(N != 0, "chunk size must be non-zero");
         let len = self.len() / N;
         let (remainder, multiple_of_n) = self.split_at(self.len() - len * N);
@@ -1152,7 +1152,7 @@ impl<T> [T] {
     #[unstable(feature = "slice_as_chunks", issue = "74985")]
     #[inline]
     #[must_use]
-    pub unsafe fn as_chunks_unchecked_mut<const N: usize>(&mut self) -> &mut [[T; N]] {
+    pub const unsafe fn as_chunks_unchecked_mut<const N: usize>(&mut self) -> &mut [[T; N]] {
         let this = &*self;
         // SAFETY: Caller must guarantee that `N` is nonzero and exactly divides the slice length
         let new_len = unsafe {
@@ -1195,7 +1195,7 @@ impl<T> [T] {
     #[inline]
     #[track_caller]
     #[must_use]
-    pub fn as_chunks_mut<const N: usize>(&mut self) -> (&mut [[T; N]], &mut [T]) {
+    pub const fn as_chunks_mut<const N: usize>(&mut self) -> (&mut [[T; N]], &mut [T]) {
         assert!(N != 0, "chunk size must be non-zero");
         let len = self.len() / N;
         let (multiple_of_n, remainder) = self.split_at_mut(len * N);
@@ -1233,7 +1233,7 @@ impl<T> [T] {
     #[inline]
     #[track_caller]
     #[must_use]
-    pub fn as_rchunks_mut<const N: usize>(&mut self) -> (&mut [T], &mut [[T; N]]) {
+    pub const fn as_rchunks_mut<const N: usize>(&mut self) -> (&mut [T], &mut [[T; N]]) {
         assert!(N != 0, "chunk size must be non-zero");
         let len = self.len() / N;
         let (remainder, multiple_of_n) = self.split_at_mut(self.len() - len * N);
@@ -1595,7 +1595,8 @@ impl<T> [T] {
     /// }
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_const_unstable(feature = "const_slice_split_at_not_mut", issue = "101158")]
+    #[rustc_const_stable(feature = "const_slice_split_at_not_mut", since = "CURRENT_RUSTC_VERSION")]
+    #[rustc_allow_const_fn_unstable(slice_split_at_unchecked)]
     #[inline]
     #[track_caller]
     #[must_use]
diff --git a/library/core/src/slice/sort.rs b/library/core/src/slice/sort.rs
index e6e3b55efa9..eb8595ca90d 100644
--- a/library/core/src/slice/sort.rs
+++ b/library/core/src/slice/sort.rs
@@ -1085,12 +1085,12 @@ where
 
             // SAFETY: left and right must be valid and part of v same for out.
             unsafe {
-                let to_copy = if is_less(&*right, &**left) {
-                    get_and_increment(&mut right)
-                } else {
-                    get_and_increment(left)
-                };
-                ptr::copy_nonoverlapping(to_copy, get_and_increment(out), 1);
+                let is_l = is_less(&*right, &**left);
+                let to_copy = if is_l { right } else { *left };
+                ptr::copy_nonoverlapping(to_copy, *out, 1);
+                *out = out.add(1);
+                right = right.add(is_l as usize);
+                *left = left.add(!is_l as usize);
             }
         }
     } else {
@@ -1113,32 +1113,18 @@ where
 
             // SAFETY: left and right must be valid and part of v same for out.
             unsafe {
-                let to_copy = if is_less(&*right.sub(1), &*left.sub(1)) {
-                    decrement_and_get(left)
-                } else {
-                    decrement_and_get(right)
-                };
-                ptr::copy_nonoverlapping(to_copy, decrement_and_get(&mut out), 1);
+                let is_l = is_less(&*right.sub(1), &*left.sub(1));
+                *left = left.sub(is_l as usize);
+                *right = right.sub(!is_l as usize);
+                let to_copy = if is_l { *left } else { *right };
+                out = out.sub(1);
+                ptr::copy_nonoverlapping(to_copy, out, 1);
             }
         }
     }
     // Finally, `hole` gets dropped. If the shorter run was not fully consumed, whatever remains of
     // it will now be copied into the hole in `v`.
 
-    unsafe fn get_and_increment<T>(ptr: &mut *mut T) -> *mut T {
-        let old = *ptr;
-
-        // SAFETY: ptr.add(1) must still be a valid pointer and part of `v`.
-        *ptr = unsafe { ptr.add(1) };
-        old
-    }
-
-    unsafe fn decrement_and_get<T>(ptr: &mut *mut T) -> *mut T {
-        // SAFETY: ptr.sub(1) must still be a valid pointer and part of `v`.
-        *ptr = unsafe { ptr.sub(1) };
-        *ptr
-    }
-
     // When dropped, copies the range `start..end` into `dest..`.
     struct MergeHole<T> {
         start: *mut T,
diff --git a/library/core/src/str/pattern.rs b/library/core/src/str/pattern.rs
index e3a464a1c51..91ee2903aab 100644
--- a/library/core/src/str/pattern.rs
+++ b/library/core/src/str/pattern.rs
@@ -791,8 +791,8 @@ pub struct CharArrayRefSearcher<'a, 'b, const N: usize>(
 /// # Examples
 ///
 /// ```
-/// assert_eq!("Hello world".find(['l', 'l']), Some(2));
-/// assert_eq!("Hello world".find(['l', 'l']), Some(2));
+/// assert_eq!("Hello world".find(['o', 'l']), Some(2));
+/// assert_eq!("Hello world".find(['h', 'w']), Some(6));
 /// ```
 impl<'a, const N: usize> Pattern<'a> for [char; N] {
     pattern_methods!(CharArraySearcher<'a, N>, MultiCharEqPattern, CharArraySearcher);
@@ -811,8 +811,8 @@ unsafe impl<'a, const N: usize> ReverseSearcher<'a> for CharArraySearcher<'a, N>
 /// # Examples
 ///
 /// ```
-/// assert_eq!("Hello world".find(&['l', 'l']), Some(2));
-/// assert_eq!("Hello world".find(&['l', 'l']), Some(2));
+/// assert_eq!("Hello world".find(&['o', 'l']), Some(2));
+/// assert_eq!("Hello world".find(&['h', 'w']), Some(6));
 /// ```
 impl<'a, 'b, const N: usize> Pattern<'a> for &'b [char; N] {
     pattern_methods!(CharArrayRefSearcher<'a, 'b, N>, MultiCharEqPattern, CharArrayRefSearcher);
diff --git a/library/core/src/task/mod.rs b/library/core/src/task/mod.rs
index c5f89b9a2c6..3f0080e3832 100644
--- a/library/core/src/task/mod.rs
+++ b/library/core/src/task/mod.rs
@@ -13,5 +13,3 @@ pub use self::wake::{Context, RawWaker, RawWakerVTable, Waker};
 mod ready;
 #[stable(feature = "ready_macro", since = "1.64.0")]
 pub use ready::ready;
-#[unstable(feature = "poll_ready", issue = "89780")]
-pub use ready::Ready;
diff --git a/library/core/src/task/poll.rs b/library/core/src/task/poll.rs
index 168516263f1..0a0f702f6fb 100644
--- a/library/core/src/task/poll.rs
+++ b/library/core/src/task/poll.rs
@@ -3,7 +3,6 @@
 use crate::convert;
 use crate::ops::{self, ControlFlow};
 use crate::result::Result;
-use crate::task::Ready;
 
 /// Indicates whether a value is available or if the current task has been
 /// scheduled to receive a wakeup instead.
@@ -95,38 +94,6 @@ impl<T> Poll<T> {
     pub const fn is_pending(&self) -> bool {
         !self.is_ready()
     }
-
-    /// Extracts the successful type of a [`Poll<T>`].
-    ///
-    /// When combined with the `?` operator, this function will
-    /// propagate any [`Poll::Pending`] values to the caller, and
-    /// extract the `T` from [`Poll::Ready`].
-    ///
-    /// # Examples
-    ///
-    /// ```rust
-    /// #![feature(poll_ready)]
-    ///
-    /// use std::task::{Context, Poll};
-    /// use std::future::{self, Future};
-    /// use std::pin::Pin;
-    ///
-    /// pub fn do_poll(cx: &mut Context<'_>) -> Poll<()> {
-    ///     let mut fut = future::ready(42);
-    ///     let fut = Pin::new(&mut fut);
-    ///
-    ///     let num = fut.poll(cx).ready()?;
-    ///     # drop(num);
-    ///     // ... use num
-    ///
-    ///     Poll::Ready(())
-    /// }
-    /// ```
-    #[inline]
-    #[unstable(feature = "poll_ready", issue = "89780")]
-    pub fn ready(self) -> Ready<T> {
-        Ready(self)
-    }
 }
 
 impl<T, E> Poll<Result<T, E>> {
diff --git a/library/core/src/task/ready.rs b/library/core/src/task/ready.rs
index b1daf545fbe..495d72fd14b 100644
--- a/library/core/src/task/ready.rs
+++ b/library/core/src/task/ready.rs
@@ -1,8 +1,3 @@
-use core::convert;
-use core::fmt;
-use core::ops::{ControlFlow, FromResidual, Try};
-use core::task::Poll;
-
 /// Extracts the successful type of a [`Poll<T>`].
 ///
 /// This macro bakes in propagation of [`Pending`] signals by returning early.
@@ -22,7 +17,7 @@ use core::task::Poll;
 ///     let fut = Pin::new(&mut fut);
 ///
 ///     let num = ready!(fut.poll(cx));
-///     # drop(num);
+///     # let _ = num;
 ///     // ... use num
 ///
 ///     Poll::Ready(())
@@ -44,7 +39,7 @@ use core::task::Poll;
 ///     Poll::Ready(t) => t,
 ///     Poll::Pending => return Poll::Pending,
 /// };
-///     # drop(num);
+///     # let _ = num; // to silence unused warning
 ///     # // ... use num
 ///     #
 ///     # Poll::Ready(())
@@ -60,55 +55,3 @@ pub macro ready($e:expr) {
         }
     }
 }
-
-/// Extracts the successful type of a [`Poll<T>`].
-///
-/// See [`Poll::ready`] for details.
-#[unstable(feature = "poll_ready", issue = "89780")]
-pub struct Ready<T>(pub(crate) Poll<T>);
-
-#[unstable(feature = "poll_ready", issue = "89780")]
-impl<T> Try for Ready<T> {
-    type Output = T;
-    type Residual = Ready<convert::Infallible>;
-
-    #[inline]
-    fn from_output(output: Self::Output) -> Self {
-        Ready(Poll::Ready(output))
-    }
-
-    #[inline]
-    fn branch(self) -> ControlFlow<Self::Residual, Self::Output> {
-        match self.0 {
-            Poll::Ready(v) => ControlFlow::Continue(v),
-            Poll::Pending => ControlFlow::Break(Ready(Poll::Pending)),
-        }
-    }
-}
-
-#[unstable(feature = "poll_ready", issue = "89780")]
-impl<T> FromResidual for Ready<T> {
-    #[inline]
-    fn from_residual(residual: Ready<convert::Infallible>) -> Self {
-        match residual.0 {
-            Poll::Pending => Ready(Poll::Pending),
-        }
-    }
-}
-
-#[unstable(feature = "poll_ready", issue = "89780")]
-impl<T> FromResidual<Ready<convert::Infallible>> for Poll<T> {
-    #[inline]
-    fn from_residual(residual: Ready<convert::Infallible>) -> Self {
-        match residual.0 {
-            Poll::Pending => Poll::Pending,
-        }
-    }
-}
-
-#[unstable(feature = "poll_ready", issue = "89780")]
-impl<T> fmt::Debug for Ready<T> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        f.debug_tuple("Ready").finish()
-    }
-}
diff --git a/library/core/src/task/wake.rs b/library/core/src/task/wake.rs
index 808825326ae..7043ab5ff2b 100644
--- a/library/core/src/task/wake.rs
+++ b/library/core/src/task/wake.rs
@@ -232,7 +232,7 @@ impl fmt::Debug for Context<'_> {
 ///
 /// [`Future::poll()`]: core::future::Future::poll
 /// [`Poll::Pending`]: core::task::Poll::Pending
-#[repr(transparent)]
+#[cfg_attr(not(doc), repr(transparent))] // work around https://github.com/rust-lang/rust/issues/66401
 #[stable(feature = "futures_api", since = "1.36.0")]
 pub struct Waker {
     waker: RawWaker,
diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs
index 3c49d1705e5..3933e328951 100644
--- a/library/core/tests/lib.rs
+++ b/library/core/tests/lib.rs
@@ -53,6 +53,7 @@
 #![feature(maybe_uninit_uninit_array_transpose)]
 #![feature(min_specialization)]
 #![feature(numfmt)]
+#![feature(num_midpoint)]
 #![feature(step_trait)]
 #![feature(str_internals)]
 #![feature(std_internals)]
diff --git a/library/core/tests/mem.rs b/library/core/tests/mem.rs
index 7f033816901..aee9c89b595 100644
--- a/library/core/tests/mem.rs
+++ b/library/core/tests/mem.rs
@@ -386,6 +386,26 @@ fn offset_of() {
     // Layout of tuples is unstable
     assert!(offset_of!((u8, u16), 0) <= size_of::<(u8, u16)>() - 1);
     assert!(offset_of!((u8, u16), 1) <= size_of::<(u8, u16)>() - 2);
+
+    #[repr(C)]
+    struct Generic<T> {
+        x: u8,
+        y: u32,
+        z: T
+    }
+
+    trait Trait {}
+
+    // Ensure that this type of generics works
+    fn offs_of_z<T>() -> usize {
+        offset_of!(Generic<T>, z)
+    }
+
+    assert_eq!(offset_of!(Generic<u8>, z), 8);
+    assert_eq!(offs_of_z::<u8>(), 8);
+
+    // Ensure that it works with the implicit lifetime in `Box<dyn Trait + '_>`.
+    assert_eq!(offset_of!(Generic<Box<dyn Trait>>, z), 8);
 }
 
 #[test]
diff --git a/library/core/tests/num/int_macros.rs b/library/core/tests/num/int_macros.rs
index 18c55e43aac..439bbe66997 100644
--- a/library/core/tests/num/int_macros.rs
+++ b/library/core/tests/num/int_macros.rs
@@ -364,6 +364,32 @@ macro_rules! int_module {
                 assert_eq!((0 as $T).borrowing_sub($T::MIN, false), ($T::MIN, true));
                 assert_eq!((0 as $T).borrowing_sub($T::MIN, true), ($T::MAX, false));
             }
+
+            #[test]
+            fn test_midpoint() {
+                assert_eq!(<$T>::midpoint(1, 3), 2);
+                assert_eq!(<$T>::midpoint(3, 1), 2);
+
+                assert_eq!(<$T>::midpoint(0, 0), 0);
+                assert_eq!(<$T>::midpoint(0, 2), 1);
+                assert_eq!(<$T>::midpoint(2, 0), 1);
+                assert_eq!(<$T>::midpoint(2, 2), 2);
+
+                assert_eq!(<$T>::midpoint(1, 4), 2);
+                assert_eq!(<$T>::midpoint(4, 1), 2);
+                assert_eq!(<$T>::midpoint(3, 4), 3);
+                assert_eq!(<$T>::midpoint(4, 3), 3);
+
+                assert_eq!(<$T>::midpoint(<$T>::MIN, <$T>::MAX), -1);
+                assert_eq!(<$T>::midpoint(<$T>::MAX, <$T>::MIN), -1);
+                assert_eq!(<$T>::midpoint(<$T>::MIN, <$T>::MIN), <$T>::MIN);
+                assert_eq!(<$T>::midpoint(<$T>::MAX, <$T>::MAX), <$T>::MAX);
+
+                assert_eq!(<$T>::midpoint(<$T>::MIN, 6), <$T>::MIN / 2 + 3);
+                assert_eq!(<$T>::midpoint(6, <$T>::MIN), <$T>::MIN / 2 + 3);
+                assert_eq!(<$T>::midpoint(<$T>::MAX, 6), <$T>::MAX / 2 + 3);
+                assert_eq!(<$T>::midpoint(6, <$T>::MAX), <$T>::MAX / 2 + 3);
+            }
         }
     };
 }
diff --git a/library/core/tests/num/mod.rs b/library/core/tests/num/mod.rs
index 3e1f848ccfe..3f3659ba837 100644
--- a/library/core/tests/num/mod.rs
+++ b/library/core/tests/num/mod.rs
@@ -724,7 +724,7 @@ assume_usize_width! {
 }
 
 macro_rules! test_float {
-    ($modname: ident, $fty: ty, $inf: expr, $neginf: expr, $nan: expr) => {
+    ($modname: ident, $fty: ty, $inf: expr, $neginf: expr, $nan: expr, $min: expr, $max: expr, $min_pos: expr) => {
         mod $modname {
             #[test]
             fn min() {
@@ -845,6 +845,38 @@ macro_rules! test_float {
                 assert!(($nan as $fty).maximum($nan).is_nan());
             }
             #[test]
+            fn midpoint() {
+                assert_eq!((0.5 as $fty).midpoint(0.5), 0.5);
+                assert_eq!((0.5 as $fty).midpoint(2.5), 1.5);
+                assert_eq!((3.0 as $fty).midpoint(4.0), 3.5);
+                assert_eq!((-3.0 as $fty).midpoint(4.0), 0.5);
+                assert_eq!((3.0 as $fty).midpoint(-4.0), -0.5);
+                assert_eq!((-3.0 as $fty).midpoint(-4.0), -3.5);
+                assert_eq!((0.0 as $fty).midpoint(0.0), 0.0);
+                assert_eq!((-0.0 as $fty).midpoint(-0.0), -0.0);
+                assert_eq!((-5.0 as $fty).midpoint(5.0), 0.0);
+                assert_eq!(($max as $fty).midpoint($min), 0.0);
+                assert_eq!(($min as $fty).midpoint($max), -0.0);
+                assert_eq!(($max as $fty).midpoint($min_pos), $max / 2.);
+                assert_eq!((-$max as $fty).midpoint($min_pos), -$max / 2.);
+                assert_eq!(($max as $fty).midpoint(-$min_pos), $max / 2.);
+                assert_eq!((-$max as $fty).midpoint(-$min_pos), -$max / 2.);
+                assert_eq!(($min_pos as $fty).midpoint($max), $max / 2.);
+                assert_eq!(($min_pos as $fty).midpoint(-$max), -$max / 2.);
+                assert_eq!((-$min_pos as $fty).midpoint($max), $max / 2.);
+                assert_eq!((-$min_pos as $fty).midpoint(-$max), -$max / 2.);
+                assert_eq!(($max as $fty).midpoint($max), $max);
+                assert_eq!(($min_pos as $fty).midpoint($min_pos), $min_pos);
+                assert_eq!((-$min_pos as $fty).midpoint(-$min_pos), -$min_pos);
+                assert_eq!(($max as $fty).midpoint(5.0), $max / 2.0 + 2.5);
+                assert_eq!(($max as $fty).midpoint(-5.0), $max / 2.0 - 2.5);
+                assert_eq!(($inf as $fty).midpoint($inf), $inf);
+                assert_eq!(($neginf as $fty).midpoint($neginf), $neginf);
+                assert!(($nan as $fty).midpoint(1.0).is_nan());
+                assert!((1.0 as $fty).midpoint($nan).is_nan());
+                assert!(($nan as $fty).midpoint($nan).is_nan());
+            }
+            #[test]
             fn rem_euclid() {
                 let a: $fty = 42.0;
                 assert!($inf.rem_euclid(a).is_nan());
@@ -867,5 +899,23 @@ macro_rules! test_float {
     };
 }
 
-test_float!(f32, f32, f32::INFINITY, f32::NEG_INFINITY, f32::NAN);
-test_float!(f64, f64, f64::INFINITY, f64::NEG_INFINITY, f64::NAN);
+test_float!(
+    f32,
+    f32,
+    f32::INFINITY,
+    f32::NEG_INFINITY,
+    f32::NAN,
+    f32::MIN,
+    f32::MAX,
+    f32::MIN_POSITIVE
+);
+test_float!(
+    f64,
+    f64,
+    f64::INFINITY,
+    f64::NEG_INFINITY,
+    f64::NAN,
+    f64::MIN,
+    f64::MAX,
+    f64::MIN_POSITIVE
+);
diff --git a/library/core/tests/num/uint_macros.rs b/library/core/tests/num/uint_macros.rs
index 15ae9f2324f..7d6203db0b9 100644
--- a/library/core/tests/num/uint_macros.rs
+++ b/library/core/tests/num/uint_macros.rs
@@ -252,6 +252,32 @@ macro_rules! uint_module {
                 assert_eq!($T::MAX.borrowing_sub(0, true), ($T::MAX - 1, false));
                 assert_eq!($T::MAX.borrowing_sub($T::MAX, true), ($T::MAX, true));
             }
+
+            #[test]
+            fn test_midpoint() {
+                assert_eq!(<$T>::midpoint(1, 3), 2);
+                assert_eq!(<$T>::midpoint(3, 1), 2);
+
+                assert_eq!(<$T>::midpoint(0, 0), 0);
+                assert_eq!(<$T>::midpoint(0, 2), 1);
+                assert_eq!(<$T>::midpoint(2, 0), 1);
+                assert_eq!(<$T>::midpoint(2, 2), 2);
+
+                assert_eq!(<$T>::midpoint(1, 4), 2);
+                assert_eq!(<$T>::midpoint(4, 1), 2);
+                assert_eq!(<$T>::midpoint(3, 4), 3);
+                assert_eq!(<$T>::midpoint(4, 3), 3);
+
+                assert_eq!(<$T>::midpoint(<$T>::MIN, <$T>::MAX), (<$T>::MAX - <$T>::MIN) / 2);
+                assert_eq!(<$T>::midpoint(<$T>::MAX, <$T>::MIN), (<$T>::MAX - <$T>::MIN) / 2);
+                assert_eq!(<$T>::midpoint(<$T>::MIN, <$T>::MIN), <$T>::MIN);
+                assert_eq!(<$T>::midpoint(<$T>::MAX, <$T>::MAX), <$T>::MAX);
+
+                assert_eq!(<$T>::midpoint(<$T>::MIN, 6), <$T>::MIN / 2 + 3);
+                assert_eq!(<$T>::midpoint(6, <$T>::MIN), <$T>::MIN / 2 + 3);
+                assert_eq!(<$T>::midpoint(<$T>::MAX, 6), (<$T>::MAX - <$T>::MIN) / 2 + 3);
+                assert_eq!(<$T>::midpoint(6, <$T>::MAX), (<$T>::MAX - <$T>::MIN) / 2 + 3);
+            }
         }
     };
 }
diff --git a/library/portable-simd/crates/core_simd/src/masks.rs b/library/portable-simd/crates/core_simd/src/masks.rs
index e58df80fca8..e0f3c7beef6 100644
--- a/library/portable-simd/crates/core_simd/src/masks.rs
+++ b/library/portable-simd/crates/core_simd/src/masks.rs
@@ -88,7 +88,7 @@ impl_element! { isize }
 /// The layout of this type is unspecified, and may change between platforms
 /// and/or Rust versions, and code should not assume that it is equivalent to
 /// `[T; LANES]`.
-#[repr(transparent)]
+#[cfg_attr(not(doc), repr(transparent))] // work around https://github.com/rust-lang/rust/issues/90435
 pub struct Mask<T, const LANES: usize>(mask_impl::Mask<T, LANES>)
 where
     T: MaskElement,
diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs
index 6640c7fb162..89dfdfafdb1 100644
--- a/library/std/src/fs.rs
+++ b/library/std/src/fs.rs
@@ -15,6 +15,7 @@ use crate::ffi::OsString;
 use crate::fmt;
 use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut, Read, Seek, SeekFrom, Write};
 use crate::path::{Path, PathBuf};
+use crate::sealed::Sealed;
 use crate::sys::fs as fs_imp;
 use crate::sys_common::{AsInner, AsInnerMut, FromInner, IntoInner};
 use crate::time::SystemTime;
@@ -1391,6 +1392,16 @@ impl FileTimes {
     }
 }
 
+impl AsInnerMut<fs_imp::FileTimes> for FileTimes {
+    fn as_inner_mut(&mut self) -> &mut fs_imp::FileTimes {
+        &mut self.0
+    }
+}
+
+// For implementing OS extension traits in `std::os`
+#[unstable(feature = "file_set_times", issue = "98245")]
+impl Sealed for FileTimes {}
+
 impl Permissions {
     /// Returns `true` if these permissions describe a readonly (unwritable) file.
     ///
@@ -1946,7 +1957,7 @@ pub fn rename<P: AsRef<Path>, Q: AsRef<Path>>(from: P, to: Q) -> io::Result<()>
 /// On success, the total number of bytes copied is returned and it is equal to
 /// the length of the `to` file as reported by `metadata`.
 ///
-/// If you’re wanting to copy the contents of one file to another and you’re
+/// If you want to copy the contents of one file to another and you’re
 /// working with [`File`]s, see the [`io::copy()`] function.
 ///
 /// # Platform-specific behavior
diff --git a/library/std/src/fs/tests.rs b/library/std/src/fs/tests.rs
index a8a0b9f122d..e2480bcbbc7 100644
--- a/library/std/src/fs/tests.rs
+++ b/library/std/src/fs/tests.rs
@@ -1,7 +1,7 @@
 use crate::io::prelude::*;
 
 use crate::env;
-use crate::fs::{self, File, OpenOptions};
+use crate::fs::{self, File, FileTimes, OpenOptions};
 use crate::io::{BorrowedBuf, ErrorKind, SeekFrom};
 use crate::mem::MaybeUninit;
 use crate::path::Path;
@@ -9,7 +9,7 @@ use crate::str;
 use crate::sync::Arc;
 use crate::sys_common::io::test::{tmpdir, TempDir};
 use crate::thread;
-use crate::time::{Duration, Instant};
+use crate::time::{Duration, Instant, SystemTime};
 
 use rand::RngCore;
 
@@ -1633,3 +1633,53 @@ fn rename_directory() {
     assert!(new_path.join("newdir").is_dir());
     assert!(new_path.join("newdir/temp.txt").exists());
 }
+
+#[test]
+fn test_file_times() {
+    #[cfg(target_os = "ios")]
+    use crate::os::ios::fs::FileTimesExt;
+    #[cfg(target_os = "macos")]
+    use crate::os::macos::fs::FileTimesExt;
+    #[cfg(target_os = "watchos")]
+    use crate::os::watchos::fs::FileTimesExt;
+    #[cfg(windows)]
+    use crate::os::windows::fs::FileTimesExt;
+
+    let tmp = tmpdir();
+    let file = File::create(tmp.join("foo")).unwrap();
+    let mut times = FileTimes::new();
+    let accessed = SystemTime::UNIX_EPOCH + Duration::from_secs(12345);
+    let modified = SystemTime::UNIX_EPOCH + Duration::from_secs(54321);
+    times = times.set_accessed(accessed).set_modified(modified);
+    #[cfg(any(windows, target_os = "macos", target_os = "ios", target_os = "watchos"))]
+    let created = SystemTime::UNIX_EPOCH + Duration::from_secs(32123);
+    #[cfg(any(windows, target_os = "macos", target_os = "ios", target_os = "watchos"))]
+    {
+        times = times.set_created(created);
+    }
+    match file.set_times(times) {
+        // Allow unsupported errors on platforms which don't support setting times.
+        #[cfg(not(any(
+            windows,
+            all(
+                unix,
+                not(any(
+                    target_os = "android",
+                    target_os = "redox",
+                    target_os = "espidf",
+                    target_os = "horizon"
+                ))
+            )
+        )))]
+        Err(e) if e.kind() == ErrorKind::Unsupported => return,
+        Err(e) => panic!("error setting file times: {e:?}"),
+        Ok(_) => {}
+    }
+    let metadata = file.metadata().unwrap();
+    assert_eq!(metadata.accessed().unwrap(), accessed);
+    assert_eq!(metadata.modified().unwrap(), modified);
+    #[cfg(any(windows, target_os = "macos", target_os = "ios", target_os = "watchos"))]
+    {
+        assert_eq!(metadata.created().unwrap(), created);
+    }
+}
diff --git a/library/std/src/io/copy.rs b/library/std/src/io/copy.rs
index 38b98afffa1..1d9d93f5b64 100644
--- a/library/std/src/io/copy.rs
+++ b/library/std/src/io/copy.rs
@@ -10,7 +10,7 @@ use crate::mem::MaybeUninit;
 /// On success, the total number of bytes that were copied from
 /// `reader` to `writer` is returned.
 ///
-/// If you’re wanting to copy the contents of one file to another and you’re
+/// If you want to copy the contents of one file to another and you’re
 /// working with filesystem paths, see the [`fs::copy`] function.
 ///
 /// [`fs::copy`]: crate::fs::copy
diff --git a/library/std/src/net/tcp.rs b/library/std/src/net/tcp.rs
index 541e95d229b..141a18a42dd 100644
--- a/library/std/src/net/tcp.rs
+++ b/library/std/src/net/tcp.rs
@@ -756,6 +756,15 @@ impl TcpListener {
     /// ];
     /// let listener = TcpListener::bind(&addrs[..]).unwrap();
     /// ```
+    ///
+    /// Creates a TCP listener bound to a port assigned by the operating system
+    /// at `127.0.0.1`.
+    ///
+    /// ```no_run
+    /// use std::net::TcpListener;
+    ///
+    /// let socket = TcpListener::bind("127.0.0.1:0").unwrap();
+    /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn bind<A: ToSocketAddrs>(addr: A) -> io::Result<TcpListener> {
         super::each_addr(addr, net_imp::TcpListener::bind).map(TcpListener)
diff --git a/library/std/src/net/udp.rs b/library/std/src/net/udp.rs
index 9628bcc5108..5ca4ed832f3 100644
--- a/library/std/src/net/udp.rs
+++ b/library/std/src/net/udp.rs
@@ -90,6 +90,15 @@ impl UdpSocket {
     /// ];
     /// let socket = UdpSocket::bind(&addrs[..]).expect("couldn't bind to address");
     /// ```
+    ///
+    /// Creates a UDP socket bound to a port assigned by the operating system
+    /// at `127.0.0.1`.
+    ///
+    /// ```no_run
+    /// use std::net::UdpSocket;
+    ///
+    /// let socket = UdpSocket::bind("127.0.0.1:0").unwrap();
+    /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn bind<A: ToSocketAddrs>(addr: A) -> io::Result<UdpSocket> {
         super::each_addr(addr, net_imp::UdpSocket::bind).map(UdpSocket)
diff --git a/library/std/src/os/ios/fs.rs b/library/std/src/os/ios/fs.rs
index 4a4637ce072..6d4d54b7c78 100644
--- a/library/std/src/os/ios/fs.rs
+++ b/library/std/src/os/ios/fs.rs
@@ -1,7 +1,9 @@
 #![stable(feature = "metadata_ext", since = "1.1.0")]
 
-use crate::fs::Metadata;
-use crate::sys_common::AsInner;
+use crate::fs::{self, Metadata};
+use crate::sealed::Sealed;
+use crate::sys_common::{AsInner, AsInnerMut, IntoInner};
+use crate::time::SystemTime;
 
 #[allow(deprecated)]
 use crate::os::ios::raw;
@@ -140,3 +142,19 @@ impl MetadataExt for Metadata {
         self.as_inner().as_inner().st_lspare as u32
     }
 }
+
+/// OS-specific extensions to [`fs::FileTimes`].
+#[unstable(feature = "file_set_times", issue = "98245")]
+pub trait FileTimesExt: Sealed {
+    /// Set the creation time of a file.
+    #[unstable(feature = "file_set_times", issue = "98245")]
+    fn set_created(self, t: SystemTime) -> Self;
+}
+
+#[unstable(feature = "file_set_times", issue = "98245")]
+impl FileTimesExt for fs::FileTimes {
+    fn set_created(mut self, t: SystemTime) -> Self {
+        self.as_inner_mut().set_created(t.into_inner());
+        self
+    }
+}
diff --git a/library/std/src/os/macos/fs.rs b/library/std/src/os/macos/fs.rs
index 91915da6a43..fe82d03d869 100644
--- a/library/std/src/os/macos/fs.rs
+++ b/library/std/src/os/macos/fs.rs
@@ -1,7 +1,9 @@
 #![stable(feature = "metadata_ext", since = "1.1.0")]
 
-use crate::fs::Metadata;
-use crate::sys_common::AsInner;
+use crate::fs::{self, Metadata};
+use crate::sealed::Sealed;
+use crate::sys_common::{AsInner, AsInnerMut, IntoInner};
+use crate::time::SystemTime;
 
 #[allow(deprecated)]
 use crate::os::macos::raw;
@@ -146,3 +148,19 @@ impl MetadataExt for Metadata {
         [qspare[0] as u64, qspare[1] as u64]
     }
 }
+
+/// OS-specific extensions to [`fs::FileTimes`].
+#[unstable(feature = "file_set_times", issue = "98245")]
+pub trait FileTimesExt: Sealed {
+    /// Set the creation time of a file.
+    #[unstable(feature = "file_set_times", issue = "98245")]
+    fn set_created(self, t: SystemTime) -> Self;
+}
+
+#[unstable(feature = "file_set_times", issue = "98245")]
+impl FileTimesExt for fs::FileTimes {
+    fn set_created(mut self, t: SystemTime) -> Self {
+        self.as_inner_mut().set_created(t.into_inner());
+        self
+    }
+}
diff --git a/library/std/src/os/watchos/fs.rs b/library/std/src/os/watchos/fs.rs
index a14fe35a77c..2ecc4c68a96 100644
--- a/library/std/src/os/watchos/fs.rs
+++ b/library/std/src/os/watchos/fs.rs
@@ -1,7 +1,9 @@
 #![stable(feature = "metadata_ext", since = "1.1.0")]
 
-use crate::fs::Metadata;
-use crate::sys_common::AsInner;
+use crate::fs::{self, Metadata};
+use crate::sealed::Sealed;
+use crate::sys_common::{AsInner, AsInnerMut, IntoInner};
+use crate::time::SystemTime;
 
 #[allow(deprecated)]
 use crate::os::watchos::raw;
@@ -140,3 +142,19 @@ impl MetadataExt for Metadata {
         self.as_inner().as_inner().st_lspare as u32
     }
 }
+
+/// OS-specific extensions to [`fs::FileTimes`].
+#[unstable(feature = "file_set_times", issue = "98245")]
+pub trait FileTimesExt: Sealed {
+    /// Set the creation time of a file.
+    #[unstable(feature = "file_set_times", issue = "98245")]
+    fn set_created(self, t: SystemTime) -> Self;
+}
+
+#[unstable(feature = "file_set_times", issue = "98245")]
+impl FileTimesExt for fs::FileTimes {
+    fn set_created(mut self, t: SystemTime) -> Self {
+        self.as_inner_mut().set_created(t.into_inner());
+        self
+    }
+}
diff --git a/library/std/src/os/windows/fs.rs b/library/std/src/os/windows/fs.rs
index a091f06dd53..94509e54796 100644
--- a/library/std/src/os/windows/fs.rs
+++ b/library/std/src/os/windows/fs.rs
@@ -9,7 +9,8 @@ use crate::io;
 use crate::path::Path;
 use crate::sealed::Sealed;
 use crate::sys;
-use crate::sys_common::{AsInner, AsInnerMut};
+use crate::sys_common::{AsInner, AsInnerMut, IntoInner};
+use crate::time::SystemTime;
 
 /// Windows-specific extensions to [`fs::File`].
 #[stable(feature = "file_offset", since = "1.15.0")]
@@ -526,6 +527,22 @@ impl FileTypeExt for fs::FileType {
     }
 }
 
+/// Windows-specific extensions to [`fs::FileTimes`].
+#[unstable(feature = "file_set_times", issue = "98245")]
+pub trait FileTimesExt: Sealed {
+    /// Set the creation time of a file.
+    #[unstable(feature = "file_set_times", issue = "98245")]
+    fn set_created(self, t: SystemTime) -> Self;
+}
+
+#[unstable(feature = "file_set_times", issue = "98245")]
+impl FileTimesExt for fs::FileTimes {
+    fn set_created(mut self, t: SystemTime) -> Self {
+        self.as_inner_mut().set_created(t.into_inner());
+        self
+    }
+}
+
 /// Creates a new symlink to a non-directory file on the filesystem.
 ///
 /// The `link` path will be a file symbolic link pointing to the `original`
diff --git a/library/std/src/os/windows/io/handle.rs b/library/std/src/os/windows/io/handle.rs
index 280757a41a2..cbf8209a5ad 100644
--- a/library/std/src/os/windows/io/handle.rs
+++ b/library/std/src/os/windows/io/handle.rs
@@ -437,6 +437,42 @@ impl<T: AsHandle> AsHandle for &mut T {
     }
 }
 
+#[stable(feature = "as_windows_ptrs", since = "CURRENT_RUSTC_VERSION")]
+/// This impl allows implementing traits that require `AsHandle` on Arc.
+/// ```
+/// # #[cfg(windows)] mod group_cfg {
+/// # use std::os::windows::io::AsHandle;
+/// use std::fs::File;
+/// use std::sync::Arc;
+///
+/// trait MyTrait: AsHandle {}
+/// impl MyTrait for Arc<File> {}
+/// impl MyTrait for Box<File> {}
+/// # }
+/// ```
+impl<T: AsHandle> AsHandle for crate::sync::Arc<T> {
+    #[inline]
+    fn as_handle(&self) -> BorrowedHandle<'_> {
+        (**self).as_handle()
+    }
+}
+
+#[stable(feature = "as_windows_ptrs", since = "CURRENT_RUSTC_VERSION")]
+impl<T: AsHandle> AsHandle for crate::rc::Rc<T> {
+    #[inline]
+    fn as_handle(&self) -> BorrowedHandle<'_> {
+        (**self).as_handle()
+    }
+}
+
+#[stable(feature = "as_windows_ptrs", since = "CURRENT_RUSTC_VERSION")]
+impl<T: AsHandle> AsHandle for Box<T> {
+    #[inline]
+    fn as_handle(&self) -> BorrowedHandle<'_> {
+        (**self).as_handle()
+    }
+}
+
 #[stable(feature = "io_safety", since = "1.63.0")]
 impl AsHandle for BorrowedHandle<'_> {
     #[inline]
diff --git a/library/std/src/os/windows/io/socket.rs b/library/std/src/os/windows/io/socket.rs
index eb6097a89a6..0c90d55c024 100644
--- a/library/std/src/os/windows/io/socket.rs
+++ b/library/std/src/os/windows/io/socket.rs
@@ -254,6 +254,42 @@ impl<T: AsSocket> AsSocket for &mut T {
     }
 }
 
+#[stable(feature = "as_windows_ptrs", since = "CURRENT_RUSTC_VERSION")]
+/// This impl allows implementing traits that require `AsSocket` on Arc.
+/// ```
+/// # #[cfg(windows)] mod group_cfg {
+/// # use std::os::windows::io::AsSocket;
+/// use std::net::UdpSocket;
+/// use std::sync::Arc;
+///
+/// trait MyTrait: AsSocket {}
+/// impl MyTrait for Arc<UdpSocket> {}
+/// impl MyTrait for Box<UdpSocket> {}
+/// # }
+/// ```
+impl<T: AsSocket> AsSocket for crate::sync::Arc<T> {
+    #[inline]
+    fn as_socket(&self) -> BorrowedSocket<'_> {
+        (**self).as_socket()
+    }
+}
+
+#[stable(feature = "as_windows_ptrs", since = "CURRENT_RUSTC_VERSION")]
+impl<T: AsSocket> AsSocket for crate::rc::Rc<T> {
+    #[inline]
+    fn as_socket(&self) -> BorrowedSocket<'_> {
+        (**self).as_socket()
+    }
+}
+
+#[stable(feature = "as_windows_ptrs", since = "CURRENT_RUSTC_VERSION")]
+impl<T: AsSocket> AsSocket for Box<T> {
+    #[inline]
+    fn as_socket(&self) -> BorrowedSocket<'_> {
+        (**self).as_socket()
+    }
+}
+
 #[stable(feature = "io_safety", since = "1.63.0")]
 impl AsSocket for BorrowedSocket<'_> {
     #[inline]
diff --git a/library/std/src/panic.rs b/library/std/src/panic.rs
index 345d72ef867..69a6f3e6d5a 100644
--- a/library/std/src/panic.rs
+++ b/library/std/src/panic.rs
@@ -19,14 +19,16 @@ pub macro panic_2015 {
         $crate::rt::begin_panic("explicit panic")
     }),
     ($msg:expr $(,)?) => ({
-        $crate::rt::begin_panic($msg)
+        $crate::rt::begin_panic($msg);
     }),
     // Special-case the single-argument case for const_panic.
     ("{}", $arg:expr $(,)?) => ({
-        $crate::rt::panic_display(&$arg)
+        $crate::rt::panic_display(&$arg);
     }),
     ($fmt:expr, $($arg:tt)+) => ({
-        $crate::rt::panic_fmt($crate::const_format_args!($fmt, $($arg)+))
+        // Semicolon to prevent temporaries inside the formatting machinery from
+        // being considered alive in the caller after the panic_fmt call.
+        $crate::rt::panic_fmt($crate::const_format_args!($fmt, $($arg)+));
     }),
 }
 
diff --git a/library/std/src/panicking.rs b/library/std/src/panicking.rs
index a46a29cbad6..6d59266b6f8 100644
--- a/library/std/src/panicking.rs
+++ b/library/std/src/panicking.rs
@@ -541,7 +541,7 @@ pub fn begin_panic_handler(info: &PanicInfo<'_>) -> ! {
             // Lazily, the first time this gets called, run the actual string formatting.
             self.string.get_or_insert_with(|| {
                 let mut s = String::new();
-                drop(s.write_fmt(*inner));
+                let _err = s.write_fmt(*inner);
                 s
             })
         }
diff --git a/library/std/src/path.rs b/library/std/src/path.rs
index 43203c5824d..febdeb51463 100644
--- a/library/std/src/path.rs
+++ b/library/std/src/path.rs
@@ -733,8 +733,9 @@ impl<'a> Components<'a> {
         }
     }
 
-    // parse a given byte sequence into the corresponding path component
-    fn parse_single_component<'b>(&self, comp: &'b [u8]) -> Option<Component<'b>> {
+    // parse a given byte sequence following the OsStr encoding into the
+    // corresponding path component
+    unsafe fn parse_single_component<'b>(&self, comp: &'b [u8]) -> Option<Component<'b>> {
         match comp {
             b"." if self.prefix_verbatim() => Some(Component::CurDir),
             b"." => None, // . components are normalized away, except at
@@ -754,7 +755,8 @@ impl<'a> Components<'a> {
             None => (0, self.path),
             Some(i) => (1, &self.path[..i]),
         };
-        (comp.len() + extra, self.parse_single_component(comp))
+        // SAFETY: `comp` is a valid substring, since it is split on a separator.
+        (comp.len() + extra, unsafe { self.parse_single_component(comp) })
     }
 
     // parse a component from the right, saying how many bytes to consume to
@@ -766,7 +768,8 @@ impl<'a> Components<'a> {
             None => (0, &self.path[start..]),
             Some(i) => (1, &self.path[start + i + 1..]),
         };
-        (comp.len() + extra, self.parse_single_component(comp))
+        // SAFETY: `comp` is a valid substring, since it is split on a separator.
+        (comp.len() + extra, unsafe { self.parse_single_component(comp) })
     }
 
     // trim away repeated separators (i.e., empty components) on the left
diff --git a/library/std/src/sync/mpmc/error.rs b/library/std/src/sync/mpmc/error.rs
index 1b8a1f38797..33b2bff8534 100644
--- a/library/std/src/sync/mpmc/error.rs
+++ b/library/std/src/sync/mpmc/error.rs
@@ -35,7 +35,7 @@ impl<T> fmt::Display for SendTimeoutError<T> {
     }
 }
 
-impl<T: Send> error::Error for SendTimeoutError<T> {}
+impl<T> error::Error for SendTimeoutError<T> {}
 
 impl<T> From<SendError<T>> for SendTimeoutError<T> {
     fn from(err: SendError<T>) -> SendTimeoutError<T> {
diff --git a/library/std/src/sync/mpsc/mod.rs b/library/std/src/sync/mpsc/mod.rs
index 6e3c28f10bb..0e0c87d1c74 100644
--- a/library/std/src/sync/mpsc/mod.rs
+++ b/library/std/src/sync/mpsc/mod.rs
@@ -1124,7 +1124,7 @@ impl<T> fmt::Display for SendError<T> {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<T: Send> error::Error for SendError<T> {
+impl<T> error::Error for SendError<T> {
     #[allow(deprecated)]
     fn description(&self) -> &str {
         "sending on a closed channel"
@@ -1152,7 +1152,7 @@ impl<T> fmt::Display for TrySendError<T> {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<T: Send> error::Error for TrySendError<T> {
+impl<T> error::Error for TrySendError<T> {
     #[allow(deprecated)]
     fn description(&self) -> &str {
         match *self {
diff --git a/library/std/src/sys/sgx/waitqueue/mod.rs b/library/std/src/sys/sgx/waitqueue/mod.rs
index 61bb11d9a6f..5e1d859ee99 100644
--- a/library/std/src/sys/sgx/waitqueue/mod.rs
+++ b/library/std/src/sys/sgx/waitqueue/mod.rs
@@ -202,12 +202,18 @@ impl WaitQueue {
     pub fn notify_one<T>(
         mut guard: SpinMutexGuard<'_, WaitVariable<T>>,
     ) -> Result<WaitGuard<'_, T>, SpinMutexGuard<'_, WaitVariable<T>>> {
+        // SAFETY: lifetime of the pop() return value is limited to the map
+        // closure (The closure return value is 'static). The underlying
+        // stack frame won't be freed until after the WaitGuard created below
+        // is dropped.
         unsafe {
-            if let Some(entry) = guard.queue.inner.pop() {
+            let tcs = guard.queue.inner.pop().map(|entry| -> Tcs {
                 let mut entry_guard = entry.lock();
-                let tcs = entry_guard.tcs;
                 entry_guard.wake = true;
-                drop(entry);
+                entry_guard.tcs
+            });
+
+            if let Some(tcs) = tcs {
                 Ok(WaitGuard { mutex_guard: Some(guard), notified_tcs: NotifiedTcs::Single(tcs) })
             } else {
                 Err(guard)
@@ -223,6 +229,9 @@ impl WaitQueue {
     pub fn notify_all<T>(
         mut guard: SpinMutexGuard<'_, WaitVariable<T>>,
     ) -> Result<WaitGuard<'_, T>, SpinMutexGuard<'_, WaitVariable<T>>> {
+        // SAFETY: lifetime of the pop() return values are limited to the
+        // while loop body. The underlying stack frames won't be freed until
+        // after the WaitGuard created below is dropped.
         unsafe {
             let mut count = 0;
             while let Some(entry) = guard.queue.inner.pop() {
@@ -230,6 +239,7 @@ impl WaitQueue {
                 let mut entry_guard = entry.lock();
                 entry_guard.wake = true;
             }
+
             if let Some(count) = NonZeroUsize::new(count) {
                 Ok(WaitGuard { mutex_guard: Some(guard), notified_tcs: NotifiedTcs::All { count } })
             } else {
diff --git a/library/std/src/sys/unix/fs.rs b/library/std/src/sys/unix/fs.rs
index 22d2ae39713..09e9ae2720f 100644
--- a/library/std/src/sys/unix/fs.rs
+++ b/library/std/src/sys/unix/fs.rs
@@ -349,6 +349,8 @@ pub struct FilePermissions {
 pub struct FileTimes {
     accessed: Option<SystemTime>,
     modified: Option<SystemTime>,
+    #[cfg(any(target_os = "macos", target_os = "ios", target_os = "watchos"))]
+    created: Option<SystemTime>,
 }
 
 #[derive(Copy, Clone, Eq, Debug)]
@@ -591,6 +593,11 @@ impl FileTimes {
     pub fn set_modified(&mut self, t: SystemTime) {
         self.modified = Some(t);
     }
+
+    #[cfg(any(target_os = "macos", target_os = "ios", target_os = "watchos"))]
+    pub fn set_created(&mut self, t: SystemTime) {
+        self.created = Some(t);
+    }
 }
 
 impl FileType {
@@ -1210,31 +1217,46 @@ impl File {
                 // Redox doesn't appear to support `UTIME_OMIT`.
                 // ESP-IDF and HorizonOS do not support `futimens` at all and the behavior for those OS is therefore
                 // the same as for Redox.
-                drop(times);
+                let _ = times;
                 Err(io::const_io_error!(
                     io::ErrorKind::Unsupported,
                     "setting file times not supported",
                 ))
-            } else if #[cfg(any(target_os = "android", target_os = "macos"))] {
+            } else if #[cfg(any(target_os = "macos", target_os = "ios", target_os = "watchos"))] {
+                let mut buf = [mem::MaybeUninit::<libc::timespec>::uninit(); 3];
+                let mut num_times = 0;
+                let mut attrlist: libc::attrlist = unsafe { mem::zeroed() };
+                attrlist.bitmapcount = libc::ATTR_BIT_MAP_COUNT;
+                if times.created.is_some() {
+                    buf[num_times].write(to_timespec(times.created)?);
+                    num_times += 1;
+                    attrlist.commonattr |= libc::ATTR_CMN_CRTIME;
+                }
+                if times.modified.is_some() {
+                    buf[num_times].write(to_timespec(times.modified)?);
+                    num_times += 1;
+                    attrlist.commonattr |= libc::ATTR_CMN_MODTIME;
+                }
+                if times.accessed.is_some() {
+                    buf[num_times].write(to_timespec(times.accessed)?);
+                    num_times += 1;
+                    attrlist.commonattr |= libc::ATTR_CMN_ACCTIME;
+                }
+                cvt(unsafe { libc::fsetattrlist(
+                    self.as_raw_fd(),
+                    (&attrlist as *const libc::attrlist).cast::<libc::c_void>().cast_mut(),
+                    buf.as_ptr().cast::<libc::c_void>().cast_mut(),
+                    num_times * mem::size_of::<libc::timespec>(),
+                    0
+                ) })?;
+                Ok(())
+            } else if #[cfg(target_os = "android")] {
                 let times = [to_timespec(times.accessed)?, to_timespec(times.modified)?];
-                // futimens requires macOS 10.13, and Android API level 19
+                // futimens requires Android API level 19
                 cvt(unsafe {
                     weak!(fn futimens(c_int, *const libc::timespec) -> c_int);
                     match futimens.get() {
                         Some(futimens) => futimens(self.as_raw_fd(), times.as_ptr()),
-                        #[cfg(target_os = "macos")]
-                        None => {
-                            fn ts_to_tv(ts: &libc::timespec) -> libc::timeval {
-                                libc::timeval {
-                                    tv_sec: ts.tv_sec,
-                                    tv_usec: (ts.tv_nsec / 1000) as _
-                                }
-                            }
-                            let timevals = [ts_to_tv(&times[0]), ts_to_tv(&times[1])];
-                            libc::futimes(self.as_raw_fd(), timevals.as_ptr())
-                        }
-                        // futimes requires even newer Android.
-                        #[cfg(target_os = "android")]
                         None => return Err(io::const_io_error!(
                             io::ErrorKind::Unsupported,
                             "setting file times requires Android API level >= 19",
diff --git a/library/std/src/sys/windows/fs.rs b/library/std/src/sys/windows/fs.rs
index ce427766d17..21a65bc25f3 100644
--- a/library/std/src/sys/windows/fs.rs
+++ b/library/std/src/sys/windows/fs.rs
@@ -88,8 +88,10 @@ pub struct FilePermissions {
 pub struct FileTimes {
     accessed: Option<c::FILETIME>,
     modified: Option<c::FILETIME>,
+    created: Option<c::FILETIME>,
 }
-impl core::fmt::Debug for c::FILETIME {
+
+impl fmt::Debug for c::FILETIME {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         let time = ((self.dwHighDateTime as u64) << 32) | self.dwLowDateTime as u64;
         f.debug_tuple("FILETIME").field(&time).finish()
@@ -582,7 +584,10 @@ impl File {
 
     pub fn set_times(&self, times: FileTimes) -> io::Result<()> {
         let is_zero = |t: c::FILETIME| t.dwLowDateTime == 0 && t.dwHighDateTime == 0;
-        if times.accessed.map_or(false, is_zero) || times.modified.map_or(false, is_zero) {
+        if times.accessed.map_or(false, is_zero)
+            || times.modified.map_or(false, is_zero)
+            || times.created.map_or(false, is_zero)
+        {
             return Err(io::const_io_error!(
                 io::ErrorKind::InvalidInput,
                 "Cannot set file timestamp to 0",
@@ -590,18 +595,23 @@ impl File {
         }
         let is_max =
             |t: c::FILETIME| t.dwLowDateTime == c::DWORD::MAX && t.dwHighDateTime == c::DWORD::MAX;
-        if times.accessed.map_or(false, is_max) || times.modified.map_or(false, is_max) {
+        if times.accessed.map_or(false, is_max)
+            || times.modified.map_or(false, is_max)
+            || times.created.map_or(false, is_max)
+        {
             return Err(io::const_io_error!(
                 io::ErrorKind::InvalidInput,
                 "Cannot set file timestamp to 0xFFFF_FFFF_FFFF_FFFF",
             ));
         }
         cvt(unsafe {
+            let created =
+                times.created.as_ref().map(|a| a as *const c::FILETIME).unwrap_or(ptr::null());
             let accessed =
                 times.accessed.as_ref().map(|a| a as *const c::FILETIME).unwrap_or(ptr::null());
             let modified =
                 times.modified.as_ref().map(|a| a as *const c::FILETIME).unwrap_or(ptr::null());
-            c::SetFileTime(self.as_raw_handle(), ptr::null_mut(), accessed, modified)
+            c::SetFileTime(self.as_raw_handle(), created, accessed, modified)
         })?;
         Ok(())
     }
@@ -1005,6 +1015,10 @@ impl FileTimes {
     pub fn set_modified(&mut self, t: SystemTime) {
         self.modified = Some(t.into_inner());
     }
+
+    pub fn set_created(&mut self, t: SystemTime) {
+        self.created = Some(t.into_inner());
+    }
 }
 
 impl FileType {
diff --git a/library/std/src/sys_common/backtrace.rs b/library/std/src/sys_common/backtrace.rs
index 8752f46ff81..6f020940df1 100644
--- a/library/std/src/sys_common/backtrace.rs
+++ b/library/std/src/sys_common/backtrace.rs
@@ -68,13 +68,17 @@ unsafe fn _print_fmt(fmt: &mut fmt::Formatter<'_>, print_fmt: PrintFmt) -> fmt::
         }
 
         let mut hit = false;
-        let mut stop = false;
         backtrace_rs::resolve_frame_unsynchronized(frame, |symbol| {
             hit = true;
+
+            // Any frames between `__rust_begin_short_backtrace` and `__rust_end_short_backtrace`
+            // are omitted from the backtrace in short mode, `__rust_end_short_backtrace` will be
+            // called before the panic hook, so we won't ignore any frames if there is no
+            // invoke of `__rust_begin_short_backtrace`.
             if print_fmt == PrintFmt::Short {
                 if let Some(sym) = symbol.name().and_then(|s| s.as_str()) {
                     if start && sym.contains("__rust_begin_short_backtrace") {
-                        stop = true;
+                        start = false;
                         return;
                     }
                     if sym.contains("__rust_end_short_backtrace") {
@@ -88,9 +92,6 @@ unsafe fn _print_fmt(fmt: &mut fmt::Formatter<'_>, print_fmt: PrintFmt) -> fmt::
                 res = bt_fmt.frame().symbol(frame, symbol);
             }
         });
-        if stop {
-            return false;
-        }
         #[cfg(target_os = "nto")]
         if libc::__my_thread_exit as *mut libc::c_void == frame.ip() {
             if !hit && start {
diff --git a/library/std/src/thread/local.rs b/library/std/src/thread/local.rs
index 3b7c31826b9..1b86d898cc7 100644
--- a/library/std/src/thread/local.rs
+++ b/library/std/src/thread/local.rs
@@ -18,8 +18,8 @@ use crate::fmt;
 /// target platform. It is instantiated with the [`thread_local!`] macro and the
 /// primary method is the [`with`] method.
 ///
-/// The [`with`] method yields a reference to the contained value which cannot be
-/// sent across threads or escape the given closure.
+/// The [`with`] method yields a reference to the contained value which cannot
+/// outlive the current thread or escape the given closure.
 ///
 /// [`thread_local!`]: crate::thread_local
 ///
diff --git a/library/std/src/thread/tests.rs b/library/std/src/thread/tests.rs
index 6c9ce6fa0dd..b65e2572cc5 100644
--- a/library/std/src/thread/tests.rs
+++ b/library/std/src/thread/tests.rs
@@ -375,7 +375,9 @@ fn test_scoped_threads_nll() {
     // this is mostly a *compilation test* for this exact function:
     fn foo(x: &u8) {
         thread::scope(|s| {
-            s.spawn(|| drop(x));
+            s.spawn(|| match x {
+                _ => (),
+            });
         });
     }
     // let's also run it for good measure
diff --git a/src/bootstrap/Cargo.lock b/src/bootstrap/Cargo.lock
index dfe6bb7f057..8f8778efee7 100644
--- a/src/bootstrap/Cargo.lock
+++ b/src/bootstrap/Cargo.lock
@@ -45,6 +45,7 @@ dependencies = [
  "build_helper",
  "cc",
  "clap",
+ "clap_complete",
  "cmake",
  "fd-lock",
  "filetime",
@@ -57,6 +58,7 @@ dependencies = [
  "once_cell",
  "opener",
  "pretty_assertions",
+ "semver",
  "serde",
  "serde_derive",
  "serde_json",
@@ -120,6 +122,15 @@ dependencies = [
 ]
 
 [[package]]
+name = "clap_complete"
+version = "4.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "36774babb166352bb4f7b9cb16f781ffa3439d2a8f12cd31bea85a38c888fea3"
+dependencies = [
+ "clap",
+]
+
+[[package]]
 name = "clap_derive"
 version = "4.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -128,7 +139,7 @@ dependencies = [
  "heck",
  "proc-macro2",
  "quote",
- "syn 2.0.15",
+ "syn 2.0.8",
 ]
 
 [[package]]
@@ -477,9 +488,9 @@ dependencies = [
 
 [[package]]
 name = "object"
-version = "0.29.0"
+version = "0.31.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "21158b2c33aa6d4561f1c0a6ea283ca92bc54802a93b263e910746d679a7eb53"
+checksum = "8bda667d9f2b5051b8833f59f3bf748b28ef54f850f4fcb389a252aa383866d1"
 dependencies = [
  "memchr",
 ]
@@ -636,20 +647,26 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
 
 [[package]]
+name = "semver"
+version = "1.0.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bebd363326d05ec3e2f532ab7660680f3b02130d780c299bca73469d521bc0ed"
+
+[[package]]
 name = "serde"
-version = "1.0.137"
+version = "1.0.160"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "61ea8d54c77f8315140a05f4c7237403bf38b72704d031543aa1d16abbf517d1"
+checksum = "bb2f3770c8bce3bcda7e149193a069a0f4365bda1fa5cd88e03bca26afc1216c"
 
 [[package]]
 name = "serde_derive"
-version = "1.0.137"
+version = "1.0.160"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1f26faba0c3959972377d3b2d306ee9f71faee9714294e41bb777f83f88578be"
+checksum = "291a097c63d8497e00160b166a967a4a79c64f3facdd01cbd7502231688d77df"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 1.0.102",
+ "syn 2.0.8",
 ]
 
 [[package]]
@@ -687,9 +704,9 @@ dependencies = [
 
 [[package]]
 name = "syn"
-version = "2.0.15"
+version = "2.0.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a34fcf3e8b60f57e6a14301a2e916d323af98b0ea63c599441eec8558660c822"
+checksum = "bcc02725fd69ab9f26eab07fad303e2497fad6fb9eba4f96c4d1687bdf704ad9"
 dependencies = [
  "proc-macro2",
  "quote",
diff --git a/src/bootstrap/Cargo.toml b/src/bootstrap/Cargo.toml
index fd5eb740630..367c6190967 100644
--- a/src/bootstrap/Cargo.toml
+++ b/src/bootstrap/Cargo.toml
@@ -37,7 +37,7 @@ filetime = "0.2"
 cc = "1.0.69"
 libc = "0.2"
 hex = "0.4"
-object = { version = "0.29.0", default-features = false, features = ["archive", "coff", "read_core", "unaligned"] }
+object = { version = "0.31.1", default-features = false, features = ["archive", "coff", "read_core", "unaligned"] }
 serde = "1.0.137"
 # Directly use serde_derive rather than through the derive feature of serde to allow building both
 # in parallel and to allow serde_json and toml to start building as soon as serde has been built.
@@ -56,6 +56,8 @@ walkdir = "2"
 # Dependencies needed by the build-metrics feature
 sysinfo = { version = "0.26.0", optional = true }
 clap = { version = "4.2.4", default-features = false, features = ["std", "usage", "help", "derive", "error-context"] }
+clap_complete = "4.2.2"
+semver = "1.0.17"
 
 # Solaris doesn't support flock() and thus fd-lock is not option now
 [target.'cfg(not(target_os = "solaris"))'.dependencies]
diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py
index f22cdad7df4..50ace987193 100644
--- a/src/bootstrap/bootstrap.py
+++ b/src/bootstrap/bootstrap.py
@@ -109,7 +109,7 @@ def _download(path, url, probably_big, verbose, exception):
                 "-L", # Follow redirect.
                 "-y", "30", "-Y", "10",    # timeout if speed is < 10 bytes/sec for > 30 seconds
                 "--connect-timeout", "30",  # timeout if cannot connect within 30 seconds
-                "--retry", "3", "-Sf", url],
+                "--retry", "3", "-SRf", url],
                 stdout=outfile,    #Implements cli redirect operator '>'
                 verbose=verbose,
                 exception=True, # Will raise RuntimeError on failure
diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs
index 237f65b039f..cf7c6596c02 100644
--- a/src/bootstrap/builder.rs
+++ b/src/bootstrap/builder.rs
@@ -839,6 +839,7 @@ impl<'a> Builder<'a> {
                 run::CollectLicenseMetadata,
                 run::GenerateCopyright,
                 run::GenerateWindowsSys,
+                run::GenerateCompletions,
             ),
             Kind::Setup => describe!(setup::Profile, setup::Hook, setup::Link, setup::Vscode),
             Kind::Clean => describe!(clean::CleanAll, clean::Rustc, clean::Std),
@@ -941,7 +942,6 @@ impl<'a> Builder<'a> {
         self.run_step_descriptions(&Builder::get_step_descriptions(Kind::Doc), paths);
     }
 
-    /// NOTE: keep this in sync with `rustdoc::clean::utils::doc_rust_lang_org_channel`, or tests will fail on beta/stable.
     pub fn doc_rust_lang_org_channel(&self) -> String {
         let channel = match &*self.config.channel {
             "stable" => &self.version,
diff --git a/src/bootstrap/builder/tests.rs b/src/bootstrap/builder/tests.rs
index c32fe59bbf0..edca8fe9b13 100644
--- a/src/bootstrap/builder/tests.rs
+++ b/src/bootstrap/builder/tests.rs
@@ -146,6 +146,22 @@ fn alias_and_path_for_library() {
     );
 }
 
+#[test]
+fn test_beta_rev_parsing() {
+    use crate::extract_beta_rev;
+
+    // single digit revision
+    assert_eq!(extract_beta_rev("1.99.9-beta.7 (xxxxxx)"), Some("7".to_string()));
+    // multiple digits
+    assert_eq!(extract_beta_rev("1.99.9-beta.777 (xxxxxx)"), Some("777".to_string()));
+    // nightly channel (no beta revision)
+    assert_eq!(extract_beta_rev("1.99.9-nightly (xxxxxx)"), None);
+    // stable channel (no beta revision)
+    assert_eq!(extract_beta_rev("1.99.9 (xxxxxxx)"), None);
+    // invalid string
+    assert_eq!(extract_beta_rev("invalid"), None);
+}
+
 mod defaults {
     use super::{configure, first, run_build};
     use crate::builder::*;
diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs
index bf3bc3247ac..710c8b52194 100644
--- a/src/bootstrap/config.rs
+++ b/src/bootstrap/config.rs
@@ -24,6 +24,7 @@ pub use crate::flags::Subcommand;
 use crate::flags::{Color, Flags, Warnings};
 use crate::util::{exe, output, t};
 use once_cell::sync::OnceCell;
+use semver::Version;
 use serde::{Deserialize, Deserializer};
 use serde_derive::Deserialize;
 
@@ -1019,6 +1020,7 @@ impl Config {
             config.download_beta_toolchain();
             config.out.join(config.build.triple).join("stage0/bin/rustc")
         });
+
         config.initial_cargo = build
             .cargo
             .map(|cargo| {
@@ -1680,6 +1682,42 @@ impl Config {
         self.rust_codegen_backends.get(0).cloned()
     }
 
+    pub fn check_build_rustc_version(&self) {
+        if self.dry_run() {
+            return;
+        }
+
+        // check rustc version is same or lower with 1 apart from the building one
+        let mut cmd = Command::new(&self.initial_rustc);
+        cmd.arg("--version");
+        let rustc_output = output(&mut cmd)
+            .lines()
+            .next()
+            .unwrap()
+            .split(' ')
+            .nth(1)
+            .unwrap()
+            .split('-')
+            .next()
+            .unwrap()
+            .to_owned();
+        let rustc_version = Version::parse(&rustc_output.trim()).unwrap();
+        let source_version =
+            Version::parse(&fs::read_to_string(self.src.join("src/version")).unwrap().trim())
+                .unwrap();
+        if !(source_version == rustc_version
+            || (source_version.major == rustc_version.major
+                && source_version.minor == rustc_version.minor + 1))
+        {
+            let prev_version = format!("{}.{}.x", source_version.major, source_version.minor - 1);
+            eprintln!(
+                "Unexpected rustc version: {}, we should use {}/{} to build source with {}",
+                rustc_version, prev_version, source_version, source_version
+            );
+            crate::detail_exit(1);
+        }
+    }
+
     /// 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/download.rs b/src/bootstrap/download.rs
index 3e82a381a1b..25df5b2573b 100644
--- a/src/bootstrap/download.rs
+++ b/src/bootstrap/download.rs
@@ -219,7 +219,7 @@ impl Config {
             "30", // timeout if cannot connect within 30 seconds
             "--retry",
             "3",
-            "-Sf",
+            "-SRf",
         ]);
         curl.arg(url);
         let f = File::create(tempfile).unwrap();
diff --git a/src/bootstrap/flags.rs b/src/bootstrap/flags.rs
index c79a1bf9563..d8b298b59a3 100644
--- a/src/bootstrap/flags.rs
+++ b/src/bootstrap/flags.rs
@@ -3,9 +3,9 @@
 //! This module implements the command-line parsing of the build system which
 //! has various flags to configure how it's run.
 
-use std::path::PathBuf;
+use std::path::{Path, PathBuf};
 
-use clap::{Parser, ValueEnum};
+use clap::{CommandFactory, Parser, ValueEnum};
 
 use crate::builder::{Builder, Kind};
 use crate::config::{target_selection_list, Config, TargetSelectionList};
@@ -54,15 +54,15 @@ pub struct Flags {
     /// Build directory, overrides `build.build-dir` in `config.toml`
     pub build_dir: Option<PathBuf>,
 
-    #[arg(global(true), long, value_name = "BUILD")]
+    #[arg(global(true), long, value_hint = clap::ValueHint::Other, value_name = "BUILD")]
     /// build target of the stage0 compiler
     pub build: Option<String>,
 
-    #[arg(global(true), long, value_name = "HOST", value_parser = target_selection_list)]
+    #[arg(global(true), long, value_hint = clap::ValueHint::Other, value_name = "HOST", value_parser = target_selection_list)]
     /// host targets to build
     pub host: Option<TargetSelectionList>,
 
-    #[arg(global(true), long, value_name = "TARGET", value_parser = target_selection_list)]
+    #[arg(global(true), long, value_hint = clap::ValueHint::Other, value_name = "TARGET", value_parser = target_selection_list)]
     /// target targets to build
     pub target: Option<TargetSelectionList>,
 
@@ -73,7 +73,7 @@ pub struct Flags {
     /// include default paths in addition to the provided ones
     pub include_default_paths: bool,
 
-    #[arg(global(true), long)]
+    #[arg(global(true), value_hint = clap::ValueHint::Other, long)]
     pub rustc_error_format: Option<String>,
 
     #[arg(global(true), long, value_hint = clap::ValueHint::CommandString, value_name = "CMD")]
@@ -82,16 +82,16 @@ pub struct Flags {
     #[arg(global(true), long)]
     /// dry run; don't build anything
     pub dry_run: bool,
-    #[arg(global(true), long, value_name = "N")]
+    #[arg(global(true), value_hint = clap::ValueHint::Other, long, value_name = "N")]
     /// stage to build (indicates compiler to use/test, e.g., stage 0 uses the
     /// bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)
     pub stage: Option<u32>,
 
-    #[arg(global(true), long, value_name = "N")]
+    #[arg(global(true), value_hint = clap::ValueHint::Other, long, value_name = "N")]
     /// stage(s) to keep without recompiling
     /// (pass multiple times to keep e.g., both stages 0 and 1)
     pub keep_stage: Vec<u32>,
-    #[arg(global(true), long, value_name = "N")]
+    #[arg(global(true), value_hint = clap::ValueHint::Other, long, value_name = "N")]
     /// stage(s) of the standard library to keep without recompiling
     /// (pass multiple times to keep e.g., both stages 0 and 1)
     pub keep_stage_std: Vec<u32>,
@@ -103,6 +103,7 @@ pub struct Flags {
         global(true),
         short,
         long,
+        value_hint = clap::ValueHint::Other,
         default_value_t = std::thread::available_parallelism().map_or(1, std::num::NonZeroUsize::get),
         value_name = "JOBS"
     )]
@@ -117,7 +118,7 @@ pub struct Flags {
     /// otherwise, use the default configured behaviour
     pub warnings: Warnings,
 
-    #[arg(global(true), long, value_name = "FORMAT")]
+    #[arg(global(true), value_hint = clap::ValueHint::Other, long, value_name = "FORMAT")]
     /// rustc error format
     pub error_format: Option<String>,
     #[arg(global(true), long)]
@@ -133,13 +134,13 @@ pub struct Flags {
     #[arg(global(true), long, value_name = "VALUE")]
     pub llvm_skip_rebuild: Option<bool>,
     /// generate PGO profile with rustc build
-    #[arg(global(true), long, value_name = "PROFILE")]
+    #[arg(global(true), value_hint = clap::ValueHint::FilePath, long, value_name = "PROFILE")]
     pub rust_profile_generate: Option<String>,
     /// use PGO profile for rustc build
-    #[arg(global(true), long, value_name = "PROFILE")]
+    #[arg(global(true), value_hint = clap::ValueHint::FilePath, long, value_name = "PROFILE")]
     pub rust_profile_use: Option<String>,
     /// use PGO profile for LLVM build
-    #[arg(global(true), long, value_name = "PROFILE")]
+    #[arg(global(true), value_hint = clap::ValueHint::FilePath, long, value_name = "PROFILE")]
     pub llvm_profile_use: Option<String>,
     // LLVM doesn't support a custom location for generating profile
     // information.
@@ -152,7 +153,7 @@ pub struct Flags {
     #[arg(global(true), long)]
     pub llvm_bolt_profile_generate: bool,
     /// use BOLT profile for LLVM build
-    #[arg(global(true), long, value_name = "PROFILE")]
+    #[arg(global(true), value_hint = clap::ValueHint::FilePath, long, value_name = "PROFILE")]
     pub llvm_bolt_profile_use: Option<String>,
     #[arg(global(true))]
     /// paths for the subcommand
@@ -364,7 +365,7 @@ pub enum Subcommand {
         #[arg(long)]
         all: bool,
     },
-    /// Duild distribution artifacts
+    /// Build distribution artifacts
     Dist,
     /// Install distribution artifacts
     Install,
@@ -524,3 +525,23 @@ impl Subcommand {
         }
     }
 }
+
+/// Returns the shell completion for a given shell, if the result differs from the current
+/// content of `path`. If `path` does not exist, always returns `Some`.
+pub fn get_completion<G: clap_complete::Generator>(shell: G, path: &Path) -> Option<String> {
+    let mut cmd = Flags::command();
+    let current = if !path.exists() {
+        String::new()
+    } else {
+        std::fs::read_to_string(path).unwrap_or_else(|_| {
+            eprintln!("couldn't read {}", path.display());
+            crate::detail_exit(1)
+        })
+    };
+    let mut buf = Vec::new();
+    clap_complete::generate(shell, &mut cmd, "x.py", &mut buf);
+    if buf == current.as_bytes() {
+        return None;
+    }
+    Some(String::from_utf8(buf).expect("completion script should be UTF-8"))
+}
diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs
index 994336977dc..6ee50ee6573 100644
--- a/src/bootstrap/lib.rs
+++ b/src/bootstrap/lib.rs
@@ -414,6 +414,7 @@ impl Build {
                 bootstrap_out.display()
             )
         }
+        config.check_build_rustc_version();
 
         if rust_info.is_from_tarball() && config.description.is_none() {
             config.description = Some("built from a source tarball".to_owned());
@@ -1323,7 +1324,7 @@ impl Build {
         match &self.config.channel[..] {
             "stable" => num.to_string(),
             "beta" => {
-                if self.rust_info().is_managed_git_subrepository() && !self.config.omit_git_hash {
+                if !self.config.omit_git_hash {
                     format!("{}-beta.{}", num, self.beta_prerelease_version())
                 } else {
                     format!("{}-beta", num)
@@ -1335,18 +1336,28 @@ impl Build {
     }
 
     fn beta_prerelease_version(&self) -> u32 {
+        fn extract_beta_rev_from_file<P: AsRef<Path>>(version_file: P) -> Option<String> {
+            let version = fs::read_to_string(version_file).ok()?;
+
+            extract_beta_rev(&version)
+        }
+
         if let Some(s) = self.prerelease_version.get() {
             return s;
         }
 
-        // Figure out how many merge commits happened since we branched off master.
-        // That's our beta number!
-        // (Note that we use a `..` range, not the `...` symmetric difference.)
-        let count =
+        // First check if there is a version file available.
+        // If available, we read the beta revision from that file.
+        // This only happens when building from a source tarball when Git should not be used.
+        let count = extract_beta_rev_from_file(self.src.join("version")).unwrap_or_else(|| {
+            // Figure out how many merge commits happened since we branched off master.
+            // That's our beta number!
+            // (Note that we use a `..` range, not the `...` symmetric difference.)
             output(self.config.git().arg("rev-list").arg("--count").arg("--merges").arg(format!(
                 "refs/remotes/origin/{}..HEAD",
                 self.config.stage0_metadata.config.nightly_branch
-            )));
+            )))
+        });
         let n = count.trim().parse().unwrap();
         self.prerelease_version.set(Some(n));
         n
@@ -1706,6 +1717,17 @@ to download LLVM rather than building it.
     }
 }
 
+/// Extract the beta revision from the full version string.
+///
+/// The full version string looks like "a.b.c-beta.y". And we need to extract
+/// the "y" part from the string.
+pub fn extract_beta_rev(version: &str) -> Option<String> {
+    let parts = version.splitn(2, "-beta.").collect::<Vec<_>>();
+    let count = parts.get(1).and_then(|s| s.find(' ').map(|p| (&s[..p]).to_string()));
+
+    count
+}
+
 #[cfg(unix)]
 fn chmod(path: &Path, perms: u32) {
     use std::os::unix::fs::*;
diff --git a/src/bootstrap/render_tests.rs b/src/bootstrap/render_tests.rs
index bedf34d89e8..fa0a4806618 100644
--- a/src/bootstrap/render_tests.rs
+++ b/src/bootstrap/render_tests.rs
@@ -168,9 +168,14 @@ impl<'a> Renderer<'a> {
         if !self.failures.is_empty() {
             println!("\nfailures:\n");
             for failure in &self.failures {
-                if let Some(stdout) = &failure.stdout {
+                if failure.stdout.is_some() || failure.message.is_some() {
                     println!("---- {} stdout ----", failure.name);
-                    println!("{stdout}");
+                    if let Some(stdout) = &failure.stdout {
+                        println!("{stdout}");
+                    }
+                    if let Some(message) = &failure.message {
+                        println!("note: {message}");
+                    }
                 }
             }
 
diff --git a/src/bootstrap/run.rs b/src/bootstrap/run.rs
index 57f3119e322..ec01f744b82 100644
--- a/src/bootstrap/run.rs
+++ b/src/bootstrap/run.rs
@@ -1,9 +1,12 @@
 use std::path::PathBuf;
 use std::process::Command;
 
+use clap_complete::shells;
+
 use crate::builder::{Builder, RunConfig, ShouldRun, Step};
 use crate::config::TargetSelection;
 use crate::dist::distdir;
+use crate::flags::get_completion;
 use crate::test;
 use crate::tool::{self, SourceType, Tool};
 use crate::util::output;
@@ -275,3 +278,34 @@ impl Step for GenerateWindowsSys {
         builder.run(&mut cmd);
     }
 }
+
+#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
+pub struct GenerateCompletions;
+
+impl Step for GenerateCompletions {
+    type Output = ();
+
+    /// Uses `clap_complete` to generate shell completions.
+    fn run(self, builder: &Builder<'_>) {
+        // FIXME(clubby789): enable zsh when clap#4898 is fixed
+        let [bash, fish, powershell] = ["x.py.sh", "x.py.fish", "x.py.ps1"]
+            .map(|filename| builder.src.join("src/etc/completions").join(filename));
+        if let Some(comp) = get_completion(shells::Bash, &bash) {
+            std::fs::write(&bash, comp).expect("writing bash completion");
+        }
+        if let Some(comp) = get_completion(shells::Fish, &fish) {
+            std::fs::write(&fish, comp).expect("writing fish completion");
+        }
+        if let Some(comp) = get_completion(shells::PowerShell, &powershell) {
+            std::fs::write(&powershell, comp).expect("writing powershell completion");
+        }
+    }
+
+    fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
+        run.alias("generate-completions")
+    }
+
+    fn make_run(run: RunConfig<'_>) {
+        run.builder.ensure(GenerateCompletions);
+    }
+}
diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs
index 854b7f5bd3a..2b72d6c48eb 100644
--- a/src/bootstrap/test.rs
+++ b/src/bootstrap/test.rs
@@ -10,6 +10,8 @@ use std::iter;
 use std::path::{Path, PathBuf};
 use std::process::{Command, Stdio};
 
+use clap_complete::shells;
+
 use crate::builder::crate_description;
 use crate::builder::{Builder, Compiler, Kind, RunConfig, ShouldRun, Step};
 use crate::cache::Interned;
@@ -613,6 +615,23 @@ impl Step for Miri {
             builder.run(&mut cargo);
         }
 
+        // Run it again for mir-opt-level 4 to catch some miscompilations.
+        if builder.config.test_args().is_empty() {
+            cargo.env("MIRIFLAGS", "-O -Zmir-opt-level=4 -Cdebug-assertions=yes");
+            // Optimizations can change backtraces
+            cargo.env("MIRI_SKIP_UI_CHECKS", "1");
+            // `MIRI_SKIP_UI_CHECKS` and `MIRI_BLESS` are incompatible
+            cargo.env_remove("MIRI_BLESS");
+            // Optimizations can change error locations and remove UB so don't run `fail` tests.
+            cargo.args(&["tests/pass", "tests/panic"]);
+
+            let mut cargo = prepare_cargo_test(cargo, &[], &[], "miri", compiler, target, builder);
+            {
+                let _time = util::timeit(&builder);
+                builder.run(&mut cargo);
+            }
+        }
+
         // # Run `cargo miri test`.
         // This is just a smoke test (Miri's own CI invokes this in a bunch of different ways and ensures
         // that we get the desired output), but that is sufficient to make sure that the libtest harness
@@ -644,8 +663,10 @@ impl Step for Miri {
         cargo.env("RUST_BACKTRACE", "1");
 
         let mut cargo = Command::from(cargo);
-        let _time = util::timeit(&builder);
-        builder.run(&mut cargo);
+        {
+            let _time = util::timeit(&builder);
+            builder.run(&mut cargo);
+        }
     }
 }
 
@@ -1121,7 +1142,24 @@ help: to skip test's attempt to check tidiness, pass `--exclude src/tools/tidy`
         builder.info("tidy check");
         try_run(builder, &mut cmd);
 
-        builder.ensure(ExpandYamlAnchors {});
+        builder.ensure(ExpandYamlAnchors);
+
+        builder.info("x.py completions check");
+        let [bash, fish, powershell] = ["x.py.sh", "x.py.fish", "x.py.ps1"]
+            .map(|filename| builder.src.join("src/etc/completions").join(filename));
+        if builder.config.cmd.bless() {
+            builder.ensure(crate::run::GenerateCompletions);
+        } else {
+            if crate::flags::get_completion(shells::Bash, &bash).is_some()
+                || crate::flags::get_completion(shells::Fish, &fish).is_some()
+                || crate::flags::get_completion(shells::PowerShell, &powershell).is_some()
+            {
+                eprintln!(
+                    "x.py completions were changed; run `x.py run generate-completions` to update them"
+                );
+                crate::detail_exit(1);
+            }
+        }
     }
 
     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version b/src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version
index d183d4ace05..806935b827f 100644
--- a/src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version
+++ b/src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version
@@ -1 +1 @@
-0.16.0
\ No newline at end of file
+0.16.4
\ No newline at end of file
diff --git a/src/ci/stage-build.py b/src/ci/stage-build.py
index 7cd5e88f6a2..8d03d3759bf 100644
--- a/src/ci/stage-build.py
+++ b/src/ci/stage-build.py
@@ -48,7 +48,6 @@ RUSTC_PGO_CRATES = [
 
 LLVM_BOLT_CRATES = LLVM_PGO_CRATES
 
-
 class Pipeline:
     # Paths
     def checkout_path(self) -> Path:
@@ -451,6 +450,44 @@ def cmd(
             )
     return subprocess.run(args, env=environment, check=True)
 
+class BenchmarkRunner:
+    def run_rustc(self, pipeline: Pipeline):
+        raise NotImplementedError
+
+    def run_llvm(self, pipeline: Pipeline):
+        raise NotImplementedError
+
+    def run_bolt(self, pipeline: Pipeline):
+        raise NotImplementedError
+
+class DefaultBenchmarkRunner(BenchmarkRunner):
+    def run_rustc(self, pipeline: Pipeline):
+        # Here we're profiling the `rustc` frontend, so we also include `Check`.
+        # The benchmark set includes various stress tests that put the frontend under pressure.
+        run_compiler_benchmarks(
+            pipeline,
+            profiles=["Check", "Debug", "Opt"],
+            scenarios=["All"],
+            crates=RUSTC_PGO_CRATES,
+            env=dict(
+                LLVM_PROFILE_FILE=str(pipeline.rustc_profile_template_path())
+            )
+        )
+    def run_llvm(self, pipeline: Pipeline):
+        run_compiler_benchmarks(
+            pipeline,
+            profiles=["Debug", "Opt"],
+            scenarios=["Full"],
+            crates=LLVM_PGO_CRATES
+        )
+
+    def run_bolt(self, pipeline: Pipeline):
+        run_compiler_benchmarks(
+            pipeline,
+            profiles=["Check", "Debug", "Opt"],
+            scenarios=["Full"],
+            crates=LLVM_BOLT_CRATES
+        )
 
 def run_compiler_benchmarks(
         pipeline: Pipeline,
@@ -580,14 +617,10 @@ def create_pipeline() -> Pipeline:
         raise Exception(f"Optimized build is not supported for platform {sys.platform}")
 
 
-def gather_llvm_profiles(pipeline: Pipeline):
+def gather_llvm_profiles(pipeline: Pipeline, runner: BenchmarkRunner):
     LOGGER.info("Running benchmarks with PGO instrumented LLVM")
-    run_compiler_benchmarks(
-        pipeline,
-        profiles=["Debug", "Opt"],
-        scenarios=["Full"],
-        crates=LLVM_PGO_CRATES
-    )
+
+    runner.run_llvm(pipeline)
 
     profile_path = pipeline.llvm_profile_merged_file()
     LOGGER.info(f"Merging LLVM PGO profiles to {profile_path}")
@@ -609,20 +642,12 @@ def gather_llvm_profiles(pipeline: Pipeline):
     delete_directory(pipeline.llvm_profile_dir_root())
 
 
-def gather_rustc_profiles(pipeline: Pipeline):
+def gather_rustc_profiles(pipeline: Pipeline, runner: BenchmarkRunner):
     LOGGER.info("Running benchmarks with PGO instrumented rustc")
 
-    # Here we're profiling the `rustc` frontend, so we also include `Check`.
-    # The benchmark set includes various stress tests that put the frontend under pressure.
-    run_compiler_benchmarks(
-        pipeline,
-        profiles=["Check", "Debug", "Opt"],
-        scenarios=["All"],
-        crates=RUSTC_PGO_CRATES,
-        env=dict(
-            LLVM_PROFILE_FILE=str(pipeline.rustc_profile_template_path())
-        )
-    )
+
+    runner.run_rustc(pipeline)
+
 
     profile_path = pipeline.rustc_profile_merged_file()
     LOGGER.info(f"Merging Rustc PGO profiles to {profile_path}")
@@ -644,14 +669,10 @@ def gather_rustc_profiles(pipeline: Pipeline):
     delete_directory(pipeline.rustc_profile_dir_root())
 
 
-def gather_llvm_bolt_profiles(pipeline: Pipeline):
+def gather_llvm_bolt_profiles(pipeline: Pipeline, runner: BenchmarkRunner):
     LOGGER.info("Running benchmarks with BOLT instrumented LLVM")
-    run_compiler_benchmarks(
-        pipeline,
-        profiles=["Check", "Debug", "Opt"],
-        scenarios=["Full"],
-        crates=LLVM_BOLT_CRATES
-    )
+
+    runner.run_bolt(pipeline)
 
     merged_profile_path = pipeline.llvm_bolt_profile_merged_file()
     profile_files_path = Path("/tmp/prof.fdata")
@@ -744,7 +765,7 @@ def record_metrics(pipeline: Pipeline, timer: Timer):
     log_metrics(metrics)
 
 
-def execute_build_pipeline(timer: Timer, pipeline: Pipeline, final_build_args: List[str]):
+def execute_build_pipeline(timer: Timer, pipeline: Pipeline, runner: BenchmarkRunner, final_build_args: List[str]):
     # Clear and prepare tmp directory
     shutil.rmtree(pipeline.opt_artifacts(), ignore_errors=True)
     os.makedirs(pipeline.opt_artifacts(), exist_ok=True)
@@ -762,7 +783,7 @@ def execute_build_pipeline(timer: Timer, pipeline: Pipeline, final_build_args: L
             record_metrics(pipeline, rustc_build)
 
         with stage1.section("Gather profiles"):
-            gather_llvm_profiles(pipeline)
+            gather_llvm_profiles(pipeline, runner)
         print_free_disk_space(pipeline)
 
     clear_llvm_files(pipeline)
@@ -781,7 +802,7 @@ def execute_build_pipeline(timer: Timer, pipeline: Pipeline, final_build_args: L
             record_metrics(pipeline, rustc_build)
 
         with stage2.section("Gather profiles"):
-            gather_rustc_profiles(pipeline)
+            gather_rustc_profiles(pipeline, runner)
         print_free_disk_space(pipeline)
 
     clear_llvm_files(pipeline)
@@ -804,7 +825,7 @@ def execute_build_pipeline(timer: Timer, pipeline: Pipeline, final_build_args: L
                 record_metrics(pipeline, rustc_build)
 
             with stage3.section("Gather profiles"):
-                gather_llvm_bolt_profiles(pipeline)
+                gather_llvm_bolt_profiles(pipeline, runner)
 
         # LLVM is not being cleared here, we want to reuse the previous build
         print_free_disk_space(pipeline)
@@ -819,7 +840,7 @@ def execute_build_pipeline(timer: Timer, pipeline: Pipeline, final_build_args: L
         record_metrics(pipeline, stage4)
 
 
-if __name__ == "__main__":
+def run(runner: BenchmarkRunner):
     logging.basicConfig(
         level=logging.DEBUG,
         format="%(name)s %(levelname)-4s: %(message)s",
@@ -832,8 +853,9 @@ if __name__ == "__main__":
 
     timer = Timer()
     pipeline = create_pipeline()
+
     try:
-        execute_build_pipeline(timer, pipeline, build_args)
+        execute_build_pipeline(timer, pipeline, runner, build_args)
     except BaseException as e:
         LOGGER.error("The multi-stage build has failed")
         raise e
@@ -842,3 +864,7 @@ if __name__ == "__main__":
         print_free_disk_space(pipeline)
 
     print_binary_sizes(pipeline)
+
+if __name__ == "__main__":
+    runner = DefaultBenchmarkRunner()
+    run(runner)
diff --git a/src/etc/completions/x.py.fish b/src/etc/completions/x.py.fish
new file mode 100644
index 00000000000..4eddd5cedf1
--- /dev/null
+++ b/src/etc/completions/x.py.fish
@@ -0,0 +1,475 @@
+complete -c x.py -n "__fish_use_subcommand" -l config -d 'TOML configuration file for build' -r -F
+complete -c x.py -n "__fish_use_subcommand" -l build-dir -d 'Build directory, overrides `build.build-dir` in `config.toml`' -r -f -a "(__fish_complete_directories)"
+complete -c x.py -n "__fish_use_subcommand" -l build -d 'build target of the stage0 compiler' -r -f
+complete -c x.py -n "__fish_use_subcommand" -l host -d 'host targets to build' -r -f
+complete -c x.py -n "__fish_use_subcommand" -l target -d 'target targets to build' -r -f
+complete -c x.py -n "__fish_use_subcommand" -l exclude -d 'build paths to exclude' -r -F
+complete -c x.py -n "__fish_use_subcommand" -l rustc-error-format -r -f
+complete -c x.py -n "__fish_use_subcommand" -l on-fail -d 'command to run on failure' -r -f -a "(__fish_complete_command)"
+complete -c x.py -n "__fish_use_subcommand" -l stage -d 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)' -r -f
+complete -c x.py -n "__fish_use_subcommand" -l keep-stage -d 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f
+complete -c x.py -n "__fish_use_subcommand" -l keep-stage-std -d 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f
+complete -c x.py -n "__fish_use_subcommand" -l src -d 'path to the root of the rust checkout' -r -f -a "(__fish_complete_directories)"
+complete -c x.py -n "__fish_use_subcommand" -s j -l jobs -d 'number of jobs to run in parallel' -r -f
+complete -c x.py -n "__fish_use_subcommand" -l warnings -d 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour' -r -f -a "{deny	,warn	,default	}"
+complete -c x.py -n "__fish_use_subcommand" -l error-format -d 'rustc error format' -r -f
+complete -c x.py -n "__fish_use_subcommand" -l color -d 'whether to use color in cargo and rustc output' -r -f -a "{always	,never	,auto	}"
+complete -c x.py -n "__fish_use_subcommand" -l llvm-skip-rebuild -d 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml' -r -f -a "{true	,false	}"
+complete -c x.py -n "__fish_use_subcommand" -l rust-profile-generate -d 'generate PGO profile with rustc build' -r -F
+complete -c x.py -n "__fish_use_subcommand" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F
+complete -c x.py -n "__fish_use_subcommand" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F
+complete -c x.py -n "__fish_use_subcommand" -l llvm-bolt-profile-use -d 'use BOLT profile for LLVM build' -r -F
+complete -c x.py -n "__fish_use_subcommand" -s v -l verbose -d 'use verbose output (-vv for very verbose)'
+complete -c x.py -n "__fish_use_subcommand" -s i -l incremental -d 'use incremental compilation'
+complete -c x.py -n "__fish_use_subcommand" -l include-default-paths -d 'include default paths in addition to the provided ones'
+complete -c x.py -n "__fish_use_subcommand" -l dry-run -d 'dry run; don\'t build anything'
+complete -c x.py -n "__fish_use_subcommand" -l json-output -d 'use message-format=json'
+complete -c x.py -n "__fish_use_subcommand" -l llvm-profile-generate -d 'generate PGO profile with llvm built for rustc'
+complete -c x.py -n "__fish_use_subcommand" -l llvm-bolt-profile-generate -d 'generate BOLT profile for LLVM build'
+complete -c x.py -n "__fish_use_subcommand" -s h -l help -d 'Print help'
+complete -c x.py -n "__fish_use_subcommand" -f -a "build" -d 'Compile either the compiler or libraries'
+complete -c x.py -n "__fish_use_subcommand" -f -a "check" -d 'Compile either the compiler or libraries, using cargo check'
+complete -c x.py -n "__fish_use_subcommand" -f -a "clippy" -d 'Run Clippy (uses rustup/cargo-installed clippy binary)'
+complete -c x.py -n "__fish_use_subcommand" -f -a "fix" -d 'Run cargo fix'
+complete -c x.py -n "__fish_use_subcommand" -f -a "fmt" -d 'Run rustfmt'
+complete -c x.py -n "__fish_use_subcommand" -f -a "doc" -d 'Build documentation'
+complete -c x.py -n "__fish_use_subcommand" -f -a "test" -d 'Build and run some test suites'
+complete -c x.py -n "__fish_use_subcommand" -f -a "bench" -d 'Build and run some benchmarks'
+complete -c x.py -n "__fish_use_subcommand" -f -a "clean" -d 'Clean out build directories'
+complete -c x.py -n "__fish_use_subcommand" -f -a "dist" -d 'Build distribution artifacts'
+complete -c x.py -n "__fish_use_subcommand" -f -a "install" -d 'Install distribution artifacts'
+complete -c x.py -n "__fish_use_subcommand" -f -a "run" -d 'Run tools contained in this repository'
+complete -c x.py -n "__fish_use_subcommand" -f -a "setup" -d 'Set up the environment for development'
+complete -c x.py -n "__fish_use_subcommand" -f -a "suggest" -d 'Suggest a subset of tests to run, based on modified files'
+complete -c x.py -n "__fish_seen_subcommand_from build" -l config -d 'TOML configuration file for build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from build" -l build-dir -d 'Build directory, overrides `build.build-dir` in `config.toml`' -r -f -a "(__fish_complete_directories)"
+complete -c x.py -n "__fish_seen_subcommand_from build" -l build -d 'build target of the stage0 compiler' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from build" -l host -d 'host targets to build' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from build" -l target -d 'target targets to build' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from build" -l exclude -d 'build paths to exclude' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from build" -l rustc-error-format -r -f
+complete -c x.py -n "__fish_seen_subcommand_from build" -l on-fail -d 'command to run on failure' -r -f -a "(__fish_complete_command)"
+complete -c x.py -n "__fish_seen_subcommand_from build" -l stage -d 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from build" -l keep-stage -d 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from build" -l keep-stage-std -d 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from build" -l src -d 'path to the root of the rust checkout' -r -f -a "(__fish_complete_directories)"
+complete -c x.py -n "__fish_seen_subcommand_from build" -s j -l jobs -d 'number of jobs to run in parallel' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from build" -l warnings -d 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour' -r -f -a "{deny	,warn	,default	}"
+complete -c x.py -n "__fish_seen_subcommand_from build" -l error-format -d 'rustc error format' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from build" -l color -d 'whether to use color in cargo and rustc output' -r -f -a "{always	,never	,auto	}"
+complete -c x.py -n "__fish_seen_subcommand_from build" -l llvm-skip-rebuild -d 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml' -r -f -a "{true	,false	}"
+complete -c x.py -n "__fish_seen_subcommand_from build" -l rust-profile-generate -d 'generate PGO profile with rustc build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from build" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from build" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from build" -l llvm-bolt-profile-use -d 'use BOLT profile for LLVM build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from build" -s v -l verbose -d 'use verbose output (-vv for very verbose)'
+complete -c x.py -n "__fish_seen_subcommand_from build" -s i -l incremental -d 'use incremental compilation'
+complete -c x.py -n "__fish_seen_subcommand_from build" -l include-default-paths -d 'include default paths in addition to the provided ones'
+complete -c x.py -n "__fish_seen_subcommand_from build" -l dry-run -d 'dry run; don\'t build anything'
+complete -c x.py -n "__fish_seen_subcommand_from build" -l json-output -d 'use message-format=json'
+complete -c x.py -n "__fish_seen_subcommand_from build" -l llvm-profile-generate -d 'generate PGO profile with llvm built for rustc'
+complete -c x.py -n "__fish_seen_subcommand_from build" -l llvm-bolt-profile-generate -d 'generate BOLT profile for LLVM build'
+complete -c x.py -n "__fish_seen_subcommand_from build" -s h -l help -d 'Print help (see more with \'--help\')'
+complete -c x.py -n "__fish_seen_subcommand_from check" -l config -d 'TOML configuration file for build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from check" -l build-dir -d 'Build directory, overrides `build.build-dir` in `config.toml`' -r -f -a "(__fish_complete_directories)"
+complete -c x.py -n "__fish_seen_subcommand_from check" -l build -d 'build target of the stage0 compiler' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from check" -l host -d 'host targets to build' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from check" -l target -d 'target targets to build' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from check" -l exclude -d 'build paths to exclude' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from check" -l rustc-error-format -r -f
+complete -c x.py -n "__fish_seen_subcommand_from check" -l on-fail -d 'command to run on failure' -r -f -a "(__fish_complete_command)"
+complete -c x.py -n "__fish_seen_subcommand_from check" -l stage -d 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from check" -l keep-stage -d 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from check" -l keep-stage-std -d 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from check" -l src -d 'path to the root of the rust checkout' -r -f -a "(__fish_complete_directories)"
+complete -c x.py -n "__fish_seen_subcommand_from check" -s j -l jobs -d 'number of jobs to run in parallel' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from check" -l warnings -d 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour' -r -f -a "{deny	,warn	,default	}"
+complete -c x.py -n "__fish_seen_subcommand_from check" -l error-format -d 'rustc error format' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from check" -l color -d 'whether to use color in cargo and rustc output' -r -f -a "{always	,never	,auto	}"
+complete -c x.py -n "__fish_seen_subcommand_from check" -l llvm-skip-rebuild -d 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml' -r -f -a "{true	,false	}"
+complete -c x.py -n "__fish_seen_subcommand_from check" -l rust-profile-generate -d 'generate PGO profile with rustc build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from check" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from check" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from check" -l llvm-bolt-profile-use -d 'use BOLT profile for LLVM build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from check" -l all-targets -d 'Check all targets'
+complete -c x.py -n "__fish_seen_subcommand_from check" -s v -l verbose -d 'use verbose output (-vv for very verbose)'
+complete -c x.py -n "__fish_seen_subcommand_from check" -s i -l incremental -d 'use incremental compilation'
+complete -c x.py -n "__fish_seen_subcommand_from check" -l include-default-paths -d 'include default paths in addition to the provided ones'
+complete -c x.py -n "__fish_seen_subcommand_from check" -l dry-run -d 'dry run; don\'t build anything'
+complete -c x.py -n "__fish_seen_subcommand_from check" -l json-output -d 'use message-format=json'
+complete -c x.py -n "__fish_seen_subcommand_from check" -l llvm-profile-generate -d 'generate PGO profile with llvm built for rustc'
+complete -c x.py -n "__fish_seen_subcommand_from check" -l llvm-bolt-profile-generate -d 'generate BOLT profile for LLVM build'
+complete -c x.py -n "__fish_seen_subcommand_from check" -s h -l help -d 'Print help (see more with \'--help\')'
+complete -c x.py -n "__fish_seen_subcommand_from clippy" -s A -d 'clippy lints to allow' -r
+complete -c x.py -n "__fish_seen_subcommand_from clippy" -s D -d 'clippy lints to deny' -r
+complete -c x.py -n "__fish_seen_subcommand_from clippy" -s W -d 'clippy lints to warn on' -r
+complete -c x.py -n "__fish_seen_subcommand_from clippy" -s F -d 'clippy lints to forbid' -r
+complete -c x.py -n "__fish_seen_subcommand_from clippy" -l config -d 'TOML configuration file for build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from clippy" -l build-dir -d 'Build directory, overrides `build.build-dir` in `config.toml`' -r -f -a "(__fish_complete_directories)"
+complete -c x.py -n "__fish_seen_subcommand_from clippy" -l build -d 'build target of the stage0 compiler' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from clippy" -l host -d 'host targets to build' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from clippy" -l target -d 'target targets to build' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from clippy" -l exclude -d 'build paths to exclude' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from clippy" -l rustc-error-format -r -f
+complete -c x.py -n "__fish_seen_subcommand_from clippy" -l on-fail -d 'command to run on failure' -r -f -a "(__fish_complete_command)"
+complete -c x.py -n "__fish_seen_subcommand_from clippy" -l stage -d 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from clippy" -l keep-stage -d 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from clippy" -l keep-stage-std -d 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from clippy" -l src -d 'path to the root of the rust checkout' -r -f -a "(__fish_complete_directories)"
+complete -c x.py -n "__fish_seen_subcommand_from clippy" -s j -l jobs -d 'number of jobs to run in parallel' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from clippy" -l warnings -d 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour' -r -f -a "{deny	,warn	,default	}"
+complete -c x.py -n "__fish_seen_subcommand_from clippy" -l error-format -d 'rustc error format' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from clippy" -l color -d 'whether to use color in cargo and rustc output' -r -f -a "{always	,never	,auto	}"
+complete -c x.py -n "__fish_seen_subcommand_from clippy" -l llvm-skip-rebuild -d 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml' -r -f -a "{true	,false	}"
+complete -c x.py -n "__fish_seen_subcommand_from clippy" -l rust-profile-generate -d 'generate PGO profile with rustc build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from clippy" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from clippy" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from clippy" -l llvm-bolt-profile-use -d 'use BOLT profile for LLVM build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from clippy" -l fix
+complete -c x.py -n "__fish_seen_subcommand_from clippy" -s v -l verbose -d 'use verbose output (-vv for very verbose)'
+complete -c x.py -n "__fish_seen_subcommand_from clippy" -s i -l incremental -d 'use incremental compilation'
+complete -c x.py -n "__fish_seen_subcommand_from clippy" -l include-default-paths -d 'include default paths in addition to the provided ones'
+complete -c x.py -n "__fish_seen_subcommand_from clippy" -l dry-run -d 'dry run; don\'t build anything'
+complete -c x.py -n "__fish_seen_subcommand_from clippy" -l json-output -d 'use message-format=json'
+complete -c x.py -n "__fish_seen_subcommand_from clippy" -l llvm-profile-generate -d 'generate PGO profile with llvm built for rustc'
+complete -c x.py -n "__fish_seen_subcommand_from clippy" -l llvm-bolt-profile-generate -d 'generate BOLT profile for LLVM build'
+complete -c x.py -n "__fish_seen_subcommand_from clippy" -s h -l help -d 'Print help (see more with \'--help\')'
+complete -c x.py -n "__fish_seen_subcommand_from fix" -l config -d 'TOML configuration file for build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from fix" -l build-dir -d 'Build directory, overrides `build.build-dir` in `config.toml`' -r -f -a "(__fish_complete_directories)"
+complete -c x.py -n "__fish_seen_subcommand_from fix" -l build -d 'build target of the stage0 compiler' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from fix" -l host -d 'host targets to build' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from fix" -l target -d 'target targets to build' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from fix" -l exclude -d 'build paths to exclude' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from fix" -l rustc-error-format -r -f
+complete -c x.py -n "__fish_seen_subcommand_from fix" -l on-fail -d 'command to run on failure' -r -f -a "(__fish_complete_command)"
+complete -c x.py -n "__fish_seen_subcommand_from fix" -l stage -d 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from fix" -l keep-stage -d 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from fix" -l keep-stage-std -d 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from fix" -l src -d 'path to the root of the rust checkout' -r -f -a "(__fish_complete_directories)"
+complete -c x.py -n "__fish_seen_subcommand_from fix" -s j -l jobs -d 'number of jobs to run in parallel' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from fix" -l warnings -d 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour' -r -f -a "{deny	,warn	,default	}"
+complete -c x.py -n "__fish_seen_subcommand_from fix" -l error-format -d 'rustc error format' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from fix" -l color -d 'whether to use color in cargo and rustc output' -r -f -a "{always	,never	,auto	}"
+complete -c x.py -n "__fish_seen_subcommand_from fix" -l llvm-skip-rebuild -d 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml' -r -f -a "{true	,false	}"
+complete -c x.py -n "__fish_seen_subcommand_from fix" -l rust-profile-generate -d 'generate PGO profile with rustc build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from fix" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from fix" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from fix" -l llvm-bolt-profile-use -d 'use BOLT profile for LLVM build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from fix" -s v -l verbose -d 'use verbose output (-vv for very verbose)'
+complete -c x.py -n "__fish_seen_subcommand_from fix" -s i -l incremental -d 'use incremental compilation'
+complete -c x.py -n "__fish_seen_subcommand_from fix" -l include-default-paths -d 'include default paths in addition to the provided ones'
+complete -c x.py -n "__fish_seen_subcommand_from fix" -l dry-run -d 'dry run; don\'t build anything'
+complete -c x.py -n "__fish_seen_subcommand_from fix" -l json-output -d 'use message-format=json'
+complete -c x.py -n "__fish_seen_subcommand_from fix" -l llvm-profile-generate -d 'generate PGO profile with llvm built for rustc'
+complete -c x.py -n "__fish_seen_subcommand_from fix" -l llvm-bolt-profile-generate -d 'generate BOLT profile for LLVM build'
+complete -c x.py -n "__fish_seen_subcommand_from fix" -s h -l help -d 'Print help (see more with \'--help\')'
+complete -c x.py -n "__fish_seen_subcommand_from fmt" -l config -d 'TOML configuration file for build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from fmt" -l build-dir -d 'Build directory, overrides `build.build-dir` in `config.toml`' -r -f -a "(__fish_complete_directories)"
+complete -c x.py -n "__fish_seen_subcommand_from fmt" -l build -d 'build target of the stage0 compiler' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from fmt" -l host -d 'host targets to build' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from fmt" -l target -d 'target targets to build' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from fmt" -l exclude -d 'build paths to exclude' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from fmt" -l rustc-error-format -r -f
+complete -c x.py -n "__fish_seen_subcommand_from fmt" -l on-fail -d 'command to run on failure' -r -f -a "(__fish_complete_command)"
+complete -c x.py -n "__fish_seen_subcommand_from fmt" -l stage -d 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from fmt" -l keep-stage -d 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from fmt" -l keep-stage-std -d 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from fmt" -l src -d 'path to the root of the rust checkout' -r -f -a "(__fish_complete_directories)"
+complete -c x.py -n "__fish_seen_subcommand_from fmt" -s j -l jobs -d 'number of jobs to run in parallel' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from fmt" -l warnings -d 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour' -r -f -a "{deny	,warn	,default	}"
+complete -c x.py -n "__fish_seen_subcommand_from fmt" -l error-format -d 'rustc error format' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from fmt" -l color -d 'whether to use color in cargo and rustc output' -r -f -a "{always	,never	,auto	}"
+complete -c x.py -n "__fish_seen_subcommand_from fmt" -l llvm-skip-rebuild -d 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml' -r -f -a "{true	,false	}"
+complete -c x.py -n "__fish_seen_subcommand_from fmt" -l rust-profile-generate -d 'generate PGO profile with rustc build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from fmt" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from fmt" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from fmt" -l llvm-bolt-profile-use -d 'use BOLT profile for LLVM build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from fmt" -l check -d 'check formatting instead of applying'
+complete -c x.py -n "__fish_seen_subcommand_from fmt" -s v -l verbose -d 'use verbose output (-vv for very verbose)'
+complete -c x.py -n "__fish_seen_subcommand_from fmt" -s i -l incremental -d 'use incremental compilation'
+complete -c x.py -n "__fish_seen_subcommand_from fmt" -l include-default-paths -d 'include default paths in addition to the provided ones'
+complete -c x.py -n "__fish_seen_subcommand_from fmt" -l dry-run -d 'dry run; don\'t build anything'
+complete -c x.py -n "__fish_seen_subcommand_from fmt" -l json-output -d 'use message-format=json'
+complete -c x.py -n "__fish_seen_subcommand_from fmt" -l llvm-profile-generate -d 'generate PGO profile with llvm built for rustc'
+complete -c x.py -n "__fish_seen_subcommand_from fmt" -l llvm-bolt-profile-generate -d 'generate BOLT profile for LLVM build'
+complete -c x.py -n "__fish_seen_subcommand_from fmt" -s h -l help -d 'Print help (see more with \'--help\')'
+complete -c x.py -n "__fish_seen_subcommand_from doc" -l config -d 'TOML configuration file for build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from doc" -l build-dir -d 'Build directory, overrides `build.build-dir` in `config.toml`' -r -f -a "(__fish_complete_directories)"
+complete -c x.py -n "__fish_seen_subcommand_from doc" -l build -d 'build target of the stage0 compiler' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from doc" -l host -d 'host targets to build' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from doc" -l target -d 'target targets to build' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from doc" -l exclude -d 'build paths to exclude' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from doc" -l rustc-error-format -r -f
+complete -c x.py -n "__fish_seen_subcommand_from doc" -l on-fail -d 'command to run on failure' -r -f -a "(__fish_complete_command)"
+complete -c x.py -n "__fish_seen_subcommand_from doc" -l stage -d 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from doc" -l keep-stage -d 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from doc" -l keep-stage-std -d 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from doc" -l src -d 'path to the root of the rust checkout' -r -f -a "(__fish_complete_directories)"
+complete -c x.py -n "__fish_seen_subcommand_from doc" -s j -l jobs -d 'number of jobs to run in parallel' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from doc" -l warnings -d 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour' -r -f -a "{deny	,warn	,default	}"
+complete -c x.py -n "__fish_seen_subcommand_from doc" -l error-format -d 'rustc error format' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from doc" -l color -d 'whether to use color in cargo and rustc output' -r -f -a "{always	,never	,auto	}"
+complete -c x.py -n "__fish_seen_subcommand_from doc" -l llvm-skip-rebuild -d 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml' -r -f -a "{true	,false	}"
+complete -c x.py -n "__fish_seen_subcommand_from doc" -l rust-profile-generate -d 'generate PGO profile with rustc build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from doc" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from doc" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from doc" -l llvm-bolt-profile-use -d 'use BOLT profile for LLVM build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from doc" -l open -d 'open the docs in a browser'
+complete -c x.py -n "__fish_seen_subcommand_from doc" -l json -d 'render the documentation in JSON format in addition to the usual HTML format'
+complete -c x.py -n "__fish_seen_subcommand_from doc" -s v -l verbose -d 'use verbose output (-vv for very verbose)'
+complete -c x.py -n "__fish_seen_subcommand_from doc" -s i -l incremental -d 'use incremental compilation'
+complete -c x.py -n "__fish_seen_subcommand_from doc" -l include-default-paths -d 'include default paths in addition to the provided ones'
+complete -c x.py -n "__fish_seen_subcommand_from doc" -l dry-run -d 'dry run; don\'t build anything'
+complete -c x.py -n "__fish_seen_subcommand_from doc" -l json-output -d 'use message-format=json'
+complete -c x.py -n "__fish_seen_subcommand_from doc" -l llvm-profile-generate -d 'generate PGO profile with llvm built for rustc'
+complete -c x.py -n "__fish_seen_subcommand_from doc" -l llvm-bolt-profile-generate -d 'generate BOLT profile for LLVM build'
+complete -c x.py -n "__fish_seen_subcommand_from doc" -s h -l help -d 'Print help (see more with \'--help\')'
+complete -c x.py -n "__fish_seen_subcommand_from test" -l skip -d 'skips tests matching SUBSTRING, if supported by test tool. May be passed multiple times' -r
+complete -c x.py -n "__fish_seen_subcommand_from test" -l test-args -d 'extra arguments to be passed for the test tool being used (e.g. libtest, compiletest or rustdoc)' -r
+complete -c x.py -n "__fish_seen_subcommand_from test" -l rustc-args -d 'extra options to pass the compiler when running tests' -r
+complete -c x.py -n "__fish_seen_subcommand_from test" -l compare-mode -d 'mode describing what file the actual ui output will be compared to' -r
+complete -c x.py -n "__fish_seen_subcommand_from test" -l pass -d 'force {check,build,run}-pass tests to this mode' -r
+complete -c x.py -n "__fish_seen_subcommand_from test" -l run -d 'whether to execute run-* tests' -r
+complete -c x.py -n "__fish_seen_subcommand_from test" -l config -d 'TOML configuration file for build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from test" -l build-dir -d 'Build directory, overrides `build.build-dir` in `config.toml`' -r -f -a "(__fish_complete_directories)"
+complete -c x.py -n "__fish_seen_subcommand_from test" -l build -d 'build target of the stage0 compiler' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from test" -l host -d 'host targets to build' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from test" -l target -d 'target targets to build' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from test" -l exclude -d 'build paths to exclude' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from test" -l rustc-error-format -r -f
+complete -c x.py -n "__fish_seen_subcommand_from test" -l on-fail -d 'command to run on failure' -r -f -a "(__fish_complete_command)"
+complete -c x.py -n "__fish_seen_subcommand_from test" -l stage -d 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from test" -l keep-stage -d 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from test" -l keep-stage-std -d 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from test" -l src -d 'path to the root of the rust checkout' -r -f -a "(__fish_complete_directories)"
+complete -c x.py -n "__fish_seen_subcommand_from test" -s j -l jobs -d 'number of jobs to run in parallel' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from test" -l warnings -d 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour' -r -f -a "{deny	,warn	,default	}"
+complete -c x.py -n "__fish_seen_subcommand_from test" -l error-format -d 'rustc error format' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from test" -l color -d 'whether to use color in cargo and rustc output' -r -f -a "{always	,never	,auto	}"
+complete -c x.py -n "__fish_seen_subcommand_from test" -l llvm-skip-rebuild -d 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml' -r -f -a "{true	,false	}"
+complete -c x.py -n "__fish_seen_subcommand_from test" -l rust-profile-generate -d 'generate PGO profile with rustc build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from test" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from test" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from test" -l llvm-bolt-profile-use -d 'use BOLT profile for LLVM build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from test" -l no-fail-fast -d 'run all tests regardless of failure'
+complete -c x.py -n "__fish_seen_subcommand_from test" -l no-doc -d 'do not run doc tests'
+complete -c x.py -n "__fish_seen_subcommand_from test" -l doc -d 'only run doc tests'
+complete -c x.py -n "__fish_seen_subcommand_from test" -l bless -d 'whether to automatically update stderr/stdout files'
+complete -c x.py -n "__fish_seen_subcommand_from test" -l force-rerun -d 'rerun tests even if the inputs are unchanged'
+complete -c x.py -n "__fish_seen_subcommand_from test" -l only-modified -d 'only run tests that result has been changed'
+complete -c x.py -n "__fish_seen_subcommand_from test" -l rustfix-coverage -d 'enable this to generate a Rustfix coverage file, which is saved in `/<build_base>/rustfix_missing_coverage.txt`'
+complete -c x.py -n "__fish_seen_subcommand_from test" -s v -l verbose -d 'use verbose output (-vv for very verbose)'
+complete -c x.py -n "__fish_seen_subcommand_from test" -s i -l incremental -d 'use incremental compilation'
+complete -c x.py -n "__fish_seen_subcommand_from test" -l include-default-paths -d 'include default paths in addition to the provided ones'
+complete -c x.py -n "__fish_seen_subcommand_from test" -l dry-run -d 'dry run; don\'t build anything'
+complete -c x.py -n "__fish_seen_subcommand_from test" -l json-output -d 'use message-format=json'
+complete -c x.py -n "__fish_seen_subcommand_from test" -l llvm-profile-generate -d 'generate PGO profile with llvm built for rustc'
+complete -c x.py -n "__fish_seen_subcommand_from test" -l llvm-bolt-profile-generate -d 'generate BOLT profile for LLVM build'
+complete -c x.py -n "__fish_seen_subcommand_from test" -s h -l help -d 'Print help (see more with \'--help\')'
+complete -c x.py -n "__fish_seen_subcommand_from bench" -l test-args -r
+complete -c x.py -n "__fish_seen_subcommand_from bench" -l config -d 'TOML configuration file for build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from bench" -l build-dir -d 'Build directory, overrides `build.build-dir` in `config.toml`' -r -f -a "(__fish_complete_directories)"
+complete -c x.py -n "__fish_seen_subcommand_from bench" -l build -d 'build target of the stage0 compiler' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from bench" -l host -d 'host targets to build' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from bench" -l target -d 'target targets to build' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from bench" -l exclude -d 'build paths to exclude' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from bench" -l rustc-error-format -r -f
+complete -c x.py -n "__fish_seen_subcommand_from bench" -l on-fail -d 'command to run on failure' -r -f -a "(__fish_complete_command)"
+complete -c x.py -n "__fish_seen_subcommand_from bench" -l stage -d 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from bench" -l keep-stage -d 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from bench" -l keep-stage-std -d 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from bench" -l src -d 'path to the root of the rust checkout' -r -f -a "(__fish_complete_directories)"
+complete -c x.py -n "__fish_seen_subcommand_from bench" -s j -l jobs -d 'number of jobs to run in parallel' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from bench" -l warnings -d 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour' -r -f -a "{deny	,warn	,default	}"
+complete -c x.py -n "__fish_seen_subcommand_from bench" -l error-format -d 'rustc error format' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from bench" -l color -d 'whether to use color in cargo and rustc output' -r -f -a "{always	,never	,auto	}"
+complete -c x.py -n "__fish_seen_subcommand_from bench" -l llvm-skip-rebuild -d 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml' -r -f -a "{true	,false	}"
+complete -c x.py -n "__fish_seen_subcommand_from bench" -l rust-profile-generate -d 'generate PGO profile with rustc build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from bench" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from bench" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from bench" -l llvm-bolt-profile-use -d 'use BOLT profile for LLVM build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from bench" -s v -l verbose -d 'use verbose output (-vv for very verbose)'
+complete -c x.py -n "__fish_seen_subcommand_from bench" -s i -l incremental -d 'use incremental compilation'
+complete -c x.py -n "__fish_seen_subcommand_from bench" -l include-default-paths -d 'include default paths in addition to the provided ones'
+complete -c x.py -n "__fish_seen_subcommand_from bench" -l dry-run -d 'dry run; don\'t build anything'
+complete -c x.py -n "__fish_seen_subcommand_from bench" -l json-output -d 'use message-format=json'
+complete -c x.py -n "__fish_seen_subcommand_from bench" -l llvm-profile-generate -d 'generate PGO profile with llvm built for rustc'
+complete -c x.py -n "__fish_seen_subcommand_from bench" -l llvm-bolt-profile-generate -d 'generate BOLT profile for LLVM build'
+complete -c x.py -n "__fish_seen_subcommand_from bench" -s h -l help -d 'Print help'
+complete -c x.py -n "__fish_seen_subcommand_from clean" -l config -d 'TOML configuration file for build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from clean" -l build-dir -d 'Build directory, overrides `build.build-dir` in `config.toml`' -r -f -a "(__fish_complete_directories)"
+complete -c x.py -n "__fish_seen_subcommand_from clean" -l build -d 'build target of the stage0 compiler' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from clean" -l host -d 'host targets to build' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from clean" -l target -d 'target targets to build' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from clean" -l exclude -d 'build paths to exclude' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from clean" -l rustc-error-format -r -f
+complete -c x.py -n "__fish_seen_subcommand_from clean" -l on-fail -d 'command to run on failure' -r -f -a "(__fish_complete_command)"
+complete -c x.py -n "__fish_seen_subcommand_from clean" -l stage -d 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from clean" -l keep-stage -d 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from clean" -l keep-stage-std -d 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from clean" -l src -d 'path to the root of the rust checkout' -r -f -a "(__fish_complete_directories)"
+complete -c x.py -n "__fish_seen_subcommand_from clean" -s j -l jobs -d 'number of jobs to run in parallel' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from clean" -l warnings -d 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour' -r -f -a "{deny	,warn	,default	}"
+complete -c x.py -n "__fish_seen_subcommand_from clean" -l error-format -d 'rustc error format' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from clean" -l color -d 'whether to use color in cargo and rustc output' -r -f -a "{always	,never	,auto	}"
+complete -c x.py -n "__fish_seen_subcommand_from clean" -l llvm-skip-rebuild -d 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml' -r -f -a "{true	,false	}"
+complete -c x.py -n "__fish_seen_subcommand_from clean" -l rust-profile-generate -d 'generate PGO profile with rustc build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from clean" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from clean" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from clean" -l llvm-bolt-profile-use -d 'use BOLT profile for LLVM build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from clean" -l all
+complete -c x.py -n "__fish_seen_subcommand_from clean" -s v -l verbose -d 'use verbose output (-vv for very verbose)'
+complete -c x.py -n "__fish_seen_subcommand_from clean" -s i -l incremental -d 'use incremental compilation'
+complete -c x.py -n "__fish_seen_subcommand_from clean" -l include-default-paths -d 'include default paths in addition to the provided ones'
+complete -c x.py -n "__fish_seen_subcommand_from clean" -l dry-run -d 'dry run; don\'t build anything'
+complete -c x.py -n "__fish_seen_subcommand_from clean" -l json-output -d 'use message-format=json'
+complete -c x.py -n "__fish_seen_subcommand_from clean" -l llvm-profile-generate -d 'generate PGO profile with llvm built for rustc'
+complete -c x.py -n "__fish_seen_subcommand_from clean" -l llvm-bolt-profile-generate -d 'generate BOLT profile for LLVM build'
+complete -c x.py -n "__fish_seen_subcommand_from clean" -s h -l help -d 'Print help'
+complete -c x.py -n "__fish_seen_subcommand_from dist" -l config -d 'TOML configuration file for build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from dist" -l build-dir -d 'Build directory, overrides `build.build-dir` in `config.toml`' -r -f -a "(__fish_complete_directories)"
+complete -c x.py -n "__fish_seen_subcommand_from dist" -l build -d 'build target of the stage0 compiler' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from dist" -l host -d 'host targets to build' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from dist" -l target -d 'target targets to build' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from dist" -l exclude -d 'build paths to exclude' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from dist" -l rustc-error-format -r -f
+complete -c x.py -n "__fish_seen_subcommand_from dist" -l on-fail -d 'command to run on failure' -r -f -a "(__fish_complete_command)"
+complete -c x.py -n "__fish_seen_subcommand_from dist" -l stage -d 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from dist" -l keep-stage -d 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from dist" -l keep-stage-std -d 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from dist" -l src -d 'path to the root of the rust checkout' -r -f -a "(__fish_complete_directories)"
+complete -c x.py -n "__fish_seen_subcommand_from dist" -s j -l jobs -d 'number of jobs to run in parallel' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from dist" -l warnings -d 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour' -r -f -a "{deny	,warn	,default	}"
+complete -c x.py -n "__fish_seen_subcommand_from dist" -l error-format -d 'rustc error format' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from dist" -l color -d 'whether to use color in cargo and rustc output' -r -f -a "{always	,never	,auto	}"
+complete -c x.py -n "__fish_seen_subcommand_from dist" -l llvm-skip-rebuild -d 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml' -r -f -a "{true	,false	}"
+complete -c x.py -n "__fish_seen_subcommand_from dist" -l rust-profile-generate -d 'generate PGO profile with rustc build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from dist" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from dist" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from dist" -l llvm-bolt-profile-use -d 'use BOLT profile for LLVM build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from dist" -s v -l verbose -d 'use verbose output (-vv for very verbose)'
+complete -c x.py -n "__fish_seen_subcommand_from dist" -s i -l incremental -d 'use incremental compilation'
+complete -c x.py -n "__fish_seen_subcommand_from dist" -l include-default-paths -d 'include default paths in addition to the provided ones'
+complete -c x.py -n "__fish_seen_subcommand_from dist" -l dry-run -d 'dry run; don\'t build anything'
+complete -c x.py -n "__fish_seen_subcommand_from dist" -l json-output -d 'use message-format=json'
+complete -c x.py -n "__fish_seen_subcommand_from dist" -l llvm-profile-generate -d 'generate PGO profile with llvm built for rustc'
+complete -c x.py -n "__fish_seen_subcommand_from dist" -l llvm-bolt-profile-generate -d 'generate BOLT profile for LLVM build'
+complete -c x.py -n "__fish_seen_subcommand_from dist" -s h -l help -d 'Print help'
+complete -c x.py -n "__fish_seen_subcommand_from install" -l config -d 'TOML configuration file for build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from install" -l build-dir -d 'Build directory, overrides `build.build-dir` in `config.toml`' -r -f -a "(__fish_complete_directories)"
+complete -c x.py -n "__fish_seen_subcommand_from install" -l build -d 'build target of the stage0 compiler' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from install" -l host -d 'host targets to build' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from install" -l target -d 'target targets to build' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from install" -l exclude -d 'build paths to exclude' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from install" -l rustc-error-format -r -f
+complete -c x.py -n "__fish_seen_subcommand_from install" -l on-fail -d 'command to run on failure' -r -f -a "(__fish_complete_command)"
+complete -c x.py -n "__fish_seen_subcommand_from install" -l stage -d 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from install" -l keep-stage -d 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from install" -l keep-stage-std -d 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from install" -l src -d 'path to the root of the rust checkout' -r -f -a "(__fish_complete_directories)"
+complete -c x.py -n "__fish_seen_subcommand_from install" -s j -l jobs -d 'number of jobs to run in parallel' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from install" -l warnings -d 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour' -r -f -a "{deny	,warn	,default	}"
+complete -c x.py -n "__fish_seen_subcommand_from install" -l error-format -d 'rustc error format' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from install" -l color -d 'whether to use color in cargo and rustc output' -r -f -a "{always	,never	,auto	}"
+complete -c x.py -n "__fish_seen_subcommand_from install" -l llvm-skip-rebuild -d 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml' -r -f -a "{true	,false	}"
+complete -c x.py -n "__fish_seen_subcommand_from install" -l rust-profile-generate -d 'generate PGO profile with rustc build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from install" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from install" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from install" -l llvm-bolt-profile-use -d 'use BOLT profile for LLVM build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from install" -s v -l verbose -d 'use verbose output (-vv for very verbose)'
+complete -c x.py -n "__fish_seen_subcommand_from install" -s i -l incremental -d 'use incremental compilation'
+complete -c x.py -n "__fish_seen_subcommand_from install" -l include-default-paths -d 'include default paths in addition to the provided ones'
+complete -c x.py -n "__fish_seen_subcommand_from install" -l dry-run -d 'dry run; don\'t build anything'
+complete -c x.py -n "__fish_seen_subcommand_from install" -l json-output -d 'use message-format=json'
+complete -c x.py -n "__fish_seen_subcommand_from install" -l llvm-profile-generate -d 'generate PGO profile with llvm built for rustc'
+complete -c x.py -n "__fish_seen_subcommand_from install" -l llvm-bolt-profile-generate -d 'generate BOLT profile for LLVM build'
+complete -c x.py -n "__fish_seen_subcommand_from install" -s h -l help -d 'Print help'
+complete -c x.py -n "__fish_seen_subcommand_from run" -l args -d 'arguments for the tool' -r
+complete -c x.py -n "__fish_seen_subcommand_from run" -l config -d 'TOML configuration file for build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from run" -l build-dir -d 'Build directory, overrides `build.build-dir` in `config.toml`' -r -f -a "(__fish_complete_directories)"
+complete -c x.py -n "__fish_seen_subcommand_from run" -l build -d 'build target of the stage0 compiler' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from run" -l host -d 'host targets to build' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from run" -l target -d 'target targets to build' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from run" -l exclude -d 'build paths to exclude' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from run" -l rustc-error-format -r -f
+complete -c x.py -n "__fish_seen_subcommand_from run" -l on-fail -d 'command to run on failure' -r -f -a "(__fish_complete_command)"
+complete -c x.py -n "__fish_seen_subcommand_from run" -l stage -d 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from run" -l keep-stage -d 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from run" -l keep-stage-std -d 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from run" -l src -d 'path to the root of the rust checkout' -r -f -a "(__fish_complete_directories)"
+complete -c x.py -n "__fish_seen_subcommand_from run" -s j -l jobs -d 'number of jobs to run in parallel' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from run" -l warnings -d 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour' -r -f -a "{deny	,warn	,default	}"
+complete -c x.py -n "__fish_seen_subcommand_from run" -l error-format -d 'rustc error format' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from run" -l color -d 'whether to use color in cargo and rustc output' -r -f -a "{always	,never	,auto	}"
+complete -c x.py -n "__fish_seen_subcommand_from run" -l llvm-skip-rebuild -d 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml' -r -f -a "{true	,false	}"
+complete -c x.py -n "__fish_seen_subcommand_from run" -l rust-profile-generate -d 'generate PGO profile with rustc build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from run" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from run" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from run" -l llvm-bolt-profile-use -d 'use BOLT profile for LLVM build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from run" -s v -l verbose -d 'use verbose output (-vv for very verbose)'
+complete -c x.py -n "__fish_seen_subcommand_from run" -s i -l incremental -d 'use incremental compilation'
+complete -c x.py -n "__fish_seen_subcommand_from run" -l include-default-paths -d 'include default paths in addition to the provided ones'
+complete -c x.py -n "__fish_seen_subcommand_from run" -l dry-run -d 'dry run; don\'t build anything'
+complete -c x.py -n "__fish_seen_subcommand_from run" -l json-output -d 'use message-format=json'
+complete -c x.py -n "__fish_seen_subcommand_from run" -l llvm-profile-generate -d 'generate PGO profile with llvm built for rustc'
+complete -c x.py -n "__fish_seen_subcommand_from run" -l llvm-bolt-profile-generate -d 'generate BOLT profile for LLVM build'
+complete -c x.py -n "__fish_seen_subcommand_from run" -s h -l help -d 'Print help (see more with \'--help\')'
+complete -c x.py -n "__fish_seen_subcommand_from setup" -l config -d 'TOML configuration file for build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from setup" -l build-dir -d 'Build directory, overrides `build.build-dir` in `config.toml`' -r -f -a "(__fish_complete_directories)"
+complete -c x.py -n "__fish_seen_subcommand_from setup" -l build -d 'build target of the stage0 compiler' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from setup" -l host -d 'host targets to build' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from setup" -l target -d 'target targets to build' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from setup" -l exclude -d 'build paths to exclude' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from setup" -l rustc-error-format -r -f
+complete -c x.py -n "__fish_seen_subcommand_from setup" -l on-fail -d 'command to run on failure' -r -f -a "(__fish_complete_command)"
+complete -c x.py -n "__fish_seen_subcommand_from setup" -l stage -d 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from setup" -l keep-stage -d 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from setup" -l keep-stage-std -d 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from setup" -l src -d 'path to the root of the rust checkout' -r -f -a "(__fish_complete_directories)"
+complete -c x.py -n "__fish_seen_subcommand_from setup" -s j -l jobs -d 'number of jobs to run in parallel' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from setup" -l warnings -d 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour' -r -f -a "{deny	,warn	,default	}"
+complete -c x.py -n "__fish_seen_subcommand_from setup" -l error-format -d 'rustc error format' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from setup" -l color -d 'whether to use color in cargo and rustc output' -r -f -a "{always	,never	,auto	}"
+complete -c x.py -n "__fish_seen_subcommand_from setup" -l llvm-skip-rebuild -d 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml' -r -f -a "{true	,false	}"
+complete -c x.py -n "__fish_seen_subcommand_from setup" -l rust-profile-generate -d 'generate PGO profile with rustc build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from setup" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from setup" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from setup" -l llvm-bolt-profile-use -d 'use BOLT profile for LLVM build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from setup" -s v -l verbose -d 'use verbose output (-vv for very verbose)'
+complete -c x.py -n "__fish_seen_subcommand_from setup" -s i -l incremental -d 'use incremental compilation'
+complete -c x.py -n "__fish_seen_subcommand_from setup" -l include-default-paths -d 'include default paths in addition to the provided ones'
+complete -c x.py -n "__fish_seen_subcommand_from setup" -l dry-run -d 'dry run; don\'t build anything'
+complete -c x.py -n "__fish_seen_subcommand_from setup" -l json-output -d 'use message-format=json'
+complete -c x.py -n "__fish_seen_subcommand_from setup" -l llvm-profile-generate -d 'generate PGO profile with llvm built for rustc'
+complete -c x.py -n "__fish_seen_subcommand_from setup" -l llvm-bolt-profile-generate -d 'generate BOLT profile for LLVM build'
+complete -c x.py -n "__fish_seen_subcommand_from setup" -s h -l help -d 'Print help (see more with \'--help\')'
+complete -c x.py -n "__fish_seen_subcommand_from suggest" -l config -d 'TOML configuration file for build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from suggest" -l build-dir -d 'Build directory, overrides `build.build-dir` in `config.toml`' -r -f -a "(__fish_complete_directories)"
+complete -c x.py -n "__fish_seen_subcommand_from suggest" -l build -d 'build target of the stage0 compiler' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from suggest" -l host -d 'host targets to build' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from suggest" -l target -d 'target targets to build' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from suggest" -l exclude -d 'build paths to exclude' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from suggest" -l rustc-error-format -r -f
+complete -c x.py -n "__fish_seen_subcommand_from suggest" -l on-fail -d 'command to run on failure' -r -f -a "(__fish_complete_command)"
+complete -c x.py -n "__fish_seen_subcommand_from suggest" -l stage -d 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from suggest" -l keep-stage -d 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from suggest" -l keep-stage-std -d 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from suggest" -l src -d 'path to the root of the rust checkout' -r -f -a "(__fish_complete_directories)"
+complete -c x.py -n "__fish_seen_subcommand_from suggest" -s j -l jobs -d 'number of jobs to run in parallel' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from suggest" -l warnings -d 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour' -r -f -a "{deny	,warn	,default	}"
+complete -c x.py -n "__fish_seen_subcommand_from suggest" -l error-format -d 'rustc error format' -r -f
+complete -c x.py -n "__fish_seen_subcommand_from suggest" -l color -d 'whether to use color in cargo and rustc output' -r -f -a "{always	,never	,auto	}"
+complete -c x.py -n "__fish_seen_subcommand_from suggest" -l llvm-skip-rebuild -d 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml' -r -f -a "{true	,false	}"
+complete -c x.py -n "__fish_seen_subcommand_from suggest" -l rust-profile-generate -d 'generate PGO profile with rustc build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from suggest" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from suggest" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from suggest" -l llvm-bolt-profile-use -d 'use BOLT profile for LLVM build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from suggest" -l run -d 'run suggested tests'
+complete -c x.py -n "__fish_seen_subcommand_from suggest" -s v -l verbose -d 'use verbose output (-vv for very verbose)'
+complete -c x.py -n "__fish_seen_subcommand_from suggest" -s i -l incremental -d 'use incremental compilation'
+complete -c x.py -n "__fish_seen_subcommand_from suggest" -l include-default-paths -d 'include default paths in addition to the provided ones'
+complete -c x.py -n "__fish_seen_subcommand_from suggest" -l dry-run -d 'dry run; don\'t build anything'
+complete -c x.py -n "__fish_seen_subcommand_from suggest" -l json-output -d 'use message-format=json'
+complete -c x.py -n "__fish_seen_subcommand_from suggest" -l llvm-profile-generate -d 'generate PGO profile with llvm built for rustc'
+complete -c x.py -n "__fish_seen_subcommand_from suggest" -l llvm-bolt-profile-generate -d 'generate BOLT profile for LLVM build'
+complete -c x.py -n "__fish_seen_subcommand_from suggest" -s h -l help -d 'Print help (see more with \'--help\')'
diff --git a/src/etc/completions/x.py.ps1 b/src/etc/completions/x.py.ps1
new file mode 100644
index 00000000000..59fabf53f98
--- /dev/null
+++ b/src/etc/completions/x.py.ps1
@@ -0,0 +1,607 @@
+
+using namespace System.Management.Automation
+using namespace System.Management.Automation.Language
+
+Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock {
+    param($wordToComplete, $commandAst, $cursorPosition)
+
+    $commandElements = $commandAst.CommandElements
+    $command = @(
+        'x.py'
+        for ($i = 1; $i -lt $commandElements.Count; $i++) {
+            $element = $commandElements[$i]
+            if ($element -isnot [StringConstantExpressionAst] -or
+                $element.StringConstantType -ne [StringConstantType]::BareWord -or
+                $element.Value.StartsWith('-') -or
+                $element.Value -eq $wordToComplete) {
+                break
+        }
+        $element.Value
+    }) -join ';'
+
+    $completions = @(switch ($command) {
+        'x.py' {
+            [CompletionResult]::new('--config', 'config', [CompletionResultType]::ParameterName, 'TOML configuration file for build')
+            [CompletionResult]::new('--build-dir', 'build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `config.toml`')
+            [CompletionResult]::new('--build', 'build', [CompletionResultType]::ParameterName, 'build target of the stage0 compiler')
+            [CompletionResult]::new('--host', 'host', [CompletionResultType]::ParameterName, 'host targets to build')
+            [CompletionResult]::new('--target', 'target', [CompletionResultType]::ParameterName, 'target targets to build')
+            [CompletionResult]::new('--exclude', 'exclude', [CompletionResultType]::ParameterName, 'build paths to exclude')
+            [CompletionResult]::new('--rustc-error-format', 'rustc-error-format', [CompletionResultType]::ParameterName, 'rustc-error-format')
+            [CompletionResult]::new('--on-fail', 'on-fail', [CompletionResultType]::ParameterName, 'command to run on failure')
+            [CompletionResult]::new('--stage', 'stage', [CompletionResultType]::ParameterName, 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)')
+            [CompletionResult]::new('--keep-stage', 'keep-stage', [CompletionResultType]::ParameterName, 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)')
+            [CompletionResult]::new('--keep-stage-std', 'keep-stage-std', [CompletionResultType]::ParameterName, 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)')
+            [CompletionResult]::new('--src', 'src', [CompletionResultType]::ParameterName, 'path to the root of the rust checkout')
+            [CompletionResult]::new('-j', 'j', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel')
+            [CompletionResult]::new('--jobs', 'jobs', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel')
+            [CompletionResult]::new('--warnings', 'warnings', [CompletionResultType]::ParameterName, 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour')
+            [CompletionResult]::new('--error-format', 'error-format', [CompletionResultType]::ParameterName, 'rustc error format')
+            [CompletionResult]::new('--color', 'color', [CompletionResultType]::ParameterName, 'whether to use color in cargo and rustc output')
+            [CompletionResult]::new('--llvm-skip-rebuild', 'llvm-skip-rebuild', [CompletionResultType]::ParameterName, 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml')
+            [CompletionResult]::new('--rust-profile-generate', 'rust-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with rustc build')
+            [CompletionResult]::new('--rust-profile-use', 'rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build')
+            [CompletionResult]::new('--llvm-profile-use', 'llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build')
+            [CompletionResult]::new('--llvm-bolt-profile-use', 'llvm-bolt-profile-use', [CompletionResultType]::ParameterName, 'use BOLT profile for LLVM build')
+            [CompletionResult]::new('-v', 'v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)')
+            [CompletionResult]::new('--verbose', 'verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)')
+            [CompletionResult]::new('-i', 'i', [CompletionResultType]::ParameterName, 'use incremental compilation')
+            [CompletionResult]::new('--incremental', 'incremental', [CompletionResultType]::ParameterName, 'use incremental compilation')
+            [CompletionResult]::new('--include-default-paths', 'include-default-paths', [CompletionResultType]::ParameterName, 'include default paths in addition to the provided ones')
+            [CompletionResult]::new('--dry-run', 'dry-run', [CompletionResultType]::ParameterName, 'dry run; don''t build anything')
+            [CompletionResult]::new('--json-output', 'json-output', [CompletionResultType]::ParameterName, 'use message-format=json')
+            [CompletionResult]::new('--llvm-profile-generate', 'llvm-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with llvm built for rustc')
+            [CompletionResult]::new('--llvm-bolt-profile-generate', 'llvm-bolt-profile-generate', [CompletionResultType]::ParameterName, 'generate BOLT profile for LLVM build')
+            [CompletionResult]::new('-h', 'h', [CompletionResultType]::ParameterName, 'Print help')
+            [CompletionResult]::new('--help', 'help', [CompletionResultType]::ParameterName, 'Print help')
+            [CompletionResult]::new('build', 'build', [CompletionResultType]::ParameterValue, 'Compile either the compiler or libraries')
+            [CompletionResult]::new('check', 'check', [CompletionResultType]::ParameterValue, 'Compile either the compiler or libraries, using cargo check')
+            [CompletionResult]::new('clippy', 'clippy', [CompletionResultType]::ParameterValue, 'Run Clippy (uses rustup/cargo-installed clippy binary)')
+            [CompletionResult]::new('fix', 'fix', [CompletionResultType]::ParameterValue, 'Run cargo fix')
+            [CompletionResult]::new('fmt', 'fmt', [CompletionResultType]::ParameterValue, 'Run rustfmt')
+            [CompletionResult]::new('doc', 'doc', [CompletionResultType]::ParameterValue, 'Build documentation')
+            [CompletionResult]::new('test', 'test', [CompletionResultType]::ParameterValue, 'Build and run some test suites')
+            [CompletionResult]::new('bench', 'bench', [CompletionResultType]::ParameterValue, 'Build and run some benchmarks')
+            [CompletionResult]::new('clean', 'clean', [CompletionResultType]::ParameterValue, 'Clean out build directories')
+            [CompletionResult]::new('dist', 'dist', [CompletionResultType]::ParameterValue, 'Build distribution artifacts')
+            [CompletionResult]::new('install', 'install', [CompletionResultType]::ParameterValue, 'Install distribution artifacts')
+            [CompletionResult]::new('run', 'run', [CompletionResultType]::ParameterValue, 'Run tools contained in this repository')
+            [CompletionResult]::new('setup', 'setup', [CompletionResultType]::ParameterValue, 'Set up the environment for development')
+            [CompletionResult]::new('suggest', 'suggest', [CompletionResultType]::ParameterValue, 'Suggest a subset of tests to run, based on modified files')
+            break
+        }
+        'x.py;build' {
+            [CompletionResult]::new('--config', 'config', [CompletionResultType]::ParameterName, 'TOML configuration file for build')
+            [CompletionResult]::new('--build-dir', 'build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `config.toml`')
+            [CompletionResult]::new('--build', 'build', [CompletionResultType]::ParameterName, 'build target of the stage0 compiler')
+            [CompletionResult]::new('--host', 'host', [CompletionResultType]::ParameterName, 'host targets to build')
+            [CompletionResult]::new('--target', 'target', [CompletionResultType]::ParameterName, 'target targets to build')
+            [CompletionResult]::new('--exclude', 'exclude', [CompletionResultType]::ParameterName, 'build paths to exclude')
+            [CompletionResult]::new('--rustc-error-format', 'rustc-error-format', [CompletionResultType]::ParameterName, 'rustc-error-format')
+            [CompletionResult]::new('--on-fail', 'on-fail', [CompletionResultType]::ParameterName, 'command to run on failure')
+            [CompletionResult]::new('--stage', 'stage', [CompletionResultType]::ParameterName, 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)')
+            [CompletionResult]::new('--keep-stage', 'keep-stage', [CompletionResultType]::ParameterName, 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)')
+            [CompletionResult]::new('--keep-stage-std', 'keep-stage-std', [CompletionResultType]::ParameterName, 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)')
+            [CompletionResult]::new('--src', 'src', [CompletionResultType]::ParameterName, 'path to the root of the rust checkout')
+            [CompletionResult]::new('-j', 'j', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel')
+            [CompletionResult]::new('--jobs', 'jobs', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel')
+            [CompletionResult]::new('--warnings', 'warnings', [CompletionResultType]::ParameterName, 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour')
+            [CompletionResult]::new('--error-format', 'error-format', [CompletionResultType]::ParameterName, 'rustc error format')
+            [CompletionResult]::new('--color', 'color', [CompletionResultType]::ParameterName, 'whether to use color in cargo and rustc output')
+            [CompletionResult]::new('--llvm-skip-rebuild', 'llvm-skip-rebuild', [CompletionResultType]::ParameterName, 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml')
+            [CompletionResult]::new('--rust-profile-generate', 'rust-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with rustc build')
+            [CompletionResult]::new('--rust-profile-use', 'rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build')
+            [CompletionResult]::new('--llvm-profile-use', 'llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build')
+            [CompletionResult]::new('--llvm-bolt-profile-use', 'llvm-bolt-profile-use', [CompletionResultType]::ParameterName, 'use BOLT profile for LLVM build')
+            [CompletionResult]::new('-v', 'v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)')
+            [CompletionResult]::new('--verbose', 'verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)')
+            [CompletionResult]::new('-i', 'i', [CompletionResultType]::ParameterName, 'use incremental compilation')
+            [CompletionResult]::new('--incremental', 'incremental', [CompletionResultType]::ParameterName, 'use incremental compilation')
+            [CompletionResult]::new('--include-default-paths', 'include-default-paths', [CompletionResultType]::ParameterName, 'include default paths in addition to the provided ones')
+            [CompletionResult]::new('--dry-run', 'dry-run', [CompletionResultType]::ParameterName, 'dry run; don''t build anything')
+            [CompletionResult]::new('--json-output', 'json-output', [CompletionResultType]::ParameterName, 'use message-format=json')
+            [CompletionResult]::new('--llvm-profile-generate', 'llvm-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with llvm built for rustc')
+            [CompletionResult]::new('--llvm-bolt-profile-generate', 'llvm-bolt-profile-generate', [CompletionResultType]::ParameterName, 'generate BOLT profile for LLVM build')
+            [CompletionResult]::new('-h', 'h', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')')
+            [CompletionResult]::new('--help', 'help', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')')
+            break
+        }
+        'x.py;check' {
+            [CompletionResult]::new('--config', 'config', [CompletionResultType]::ParameterName, 'TOML configuration file for build')
+            [CompletionResult]::new('--build-dir', 'build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `config.toml`')
+            [CompletionResult]::new('--build', 'build', [CompletionResultType]::ParameterName, 'build target of the stage0 compiler')
+            [CompletionResult]::new('--host', 'host', [CompletionResultType]::ParameterName, 'host targets to build')
+            [CompletionResult]::new('--target', 'target', [CompletionResultType]::ParameterName, 'target targets to build')
+            [CompletionResult]::new('--exclude', 'exclude', [CompletionResultType]::ParameterName, 'build paths to exclude')
+            [CompletionResult]::new('--rustc-error-format', 'rustc-error-format', [CompletionResultType]::ParameterName, 'rustc-error-format')
+            [CompletionResult]::new('--on-fail', 'on-fail', [CompletionResultType]::ParameterName, 'command to run on failure')
+            [CompletionResult]::new('--stage', 'stage', [CompletionResultType]::ParameterName, 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)')
+            [CompletionResult]::new('--keep-stage', 'keep-stage', [CompletionResultType]::ParameterName, 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)')
+            [CompletionResult]::new('--keep-stage-std', 'keep-stage-std', [CompletionResultType]::ParameterName, 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)')
+            [CompletionResult]::new('--src', 'src', [CompletionResultType]::ParameterName, 'path to the root of the rust checkout')
+            [CompletionResult]::new('-j', 'j', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel')
+            [CompletionResult]::new('--jobs', 'jobs', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel')
+            [CompletionResult]::new('--warnings', 'warnings', [CompletionResultType]::ParameterName, 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour')
+            [CompletionResult]::new('--error-format', 'error-format', [CompletionResultType]::ParameterName, 'rustc error format')
+            [CompletionResult]::new('--color', 'color', [CompletionResultType]::ParameterName, 'whether to use color in cargo and rustc output')
+            [CompletionResult]::new('--llvm-skip-rebuild', 'llvm-skip-rebuild', [CompletionResultType]::ParameterName, 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml')
+            [CompletionResult]::new('--rust-profile-generate', 'rust-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with rustc build')
+            [CompletionResult]::new('--rust-profile-use', 'rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build')
+            [CompletionResult]::new('--llvm-profile-use', 'llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build')
+            [CompletionResult]::new('--llvm-bolt-profile-use', 'llvm-bolt-profile-use', [CompletionResultType]::ParameterName, 'use BOLT profile for LLVM build')
+            [CompletionResult]::new('--all-targets', 'all-targets', [CompletionResultType]::ParameterName, 'Check all targets')
+            [CompletionResult]::new('-v', 'v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)')
+            [CompletionResult]::new('--verbose', 'verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)')
+            [CompletionResult]::new('-i', 'i', [CompletionResultType]::ParameterName, 'use incremental compilation')
+            [CompletionResult]::new('--incremental', 'incremental', [CompletionResultType]::ParameterName, 'use incremental compilation')
+            [CompletionResult]::new('--include-default-paths', 'include-default-paths', [CompletionResultType]::ParameterName, 'include default paths in addition to the provided ones')
+            [CompletionResult]::new('--dry-run', 'dry-run', [CompletionResultType]::ParameterName, 'dry run; don''t build anything')
+            [CompletionResult]::new('--json-output', 'json-output', [CompletionResultType]::ParameterName, 'use message-format=json')
+            [CompletionResult]::new('--llvm-profile-generate', 'llvm-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with llvm built for rustc')
+            [CompletionResult]::new('--llvm-bolt-profile-generate', 'llvm-bolt-profile-generate', [CompletionResultType]::ParameterName, 'generate BOLT profile for LLVM build')
+            [CompletionResult]::new('-h', 'h', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')')
+            [CompletionResult]::new('--help', 'help', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')')
+            break
+        }
+        'x.py;clippy' {
+            [CompletionResult]::new('-A', 'A', [CompletionResultType]::ParameterName, 'clippy lints to allow')
+            [CompletionResult]::new('-D', 'D', [CompletionResultType]::ParameterName, 'clippy lints to deny')
+            [CompletionResult]::new('-W', 'W', [CompletionResultType]::ParameterName, 'clippy lints to warn on')
+            [CompletionResult]::new('-F', 'F', [CompletionResultType]::ParameterName, 'clippy lints to forbid')
+            [CompletionResult]::new('--config', 'config', [CompletionResultType]::ParameterName, 'TOML configuration file for build')
+            [CompletionResult]::new('--build-dir', 'build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `config.toml`')
+            [CompletionResult]::new('--build', 'build', [CompletionResultType]::ParameterName, 'build target of the stage0 compiler')
+            [CompletionResult]::new('--host', 'host', [CompletionResultType]::ParameterName, 'host targets to build')
+            [CompletionResult]::new('--target', 'target', [CompletionResultType]::ParameterName, 'target targets to build')
+            [CompletionResult]::new('--exclude', 'exclude', [CompletionResultType]::ParameterName, 'build paths to exclude')
+            [CompletionResult]::new('--rustc-error-format', 'rustc-error-format', [CompletionResultType]::ParameterName, 'rustc-error-format')
+            [CompletionResult]::new('--on-fail', 'on-fail', [CompletionResultType]::ParameterName, 'command to run on failure')
+            [CompletionResult]::new('--stage', 'stage', [CompletionResultType]::ParameterName, 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)')
+            [CompletionResult]::new('--keep-stage', 'keep-stage', [CompletionResultType]::ParameterName, 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)')
+            [CompletionResult]::new('--keep-stage-std', 'keep-stage-std', [CompletionResultType]::ParameterName, 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)')
+            [CompletionResult]::new('--src', 'src', [CompletionResultType]::ParameterName, 'path to the root of the rust checkout')
+            [CompletionResult]::new('-j', 'j', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel')
+            [CompletionResult]::new('--jobs', 'jobs', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel')
+            [CompletionResult]::new('--warnings', 'warnings', [CompletionResultType]::ParameterName, 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour')
+            [CompletionResult]::new('--error-format', 'error-format', [CompletionResultType]::ParameterName, 'rustc error format')
+            [CompletionResult]::new('--color', 'color', [CompletionResultType]::ParameterName, 'whether to use color in cargo and rustc output')
+            [CompletionResult]::new('--llvm-skip-rebuild', 'llvm-skip-rebuild', [CompletionResultType]::ParameterName, 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml')
+            [CompletionResult]::new('--rust-profile-generate', 'rust-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with rustc build')
+            [CompletionResult]::new('--rust-profile-use', 'rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build')
+            [CompletionResult]::new('--llvm-profile-use', 'llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build')
+            [CompletionResult]::new('--llvm-bolt-profile-use', 'llvm-bolt-profile-use', [CompletionResultType]::ParameterName, 'use BOLT profile for LLVM build')
+            [CompletionResult]::new('--fix', 'fix', [CompletionResultType]::ParameterName, 'fix')
+            [CompletionResult]::new('-v', 'v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)')
+            [CompletionResult]::new('--verbose', 'verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)')
+            [CompletionResult]::new('-i', 'i', [CompletionResultType]::ParameterName, 'use incremental compilation')
+            [CompletionResult]::new('--incremental', 'incremental', [CompletionResultType]::ParameterName, 'use incremental compilation')
+            [CompletionResult]::new('--include-default-paths', 'include-default-paths', [CompletionResultType]::ParameterName, 'include default paths in addition to the provided ones')
+            [CompletionResult]::new('--dry-run', 'dry-run', [CompletionResultType]::ParameterName, 'dry run; don''t build anything')
+            [CompletionResult]::new('--json-output', 'json-output', [CompletionResultType]::ParameterName, 'use message-format=json')
+            [CompletionResult]::new('--llvm-profile-generate', 'llvm-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with llvm built for rustc')
+            [CompletionResult]::new('--llvm-bolt-profile-generate', 'llvm-bolt-profile-generate', [CompletionResultType]::ParameterName, 'generate BOLT profile for LLVM build')
+            [CompletionResult]::new('-h', 'h', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')')
+            [CompletionResult]::new('--help', 'help', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')')
+            break
+        }
+        'x.py;fix' {
+            [CompletionResult]::new('--config', 'config', [CompletionResultType]::ParameterName, 'TOML configuration file for build')
+            [CompletionResult]::new('--build-dir', 'build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `config.toml`')
+            [CompletionResult]::new('--build', 'build', [CompletionResultType]::ParameterName, 'build target of the stage0 compiler')
+            [CompletionResult]::new('--host', 'host', [CompletionResultType]::ParameterName, 'host targets to build')
+            [CompletionResult]::new('--target', 'target', [CompletionResultType]::ParameterName, 'target targets to build')
+            [CompletionResult]::new('--exclude', 'exclude', [CompletionResultType]::ParameterName, 'build paths to exclude')
+            [CompletionResult]::new('--rustc-error-format', 'rustc-error-format', [CompletionResultType]::ParameterName, 'rustc-error-format')
+            [CompletionResult]::new('--on-fail', 'on-fail', [CompletionResultType]::ParameterName, 'command to run on failure')
+            [CompletionResult]::new('--stage', 'stage', [CompletionResultType]::ParameterName, 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)')
+            [CompletionResult]::new('--keep-stage', 'keep-stage', [CompletionResultType]::ParameterName, 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)')
+            [CompletionResult]::new('--keep-stage-std', 'keep-stage-std', [CompletionResultType]::ParameterName, 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)')
+            [CompletionResult]::new('--src', 'src', [CompletionResultType]::ParameterName, 'path to the root of the rust checkout')
+            [CompletionResult]::new('-j', 'j', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel')
+            [CompletionResult]::new('--jobs', 'jobs', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel')
+            [CompletionResult]::new('--warnings', 'warnings', [CompletionResultType]::ParameterName, 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour')
+            [CompletionResult]::new('--error-format', 'error-format', [CompletionResultType]::ParameterName, 'rustc error format')
+            [CompletionResult]::new('--color', 'color', [CompletionResultType]::ParameterName, 'whether to use color in cargo and rustc output')
+            [CompletionResult]::new('--llvm-skip-rebuild', 'llvm-skip-rebuild', [CompletionResultType]::ParameterName, 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml')
+            [CompletionResult]::new('--rust-profile-generate', 'rust-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with rustc build')
+            [CompletionResult]::new('--rust-profile-use', 'rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build')
+            [CompletionResult]::new('--llvm-profile-use', 'llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build')
+            [CompletionResult]::new('--llvm-bolt-profile-use', 'llvm-bolt-profile-use', [CompletionResultType]::ParameterName, 'use BOLT profile for LLVM build')
+            [CompletionResult]::new('-v', 'v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)')
+            [CompletionResult]::new('--verbose', 'verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)')
+            [CompletionResult]::new('-i', 'i', [CompletionResultType]::ParameterName, 'use incremental compilation')
+            [CompletionResult]::new('--incremental', 'incremental', [CompletionResultType]::ParameterName, 'use incremental compilation')
+            [CompletionResult]::new('--include-default-paths', 'include-default-paths', [CompletionResultType]::ParameterName, 'include default paths in addition to the provided ones')
+            [CompletionResult]::new('--dry-run', 'dry-run', [CompletionResultType]::ParameterName, 'dry run; don''t build anything')
+            [CompletionResult]::new('--json-output', 'json-output', [CompletionResultType]::ParameterName, 'use message-format=json')
+            [CompletionResult]::new('--llvm-profile-generate', 'llvm-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with llvm built for rustc')
+            [CompletionResult]::new('--llvm-bolt-profile-generate', 'llvm-bolt-profile-generate', [CompletionResultType]::ParameterName, 'generate BOLT profile for LLVM build')
+            [CompletionResult]::new('-h', 'h', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')')
+            [CompletionResult]::new('--help', 'help', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')')
+            break
+        }
+        'x.py;fmt' {
+            [CompletionResult]::new('--config', 'config', [CompletionResultType]::ParameterName, 'TOML configuration file for build')
+            [CompletionResult]::new('--build-dir', 'build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `config.toml`')
+            [CompletionResult]::new('--build', 'build', [CompletionResultType]::ParameterName, 'build target of the stage0 compiler')
+            [CompletionResult]::new('--host', 'host', [CompletionResultType]::ParameterName, 'host targets to build')
+            [CompletionResult]::new('--target', 'target', [CompletionResultType]::ParameterName, 'target targets to build')
+            [CompletionResult]::new('--exclude', 'exclude', [CompletionResultType]::ParameterName, 'build paths to exclude')
+            [CompletionResult]::new('--rustc-error-format', 'rustc-error-format', [CompletionResultType]::ParameterName, 'rustc-error-format')
+            [CompletionResult]::new('--on-fail', 'on-fail', [CompletionResultType]::ParameterName, 'command to run on failure')
+            [CompletionResult]::new('--stage', 'stage', [CompletionResultType]::ParameterName, 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)')
+            [CompletionResult]::new('--keep-stage', 'keep-stage', [CompletionResultType]::ParameterName, 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)')
+            [CompletionResult]::new('--keep-stage-std', 'keep-stage-std', [CompletionResultType]::ParameterName, 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)')
+            [CompletionResult]::new('--src', 'src', [CompletionResultType]::ParameterName, 'path to the root of the rust checkout')
+            [CompletionResult]::new('-j', 'j', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel')
+            [CompletionResult]::new('--jobs', 'jobs', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel')
+            [CompletionResult]::new('--warnings', 'warnings', [CompletionResultType]::ParameterName, 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour')
+            [CompletionResult]::new('--error-format', 'error-format', [CompletionResultType]::ParameterName, 'rustc error format')
+            [CompletionResult]::new('--color', 'color', [CompletionResultType]::ParameterName, 'whether to use color in cargo and rustc output')
+            [CompletionResult]::new('--llvm-skip-rebuild', 'llvm-skip-rebuild', [CompletionResultType]::ParameterName, 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml')
+            [CompletionResult]::new('--rust-profile-generate', 'rust-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with rustc build')
+            [CompletionResult]::new('--rust-profile-use', 'rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build')
+            [CompletionResult]::new('--llvm-profile-use', 'llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build')
+            [CompletionResult]::new('--llvm-bolt-profile-use', 'llvm-bolt-profile-use', [CompletionResultType]::ParameterName, 'use BOLT profile for LLVM build')
+            [CompletionResult]::new('--check', 'check', [CompletionResultType]::ParameterName, 'check formatting instead of applying')
+            [CompletionResult]::new('-v', 'v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)')
+            [CompletionResult]::new('--verbose', 'verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)')
+            [CompletionResult]::new('-i', 'i', [CompletionResultType]::ParameterName, 'use incremental compilation')
+            [CompletionResult]::new('--incremental', 'incremental', [CompletionResultType]::ParameterName, 'use incremental compilation')
+            [CompletionResult]::new('--include-default-paths', 'include-default-paths', [CompletionResultType]::ParameterName, 'include default paths in addition to the provided ones')
+            [CompletionResult]::new('--dry-run', 'dry-run', [CompletionResultType]::ParameterName, 'dry run; don''t build anything')
+            [CompletionResult]::new('--json-output', 'json-output', [CompletionResultType]::ParameterName, 'use message-format=json')
+            [CompletionResult]::new('--llvm-profile-generate', 'llvm-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with llvm built for rustc')
+            [CompletionResult]::new('--llvm-bolt-profile-generate', 'llvm-bolt-profile-generate', [CompletionResultType]::ParameterName, 'generate BOLT profile for LLVM build')
+            [CompletionResult]::new('-h', 'h', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')')
+            [CompletionResult]::new('--help', 'help', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')')
+            break
+        }
+        'x.py;doc' {
+            [CompletionResult]::new('--config', 'config', [CompletionResultType]::ParameterName, 'TOML configuration file for build')
+            [CompletionResult]::new('--build-dir', 'build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `config.toml`')
+            [CompletionResult]::new('--build', 'build', [CompletionResultType]::ParameterName, 'build target of the stage0 compiler')
+            [CompletionResult]::new('--host', 'host', [CompletionResultType]::ParameterName, 'host targets to build')
+            [CompletionResult]::new('--target', 'target', [CompletionResultType]::ParameterName, 'target targets to build')
+            [CompletionResult]::new('--exclude', 'exclude', [CompletionResultType]::ParameterName, 'build paths to exclude')
+            [CompletionResult]::new('--rustc-error-format', 'rustc-error-format', [CompletionResultType]::ParameterName, 'rustc-error-format')
+            [CompletionResult]::new('--on-fail', 'on-fail', [CompletionResultType]::ParameterName, 'command to run on failure')
+            [CompletionResult]::new('--stage', 'stage', [CompletionResultType]::ParameterName, 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)')
+            [CompletionResult]::new('--keep-stage', 'keep-stage', [CompletionResultType]::ParameterName, 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)')
+            [CompletionResult]::new('--keep-stage-std', 'keep-stage-std', [CompletionResultType]::ParameterName, 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)')
+            [CompletionResult]::new('--src', 'src', [CompletionResultType]::ParameterName, 'path to the root of the rust checkout')
+            [CompletionResult]::new('-j', 'j', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel')
+            [CompletionResult]::new('--jobs', 'jobs', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel')
+            [CompletionResult]::new('--warnings', 'warnings', [CompletionResultType]::ParameterName, 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour')
+            [CompletionResult]::new('--error-format', 'error-format', [CompletionResultType]::ParameterName, 'rustc error format')
+            [CompletionResult]::new('--color', 'color', [CompletionResultType]::ParameterName, 'whether to use color in cargo and rustc output')
+            [CompletionResult]::new('--llvm-skip-rebuild', 'llvm-skip-rebuild', [CompletionResultType]::ParameterName, 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml')
+            [CompletionResult]::new('--rust-profile-generate', 'rust-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with rustc build')
+            [CompletionResult]::new('--rust-profile-use', 'rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build')
+            [CompletionResult]::new('--llvm-profile-use', 'llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build')
+            [CompletionResult]::new('--llvm-bolt-profile-use', 'llvm-bolt-profile-use', [CompletionResultType]::ParameterName, 'use BOLT profile for LLVM build')
+            [CompletionResult]::new('--open', 'open', [CompletionResultType]::ParameterName, 'open the docs in a browser')
+            [CompletionResult]::new('--json', 'json', [CompletionResultType]::ParameterName, 'render the documentation in JSON format in addition to the usual HTML format')
+            [CompletionResult]::new('-v', 'v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)')
+            [CompletionResult]::new('--verbose', 'verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)')
+            [CompletionResult]::new('-i', 'i', [CompletionResultType]::ParameterName, 'use incremental compilation')
+            [CompletionResult]::new('--incremental', 'incremental', [CompletionResultType]::ParameterName, 'use incremental compilation')
+            [CompletionResult]::new('--include-default-paths', 'include-default-paths', [CompletionResultType]::ParameterName, 'include default paths in addition to the provided ones')
+            [CompletionResult]::new('--dry-run', 'dry-run', [CompletionResultType]::ParameterName, 'dry run; don''t build anything')
+            [CompletionResult]::new('--json-output', 'json-output', [CompletionResultType]::ParameterName, 'use message-format=json')
+            [CompletionResult]::new('--llvm-profile-generate', 'llvm-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with llvm built for rustc')
+            [CompletionResult]::new('--llvm-bolt-profile-generate', 'llvm-bolt-profile-generate', [CompletionResultType]::ParameterName, 'generate BOLT profile for LLVM build')
+            [CompletionResult]::new('-h', 'h', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')')
+            [CompletionResult]::new('--help', 'help', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')')
+            break
+        }
+        'x.py;test' {
+            [CompletionResult]::new('--skip', 'skip', [CompletionResultType]::ParameterName, 'skips tests matching SUBSTRING, if supported by test tool. May be passed multiple times')
+            [CompletionResult]::new('--test-args', 'test-args', [CompletionResultType]::ParameterName, 'extra arguments to be passed for the test tool being used (e.g. libtest, compiletest or rustdoc)')
+            [CompletionResult]::new('--rustc-args', 'rustc-args', [CompletionResultType]::ParameterName, 'extra options to pass the compiler when running tests')
+            [CompletionResult]::new('--compare-mode', 'compare-mode', [CompletionResultType]::ParameterName, 'mode describing what file the actual ui output will be compared to')
+            [CompletionResult]::new('--pass', 'pass', [CompletionResultType]::ParameterName, 'force {check,build,run}-pass tests to this mode')
+            [CompletionResult]::new('--run', 'run', [CompletionResultType]::ParameterName, 'whether to execute run-* tests')
+            [CompletionResult]::new('--config', 'config', [CompletionResultType]::ParameterName, 'TOML configuration file for build')
+            [CompletionResult]::new('--build-dir', 'build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `config.toml`')
+            [CompletionResult]::new('--build', 'build', [CompletionResultType]::ParameterName, 'build target of the stage0 compiler')
+            [CompletionResult]::new('--host', 'host', [CompletionResultType]::ParameterName, 'host targets to build')
+            [CompletionResult]::new('--target', 'target', [CompletionResultType]::ParameterName, 'target targets to build')
+            [CompletionResult]::new('--exclude', 'exclude', [CompletionResultType]::ParameterName, 'build paths to exclude')
+            [CompletionResult]::new('--rustc-error-format', 'rustc-error-format', [CompletionResultType]::ParameterName, 'rustc-error-format')
+            [CompletionResult]::new('--on-fail', 'on-fail', [CompletionResultType]::ParameterName, 'command to run on failure')
+            [CompletionResult]::new('--stage', 'stage', [CompletionResultType]::ParameterName, 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)')
+            [CompletionResult]::new('--keep-stage', 'keep-stage', [CompletionResultType]::ParameterName, 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)')
+            [CompletionResult]::new('--keep-stage-std', 'keep-stage-std', [CompletionResultType]::ParameterName, 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)')
+            [CompletionResult]::new('--src', 'src', [CompletionResultType]::ParameterName, 'path to the root of the rust checkout')
+            [CompletionResult]::new('-j', 'j', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel')
+            [CompletionResult]::new('--jobs', 'jobs', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel')
+            [CompletionResult]::new('--warnings', 'warnings', [CompletionResultType]::ParameterName, 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour')
+            [CompletionResult]::new('--error-format', 'error-format', [CompletionResultType]::ParameterName, 'rustc error format')
+            [CompletionResult]::new('--color', 'color', [CompletionResultType]::ParameterName, 'whether to use color in cargo and rustc output')
+            [CompletionResult]::new('--llvm-skip-rebuild', 'llvm-skip-rebuild', [CompletionResultType]::ParameterName, 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml')
+            [CompletionResult]::new('--rust-profile-generate', 'rust-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with rustc build')
+            [CompletionResult]::new('--rust-profile-use', 'rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build')
+            [CompletionResult]::new('--llvm-profile-use', 'llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build')
+            [CompletionResult]::new('--llvm-bolt-profile-use', 'llvm-bolt-profile-use', [CompletionResultType]::ParameterName, 'use BOLT profile for LLVM build')
+            [CompletionResult]::new('--no-fail-fast', 'no-fail-fast', [CompletionResultType]::ParameterName, 'run all tests regardless of failure')
+            [CompletionResult]::new('--no-doc', 'no-doc', [CompletionResultType]::ParameterName, 'do not run doc tests')
+            [CompletionResult]::new('--doc', 'doc', [CompletionResultType]::ParameterName, 'only run doc tests')
+            [CompletionResult]::new('--bless', 'bless', [CompletionResultType]::ParameterName, 'whether to automatically update stderr/stdout files')
+            [CompletionResult]::new('--force-rerun', 'force-rerun', [CompletionResultType]::ParameterName, 'rerun tests even if the inputs are unchanged')
+            [CompletionResult]::new('--only-modified', 'only-modified', [CompletionResultType]::ParameterName, 'only run tests that result has been changed')
+            [CompletionResult]::new('--rustfix-coverage', 'rustfix-coverage', [CompletionResultType]::ParameterName, 'enable this to generate a Rustfix coverage file, which is saved in `/<build_base>/rustfix_missing_coverage.txt`')
+            [CompletionResult]::new('-v', 'v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)')
+            [CompletionResult]::new('--verbose', 'verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)')
+            [CompletionResult]::new('-i', 'i', [CompletionResultType]::ParameterName, 'use incremental compilation')
+            [CompletionResult]::new('--incremental', 'incremental', [CompletionResultType]::ParameterName, 'use incremental compilation')
+            [CompletionResult]::new('--include-default-paths', 'include-default-paths', [CompletionResultType]::ParameterName, 'include default paths in addition to the provided ones')
+            [CompletionResult]::new('--dry-run', 'dry-run', [CompletionResultType]::ParameterName, 'dry run; don''t build anything')
+            [CompletionResult]::new('--json-output', 'json-output', [CompletionResultType]::ParameterName, 'use message-format=json')
+            [CompletionResult]::new('--llvm-profile-generate', 'llvm-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with llvm built for rustc')
+            [CompletionResult]::new('--llvm-bolt-profile-generate', 'llvm-bolt-profile-generate', [CompletionResultType]::ParameterName, 'generate BOLT profile for LLVM build')
+            [CompletionResult]::new('-h', 'h', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')')
+            [CompletionResult]::new('--help', 'help', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')')
+            break
+        }
+        'x.py;bench' {
+            [CompletionResult]::new('--test-args', 'test-args', [CompletionResultType]::ParameterName, 'test-args')
+            [CompletionResult]::new('--config', 'config', [CompletionResultType]::ParameterName, 'TOML configuration file for build')
+            [CompletionResult]::new('--build-dir', 'build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `config.toml`')
+            [CompletionResult]::new('--build', 'build', [CompletionResultType]::ParameterName, 'build target of the stage0 compiler')
+            [CompletionResult]::new('--host', 'host', [CompletionResultType]::ParameterName, 'host targets to build')
+            [CompletionResult]::new('--target', 'target', [CompletionResultType]::ParameterName, 'target targets to build')
+            [CompletionResult]::new('--exclude', 'exclude', [CompletionResultType]::ParameterName, 'build paths to exclude')
+            [CompletionResult]::new('--rustc-error-format', 'rustc-error-format', [CompletionResultType]::ParameterName, 'rustc-error-format')
+            [CompletionResult]::new('--on-fail', 'on-fail', [CompletionResultType]::ParameterName, 'command to run on failure')
+            [CompletionResult]::new('--stage', 'stage', [CompletionResultType]::ParameterName, 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)')
+            [CompletionResult]::new('--keep-stage', 'keep-stage', [CompletionResultType]::ParameterName, 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)')
+            [CompletionResult]::new('--keep-stage-std', 'keep-stage-std', [CompletionResultType]::ParameterName, 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)')
+            [CompletionResult]::new('--src', 'src', [CompletionResultType]::ParameterName, 'path to the root of the rust checkout')
+            [CompletionResult]::new('-j', 'j', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel')
+            [CompletionResult]::new('--jobs', 'jobs', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel')
+            [CompletionResult]::new('--warnings', 'warnings', [CompletionResultType]::ParameterName, 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour')
+            [CompletionResult]::new('--error-format', 'error-format', [CompletionResultType]::ParameterName, 'rustc error format')
+            [CompletionResult]::new('--color', 'color', [CompletionResultType]::ParameterName, 'whether to use color in cargo and rustc output')
+            [CompletionResult]::new('--llvm-skip-rebuild', 'llvm-skip-rebuild', [CompletionResultType]::ParameterName, 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml')
+            [CompletionResult]::new('--rust-profile-generate', 'rust-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with rustc build')
+            [CompletionResult]::new('--rust-profile-use', 'rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build')
+            [CompletionResult]::new('--llvm-profile-use', 'llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build')
+            [CompletionResult]::new('--llvm-bolt-profile-use', 'llvm-bolt-profile-use', [CompletionResultType]::ParameterName, 'use BOLT profile for LLVM build')
+            [CompletionResult]::new('-v', 'v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)')
+            [CompletionResult]::new('--verbose', 'verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)')
+            [CompletionResult]::new('-i', 'i', [CompletionResultType]::ParameterName, 'use incremental compilation')
+            [CompletionResult]::new('--incremental', 'incremental', [CompletionResultType]::ParameterName, 'use incremental compilation')
+            [CompletionResult]::new('--include-default-paths', 'include-default-paths', [CompletionResultType]::ParameterName, 'include default paths in addition to the provided ones')
+            [CompletionResult]::new('--dry-run', 'dry-run', [CompletionResultType]::ParameterName, 'dry run; don''t build anything')
+            [CompletionResult]::new('--json-output', 'json-output', [CompletionResultType]::ParameterName, 'use message-format=json')
+            [CompletionResult]::new('--llvm-profile-generate', 'llvm-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with llvm built for rustc')
+            [CompletionResult]::new('--llvm-bolt-profile-generate', 'llvm-bolt-profile-generate', [CompletionResultType]::ParameterName, 'generate BOLT profile for LLVM build')
+            [CompletionResult]::new('-h', 'h', [CompletionResultType]::ParameterName, 'Print help')
+            [CompletionResult]::new('--help', 'help', [CompletionResultType]::ParameterName, 'Print help')
+            break
+        }
+        'x.py;clean' {
+            [CompletionResult]::new('--config', 'config', [CompletionResultType]::ParameterName, 'TOML configuration file for build')
+            [CompletionResult]::new('--build-dir', 'build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `config.toml`')
+            [CompletionResult]::new('--build', 'build', [CompletionResultType]::ParameterName, 'build target of the stage0 compiler')
+            [CompletionResult]::new('--host', 'host', [CompletionResultType]::ParameterName, 'host targets to build')
+            [CompletionResult]::new('--target', 'target', [CompletionResultType]::ParameterName, 'target targets to build')
+            [CompletionResult]::new('--exclude', 'exclude', [CompletionResultType]::ParameterName, 'build paths to exclude')
+            [CompletionResult]::new('--rustc-error-format', 'rustc-error-format', [CompletionResultType]::ParameterName, 'rustc-error-format')
+            [CompletionResult]::new('--on-fail', 'on-fail', [CompletionResultType]::ParameterName, 'command to run on failure')
+            [CompletionResult]::new('--stage', 'stage', [CompletionResultType]::ParameterName, 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)')
+            [CompletionResult]::new('--keep-stage', 'keep-stage', [CompletionResultType]::ParameterName, 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)')
+            [CompletionResult]::new('--keep-stage-std', 'keep-stage-std', [CompletionResultType]::ParameterName, 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)')
+            [CompletionResult]::new('--src', 'src', [CompletionResultType]::ParameterName, 'path to the root of the rust checkout')
+            [CompletionResult]::new('-j', 'j', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel')
+            [CompletionResult]::new('--jobs', 'jobs', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel')
+            [CompletionResult]::new('--warnings', 'warnings', [CompletionResultType]::ParameterName, 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour')
+            [CompletionResult]::new('--error-format', 'error-format', [CompletionResultType]::ParameterName, 'rustc error format')
+            [CompletionResult]::new('--color', 'color', [CompletionResultType]::ParameterName, 'whether to use color in cargo and rustc output')
+            [CompletionResult]::new('--llvm-skip-rebuild', 'llvm-skip-rebuild', [CompletionResultType]::ParameterName, 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml')
+            [CompletionResult]::new('--rust-profile-generate', 'rust-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with rustc build')
+            [CompletionResult]::new('--rust-profile-use', 'rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build')
+            [CompletionResult]::new('--llvm-profile-use', 'llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build')
+            [CompletionResult]::new('--llvm-bolt-profile-use', 'llvm-bolt-profile-use', [CompletionResultType]::ParameterName, 'use BOLT profile for LLVM build')
+            [CompletionResult]::new('--all', 'all', [CompletionResultType]::ParameterName, 'all')
+            [CompletionResult]::new('-v', 'v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)')
+            [CompletionResult]::new('--verbose', 'verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)')
+            [CompletionResult]::new('-i', 'i', [CompletionResultType]::ParameterName, 'use incremental compilation')
+            [CompletionResult]::new('--incremental', 'incremental', [CompletionResultType]::ParameterName, 'use incremental compilation')
+            [CompletionResult]::new('--include-default-paths', 'include-default-paths', [CompletionResultType]::ParameterName, 'include default paths in addition to the provided ones')
+            [CompletionResult]::new('--dry-run', 'dry-run', [CompletionResultType]::ParameterName, 'dry run; don''t build anything')
+            [CompletionResult]::new('--json-output', 'json-output', [CompletionResultType]::ParameterName, 'use message-format=json')
+            [CompletionResult]::new('--llvm-profile-generate', 'llvm-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with llvm built for rustc')
+            [CompletionResult]::new('--llvm-bolt-profile-generate', 'llvm-bolt-profile-generate', [CompletionResultType]::ParameterName, 'generate BOLT profile for LLVM build')
+            [CompletionResult]::new('-h', 'h', [CompletionResultType]::ParameterName, 'Print help')
+            [CompletionResult]::new('--help', 'help', [CompletionResultType]::ParameterName, 'Print help')
+            break
+        }
+        'x.py;dist' {
+            [CompletionResult]::new('--config', 'config', [CompletionResultType]::ParameterName, 'TOML configuration file for build')
+            [CompletionResult]::new('--build-dir', 'build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `config.toml`')
+            [CompletionResult]::new('--build', 'build', [CompletionResultType]::ParameterName, 'build target of the stage0 compiler')
+            [CompletionResult]::new('--host', 'host', [CompletionResultType]::ParameterName, 'host targets to build')
+            [CompletionResult]::new('--target', 'target', [CompletionResultType]::ParameterName, 'target targets to build')
+            [CompletionResult]::new('--exclude', 'exclude', [CompletionResultType]::ParameterName, 'build paths to exclude')
+            [CompletionResult]::new('--rustc-error-format', 'rustc-error-format', [CompletionResultType]::ParameterName, 'rustc-error-format')
+            [CompletionResult]::new('--on-fail', 'on-fail', [CompletionResultType]::ParameterName, 'command to run on failure')
+            [CompletionResult]::new('--stage', 'stage', [CompletionResultType]::ParameterName, 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)')
+            [CompletionResult]::new('--keep-stage', 'keep-stage', [CompletionResultType]::ParameterName, 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)')
+            [CompletionResult]::new('--keep-stage-std', 'keep-stage-std', [CompletionResultType]::ParameterName, 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)')
+            [CompletionResult]::new('--src', 'src', [CompletionResultType]::ParameterName, 'path to the root of the rust checkout')
+            [CompletionResult]::new('-j', 'j', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel')
+            [CompletionResult]::new('--jobs', 'jobs', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel')
+            [CompletionResult]::new('--warnings', 'warnings', [CompletionResultType]::ParameterName, 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour')
+            [CompletionResult]::new('--error-format', 'error-format', [CompletionResultType]::ParameterName, 'rustc error format')
+            [CompletionResult]::new('--color', 'color', [CompletionResultType]::ParameterName, 'whether to use color in cargo and rustc output')
+            [CompletionResult]::new('--llvm-skip-rebuild', 'llvm-skip-rebuild', [CompletionResultType]::ParameterName, 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml')
+            [CompletionResult]::new('--rust-profile-generate', 'rust-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with rustc build')
+            [CompletionResult]::new('--rust-profile-use', 'rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build')
+            [CompletionResult]::new('--llvm-profile-use', 'llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build')
+            [CompletionResult]::new('--llvm-bolt-profile-use', 'llvm-bolt-profile-use', [CompletionResultType]::ParameterName, 'use BOLT profile for LLVM build')
+            [CompletionResult]::new('-v', 'v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)')
+            [CompletionResult]::new('--verbose', 'verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)')
+            [CompletionResult]::new('-i', 'i', [CompletionResultType]::ParameterName, 'use incremental compilation')
+            [CompletionResult]::new('--incremental', 'incremental', [CompletionResultType]::ParameterName, 'use incremental compilation')
+            [CompletionResult]::new('--include-default-paths', 'include-default-paths', [CompletionResultType]::ParameterName, 'include default paths in addition to the provided ones')
+            [CompletionResult]::new('--dry-run', 'dry-run', [CompletionResultType]::ParameterName, 'dry run; don''t build anything')
+            [CompletionResult]::new('--json-output', 'json-output', [CompletionResultType]::ParameterName, 'use message-format=json')
+            [CompletionResult]::new('--llvm-profile-generate', 'llvm-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with llvm built for rustc')
+            [CompletionResult]::new('--llvm-bolt-profile-generate', 'llvm-bolt-profile-generate', [CompletionResultType]::ParameterName, 'generate BOLT profile for LLVM build')
+            [CompletionResult]::new('-h', 'h', [CompletionResultType]::ParameterName, 'Print help')
+            [CompletionResult]::new('--help', 'help', [CompletionResultType]::ParameterName, 'Print help')
+            break
+        }
+        'x.py;install' {
+            [CompletionResult]::new('--config', 'config', [CompletionResultType]::ParameterName, 'TOML configuration file for build')
+            [CompletionResult]::new('--build-dir', 'build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `config.toml`')
+            [CompletionResult]::new('--build', 'build', [CompletionResultType]::ParameterName, 'build target of the stage0 compiler')
+            [CompletionResult]::new('--host', 'host', [CompletionResultType]::ParameterName, 'host targets to build')
+            [CompletionResult]::new('--target', 'target', [CompletionResultType]::ParameterName, 'target targets to build')
+            [CompletionResult]::new('--exclude', 'exclude', [CompletionResultType]::ParameterName, 'build paths to exclude')
+            [CompletionResult]::new('--rustc-error-format', 'rustc-error-format', [CompletionResultType]::ParameterName, 'rustc-error-format')
+            [CompletionResult]::new('--on-fail', 'on-fail', [CompletionResultType]::ParameterName, 'command to run on failure')
+            [CompletionResult]::new('--stage', 'stage', [CompletionResultType]::ParameterName, 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)')
+            [CompletionResult]::new('--keep-stage', 'keep-stage', [CompletionResultType]::ParameterName, 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)')
+            [CompletionResult]::new('--keep-stage-std', 'keep-stage-std', [CompletionResultType]::ParameterName, 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)')
+            [CompletionResult]::new('--src', 'src', [CompletionResultType]::ParameterName, 'path to the root of the rust checkout')
+            [CompletionResult]::new('-j', 'j', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel')
+            [CompletionResult]::new('--jobs', 'jobs', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel')
+            [CompletionResult]::new('--warnings', 'warnings', [CompletionResultType]::ParameterName, 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour')
+            [CompletionResult]::new('--error-format', 'error-format', [CompletionResultType]::ParameterName, 'rustc error format')
+            [CompletionResult]::new('--color', 'color', [CompletionResultType]::ParameterName, 'whether to use color in cargo and rustc output')
+            [CompletionResult]::new('--llvm-skip-rebuild', 'llvm-skip-rebuild', [CompletionResultType]::ParameterName, 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml')
+            [CompletionResult]::new('--rust-profile-generate', 'rust-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with rustc build')
+            [CompletionResult]::new('--rust-profile-use', 'rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build')
+            [CompletionResult]::new('--llvm-profile-use', 'llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build')
+            [CompletionResult]::new('--llvm-bolt-profile-use', 'llvm-bolt-profile-use', [CompletionResultType]::ParameterName, 'use BOLT profile for LLVM build')
+            [CompletionResult]::new('-v', 'v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)')
+            [CompletionResult]::new('--verbose', 'verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)')
+            [CompletionResult]::new('-i', 'i', [CompletionResultType]::ParameterName, 'use incremental compilation')
+            [CompletionResult]::new('--incremental', 'incremental', [CompletionResultType]::ParameterName, 'use incremental compilation')
+            [CompletionResult]::new('--include-default-paths', 'include-default-paths', [CompletionResultType]::ParameterName, 'include default paths in addition to the provided ones')
+            [CompletionResult]::new('--dry-run', 'dry-run', [CompletionResultType]::ParameterName, 'dry run; don''t build anything')
+            [CompletionResult]::new('--json-output', 'json-output', [CompletionResultType]::ParameterName, 'use message-format=json')
+            [CompletionResult]::new('--llvm-profile-generate', 'llvm-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with llvm built for rustc')
+            [CompletionResult]::new('--llvm-bolt-profile-generate', 'llvm-bolt-profile-generate', [CompletionResultType]::ParameterName, 'generate BOLT profile for LLVM build')
+            [CompletionResult]::new('-h', 'h', [CompletionResultType]::ParameterName, 'Print help')
+            [CompletionResult]::new('--help', 'help', [CompletionResultType]::ParameterName, 'Print help')
+            break
+        }
+        'x.py;run' {
+            [CompletionResult]::new('--args', 'args', [CompletionResultType]::ParameterName, 'arguments for the tool')
+            [CompletionResult]::new('--config', 'config', [CompletionResultType]::ParameterName, 'TOML configuration file for build')
+            [CompletionResult]::new('--build-dir', 'build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `config.toml`')
+            [CompletionResult]::new('--build', 'build', [CompletionResultType]::ParameterName, 'build target of the stage0 compiler')
+            [CompletionResult]::new('--host', 'host', [CompletionResultType]::ParameterName, 'host targets to build')
+            [CompletionResult]::new('--target', 'target', [CompletionResultType]::ParameterName, 'target targets to build')
+            [CompletionResult]::new('--exclude', 'exclude', [CompletionResultType]::ParameterName, 'build paths to exclude')
+            [CompletionResult]::new('--rustc-error-format', 'rustc-error-format', [CompletionResultType]::ParameterName, 'rustc-error-format')
+            [CompletionResult]::new('--on-fail', 'on-fail', [CompletionResultType]::ParameterName, 'command to run on failure')
+            [CompletionResult]::new('--stage', 'stage', [CompletionResultType]::ParameterName, 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)')
+            [CompletionResult]::new('--keep-stage', 'keep-stage', [CompletionResultType]::ParameterName, 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)')
+            [CompletionResult]::new('--keep-stage-std', 'keep-stage-std', [CompletionResultType]::ParameterName, 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)')
+            [CompletionResult]::new('--src', 'src', [CompletionResultType]::ParameterName, 'path to the root of the rust checkout')
+            [CompletionResult]::new('-j', 'j', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel')
+            [CompletionResult]::new('--jobs', 'jobs', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel')
+            [CompletionResult]::new('--warnings', 'warnings', [CompletionResultType]::ParameterName, 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour')
+            [CompletionResult]::new('--error-format', 'error-format', [CompletionResultType]::ParameterName, 'rustc error format')
+            [CompletionResult]::new('--color', 'color', [CompletionResultType]::ParameterName, 'whether to use color in cargo and rustc output')
+            [CompletionResult]::new('--llvm-skip-rebuild', 'llvm-skip-rebuild', [CompletionResultType]::ParameterName, 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml')
+            [CompletionResult]::new('--rust-profile-generate', 'rust-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with rustc build')
+            [CompletionResult]::new('--rust-profile-use', 'rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build')
+            [CompletionResult]::new('--llvm-profile-use', 'llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build')
+            [CompletionResult]::new('--llvm-bolt-profile-use', 'llvm-bolt-profile-use', [CompletionResultType]::ParameterName, 'use BOLT profile for LLVM build')
+            [CompletionResult]::new('-v', 'v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)')
+            [CompletionResult]::new('--verbose', 'verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)')
+            [CompletionResult]::new('-i', 'i', [CompletionResultType]::ParameterName, 'use incremental compilation')
+            [CompletionResult]::new('--incremental', 'incremental', [CompletionResultType]::ParameterName, 'use incremental compilation')
+            [CompletionResult]::new('--include-default-paths', 'include-default-paths', [CompletionResultType]::ParameterName, 'include default paths in addition to the provided ones')
+            [CompletionResult]::new('--dry-run', 'dry-run', [CompletionResultType]::ParameterName, 'dry run; don''t build anything')
+            [CompletionResult]::new('--json-output', 'json-output', [CompletionResultType]::ParameterName, 'use message-format=json')
+            [CompletionResult]::new('--llvm-profile-generate', 'llvm-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with llvm built for rustc')
+            [CompletionResult]::new('--llvm-bolt-profile-generate', 'llvm-bolt-profile-generate', [CompletionResultType]::ParameterName, 'generate BOLT profile for LLVM build')
+            [CompletionResult]::new('-h', 'h', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')')
+            [CompletionResult]::new('--help', 'help', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')')
+            break
+        }
+        'x.py;setup' {
+            [CompletionResult]::new('--config', 'config', [CompletionResultType]::ParameterName, 'TOML configuration file for build')
+            [CompletionResult]::new('--build-dir', 'build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `config.toml`')
+            [CompletionResult]::new('--build', 'build', [CompletionResultType]::ParameterName, 'build target of the stage0 compiler')
+            [CompletionResult]::new('--host', 'host', [CompletionResultType]::ParameterName, 'host targets to build')
+            [CompletionResult]::new('--target', 'target', [CompletionResultType]::ParameterName, 'target targets to build')
+            [CompletionResult]::new('--exclude', 'exclude', [CompletionResultType]::ParameterName, 'build paths to exclude')
+            [CompletionResult]::new('--rustc-error-format', 'rustc-error-format', [CompletionResultType]::ParameterName, 'rustc-error-format')
+            [CompletionResult]::new('--on-fail', 'on-fail', [CompletionResultType]::ParameterName, 'command to run on failure')
+            [CompletionResult]::new('--stage', 'stage', [CompletionResultType]::ParameterName, 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)')
+            [CompletionResult]::new('--keep-stage', 'keep-stage', [CompletionResultType]::ParameterName, 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)')
+            [CompletionResult]::new('--keep-stage-std', 'keep-stage-std', [CompletionResultType]::ParameterName, 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)')
+            [CompletionResult]::new('--src', 'src', [CompletionResultType]::ParameterName, 'path to the root of the rust checkout')
+            [CompletionResult]::new('-j', 'j', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel')
+            [CompletionResult]::new('--jobs', 'jobs', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel')
+            [CompletionResult]::new('--warnings', 'warnings', [CompletionResultType]::ParameterName, 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour')
+            [CompletionResult]::new('--error-format', 'error-format', [CompletionResultType]::ParameterName, 'rustc error format')
+            [CompletionResult]::new('--color', 'color', [CompletionResultType]::ParameterName, 'whether to use color in cargo and rustc output')
+            [CompletionResult]::new('--llvm-skip-rebuild', 'llvm-skip-rebuild', [CompletionResultType]::ParameterName, 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml')
+            [CompletionResult]::new('--rust-profile-generate', 'rust-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with rustc build')
+            [CompletionResult]::new('--rust-profile-use', 'rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build')
+            [CompletionResult]::new('--llvm-profile-use', 'llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build')
+            [CompletionResult]::new('--llvm-bolt-profile-use', 'llvm-bolt-profile-use', [CompletionResultType]::ParameterName, 'use BOLT profile for LLVM build')
+            [CompletionResult]::new('-v', 'v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)')
+            [CompletionResult]::new('--verbose', 'verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)')
+            [CompletionResult]::new('-i', 'i', [CompletionResultType]::ParameterName, 'use incremental compilation')
+            [CompletionResult]::new('--incremental', 'incremental', [CompletionResultType]::ParameterName, 'use incremental compilation')
+            [CompletionResult]::new('--include-default-paths', 'include-default-paths', [CompletionResultType]::ParameterName, 'include default paths in addition to the provided ones')
+            [CompletionResult]::new('--dry-run', 'dry-run', [CompletionResultType]::ParameterName, 'dry run; don''t build anything')
+            [CompletionResult]::new('--json-output', 'json-output', [CompletionResultType]::ParameterName, 'use message-format=json')
+            [CompletionResult]::new('--llvm-profile-generate', 'llvm-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with llvm built for rustc')
+            [CompletionResult]::new('--llvm-bolt-profile-generate', 'llvm-bolt-profile-generate', [CompletionResultType]::ParameterName, 'generate BOLT profile for LLVM build')
+            [CompletionResult]::new('-h', 'h', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')')
+            [CompletionResult]::new('--help', 'help', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')')
+            break
+        }
+        'x.py;suggest' {
+            [CompletionResult]::new('--config', 'config', [CompletionResultType]::ParameterName, 'TOML configuration file for build')
+            [CompletionResult]::new('--build-dir', 'build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `config.toml`')
+            [CompletionResult]::new('--build', 'build', [CompletionResultType]::ParameterName, 'build target of the stage0 compiler')
+            [CompletionResult]::new('--host', 'host', [CompletionResultType]::ParameterName, 'host targets to build')
+            [CompletionResult]::new('--target', 'target', [CompletionResultType]::ParameterName, 'target targets to build')
+            [CompletionResult]::new('--exclude', 'exclude', [CompletionResultType]::ParameterName, 'build paths to exclude')
+            [CompletionResult]::new('--rustc-error-format', 'rustc-error-format', [CompletionResultType]::ParameterName, 'rustc-error-format')
+            [CompletionResult]::new('--on-fail', 'on-fail', [CompletionResultType]::ParameterName, 'command to run on failure')
+            [CompletionResult]::new('--stage', 'stage', [CompletionResultType]::ParameterName, 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)')
+            [CompletionResult]::new('--keep-stage', 'keep-stage', [CompletionResultType]::ParameterName, 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)')
+            [CompletionResult]::new('--keep-stage-std', 'keep-stage-std', [CompletionResultType]::ParameterName, 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)')
+            [CompletionResult]::new('--src', 'src', [CompletionResultType]::ParameterName, 'path to the root of the rust checkout')
+            [CompletionResult]::new('-j', 'j', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel')
+            [CompletionResult]::new('--jobs', 'jobs', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel')
+            [CompletionResult]::new('--warnings', 'warnings', [CompletionResultType]::ParameterName, 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour')
+            [CompletionResult]::new('--error-format', 'error-format', [CompletionResultType]::ParameterName, 'rustc error format')
+            [CompletionResult]::new('--color', 'color', [CompletionResultType]::ParameterName, 'whether to use color in cargo and rustc output')
+            [CompletionResult]::new('--llvm-skip-rebuild', 'llvm-skip-rebuild', [CompletionResultType]::ParameterName, 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml')
+            [CompletionResult]::new('--rust-profile-generate', 'rust-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with rustc build')
+            [CompletionResult]::new('--rust-profile-use', 'rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build')
+            [CompletionResult]::new('--llvm-profile-use', 'llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build')
+            [CompletionResult]::new('--llvm-bolt-profile-use', 'llvm-bolt-profile-use', [CompletionResultType]::ParameterName, 'use BOLT profile for LLVM build')
+            [CompletionResult]::new('--run', 'run', [CompletionResultType]::ParameterName, 'run suggested tests')
+            [CompletionResult]::new('-v', 'v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)')
+            [CompletionResult]::new('--verbose', 'verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)')
+            [CompletionResult]::new('-i', 'i', [CompletionResultType]::ParameterName, 'use incremental compilation')
+            [CompletionResult]::new('--incremental', 'incremental', [CompletionResultType]::ParameterName, 'use incremental compilation')
+            [CompletionResult]::new('--include-default-paths', 'include-default-paths', [CompletionResultType]::ParameterName, 'include default paths in addition to the provided ones')
+            [CompletionResult]::new('--dry-run', 'dry-run', [CompletionResultType]::ParameterName, 'dry run; don''t build anything')
+            [CompletionResult]::new('--json-output', 'json-output', [CompletionResultType]::ParameterName, 'use message-format=json')
+            [CompletionResult]::new('--llvm-profile-generate', 'llvm-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with llvm built for rustc')
+            [CompletionResult]::new('--llvm-bolt-profile-generate', 'llvm-bolt-profile-generate', [CompletionResultType]::ParameterName, 'generate BOLT profile for LLVM build')
+            [CompletionResult]::new('-h', 'h', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')')
+            [CompletionResult]::new('--help', 'help', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')')
+            break
+        }
+    })
+
+    $completions.Where{ $_.CompletionText -like "$wordToComplete*" } |
+        Sort-Object -Property ListItemText
+}
diff --git a/src/etc/completions/x.py.sh b/src/etc/completions/x.py.sh
new file mode 100644
index 00000000000..931cc4353b2
--- /dev/null
+++ b/src/etc/completions/x.py.sh
@@ -0,0 +1,1644 @@
+_x.py() {
+    local i cur prev opts cmd
+    COMPREPLY=()
+    cur="${COMP_WORDS[COMP_CWORD]}"
+    prev="${COMP_WORDS[COMP_CWORD-1]}"
+    cmd=""
+    opts=""
+
+    for i in ${COMP_WORDS[@]}
+    do
+        case "${cmd},${i}" in
+            ",$1")
+                cmd="x.py"
+                ;;
+            bootstrap,bench)
+                cmd="bootstrap__bench"
+                ;;
+            bootstrap,build)
+                cmd="bootstrap__build"
+                ;;
+            bootstrap,check)
+                cmd="bootstrap__check"
+                ;;
+            bootstrap,clean)
+                cmd="bootstrap__clean"
+                ;;
+            bootstrap,clippy)
+                cmd="bootstrap__clippy"
+                ;;
+            bootstrap,dist)
+                cmd="bootstrap__dist"
+                ;;
+            bootstrap,doc)
+                cmd="bootstrap__doc"
+                ;;
+            bootstrap,fix)
+                cmd="bootstrap__fix"
+                ;;
+            bootstrap,fmt)
+                cmd="bootstrap__fmt"
+                ;;
+            bootstrap,install)
+                cmd="bootstrap__install"
+                ;;
+            bootstrap,run)
+                cmd="bootstrap__run"
+                ;;
+            bootstrap,setup)
+                cmd="bootstrap__setup"
+                ;;
+            bootstrap,suggest)
+                cmd="bootstrap__suggest"
+                ;;
+            bootstrap,test)
+                cmd="bootstrap__test"
+                ;;
+            *)
+                ;;
+        esac
+    done
+
+    case "${cmd}" in
+        x.py)
+            opts="-v -i -j -h --verbose --incremental --config --build-dir --build --host --target --exclude --include-default-paths --rustc-error-format --on-fail --dry-run --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --llvm-bolt-profile-generate --llvm-bolt-profile-use --help [PATHS]... [ARGS]... build check clippy fix fmt doc test bench clean dist install run setup suggest"
+            if [[ ${cur} == -* || ${COMP_CWORD} -eq 1 ]] ; then
+                COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
+                return 0
+            fi
+            case "${prev}" in
+                --config)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --build-dir)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --build)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --host)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --target)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --exclude)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --rustc-error-format)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --on-fail)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --stage)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --keep-stage)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --keep-stage-std)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --src)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --jobs)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                -j)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --warnings)
+                    COMPREPLY=($(compgen -W "deny warn default" -- "${cur}"))
+                    return 0
+                    ;;
+                --error-format)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --color)
+                    COMPREPLY=($(compgen -W "always never auto" -- "${cur}"))
+                    return 0
+                    ;;
+                --llvm-skip-rebuild)
+                    COMPREPLY=($(compgen -W "true false" -- "${cur}"))
+                    return 0
+                    ;;
+                --rust-profile-generate)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --rust-profile-use)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --llvm-profile-use)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --llvm-bolt-profile-use)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                *)
+                    COMPREPLY=()
+                    ;;
+            esac
+            COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
+            return 0
+            ;;
+        x.py__bench)
+            opts="-v -i -j -h --test-args --verbose --incremental --config --build-dir --build --host --target --exclude --include-default-paths --rustc-error-format --on-fail --dry-run --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --llvm-bolt-profile-generate --llvm-bolt-profile-use --help [PATHS]... [ARGS]..."
+            if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
+                COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
+                return 0
+            fi
+            case "${prev}" in
+                --test-args)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --config)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --build-dir)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --build)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --host)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --target)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --exclude)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --rustc-error-format)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --on-fail)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --stage)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --keep-stage)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --keep-stage-std)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --src)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --jobs)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                -j)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --warnings)
+                    COMPREPLY=($(compgen -W "deny warn default" -- "${cur}"))
+                    return 0
+                    ;;
+                --error-format)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --color)
+                    COMPREPLY=($(compgen -W "always never auto" -- "${cur}"))
+                    return 0
+                    ;;
+                --llvm-skip-rebuild)
+                    COMPREPLY=($(compgen -W "true false" -- "${cur}"))
+                    return 0
+                    ;;
+                --rust-profile-generate)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --rust-profile-use)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --llvm-profile-use)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --llvm-bolt-profile-use)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                *)
+                    COMPREPLY=()
+                    ;;
+            esac
+            COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
+            return 0
+            ;;
+        x.py__build)
+            opts="-v -i -j -h --verbose --incremental --config --build-dir --build --host --target --exclude --include-default-paths --rustc-error-format --on-fail --dry-run --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --llvm-bolt-profile-generate --llvm-bolt-profile-use --help [PATHS]... [ARGS]..."
+            if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
+                COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
+                return 0
+            fi
+            case "${prev}" in
+                --config)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --build-dir)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --build)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --host)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --target)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --exclude)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --rustc-error-format)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --on-fail)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --stage)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --keep-stage)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --keep-stage-std)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --src)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --jobs)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                -j)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --warnings)
+                    COMPREPLY=($(compgen -W "deny warn default" -- "${cur}"))
+                    return 0
+                    ;;
+                --error-format)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --color)
+                    COMPREPLY=($(compgen -W "always never auto" -- "${cur}"))
+                    return 0
+                    ;;
+                --llvm-skip-rebuild)
+                    COMPREPLY=($(compgen -W "true false" -- "${cur}"))
+                    return 0
+                    ;;
+                --rust-profile-generate)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --rust-profile-use)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --llvm-profile-use)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --llvm-bolt-profile-use)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                *)
+                    COMPREPLY=()
+                    ;;
+            esac
+            COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
+            return 0
+            ;;
+        x.py__check)
+            opts="-v -i -j -h --all-targets --verbose --incremental --config --build-dir --build --host --target --exclude --include-default-paths --rustc-error-format --on-fail --dry-run --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --llvm-bolt-profile-generate --llvm-bolt-profile-use --help [PATHS]... [ARGS]..."
+            if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
+                COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
+                return 0
+            fi
+            case "${prev}" in
+                --config)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --build-dir)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --build)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --host)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --target)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --exclude)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --rustc-error-format)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --on-fail)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --stage)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --keep-stage)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --keep-stage-std)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --src)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --jobs)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                -j)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --warnings)
+                    COMPREPLY=($(compgen -W "deny warn default" -- "${cur}"))
+                    return 0
+                    ;;
+                --error-format)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --color)
+                    COMPREPLY=($(compgen -W "always never auto" -- "${cur}"))
+                    return 0
+                    ;;
+                --llvm-skip-rebuild)
+                    COMPREPLY=($(compgen -W "true false" -- "${cur}"))
+                    return 0
+                    ;;
+                --rust-profile-generate)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --rust-profile-use)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --llvm-profile-use)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --llvm-bolt-profile-use)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                *)
+                    COMPREPLY=()
+                    ;;
+            esac
+            COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
+            return 0
+            ;;
+        x.py__clean)
+            opts="-v -i -j -h --all --verbose --incremental --config --build-dir --build --host --target --exclude --include-default-paths --rustc-error-format --on-fail --dry-run --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --llvm-bolt-profile-generate --llvm-bolt-profile-use --help [PATHS]... [ARGS]..."
+            if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
+                COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
+                return 0
+            fi
+            case "${prev}" in
+                --config)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --build-dir)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --build)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --host)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --target)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --exclude)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --rustc-error-format)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --on-fail)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --stage)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --keep-stage)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --keep-stage-std)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --src)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --jobs)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                -j)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --warnings)
+                    COMPREPLY=($(compgen -W "deny warn default" -- "${cur}"))
+                    return 0
+                    ;;
+                --error-format)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --color)
+                    COMPREPLY=($(compgen -W "always never auto" -- "${cur}"))
+                    return 0
+                    ;;
+                --llvm-skip-rebuild)
+                    COMPREPLY=($(compgen -W "true false" -- "${cur}"))
+                    return 0
+                    ;;
+                --rust-profile-generate)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --rust-profile-use)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --llvm-profile-use)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --llvm-bolt-profile-use)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                *)
+                    COMPREPLY=()
+                    ;;
+            esac
+            COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
+            return 0
+            ;;
+        x.py__clippy)
+            opts="-A -D -W -F -v -i -j -h --fix --verbose --incremental --config --build-dir --build --host --target --exclude --include-default-paths --rustc-error-format --on-fail --dry-run --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --llvm-bolt-profile-generate --llvm-bolt-profile-use --help [PATHS]... [ARGS]..."
+            if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
+                COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
+                return 0
+            fi
+            case "${prev}" in
+                -A)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                -D)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                -W)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                -F)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --config)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --build-dir)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --build)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --host)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --target)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --exclude)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --rustc-error-format)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --on-fail)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --stage)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --keep-stage)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --keep-stage-std)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --src)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --jobs)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                -j)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --warnings)
+                    COMPREPLY=($(compgen -W "deny warn default" -- "${cur}"))
+                    return 0
+                    ;;
+                --error-format)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --color)
+                    COMPREPLY=($(compgen -W "always never auto" -- "${cur}"))
+                    return 0
+                    ;;
+                --llvm-skip-rebuild)
+                    COMPREPLY=($(compgen -W "true false" -- "${cur}"))
+                    return 0
+                    ;;
+                --rust-profile-generate)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --rust-profile-use)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --llvm-profile-use)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --llvm-bolt-profile-use)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                *)
+                    COMPREPLY=()
+                    ;;
+            esac
+            COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
+            return 0
+            ;;
+        x.py__dist)
+            opts="-v -i -j -h --verbose --incremental --config --build-dir --build --host --target --exclude --include-default-paths --rustc-error-format --on-fail --dry-run --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --llvm-bolt-profile-generate --llvm-bolt-profile-use --help [PATHS]... [ARGS]..."
+            if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
+                COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
+                return 0
+            fi
+            case "${prev}" in
+                --config)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --build-dir)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --build)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --host)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --target)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --exclude)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --rustc-error-format)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --on-fail)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --stage)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --keep-stage)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --keep-stage-std)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --src)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --jobs)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                -j)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --warnings)
+                    COMPREPLY=($(compgen -W "deny warn default" -- "${cur}"))
+                    return 0
+                    ;;
+                --error-format)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --color)
+                    COMPREPLY=($(compgen -W "always never auto" -- "${cur}"))
+                    return 0
+                    ;;
+                --llvm-skip-rebuild)
+                    COMPREPLY=($(compgen -W "true false" -- "${cur}"))
+                    return 0
+                    ;;
+                --rust-profile-generate)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --rust-profile-use)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --llvm-profile-use)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --llvm-bolt-profile-use)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                *)
+                    COMPREPLY=()
+                    ;;
+            esac
+            COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
+            return 0
+            ;;
+        x.py__doc)
+            opts="-v -i -j -h --open --json --verbose --incremental --config --build-dir --build --host --target --exclude --include-default-paths --rustc-error-format --on-fail --dry-run --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --llvm-bolt-profile-generate --llvm-bolt-profile-use --help [PATHS]... [ARGS]..."
+            if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
+                COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
+                return 0
+            fi
+            case "${prev}" in
+                --config)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --build-dir)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --build)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --host)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --target)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --exclude)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --rustc-error-format)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --on-fail)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --stage)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --keep-stage)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --keep-stage-std)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --src)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --jobs)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                -j)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --warnings)
+                    COMPREPLY=($(compgen -W "deny warn default" -- "${cur}"))
+                    return 0
+                    ;;
+                --error-format)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --color)
+                    COMPREPLY=($(compgen -W "always never auto" -- "${cur}"))
+                    return 0
+                    ;;
+                --llvm-skip-rebuild)
+                    COMPREPLY=($(compgen -W "true false" -- "${cur}"))
+                    return 0
+                    ;;
+                --rust-profile-generate)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --rust-profile-use)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --llvm-profile-use)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --llvm-bolt-profile-use)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                *)
+                    COMPREPLY=()
+                    ;;
+            esac
+            COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
+            return 0
+            ;;
+        x.py__fix)
+            opts="-v -i -j -h --verbose --incremental --config --build-dir --build --host --target --exclude --include-default-paths --rustc-error-format --on-fail --dry-run --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --llvm-bolt-profile-generate --llvm-bolt-profile-use --help [PATHS]... [ARGS]..."
+            if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
+                COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
+                return 0
+            fi
+            case "${prev}" in
+                --config)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --build-dir)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --build)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --host)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --target)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --exclude)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --rustc-error-format)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --on-fail)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --stage)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --keep-stage)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --keep-stage-std)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --src)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --jobs)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                -j)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --warnings)
+                    COMPREPLY=($(compgen -W "deny warn default" -- "${cur}"))
+                    return 0
+                    ;;
+                --error-format)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --color)
+                    COMPREPLY=($(compgen -W "always never auto" -- "${cur}"))
+                    return 0
+                    ;;
+                --llvm-skip-rebuild)
+                    COMPREPLY=($(compgen -W "true false" -- "${cur}"))
+                    return 0
+                    ;;
+                --rust-profile-generate)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --rust-profile-use)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --llvm-profile-use)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --llvm-bolt-profile-use)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                *)
+                    COMPREPLY=()
+                    ;;
+            esac
+            COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
+            return 0
+            ;;
+        x.py__fmt)
+            opts="-v -i -j -h --check --verbose --incremental --config --build-dir --build --host --target --exclude --include-default-paths --rustc-error-format --on-fail --dry-run --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --llvm-bolt-profile-generate --llvm-bolt-profile-use --help [PATHS]... [ARGS]..."
+            if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
+                COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
+                return 0
+            fi
+            case "${prev}" in
+                --config)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --build-dir)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --build)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --host)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --target)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --exclude)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --rustc-error-format)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --on-fail)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --stage)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --keep-stage)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --keep-stage-std)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --src)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --jobs)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                -j)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --warnings)
+                    COMPREPLY=($(compgen -W "deny warn default" -- "${cur}"))
+                    return 0
+                    ;;
+                --error-format)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --color)
+                    COMPREPLY=($(compgen -W "always never auto" -- "${cur}"))
+                    return 0
+                    ;;
+                --llvm-skip-rebuild)
+                    COMPREPLY=($(compgen -W "true false" -- "${cur}"))
+                    return 0
+                    ;;
+                --rust-profile-generate)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --rust-profile-use)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --llvm-profile-use)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --llvm-bolt-profile-use)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                *)
+                    COMPREPLY=()
+                    ;;
+            esac
+            COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
+            return 0
+            ;;
+        x.py__install)
+            opts="-v -i -j -h --verbose --incremental --config --build-dir --build --host --target --exclude --include-default-paths --rustc-error-format --on-fail --dry-run --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --llvm-bolt-profile-generate --llvm-bolt-profile-use --help [PATHS]... [ARGS]..."
+            if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
+                COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
+                return 0
+            fi
+            case "${prev}" in
+                --config)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --build-dir)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --build)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --host)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --target)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --exclude)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --rustc-error-format)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --on-fail)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --stage)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --keep-stage)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --keep-stage-std)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --src)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --jobs)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                -j)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --warnings)
+                    COMPREPLY=($(compgen -W "deny warn default" -- "${cur}"))
+                    return 0
+                    ;;
+                --error-format)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --color)
+                    COMPREPLY=($(compgen -W "always never auto" -- "${cur}"))
+                    return 0
+                    ;;
+                --llvm-skip-rebuild)
+                    COMPREPLY=($(compgen -W "true false" -- "${cur}"))
+                    return 0
+                    ;;
+                --rust-profile-generate)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --rust-profile-use)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --llvm-profile-use)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --llvm-bolt-profile-use)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                *)
+                    COMPREPLY=()
+                    ;;
+            esac
+            COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
+            return 0
+            ;;
+        x.py__run)
+            opts="-v -i -j -h --args --verbose --incremental --config --build-dir --build --host --target --exclude --include-default-paths --rustc-error-format --on-fail --dry-run --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --llvm-bolt-profile-generate --llvm-bolt-profile-use --help [PATHS]... [ARGS]..."
+            if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
+                COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
+                return 0
+            fi
+            case "${prev}" in
+                --args)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --config)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --build-dir)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --build)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --host)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --target)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --exclude)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --rustc-error-format)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --on-fail)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --stage)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --keep-stage)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --keep-stage-std)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --src)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --jobs)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                -j)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --warnings)
+                    COMPREPLY=($(compgen -W "deny warn default" -- "${cur}"))
+                    return 0
+                    ;;
+                --error-format)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --color)
+                    COMPREPLY=($(compgen -W "always never auto" -- "${cur}"))
+                    return 0
+                    ;;
+                --llvm-skip-rebuild)
+                    COMPREPLY=($(compgen -W "true false" -- "${cur}"))
+                    return 0
+                    ;;
+                --rust-profile-generate)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --rust-profile-use)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --llvm-profile-use)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --llvm-bolt-profile-use)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                *)
+                    COMPREPLY=()
+                    ;;
+            esac
+            COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
+            return 0
+            ;;
+        x.py__setup)
+            opts="-v -i -j -h --verbose --incremental --config --build-dir --build --host --target --exclude --include-default-paths --rustc-error-format --on-fail --dry-run --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --llvm-bolt-profile-generate --llvm-bolt-profile-use --help [<PROFILE>|hook|vscode|link] [PATHS]... [ARGS]..."
+            if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
+                COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
+                return 0
+            fi
+            case "${prev}" in
+                --config)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --build-dir)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --build)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --host)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --target)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --exclude)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --rustc-error-format)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --on-fail)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --stage)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --keep-stage)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --keep-stage-std)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --src)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --jobs)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                -j)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --warnings)
+                    COMPREPLY=($(compgen -W "deny warn default" -- "${cur}"))
+                    return 0
+                    ;;
+                --error-format)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --color)
+                    COMPREPLY=($(compgen -W "always never auto" -- "${cur}"))
+                    return 0
+                    ;;
+                --llvm-skip-rebuild)
+                    COMPREPLY=($(compgen -W "true false" -- "${cur}"))
+                    return 0
+                    ;;
+                --rust-profile-generate)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --rust-profile-use)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --llvm-profile-use)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --llvm-bolt-profile-use)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                *)
+                    COMPREPLY=()
+                    ;;
+            esac
+            COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
+            return 0
+            ;;
+        x.py__suggest)
+            opts="-v -i -j -h --run --verbose --incremental --config --build-dir --build --host --target --exclude --include-default-paths --rustc-error-format --on-fail --dry-run --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --llvm-bolt-profile-generate --llvm-bolt-profile-use --help [PATHS]... [ARGS]..."
+            if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
+                COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
+                return 0
+            fi
+            case "${prev}" in
+                --config)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --build-dir)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --build)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --host)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --target)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --exclude)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --rustc-error-format)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --on-fail)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --stage)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --keep-stage)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --keep-stage-std)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --src)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --jobs)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                -j)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --warnings)
+                    COMPREPLY=($(compgen -W "deny warn default" -- "${cur}"))
+                    return 0
+                    ;;
+                --error-format)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --color)
+                    COMPREPLY=($(compgen -W "always never auto" -- "${cur}"))
+                    return 0
+                    ;;
+                --llvm-skip-rebuild)
+                    COMPREPLY=($(compgen -W "true false" -- "${cur}"))
+                    return 0
+                    ;;
+                --rust-profile-generate)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --rust-profile-use)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --llvm-profile-use)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --llvm-bolt-profile-use)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                *)
+                    COMPREPLY=()
+                    ;;
+            esac
+            COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
+            return 0
+            ;;
+        x.py__test)
+            opts="-v -i -j -h --no-fail-fast --skip --test-args --rustc-args --no-doc --doc --bless --force-rerun --only-modified --compare-mode --pass --run --rustfix-coverage --verbose --incremental --config --build-dir --build --host --target --exclude --include-default-paths --rustc-error-format --on-fail --dry-run --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --llvm-bolt-profile-generate --llvm-bolt-profile-use --help [PATHS]... [ARGS]..."
+            if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
+                COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
+                return 0
+            fi
+            case "${prev}" in
+                --skip)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --test-args)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --rustc-args)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --compare-mode)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --pass)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --run)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --config)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --build-dir)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --build)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --host)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --target)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --exclude)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --rustc-error-format)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --on-fail)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --stage)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --keep-stage)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --keep-stage-std)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --src)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --jobs)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                -j)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --warnings)
+                    COMPREPLY=($(compgen -W "deny warn default" -- "${cur}"))
+                    return 0
+                    ;;
+                --error-format)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
+                --color)
+                    COMPREPLY=($(compgen -W "always never auto" -- "${cur}"))
+                    return 0
+                    ;;
+                --llvm-skip-rebuild)
+                    COMPREPLY=($(compgen -W "true false" -- "${cur}"))
+                    return 0
+                    ;;
+                --rust-profile-generate)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --rust-profile-use)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --llvm-profile-use)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                --llvm-bolt-profile-use)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
+                *)
+                    COMPREPLY=()
+                    ;;
+            esac
+            COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
+            return 0
+            ;;
+    esac
+}
+
+complete -F _x.py -o bashdefault -o default x.py
diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs
index b802fd065fe..17aa6b38e38 100644
--- a/src/librustdoc/clean/utils.rs
+++ b/src/librustdoc/clean/utils.rs
@@ -594,9 +594,8 @@ pub(super) fn display_macro_source(
     def_id: DefId,
     vis: ty::Visibility<DefId>,
 ) -> String {
-    let tts: Vec<_> = def.body.tokens.clone().into_trees().collect();
     // Extract the spans of all matchers. They represent the "interface" of the macro.
-    let matchers = tts.chunks(4).map(|arm| &arm[0]);
+    let matchers = def.body.tokens.chunks(4).map(|arm| &arm[0]);
 
     if def.macro_rules {
         format!("macro_rules! {} {{\n{}}}", name, render_macro_arms(cx.tcx, matchers, ";"))
diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs
index 4b0aee9c3ad..09e7ed293d4 100644
--- a/src/librustdoc/html/markdown.rs
+++ b/src/librustdoc/html/markdown.rs
@@ -551,7 +551,15 @@ impl<'a, I: Iterator<Item = Event<'a>>> SummaryLine<'a, I> {
 }
 
 fn check_if_allowed_tag(t: &Tag<'_>) -> bool {
-    matches!(t, Tag::Paragraph | Tag::Emphasis | Tag::Strong | Tag::Link(..) | Tag::BlockQuote)
+    matches!(
+        t,
+        Tag::Paragraph
+            | Tag::Emphasis
+            | Tag::Strong
+            | Tag::Strikethrough
+            | Tag::Link(..)
+            | Tag::BlockQuote
+    )
 }
 
 fn is_forbidden_tag(t: &Tag<'_>) -> bool {
@@ -773,7 +781,7 @@ impl<'tcx> ExtraInfo<'tcx> {
         ExtraInfo { def_id, sp, tcx }
     }
 
-    fn error_invalid_codeblock_attr(&self, msg: &str, help: &str) {
+    fn error_invalid_codeblock_attr(&self, msg: String, help: &str) {
         if let Some(def_id) = self.def_id.as_local() {
             self.tcx.struct_span_lint_hir(
                 crate::lint::INVALID_CODEBLOCK_ATTRIBUTES,
@@ -948,7 +956,7 @@ impl LangString {
                     } {
                         if let Some(extra) = extra {
                             extra.error_invalid_codeblock_attr(
-                                &format!("unknown attribute `{}`. Did you mean `{}`?", x, flag),
+                                format!("unknown attribute `{}`. Did you mean `{}`?", x, flag),
                                 help,
                             );
                         }
diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs
index d6773169639..0a2f5f6653c 100644
--- a/src/librustdoc/html/render/mod.rs
+++ b/src/librustdoc/html/render/mod.rs
@@ -1751,7 +1751,7 @@ fn render_impl(
             if trait_.is_none() && i.inner_impl().items.is_empty() {
                 w.write_str(
                     "<div class=\"item-info\">\
-                    <div class=\"stab empty-impl\">This impl block contains no items.</div>
+                    <div class=\"stab empty-impl\">This impl block contains no items.</div>\
                 </div>",
                 );
             }
diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs
index b6eb450d62b..0a56916edcd 100644
--- a/src/librustdoc/lib.rs
+++ b/src/librustdoc/lib.rs
@@ -192,11 +192,11 @@ fn init_logging() {
         Ok("auto") | Err(VarError::NotPresent) => io::stdout().is_terminal(),
         Ok(value) => early_error(
             ErrorOutputType::default(),
-            &format!("invalid log color value '{}': expected one of always, never, or auto", value),
+            format!("invalid log color value '{}': expected one of always, never, or auto", value),
         ),
         Err(VarError::NotUnicode(value)) => early_error(
             ErrorOutputType::default(),
-            &format!(
+            format!(
                 "invalid log color value '{}': expected one of always, never, or auto",
                 value.to_string_lossy()
             ),
@@ -228,7 +228,7 @@ fn get_args() -> Option<Vec<String>> {
                 .map_err(|arg| {
                     early_warn(
                         ErrorOutputType::default(),
-                        &format!("Argument {} is not valid Unicode: {:?}", i, arg),
+                        format!("Argument {} is not valid Unicode: {:?}", i, arg),
                     );
                 })
                 .ok()
@@ -721,7 +721,7 @@ fn main_args(at_args: &[String]) -> MainResult {
     let matches = match options.parse(&args[1..]) {
         Ok(m) => m,
         Err(err) => {
-            early_error(ErrorOutputType::default(), &err.to_string());
+            early_error(ErrorOutputType::default(), err.to_string());
         }
     };
 
@@ -739,6 +739,9 @@ fn main_args(at_args: &[String]) -> MainResult {
         }
     };
 
+    // Set parallel mode before error handler creation, which will create `Lock`s.
+    interface::set_thread_safe_mode(&options.unstable_opts);
+
     let diag = core::new_handler(
         options.error_format,
         None,
diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs
index a885ff0ca5e..9381b3e0567 100644
--- a/src/librustdoc/passes/collect_intra_doc_links.rs
+++ b/src/librustdoc/passes/collect_intra_doc_links.rs
@@ -8,7 +8,7 @@ use rustc_data_structures::{
     fx::{FxHashMap, FxHashSet},
     intern::Interned,
 };
-use rustc_errors::{Applicability, Diagnostic};
+use rustc_errors::{Applicability, Diagnostic, DiagnosticMessage};
 use rustc_hir::def::Namespace::*;
 use rustc_hir::def::{DefKind, Namespace, PerNS};
 use rustc_hir::def_id::{DefId, CRATE_DEF_ID};
@@ -24,6 +24,7 @@ use rustc_span::BytePos;
 use smallvec::{smallvec, SmallVec};
 
 use std::borrow::Cow;
+use std::fmt::Display;
 use std::mem;
 use std::ops::Range;
 
@@ -841,7 +842,7 @@ impl PreprocessingError {
         match self {
             PreprocessingError::MultipleAnchors => report_multiple_anchors(cx, diag_info),
             PreprocessingError::Disambiguator(range, msg) => {
-                disambiguator_error(cx, diag_info, range.clone(), msg)
+                disambiguator_error(cx, diag_info, range.clone(), msg.as_str())
             }
             PreprocessingError::MalformedGenerics(err, path_str) => {
                 report_malformed_generics(cx, diag_info, *err, path_str)
@@ -1185,7 +1186,7 @@ impl LinkCollector<'_, '_> {
             }
             suggest_disambiguator(resolved, diag, path_str, &ori_link.link, sp);
         };
-        report_diagnostic(self.cx.tcx, BROKEN_INTRA_DOC_LINKS, &msg, diag_info, callback);
+        report_diagnostic(self.cx.tcx, BROKEN_INTRA_DOC_LINKS, msg, diag_info, callback);
     }
 
     fn report_rawptr_assoc_feature_gate(&self, dox: &str, ori_link: &Range<usize>, item: &Item) {
@@ -1581,7 +1582,7 @@ impl Suggestion {
 fn report_diagnostic(
     tcx: TyCtxt<'_>,
     lint: &'static Lint,
-    msg: &str,
+    msg: impl Into<DiagnosticMessage> + Display,
     DiagnosticInfo { item, ori_link: _, dox, link_range }: &DiagnosticInfo<'_>,
     decorate: impl FnOnce(&mut Diagnostic, Option<rustc_span::Span>),
 ) {
@@ -1649,7 +1650,7 @@ fn resolution_failure(
     report_diagnostic(
         tcx,
         BROKEN_INTRA_DOC_LINKS,
-        &format!("unresolved link to `{}`", path_str),
+        format!("unresolved link to `{}`", path_str),
         &diag_info,
         |diag, sp| {
             let item = |res: Res| format!("the {} `{}`", res.descr(), res.name(tcx),);
@@ -1865,20 +1866,20 @@ fn resolution_failure(
 
 fn report_multiple_anchors(cx: &DocContext<'_>, diag_info: DiagnosticInfo<'_>) {
     let msg = format!("`{}` contains multiple anchors", diag_info.ori_link);
-    anchor_failure(cx, diag_info, &msg, 1)
+    anchor_failure(cx, diag_info, msg, 1)
 }
 
 fn report_anchor_conflict(cx: &DocContext<'_>, diag_info: DiagnosticInfo<'_>, def_id: DefId) {
     let (link, kind) = (diag_info.ori_link, Res::from_def_id(cx.tcx, def_id).descr());
     let msg = format!("`{link}` contains an anchor, but links to {kind}s are already anchored");
-    anchor_failure(cx, diag_info, &msg, 0)
+    anchor_failure(cx, diag_info, msg, 0)
 }
 
 /// Report an anchor failure.
 fn anchor_failure(
     cx: &DocContext<'_>,
     diag_info: DiagnosticInfo<'_>,
-    msg: &str,
+    msg: String,
     anchor_idx: usize,
 ) {
     report_diagnostic(cx.tcx, BROKEN_INTRA_DOC_LINKS, msg, &diag_info, |diag, sp| {
@@ -1898,7 +1899,7 @@ fn disambiguator_error(
     cx: &DocContext<'_>,
     mut diag_info: DiagnosticInfo<'_>,
     disambiguator_range: Range<usize>,
-    msg: &str,
+    msg: impl Into<DiagnosticMessage> + Display,
 ) {
     diag_info.link_range = disambiguator_range;
     report_diagnostic(cx.tcx, BROKEN_INTRA_DOC_LINKS, msg, &diag_info, |diag, _sp| {
@@ -1919,7 +1920,7 @@ fn report_malformed_generics(
     report_diagnostic(
         cx.tcx,
         BROKEN_INTRA_DOC_LINKS,
-        &format!("unresolved link to `{}`", path_str),
+        format!("unresolved link to `{}`", path_str),
         &diag_info,
         |diag, sp| {
             let note = match err {
@@ -1994,7 +1995,7 @@ fn ambiguity_error(
         }
     }
 
-    report_diagnostic(cx.tcx, BROKEN_INTRA_DOC_LINKS, &msg, diag_info, |diag, sp| {
+    report_diagnostic(cx.tcx, BROKEN_INTRA_DOC_LINKS, msg, diag_info, |diag, sp| {
         if let Some(sp) = sp {
             diag.span_label(sp, "ambiguous link");
         } else {
@@ -2046,7 +2047,7 @@ fn privacy_error(cx: &DocContext<'_>, diag_info: &DiagnosticInfo<'_>, path_str:
     let msg =
         format!("public documentation for `{}` links to private item `{}`", item_name, path_str);
 
-    report_diagnostic(cx.tcx, PRIVATE_INTRA_DOC_LINKS, &msg, diag_info, |diag, sp| {
+    report_diagnostic(cx.tcx, PRIVATE_INTRA_DOC_LINKS, msg, diag_info, |diag, sp| {
         if let Some(sp) = sp {
             diag.span_label(sp, "this item is private");
         }
diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs
index deb29b1e7a9..8f8dc6b7090 100644
--- a/src/librustdoc/visit_ast.rs
+++ b/src/librustdoc/visit_ast.rs
@@ -5,7 +5,7 @@ use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::{DefId, DefIdMap, LocalDefId, LocalDefIdSet};
-use rustc_hir::intravisit::{walk_item, Visitor};
+use rustc_hir::intravisit::{walk_body, walk_item, Visitor};
 use rustc_hir::{Node, CRATE_HIR_ID};
 use rustc_middle::hir::nested_filter;
 use rustc_middle::ty::TyCtxt;
@@ -106,6 +106,7 @@ pub(crate) struct RustdocVisitor<'a, 'tcx> {
     exact_paths: DefIdMap<Vec<Symbol>>,
     modules: Vec<Module<'tcx>>,
     is_importable_from_parent: bool,
+    inside_body: bool,
 }
 
 impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
@@ -129,6 +130,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
             exact_paths: Default::default(),
             modules: vec![om],
             is_importable_from_parent: true,
+            inside_body: false,
         }
     }
 
@@ -368,6 +370,26 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
         import_id: Option<LocalDefId>,
     ) {
         debug!("visiting item {:?}", item);
+        if self.inside_body {
+            // Only impls can be "seen" outside a body. For example:
+            //
+            // ```
+            // struct Bar;
+            //
+            // fn foo() {
+            //     impl Bar { fn bar() {} }
+            // }
+            // Bar::bar();
+            // ```
+            if let hir::ItemKind::Impl(impl_) = item.kind &&
+                // Don't duplicate impls when inlining or if it's implementing a trait, we'll pick
+                // them up regardless of where they're located.
+                impl_.of_trait.is_none()
+            {
+                self.add_to_current_mod(item, None, None);
+            }
+            return;
+        }
         let name = renamed.unwrap_or(item.ident.name);
         let tcx = self.cx.tcx;
 
@@ -455,7 +477,8 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
             | hir::ItemKind::Union(..)
             | hir::ItemKind::TyAlias(..)
             | hir::ItemKind::OpaqueTy(hir::OpaqueTy {
-                origin: hir::OpaqueTyOrigin::TyAlias, ..
+                origin: hir::OpaqueTyOrigin::TyAlias { .. },
+                ..
             })
             | hir::ItemKind::Static(..)
             | hir::ItemKind::Trait(..)
@@ -563,4 +586,10 @@ impl<'a, 'tcx> Visitor<'tcx> for RustdocVisitor<'a, 'tcx> {
     fn visit_lifetime(&mut self, _: &hir::Lifetime) {
         // Unneeded.
     }
+
+    fn visit_body(&mut self, b: &'tcx hir::Body<'tcx>) {
+        let prev = mem::replace(&mut self.inside_body, true);
+        walk_body(self, b);
+        self.inside_body = prev;
+    }
 }
diff --git a/src/llvm-project b/src/llvm-project
-Subproject ea6fa9c2d43aaf0f11559719eda9b54d356d541
+Subproject 533d3f338b804d54e5d0ac4fba6276af23002d9
diff --git a/src/tools/cargo b/src/tools/cargo
-Subproject 13413c64ff88dd6c2824e9eb9374fc5f10895d2
+Subproject 09276c703a473ab33daaeb94917232e80eefd62
diff --git a/src/tools/clippy/.github/workflows/clippy.yml b/src/tools/clippy/.github/workflows/clippy.yml
index b9921301197..a9d42159c4b 100644
--- a/src/tools/clippy/.github/workflows/clippy.yml
+++ b/src/tools/clippy/.github/workflows/clippy.yml
@@ -39,7 +39,7 @@ jobs:
         github_token: "${{ secrets.github_token }}"
 
     - name: Checkout
-      uses: actions/checkout@v3.0.2
+      uses: actions/checkout@v3
 
     - name: Install toolchain
       run: rustup show active-toolchain
diff --git a/src/tools/clippy/.github/workflows/clippy_bors.yml b/src/tools/clippy/.github/workflows/clippy_bors.yml
index 93198aabdb5..30a156c925b 100644
--- a/src/tools/clippy/.github/workflows/clippy_bors.yml
+++ b/src/tools/clippy/.github/workflows/clippy_bors.yml
@@ -27,7 +27,7 @@ jobs:
         github_token: "${{ secrets.github_token }}"
 
     - name: Checkout
-      uses: actions/checkout@v3.0.2
+      uses: actions/checkout@v3
       with:
         ref: ${{ github.ref }}
 
@@ -83,7 +83,7 @@ jobs:
         github_token: "${{ secrets.github_token }}"
 
     - name: Checkout
-      uses: actions/checkout@v3.0.2
+      uses: actions/checkout@v3
 
     - name: Install toolchain
       run: rustup show active-toolchain
@@ -149,7 +149,7 @@ jobs:
         github_token: "${{ secrets.github_token }}"
 
     - name: Checkout
-      uses: actions/checkout@v3.0.2
+      uses: actions/checkout@v3
 
     - name: Install toolchain
       run: rustup show active-toolchain
@@ -173,7 +173,7 @@ jobs:
         github_token: "${{ secrets.github_token }}"
 
     - name: Checkout
-      uses: actions/checkout@v3.0.2
+      uses: actions/checkout@v3
 
     - name: Install toolchain
       run: rustup show active-toolchain
@@ -233,7 +233,7 @@ jobs:
         github_token: "${{ secrets.github_token }}"
 
     - name: Checkout
-      uses: actions/checkout@v3.0.2
+      uses: actions/checkout@v3
 
     - name: Install toolchain
       run: rustup show active-toolchain
diff --git a/src/tools/clippy/.github/workflows/clippy_dev.yml b/src/tools/clippy/.github/workflows/clippy_dev.yml
index 14f20212add..514706d64c8 100644
--- a/src/tools/clippy/.github/workflows/clippy_dev.yml
+++ b/src/tools/clippy/.github/workflows/clippy_dev.yml
@@ -25,7 +25,7 @@ jobs:
     steps:
     # Setup
     - name: Checkout
-      uses: actions/checkout@v3.0.2
+      uses: actions/checkout@v3
 
     # Run
     - name: Build
diff --git a/src/tools/clippy/.github/workflows/deploy.yml b/src/tools/clippy/.github/workflows/deploy.yml
index 71d71d10359..f42928c2cd1 100644
--- a/src/tools/clippy/.github/workflows/deploy.yml
+++ b/src/tools/clippy/.github/workflows/deploy.yml
@@ -21,10 +21,10 @@ jobs:
     steps:
     # Setup
     - name: Checkout
-      uses: actions/checkout@v3.0.2
+      uses: actions/checkout@v3
 
     - name: Checkout
-      uses: actions/checkout@v3.0.2
+      uses: actions/checkout@v3
       with:
         ref: ${{ env.TARGET_BRANCH }}
         path: 'out'
diff --git a/src/tools/clippy/.github/workflows/remark.yml b/src/tools/clippy/.github/workflows/remark.yml
index 0bc2f49f5e9..7d25b6a2b79 100644
--- a/src/tools/clippy/.github/workflows/remark.yml
+++ b/src/tools/clippy/.github/workflows/remark.yml
@@ -16,10 +16,10 @@ jobs:
     steps:
     # Setup
     - name: Checkout
-      uses: actions/checkout@v3.0.2
+      uses: actions/checkout@v3
 
     - name: Setup Node.js
-      uses: actions/setup-node@v1.4.4
+      uses: actions/setup-node@v3
       with:
         node-version: '14.x'
 
diff --git a/src/tools/clippy/CHANGELOG.md b/src/tools/clippy/CHANGELOG.md
index ebf5b58a586..79f2a47110b 100644
--- a/src/tools/clippy/CHANGELOG.md
+++ b/src/tools/clippy/CHANGELOG.md
@@ -4620,6 +4620,7 @@ Released 2018-09-13
 [`else_if_without_else`]: https://rust-lang.github.io/rust-clippy/master/index.html#else_if_without_else
 [`empty_drop`]: https://rust-lang.github.io/rust-clippy/master/index.html#empty_drop
 [`empty_enum`]: https://rust-lang.github.io/rust-clippy/master/index.html#empty_enum
+[`empty_line_after_doc_comments`]: https://rust-lang.github.io/rust-clippy/master/index.html#empty_line_after_doc_comments
 [`empty_line_after_outer_attr`]: https://rust-lang.github.io/rust-clippy/master/index.html#empty_line_after_outer_attr
 [`empty_loop`]: https://rust-lang.github.io/rust-clippy/master/index.html#empty_loop
 [`empty_structs_with_brackets`]: https://rust-lang.github.io/rust-clippy/master/index.html#empty_structs_with_brackets
@@ -4785,6 +4786,7 @@ Released 2018-09-13
 [`manual_main_separator_str`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_main_separator_str
 [`manual_map`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_map
 [`manual_memcpy`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_memcpy
+[`manual_next_back`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_next_back
 [`manual_non_exhaustive`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_non_exhaustive
 [`manual_ok_or`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_ok_or
 [`manual_range_contains`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_range_contains
@@ -4897,6 +4899,7 @@ Released 2018-09-13
 [`no_effect_underscore_binding`]: https://rust-lang.github.io/rust-clippy/master/index.html#no_effect_underscore_binding
 [`no_mangle_with_rust_abi`]: https://rust-lang.github.io/rust-clippy/master/index.html#no_mangle_with_rust_abi
 [`non_ascii_literal`]: https://rust-lang.github.io/rust-clippy/master/index.html#non_ascii_literal
+[`non_minimal_cfg`]: https://rust-lang.github.io/rust-clippy/master/index.html#non_minimal_cfg
 [`non_octal_unix_permissions`]: https://rust-lang.github.io/rust-clippy/master/index.html#non_octal_unix_permissions
 [`non_send_fields_in_send_ty`]: https://rust-lang.github.io/rust-clippy/master/index.html#non_send_fields_in_send_ty
 [`nonminimal_bool`]: https://rust-lang.github.io/rust-clippy/master/index.html#nonminimal_bool
@@ -4978,6 +4981,7 @@ Released 2018-09-13
 [`ref_binding_to_reference`]: https://rust-lang.github.io/rust-clippy/master/index.html#ref_binding_to_reference
 [`ref_in_deref`]: https://rust-lang.github.io/rust-clippy/master/index.html#ref_in_deref
 [`ref_option_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#ref_option_ref
+[`ref_patterns`]: https://rust-lang.github.io/rust-clippy/master/index.html#ref_patterns
 [`regex_macro`]: https://rust-lang.github.io/rust-clippy/master/index.html#regex_macro
 [`repeat_once`]: https://rust-lang.github.io/rust-clippy/master/index.html#repeat_once
 [`replace_consts`]: https://rust-lang.github.io/rust-clippy/master/index.html#replace_consts
diff --git a/src/tools/clippy/README.md b/src/tools/clippy/README.md
index 6745e15c006..d712d3e6750 100644
--- a/src/tools/clippy/README.md
+++ b/src/tools/clippy/README.md
@@ -278,7 +278,7 @@ If you want to contribute to Clippy, you can find more information in [CONTRIBUT
 
 <!-- REUSE-IgnoreStart -->
 
-Copyright 2014-2022 The Rust Project Developers
+Copyright 2014-2023 The Rust Project Developers
 
 Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
 [https://www.apache.org/licenses/LICENSE-2.0](https://www.apache.org/licenses/LICENSE-2.0)> or the MIT license
diff --git a/src/tools/clippy/book/src/development/type_checking.md b/src/tools/clippy/book/src/development/type_checking.md
index 225de849566..d7c2775b896 100644
--- a/src/tools/clippy/book/src/development/type_checking.md
+++ b/src/tools/clippy/book/src/development/type_checking.md
@@ -133,7 +133,7 @@ in this chapter:
 - [Type checking](https://rustc-dev-guide.rust-lang.org/type-checking.html)
 - [Ty module](https://rustc-dev-guide.rust-lang.org/ty.html)
 
-[Adt]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/enum.TyKind.html#variant.Adt
+[Adt]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_type_ir/sty/enum.TyKind.html#variant.Adt
 [AdtDef]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/adt/struct.AdtDef.html
 [expr_ty]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.TypeckResults.html#method.expr_ty
 [node_type]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.TypeckResults.html#method.node_type
@@ -142,9 +142,9 @@ in this chapter:
 [kind]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.Ty.html#method.kind
 [LateContext]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint/struct.LateContext.html
 [LateLintPass]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint/trait.LateLintPass.html
-[pat_ty]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/context/struct.TypeckResults.html#method.pat_ty
+[pat_ty]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/typeck_results/struct.TypeckResults.html#method.pat_ty
 [Ty]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.Ty.html
-[TyKind]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/enum.TyKind.html
+[TyKind]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_type_ir/sty/enum.TyKind.html
 [TypeckResults]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.TypeckResults.html
 [middle_ty]: https://doc.rust-lang.org/beta/nightly-rustc/rustc_middle/ty/struct.Ty.html
 [hir_ty]: https://doc.rust-lang.org/beta/nightly-rustc/rustc_hir/struct.Ty.html
diff --git a/src/tools/clippy/clippy_lints/Cargo.toml b/src/tools/clippy/clippy_lints/Cargo.toml
index 37e1e6a742f..98e69c7fd26 100644
--- a/src/tools/clippy/clippy_lints/Cargo.toml
+++ b/src/tools/clippy/clippy_lints/Cargo.toml
@@ -17,7 +17,7 @@ if_chain = "1.0"
 itertools = "0.10.1"
 pulldown-cmark = { version = "0.9", default-features = false }
 quine-mc_cluskey = "0.2"
-regex-syntax = "0.6"
+regex-syntax = "0.7"
 serde = { version = "1.0", features = ["derive"] }
 serde_json = { version = "1.0", optional = true }
 tempfile = { version = "3.2", optional = true }
diff --git a/src/tools/clippy/clippy_lints/src/assertions_on_constants.rs b/src/tools/clippy/clippy_lints/src/assertions_on_constants.rs
index a36df55d0bd..a8dc0cb3b58 100644
--- a/src/tools/clippy/clippy_lints/src/assertions_on_constants.rs
+++ b/src/tools/clippy/clippy_lints/src/assertions_on_constants.rs
@@ -38,7 +38,7 @@ impl<'tcx> LateLintPass<'tcx> for AssertionsOnConstants {
             _ => return,
         };
         let Some((condition, panic_expn)) = find_assert_args(cx, e, macro_call.expn) else { return };
-        let Some((Constant::Bool(val), _)) = constant(cx, cx.typeck_results(), condition) else { return };
+        let Some(Constant::Bool(val)) = constant(cx, cx.typeck_results(), condition) else { return };
         if val {
             span_lint_and_help(
                 cx,
diff --git a/src/tools/clippy/clippy_lints/src/attrs.rs b/src/tools/clippy/clippy_lints/src/attrs.rs
index 751c262673b..897495ba108 100644
--- a/src/tools/clippy/clippy_lints/src/attrs.rs
+++ b/src/tools/clippy/clippy_lints/src/attrs.rs
@@ -178,6 +178,52 @@ declare_clippy_lint! {
 
 declare_clippy_lint! {
     /// ### What it does
+    /// Checks for empty lines after documenation comments.
+    ///
+    /// ### Why is this bad?
+    /// The documentation comment was most likely meant to be an inner attribute or regular comment.
+    /// If it was intended to be a documentation comment, then the empty line should be removed to
+    /// be more idiomatic.
+    ///
+    /// ### Known problems
+    /// Only detects empty lines immediately following the documentation. If the doc comment is followed
+    /// by an attribute and then an empty line, this lint will not trigger. Use `empty_line_after_outer_attr`
+    /// in combination with this lint to detect both cases.
+    ///
+    /// Does not detect empty lines after doc attributes (e.g. `#[doc = ""]`).
+    ///
+    /// ### Example
+    /// ```rust
+    /// /// Some doc comment with a blank line after it.
+    ///
+    /// fn not_quite_good_code() { }
+    /// ```
+    ///
+    /// Use instead:
+    /// ```rust
+    /// /// Good (no blank line)
+    /// fn this_is_fine() { }
+    /// ```
+    ///
+    /// ```rust
+    /// // Good (convert to a regular comment)
+    ///
+    /// fn this_is_fine_too() { }
+    /// ```
+    ///
+    /// ```rust
+    /// //! Good (convert to a comment on an inner attribute)
+    ///
+    /// fn this_is_fine_as_well() { }
+    /// ```
+    #[clippy::version = "1.70.0"]
+    pub EMPTY_LINE_AFTER_DOC_COMMENTS,
+    nursery,
+    "empty line after documentation comments"
+}
+
+declare_clippy_lint! {
+    /// ### What it does
     /// Checks for `warn`/`deny`/`forbid` attributes targeting the whole clippy::restriction category.
     ///
     /// ### Why is this bad?
@@ -292,6 +338,30 @@ declare_clippy_lint! {
     "ensures that all `allow` and `expect` attributes have a reason"
 }
 
+declare_clippy_lint! {
+    /// ### What it does
+    /// Checks for `any` and `all` combinators in `cfg` with only one condition.
+    ///
+    /// ### Why is this bad?
+    /// If there is only one condition, no need to wrap it into `any` or `all` combinators.
+    ///
+    /// ### Example
+    /// ```rust
+    /// #[cfg(any(unix))]
+    /// pub struct Bar;
+    /// ```
+    ///
+    /// Use instead:
+    /// ```rust
+    /// #[cfg(unix)]
+    /// pub struct Bar;
+    /// ```
+    #[clippy::version = "1.71.0"]
+    pub NON_MINIMAL_CFG,
+    style,
+    "ensure that all `cfg(any())` and `cfg(all())` have more than one condition"
+}
+
 declare_lint_pass!(Attributes => [
     ALLOW_ATTRIBUTES_WITHOUT_REASON,
     INLINE_ALWAYS,
@@ -604,6 +674,8 @@ impl_lint_pass!(EarlyAttributes => [
     DEPRECATED_CFG_ATTR,
     MISMATCHED_TARGET_OS,
     EMPTY_LINE_AFTER_OUTER_ATTR,
+    EMPTY_LINE_AFTER_DOC_COMMENTS,
+    NON_MINIMAL_CFG,
 ]);
 
 impl EarlyLintPass for EarlyAttributes {
@@ -614,15 +686,22 @@ impl EarlyLintPass for EarlyAttributes {
     fn check_attribute(&mut self, cx: &EarlyContext<'_>, attr: &Attribute) {
         check_deprecated_cfg_attr(cx, attr, &self.msrv);
         check_mismatched_target_os(cx, attr);
+        check_minimal_cfg_condition(cx, attr);
     }
 
     extract_msrv_attr!(EarlyContext);
 }
 
+/// Check for empty lines after outer attributes.
+///
+/// Attributes and documenation comments are both considered outer attributes
+/// by the AST. However, the average user likely considers them to be different.
+/// Checking for empty lines after each of these attributes is split into two different
+/// lints but can share the same logic.
 fn check_empty_line_after_outer_attr(cx: &EarlyContext<'_>, item: &rustc_ast::Item) {
     let mut iter = item.attrs.iter().peekable();
     while let Some(attr) = iter.next() {
-        if matches!(attr.kind, AttrKind::Normal(..))
+        if (matches!(attr.kind, AttrKind::Normal(..)) || matches!(attr.kind, AttrKind::DocComment(..)))
             && attr.style == AttrStyle::Outer
             && is_present_in_source(cx, attr.span)
         {
@@ -639,13 +718,20 @@ fn check_empty_line_after_outer_attr(cx: &EarlyContext<'_>, item: &rustc_ast::It
                 let lines = without_block_comments(lines);
 
                 if lines.iter().filter(|l| l.trim().is_empty()).count() > 2 {
-                    span_lint(
-                        cx,
-                        EMPTY_LINE_AFTER_OUTER_ATTR,
-                        begin_of_attr_to_item,
-                        "found an empty line after an outer attribute. \
-                        Perhaps you forgot to add a `!` to make it an inner attribute?",
-                    );
+                    let (lint_msg, lint_type) = match attr.kind {
+                        AttrKind::DocComment(..) => (
+                            "found an empty line after a doc comment. \
+                            Perhaps you need to use `//!` to make a comment on a module, remove the empty line, or make a regular comment with `//`?",
+                            EMPTY_LINE_AFTER_DOC_COMMENTS,
+                        ),
+                        AttrKind::Normal(..) => (
+                            "found an empty line after an outer attribute. \
+                            Perhaps you forgot to add a `!` to make it an inner attribute?",
+                            EMPTY_LINE_AFTER_OUTER_ATTR,
+                        ),
+                    };
+
+                    span_lint(cx, lint_type, begin_of_attr_to_item, lint_msg);
                 }
             }
         }
@@ -690,6 +776,48 @@ fn check_deprecated_cfg_attr(cx: &EarlyContext<'_>, attr: &Attribute, msrv: &Msr
     }
 }
 
+fn check_nested_cfg(cx: &EarlyContext<'_>, items: &[NestedMetaItem]) {
+    for item in items.iter() {
+        if let NestedMetaItem::MetaItem(meta) = item {
+            if !meta.has_name(sym::any) && !meta.has_name(sym::all) {
+                continue;
+            }
+            if let MetaItemKind::List(list) = &meta.kind {
+                check_nested_cfg(cx, list);
+                if list.len() == 1 {
+                    span_lint_and_then(
+                        cx,
+                        NON_MINIMAL_CFG,
+                        meta.span,
+                        "unneeded sub `cfg` when there is only one condition",
+                        |diag| {
+                            if let Some(snippet) = snippet_opt(cx, list[0].span()) {
+                                diag.span_suggestion(meta.span, "try", snippet, Applicability::MaybeIncorrect);
+                            }
+                        },
+                    );
+                } else if list.is_empty() && meta.has_name(sym::all) {
+                    span_lint_and_then(
+                        cx,
+                        NON_MINIMAL_CFG,
+                        meta.span,
+                        "unneeded sub `cfg` when there is no condition",
+                        |_| {},
+                    );
+                }
+            }
+        }
+    }
+}
+
+fn check_minimal_cfg_condition(cx: &EarlyContext<'_>, attr: &Attribute) {
+    if attr.has_name(sym::cfg) &&
+        let Some(items) = attr.meta_item_list()
+    {
+        check_nested_cfg(cx, &items);
+    }
+}
+
 fn check_mismatched_target_os(cx: &EarlyContext<'_>, attr: &Attribute) {
     fn find_os(name: &str) -> Option<&'static str> {
         UNIX_SYSTEMS
diff --git a/src/tools/clippy/clippy_lints/src/borrow_deref_ref.rs b/src/tools/clippy/clippy_lints/src/borrow_deref_ref.rs
index c4520d00392..814108ed8a7 100644
--- a/src/tools/clippy/clippy_lints/src/borrow_deref_ref.rs
+++ b/src/tools/clippy/clippy_lints/src/borrow_deref_ref.rs
@@ -1,5 +1,6 @@
 use crate::reference::DEREF_ADDROF;
 use clippy_utils::diagnostics::span_lint_and_then;
+use clippy_utils::is_from_proc_macro;
 use clippy_utils::source::snippet_opt;
 use clippy_utils::ty::implements_trait;
 use clippy_utils::{get_parent_expr, is_lint_allowed};
@@ -47,8 +48,8 @@ declare_clippy_lint! {
 
 declare_lint_pass!(BorrowDerefRef => [BORROW_DEREF_REF]);
 
-impl LateLintPass<'_> for BorrowDerefRef {
-    fn check_expr(&mut self, cx: &LateContext<'_>, e: &rustc_hir::Expr<'_>) {
+impl<'tcx> LateLintPass<'tcx> for BorrowDerefRef {
+    fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &rustc_hir::Expr<'tcx>) {
         if_chain! {
             if !e.span.from_expansion();
             if let ExprKind::AddrOf(_, Mutability::Not, addrof_target) = e.kind;
@@ -58,6 +59,7 @@ impl LateLintPass<'_> for BorrowDerefRef {
             if !matches!(deref_target.kind, ExprKind::Unary(UnOp::Deref, ..) );
             let ref_ty = cx.typeck_results().expr_ty(deref_target);
             if let ty::Ref(_, inner_ty, Mutability::Not) = ref_ty.kind();
+            if !is_from_proc_macro(cx, e);
             then{
 
                 if let Some(parent_expr) = get_parent_expr(cx, e){
diff --git a/src/tools/clippy/clippy_lints/src/box_default.rs b/src/tools/clippy/clippy_lints/src/box_default.rs
index dfa949d1af2..e42c3fe2432 100644
--- a/src/tools/clippy/clippy_lints/src/box_default.rs
+++ b/src/tools/clippy/clippy_lints/src/box_default.rs
@@ -8,7 +8,9 @@ use rustc_hir::{
     Block, Expr, ExprKind, Local, Node, QPath, TyKind,
 };
 use rustc_lint::{LateContext, LateLintPass, LintContext};
-use rustc_middle::{lint::in_external_macro, ty::print::with_forced_trimmed_paths};
+use rustc_middle::lint::in_external_macro;
+use rustc_middle::ty::print::with_forced_trimmed_paths;
+use rustc_middle::ty::IsSuggestable;
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 use rustc_span::sym;
 
@@ -49,7 +51,6 @@ impl LateLintPass<'_> for BoxDefault {
             && path_def_id(cx, ty).map_or(false, |id| Some(id) == cx.tcx.lang_items().owned_box())
             && is_default_equivalent(cx, arg)
         {
-            let arg_ty = cx.typeck_results().expr_ty(arg);
             span_lint_and_sugg(
                 cx,
                 BOX_DEFAULT,
@@ -58,8 +59,10 @@ impl LateLintPass<'_> for BoxDefault {
                 "try",
                 if is_plain_default(arg_path) || given_type(cx, expr) {
                     "Box::default()".into()
-                } else {
+                } else if let Some(arg_ty) = cx.typeck_results().expr_ty(arg).make_suggestable(cx.tcx, true) {
                     with_forced_trimmed_paths!(format!("Box::<{arg_ty}>::default()"))
+                } else {
+                    return
                 },
                 Applicability::MachineApplicable
             );
diff --git a/src/tools/clippy/clippy_lints/src/casts/cast_nan_to_int.rs b/src/tools/clippy/clippy_lints/src/casts/cast_nan_to_int.rs
index 322dc41b3a1..da756129db3 100644
--- a/src/tools/clippy/clippy_lints/src/casts/cast_nan_to_int.rs
+++ b/src/tools/clippy/clippy_lints/src/casts/cast_nan_to_int.rs
@@ -21,8 +21,8 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_expr: &Expr<'_>,
 
 fn is_known_nan(cx: &LateContext<'_>, e: &Expr<'_>) -> bool {
     match constant(cx, cx.typeck_results(), e) {
-        Some((Constant::F64(n), _)) => n.is_nan(),
-        Some((Constant::F32(n), _)) => n.is_nan(),
+        Some(Constant::F64(n)) => n.is_nan(),
+        Some(Constant::F32(n)) => n.is_nan(),
         _ => false,
     }
 }
diff --git a/src/tools/clippy/clippy_lints/src/casts/cast_possible_truncation.rs b/src/tools/clippy/clippy_lints/src/casts/cast_possible_truncation.rs
index 95c2ecbf791..84b99ad5c24 100644
--- a/src/tools/clippy/clippy_lints/src/casts/cast_possible_truncation.rs
+++ b/src/tools/clippy/clippy_lints/src/casts/cast_possible_truncation.rs
@@ -15,7 +15,7 @@ use rustc_target::abi::IntegerType;
 use super::{utils, CAST_ENUM_TRUNCATION, CAST_POSSIBLE_TRUNCATION};
 
 fn constant_int(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<u128> {
-    if let Some((Constant::Int(c), _)) = constant(cx, cx.typeck_results(), expr) {
+    if let Some(Constant::Int(c)) = constant(cx, cx.typeck_results(), expr) {
         Some(c)
     } else {
         None
diff --git a/src/tools/clippy/clippy_lints/src/casts/cast_sign_loss.rs b/src/tools/clippy/clippy_lints/src/casts/cast_sign_loss.rs
index a20a97d4e56..a83dfd94dc2 100644
--- a/src/tools/clippy/clippy_lints/src/casts/cast_sign_loss.rs
+++ b/src/tools/clippy/clippy_lints/src/casts/cast_sign_loss.rs
@@ -29,7 +29,7 @@ fn should_lint(cx: &LateContext<'_>, cast_op: &Expr<'_>, cast_from: Ty<'_>, cast
             // Don't lint for positive constants.
             let const_val = constant(cx, cx.typeck_results(), cast_op);
             if_chain! {
-                if let Some((Constant::Int(n), _)) = const_val;
+                if let Some(Constant::Int(n)) = const_val;
                 if let ty::Int(ity) = *cast_from.kind();
                 if sext(cx.tcx, n, ity) >= 0;
                 then {
diff --git a/src/tools/clippy/clippy_lints/src/dbg_macro.rs b/src/tools/clippy/clippy_lints/src/dbg_macro.rs
index 799e71e847a..ea17e7a6071 100644
--- a/src/tools/clippy/clippy_lints/src/dbg_macro.rs
+++ b/src/tools/clippy/clippy_lints/src/dbg_macro.rs
@@ -3,10 +3,10 @@ use clippy_utils::macros::root_macro_call_first_node;
 use clippy_utils::source::snippet_with_applicability;
 use clippy_utils::{is_in_cfg_test, is_in_test_function};
 use rustc_errors::Applicability;
-use rustc_hir::{Expr, ExprKind};
-use rustc_lint::{LateContext, LateLintPass};
+use rustc_hir::{Expr, ExprKind, Node};
+use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_session::{declare_tool_lint, impl_lint_pass};
-use rustc_span::sym;
+use rustc_span::{sym, BytePos, Pos, Span};
 
 declare_clippy_lint! {
     /// ### What it does
@@ -31,6 +31,31 @@ declare_clippy_lint! {
     "`dbg!` macro is intended as a debugging tool"
 }
 
+/// Gets the span of the statement up to the next semicolon, if and only if the next
+/// non-whitespace character actually is a semicolon.
+/// E.g.
+/// ```rust,ignore
+/// 
+///    dbg!();
+///    ^^^^^^^  this span is returned
+///
+///   foo!(dbg!());
+///             no span is returned
+/// ```
+fn span_including_semi(cx: &LateContext<'_>, span: Span) -> Option<Span> {
+    let sm = cx.sess().source_map();
+    let sf = sm.lookup_source_file(span.hi());
+    let src = sf.src.as_ref()?.get(span.hi().to_usize()..)?;
+    let first_non_whitespace = src.find(|c: char| !c.is_whitespace())?;
+
+    if src.as_bytes()[first_non_whitespace] == b';' {
+        let hi = span.hi() + BytePos::from_usize(first_non_whitespace + 1);
+        Some(span.with_hi(hi))
+    } else {
+        None
+    }
+}
+
 #[derive(Copy, Clone)]
 pub struct DbgMacro {
     allow_dbg_in_tests: bool,
@@ -55,13 +80,25 @@ impl LateLintPass<'_> for DbgMacro {
                 return;
             }
             let mut applicability = Applicability::MachineApplicable;
-            let suggestion = match expr.peel_drop_temps().kind {
+
+            let (sugg_span, suggestion) = match expr.peel_drop_temps().kind {
                 // dbg!()
-                ExprKind::Block(_, _) => String::new(),
-                // dbg!(1)
-                ExprKind::Match(val, ..) => {
-                    snippet_with_applicability(cx, val.span.source_callsite(), "..", &mut applicability).to_string()
+                ExprKind::Block(..) => {
+                    // If the `dbg!` macro is a "free" statement and not contained within other expressions,
+                    // remove the whole statement.
+                    if let Some(Node::Stmt(stmt)) = cx.tcx.hir().find_parent(expr.hir_id)
+                        && let Some(span) = span_including_semi(cx, stmt.span.source_callsite())
+                    {
+                        (span, String::new())
+                    } else {
+                        (macro_call.span, String::from("()"))
+                    }
                 },
+                // dbg!(1)
+                ExprKind::Match(val, ..) => (
+                    macro_call.span,
+                    snippet_with_applicability(cx, val.span.source_callsite(), "..", &mut applicability).to_string(),
+                ),
                 // dbg!(2, 3)
                 ExprKind::Tup(
                     [
@@ -82,7 +119,7 @@ impl LateLintPass<'_> for DbgMacro {
                         "..",
                         &mut applicability,
                     );
-                    format!("({snippet})")
+                    (macro_call.span, format!("({snippet})"))
                 },
                 _ => return,
             };
@@ -90,7 +127,7 @@ impl LateLintPass<'_> for DbgMacro {
             span_lint_and_sugg(
                 cx,
                 DBG_MACRO,
-                macro_call.span,
+                sugg_span,
                 "the `dbg!` macro is intended as a debugging tool",
                 "remove the invocation before committing it to a version control system",
                 suggestion,
diff --git a/src/tools/clippy/clippy_lints/src/declared_lints.rs b/src/tools/clippy/clippy_lints/src/declared_lints.rs
index 79d0f6f3607..423eee47742 100644
--- a/src/tools/clippy/clippy_lints/src/declared_lints.rs
+++ b/src/tools/clippy/clippy_lints/src/declared_lints.rs
@@ -48,9 +48,11 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
     crate::attrs::BLANKET_CLIPPY_RESTRICTION_LINTS_INFO,
     crate::attrs::DEPRECATED_CFG_ATTR_INFO,
     crate::attrs::DEPRECATED_SEMVER_INFO,
+    crate::attrs::EMPTY_LINE_AFTER_DOC_COMMENTS_INFO,
     crate::attrs::EMPTY_LINE_AFTER_OUTER_ATTR_INFO,
     crate::attrs::INLINE_ALWAYS_INFO,
     crate::attrs::MISMATCHED_TARGET_OS_INFO,
+    crate::attrs::NON_MINIMAL_CFG_INFO,
     crate::attrs::USELESS_ATTRIBUTE_INFO,
     crate::await_holding_invalid::AWAIT_HOLDING_INVALID_TYPE_INFO,
     crate::await_holding_invalid::AWAIT_HOLDING_LOCK_INFO,
@@ -132,12 +134,8 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
     crate::doc::NEEDLESS_DOCTEST_MAIN_INFO,
     crate::doc::UNNECESSARY_SAFETY_DOC_INFO,
     crate::double_parens::DOUBLE_PARENS_INFO,
-    crate::drop_forget_ref::DROP_COPY_INFO,
     crate::drop_forget_ref::DROP_NON_DROP_INFO,
-    crate::drop_forget_ref::DROP_REF_INFO,
-    crate::drop_forget_ref::FORGET_COPY_INFO,
     crate::drop_forget_ref::FORGET_NON_DROP_INFO,
-    crate::drop_forget_ref::FORGET_REF_INFO,
     crate::drop_forget_ref::UNDROPPED_MANUALLY_DROPS_INFO,
     crate::duplicate_mod::DUPLICATE_MOD_INFO,
     crate::else_if_without_else::ELSE_IF_WITHOUT_ELSE_INFO,
@@ -351,6 +349,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
     crate::methods::ITER_WITH_DRAIN_INFO,
     crate::methods::MANUAL_FILTER_MAP_INFO,
     crate::methods::MANUAL_FIND_MAP_INFO,
+    crate::methods::MANUAL_NEXT_BACK_INFO,
     crate::methods::MANUAL_OK_OR_INFO,
     crate::methods::MANUAL_SATURATING_ARITHMETIC_INFO,
     crate::methods::MANUAL_SPLIT_ONCE_INFO,
@@ -489,7 +488,6 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
     crate::operators::FLOAT_EQUALITY_WITHOUT_ABS_INFO,
     crate::operators::IDENTITY_OP_INFO,
     crate::operators::INEFFECTIVE_BIT_MASK_INFO,
-    crate::operators::INTEGER_ARITHMETIC_INFO,
     crate::operators::INTEGER_DIVISION_INFO,
     crate::operators::MISREFACTORED_ASSIGN_OP_INFO,
     crate::operators::MODULO_ARITHMETIC_INFO,
@@ -539,6 +537,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
     crate::redundant_slicing::REDUNDANT_SLICING_INFO,
     crate::redundant_static_lifetimes::REDUNDANT_STATIC_LIFETIMES_INFO,
     crate::ref_option_ref::REF_OPTION_REF_INFO,
+    crate::ref_patterns::REF_PATTERNS_INFO,
     crate::reference::DEREF_ADDROF_INFO,
     crate::regex::INVALID_REGEX_INFO,
     crate::regex::TRIVIAL_REGEX_INFO,
diff --git a/src/tools/clippy/clippy_lints/src/default_constructed_unit_structs.rs b/src/tools/clippy/clippy_lints/src/default_constructed_unit_structs.rs
index e529d81a7e9..9bd7a0dc0f3 100644
--- a/src/tools/clippy/clippy_lints/src/default_constructed_unit_structs.rs
+++ b/src/tools/clippy/clippy_lints/src/default_constructed_unit_structs.rs
@@ -1,4 +1,4 @@
-use clippy_utils::{diagnostics::span_lint_and_sugg, is_from_proc_macro, match_def_path, paths};
+use clippy_utils::{diagnostics::span_lint_and_sugg, match_def_path, paths};
 use hir::{def::Res, ExprKind};
 use rustc_errors::Applicability;
 use rustc_hir as hir;
@@ -55,7 +55,8 @@ impl LateLintPass<'_> for DefaultConstructedUnitStructs {
             if let ty::Adt(def, ..) = cx.typeck_results().expr_ty(expr).kind();
             if def.is_struct();
             if let var @ ty::VariantDef { ctor: Some((hir::def::CtorKind::Const, _)), .. } = def.non_enum_variant();
-            if !var.is_field_list_non_exhaustive() && !is_from_proc_macro(cx, expr);
+            if !var.is_field_list_non_exhaustive();
+            if !expr.span.from_expansion() && !qpath.span().from_expansion();
             then {
                 span_lint_and_sugg(
                     cx,
diff --git a/src/tools/clippy/clippy_lints/src/drop_forget_ref.rs b/src/tools/clippy/clippy_lints/src/drop_forget_ref.rs
index 11e1bcdf12d..9c60edb1794 100644
--- a/src/tools/clippy/clippy_lints/src/drop_forget_ref.rs
+++ b/src/tools/clippy/clippy_lints/src/drop_forget_ref.rs
@@ -9,102 +9,6 @@ use rustc_span::sym;
 
 declare_clippy_lint! {
     /// ### What it does
-    /// Checks for calls to `std::mem::drop` with a reference
-    /// instead of an owned value.
-    ///
-    /// ### Why is this bad?
-    /// Calling `drop` on a reference will only drop the
-    /// reference itself, which is a no-op. It will not call the `drop` method (from
-    /// the `Drop` trait implementation) on the underlying referenced value, which
-    /// is likely what was intended.
-    ///
-    /// ### Example
-    /// ```ignore
-    /// let mut lock_guard = mutex.lock();
-    /// std::mem::drop(&lock_guard) // Should have been drop(lock_guard), mutex
-    /// // still locked
-    /// operation_that_requires_mutex_to_be_unlocked();
-    /// ```
-    #[clippy::version = "pre 1.29.0"]
-    pub DROP_REF,
-    correctness,
-    "calls to `std::mem::drop` with a reference instead of an owned value"
-}
-
-declare_clippy_lint! {
-    /// ### What it does
-    /// Checks for calls to `std::mem::forget` with a reference
-    /// instead of an owned value.
-    ///
-    /// ### Why is this bad?
-    /// Calling `forget` on a reference will only forget the
-    /// reference itself, which is a no-op. It will not forget the underlying
-    /// referenced
-    /// value, which is likely what was intended.
-    ///
-    /// ### Example
-    /// ```rust
-    /// let x = Box::new(1);
-    /// std::mem::forget(&x) // Should have been forget(x), x will still be dropped
-    /// ```
-    #[clippy::version = "pre 1.29.0"]
-    pub FORGET_REF,
-    correctness,
-    "calls to `std::mem::forget` with a reference instead of an owned value"
-}
-
-declare_clippy_lint! {
-    /// ### What it does
-    /// Checks for calls to `std::mem::drop` with a value
-    /// that derives the Copy trait
-    ///
-    /// ### Why is this bad?
-    /// Calling `std::mem::drop` [does nothing for types that
-    /// implement Copy](https://doc.rust-lang.org/std/mem/fn.drop.html), since the
-    /// value will be copied and moved into the function on invocation.
-    ///
-    /// ### Example
-    /// ```rust
-    /// let x: i32 = 42; // i32 implements Copy
-    /// std::mem::drop(x) // A copy of x is passed to the function, leaving the
-    ///                   // original unaffected
-    /// ```
-    #[clippy::version = "pre 1.29.0"]
-    pub DROP_COPY,
-    correctness,
-    "calls to `std::mem::drop` with a value that implements Copy"
-}
-
-declare_clippy_lint! {
-    /// ### What it does
-    /// Checks for calls to `std::mem::forget` with a value that
-    /// derives the Copy trait
-    ///
-    /// ### Why is this bad?
-    /// Calling `std::mem::forget` [does nothing for types that
-    /// implement Copy](https://doc.rust-lang.org/std/mem/fn.drop.html) since the
-    /// value will be copied and moved into the function on invocation.
-    ///
-    /// An alternative, but also valid, explanation is that Copy types do not
-    /// implement
-    /// the Drop trait, which means they have no destructors. Without a destructor,
-    /// there
-    /// is nothing for `std::mem::forget` to ignore.
-    ///
-    /// ### Example
-    /// ```rust
-    /// let x: i32 = 42; // i32 implements Copy
-    /// std::mem::forget(x) // A copy of x is passed to the function, leaving the
-    ///                     // original unaffected
-    /// ```
-    #[clippy::version = "pre 1.29.0"]
-    pub FORGET_COPY,
-    correctness,
-    "calls to `std::mem::forget` with a value that implements Copy"
-}
-
-declare_clippy_lint! {
-    /// ### What it does
     /// Checks for calls to `std::mem::drop` with a value that does not implement `Drop`.
     ///
     /// ### Why is this bad?
@@ -172,24 +76,12 @@ declare_clippy_lint! {
     "use of safe `std::mem::drop` function to drop a std::mem::ManuallyDrop, which will not drop the inner value"
 }
 
-const DROP_REF_SUMMARY: &str = "calls to `std::mem::drop` with a reference instead of an owned value. \
-                                Dropping a reference does nothing";
-const FORGET_REF_SUMMARY: &str = "calls to `std::mem::forget` with a reference instead of an owned value. \
-                                  Forgetting a reference does nothing";
-const DROP_COPY_SUMMARY: &str = "calls to `std::mem::drop` with a value that implements `Copy`. \
-                                 Dropping a copy leaves the original intact";
-const FORGET_COPY_SUMMARY: &str = "calls to `std::mem::forget` with a value that implements `Copy`. \
-                                   Forgetting a copy leaves the original intact";
 const DROP_NON_DROP_SUMMARY: &str = "call to `std::mem::drop` with a value that does not implement `Drop`. \
                                  Dropping such a type only extends its contained lifetimes";
 const FORGET_NON_DROP_SUMMARY: &str = "call to `std::mem::forget` with a value that does not implement `Drop`. \
                                    Forgetting such a type is the same as dropping it";
 
 declare_lint_pass!(DropForgetRef => [
-    DROP_REF,
-    FORGET_REF,
-    DROP_COPY,
-    FORGET_COPY,
     DROP_NON_DROP,
     FORGET_NON_DROP,
     UNDROPPED_MANUALLY_DROPS
@@ -206,10 +98,11 @@ impl<'tcx> LateLintPass<'tcx> for DropForgetRef {
             let is_copy = is_copy(cx, arg_ty);
             let drop_is_single_call_in_arm = is_single_call_in_arm(cx, arg, expr);
             let (lint, msg) = match fn_name {
-                sym::mem_drop if arg_ty.is_ref() && !drop_is_single_call_in_arm => (DROP_REF, DROP_REF_SUMMARY),
-                sym::mem_forget if arg_ty.is_ref() => (FORGET_REF, FORGET_REF_SUMMARY),
-                sym::mem_drop if is_copy && !drop_is_single_call_in_arm => (DROP_COPY, DROP_COPY_SUMMARY),
-                sym::mem_forget if is_copy => (FORGET_COPY, FORGET_COPY_SUMMARY),
+                // early return for uplifted lints: dropping_references, dropping_copy_types, forgetting_references, forgetting_copy_types
+                sym::mem_drop if arg_ty.is_ref() && !drop_is_single_call_in_arm => return,
+                sym::mem_forget if arg_ty.is_ref() => return,
+                sym::mem_drop if is_copy && !drop_is_single_call_in_arm => return,
+                sym::mem_forget if is_copy => return,
                 sym::mem_drop if is_type_lang_item(cx, arg_ty, LangItem::ManuallyDrop) => {
                     span_lint_and_help(
                         cx,
diff --git a/src/tools/clippy/clippy_lints/src/floating_point_arithmetic.rs b/src/tools/clippy/clippy_lints/src/floating_point_arithmetic.rs
index a1a2c398a8a..3c55a563af4 100644
--- a/src/tools/clippy/clippy_lints/src/floating_point_arithmetic.rs
+++ b/src/tools/clippy/clippy_lints/src/floating_point_arithmetic.rs
@@ -114,7 +114,7 @@ declare_lint_pass!(FloatingPointArithmetic => [
 // Returns the specialized log method for a given base if base is constant
 // and is one of 2, 10 and e
 fn get_specialized_log_method(cx: &LateContext<'_>, base: &Expr<'_>) -> Option<&'static str> {
-    if let Some((value, _)) = constant(cx, cx.typeck_results(), base) {
+    if let Some(value) = constant(cx, cx.typeck_results(), base) {
         if F32(2.0) == value || F64(2.0) == value {
             return Some("log2");
         } else if F32(10.0) == value || F64(10.0) == value {
@@ -193,8 +193,8 @@ fn check_ln1p(cx: &LateContext<'_>, expr: &Expr<'_>, receiver: &Expr<'_>) {
             constant(cx, cx.typeck_results(), lhs),
             constant(cx, cx.typeck_results(), rhs),
         ) {
-            (Some((value, _)), _) if F32(1.0) == value || F64(1.0) == value => rhs,
-            (_, Some((value, _))) if F32(1.0) == value || F64(1.0) == value => lhs,
+            (Some(value), _) if F32(1.0) == value || F64(1.0) == value => rhs,
+            (_, Some(value)) if F32(1.0) == value || F64(1.0) == value => lhs,
             _ => return,
         };
 
@@ -237,7 +237,7 @@ fn get_integer_from_float_constant(value: &Constant) -> Option<i32> {
 
 fn check_powf(cx: &LateContext<'_>, expr: &Expr<'_>, receiver: &Expr<'_>, args: &[Expr<'_>]) {
     // Check receiver
-    if let Some((value, _)) = constant(cx, cx.typeck_results(), receiver) {
+    if let Some(value) = constant(cx, cx.typeck_results(), receiver) {
         if let Some(method) = if F32(f32_consts::E) == value || F64(f64_consts::E) == value {
             Some("exp")
         } else if F32(2.0) == value || F64(2.0) == value {
@@ -258,7 +258,7 @@ fn check_powf(cx: &LateContext<'_>, expr: &Expr<'_>, receiver: &Expr<'_>, args:
     }
 
     // Check argument
-    if let Some((value, _)) = constant(cx, cx.typeck_results(), &args[0]) {
+    if let Some(value) = constant(cx, cx.typeck_results(), &args[0]) {
         let (lint, help, suggestion) = if F32(1.0 / 2.0) == value || F64(1.0 / 2.0) == value {
             (
                 SUBOPTIMAL_FLOPS,
@@ -298,7 +298,7 @@ fn check_powf(cx: &LateContext<'_>, expr: &Expr<'_>, receiver: &Expr<'_>, args:
 }
 
 fn check_powi(cx: &LateContext<'_>, expr: &Expr<'_>, receiver: &Expr<'_>, args: &[Expr<'_>]) {
-    if let Some((value, _)) = constant(cx, cx.typeck_results(), &args[0]) {
+    if let Some(value) = constant(cx, cx.typeck_results(), &args[0]) {
         if value == Int(2) {
             if let Some(parent) = get_parent_expr(cx, expr) {
                 if let Some(grandparent) = get_parent_expr(cx, parent) {
@@ -384,8 +384,8 @@ fn detect_hypot(cx: &LateContext<'_>, receiver: &Expr<'_>) -> Option<String> {
                 _
             ) = &add_rhs.kind;
             if lmethod_name.as_str() == "powi" && rmethod_name.as_str() == "powi";
-            if let Some((lvalue, _)) = constant(cx, cx.typeck_results(), largs_1);
-            if let Some((rvalue, _)) = constant(cx, cx.typeck_results(), rargs_1);
+            if let Some(lvalue) = constant(cx, cx.typeck_results(), largs_1);
+            if let Some(rvalue) = constant(cx, cx.typeck_results(), rargs_1);
             if Int(2) == lvalue && Int(2) == rvalue;
             then {
                 return Some(format!("{}.hypot({})", Sugg::hir(cx, largs_0, "..").maybe_par(), Sugg::hir(cx, rargs_0, "..")));
@@ -416,7 +416,7 @@ fn check_expm1(cx: &LateContext<'_>, expr: &Expr<'_>) {
     if_chain! {
         if let ExprKind::Binary(Spanned { node: BinOpKind::Sub, .. }, lhs, rhs) = expr.kind;
         if cx.typeck_results().expr_ty(lhs).is_floating_point();
-        if let Some((value, _)) = constant(cx, cx.typeck_results(), rhs);
+        if let Some(value) = constant(cx, cx.typeck_results(), rhs);
         if F32(1.0) == value || F64(1.0) == value;
         if let ExprKind::MethodCall(path, self_arg, ..) = &lhs.kind;
         if cx.typeck_results().expr_ty(self_arg).is_floating_point();
@@ -669,8 +669,8 @@ fn check_radians(cx: &LateContext<'_>, expr: &Expr<'_>) {
             mul_lhs,
             mul_rhs,
         ) = &div_lhs.kind;
-        if let Some((rvalue, _)) = constant(cx, cx.typeck_results(), div_rhs);
-        if let Some((lvalue, _)) = constant(cx, cx.typeck_results(), mul_rhs);
+        if let Some(rvalue) = constant(cx, cx.typeck_results(), div_rhs);
+        if let Some(lvalue) = constant(cx, cx.typeck_results(), mul_rhs);
         then {
             // TODO: also check for constant values near PI/180 or 180/PI
             if (F32(f32_consts::PI) == rvalue || F64(f64_consts::PI) == rvalue) &&
diff --git a/src/tools/clippy/clippy_lints/src/fn_null_check.rs b/src/tools/clippy/clippy_lints/src/fn_null_check.rs
index d8f4a5fe221..521045a9fed 100644
--- a/src/tools/clippy/clippy_lints/src/fn_null_check.rs
+++ b/src/tools/clippy/clippy_lints/src/fn_null_check.rs
@@ -89,11 +89,7 @@ impl<'tcx> LateLintPass<'tcx> for FnNullCheck {
 
                     // Catching:
                     // (fn_ptr as *<const/mut> <ty>) == <const that evaluates to null_ptr>
-                    _ if matches!(
-                        constant(cx, cx.typeck_results(), to_check),
-                        Some((Constant::RawPtr(0), _))
-                    ) =>
-                    {
+                    _ if matches!(constant(cx, cx.typeck_results(), to_check), Some(Constant::RawPtr(0))) => {
                         lint_expr(cx, expr);
                     },
 
diff --git a/src/tools/clippy/clippy_lints/src/implicit_saturating_add.rs b/src/tools/clippy/clippy_lints/src/implicit_saturating_add.rs
index 012aa5a1d1d..ee7973b82ab 100644
--- a/src/tools/clippy/clippy_lints/src/implicit_saturating_add.rs
+++ b/src/tools/clippy/clippy_lints/src/implicit_saturating_add.rs
@@ -101,10 +101,10 @@ fn get_int_max(ty: Ty<'_>) -> Option<u128> {
 fn get_const<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'tcx>) -> Option<(u128, BinOpKind, &'tcx Expr<'tcx>)> {
     if let ExprKind::Binary(op, l, r) = expr.kind {
         let tr = cx.typeck_results();
-        if let Some((Constant::Int(c), _)) = constant(cx, tr, r) {
+        if let Some(Constant::Int(c)) = constant(cx, tr, r) {
             return Some((c, op.node, l));
         };
-        if let Some((Constant::Int(c), _)) = constant(cx, tr, l) {
+        if let Some(Constant::Int(c)) = constant(cx, tr, l) {
             return Some((c, invert_op(op.node)?, r));
         }
     }
diff --git a/src/tools/clippy/clippy_lints/src/index_refutable_slice.rs b/src/tools/clippy/clippy_lints/src/index_refutable_slice.rs
index bdeddf44df7..7a269e98ff1 100644
--- a/src/tools/clippy/clippy_lints/src/index_refutable_slice.rs
+++ b/src/tools/clippy/clippy_lints/src/index_refutable_slice.rs
@@ -254,7 +254,7 @@ impl<'a, 'tcx> Visitor<'tcx> for SliceIndexLintingVisitor<'a, 'tcx> {
                 let parent_id = map.parent_id(expr.hir_id);
                 if let Some(hir::Node::Expr(parent_expr)) = map.find(parent_id);
                 if let hir::ExprKind::Index(_, index_expr) = parent_expr.kind;
-                if let Some((Constant::Int(index_value), _)) = constant(cx, cx.typeck_results(), index_expr);
+                if let Some(Constant::Int(index_value)) = constant(cx, cx.typeck_results(), index_expr);
                 if let Ok(index_value) = index_value.try_into();
                 if index_value < max_suggested_slice;
 
diff --git a/src/tools/clippy/clippy_lints/src/indexing_slicing.rs b/src/tools/clippy/clippy_lints/src/indexing_slicing.rs
index 924a361c0f6..22c14d9b04d 100644
--- a/src/tools/clippy/clippy_lints/src/indexing_slicing.rs
+++ b/src/tools/clippy/clippy_lints/src/indexing_slicing.rs
@@ -191,18 +191,14 @@ impl<'tcx> LateLintPass<'tcx> for IndexingSlicing {
 /// Returns a tuple of options with the start and end (exclusive) values of
 /// the range. If the start or end is not constant, None is returned.
 fn to_const_range(cx: &LateContext<'_>, range: higher::Range<'_>, array_size: u128) -> (Option<u128>, Option<u128>) {
-    let s = range
-        .start
-        .map(|expr| constant(cx, cx.typeck_results(), expr).map(|(c, _)| c));
+    let s = range.start.map(|expr| constant(cx, cx.typeck_results(), expr));
     let start = match s {
         Some(Some(Constant::Int(x))) => Some(x),
         Some(_) => None,
         None => Some(0),
     };
 
-    let e = range
-        .end
-        .map(|expr| constant(cx, cx.typeck_results(), expr).map(|(c, _)| c));
+    let e = range.end.map(|expr| constant(cx, cx.typeck_results(), expr));
     let end = match e {
         Some(Some(Constant::Int(x))) => {
             if range.limits == RangeLimits::Closed {
diff --git a/src/tools/clippy/clippy_lints/src/let_underscore.rs b/src/tools/clippy/clippy_lints/src/let_underscore.rs
index 16772a9d598..e6614180920 100644
--- a/src/tools/clippy/clippy_lints/src/let_underscore.rs
+++ b/src/tools/clippy/clippy_lints/src/let_underscore.rs
@@ -1,10 +1,12 @@
 use clippy_utils::diagnostics::span_lint_and_help;
+use clippy_utils::is_from_proc_macro;
 use clippy_utils::ty::{implements_trait, is_must_use_ty, match_type};
 use clippy_utils::{is_must_use_func_call, paths};
-use rustc_hir::{ExprKind, Local, PatKind};
+use rustc_hir::{Local, PatKind};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::lint::in_external_macro;
 use rustc_middle::ty::subst::GenericArgKind;
+use rustc_middle::ty::IsSuggestable;
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 use rustc_span::{BytePos, Span};
 
@@ -138,7 +140,7 @@ const SYNC_GUARD_PATHS: [&[&str]; 3] = [
 ];
 
 impl<'tcx> LateLintPass<'tcx> for LetUnderscore {
-    fn check_local(&mut self, cx: &LateContext<'_>, local: &Local<'_>) {
+    fn check_local(&mut self, cx: &LateContext<'tcx>, local: &Local<'tcx>) {
         if !in_external_macro(cx.tcx.sess, local.span)
             && let PatKind::Wild = local.pat.kind
             && let Some(init) = local.init
@@ -191,15 +193,17 @@ impl<'tcx> LateLintPass<'tcx> for LetUnderscore {
             if local.pat.default_binding_modes && local.ty.is_none() {
                 // When `default_binding_modes` is true, the `let` keyword is present.
 
-				// Ignore function calls that return impl traits...
-				if let Some(init) = local.init &&
-				matches!(init.kind, ExprKind::Call(_, _) | ExprKind::MethodCall(_, _, _, _)) {
-					let expr_ty = cx.typeck_results().expr_ty(init);
-					if expr_ty.is_impl_trait() {
-						return;
-					}
-				}
+                // Ignore unnameable types
+                if let Some(init) = local.init
+                    && !cx.typeck_results().expr_ty(init).is_suggestable(cx.tcx, true)
+                {
+                    return;
+                }
 
+                // Ignore if it is from a procedural macro...
+                if is_from_proc_macro(cx, init) {
+                    return;
+                }
 
 				span_lint_and_help(
                     cx,
diff --git a/src/tools/clippy/clippy_lints/src/lib.rs b/src/tools/clippy/clippy_lints/src/lib.rs
index 3517842a01e..b442a4ac5f6 100644
--- a/src/tools/clippy/clippy_lints/src/lib.rs
+++ b/src/tools/clippy/clippy_lints/src/lib.rs
@@ -266,6 +266,7 @@ mod redundant_pub_crate;
 mod redundant_slicing;
 mod redundant_static_lifetimes;
 mod ref_option_ref;
+mod ref_patterns;
 mod reference;
 mod regex;
 mod return_self_not_must_use;
@@ -331,8 +332,11 @@ mod zero_div_zero;
 mod zero_sized_map_values;
 // end lints modules, do not remove this comment, it’s used in `update_lints`
 
-use crate::utils::conf::{format_error, TryConf};
 pub use crate::utils::conf::{lookup_conf_file, Conf};
+use crate::utils::{
+    conf::{format_error, metadata::get_configuration_metadata, TryConf},
+    FindAll,
+};
 
 /// Register all pre expansion lints
 ///
@@ -471,7 +475,22 @@ pub(crate) struct LintInfo {
 pub fn explain(name: &str) {
     let target = format!("clippy::{}", name.to_ascii_uppercase());
     match declared_lints::LINTS.iter().find(|info| info.lint.name == target) {
-        Some(info) => print!("{}", info.explanation),
+        Some(info) => {
+            println!("{}", info.explanation);
+            // Check if the lint has configuration
+            let mdconf = get_configuration_metadata();
+            if let Some(config_vec_positions) = mdconf
+                .iter()
+                .find_all(|cconf| cconf.lints.contains(&info.lint.name_lower()[8..].to_owned()))
+            {
+                // If it has, print it
+                println!("### Configuration for {}:\n", info.lint.name_lower());
+                for position in config_vec_positions {
+                    let conf = &mdconf[position];
+                    println!("  - {}: {} (default: {})", conf.name, conf.doc, conf.default);
+                }
+            }
+        },
         None => println!("unknown lint: {name}"),
     }
 }
@@ -971,6 +990,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
     store.register_late_pass(|_| Box::new(manual_slice_size_calculation::ManualSliceSizeCalculation));
     store.register_early_pass(|| Box::new(suspicious_doc_comments::SuspiciousDocComments));
     store.register_late_pass(|_| Box::new(items_after_test_module::ItemsAfterTestModule));
+    store.register_early_pass(|| Box::new(ref_patterns::RefPatterns));
     store.register_late_pass(|_| Box::new(default_constructed_unit_structs::DefaultConstructedUnitStructs));
     // add lints here, do not remove this comment, it's used in `new_lint`
 }
diff --git a/src/tools/clippy/clippy_lints/src/lines_filter_map_ok.rs b/src/tools/clippy/clippy_lints/src/lines_filter_map_ok.rs
index bba9bb445a7..09b2032e20f 100644
--- a/src/tools/clippy/clippy_lints/src/lines_filter_map_ok.rs
+++ b/src/tools/clippy/clippy_lints/src/lines_filter_map_ok.rs
@@ -25,7 +25,7 @@ declare_clippy_lint! {
     ///
     /// ### Known problems
     /// This lint suggests replacing `filter_map()` or `flat_map()` applied to a `Lines`
-    /// instance in all cases. There two cases where the suggestion might not be
+    /// instance in all cases. There are two cases where the suggestion might not be
     /// appropriate or necessary:
     ///
     /// - If the `Lines` instance can never produce any error, or if an error is produced
diff --git a/src/tools/clippy/clippy_lints/src/manual_let_else.rs b/src/tools/clippy/clippy_lints/src/manual_let_else.rs
index 1247370b74a..3f8b42ffe80 100644
--- a/src/tools/clippy/clippy_lints/src/manual_let_else.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_let_else.rs
@@ -38,7 +38,6 @@ declare_clippy_lint! {
     /// Could be written:
     ///
     /// ```rust
-    /// # #![feature(let_else)]
     /// # fn main () {
     /// # let w = Some(0);
     /// let Some(v) = w else { return };
@@ -69,29 +68,23 @@ impl_lint_pass!(ManualLetElse => [MANUAL_LET_ELSE]);
 
 impl<'tcx> LateLintPass<'tcx> for ManualLetElse {
     fn check_stmt(&mut self, cx: &LateContext<'_>, stmt: &'tcx Stmt<'tcx>) {
-        let if_let_or_match = if_chain! {
-            if self.msrv.meets(msrvs::LET_ELSE);
-            if !in_external_macro(cx.sess(), stmt.span);
-            if let StmtKind::Local(local) = stmt.kind;
-            if let Some(init) = local.init;
-            if local.els.is_none();
-            if local.ty.is_none();
-            if init.span.ctxt() == stmt.span.ctxt();
-            if let Some(if_let_or_match) = IfLetOrMatch::parse(cx, init);
-            then {
-                if_let_or_match
-            } else {
-                return;
-            }
-        };
+        if !self.msrv.meets(msrvs::LET_ELSE) || in_external_macro(cx.sess(), stmt.span) {
+            return;
+        }
 
+        if let StmtKind::Local(local) = stmt.kind &&
+            let Some(init) = local.init &&
+            local.els.is_none() &&
+            local.ty.is_none() &&
+            init.span.ctxt() == stmt.span.ctxt() &&
+            let Some(if_let_or_match) = IfLetOrMatch::parse(cx, init) {
         match if_let_or_match {
             IfLetOrMatch::IfLet(if_let_expr, let_pat, if_then, if_else) => if_chain! {
                 if expr_is_simple_identity(let_pat, if_then);
                 if let Some(if_else) = if_else;
                 if expr_diverges(cx, if_else);
                 then {
-                    emit_manual_let_else(cx, stmt.span, if_let_expr, let_pat, if_else);
+                    emit_manual_let_else(cx, stmt.span, if_let_expr, local.pat, let_pat, if_else);
                 }
             },
             IfLetOrMatch::Match(match_expr, arms, source) => {
@@ -128,15 +121,23 @@ impl<'tcx> LateLintPass<'tcx> for ManualLetElse {
                     return;
                 }
 
-                emit_manual_let_else(cx, stmt.span, match_expr, pat_arm.pat, diverging_arm.body);
+                emit_manual_let_else(cx, stmt.span, match_expr, local.pat, pat_arm.pat, diverging_arm.body);
             },
         }
+        };
     }
 
     extract_msrv_attr!(LateContext);
 }
 
-fn emit_manual_let_else(cx: &LateContext<'_>, span: Span, expr: &Expr<'_>, pat: &Pat<'_>, else_body: &Expr<'_>) {
+fn emit_manual_let_else(
+    cx: &LateContext<'_>,
+    span: Span,
+    expr: &Expr<'_>,
+    local: &Pat<'_>,
+    pat: &Pat<'_>,
+    else_body: &Expr<'_>,
+) {
     span_lint_and_then(
         cx,
         MANUAL_LET_ELSE,
@@ -145,12 +146,11 @@ fn emit_manual_let_else(cx: &LateContext<'_>, span: Span, expr: &Expr<'_>, pat:
         |diag| {
             // This is far from perfect, for example there needs to be:
             // * mut additions for the bindings
-            // * renamings of the bindings
+            // * renamings of the bindings for `PatKind::Or`
             // * unused binding collision detection with existing ones
             // * putting patterns with at the top level | inside ()
             // for this to be machine applicable.
             let mut app = Applicability::HasPlaceholders;
-            let (sn_pat, _) = snippet_with_context(cx, pat.span, span.ctxt(), "", &mut app);
             let (sn_expr, _) = snippet_with_context(cx, expr.span, span.ctxt(), "", &mut app);
             let (sn_else, _) = snippet_with_context(cx, else_body.span, span.ctxt(), "", &mut app);
 
@@ -159,10 +159,21 @@ fn emit_manual_let_else(cx: &LateContext<'_>, span: Span, expr: &Expr<'_>, pat:
             } else {
                 format!("{{ {sn_else} }}")
             };
-            let sn_bl = if matches!(pat.kind, PatKind::Or(..)) {
-                format!("({sn_pat})")
-            } else {
-                sn_pat.into_owned()
+            let sn_bl = match pat.kind {
+                PatKind::Or(..) => {
+                    let (sn_pat, _) = snippet_with_context(cx, pat.span, span.ctxt(), "", &mut app);
+                    format!("({sn_pat})")
+                },
+                // Replace the variable name iff `TupleStruct` has one argument like `Variant(v)`.
+                PatKind::TupleStruct(ref w, args, ..) if args.len() == 1 => {
+                    let sn_wrapper = cx.sess().source_map().span_to_snippet(w.span()).unwrap_or_default();
+                    let (sn_inner, _) = snippet_with_context(cx, local.span, span.ctxt(), "", &mut app);
+                    format!("{sn_wrapper}({sn_inner})")
+                },
+                _ => {
+                    let (sn_pat, _) = snippet_with_context(cx, pat.span, span.ctxt(), "", &mut app);
+                    sn_pat.into_owned()
+                },
             };
             let sugg = format!("let {sn_bl} = {sn_expr} else {else_bl};");
             diag.span_suggestion(span, "consider writing", sugg, app);
diff --git a/src/tools/clippy/clippy_lints/src/manual_strip.rs b/src/tools/clippy/clippy_lints/src/manual_strip.rs
index 7d28c111624..93d977a5c96 100644
--- a/src/tools/clippy/clippy_lints/src/manual_strip.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_strip.rs
@@ -144,7 +144,7 @@ fn len_arg<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option<&'tcx E
 
 // Returns the length of the `expr` if it's a constant string or char.
 fn constant_length(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<u128> {
-    let (value, _) = constant(cx, cx.typeck_results(), expr)?;
+    let value = constant(cx, cx.typeck_results(), expr)?;
     match value {
         Constant::Str(value) => Some(value.len() as u128),
         Constant::Char(value) => Some(value.len_utf8() as u128),
diff --git a/src/tools/clippy/clippy_lints/src/matches/match_like_matches.rs b/src/tools/clippy/clippy_lints/src/matches/match_like_matches.rs
index 33bc20dad6b..0064619ef89 100644
--- a/src/tools/clippy/clippy_lints/src/matches/match_like_matches.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/match_like_matches.rs
@@ -1,10 +1,12 @@
+use super::REDUNDANT_PATTERN_MATCHING;
 use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::is_lint_allowed;
 use clippy_utils::is_wild;
 use clippy_utils::source::snippet_with_applicability;
 use clippy_utils::span_contains_comment;
 use rustc_ast::{Attribute, LitKind};
 use rustc_errors::Applicability;
-use rustc_hir::{Arm, BorrowKind, Expr, ExprKind, Guard, Pat};
+use rustc_hir::{Arm, BorrowKind, Expr, ExprKind, Guard, Pat, PatKind, QPath};
 use rustc_lint::{LateContext, LintContext};
 use rustc_middle::ty;
 use rustc_span::source_map::Spanned;
@@ -99,6 +101,14 @@ where
                 }
             }
 
+            for arm in iter_without_last.clone() {
+                if let Some(pat) = arm.1 {
+                    if !is_lint_allowed(cx, REDUNDANT_PATTERN_MATCHING, pat.hir_id) && is_some(pat.kind) {
+                        return false;
+                    }
+                }
+            }
+
             // The suggestion may be incorrect, because some arms can have `cfg` attributes
             // evaluated into `false` and so such arms will be stripped before.
             let mut applicability = Applicability::MaybeIncorrect;
@@ -170,3 +180,13 @@ fn find_bool_lit(ex: &ExprKind<'_>) -> Option<bool> {
         _ => None,
     }
 }
+
+fn is_some(path_kind: PatKind<'_>) -> bool {
+    match path_kind {
+        PatKind::TupleStruct(QPath::Resolved(_, path), [first, ..], _) if is_wild(first) => {
+            let name = path.segments[0].ident;
+            name.name == rustc_span::sym::Some
+        },
+        _ => false,
+    }
+}
diff --git a/src/tools/clippy/clippy_lints/src/matches/match_same_arms.rs b/src/tools/clippy/clippy_lints/src/matches/match_same_arms.rs
index a48f4c77f85..ae8262ace96 100644
--- a/src/tools/clippy/clippy_lints/src/matches/match_same_arms.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/match_same_arms.rs
@@ -282,9 +282,8 @@ impl<'a> NormalizedPat<'a> {
                 // TODO: Handle negative integers. They're currently treated as a wild match.
                 ExprKind::Lit(lit) => match lit.node {
                     LitKind::Str(sym, _) => Self::LitStr(sym),
-                    LitKind::ByteStr(ref bytes, _) => Self::LitBytes(bytes),
+                    LitKind::ByteStr(ref bytes, _) | LitKind::CStr(ref bytes, _) => Self::LitBytes(bytes),
                     LitKind::Byte(val) => Self::LitInt(val.into()),
-                    LitKind::CStr(ref bytes, _) => Self::LitBytes(bytes),
                     LitKind::Char(val) => Self::LitInt(val.into()),
                     LitKind::Int(val, _) => Self::LitInt(val),
                     LitKind::Bool(val) => Self::LitBool(val),
diff --git a/src/tools/clippy/clippy_lints/src/matches/mod.rs b/src/tools/clippy/clippy_lints/src/matches/mod.rs
index 87b63eead25..55ec9d4474f 100644
--- a/src/tools/clippy/clippy_lints/src/matches/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/mod.rs
@@ -25,9 +25,9 @@ mod wild_in_or_pats;
 
 use clippy_utils::msrvs::{self, Msrv};
 use clippy_utils::source::{snippet_opt, walk_span_to_context};
-use clippy_utils::{higher, in_constant, is_span_match};
+use clippy_utils::{higher, in_constant, is_span_match, tokenize_with_text};
 use rustc_hir::{Arm, Expr, ExprKind, Local, MatchSource, Pat};
-use rustc_lexer::{tokenize, TokenKind};
+use rustc_lexer::TokenKind;
 use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_middle::lint::in_external_macro;
 use rustc_session::{declare_tool_lint, impl_lint_pass};
@@ -1147,12 +1147,7 @@ fn span_contains_cfg(cx: &LateContext<'_>, s: Span) -> bool {
         // Assume true. This would require either an invalid span, or one which crosses file boundaries.
         return true;
     };
-    let mut pos = 0usize;
-    let mut iter = tokenize(&snip).map(|t| {
-        let start = pos;
-        pos += t.len as usize;
-        (t.kind, start..pos)
-    });
+    let mut iter = tokenize_with_text(&snip);
 
     // Search for the token sequence [`#`, `[`, `cfg`]
     while iter.any(|(t, _)| matches!(t, TokenKind::Pound)) {
@@ -1163,7 +1158,7 @@ fn span_contains_cfg(cx: &LateContext<'_>, s: Span) -> bool {
             )
         });
         if matches!(iter.next(), Some((TokenKind::OpenBracket, _)))
-            && matches!(iter.next(), Some((TokenKind::Ident, range)) if &snip[range.clone()] == "cfg")
+            && matches!(iter.next(), Some((TokenKind::Ident, "cfg")))
         {
             return true;
         }
diff --git a/src/tools/clippy/clippy_lints/src/matches/overlapping_arms.rs b/src/tools/clippy/clippy_lints/src/matches/overlapping_arms.rs
index ae69ca8a339..abf2525a61c 100644
--- a/src/tools/clippy/clippy_lints/src/matches/overlapping_arms.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/overlapping_arms.rs
@@ -34,7 +34,7 @@ fn all_ranges<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'_>], ty: Ty<'tcx>)
             if let Arm { pat, guard: None, .. } = *arm {
                 if let PatKind::Range(ref lhs, ref rhs, range_end) = pat.kind {
                     let lhs_const = match lhs {
-                        Some(lhs) => constant(cx, cx.typeck_results(), lhs)?.0,
+                        Some(lhs) => constant(cx, cx.typeck_results(), lhs)?,
                         None => {
                             let min_val_const = ty.numeric_min_val(cx.tcx)?;
                             let min_constant = mir::ConstantKind::from_value(
@@ -45,7 +45,7 @@ fn all_ranges<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'_>], ty: Ty<'tcx>)
                         },
                     };
                     let rhs_const = match rhs {
-                        Some(rhs) => constant(cx, cx.typeck_results(), rhs)?.0,
+                        Some(rhs) => constant(cx, cx.typeck_results(), rhs)?,
                         None => {
                             let max_val_const = ty.numeric_max_val(cx.tcx)?;
                             let max_constant = mir::ConstantKind::from_value(
diff --git a/src/tools/clippy/clippy_lints/src/matches/redundant_pattern_match.rs b/src/tools/clippy/clippy_lints/src/matches/redundant_pattern_match.rs
index af121f317cd..e81e09da425 100644
--- a/src/tools/clippy/clippy_lints/src/matches/redundant_pattern_match.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/redundant_pattern_match.rs
@@ -189,73 +189,7 @@ pub(super) fn check_match<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, op
     if arms.len() == 2 {
         let node_pair = (&arms[0].pat.kind, &arms[1].pat.kind);
 
-        let found_good_method = match node_pair {
-            (
-                PatKind::TupleStruct(ref path_left, patterns_left, _),
-                PatKind::TupleStruct(ref path_right, patterns_right, _),
-            ) if patterns_left.len() == 1 && patterns_right.len() == 1 => {
-                if let (PatKind::Wild, PatKind::Wild) = (&patterns_left[0].kind, &patterns_right[0].kind) {
-                    find_good_method_for_match(
-                        cx,
-                        arms,
-                        path_left,
-                        path_right,
-                        Item::Lang(ResultOk),
-                        Item::Lang(ResultErr),
-                        "is_ok()",
-                        "is_err()",
-                    )
-                    .or_else(|| {
-                        find_good_method_for_match(
-                            cx,
-                            arms,
-                            path_left,
-                            path_right,
-                            Item::Diag(sym::IpAddr, sym!(V4)),
-                            Item::Diag(sym::IpAddr, sym!(V6)),
-                            "is_ipv4()",
-                            "is_ipv6()",
-                        )
-                    })
-                } else {
-                    None
-                }
-            },
-            (PatKind::TupleStruct(ref path_left, patterns, _), PatKind::Path(ref path_right))
-            | (PatKind::Path(ref path_left), PatKind::TupleStruct(ref path_right, patterns, _))
-                if patterns.len() == 1 =>
-            {
-                if let PatKind::Wild = patterns[0].kind {
-                    find_good_method_for_match(
-                        cx,
-                        arms,
-                        path_left,
-                        path_right,
-                        Item::Lang(OptionSome),
-                        Item::Lang(OptionNone),
-                        "is_some()",
-                        "is_none()",
-                    )
-                    .or_else(|| {
-                        find_good_method_for_match(
-                            cx,
-                            arms,
-                            path_left,
-                            path_right,
-                            Item::Lang(PollReady),
-                            Item::Lang(PollPending),
-                            "is_ready()",
-                            "is_pending()",
-                        )
-                    })
-                } else {
-                    None
-                }
-            },
-            _ => None,
-        };
-
-        if let Some(good_method) = found_good_method {
+        if let Some(good_method) = found_good_method(cx, arms, node_pair) {
             let span = expr.span.to(op.span);
             let result_expr = match &op.kind {
                 ExprKind::AddrOf(_, _, borrowed) => borrowed,
@@ -279,6 +213,127 @@ pub(super) fn check_match<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, op
     }
 }
 
+fn found_good_method<'a>(
+    cx: &LateContext<'_>,
+    arms: &[Arm<'_>],
+    node: (&PatKind<'_>, &PatKind<'_>),
+) -> Option<&'a str> {
+    match node {
+        (
+            PatKind::TupleStruct(ref path_left, patterns_left, _),
+            PatKind::TupleStruct(ref path_right, patterns_right, _),
+        ) if patterns_left.len() == 1 && patterns_right.len() == 1 => {
+            if let (PatKind::Wild, PatKind::Wild) = (&patterns_left[0].kind, &patterns_right[0].kind) {
+                find_good_method_for_match(
+                    cx,
+                    arms,
+                    path_left,
+                    path_right,
+                    Item::Lang(ResultOk),
+                    Item::Lang(ResultErr),
+                    "is_ok()",
+                    "is_err()",
+                )
+                .or_else(|| {
+                    find_good_method_for_match(
+                        cx,
+                        arms,
+                        path_left,
+                        path_right,
+                        Item::Diag(sym::IpAddr, sym!(V4)),
+                        Item::Diag(sym::IpAddr, sym!(V6)),
+                        "is_ipv4()",
+                        "is_ipv6()",
+                    )
+                })
+            } else {
+                None
+            }
+        },
+        (PatKind::TupleStruct(ref path_left, patterns, _), PatKind::Path(ref path_right))
+        | (PatKind::Path(ref path_left), PatKind::TupleStruct(ref path_right, patterns, _))
+            if patterns.len() == 1 =>
+        {
+            if let PatKind::Wild = patterns[0].kind {
+                find_good_method_for_match(
+                    cx,
+                    arms,
+                    path_left,
+                    path_right,
+                    Item::Lang(OptionSome),
+                    Item::Lang(OptionNone),
+                    "is_some()",
+                    "is_none()",
+                )
+                .or_else(|| {
+                    find_good_method_for_match(
+                        cx,
+                        arms,
+                        path_left,
+                        path_right,
+                        Item::Lang(PollReady),
+                        Item::Lang(PollPending),
+                        "is_ready()",
+                        "is_pending()",
+                    )
+                })
+            } else {
+                None
+            }
+        },
+        (PatKind::TupleStruct(ref path_left, patterns, _), PatKind::Wild) if patterns.len() == 1 => {
+            if let PatKind::Wild = patterns[0].kind {
+                get_good_method(cx, arms, path_left)
+            } else {
+                None
+            }
+        },
+        (PatKind::Path(ref path_left), PatKind::Wild) => get_good_method(cx, arms, path_left),
+        _ => None,
+    }
+}
+
+fn get_ident(path: &QPath<'_>) -> Option<rustc_span::symbol::Ident> {
+    match path {
+        QPath::Resolved(_, path) => {
+            let name = path.segments[0].ident;
+            Some(name)
+        },
+        _ => None,
+    }
+}
+
+fn get_good_method<'a>(cx: &LateContext<'_>, arms: &[Arm<'_>], path_left: &QPath<'_>) -> Option<&'a str> {
+    if let Some(name) = get_ident(path_left) {
+        return match name.as_str() {
+            "Ok" => {
+                find_good_method_for_matches_macro(cx, arms, path_left, Item::Lang(ResultOk), "is_ok()", "is_err()")
+            },
+            "Err" => {
+                find_good_method_for_matches_macro(cx, arms, path_left, Item::Lang(ResultErr), "is_err()", "is_ok()")
+            },
+            "Some" => find_good_method_for_matches_macro(
+                cx,
+                arms,
+                path_left,
+                Item::Lang(OptionSome),
+                "is_some()",
+                "is_none()",
+            ),
+            "None" => find_good_method_for_matches_macro(
+                cx,
+                arms,
+                path_left,
+                Item::Lang(OptionNone),
+                "is_none()",
+                "is_some()",
+            ),
+            _ => None,
+        };
+    }
+    None
+}
+
 #[derive(Clone, Copy)]
 enum Item {
     Lang(LangItem),
@@ -289,10 +344,11 @@ fn is_pat_variant(cx: &LateContext<'_>, pat: &Pat<'_>, path: &QPath<'_>, expecte
     let Some(id) = cx.typeck_results().qpath_res(path, pat.hir_id).opt_def_id() else { return false };
 
     match expected_item {
-        Item::Lang(expected_lang_item) => {
-            let expected_id = cx.tcx.lang_items().require(expected_lang_item).unwrap();
-            cx.tcx.parent(id) == expected_id
-        },
+        Item::Lang(expected_lang_item) => cx
+            .tcx
+            .lang_items()
+            .get(expected_lang_item)
+            .map_or(false, |expected_id| cx.tcx.parent(id) == expected_id),
         Item::Diag(expected_ty, expected_variant) => {
             let ty = cx.typeck_results().pat_ty(pat);
 
@@ -345,3 +401,29 @@ fn find_good_method_for_match<'a>(
         _ => None,
     }
 }
+
+fn find_good_method_for_matches_macro<'a>(
+    cx: &LateContext<'_>,
+    arms: &[Arm<'_>],
+    path_left: &QPath<'_>,
+    expected_item_left: Item,
+    should_be_left: &'a str,
+    should_be_right: &'a str,
+) -> Option<&'a str> {
+    let first_pat = arms[0].pat;
+
+    let body_node_pair = if is_pat_variant(cx, first_pat, path_left, expected_item_left) {
+        (&arms[0].body.kind, &arms[1].body.kind)
+    } else {
+        return None;
+    };
+
+    match body_node_pair {
+        (ExprKind::Lit(lit_left), ExprKind::Lit(lit_right)) => match (&lit_left.node, &lit_right.node) {
+            (LitKind::Bool(true), LitKind::Bool(false)) => Some(should_be_left),
+            (LitKind::Bool(false), LitKind::Bool(true)) => Some(should_be_right),
+            _ => None,
+        },
+        _ => None,
+    }
+}
diff --git a/src/tools/clippy/clippy_lints/src/methods/iter_nth_zero.rs b/src/tools/clippy/clippy_lints/src/methods/iter_nth_zero.rs
index c830958d5c8..d1609eebfdc 100644
--- a/src/tools/clippy/clippy_lints/src/methods/iter_nth_zero.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/iter_nth_zero.rs
@@ -13,7 +13,7 @@ use super::ITER_NTH_ZERO;
 pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, recv: &hir::Expr<'_>, arg: &hir::Expr<'_>) {
     if_chain! {
         if is_trait_method(cx, expr, sym::Iterator);
-        if let Some((Constant::Int(0), _)) = constant(cx, cx.typeck_results(), arg);
+        if let Some(Constant::Int(0)) = constant(cx, cx.typeck_results(), arg);
         then {
             let mut applicability = Applicability::MachineApplicable;
             span_lint_and_sugg(
diff --git a/src/tools/clippy/clippy_lints/src/methods/iterator_step_by_zero.rs b/src/tools/clippy/clippy_lints/src/methods/iterator_step_by_zero.rs
index 64c09214a76..b631cd00cda 100644
--- a/src/tools/clippy/clippy_lints/src/methods/iterator_step_by_zero.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/iterator_step_by_zero.rs
@@ -9,7 +9,7 @@ use super::ITERATOR_STEP_BY_ZERO;
 
 pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &hir::Expr<'_>, arg: &'tcx hir::Expr<'_>) {
     if is_trait_method(cx, expr, sym::Iterator) {
-        if let Some((Constant::Int(0), _)) = constant(cx, cx.typeck_results(), arg) {
+        if let Some(Constant::Int(0)) = constant(cx, cx.typeck_results(), arg) {
             span_lint(
                 cx,
                 ITERATOR_STEP_BY_ZERO,
diff --git a/src/tools/clippy/clippy_lints/src/methods/manual_next_back.rs b/src/tools/clippy/clippy_lints/src/methods/manual_next_back.rs
new file mode 100644
index 00000000000..5f3fec53827
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/methods/manual_next_back.rs
@@ -0,0 +1,38 @@
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::is_trait_method;
+use clippy_utils::ty::implements_trait;
+use rustc_errors::Applicability;
+use rustc_hir::Expr;
+use rustc_lint::LateContext;
+use rustc_span::symbol::sym;
+
+pub(super) fn check<'tcx>(
+    cx: &LateContext<'tcx>,
+    expr: &'tcx Expr<'_>,
+    rev_call: &'tcx Expr<'_>,
+    rev_recv: &'tcx Expr<'_>,
+) {
+    let rev_recv_ty = cx.typeck_results().expr_ty(rev_recv);
+
+    // check that the receiver of `rev` implements `DoubleEndedIterator` and
+    // that `rev` and `next` come from `Iterator`
+    if cx
+        .tcx
+        .get_diagnostic_item(sym::DoubleEndedIterator)
+        .map_or(false, |double_ended_iterator| {
+            implements_trait(cx, rev_recv_ty, double_ended_iterator, &[])
+        })
+        && is_trait_method(cx, rev_call, sym::Iterator)
+        && is_trait_method(cx, expr, sym::Iterator)
+    {
+        span_lint_and_sugg(
+            cx,
+            super::MANUAL_NEXT_BACK,
+            expr.span.with_lo(rev_recv.span.hi()),
+            "manual backwards iteration",
+            "use",
+            String::from(".next_back()"),
+            Applicability::MachineApplicable,
+        );
+    }
+}
diff --git a/src/tools/clippy/clippy_lints/src/methods/mod.rs b/src/tools/clippy/clippy_lints/src/methods/mod.rs
index 06b88e34d24..9a594d964ab 100644
--- a/src/tools/clippy/clippy_lints/src/methods/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/mod.rs
@@ -45,6 +45,7 @@ mod iter_overeager_cloned;
 mod iter_skip_next;
 mod iter_with_drain;
 mod iterator_step_by_zero;
+mod manual_next_back;
 mod manual_ok_or;
 mod manual_saturating_arithmetic;
 mod manual_str_repeat;
@@ -3132,8 +3133,11 @@ declare_clippy_lint! {
     /// ### Example
     /// ```rust
     /// # let iterator = vec![1].into_iter();
-    /// let len = iterator.clone().collect::<Vec<_>>().len();
-    /// // should be
+    /// let len = iterator.collect::<Vec<_>>().len();
+    /// ```
+    /// Use instead:
+    /// ```rust
+    /// # let iterator = vec![1].into_iter();
     /// let len = iterator.count();
     /// ```
     #[clippy::version = "1.30.0"]
@@ -3193,6 +3197,29 @@ declare_clippy_lint! {
     "calling `drain` in order to `clear` a container"
 }
 
+declare_clippy_lint! {
+    /// ### What it does
+    /// Checks for `.rev().next()` on a `DoubleEndedIterator`
+    ///
+    /// ### Why is this bad?
+    /// `.next_back()` is cleaner.
+    ///
+    /// ### Example
+    /// ```rust
+    /// # let foo = [0; 10];
+    /// foo.iter().rev().next();
+    /// ```
+    /// Use instead:
+    /// ```rust
+    /// # let foo = [0; 10];
+    /// foo.iter().next_back();
+    /// ```
+    #[clippy::version = "1.71.0"]
+    pub MANUAL_NEXT_BACK,
+    style,
+    "manual reverse iteration of `DoubleEndedIterator`"
+}
+
 pub struct Methods {
     avoid_breaking_exported_api: bool,
     msrv: Msrv,
@@ -3321,6 +3348,7 @@ impl_lint_pass!(Methods => [
     NEEDLESS_COLLECT,
     SUSPICIOUS_COMMAND_ARG_SPACE,
     CLEAR_WITH_DRAIN,
+    MANUAL_NEXT_BACK,
 ]);
 
 /// Extracts a method call name, args, and `Span` of the method name.
@@ -3677,6 +3705,7 @@ impl Methods {
                             ("iter", []) => iter_next_slice::check(cx, expr, recv2),
                             ("skip", [arg]) => iter_skip_next::check(cx, expr, recv2, arg),
                             ("skip_while", [_]) => skip_while_next::check(cx, expr),
+                            ("rev", [])=> manual_next_back::check(cx, expr, recv, recv2),
                             _ => {},
                         }
                     }
@@ -3741,13 +3770,13 @@ impl Methods {
                     unnecessary_sort_by::check(cx, expr, recv, arg, true);
                 },
                 ("splitn" | "rsplitn", [count_arg, pat_arg]) => {
-                    if let Some((Constant::Int(count), _)) = constant(cx, cx.typeck_results(), count_arg) {
+                    if let Some(Constant::Int(count)) = constant(cx, cx.typeck_results(), count_arg) {
                         suspicious_splitn::check(cx, name, expr, recv, count);
                         str_splitn::check(cx, name, expr, recv, pat_arg, count, &self.msrv);
                     }
                 },
                 ("splitn_mut" | "rsplitn_mut", [count_arg, _]) => {
-                    if let Some((Constant::Int(count), _)) = constant(cx, cx.typeck_results(), count_arg) {
+                    if let Some(Constant::Int(count)) = constant(cx, cx.typeck_results(), count_arg) {
                         suspicious_splitn::check(cx, name, expr, recv, count);
                     }
                 },
diff --git a/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs b/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs
index 0b0c6adc504..6841aaf626c 100644
--- a/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs
@@ -1,6 +1,5 @@
 use super::NEEDLESS_COLLECT;
 use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_hir_and_then};
-use clippy_utils::higher;
 use clippy_utils::source::{snippet, snippet_with_applicability};
 use clippy_utils::sugg::Sugg;
 use clippy_utils::ty::{is_type_diagnostic_item, make_normalized_projection, make_projection};
@@ -8,6 +7,7 @@ use clippy_utils::{
     can_move_expr_to_closure, get_enclosing_block, get_parent_node, is_trait_method, path_to_local, path_to_local_id,
     CaptureKind,
 };
+use clippy_utils::{fn_def_id, higher};
 use rustc_data_structures::fx::FxHashMap;
 use rustc_errors::{Applicability, MultiSpan};
 use rustc_hir::intravisit::{walk_block, walk_expr, Visitor};
@@ -16,7 +16,7 @@ use rustc_hir::{
 };
 use rustc_lint::LateContext;
 use rustc_middle::hir::nested_filter;
-use rustc_middle::ty::{self, AssocKind, EarlyBinder, GenericArg, GenericArgKind, Ty};
+use rustc_middle::ty::{self, AssocKind, Clause, EarlyBinder, GenericArg, GenericArgKind, PredicateKind, Ty};
 use rustc_span::symbol::Ident;
 use rustc_span::{sym, Span, Symbol};
 
@@ -32,6 +32,8 @@ pub(super) fn check<'tcx>(
     if let Some(parent) = get_parent_node(cx.tcx, collect_expr.hir_id) {
         match parent {
             Node::Expr(parent) => {
+                check_collect_into_intoiterator(cx, parent, collect_expr, call_span, iter_expr);
+
                 if let ExprKind::MethodCall(name, _, args @ ([] | [_]), _) = parent.kind {
                     let mut app = Applicability::MachineApplicable;
                     let name = name.ident.as_str();
@@ -134,6 +136,68 @@ pub(super) fn check<'tcx>(
     }
 }
 
+/// checks for for collecting into a (generic) method or function argument
+/// taking an `IntoIterator`
+fn check_collect_into_intoiterator<'tcx>(
+    cx: &LateContext<'tcx>,
+    parent: &'tcx Expr<'tcx>,
+    collect_expr: &'tcx Expr<'tcx>,
+    call_span: Span,
+    iter_expr: &'tcx Expr<'tcx>,
+) {
+    if let Some(id) = fn_def_id(cx, parent) {
+        let args = match parent.kind {
+            ExprKind::Call(_, args) | ExprKind::MethodCall(_, _, args, _) => args,
+            _ => &[],
+        };
+        // find the argument index of the `collect_expr` in the
+        // function / method call
+        if let Some(arg_idx) = args.iter().position(|e| e.hir_id == collect_expr.hir_id).map(|i| {
+            if matches!(parent.kind, ExprKind::MethodCall(_, _, _, _)) {
+                i + 1
+            } else {
+                i
+            }
+        }) {
+            // extract the input types of the function/method call
+            // that contains `collect_expr`
+            let inputs = cx
+                .tcx
+                .liberate_late_bound_regions(id, cx.tcx.fn_sig(id).subst_identity())
+                .inputs();
+
+            // map IntoIterator generic bounds to their signature
+            // types and check whether the argument type is an
+            // `IntoIterator`
+            if cx
+                .tcx
+                .param_env(id)
+                .caller_bounds()
+                .into_iter()
+                .filter_map(|p| {
+                    if let PredicateKind::Clause(Clause::Trait(t)) = p.kind().skip_binder()
+                            && cx.tcx.is_diagnostic_item(sym::IntoIterator,t.trait_ref.def_id) {
+                                Some(t.self_ty())
+                            } else {
+                                None
+                            }
+                })
+                .any(|ty| ty == inputs[arg_idx])
+            {
+                span_lint_and_sugg(
+                    cx,
+                    NEEDLESS_COLLECT,
+                    call_span.with_lo(iter_expr.span.hi()),
+                    NEEDLESS_COLLECT_MSG,
+                    "remove this call",
+                    String::new(),
+                    Applicability::MachineApplicable,
+                );
+            }
+        }
+    }
+}
+
 /// Checks if the given method call matches the expected signature of `([&[mut]] self) -> bool`
 fn is_is_empty_sig(cx: &LateContext<'_>, call_id: HirId) -> bool {
     cx.typeck_results().type_dependent_def_id(call_id).map_or(false, |id| {
diff --git a/src/tools/clippy/clippy_lints/src/methods/repeat_once.rs b/src/tools/clippy/clippy_lints/src/methods/repeat_once.rs
index a345ec813ff..bb4cdd2a6fa 100644
--- a/src/tools/clippy/clippy_lints/src/methods/repeat_once.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/repeat_once.rs
@@ -1,4 +1,4 @@
-use clippy_utils::consts::{constant_context, Constant};
+use clippy_utils::consts::{constant, Constant};
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::source::snippet;
 use clippy_utils::ty::is_type_lang_item;
@@ -14,7 +14,7 @@ pub(super) fn check<'tcx>(
     recv: &'tcx Expr<'_>,
     repeat_arg: &'tcx Expr<'_>,
 ) {
-    if constant_context(cx, cx.typeck_results()).expr(repeat_arg) == Some(Constant::Int(1)) {
+    if constant(cx, cx.typeck_results(), repeat_arg) == Some(Constant::Int(1)) {
         let ty = cx.typeck_results().expr_ty(recv).peel_refs();
         if ty.is_str() {
             span_lint_and_sugg(
diff --git a/src/tools/clippy/clippy_lints/src/methods/str_splitn.rs b/src/tools/clippy/clippy_lints/src/methods/str_splitn.rs
index 91f7ce1dbe5..5ea12c44184 100644
--- a/src/tools/clippy/clippy_lints/src/methods/str_splitn.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/str_splitn.rs
@@ -316,7 +316,7 @@ fn parse_iter_usage<'tcx>(
                     };
                 },
                 ("nth" | "skip", [idx_expr]) if cx.tcx.trait_of_item(did) == Some(iter_id) => {
-                    if let Some((Constant::Int(idx), _)) = constant(cx, cx.typeck_results(), idx_expr) {
+                    if let Some(Constant::Int(idx)) = constant(cx, cx.typeck_results(), idx_expr) {
                         let span = if name.ident.as_str() == "nth" {
                             e.span
                         } else {
diff --git a/src/tools/clippy/clippy_lints/src/misc.rs b/src/tools/clippy/clippy_lints/src/misc.rs
index 3752b9a946f..303f0125690 100644
--- a/src/tools/clippy/clippy_lints/src/misc.rs
+++ b/src/tools/clippy/clippy_lints/src/misc.rs
@@ -16,9 +16,12 @@ use rustc_span::source_map::{ExpnKind, Span};
 
 use clippy_utils::sugg::Sugg;
 use clippy_utils::{
-    get_parent_expr, in_constant, is_integer_literal, is_no_std_crate, iter_input_pats, last_path_segment, SpanlessEq,
+    get_parent_expr, in_constant, is_integer_literal, is_lint_allowed, is_no_std_crate, iter_input_pats,
+    last_path_segment, SpanlessEq,
 };
 
+use crate::ref_patterns::REF_PATTERNS;
+
 declare_clippy_lint! {
     /// ### What it does
     /// Checks for function arguments and let bindings denoted as
@@ -162,6 +165,10 @@ impl<'tcx> LateLintPass<'tcx> for LintPass {
             return;
         }
         for arg in iter_input_pats(decl, body) {
+            // Do not emit if clippy::ref_patterns is not allowed to avoid having two lints for the same issue.
+            if !is_lint_allowed(cx, REF_PATTERNS, arg.pat.hir_id) {
+                return;
+            }
             if let PatKind::Binding(BindingAnnotation(ByRef::Yes, _), ..) = arg.pat.kind {
                 span_lint(
                     cx,
@@ -180,6 +187,8 @@ impl<'tcx> LateLintPass<'tcx> for LintPass {
             if let StmtKind::Local(local) = stmt.kind;
             if let PatKind::Binding(BindingAnnotation(ByRef::Yes, mutabl), .., name, None) = local.pat.kind;
             if let Some(init) = local.init;
+            // Do not emit if clippy::ref_patterns is not allowed to avoid having two lints for the same issue.
+            if is_lint_allowed(cx, REF_PATTERNS, local.pat.hir_id);
             then {
                 let ctxt = local.span.ctxt();
                 let mut app = Applicability::MachineApplicable;
diff --git a/src/tools/clippy/clippy_lints/src/needless_bool.rs b/src/tools/clippy/clippy_lints/src/needless_bool.rs
index 71281a0b40b..62af42a3961 100644
--- a/src/tools/clippy/clippy_lints/src/needless_bool.rs
+++ b/src/tools/clippy/clippy_lints/src/needless_bool.rs
@@ -146,7 +146,7 @@ fn is_parent_stmt(cx: &LateContext<'_>, id: HirId) -> bool {
 impl<'tcx> LateLintPass<'tcx> for NeedlessBool {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) {
         use self::Expression::{Bool, RetBool};
-        if e.span.from_expansion() {
+        if e.span.from_expansion() || !span_extract_comment(cx.tcx.sess.source_map(), e.span).is_empty() {
             return;
         }
         if let Some(higher::If {
@@ -209,8 +209,7 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessBool {
             }
             if let Some((lhs_a, a)) = fetch_assign(then) &&
                 let Some((lhs_b, b)) = fetch_assign(r#else) &&
-                SpanlessEq::new(cx).eq_expr(lhs_a, lhs_b) &&
-                span_extract_comment(cx.tcx.sess.source_map(), e.span).is_empty()
+                SpanlessEq::new(cx).eq_expr(lhs_a, lhs_b)
             {
                 let mut applicability = Applicability::MachineApplicable;
                 let cond = Sugg::hir_with_applicability(cx, cond, "..", &mut applicability);
diff --git a/src/tools/clippy/clippy_lints/src/operators/absurd_extreme_comparisons.rs b/src/tools/clippy/clippy_lints/src/operators/absurd_extreme_comparisons.rs
index d29ca37eaeb..f4863600ccc 100644
--- a/src/tools/clippy/clippy_lints/src/operators/absurd_extreme_comparisons.rs
+++ b/src/tools/clippy/clippy_lints/src/operators/absurd_extreme_comparisons.rs
@@ -121,7 +121,7 @@ fn detect_absurd_comparison<'tcx>(
 fn detect_extreme_expr<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option<ExtremeExpr<'tcx>> {
     let ty = cx.typeck_results().expr_ty(expr);
 
-    let cv = constant(cx, cx.typeck_results(), expr)?.0;
+    let cv = constant(cx, cx.typeck_results(), expr)?;
 
     let which = match (ty.kind(), cv) {
         (&ty::Bool, Constant::Bool(false)) | (&ty::Uint(_), Constant::Int(0)) => ExtremeType::Minimum,
diff --git a/src/tools/clippy/clippy_lints/src/operators/arithmetic_side_effects.rs b/src/tools/clippy/clippy_lints/src/operators/arithmetic_side_effects.rs
index f72595987ee..5c240276b76 100644
--- a/src/tools/clippy/clippy_lints/src/operators/arithmetic_side_effects.rs
+++ b/src/tools/clippy/clippy_lints/src/operators/arithmetic_side_effects.rs
@@ -21,7 +21,7 @@ const HARD_CODED_ALLOWED_BINARY: &[[&str; 2]] = &[
     ["f64", "f64"],
     ["std::num::Saturating", "std::num::Saturating"],
     ["std::num::Wrapping", "std::num::Wrapping"],
-    ["std::string::String", "&str"],
+    ["std::string::String", "str"],
 ];
 const HARD_CODED_ALLOWED_UNARY: &[&str] = &["f32", "f64", "std::num::Saturating", "std::num::Wrapping"];
 const INTEGER_METHODS: &[&str] = &["saturating_div", "wrapping_div", "wrapping_rem", "wrapping_rem_euclid"];
@@ -113,7 +113,7 @@ impl ArithmeticSideEffects {
         if let hir::ExprKind::Lit(lit) = actual.kind && let ast::LitKind::Int(n, _) = lit.node {
             return Some(n)
         }
-        if let Some((Constant::Int(n), _)) = constant(cx, cx.typeck_results(), expr) {
+        if let Some(Constant::Int(n)) = constant(cx, cx.typeck_results(), expr) {
             return Some(n);
         }
         None
@@ -144,8 +144,10 @@ impl ArithmeticSideEffects {
         ) {
             return;
         };
-        let lhs_ty = cx.typeck_results().expr_ty(lhs);
-        let rhs_ty = cx.typeck_results().expr_ty(rhs);
+        let (actual_lhs, lhs_ref_counter) = peel_hir_expr_refs(lhs);
+        let (actual_rhs, rhs_ref_counter) = peel_hir_expr_refs(rhs);
+        let lhs_ty = cx.typeck_results().expr_ty(actual_lhs).peel_refs();
+        let rhs_ty = cx.typeck_results().expr_ty(actual_rhs).peel_refs();
         if self.has_allowed_binary(lhs_ty, rhs_ty) {
             return;
         }
@@ -154,8 +156,6 @@ impl ArithmeticSideEffects {
                 // At least for integers, shifts are already handled by the CTFE
                 return;
             }
-            let (actual_lhs, lhs_ref_counter) = peel_hir_expr_refs(lhs);
-            let (actual_rhs, rhs_ref_counter) = peel_hir_expr_refs(rhs);
             match (
                 Self::literal_integer(cx, actual_lhs),
                 Self::literal_integer(cx, actual_rhs),
diff --git a/src/tools/clippy/clippy_lints/src/operators/bit_mask.rs b/src/tools/clippy/clippy_lints/src/operators/bit_mask.rs
index 1369b3e7462..1fddf0f50e3 100644
--- a/src/tools/clippy/clippy_lints/src/operators/bit_mask.rs
+++ b/src/tools/clippy/clippy_lints/src/operators/bit_mask.rs
@@ -166,7 +166,7 @@ fn check_ineffective_gt(cx: &LateContext<'_>, span: Span, m: u128, c: u128, op:
 }
 
 fn fetch_int_literal(cx: &LateContext<'_>, lit: &Expr<'_>) -> Option<u128> {
-    match constant(cx, cx.typeck_results(), lit)?.0 {
+    match constant(cx, cx.typeck_results(), lit)? {
         Constant::Int(n) => Some(n),
         _ => None,
     }
diff --git a/src/tools/clippy/clippy_lints/src/operators/cmp_nan.rs b/src/tools/clippy/clippy_lints/src/operators/cmp_nan.rs
index 786ae1552ad..e18064b7061 100644
--- a/src/tools/clippy/clippy_lints/src/operators/cmp_nan.rs
+++ b/src/tools/clippy/clippy_lints/src/operators/cmp_nan.rs
@@ -18,7 +18,7 @@ pub(super) fn check(cx: &LateContext<'_>, e: &Expr<'_>, op: BinOpKind, lhs: &Exp
 }
 
 fn is_nan(cx: &LateContext<'_>, e: &Expr<'_>) -> bool {
-    if let Some((value, _)) = constant(cx, cx.typeck_results(), e) {
+    if let Some(value) = constant(cx, cx.typeck_results(), e) {
         match value {
             Constant::F32(num) => num.is_nan(),
             Constant::F64(num) => num.is_nan(),
diff --git a/src/tools/clippy/clippy_lints/src/operators/duration_subsec.rs b/src/tools/clippy/clippy_lints/src/operators/duration_subsec.rs
index 49e662cacb0..f120be13836 100644
--- a/src/tools/clippy/clippy_lints/src/operators/duration_subsec.rs
+++ b/src/tools/clippy/clippy_lints/src/operators/duration_subsec.rs
@@ -19,7 +19,7 @@ pub(crate) fn check<'tcx>(
     if op == BinOpKind::Div
         && let ExprKind::MethodCall(method_path, self_arg, [], _) = left.kind
         && is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(self_arg).peel_refs(), sym::Duration)
-        && let Some((Constant::Int(divisor), _)) = constant(cx, cx.typeck_results(), right)
+        && let Some(Constant::Int(divisor)) = constant(cx, cx.typeck_results(), right)
     {
         let suggested_fn = match (method_path.ident.as_str(), divisor) {
             ("subsec_micros", 1_000) | ("subsec_nanos", 1_000_000) => "subsec_millis",
diff --git a/src/tools/clippy/clippy_lints/src/operators/float_cmp.rs b/src/tools/clippy/clippy_lints/src/operators/float_cmp.rs
index 97ddcdb2479..15dff126be7 100644
--- a/src/tools/clippy/clippy_lints/src/operators/float_cmp.rs
+++ b/src/tools/clippy/clippy_lints/src/operators/float_cmp.rs
@@ -1,4 +1,4 @@
-use clippy_utils::consts::{constant, Constant};
+use clippy_utils::consts::{constant_with_source, Constant};
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::get_item_name;
 use clippy_utils::sugg::Sugg;
@@ -18,9 +18,16 @@ pub(crate) fn check<'tcx>(
     right: &'tcx Expr<'_>,
 ) {
     if (op == BinOpKind::Eq || op == BinOpKind::Ne) && (is_float(cx, left) || is_float(cx, right)) {
-        if is_allowed(cx, left) || is_allowed(cx, right) {
-            return;
-        }
+        let left_is_local = match constant_with_source(cx, cx.typeck_results(), left) {
+            Some((c, s)) if !is_allowed(&c) => s.is_local(),
+            Some(_) => return,
+            None => true,
+        };
+        let right_is_local = match constant_with_source(cx, cx.typeck_results(), right) {
+            Some((c, s)) if !is_allowed(&c) => s.is_local(),
+            Some(_) => return,
+            None => true,
+        };
 
         // Allow comparing the results of signum()
         if is_signum(cx, left) && is_signum(cx, right) {
@@ -34,10 +41,7 @@ pub(crate) fn check<'tcx>(
             }
         }
         let is_comparing_arrays = is_array(cx, left) || is_array(cx, right);
-        let (lint, msg) = get_lint_and_message(
-            is_named_constant(cx, left) || is_named_constant(cx, right),
-            is_comparing_arrays,
-        );
+        let (lint, msg) = get_lint_and_message(left_is_local && right_is_local, is_comparing_arrays);
         span_lint_and_then(cx, lint, expr.span, msg, |diag| {
             let lhs = Sugg::hir(cx, left, "..");
             let rhs = Sugg::hir(cx, right, "..");
@@ -59,44 +63,33 @@ pub(crate) fn check<'tcx>(
     }
 }
 
-fn get_lint_and_message(
-    is_comparing_constants: bool,
-    is_comparing_arrays: bool,
-) -> (&'static rustc_lint::Lint, &'static str) {
-    if is_comparing_constants {
+fn get_lint_and_message(is_local: bool, is_comparing_arrays: bool) -> (&'static rustc_lint::Lint, &'static str) {
+    if is_local {
         (
-            FLOAT_CMP_CONST,
+            FLOAT_CMP,
             if is_comparing_arrays {
-                "strict comparison of `f32` or `f64` constant arrays"
+                "strict comparison of `f32` or `f64` arrays"
             } else {
-                "strict comparison of `f32` or `f64` constant"
+                "strict comparison of `f32` or `f64`"
             },
         )
     } else {
         (
-            FLOAT_CMP,
+            FLOAT_CMP_CONST,
             if is_comparing_arrays {
-                "strict comparison of `f32` or `f64` arrays"
+                "strict comparison of `f32` or `f64` constant arrays"
             } else {
-                "strict comparison of `f32` or `f64`"
+                "strict comparison of `f32` or `f64` constant"
             },
         )
     }
 }
 
-fn is_named_constant<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> bool {
-    if let Some((_, res)) = constant(cx, cx.typeck_results(), expr) {
-        res
-    } else {
-        false
-    }
-}
-
-fn is_allowed<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> bool {
-    match constant(cx, cx.typeck_results(), expr) {
-        Some((Constant::F32(f), _)) => f == 0.0 || f.is_infinite(),
-        Some((Constant::F64(f), _)) => f == 0.0 || f.is_infinite(),
-        Some((Constant::Vec(vec), _)) => vec.iter().all(|f| match f {
+fn is_allowed(val: &Constant) -> bool {
+    match val {
+        &Constant::F32(f) => f == 0.0 || f.is_infinite(),
+        &Constant::F64(f) => f == 0.0 || f.is_infinite(),
+        Constant::Vec(vec) => vec.iter().all(|f| match f {
             Constant::F32(f) => *f == 0.0 || (*f).is_infinite(),
             Constant::F64(f) => *f == 0.0 || (*f).is_infinite(),
             _ => false,
diff --git a/src/tools/clippy/clippy_lints/src/operators/mod.rs b/src/tools/clippy/clippy_lints/src/operators/mod.rs
index 19599731bd6..d63a836e73d 100644
--- a/src/tools/clippy/clippy_lints/src/operators/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/operators/mod.rs
@@ -98,32 +98,6 @@ declare_clippy_lint! {
 
 declare_clippy_lint! {
     /// ### What it does
-    /// Checks for integer arithmetic operations which could overflow or panic.
-    ///
-    /// Specifically, checks for any operators (`+`, `-`, `*`, `<<`, etc) which are capable
-    /// of overflowing according to the [Rust
-    /// Reference](https://doc.rust-lang.org/reference/expressions/operator-expr.html#overflow),
-    /// or which can panic (`/`, `%`). No bounds analysis or sophisticated reasoning is
-    /// attempted.
-    ///
-    /// ### Why is this bad?
-    /// Integer overflow will trigger a panic in debug builds or will wrap in
-    /// release mode. Division by zero will cause a panic in either mode. In some applications one
-    /// wants explicitly checked, wrapping or saturating arithmetic.
-    ///
-    /// ### Example
-    /// ```rust
-    /// # let a = 0;
-    /// a + 1;
-    /// ```
-    #[clippy::version = "pre 1.29.0"]
-    pub INTEGER_ARITHMETIC,
-    restriction,
-    "any integer arithmetic expression which could overflow or panic"
-}
-
-declare_clippy_lint! {
-    /// ### What it does
     /// Checks for float arithmetic.
     ///
     /// ### Why is this bad?
@@ -787,7 +761,6 @@ pub struct Operators {
 impl_lint_pass!(Operators => [
     ABSURD_EXTREME_COMPARISONS,
     ARITHMETIC_SIDE_EFFECTS,
-    INTEGER_ARITHMETIC,
     FLOAT_ARITHMETIC,
     ASSIGN_OP_PATTERN,
     MISREFACTORED_ASSIGN_OP,
diff --git a/src/tools/clippy/clippy_lints/src/operators/modulo_arithmetic.rs b/src/tools/clippy/clippy_lints/src/operators/modulo_arithmetic.rs
index af4e74947f4..a2c3a4d8ba7 100644
--- a/src/tools/clippy/clippy_lints/src/operators/modulo_arithmetic.rs
+++ b/src/tools/clippy/clippy_lints/src/operators/modulo_arithmetic.rs
@@ -40,7 +40,7 @@ struct OperandInfo {
 
 fn analyze_operand(operand: &Expr<'_>, cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<OperandInfo> {
     match constant(cx, cx.typeck_results(), operand) {
-        Some((Constant::Int(v), _)) => match *cx.typeck_results().expr_ty(expr).kind() {
+        Some(Constant::Int(v)) => match *cx.typeck_results().expr_ty(expr).kind() {
             ty::Int(ity) => {
                 let value = sext(cx.tcx, v, ity);
                 return Some(OperandInfo {
@@ -58,10 +58,10 @@ fn analyze_operand(operand: &Expr<'_>, cx: &LateContext<'_>, expr: &Expr<'_>) ->
             },
             _ => {},
         },
-        Some((Constant::F32(f), _)) => {
+        Some(Constant::F32(f)) => {
             return Some(floating_point_operand_info(&f));
         },
-        Some((Constant::F64(f), _)) => {
+        Some(Constant::F64(f)) => {
             return Some(floating_point_operand_info(&f));
         },
         _ => {},
diff --git a/src/tools/clippy/clippy_lints/src/operators/numeric_arithmetic.rs b/src/tools/clippy/clippy_lints/src/operators/numeric_arithmetic.rs
index 77fd45b199a..102845ceed0 100644
--- a/src/tools/clippy/clippy_lints/src/operators/numeric_arithmetic.rs
+++ b/src/tools/clippy/clippy_lints/src/operators/numeric_arithmetic.rs
@@ -1,8 +1,6 @@
-use super::{FLOAT_ARITHMETIC, INTEGER_ARITHMETIC};
+use super::FLOAT_ARITHMETIC;
 use clippy_utils::consts::constant_simple;
 use clippy_utils::diagnostics::span_lint;
-use clippy_utils::is_from_proc_macro;
-use clippy_utils::is_integer_literal;
 use rustc_hir as hir;
 use rustc_lint::LateContext;
 use rustc_span::source_map::Span;
@@ -45,31 +43,8 @@ impl Context {
             _ => (),
         }
 
-        let (l_ty, r_ty) = (cx.typeck_results().expr_ty(l), cx.typeck_results().expr_ty(r));
-        if l_ty.peel_refs().is_integral() && r_ty.peel_refs().is_integral() {
-            if is_from_proc_macro(cx, expr) {
-                return;
-            }
-            match op {
-                hir::BinOpKind::Div | hir::BinOpKind::Rem => match &r.kind {
-                    hir::ExprKind::Lit(_lit) => (),
-                    hir::ExprKind::Unary(hir::UnOp::Neg, expr) => {
-                        if is_integer_literal(expr, 1) {
-                            span_lint(cx, INTEGER_ARITHMETIC, expr.span, "integer arithmetic detected");
-                            self.expr_id = Some(expr.hir_id);
-                        }
-                    },
-                    _ => {
-                        span_lint(cx, INTEGER_ARITHMETIC, expr.span, "integer arithmetic detected");
-                        self.expr_id = Some(expr.hir_id);
-                    },
-                },
-                _ => {
-                    span_lint(cx, INTEGER_ARITHMETIC, expr.span, "integer arithmetic detected");
-                    self.expr_id = Some(expr.hir_id);
-                },
-            }
-        } else if r_ty.peel_refs().is_floating_point() && r_ty.peel_refs().is_floating_point() {
+        let (_, r_ty) = (cx.typeck_results().expr_ty(l), cx.typeck_results().expr_ty(r));
+        if r_ty.peel_refs().is_floating_point() && r_ty.peel_refs().is_floating_point() {
             span_lint(cx, FLOAT_ARITHMETIC, expr.span, "floating-point arithmetic detected");
             self.expr_id = Some(expr.hir_id);
         }
@@ -80,17 +55,9 @@ impl Context {
             return;
         }
         let ty = cx.typeck_results().expr_ty(arg);
-        if constant_simple(cx, cx.typeck_results(), expr).is_none() {
-            if ty.is_integral() {
-                if is_from_proc_macro(cx, expr) {
-                    return;
-                }
-                span_lint(cx, INTEGER_ARITHMETIC, expr.span, "integer arithmetic detected");
-                self.expr_id = Some(expr.hir_id);
-            } else if ty.is_floating_point() {
-                span_lint(cx, FLOAT_ARITHMETIC, expr.span, "floating-point arithmetic detected");
-                self.expr_id = Some(expr.hir_id);
-            }
+        if constant_simple(cx, cx.typeck_results(), expr).is_none() && ty.is_floating_point() {
+            span_lint(cx, FLOAT_ARITHMETIC, expr.span, "floating-point arithmetic detected");
+            self.expr_id = Some(expr.hir_id);
         }
     }
 
diff --git a/src/tools/clippy/clippy_lints/src/option_if_let_else.rs b/src/tools/clippy/clippy_lints/src/option_if_let_else.rs
index bbbcda069c5..aa6d4004268 100644
--- a/src/tools/clippy/clippy_lints/src/option_if_let_else.rs
+++ b/src/tools/clippy/clippy_lints/src/option_if_let_else.rs
@@ -122,7 +122,7 @@ fn try_get_option_occurrence<'tcx>(
         ExprKind::Unary(UnOp::Deref, inner_expr) | ExprKind::AddrOf(_, _, inner_expr) => inner_expr,
         _ => expr,
     };
-    let inner_pat = try_get_inner_pat(cx, pat)?;
+    let (inner_pat, is_result) = try_get_inner_pat_and_is_result(cx, pat)?;
     if_chain! {
         if let PatKind::Binding(bind_annotation, _, id, None) = inner_pat.kind;
         if let Some(some_captures) = can_move_expr_to_closure(cx, if_then);
@@ -176,7 +176,7 @@ fn try_get_option_occurrence<'tcx>(
                 ),
                 none_expr: format!(
                     "{}{}",
-                    if method_sugg == "map_or" { "" } else { "|| " },
+                    if method_sugg == "map_or" { "" } else if is_result { "|_| " } else { "|| "},
                     Sugg::hir_with_context(cx, none_body, ctxt, "..", &mut app),
                 ),
             });
@@ -186,11 +186,13 @@ fn try_get_option_occurrence<'tcx>(
     None
 }
 
-fn try_get_inner_pat<'tcx>(cx: &LateContext<'tcx>, pat: &Pat<'tcx>) -> Option<&'tcx Pat<'tcx>> {
+fn try_get_inner_pat_and_is_result<'tcx>(cx: &LateContext<'tcx>, pat: &Pat<'tcx>) -> Option<(&'tcx Pat<'tcx>, bool)> {
     if let PatKind::TupleStruct(ref qpath, [inner_pat], ..) = pat.kind {
         let res = cx.qpath_res(qpath, pat.hir_id);
-        if is_res_lang_ctor(cx, res, OptionSome) || is_res_lang_ctor(cx, res, ResultOk) {
-            return Some(inner_pat);
+        if is_res_lang_ctor(cx, res, OptionSome) {
+            return Some((inner_pat, false));
+        } else if is_res_lang_ctor(cx, res, ResultOk) {
+            return Some((inner_pat, true));
         }
     }
     None
diff --git a/src/tools/clippy/clippy_lints/src/ranges.rs b/src/tools/clippy/clippy_lints/src/ranges.rs
index fc655fe2d0b..dd7ded491e7 100644
--- a/src/tools/clippy/clippy_lints/src/ranges.rs
+++ b/src/tools/clippy/clippy_lints/src/ranges.rs
@@ -319,7 +319,7 @@ fn check_range_bounds<'a>(cx: &'a LateContext<'_>, ex: &'a Expr<'_>) -> Option<R
             _ => return None,
         };
         if let Some(id) = path_to_local(l) {
-            if let Some((c, _)) = constant(cx, cx.typeck_results(), r) {
+            if let Some(c) = constant(cx, cx.typeck_results(), r) {
                 return Some(RangeBounds {
                     val: c,
                     expr: r,
@@ -331,7 +331,7 @@ fn check_range_bounds<'a>(cx: &'a LateContext<'_>, ex: &'a Expr<'_>) -> Option<R
                 });
             }
         } else if let Some(id) = path_to_local(r) {
-            if let Some((c, _)) = constant(cx, cx.typeck_results(), l) {
+            if let Some(c) = constant(cx, cx.typeck_results(), l) {
                 return Some(RangeBounds {
                     val: c,
                     expr: l,
@@ -451,8 +451,8 @@ fn check_reversed_empty_range(cx: &LateContext<'_>, expr: &Expr<'_>) {
         if let Some(higher::Range { start: Some(start), end: Some(end), limits }) = higher::Range::hir(expr);
         let ty = cx.typeck_results().expr_ty(start);
         if let ty::Int(_) | ty::Uint(_) = ty.kind();
-        if let Some((start_idx, _)) = constant(cx, cx.typeck_results(), start);
-        if let Some((end_idx, _)) = constant(cx, cx.typeck_results(), end);
+        if let Some(start_idx) = constant(cx, cx.typeck_results(), start);
+        if let Some(end_idx) = constant(cx, cx.typeck_results(), end);
         if let Some(ordering) = Constant::partial_cmp(cx.tcx, ty, &start_idx, &end_idx);
         if is_empty_range(limits, ordering);
         then {
diff --git a/src/tools/clippy/clippy_lints/src/ref_patterns.rs b/src/tools/clippy/clippy_lints/src/ref_patterns.rs
new file mode 100644
index 00000000000..b1530eed1c1
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/ref_patterns.rs
@@ -0,0 +1,44 @@
+use clippy_utils::diagnostics::span_lint_and_help;
+use rustc_ast::ast::{BindingAnnotation, Pat, PatKind};
+use rustc_lint::{EarlyContext, EarlyLintPass};
+use rustc_session::{declare_lint_pass, declare_tool_lint};
+
+declare_clippy_lint! {
+    /// ### What it does
+    /// Checks for usages of the `ref` keyword.
+    /// ### Why is this bad?
+    /// The `ref` keyword can be confusing for people unfamiliar with it, and often
+    /// it is more concise to use `&` instead.
+    /// ### Example
+    /// ```rust
+    /// let opt = Some(5);
+    /// if let Some(ref foo) = opt {}
+    /// ```
+    /// Use instead:
+    /// ```rust
+    /// let opt = Some(5);
+    /// if let Some(foo) = &opt {}
+    /// ```
+    #[clippy::version = "1.71.0"]
+    pub REF_PATTERNS,
+    restriction,
+    "use of a ref pattern, e.g. Some(ref value)"
+}
+declare_lint_pass!(RefPatterns => [REF_PATTERNS]);
+
+impl EarlyLintPass for RefPatterns {
+    fn check_pat(&mut self, cx: &EarlyContext<'_>, pat: &Pat) {
+        if let PatKind::Ident(BindingAnnotation::REF, _, _) = pat.kind
+                && !pat.span.from_expansion()
+        {
+            span_lint_and_help(
+                cx,
+                REF_PATTERNS,
+                pat.span,
+                "usage of ref pattern",
+                None,
+                "consider using `&` for clarity instead",
+            );
+        }
+    }
+}
diff --git a/src/tools/clippy/clippy_lints/src/regex.rs b/src/tools/clippy/clippy_lints/src/regex.rs
index b8b32df6cc6..ef19c6f4617 100644
--- a/src/tools/clippy/clippy_lints/src/regex.rs
+++ b/src/tools/clippy/clippy_lints/src/regex.rs
@@ -122,37 +122,39 @@ fn lint_syntax_error(cx: &LateContext<'_>, error: &regex_syntax::Error, unescape
 }
 
 fn const_str<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> Option<String> {
-    constant(cx, cx.typeck_results(), e).and_then(|(c, _)| match c {
+    constant(cx, cx.typeck_results(), e).and_then(|c| match c {
         Constant::Str(s) => Some(s),
         _ => None,
     })
 }
 
 fn is_trivial_regex(s: &regex_syntax::hir::Hir) -> Option<&'static str> {
-    use regex_syntax::hir::Anchor::{EndText, StartText};
-    use regex_syntax::hir::HirKind::{Alternation, Anchor, Concat, Empty, Literal};
+    use regex_syntax::hir::HirKind::{Alternation, Concat, Empty, Literal, Look};
+    use regex_syntax::hir::Look as HirLook;
 
     let is_literal = |e: &[regex_syntax::hir::Hir]| e.iter().all(|e| matches!(*e.kind(), Literal(_)));
 
     match *s.kind() {
-        Empty | Anchor(_) => Some("the regex is unlikely to be useful as it is"),
+        Empty | Look(_) => Some("the regex is unlikely to be useful as it is"),
         Literal(_) => Some("consider using `str::contains`"),
         Alternation(ref exprs) => {
-            if exprs.iter().all(|e| e.kind().is_empty()) {
+            if exprs.iter().all(|e| matches!(e.kind(), Empty)) {
                 Some("the regex is unlikely to be useful as it is")
             } else {
                 None
             }
         },
         Concat(ref exprs) => match (exprs[0].kind(), exprs[exprs.len() - 1].kind()) {
-            (&Anchor(StartText), &Anchor(EndText)) if exprs[1..(exprs.len() - 1)].is_empty() => {
+            (&Look(HirLook::Start), &Look(HirLook::End)) if exprs[1..(exprs.len() - 1)].is_empty() => {
                 Some("consider using `str::is_empty`")
             },
-            (&Anchor(StartText), &Anchor(EndText)) if is_literal(&exprs[1..(exprs.len() - 1)]) => {
+            (&Look(HirLook::Start), &Look(HirLook::End)) if is_literal(&exprs[1..(exprs.len() - 1)]) => {
                 Some("consider using `==` on `str`s")
             },
-            (&Anchor(StartText), &Literal(_)) if is_literal(&exprs[1..]) => Some("consider using `str::starts_with`"),
-            (&Literal(_), &Anchor(EndText)) if is_literal(&exprs[1..(exprs.len() - 1)]) => {
+            (&Look(HirLook::Start), &Literal(_)) if is_literal(&exprs[1..]) => {
+                Some("consider using `str::starts_with`")
+            },
+            (&Literal(_), &Look(HirLook::End)) if is_literal(&exprs[1..(exprs.len() - 1)]) => {
                 Some("consider using `str::ends_with`")
             },
             _ if is_literal(exprs) => Some("consider using `str::contains`"),
@@ -175,10 +177,7 @@ fn check_set<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, utf8: bool) {
 }
 
 fn check_regex<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, utf8: bool) {
-    let mut parser = regex_syntax::ParserBuilder::new()
-        .unicode(true)
-        .allow_invalid_utf8(!utf8)
-        .build();
+    let mut parser = regex_syntax::ParserBuilder::new().unicode(true).utf8(!utf8).build();
 
     if let ExprKind::Lit(lit) = expr.kind {
         if let LitKind::Str(ref r, style) = lit.node {
diff --git a/src/tools/clippy/clippy_lints/src/renamed_lints.rs b/src/tools/clippy/clippy_lints/src/renamed_lints.rs
index 5e81a01a461..b0db56bb417 100644
--- a/src/tools/clippy/clippy_lints/src/renamed_lints.rs
+++ b/src/tools/clippy/clippy_lints/src/renamed_lints.rs
@@ -15,6 +15,7 @@ pub static RENAMED_LINTS: &[(&str, &str)] = &[
     ("clippy::eval_order_dependence", "clippy::mixed_read_write_in_expression"),
     ("clippy::identity_conversion", "clippy::useless_conversion"),
     ("clippy::if_let_some_result", "clippy::match_result_ok"),
+    ("clippy::integer_arithmetic", "clippy::arithmetic_side_effects"),
     ("clippy::logic_bug", "clippy::overly_complex_bool_expr"),
     ("clippy::new_without_default_derive", "clippy::new_without_default"),
     ("clippy::option_and_then_some", "clippy::bind_instead_of_map"),
@@ -32,9 +33,13 @@ pub static RENAMED_LINTS: &[(&str, &str)] = &[
     ("clippy::zero_width_space", "clippy::invisible_characters"),
     ("clippy::clone_double_ref", "suspicious_double_ref_op"),
     ("clippy::drop_bounds", "drop_bounds"),
+    ("clippy::drop_copy", "dropping_copy_types"),
+    ("clippy::drop_ref", "dropping_references"),
     ("clippy::for_loop_over_option", "for_loops_over_fallibles"),
     ("clippy::for_loop_over_result", "for_loops_over_fallibles"),
     ("clippy::for_loops_over_fallibles", "for_loops_over_fallibles"),
+    ("clippy::forget_copy", "forgetting_copy_types"),
+    ("clippy::forget_ref", "forgetting_references"),
     ("clippy::into_iter_on_array", "array_into_iter"),
     ("clippy::invalid_atomic_ordering", "invalid_atomic_ordering"),
     ("clippy::invalid_ref", "invalid_value"),
diff --git a/src/tools/clippy/clippy_lints/src/strings.rs b/src/tools/clippy/clippy_lints/src/strings.rs
index 5b588e914fd..483f860a8b5 100644
--- a/src/tools/clippy/clippy_lints/src/strings.rs
+++ b/src/tools/clippy/clippy_lints/src/strings.rs
@@ -132,7 +132,7 @@ declare_clippy_lint! {
     /// Probably lots of false positives. If an index comes from a known valid position (e.g.
     /// obtained via `char_indices` over the same string), it is totally OK.
     ///
-    /// # Example
+    /// ### Example
     /// ```rust,should_panic
     /// &"Ölkanne"[1..];
     /// ```
diff --git a/src/tools/clippy/clippy_lints/src/trait_bounds.rs b/src/tools/clippy/clippy_lints/src/trait_bounds.rs
index b5f11b4acae..4ccda15068b 100644
--- a/src/tools/clippy/clippy_lints/src/trait_bounds.rs
+++ b/src/tools/clippy/clippy_lints/src/trait_bounds.rs
@@ -37,12 +37,12 @@ declare_clippy_lint! {
     #[clippy::version = "1.38.0"]
     pub TYPE_REPETITION_IN_BOUNDS,
     nursery,
-    "types are repeated unnecessary in trait bounds use `+` instead of using `T: _, T: _`"
+    "types are repeated unnecessarily in trait bounds, use `+` instead of using `T: _, T: _`"
 }
 
 declare_clippy_lint! {
     /// ### What it does
-    /// Checks for cases where generics are being used and multiple
+    /// Checks for cases where generics or trait objects are being used and multiple
     /// syntax specifications for trait bounds are used simultaneously.
     ///
     /// ### Why is this bad?
@@ -167,6 +167,61 @@ impl<'tcx> LateLintPass<'tcx> for TraitBounds {
             }
         }
     }
+
+    fn check_ty(&mut self, cx: &LateContext<'tcx>, ty: &'tcx Ty<'tcx>) {
+        if_chain! {
+            if let TyKind::Ref(.., mut_ty) = &ty.kind;
+            if let TyKind::TraitObject(bounds, ..) = mut_ty.ty.kind;
+            if bounds.len() > 2;
+            then {
+
+                // Build up a hash of every trait we've seen
+                // When we see a trait for the first time, add it to unique_traits
+                // so we can later use it to build a string of all traits exactly once, without duplicates
+
+                let mut seen_def_ids = FxHashSet::default();
+                let mut unique_traits = Vec::new();
+
+                // Iterate the bounds and add them to our seen hash
+                // If we haven't yet seen it, add it to the fixed traits
+                for bound in bounds.iter() {
+                    let Some(def_id) = bound.trait_ref.trait_def_id() else { continue; };
+
+                    let new_trait = seen_def_ids.insert(def_id);
+
+                    if new_trait {
+                        unique_traits.push(bound);
+                    }
+                }
+
+                // If the number of unique traits isn't the same as the number of traits in the bounds,
+                // there must be 1 or more duplicates
+                if bounds.len() != unique_traits.len() {
+                    let mut bounds_span = bounds[0].span;
+
+                    for bound in bounds.iter().skip(1) {
+                        bounds_span = bounds_span.to(bound.span);
+                    }
+
+                    let fixed_trait_snippet = unique_traits
+                        .iter()
+                        .filter_map(|b| snippet_opt(cx, b.span))
+                        .collect::<Vec<_>>()
+                        .join(" + ");
+
+                    span_lint_and_sugg(
+                        cx,
+                        TRAIT_DUPLICATION_IN_BOUNDS,
+                        bounds_span,
+                        "this trait bound is already specified in trait declaration",
+                        "try",
+                        fixed_trait_snippet,
+                        Applicability::MaybeIncorrect,
+                    );
+                }
+            }
+        }
+    }
 }
 
 impl TraitBounds {
diff --git a/src/tools/clippy/clippy_lints/src/transmute/transmute_null_to_fn.rs b/src/tools/clippy/clippy_lints/src/transmute/transmute_null_to_fn.rs
index e75d7f6bf1d..4944381da24 100644
--- a/src/tools/clippy/clippy_lints/src/transmute/transmute_null_to_fn.rs
+++ b/src/tools/clippy/clippy_lints/src/transmute/transmute_null_to_fn.rs
@@ -31,9 +31,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, arg: &'t
     match arg.kind {
         // Catching:
         // transmute over constants that resolve to `null`.
-        ExprKind::Path(ref _qpath)
-            if matches!(constant(cx, cx.typeck_results(), arg), Some((Constant::RawPtr(0), _))) =>
-        {
+        ExprKind::Path(ref _qpath) if matches!(constant(cx, cx.typeck_results(), arg), Some(Constant::RawPtr(0))) => {
             lint_expr(cx, expr);
             true
         },
diff --git a/src/tools/clippy/clippy_lints/src/transmute/transmuting_null.rs b/src/tools/clippy/clippy_lints/src/transmute/transmuting_null.rs
index 1e407fc4138..770914e99e1 100644
--- a/src/tools/clippy/clippy_lints/src/transmute/transmuting_null.rs
+++ b/src/tools/clippy/clippy_lints/src/transmute/transmuting_null.rs
@@ -1,4 +1,4 @@
-use clippy_utils::consts::{constant_context, Constant};
+use clippy_utils::consts::{constant, Constant};
 use clippy_utils::diagnostics::span_lint;
 use clippy_utils::{is_integer_literal, is_path_diagnostic_item};
 use rustc_hir::{Expr, ExprKind};
@@ -16,9 +16,8 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, arg: &'t
     }
 
     // Catching transmute over constants that resolve to `null`.
-    let mut const_eval_context = constant_context(cx, cx.typeck_results());
     if let ExprKind::Path(ref _qpath) = arg.kind &&
-        let Some(Constant::RawPtr(0)) = const_eval_context.expr(arg)
+        let Some(Constant::RawPtr(0)) = constant(cx, cx.typeck_results(), arg)
     {
         span_lint(cx, TRANSMUTING_NULL, expr.span, LINT_MSG);
         return true;
diff --git a/src/tools/clippy/clippy_lints/src/useless_conversion.rs b/src/tools/clippy/clippy_lints/src/useless_conversion.rs
index ddbe6b2c790..28c3fc859e3 100644
--- a/src/tools/clippy/clippy_lints/src/useless_conversion.rs
+++ b/src/tools/clippy/clippy_lints/src/useless_conversion.rs
@@ -1,4 +1,5 @@
 use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_sugg};
+use clippy_utils::is_ty_alias;
 use clippy_utils::source::{snippet, snippet_with_context};
 use clippy_utils::sugg::Sugg;
 use clippy_utils::ty::{is_copy, is_type_diagnostic_item, same_type_and_consts};
@@ -138,6 +139,7 @@ impl<'tcx> LateLintPass<'tcx> for UselessConversion {
                 if_chain! {
                     if let ExprKind::Path(ref qpath) = path.kind;
                     if let Some(def_id) = cx.qpath_res(qpath, path.hir_id).opt_def_id();
+                    if !is_ty_alias(qpath);
                     then {
                         let a = cx.typeck_results().expr_ty(e);
                         let b = cx.typeck_results().expr_ty(arg);
diff --git a/src/tools/clippy/clippy_lints/src/utils/author.rs b/src/tools/clippy/clippy_lints/src/utils/author.rs
index 935ea90d245..3c2bf5abab2 100644
--- a/src/tools/clippy/clippy_lints/src/utils/author.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/author.rs
@@ -308,7 +308,7 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> {
                 bind!(self, vec);
                 kind!("CStr(ref {vec})");
                 chain!(self, "let [{:?}] = **{vec}", vec.value);
-            }
+            },
             LitKind::Str(s, _) => {
                 bind!(self, s);
                 kind!("Str({s}, _)");
diff --git a/src/tools/clippy/clippy_lints/src/utils/conf.rs b/src/tools/clippy/clippy_lints/src/utils/conf.rs
index 5f05d971fce..f6de66bb514 100644
--- a/src/tools/clippy/clippy_lints/src/utils/conf.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/conf.rs
@@ -174,16 +174,15 @@ macro_rules! define_Conf {
             }
         }
 
-        #[cfg(feature = "internal")]
         pub mod metadata {
-            use crate::utils::internal_lints::metadata_collector::ClippyConfiguration;
+            use crate::utils::ClippyConfiguration;
 
             macro_rules! wrap_option {
                 () => (None);
                 ($x:literal) => (Some($x));
             }
 
-            pub(crate) fn get_configuration_metadata() -> Vec<ClippyConfiguration> {
+            pub fn get_configuration_metadata() -> Vec<ClippyConfiguration> {
                 vec![
                     $(
                         {
diff --git a/src/tools/clippy/clippy_lints/src/utils/internal_lints/metadata_collector.rs b/src/tools/clippy/clippy_lints/src/utils/internal_lints/metadata_collector.rs
index 3d0d4a52511..7a1cd3effae 100644
--- a/src/tools/clippy/clippy_lints/src/utils/internal_lints/metadata_collector.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/internal_lints/metadata_collector.rs
@@ -8,7 +8,11 @@
 //! a simple mistake)
 
 use crate::renamed_lints::RENAMED_LINTS;
-use crate::utils::internal_lints::lint_without_lint_pass::{extract_clippy_version_value, is_lint_ref_type};
+use crate::utils::{
+    collect_configs,
+    internal_lints::lint_without_lint_pass::{extract_clippy_version_value, is_lint_ref_type},
+    ClippyConfiguration,
+};
 
 use clippy_utils::diagnostics::span_lint;
 use clippy_utils::ty::{match_type, walk_ptrs_ty_depth};
@@ -520,111 +524,6 @@ impl Serialize for ApplicabilityInfo {
     }
 }
 
-// ==================================================================
-// Configuration
-// ==================================================================
-#[derive(Debug, Clone, Default)]
-pub struct ClippyConfiguration {
-    name: String,
-    config_type: &'static str,
-    default: String,
-    lints: Vec<String>,
-    doc: String,
-    #[allow(dead_code)]
-    deprecation_reason: Option<&'static str>,
-}
-
-impl ClippyConfiguration {
-    pub fn new(
-        name: &'static str,
-        config_type: &'static str,
-        default: String,
-        doc_comment: &'static str,
-        deprecation_reason: Option<&'static str>,
-    ) -> Self {
-        let (lints, doc) = parse_config_field_doc(doc_comment)
-            .unwrap_or_else(|| (vec![], "[ERROR] MALFORMED DOC COMMENT".to_string()));
-
-        Self {
-            name: to_kebab(name),
-            lints,
-            doc,
-            config_type,
-            default,
-            deprecation_reason,
-        }
-    }
-
-    fn to_markdown_paragraph(&self) -> String {
-        format!(
-            "### {}\n{}\n\n**Default Value:** `{}` (`{}`)\n\n{}\n\n",
-            self.name,
-            self.doc
-                .lines()
-                .map(|line| line.strip_prefix("    ").unwrap_or(line))
-                .join("\n"),
-            self.default,
-            self.config_type,
-            self.lints
-                .iter()
-                .map(|name| name.to_string().split_whitespace().next().unwrap().to_string())
-                .map(|name| format!("* [{name}](https://rust-lang.github.io/rust-clippy/master/index.html#{name})"))
-                .join("\n"),
-        )
-    }
-
-    fn to_markdown_table_entry(&self) -> String {
-        format!("| [{}](#{}) | `{}` |", self.name, self.name, self.default)
-    }
-}
-
-fn collect_configs() -> Vec<ClippyConfiguration> {
-    crate::utils::conf::metadata::get_configuration_metadata()
-}
-
-/// This parses the field documentation of the config struct.
-///
-/// ```rust, ignore
-/// parse_config_field_doc(cx, "Lint: LINT_NAME_1, LINT_NAME_2. Papa penguin, papa penguin")
-/// ```
-///
-/// Would yield:
-/// ```rust, ignore
-/// Some(["lint_name_1", "lint_name_2"], "Papa penguin, papa penguin")
-/// ```
-fn parse_config_field_doc(doc_comment: &str) -> Option<(Vec<String>, String)> {
-    const DOC_START: &str = " Lint: ";
-    if_chain! {
-        if doc_comment.starts_with(DOC_START);
-        if let Some(split_pos) = doc_comment.find('.');
-        then {
-            let mut doc_comment = doc_comment.to_string();
-            let mut documentation = doc_comment.split_off(split_pos);
-
-            // Extract lints
-            doc_comment.make_ascii_lowercase();
-            let lints: Vec<String> = doc_comment
-                .split_off(DOC_START.len())
-                .split(", ")
-                .map(str::to_string)
-                .collect();
-
-            // Format documentation correctly
-            // split off leading `.` from lint name list and indent for correct formatting
-            documentation = documentation.trim_start_matches('.').trim().replace("\n ", "\n    ");
-
-            Some((lints, documentation))
-        } else {
-            None
-        }
-    }
-}
-
-/// Transforms a given `snake_case_string` to a tasty `kebab-case-string`
-fn to_kebab(config_name: &str) -> String {
-    config_name.replace('_', "-")
-}
-
 impl fmt::Display for ClippyConfiguration {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> fmt::Result {
         writeln!(
diff --git a/src/tools/clippy/clippy_lints/src/utils/mod.rs b/src/tools/clippy/clippy_lints/src/utils/mod.rs
index dc647af264c..d3ea7cafa80 100644
--- a/src/tools/clippy/clippy_lints/src/utils/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/mod.rs
@@ -4,3 +4,143 @@ pub mod dump_hir;
 pub mod format_args_collector;
 #[cfg(feature = "internal")]
 pub mod internal_lints;
+#[cfg(feature = "internal")]
+use itertools::Itertools;
+
+/// Transforms a given `snake_case_string` to a tasty `kebab-case-string`
+fn to_kebab(config_name: &str) -> String {
+    config_name.replace('_', "-")
+}
+
+// ==================================================================
+// Configuration
+// ==================================================================
+#[derive(Debug, Clone, Default)] //~ ERROR no such field
+pub struct ClippyConfiguration {
+    pub name: String,
+    #[allow(dead_code)]
+    config_type: &'static str,
+    pub default: String,
+    pub lints: Vec<String>,
+    pub doc: String,
+    #[allow(dead_code)]
+    deprecation_reason: Option<&'static str>,
+}
+
+impl ClippyConfiguration {
+    pub fn new(
+        name: &'static str,
+        config_type: &'static str,
+        default: String,
+        doc_comment: &'static str,
+        deprecation_reason: Option<&'static str>,
+    ) -> Self {
+        let (lints, doc) = parse_config_field_doc(doc_comment)
+            .unwrap_or_else(|| (vec![], "[ERROR] MALFORMED DOC COMMENT".to_string()));
+
+        Self {
+            name: to_kebab(name),
+            lints,
+            doc,
+            config_type,
+            default,
+            deprecation_reason,
+        }
+    }
+
+    #[cfg(feature = "internal")]
+    fn to_markdown_paragraph(&self) -> String {
+        format!(
+            "### {}\n{}\n\n**Default Value:** `{}` (`{}`)\n\n{}\n\n",
+            self.name,
+            self.doc
+                .lines()
+                .map(|line| line.strip_prefix("    ").unwrap_or(line))
+                .join("\n"),
+            self.default,
+            self.config_type,
+            self.lints
+                .iter()
+                .map(|name| name.to_string().split_whitespace().next().unwrap().to_string())
+                .map(|name| format!("* [{name}](https://rust-lang.github.io/rust-clippy/master/index.html#{name})"))
+                .join("\n"),
+        )
+    }
+
+    #[cfg(feature = "internal")]
+    fn to_markdown_table_entry(&self) -> String {
+        format!("| [{}](#{}) | `{}` |", self.name, self.name, self.default)
+    }
+}
+
+#[cfg(feature = "internal")]
+fn collect_configs() -> Vec<ClippyConfiguration> {
+    crate::utils::conf::metadata::get_configuration_metadata()
+}
+
+/// This parses the field documentation of the config struct.
+///
+/// ```rust, ignore
+/// parse_config_field_doc(cx, "Lint: LINT_NAME_1, LINT_NAME_2. Papa penguin, papa penguin")
+/// ```
+///
+/// Would yield:
+/// ```rust, ignore
+/// Some(["lint_name_1", "lint_name_2"], "Papa penguin, papa penguin")
+/// ```
+fn parse_config_field_doc(doc_comment: &str) -> Option<(Vec<String>, String)> {
+    const DOC_START: &str = " Lint: ";
+    if_chain! {
+        if doc_comment.starts_with(DOC_START);
+        if let Some(split_pos) = doc_comment.find('.');
+        then {
+            let mut doc_comment = doc_comment.to_string();
+            let mut documentation = doc_comment.split_off(split_pos);
+
+            // Extract lints
+            doc_comment.make_ascii_lowercase();
+            let lints: Vec<String> = doc_comment
+                .split_off(DOC_START.len())
+                .split(", ")
+                .map(str::to_string)
+                .collect();
+
+            // Format documentation correctly
+            // split off leading `.` from lint name list and indent for correct formatting
+            documentation = documentation.trim_start_matches('.').trim().replace("\n ", "\n    ");
+
+            Some((lints, documentation))
+        } else {
+            None
+        }
+    }
+}
+
+// Shamelessly stolen from find_all (https://github.com/nectariner/find_all)
+pub trait FindAll: Iterator + Sized {
+    fn find_all<P>(&mut self, predicate: P) -> Option<Vec<usize>>
+    where
+        P: FnMut(&Self::Item) -> bool;
+}
+
+impl<I> FindAll for I
+where
+    I: Iterator,
+{
+    fn find_all<P>(&mut self, mut predicate: P) -> Option<Vec<usize>>
+    where
+        P: FnMut(&Self::Item) -> bool,
+    {
+        let mut occurences = Vec::<usize>::default();
+        for (index, element) in self.enumerate() {
+            if predicate(&element) {
+                occurences.push(index);
+            }
+        }
+
+        match occurences.len() {
+            0 => None,
+            _ => Some(occurences),
+        }
+    }
+}
diff --git a/src/tools/clippy/clippy_lints/src/vec.rs b/src/tools/clippy/clippy_lints/src/vec.rs
index 297a80e5767..7329e508106 100644
--- a/src/tools/clippy/clippy_lints/src/vec.rs
+++ b/src/tools/clippy/clippy_lints/src/vec.rs
@@ -84,7 +84,7 @@ impl UselessVec {
         let mut applicability = Applicability::MachineApplicable;
         let snippet = match *vec_args {
             higher::VecArgs::Repeat(elem, len) => {
-                if let Some((Constant::Int(len_constant), _)) = constant(cx, cx.typeck_results(), len) {
+                if let Some(Constant::Int(len_constant)) = constant(cx, cx.typeck_results(), len) {
                     #[expect(clippy::cast_possible_truncation)]
                     if len_constant as u64 * size_of(cx, elem) > self.too_large_for_stack {
                         return;
diff --git a/src/tools/clippy/clippy_lints/src/wildcard_imports.rs b/src/tools/clippy/clippy_lints/src/wildcard_imports.rs
index 36f910c983f..a9089fba3c5 100644
--- a/src/tools/clippy/clippy_lints/src/wildcard_imports.rs
+++ b/src/tools/clippy/clippy_lints/src/wildcard_imports.rs
@@ -7,7 +7,7 @@ use rustc_hir::{
     def::{DefKind, Res},
     Item, ItemKind, PathSegment, UseKind,
 };
-use rustc_lint::{LateContext, LateLintPass};
+use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_middle::ty;
 use rustc_session::{declare_tool_lint, impl_lint_pass};
 use rustc_span::symbol::kw;
@@ -117,6 +117,10 @@ impl_lint_pass!(WildcardImports => [ENUM_GLOB_USE, WILDCARD_IMPORTS]);
 
 impl LateLintPass<'_> for WildcardImports {
     fn check_item(&mut self, cx: &LateContext<'_>, item: &Item<'_>) {
+        if cx.sess().is_test_crate() {
+            return;
+        }
+
         if is_test_module_or_function(cx.tcx, item) {
             self.test_modules_deep = self.test_modules_deep.saturating_add(1);
         }
diff --git a/src/tools/clippy/clippy_utils/src/consts.rs b/src/tools/clippy/clippy_utils/src/consts.rs
index 8075881e3bb..fb772644c0d 100644
--- a/src/tools/clippy/clippy_utils/src/consts.rs
+++ b/src/tools/clippy/clippy_utils/src/consts.rs
@@ -1,18 +1,21 @@
 #![allow(clippy::float_cmp)]
 
+use crate::source::{get_source_text, walk_span_to_context};
 use crate::{clip, is_direct_expn_of, sext, unsext};
 use if_chain::if_chain;
 use rustc_ast::ast::{self, LitFloatType, LitKind};
 use rustc_data_structures::sync::Lrc;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::{BinOp, BinOpKind, Block, Expr, ExprKind, HirId, Item, ItemKind, Node, QPath, UnOp};
+use rustc_lexer::tokenize;
 use rustc_lint::LateContext;
 use rustc_middle::mir;
 use rustc_middle::mir::interpret::Scalar;
-use rustc_middle::ty::SubstsRef;
 use rustc_middle::ty::{self, EarlyBinder, FloatTy, ScalarInt, Ty, TyCtxt};
+use rustc_middle::ty::{List, SubstsRef};
 use rustc_middle::{bug, span_bug};
 use rustc_span::symbol::Symbol;
+use rustc_span::SyntaxContext;
 use std::cmp::Ordering::{self, Equal};
 use std::hash::{Hash, Hasher};
 use std::iter;
@@ -210,8 +213,7 @@ pub fn lit_to_mir_constant(lit: &LitKind, ty: Option<Ty<'_>>) -> Constant {
     match *lit {
         LitKind::Str(ref is, _) => Constant::Str(is.to_string()),
         LitKind::Byte(b) => Constant::Int(u128::from(b)),
-        LitKind::ByteStr(ref s, _) => Constant::Binary(Lrc::clone(s)),
-        LitKind::CStr(ref s, _) => Constant::Binary(Lrc::clone(s)),
+        LitKind::ByteStr(ref s, _) | LitKind::CStr(ref s, _) => Constant::Binary(Lrc::clone(s)),
         LitKind::Char(c) => Constant::Char(c),
         LitKind::Int(n, _) => Constant::Int(n),
         LitKind::Float(ref is, LitFloatType::Suffixed(fty)) => match fty {
@@ -228,27 +230,46 @@ pub fn lit_to_mir_constant(lit: &LitKind, ty: Option<Ty<'_>>) -> Constant {
     }
 }
 
+/// The source of a constant value.
+pub enum ConstantSource {
+    /// The value is determined solely from the expression.
+    Local,
+    /// The value is dependent on a defined constant.
+    Constant,
+}
+impl ConstantSource {
+    pub fn is_local(&self) -> bool {
+        matches!(self, Self::Local)
+    }
+}
+
+/// Attempts to evaluate the expression as a constant.
 pub fn constant<'tcx>(
     lcx: &LateContext<'tcx>,
     typeck_results: &ty::TypeckResults<'tcx>,
     e: &Expr<'_>,
-) -> Option<(Constant, bool)> {
-    let mut cx = ConstEvalLateContext {
-        lcx,
-        typeck_results,
-        param_env: lcx.param_env,
-        needed_resolution: false,
-        substs: ty::List::empty(),
-    };
-    cx.expr(e).map(|cst| (cst, cx.needed_resolution))
+) -> Option<Constant> {
+    ConstEvalLateContext::new(lcx, typeck_results).expr(e)
+}
+
+/// Attempts to evaluate the expression as a constant.
+pub fn constant_with_source<'tcx>(
+    lcx: &LateContext<'tcx>,
+    typeck_results: &ty::TypeckResults<'tcx>,
+    e: &Expr<'_>,
+) -> Option<(Constant, ConstantSource)> {
+    let mut ctxt = ConstEvalLateContext::new(lcx, typeck_results);
+    let res = ctxt.expr(e);
+    res.map(|x| (x, ctxt.source))
 }
 
+/// Attempts to evaluate an expression only if it's value is not dependent on other items.
 pub fn constant_simple<'tcx>(
     lcx: &LateContext<'tcx>,
     typeck_results: &ty::TypeckResults<'tcx>,
     e: &Expr<'_>,
 ) -> Option<Constant> {
-    constant(lcx, typeck_results, e).and_then(|(cst, res)| if res { None } else { Some(cst) })
+    constant_with_source(lcx, typeck_results, e).and_then(|(c, s)| s.is_local().then_some(c))
 }
 
 pub fn constant_full_int<'tcx>(
@@ -297,29 +318,25 @@ impl Ord for FullInt {
     }
 }
 
-/// Creates a `ConstEvalLateContext` from the given `LateContext` and `TypeckResults`.
-pub fn constant_context<'a, 'tcx>(
-    lcx: &'a LateContext<'tcx>,
-    typeck_results: &'a ty::TypeckResults<'tcx>,
-) -> ConstEvalLateContext<'a, 'tcx> {
-    ConstEvalLateContext {
-        lcx,
-        typeck_results,
-        param_env: lcx.param_env,
-        needed_resolution: false,
-        substs: ty::List::empty(),
-    }
-}
-
 pub struct ConstEvalLateContext<'a, 'tcx> {
     lcx: &'a LateContext<'tcx>,
     typeck_results: &'a ty::TypeckResults<'tcx>,
     param_env: ty::ParamEnv<'tcx>,
-    needed_resolution: bool,
+    source: ConstantSource,
     substs: SubstsRef<'tcx>,
 }
 
 impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> {
+    fn new(lcx: &'a LateContext<'tcx>, typeck_results: &'a ty::TypeckResults<'tcx>) -> Self {
+        Self {
+            lcx,
+            typeck_results,
+            param_env: lcx.param_env,
+            source: ConstantSource::Local,
+            substs: List::empty(),
+        }
+    }
+
     /// Simple constant folding: Insert an expression, get a constant or none.
     pub fn expr(&mut self, e: &Expr<'_>) -> Option<Constant> {
         match e.kind {
@@ -454,11 +471,9 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> {
                     .const_eval_resolve(self.param_env, mir::UnevaluatedConst::new(def_id, substs), None)
                     .ok()
                     .map(|val| rustc_middle::mir::ConstantKind::from_value(val, ty))?;
-                let result = miri_to_const(self.lcx.tcx, result);
-                if result.is_some() {
-                    self.needed_resolution = true;
-                }
-                result
+                let result = miri_to_const(self.lcx.tcx, result)?;
+                self.source = ConstantSource::Constant;
+                Some(result)
             },
             // FIXME: cover all usable cases.
             _ => None,
@@ -492,8 +507,33 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> {
 
     /// A block can only yield a constant if it only has one constant expression.
     fn block(&mut self, block: &Block<'_>) -> Option<Constant> {
-        if block.stmts.is_empty() {
-            block.expr.as_ref().and_then(|b| self.expr(b))
+        if block.stmts.is_empty()
+            && let Some(expr) = block.expr
+        {
+            // Try to detect any `cfg`ed statements or empty macro expansions.
+            let span = block.span.data();
+            if span.ctxt == SyntaxContext::root() {
+                if let Some(expr_span) = walk_span_to_context(expr.span, span.ctxt)
+                    && let expr_lo = expr_span.lo()
+                    && expr_lo >= span.lo
+                    && let Some(src) = get_source_text(self.lcx, span.lo..expr_lo)
+                    && let Some(src) = src.as_str()
+                {
+                    use rustc_lexer::TokenKind::{Whitespace, LineComment, BlockComment, Semi, OpenBrace};
+                    if !tokenize(src)
+                        .map(|t| t.kind)
+                        .filter(|t| !matches!(t, Whitespace | LineComment { .. } | BlockComment { .. } | Semi))
+                        .eq([OpenBrace])
+                    {
+                        self.source = ConstantSource::Constant;
+                    }
+                } else {
+                    // Unable to access the source. Assume a non-local dependency.
+                    self.source = ConstantSource::Constant;
+                }
+            }
+
+            self.expr(expr)
         } else {
             None
         }
diff --git a/src/tools/clippy/clippy_utils/src/hir_utils.rs b/src/tools/clippy/clippy_utils/src/hir_utils.rs
index 9b7408d5133..a49246a7832 100644
--- a/src/tools/clippy/clippy_utils/src/hir_utils.rs
+++ b/src/tools/clippy/clippy_utils/src/hir_utils.rs
@@ -1,6 +1,7 @@
 use crate::consts::constant_simple;
 use crate::macros::macro_backtrace;
-use crate::source::snippet_opt;
+use crate::source::{get_source_text, snippet_opt, walk_span_to_context, SpanRange};
+use crate::tokenize_with_text;
 use rustc_ast::ast::InlineAsmTemplatePiece;
 use rustc_data_structures::fx::FxHasher;
 use rustc_hir::def::Res;
@@ -13,8 +14,9 @@ use rustc_hir::{
 use rustc_lexer::{tokenize, TokenKind};
 use rustc_lint::LateContext;
 use rustc_middle::ty::TypeckResults;
-use rustc_span::{sym, Symbol};
+use rustc_span::{sym, BytePos, ExpnKind, MacroKind, Symbol, SyntaxContext};
 use std::hash::{Hash, Hasher};
+use std::ops::Range;
 
 /// Callback that is called when two expressions are not equal in the sense of `SpanlessEq`, but
 /// other conditions would make them equal.
@@ -65,6 +67,8 @@ impl<'a, 'tcx> SpanlessEq<'a, 'tcx> {
     pub fn inter_expr(&mut self) -> HirEqInterExpr<'_, 'a, 'tcx> {
         HirEqInterExpr {
             inner: self,
+            left_ctxt: SyntaxContext::root(),
+            right_ctxt: SyntaxContext::root(),
             locals: HirIdMap::default(),
         }
     }
@@ -92,6 +96,8 @@ impl<'a, 'tcx> SpanlessEq<'a, 'tcx> {
 
 pub struct HirEqInterExpr<'a, 'b, 'tcx> {
     inner: &'a mut SpanlessEq<'b, 'tcx>,
+    left_ctxt: SyntaxContext,
+    right_ctxt: SyntaxContext,
 
     // When binding are declared, the binding ID in the left expression is mapped to the one on the
     // right. For example, when comparing `{ let x = 1; x + 2 }` and `{ let y = 1; y + 2 }`,
@@ -126,52 +132,88 @@ impl HirEqInterExpr<'_, '_, '_> {
     }
 
     /// Checks whether two blocks are the same.
+    #[expect(clippy::similar_names)]
     fn eq_block(&mut self, left: &Block<'_>, right: &Block<'_>) -> bool {
-        match (left.stmts, left.expr, right.stmts, right.expr) {
-            ([], None, [], None) => {
-                // For empty blocks, check to see if the tokens are equal. This will catch the case where a macro
-                // expanded to nothing, or the cfg attribute was used.
-                let (Some(left), Some(right)) = (
-                    snippet_opt(self.inner.cx, left.span),
-                    snippet_opt(self.inner.cx, right.span),
-                ) else { return true };
-                let mut left_pos = 0;
-                let left = tokenize(&left)
-                    .map(|t| {
-                        let end = left_pos + t.len as usize;
-                        let s = &left[left_pos..end];
-                        left_pos = end;
-                        (t, s)
-                    })
-                    .filter(|(t, _)| {
-                        !matches!(
-                            t.kind,
-                            TokenKind::LineComment { .. } | TokenKind::BlockComment { .. } | TokenKind::Whitespace
-                        )
-                    })
-                    .map(|(_, s)| s);
-                let mut right_pos = 0;
-                let right = tokenize(&right)
-                    .map(|t| {
-                        let end = right_pos + t.len as usize;
-                        let s = &right[right_pos..end];
-                        right_pos = end;
-                        (t, s)
-                    })
-                    .filter(|(t, _)| {
-                        !matches!(
-                            t.kind,
-                            TokenKind::LineComment { .. } | TokenKind::BlockComment { .. } | TokenKind::Whitespace
-                        )
-                    })
-                    .map(|(_, s)| s);
-                left.eq(right)
-            },
-            _ => {
-                over(left.stmts, right.stmts, |l, r| self.eq_stmt(l, r))
-                    && both(&left.expr, &right.expr, |l, r| self.eq_expr(l, r))
-            },
+        use TokenKind::{BlockComment, LineComment, Semi, Whitespace};
+        if left.stmts.len() != right.stmts.len() {
+            return false;
+        }
+        let lspan = left.span.data();
+        let rspan = right.span.data();
+        if lspan.ctxt != SyntaxContext::root() && rspan.ctxt != SyntaxContext::root() {
+            // Don't try to check in between statements inside macros.
+            return over(left.stmts, right.stmts, |left, right| self.eq_stmt(left, right))
+                && both(&left.expr, &right.expr, |left, right| self.eq_expr(left, right));
+        }
+        if lspan.ctxt != rspan.ctxt {
+            return false;
         }
+
+        let mut lstart = lspan.lo;
+        let mut rstart = rspan.lo;
+
+        for (left, right) in left.stmts.iter().zip(right.stmts) {
+            if !self.eq_stmt(left, right) {
+                return false;
+            }
+
+            // Try to detect any `cfg`ed statements or empty macro expansions.
+            let Some(lstmt_span) = walk_span_to_context(left.span, lspan.ctxt) else {
+                return false;
+            };
+            let Some(rstmt_span) = walk_span_to_context(right.span, rspan.ctxt) else {
+                return false;
+            };
+            let lstmt_span = lstmt_span.data();
+            let rstmt_span = rstmt_span.data();
+
+            if lstmt_span.lo < lstart && rstmt_span.lo < rstart {
+                // Can happen when macros expand to multiple statements, or rearrange statements.
+                // Nothing in between the statements to check in this case.
+                continue;
+            }
+            if lstmt_span.lo < lstart || rstmt_span.lo < rstart {
+                // Only one of the blocks had a weird macro.
+                return false;
+            }
+            if !eq_span_tokens(self.inner.cx, lstart..lstmt_span.lo, rstart..rstmt_span.lo, |t| {
+                !matches!(t, Whitespace | LineComment { .. } | BlockComment { .. } | Semi)
+            }) {
+                return false;
+            }
+
+            lstart = lstmt_span.hi;
+            rstart = rstmt_span.hi;
+        }
+
+        let (lend, rend) = match (left.expr, right.expr) {
+            (Some(left), Some(right)) => {
+                if !self.eq_expr(left, right) {
+                    return false;
+                }
+                let Some(lexpr_span) = walk_span_to_context(left.span, lspan.ctxt) else {
+                    return false;
+                };
+                let Some(rexpr_span) = walk_span_to_context(right.span, rspan.ctxt) else {
+                    return false;
+                };
+                (lexpr_span.lo(), rexpr_span.lo())
+            },
+            (None, None) => (lspan.hi, rspan.hi),
+            (Some(_), None) | (None, Some(_)) => return false,
+        };
+
+        if lend < lstart && rend < rstart {
+            // Can happen when macros rearrange the input.
+            // Nothing in between the statements to check in this case.
+            return true;
+        } else if lend < lstart || rend < rstart {
+            // Only one of the blocks had a weird macro
+            return false;
+        }
+        eq_span_tokens(self.inner.cx, lstart..lend, rstart..rend, |t| {
+            !matches!(t, Whitespace | LineComment { .. } | BlockComment { .. } | Semi)
+        })
     }
 
     fn should_ignore(&mut self, expr: &Expr<'_>) -> bool {
@@ -207,7 +249,7 @@ impl HirEqInterExpr<'_, '_, '_> {
 
     #[expect(clippy::similar_names)]
     pub fn eq_expr(&mut self, left: &Expr<'_>, right: &Expr<'_>) -> bool {
-        if !self.inner.allow_side_effects && left.span.ctxt() != right.span.ctxt() {
+        if !self.check_ctxt(left.span.ctxt(), right.span.ctxt()) {
             return false;
         }
 
@@ -440,6 +482,45 @@ impl HirEqInterExpr<'_, '_, '_> {
     fn eq_type_binding(&mut self, left: &TypeBinding<'_>, right: &TypeBinding<'_>) -> bool {
         left.ident.name == right.ident.name && self.eq_ty(left.ty(), right.ty())
     }
+
+    fn check_ctxt(&mut self, left: SyntaxContext, right: SyntaxContext) -> bool {
+        if self.left_ctxt == left && self.right_ctxt == right {
+            return true;
+        } else if self.left_ctxt == left || self.right_ctxt == right {
+            // Only one context has changed. This can only happen if the two nodes are written differently.
+            return false;
+        } else if left != SyntaxContext::root() {
+            let mut left_data = left.outer_expn_data();
+            let mut right_data = right.outer_expn_data();
+            loop {
+                use TokenKind::{BlockComment, LineComment, Whitespace};
+                if left_data.macro_def_id != right_data.macro_def_id
+                    || (matches!(left_data.kind, ExpnKind::Macro(MacroKind::Bang, name) if name == sym::cfg)
+                        && !eq_span_tokens(self.inner.cx, left_data.call_site, right_data.call_site, |t| {
+                            !matches!(t, Whitespace | LineComment { .. } | BlockComment { .. })
+                        }))
+                {
+                    // Either a different chain of macro calls, or different arguments to the `cfg` macro.
+                    return false;
+                }
+                let left_ctxt = left_data.call_site.ctxt();
+                let right_ctxt = right_data.call_site.ctxt();
+                if left_ctxt == SyntaxContext::root() && right_ctxt == SyntaxContext::root() {
+                    break;
+                }
+                if left_ctxt == SyntaxContext::root() || right_ctxt == SyntaxContext::root() {
+                    // Different lengths for the expansion stack. This can only happen if nodes are written differently,
+                    // or shouldn't be compared to start with.
+                    return false;
+                }
+                left_data = left_ctxt.outer_expn_data();
+                right_data = right_ctxt.outer_expn_data();
+            }
+        }
+        self.left_ctxt = left;
+        self.right_ctxt = right;
+        true
+    }
 }
 
 /// Some simple reductions like `{ return }` => `return`
@@ -1038,3 +1119,34 @@ pub fn hash_expr(cx: &LateContext<'_>, e: &Expr<'_>) -> u64 {
     h.hash_expr(e);
     h.finish()
 }
+
+#[expect(clippy::similar_names)]
+fn eq_span_tokens(
+    cx: &LateContext<'_>,
+    left: impl SpanRange,
+    right: impl SpanRange,
+    pred: impl Fn(TokenKind) -> bool,
+) -> bool {
+    fn f(cx: &LateContext<'_>, left: Range<BytePos>, right: Range<BytePos>, pred: impl Fn(TokenKind) -> bool) -> bool {
+        if let Some(lsrc) = get_source_text(cx, left)
+            && let Some(lsrc) = lsrc.as_str()
+            && let Some(rsrc) = get_source_text(cx, right)
+            && let Some(rsrc) = rsrc.as_str()
+        {
+            let pred = |t: &(_, _)| pred(t.0);
+            let map = |(_, x)| x;
+
+            let ltok = tokenize_with_text(lsrc)
+                .filter(pred)
+                .map(map);
+            let rtok = tokenize_with_text(rsrc)
+                .filter(pred)
+                .map(map);
+            ltok.eq(rtok)
+        } else {
+            // Unable to access the source. Conservatively assume the blocks aren't equal.
+            false
+        }
+    }
+    f(cx, left.into_range(), right.into_range(), pred)
+}
diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs
index 964104fc31d..575c29a6b6f 100644
--- a/src/tools/clippy/clippy_utils/src/lib.rs
+++ b/src/tools/clippy/clippy_utils/src/lib.rs
@@ -1,5 +1,6 @@
 #![feature(array_chunks)]
 #![feature(box_patterns)]
+#![feature(if_let_guard)]
 #![feature(let_chains)]
 #![feature(lint_reasons)]
 #![feature(never_type)]
@@ -76,6 +77,7 @@ use std::sync::OnceLock;
 use std::sync::{Mutex, MutexGuard};
 
 use if_chain::if_chain;
+use itertools::Itertools;
 use rustc_ast::ast::{self, LitKind, RangeLimits};
 use rustc_ast::Attribute;
 use rustc_data_structures::fx::FxHashMap;
@@ -282,6 +284,15 @@ pub fn is_wild(pat: &Pat<'_>) -> bool {
     matches!(pat.kind, PatKind::Wild)
 }
 
+/// Checks if the given `QPath` belongs to a type alias.
+pub fn is_ty_alias(qpath: &QPath<'_>) -> bool {
+    match *qpath {
+        QPath::Resolved(_, path) => matches!(path.res, Res::Def(DefKind::TyAlias, ..)),
+        QPath::TypeRelative(ty, _) if let TyKind::Path(qpath) = ty.kind => { is_ty_alias(&qpath) },
+        _ => false,
+    }
+}
+
 /// Checks if the method call given in `expr` belongs to the given trait.
 /// This is a deprecated function, consider using [`is_trait_method`].
 pub fn match_trait_method(cx: &LateContext<'_>, expr: &Expr<'_>, path: &[&str]) -> bool {
@@ -1488,7 +1499,7 @@ pub fn is_range_full(cx: &LateContext<'_>, expr: &Expr<'_>, container_path: Opti
                 && let const_val = cx.tcx.valtree_to_const_val((bnd_ty, min_val.to_valtree()))
                 && let min_const_kind = ConstantKind::from_value(const_val, bnd_ty)
                 && let Some(min_const) = miri_to_const(cx.tcx, min_const_kind)
-                && let Some((start_const, _)) = constant(cx, cx.typeck_results(), start)
+                && let Some(start_const) = constant(cx, cx.typeck_results(), start)
             {
                 start_const == min_const
             } else {
@@ -1504,7 +1515,7 @@ pub fn is_range_full(cx: &LateContext<'_>, expr: &Expr<'_>, container_path: Opti
                         && let const_val = cx.tcx.valtree_to_const_val((bnd_ty, max_val.to_valtree()))
                         && let max_const_kind = ConstantKind::from_value(const_val, bnd_ty)
                         && let Some(max_const) = miri_to_const(cx.tcx, max_const_kind)
-                        && let Some((end_const, _)) = constant(cx, cx.typeck_results(), end)
+                        && let Some(end_const) = constant(cx, cx.typeck_results(), end)
                     {
                         end_const == max_const
                     } else {
@@ -1536,7 +1547,7 @@ pub fn is_integer_const(cx: &LateContext<'_>, e: &Expr<'_>, value: u128) -> bool
         return true;
     }
     let enclosing_body = cx.tcx.hir().enclosing_body_owner(e.hir_id);
-    if let Some((Constant::Int(v), _)) = constant(cx, cx.tcx.typeck(enclosing_body), e) {
+    if let Some(Constant::Int(v)) = constant(cx, cx.tcx.typeck(enclosing_body), e) {
         return value == v;
     }
     false
@@ -2480,6 +2491,17 @@ pub fn walk_to_expr_usage<'tcx, T>(
     None
 }
 
+/// Tokenizes the input while keeping the text associated with each token.
+pub fn tokenize_with_text(s: &str) -> impl Iterator<Item = (TokenKind, &str)> {
+    let mut pos = 0;
+    tokenize(s).map(move |t| {
+        let end = pos + t.len;
+        let range = pos as usize..end as usize;
+        pos = end;
+        (t.kind, s.get(range).unwrap_or_default())
+    })
+}
+
 /// Checks whether a given span has any comment token
 /// This checks for all types of comment: line "//", block "/**", doc "///" "//!"
 pub fn span_contains_comment(sm: &SourceMap, span: Span) -> bool {
@@ -2496,23 +2518,11 @@ pub fn span_contains_comment(sm: &SourceMap, span: Span) -> bool {
 /// Comments are returned wrapped with their relevant delimiters
 pub fn span_extract_comment(sm: &SourceMap, span: Span) -> String {
     let snippet = sm.span_to_snippet(span).unwrap_or_default();
-    let mut comments_buf: Vec<String> = Vec::new();
-    let mut index: usize = 0;
-
-    for token in tokenize(&snippet) {
-        let token_range = index..(index + token.len as usize);
-        index += token.len as usize;
-        match token.kind {
-            TokenKind::BlockComment { .. } | TokenKind::LineComment { .. } => {
-                if let Some(comment) = snippet.get(token_range) {
-                    comments_buf.push(comment.to_string());
-                }
-            },
-            _ => (),
-        }
-    }
-
-    comments_buf.join("\n")
+    let res = tokenize_with_text(&snippet)
+        .filter(|(t, _)| matches!(t, TokenKind::BlockComment { .. } | TokenKind::LineComment { .. }))
+        .map(|(_, s)| s)
+        .join("\n");
+    res
 }
 
 pub fn span_find_starting_semi(sm: &SourceMap, span: Span) -> Span {
diff --git a/src/tools/clippy/clippy_utils/src/source.rs b/src/tools/clippy/clippy_utils/src/source.rs
index 62fa37660fa..0f60290644a 100644
--- a/src/tools/clippy/clippy_utils/src/source.rs
+++ b/src/tools/clippy/clippy_utils/src/source.rs
@@ -2,14 +2,64 @@
 
 #![allow(clippy::module_name_repetitions)]
 
+use rustc_data_structures::sync::Lrc;
 use rustc_errors::Applicability;
 use rustc_hir::{Expr, ExprKind};
 use rustc_lint::{LateContext, LintContext};
 use rustc_session::Session;
-use rustc_span::hygiene;
 use rustc_span::source_map::{original_sp, SourceMap};
+use rustc_span::{hygiene, SourceFile};
 use rustc_span::{BytePos, Pos, Span, SpanData, SyntaxContext, DUMMY_SP};
 use std::borrow::Cow;
+use std::ops::Range;
+
+/// A type which can be converted to the range portion of a `Span`.
+pub trait SpanRange {
+    fn into_range(self) -> Range<BytePos>;
+}
+impl SpanRange for Span {
+    fn into_range(self) -> Range<BytePos> {
+        let data = self.data();
+        data.lo..data.hi
+    }
+}
+impl SpanRange for SpanData {
+    fn into_range(self) -> Range<BytePos> {
+        self.lo..self.hi
+    }
+}
+impl SpanRange for Range<BytePos> {
+    fn into_range(self) -> Range<BytePos> {
+        self
+    }
+}
+
+pub struct SourceFileRange {
+    pub sf: Lrc<SourceFile>,
+    pub range: Range<usize>,
+}
+impl SourceFileRange {
+    /// Attempts to get the text from the source file. This can fail if the source text isn't
+    /// loaded.
+    pub fn as_str(&self) -> Option<&str> {
+        self.sf.src.as_ref().and_then(|x| x.get(self.range.clone()))
+    }
+}
+
+/// Gets the source file, and range in the file, of the given span. Returns `None` if the span
+/// extends through multiple files, or is malformed.
+pub fn get_source_text(cx: &impl LintContext, sp: impl SpanRange) -> Option<SourceFileRange> {
+    fn f(sm: &SourceMap, sp: Range<BytePos>) -> Option<SourceFileRange> {
+        let start = sm.lookup_byte_offset(sp.start);
+        let end = sm.lookup_byte_offset(sp.end);
+        if !Lrc::ptr_eq(&start.sf, &end.sf) || start.pos > end.pos {
+            return None;
+        }
+        let range = start.pos.to_usize()..end.pos.to_usize();
+        Some(SourceFileRange { sf: start.sf, range })
+    }
+    f(cx.sess().source_map(), sp.into_range())
+}
 
 /// Like `snippet_block`, but add braces if the expr is not an `ExprKind::Block`.
 pub fn expr_block<T: LintContext>(
diff --git a/src/tools/clippy/rust-toolchain b/src/tools/clippy/rust-toolchain
index 60b8a5ac071..bc7fb711ed8 100644
--- a/src/tools/clippy/rust-toolchain
+++ b/src/tools/clippy/rust-toolchain
@@ -1,3 +1,3 @@
 [toolchain]
-channel = "nightly-2023-05-05"
+channel = "nightly-2023-05-20"
 components = ["cargo", "llvm-tools", "rust-src", "rust-std", "rustc", "rustc-dev", "rustfmt"]
diff --git a/src/tools/clippy/tests/ui-internal/custom_ice_message.rs b/src/tools/clippy/tests/ui-internal/custom_ice_message.rs
index acb98d7ba98..99ce7028390 100644
--- a/src/tools/clippy/tests/ui-internal/custom_ice_message.rs
+++ b/src/tools/clippy/tests/ui-internal/custom_ice_message.rs
@@ -3,6 +3,7 @@
 //@normalize-stderr-test: "produce_ice.rs:\d*:\d*" -> "produce_ice.rs"
 //@normalize-stderr-test: "', .*clippy_lints" -> "', clippy_lints"
 //@normalize-stderr-test: "'rustc'" -> "'<unnamed>'"
+//@normalize-stderr-test: "running on .*" -> "running on <target>"
 //@normalize-stderr-test: "(?ms)query stack during panic:\n.*end of query stack\n" -> ""
 
 #![deny(clippy::internal)]
diff --git a/src/tools/clippy/tests/ui-internal/custom_ice_message.stderr b/src/tools/clippy/tests/ui-internal/custom_ice_message.stderr
index b4619e980f3..0fc385cd693 100644
--- a/src/tools/clippy/tests/ui-internal/custom_ice_message.stderr
+++ b/src/tools/clippy/tests/ui-internal/custom_ice_message.stderr
@@ -1,12 +1,14 @@
 thread '<unnamed>' panicked at 'Would you like some help with that?', clippy_lints/src/utils/internal_lints/produce_ice.rs
 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
 
-error: internal compiler error: unexpected panic
-
-note: the compiler unexpectedly panicked. this is a bug.
+error: the compiler unexpectedly panicked. this is a bug.
 
 note: we would appreciate a bug report: https://github.com/rust-lang/rust-clippy/issues/new
 
+note: rustc 1.71.0-nightly (521f4dae1 2023-05-19) running on <target>
+
+note: compiler flags: -C prefer-dynamic -Z ui-testing
+
 note: Clippy version: foo
 
 thread panicked while panicking. aborting.
diff --git a/src/tools/clippy/tests/ui/arithmetic_side_effects.rs b/src/tools/clippy/tests/ui/arithmetic_side_effects.rs
index ab408bdf261..f95af1017bc 100644
--- a/src/tools/clippy/tests/ui/arithmetic_side_effects.rs
+++ b/src/tools/clippy/tests/ui/arithmetic_side_effects.rs
@@ -458,4 +458,12 @@ pub fn issue_10583(a: u16) -> u16 {
     10 / a
 }
 
+pub fn issue_10767() {
+    let n = &1.0;
+    n + n;
+    3.1_f32 + &1.2_f32;
+    &3.4_f32 + 1.5_f32;
+    &3.5_f32 + &1.3_f32;
+}
+
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/borrow_deref_ref.fixed b/src/tools/clippy/tests/ui/borrow_deref_ref.fixed
index 165e4bc8272..75526461792 100644
--- a/src/tools/clippy/tests/ui/borrow_deref_ref.fixed
+++ b/src/tools/clippy/tests/ui/borrow_deref_ref.fixed
@@ -1,7 +1,11 @@
 //@run-rustfix
+//@aux-build: proc_macros.rs
 
 #![allow(dead_code, unused_variables)]
 
+extern crate proc_macros;
+use proc_macros::with_span;
+
 fn main() {}
 
 mod should_lint {
@@ -47,6 +51,17 @@ mod should_not_lint2 {
     }
 }
 
+with_span!(
+    span
+
+    fn just_returning(x: &u32) -> &u32 {
+        x
+    }
+
+    fn dont_lint_proc_macro() {
+        let a = &mut &*just_returning(&12);
+    }
+);
 // this mod explains why we should not lint `& &* (&T)`
 mod false_negative {
     fn foo() {
diff --git a/src/tools/clippy/tests/ui/borrow_deref_ref.rs b/src/tools/clippy/tests/ui/borrow_deref_ref.rs
index 66c8d69bef9..e319d365f7e 100644
--- a/src/tools/clippy/tests/ui/borrow_deref_ref.rs
+++ b/src/tools/clippy/tests/ui/borrow_deref_ref.rs
@@ -1,7 +1,11 @@
 //@run-rustfix
+//@aux-build: proc_macros.rs
 
 #![allow(dead_code, unused_variables)]
 
+extern crate proc_macros;
+use proc_macros::with_span;
+
 fn main() {}
 
 mod should_lint {
@@ -47,6 +51,17 @@ mod should_not_lint2 {
     }
 }
 
+with_span!(
+    span
+
+    fn just_returning(x: &u32) -> &u32 {
+        x
+    }
+
+    fn dont_lint_proc_macro() {
+        let a = &mut &*just_returning(&12);
+    }
+);
 // this mod explains why we should not lint `& &* (&T)`
 mod false_negative {
     fn foo() {
diff --git a/src/tools/clippy/tests/ui/borrow_deref_ref.stderr b/src/tools/clippy/tests/ui/borrow_deref_ref.stderr
index d72de37c69f..1e47cda6796 100644
--- a/src/tools/clippy/tests/ui/borrow_deref_ref.stderr
+++ b/src/tools/clippy/tests/ui/borrow_deref_ref.stderr
@@ -1,5 +1,5 @@
 error: deref on an immutable reference
-  --> $DIR/borrow_deref_ref.rs:10:17
+  --> $DIR/borrow_deref_ref.rs:14:17
    |
 LL |         let b = &*a;
    |                 ^^^ help: if you would like to reborrow, try removing `&*`: `a`
@@ -7,13 +7,13 @@ LL |         let b = &*a;
    = note: `-D clippy::borrow-deref-ref` implied by `-D warnings`
 
 error: deref on an immutable reference
-  --> $DIR/borrow_deref_ref.rs:12:22
+  --> $DIR/borrow_deref_ref.rs:16:22
    |
 LL |         let b = &mut &*bar(&12);
    |                      ^^^^^^^^^^ help: if you would like to reborrow, try removing `&*`: `bar(&12)`
 
 error: deref on an immutable reference
-  --> $DIR/borrow_deref_ref.rs:55:23
+  --> $DIR/borrow_deref_ref.rs:70:23
    |
 LL |         let addr_y = &&*x as *const _ as usize; // assert ok
    |                       ^^^ help: if you would like to reborrow, try removing `&*`: `x`
diff --git a/src/tools/clippy/tests/ui/box_default.fixed b/src/tools/clippy/tests/ui/box_default.fixed
index e6331290420..840902b5323 100644
--- a/src/tools/clippy/tests/ui/box_default.fixed
+++ b/src/tools/clippy/tests/ui/box_default.fixed
@@ -35,6 +35,13 @@ fn main() {
     let _more = ret_ty_fn();
     call_ty_fn(Box::default());
     issue_10381();
+
+    // `Box::<Option<_>>::default()` would be valid here, but not `Box::default()` or
+    // `Box::<Option<[closure@...]>::default()`
+    //
+    // Would have a suggestion after https://github.com/rust-lang/rust/blob/fdd030127cc68afec44a8d3f6341525dd34e50ae/compiler/rustc_middle/src/ty/diagnostics.rs#L554-L563
+    let mut unnameable = Box::new(Option::default());
+    let _ = unnameable.insert(|| {});
 }
 
 fn ret_ty_fn() -> Box<bool> {
diff --git a/src/tools/clippy/tests/ui/box_default.rs b/src/tools/clippy/tests/ui/box_default.rs
index 34a05a29c5a..3618486a473 100644
--- a/src/tools/clippy/tests/ui/box_default.rs
+++ b/src/tools/clippy/tests/ui/box_default.rs
@@ -35,6 +35,13 @@ fn main() {
     let _more = ret_ty_fn();
     call_ty_fn(Box::new(u8::default()));
     issue_10381();
+
+    // `Box::<Option<_>>::default()` would be valid here, but not `Box::default()` or
+    // `Box::<Option<[closure@...]>::default()`
+    //
+    // Would have a suggestion after https://github.com/rust-lang/rust/blob/fdd030127cc68afec44a8d3f6341525dd34e50ae/compiler/rustc_middle/src/ty/diagnostics.rs#L554-L563
+    let mut unnameable = Box::new(Option::default());
+    let _ = unnameable.insert(|| {});
 }
 
 fn ret_ty_fn() -> Box<bool> {
diff --git a/src/tools/clippy/tests/ui/box_default.stderr b/src/tools/clippy/tests/ui/box_default.stderr
index c9834863601..13dfc5ae48a 100644
--- a/src/tools/clippy/tests/ui/box_default.stderr
+++ b/src/tools/clippy/tests/ui/box_default.stderr
@@ -73,25 +73,25 @@ LL |     call_ty_fn(Box::new(u8::default()));
    |                ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::default()`
 
 error: `Box::new(_)` of default value
-  --> $DIR/box_default.rs:41:5
+  --> $DIR/box_default.rs:48:5
    |
 LL |     Box::new(bool::default())
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::<bool>::default()`
 
 error: `Box::new(_)` of default value
-  --> $DIR/box_default.rs:58:28
+  --> $DIR/box_default.rs:65:28
    |
 LL |     let _: Box<dyn Read> = Box::new(ImplementsDefault::default());
    |                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::<ImplementsDefault>::default()`
 
 error: `Box::new(_)` of default value
-  --> $DIR/box_default.rs:67:17
+  --> $DIR/box_default.rs:74:17
    |
 LL |         let _ = Box::new(WeirdPathed::default());
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::<WeirdPathed>::default()`
 
 error: `Box::new(_)` of default value
-  --> $DIR/box_default.rs:79:18
+  --> $DIR/box_default.rs:86:18
    |
 LL |             Some(Box::new(Foo::default()))
    |                  ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::<Foo>::default()`
diff --git a/src/tools/clippy/tests/ui/collapsible_if.fixed b/src/tools/clippy/tests/ui/collapsible_if.fixed
index d2aba2ac59b..c6514a55934 100644
--- a/src/tools/clippy/tests/ui/collapsible_if.fixed
+++ b/src/tools/clippy/tests/ui/collapsible_if.fixed
@@ -1,5 +1,10 @@
 //@run-rustfix
-#![allow(clippy::assertions_on_constants, clippy::equatable_if_let)]
+#![allow(
+    clippy::assertions_on_constants,
+    clippy::equatable_if_let,
+    clippy::nonminimal_bool,
+    clippy::eq_op
+)]
 
 #[rustfmt::skip]
 #[warn(clippy::collapsible_if)]
diff --git a/src/tools/clippy/tests/ui/collapsible_if.rs b/src/tools/clippy/tests/ui/collapsible_if.rs
index e0bef7f9c97..2c85b68df63 100644
--- a/src/tools/clippy/tests/ui/collapsible_if.rs
+++ b/src/tools/clippy/tests/ui/collapsible_if.rs
@@ -1,5 +1,10 @@
 //@run-rustfix
-#![allow(clippy::assertions_on_constants, clippy::equatable_if_let)]
+#![allow(
+    clippy::assertions_on_constants,
+    clippy::equatable_if_let,
+    clippy::nonminimal_bool,
+    clippy::eq_op
+)]
 
 #[rustfmt::skip]
 #[warn(clippy::collapsible_if)]
diff --git a/src/tools/clippy/tests/ui/collapsible_if.stderr b/src/tools/clippy/tests/ui/collapsible_if.stderr
index 6327444df21..c687bae1acc 100644
--- a/src/tools/clippy/tests/ui/collapsible_if.stderr
+++ b/src/tools/clippy/tests/ui/collapsible_if.stderr
@@ -1,5 +1,5 @@
 error: this `if` statement can be collapsed
-  --> $DIR/collapsible_if.rs:9:5
+  --> $DIR/collapsible_if.rs:14:5
    |
 LL | /     if x == "hello" {
 LL | |         if y == "world" {
@@ -17,7 +17,7 @@ LL +     }
    |
 
 error: this `if` statement can be collapsed
-  --> $DIR/collapsible_if.rs:15:5
+  --> $DIR/collapsible_if.rs:20:5
    |
 LL | /     if x == "hello" || x == "world" {
 LL | |         if y == "world" || y == "hello" {
@@ -34,7 +34,7 @@ LL +     }
    |
 
 error: this `if` statement can be collapsed
-  --> $DIR/collapsible_if.rs:21:5
+  --> $DIR/collapsible_if.rs:26:5
    |
 LL | /     if x == "hello" && x == "world" {
 LL | |         if y == "world" || y == "hello" {
@@ -51,7 +51,7 @@ LL +     }
    |
 
 error: this `if` statement can be collapsed
-  --> $DIR/collapsible_if.rs:27:5
+  --> $DIR/collapsible_if.rs:32:5
    |
 LL | /     if x == "hello" || x == "world" {
 LL | |         if y == "world" && y == "hello" {
@@ -68,7 +68,7 @@ LL +     }
    |
 
 error: this `if` statement can be collapsed
-  --> $DIR/collapsible_if.rs:33:5
+  --> $DIR/collapsible_if.rs:38:5
    |
 LL | /     if x == "hello" && x == "world" {
 LL | |         if y == "world" && y == "hello" {
@@ -85,7 +85,7 @@ LL +     }
    |
 
 error: this `if` statement can be collapsed
-  --> $DIR/collapsible_if.rs:39:5
+  --> $DIR/collapsible_if.rs:44:5
    |
 LL | /     if 42 == 1337 {
 LL | |         if 'a' != 'A' {
@@ -102,7 +102,7 @@ LL +     }
    |
 
 error: this `if` statement can be collapsed
-  --> $DIR/collapsible_if.rs:95:5
+  --> $DIR/collapsible_if.rs:100:5
    |
 LL | /     if x == "hello" {
 LL | |         if y == "world" { // Collapsible
@@ -119,7 +119,7 @@ LL +     }
    |
 
 error: this `if` statement can be collapsed
-  --> $DIR/collapsible_if.rs:154:5
+  --> $DIR/collapsible_if.rs:159:5
    |
 LL | /     if matches!(true, true) {
 LL | |         if matches!(true, true) {}
@@ -127,7 +127,7 @@ LL | |     }
    | |_____^ help: collapse nested if block: `if matches!(true, true) && matches!(true, true) {}`
 
 error: this `if` statement can be collapsed
-  --> $DIR/collapsible_if.rs:159:5
+  --> $DIR/collapsible_if.rs:164:5
    |
 LL | /     if matches!(true, true) && truth() {
 LL | |         if matches!(true, true) {}
diff --git a/src/tools/clippy/tests/ui/dbg_macro.rs b/src/tools/clippy/tests/ui/dbg_macro.rs
index 8701e3cd29f..10788d40481 100644
--- a/src/tools/clippy/tests/ui/dbg_macro.rs
+++ b/src/tools/clippy/tests/ui/dbg_macro.rs
@@ -4,6 +4,7 @@
 fn foo(n: u32) -> u32 {
     if let Some(n) = dbg!(n.checked_sub(4)) { n } else { n }
 }
+fn bar(_: ()) {}
 
 fn factorial(n: u32) -> u32 {
     if dbg!(n <= 1) {
@@ -21,6 +22,32 @@ fn main() {
     dbg!(1, 2, 3, 4, 5);
 }
 
+fn issue9914() {
+    macro_rules! foo {
+        ($x:expr) => {
+            $x;
+        };
+    }
+    macro_rules! foo2 {
+        ($x:expr) => {
+            $x;
+        };
+    }
+    macro_rules! expand_to_dbg {
+        () => {
+            dbg!();
+        };
+    }
+
+    dbg!();
+    #[allow(clippy::let_unit_value)]
+    let _ = dbg!();
+    bar(dbg!());
+    foo!(dbg!());
+    foo2!(foo!(dbg!()));
+    expand_to_dbg!();
+}
+
 mod issue7274 {
     trait Thing<'b> {
         fn foo(&self);
diff --git a/src/tools/clippy/tests/ui/dbg_macro.stderr b/src/tools/clippy/tests/ui/dbg_macro.stderr
index ddb5f1342e9..530e7663317 100644
--- a/src/tools/clippy/tests/ui/dbg_macro.stderr
+++ b/src/tools/clippy/tests/ui/dbg_macro.stderr
@@ -11,7 +11,7 @@ LL |     if let Some(n) = n.checked_sub(4) { n } else { n }
    |                      ~~~~~~~~~~~~~~~~
 
 error: the `dbg!` macro is intended as a debugging tool
-  --> $DIR/dbg_macro.rs:9:8
+  --> $DIR/dbg_macro.rs:10:8
    |
 LL |     if dbg!(n <= 1) {
    |        ^^^^^^^^^^^^
@@ -22,7 +22,7 @@ LL |     if n <= 1 {
    |        ~~~~~~
 
 error: the `dbg!` macro is intended as a debugging tool
-  --> $DIR/dbg_macro.rs:10:9
+  --> $DIR/dbg_macro.rs:11:9
    |
 LL |         dbg!(1)
    |         ^^^^^^^
@@ -33,7 +33,7 @@ LL |         1
    |
 
 error: the `dbg!` macro is intended as a debugging tool
-  --> $DIR/dbg_macro.rs:12:9
+  --> $DIR/dbg_macro.rs:13:9
    |
 LL |         dbg!(n * factorial(n - 1))
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -44,7 +44,7 @@ LL |         n * factorial(n - 1)
    |
 
 error: the `dbg!` macro is intended as a debugging tool
-  --> $DIR/dbg_macro.rs:17:5
+  --> $DIR/dbg_macro.rs:18:5
    |
 LL |     dbg!(42);
    |     ^^^^^^^^
@@ -55,7 +55,7 @@ LL |     42;
    |     ~~
 
 error: the `dbg!` macro is intended as a debugging tool
-  --> $DIR/dbg_macro.rs:18:5
+  --> $DIR/dbg_macro.rs:19:5
    |
 LL |     dbg!(dbg!(dbg!(42)));
    |     ^^^^^^^^^^^^^^^^^^^^
@@ -66,7 +66,7 @@ LL |     dbg!(dbg!(42));
    |     ~~~~~~~~~~~~~~
 
 error: the `dbg!` macro is intended as a debugging tool
-  --> $DIR/dbg_macro.rs:19:14
+  --> $DIR/dbg_macro.rs:20:14
    |
 LL |     foo(3) + dbg!(factorial(4));
    |              ^^^^^^^^^^^^^^^^^^
@@ -77,7 +77,7 @@ LL |     foo(3) + factorial(4);
    |              ~~~~~~~~~~~~
 
 error: the `dbg!` macro is intended as a debugging tool
-  --> $DIR/dbg_macro.rs:20:5
+  --> $DIR/dbg_macro.rs:21:5
    |
 LL |     dbg!(1, 2, dbg!(3, 4));
    |     ^^^^^^^^^^^^^^^^^^^^^^
@@ -88,7 +88,7 @@ LL |     (1, 2, dbg!(3, 4));
    |     ~~~~~~~~~~~~~~~~~~
 
 error: the `dbg!` macro is intended as a debugging tool
-  --> $DIR/dbg_macro.rs:21:5
+  --> $DIR/dbg_macro.rs:22:5
    |
 LL |     dbg!(1, 2, 3, 4, 5);
    |     ^^^^^^^^^^^^^^^^^^^
@@ -99,7 +99,63 @@ LL |     (1, 2, 3, 4, 5);
    |     ~~~~~~~~~~~~~~~
 
 error: the `dbg!` macro is intended as a debugging tool
-  --> $DIR/dbg_macro.rs:41:9
+  --> $DIR/dbg_macro.rs:42:5
+   |
+LL |     dbg!();
+   |     ^^^^^^^
+   |
+help: remove the invocation before committing it to a version control system
+   |
+LL -     dbg!();
+LL +     
+   |
+
+error: the `dbg!` macro is intended as a debugging tool
+  --> $DIR/dbg_macro.rs:44:13
+   |
+LL |     let _ = dbg!();
+   |             ^^^^^^
+   |
+help: remove the invocation before committing it to a version control system
+   |
+LL |     let _ = ();
+   |             ~~
+
+error: the `dbg!` macro is intended as a debugging tool
+  --> $DIR/dbg_macro.rs:45:9
+   |
+LL |     bar(dbg!());
+   |         ^^^^^^
+   |
+help: remove the invocation before committing it to a version control system
+   |
+LL |     bar(());
+   |         ~~
+
+error: the `dbg!` macro is intended as a debugging tool
+  --> $DIR/dbg_macro.rs:46:10
+   |
+LL |     foo!(dbg!());
+   |          ^^^^^^
+   |
+help: remove the invocation before committing it to a version control system
+   |
+LL |     foo!(());
+   |          ~~
+
+error: the `dbg!` macro is intended as a debugging tool
+  --> $DIR/dbg_macro.rs:47:16
+   |
+LL |     foo2!(foo!(dbg!()));
+   |                ^^^^^^
+   |
+help: remove the invocation before committing it to a version control system
+   |
+LL |     foo2!(foo!(()));
+   |                ~~
+
+error: the `dbg!` macro is intended as a debugging tool
+  --> $DIR/dbg_macro.rs:68:9
    |
 LL |         dbg!(2);
    |         ^^^^^^^
@@ -110,7 +166,7 @@ LL |         2;
    |         ~
 
 error: the `dbg!` macro is intended as a debugging tool
-  --> $DIR/dbg_macro.rs:47:5
+  --> $DIR/dbg_macro.rs:74:5
    |
 LL |     dbg!(1);
    |     ^^^^^^^
@@ -121,7 +177,7 @@ LL |     1;
    |     ~
 
 error: the `dbg!` macro is intended as a debugging tool
-  --> $DIR/dbg_macro.rs:52:5
+  --> $DIR/dbg_macro.rs:79:5
    |
 LL |     dbg!(1);
    |     ^^^^^^^
@@ -132,7 +188,7 @@ LL |     1;
    |     ~
 
 error: the `dbg!` macro is intended as a debugging tool
-  --> $DIR/dbg_macro.rs:58:9
+  --> $DIR/dbg_macro.rs:85:9
    |
 LL |         dbg!(1);
    |         ^^^^^^^
@@ -142,5 +198,5 @@ help: remove the invocation before committing it to a version control system
 LL |         1;
    |         ~
 
-error: aborting due to 13 previous errors
+error: aborting due to 18 previous errors
 
diff --git a/src/tools/clippy/tests/ui/default_constructed_unit_structs.fixed b/src/tools/clippy/tests/ui/default_constructed_unit_structs.fixed
index 4c2d1ea48e1..e1012f38bba 100644
--- a/src/tools/clippy/tests/ui/default_constructed_unit_structs.fixed
+++ b/src/tools/clippy/tests/ui/default_constructed_unit_structs.fixed
@@ -105,6 +105,7 @@ fn main() {
     // should lint
     let _ = PhantomData::<usize>;
     let _: PhantomData<i32> = PhantomData;
+    let _: PhantomData<i32> = std::marker::PhantomData;
     let _ = UnitStruct;
 
     // should not lint
@@ -116,4 +117,21 @@ fn main() {
     let _ = EmptyStruct::default();
     let _ = FakeDefault::default();
     let _ = <FakeDefault as Default>::default();
+
+    macro_rules! in_macro {
+        ($i:ident) => {{
+            let _ = UnitStruct::default();
+            let _ = $i::default();
+        }};
+    }
+
+    in_macro!(UnitStruct);
+
+    macro_rules! struct_from_macro {
+        () => {
+            UnitStruct
+        };
+    }
+
+    let _ = <struct_from_macro!()>::default();
 }
diff --git a/src/tools/clippy/tests/ui/default_constructed_unit_structs.rs b/src/tools/clippy/tests/ui/default_constructed_unit_structs.rs
index 850793dd5de..c7b4313dbf0 100644
--- a/src/tools/clippy/tests/ui/default_constructed_unit_structs.rs
+++ b/src/tools/clippy/tests/ui/default_constructed_unit_structs.rs
@@ -105,6 +105,7 @@ fn main() {
     // should lint
     let _ = PhantomData::<usize>::default();
     let _: PhantomData<i32> = PhantomData::default();
+    let _: PhantomData<i32> = std::marker::PhantomData::default();
     let _ = UnitStruct::default();
 
     // should not lint
@@ -116,4 +117,21 @@ fn main() {
     let _ = EmptyStruct::default();
     let _ = FakeDefault::default();
     let _ = <FakeDefault as Default>::default();
+
+    macro_rules! in_macro {
+        ($i:ident) => {{
+            let _ = UnitStruct::default();
+            let _ = $i::default();
+        }};
+    }
+
+    in_macro!(UnitStruct);
+
+    macro_rules! struct_from_macro {
+        () => {
+            UnitStruct
+        };
+    }
+
+    let _ = <struct_from_macro!()>::default();
 }
diff --git a/src/tools/clippy/tests/ui/default_constructed_unit_structs.stderr b/src/tools/clippy/tests/ui/default_constructed_unit_structs.stderr
index 4058943d087..61a32fb10e5 100644
--- a/src/tools/clippy/tests/ui/default_constructed_unit_structs.stderr
+++ b/src/tools/clippy/tests/ui/default_constructed_unit_structs.stderr
@@ -25,10 +25,16 @@ LL |     let _: PhantomData<i32> = PhantomData::default();
    |                                          ^^^^^^^^^^^ help: remove this call to `default`
 
 error: use of `default` to create a unit struct
-  --> $DIR/default_constructed_unit_structs.rs:108:23
+  --> $DIR/default_constructed_unit_structs.rs:108:55
+   |
+LL |     let _: PhantomData<i32> = std::marker::PhantomData::default();
+   |                                                       ^^^^^^^^^^^ help: remove this call to `default`
+
+error: use of `default` to create a unit struct
+  --> $DIR/default_constructed_unit_structs.rs:109:23
    |
 LL |     let _ = UnitStruct::default();
    |                       ^^^^^^^^^^^ help: remove this call to `default`
 
-error: aborting due to 5 previous errors
+error: aborting due to 6 previous errors
 
diff --git a/src/tools/clippy/tests/ui/diverging_sub_expression.stderr b/src/tools/clippy/tests/ui/diverging_sub_expression.stderr
index 9c91d935716..51a3b0d972e 100644
--- a/src/tools/clippy/tests/ui/diverging_sub_expression.stderr
+++ b/src/tools/clippy/tests/ui/diverging_sub_expression.stderr
@@ -31,18 +31,10 @@ LL |             3 => true || diverge(),
    |                          ^^^^^^^^^
 
 error: sub-expression diverges
-  --> $DIR/diverging_sub_expression.rs:36:30
-   |
-LL |                 _ => true || panic!("boo"),
-   |                              ^^^^^^^^^^^^^
-   |
-   = note: this error originates in the macro `$crate::panic::panic_2021` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info)
-
-error: sub-expression diverges
   --> $DIR/diverging_sub_expression.rs:38:26
    |
 LL |             _ => true || break,
    |                          ^^^^^
 
-error: aborting due to 7 previous errors
+error: aborting due to 6 previous errors
 
diff --git a/src/tools/clippy/tests/ui/drop_forget_copy.rs b/src/tools/clippy/tests/ui/drop_forget_copy.rs
deleted file mode 100644
index a7276dd59f4..00000000000
--- a/src/tools/clippy/tests/ui/drop_forget_copy.rs
+++ /dev/null
@@ -1,86 +0,0 @@
-#![warn(clippy::drop_copy, clippy::forget_copy)]
-#![allow(clippy::toplevel_ref_arg, clippy::drop_ref, clippy::forget_ref, unused_mut)]
-
-use std::mem::{drop, forget};
-use std::vec::Vec;
-
-#[derive(Copy, Clone)]
-struct SomeStruct;
-
-struct AnotherStruct {
-    x: u8,
-    y: u8,
-    z: Vec<u8>,
-}
-
-impl Clone for AnotherStruct {
-    fn clone(&self) -> AnotherStruct {
-        AnotherStruct {
-            x: self.x,
-            y: self.y,
-            z: self.z.clone(),
-        }
-    }
-}
-
-fn main() {
-    let s1 = SomeStruct {};
-    let s2 = s1;
-    let s3 = &s1;
-    let mut s4 = s1;
-    let ref s5 = s1;
-
-    drop(s1);
-    drop(s2);
-    drop(s3);
-    drop(s4);
-    drop(s5);
-
-    forget(s1);
-    forget(s2);
-    forget(s3);
-    forget(s4);
-    forget(s5);
-
-    let a1 = AnotherStruct {
-        x: 255,
-        y: 0,
-        z: vec![1, 2, 3],
-    };
-    let a2 = &a1;
-    let mut a3 = a1.clone();
-    let ref a4 = a1;
-    let a5 = a1.clone();
-
-    drop(a2);
-    drop(a3);
-    drop(a4);
-    drop(a5);
-
-    forget(a2);
-    let a3 = &a1;
-    forget(a3);
-    forget(a4);
-    let a5 = a1.clone();
-    forget(a5);
-}
-
-#[allow(unused)]
-#[allow(clippy::unit_cmp)]
-fn issue9482(x: u8) {
-    fn println_and<T>(t: T) -> T {
-        println!("foo");
-        t
-    }
-
-    match x {
-        0 => drop(println_and(12)), // Don't lint (copy type), we only care about side-effects
-        1 => drop(println_and(String::new())), // Don't lint (no copy type), we only care about side-effects
-        2 => {
-            drop(println_and(13)); // Lint, even if we only care about the side-effect, it's already in a block
-        },
-        3 if drop(println_and(14)) == () => (), // Lint, idiomatic use is only in body of `Arm`
-        4 => drop(2),                           // Lint, not a fn/method call
-        _ => (),
-    }
-}
diff --git a/src/tools/clippy/tests/ui/drop_forget_copy.stderr b/src/tools/clippy/tests/ui/drop_forget_copy.stderr
deleted file mode 100644
index 90bef1c3c43..00000000000
--- a/src/tools/clippy/tests/ui/drop_forget_copy.stderr
+++ /dev/null
@@ -1,112 +0,0 @@
-error: calls to `std::mem::drop` with a value that implements `Copy`. Dropping a copy leaves the original intact
-  --> $DIR/drop_forget_copy.rs:33:5
-   |
-LL |     drop(s1);
-   |     ^^^^^^^^
-   |
-note: argument has type `SomeStruct`
-  --> $DIR/drop_forget_copy.rs:33:10
-   |
-LL |     drop(s1);
-   |          ^^
-   = note: `-D clippy::drop-copy` implied by `-D warnings`
-
-error: calls to `std::mem::drop` with a value that implements `Copy`. Dropping a copy leaves the original intact
-  --> $DIR/drop_forget_copy.rs:34:5
-   |
-LL |     drop(s2);
-   |     ^^^^^^^^
-   |
-note: argument has type `SomeStruct`
-  --> $DIR/drop_forget_copy.rs:34:10
-   |
-LL |     drop(s2);
-   |          ^^
-
-error: calls to `std::mem::drop` with a value that implements `Copy`. Dropping a copy leaves the original intact
-  --> $DIR/drop_forget_copy.rs:36:5
-   |
-LL |     drop(s4);
-   |     ^^^^^^^^
-   |
-note: argument has type `SomeStruct`
-  --> $DIR/drop_forget_copy.rs:36:10
-   |
-LL |     drop(s4);
-   |          ^^
-
-error: calls to `std::mem::forget` with a value that implements `Copy`. Forgetting a copy leaves the original intact
-  --> $DIR/drop_forget_copy.rs:39:5
-   |
-LL |     forget(s1);
-   |     ^^^^^^^^^^
-   |
-note: argument has type `SomeStruct`
-  --> $DIR/drop_forget_copy.rs:39:12
-   |
-LL |     forget(s1);
-   |            ^^
-   = note: `-D clippy::forget-copy` implied by `-D warnings`
-
-error: calls to `std::mem::forget` with a value that implements `Copy`. Forgetting a copy leaves the original intact
-  --> $DIR/drop_forget_copy.rs:40:5
-   |
-LL |     forget(s2);
-   |     ^^^^^^^^^^
-   |
-note: argument has type `SomeStruct`
-  --> $DIR/drop_forget_copy.rs:40:12
-   |
-LL |     forget(s2);
-   |            ^^
-
-error: calls to `std::mem::forget` with a value that implements `Copy`. Forgetting a copy leaves the original intact
-  --> $DIR/drop_forget_copy.rs:42:5
-   |
-LL |     forget(s4);
-   |     ^^^^^^^^^^
-   |
-note: argument has type `SomeStruct`
-  --> $DIR/drop_forget_copy.rs:42:12
-   |
-LL |     forget(s4);
-   |            ^^
-
-error: calls to `std::mem::drop` with a value that implements `Copy`. Dropping a copy leaves the original intact
-  --> $DIR/drop_forget_copy.rs:80:13
-   |
-LL |             drop(println_and(13)); // Lint, even if we only care about the side-effect, it's already in a block
-   |             ^^^^^^^^^^^^^^^^^^^^^
-   |
-note: argument has type `i32`
-  --> $DIR/drop_forget_copy.rs:80:18
-   |
-LL |             drop(println_and(13)); // Lint, even if we only care about the side-effect, it's already in a block
-   |                  ^^^^^^^^^^^^^^^
-
-error: calls to `std::mem::drop` with a value that implements `Copy`. Dropping a copy leaves the original intact
-  --> $DIR/drop_forget_copy.rs:82:14
-   |
-LL |         3 if drop(println_and(14)) == () => (), // Lint, idiomatic use is only in body of `Arm`
-   |              ^^^^^^^^^^^^^^^^^^^^^
-   |
-note: argument has type `i32`
-  --> $DIR/drop_forget_copy.rs:82:19
-   |
-LL |         3 if drop(println_and(14)) == () => (), // Lint, idiomatic use is only in body of `Arm`
-   |                   ^^^^^^^^^^^^^^^
-
-error: calls to `std::mem::drop` with a value that implements `Copy`. Dropping a copy leaves the original intact
-  --> $DIR/drop_forget_copy.rs:83:14
-   |
-LL |         4 => drop(2),                           // Lint, not a fn/method call
-   |              ^^^^^^^
-   |
-note: argument has type `i32`
-  --> $DIR/drop_forget_copy.rs:83:19
-   |
-LL |         4 => drop(2),                           // Lint, not a fn/method call
-   |                   ^
-
-error: aborting due to 9 previous errors
-
diff --git a/src/tools/clippy/tests/ui/drop_ref.stderr b/src/tools/clippy/tests/ui/drop_ref.stderr
deleted file mode 100644
index 293b9f6de83..00000000000
--- a/src/tools/clippy/tests/ui/drop_ref.stderr
+++ /dev/null
@@ -1,147 +0,0 @@
-error: calls to `std::mem::drop` with a reference instead of an owned value. Dropping a reference does nothing
-  --> $DIR/drop_ref.rs:11:5
-   |
-LL |     drop(&SomeStruct);
-   |     ^^^^^^^^^^^^^^^^^
-   |
-note: argument has type `&SomeStruct`
-  --> $DIR/drop_ref.rs:11:10
-   |
-LL |     drop(&SomeStruct);
-   |          ^^^^^^^^^^^
-   = note: `-D clippy::drop-ref` implied by `-D warnings`
-
-error: calls to `std::mem::drop` with a reference instead of an owned value. Dropping a reference does nothing
-  --> $DIR/drop_ref.rs:14:5
-   |
-LL |     drop(&owned1);
-   |     ^^^^^^^^^^^^^
-   |
-note: argument has type `&SomeStruct`
-  --> $DIR/drop_ref.rs:14:10
-   |
-LL |     drop(&owned1);
-   |          ^^^^^^^
-
-error: calls to `std::mem::drop` with a reference instead of an owned value. Dropping a reference does nothing
-  --> $DIR/drop_ref.rs:15:5
-   |
-LL |     drop(&&owned1);
-   |     ^^^^^^^^^^^^^^
-   |
-note: argument has type `&&SomeStruct`
-  --> $DIR/drop_ref.rs:15:10
-   |
-LL |     drop(&&owned1);
-   |          ^^^^^^^^
-
-error: calls to `std::mem::drop` with a reference instead of an owned value. Dropping a reference does nothing
-  --> $DIR/drop_ref.rs:16:5
-   |
-LL |     drop(&mut owned1);
-   |     ^^^^^^^^^^^^^^^^^
-   |
-note: argument has type `&mut SomeStruct`
-  --> $DIR/drop_ref.rs:16:10
-   |
-LL |     drop(&mut owned1);
-   |          ^^^^^^^^^^^
-
-error: calls to `std::mem::drop` with a reference instead of an owned value. Dropping a reference does nothing
-  --> $DIR/drop_ref.rs:20:5
-   |
-LL |     drop(reference1);
-   |     ^^^^^^^^^^^^^^^^
-   |
-note: argument has type `&SomeStruct`
-  --> $DIR/drop_ref.rs:20:10
-   |
-LL |     drop(reference1);
-   |          ^^^^^^^^^^
-
-error: calls to `std::mem::drop` with a reference instead of an owned value. Dropping a reference does nothing
-  --> $DIR/drop_ref.rs:23:5
-   |
-LL |     drop(reference2);
-   |     ^^^^^^^^^^^^^^^^
-   |
-note: argument has type `&mut SomeStruct`
-  --> $DIR/drop_ref.rs:23:10
-   |
-LL |     drop(reference2);
-   |          ^^^^^^^^^^
-
-error: calls to `std::mem::drop` with a reference instead of an owned value. Dropping a reference does nothing
-  --> $DIR/drop_ref.rs:26:5
-   |
-LL |     drop(reference3);
-   |     ^^^^^^^^^^^^^^^^
-   |
-note: argument has type `&SomeStruct`
-  --> $DIR/drop_ref.rs:26:10
-   |
-LL |     drop(reference3);
-   |          ^^^^^^^^^^
-
-error: calls to `std::mem::drop` with a reference instead of an owned value. Dropping a reference does nothing
-  --> $DIR/drop_ref.rs:31:5
-   |
-LL |     drop(&val);
-   |     ^^^^^^^^^^
-   |
-note: argument has type `&T`
-  --> $DIR/drop_ref.rs:31:10
-   |
-LL |     drop(&val);
-   |          ^^^^
-
-error: calls to `std::mem::drop` with a reference instead of an owned value. Dropping a reference does nothing
-  --> $DIR/drop_ref.rs:39:5
-   |
-LL |     std::mem::drop(&SomeStruct);
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-note: argument has type `&SomeStruct`
-  --> $DIR/drop_ref.rs:39:20
-   |
-LL |     std::mem::drop(&SomeStruct);
-   |                    ^^^^^^^^^^^
-
-error: calls to `std::mem::drop` with a reference instead of an owned value. Dropping a reference does nothing
-  --> $DIR/drop_ref.rs:91:13
-   |
-LL |             drop(println_and(&13)); // Lint, even if we only care about the side-effect, it's already in a block
-   |             ^^^^^^^^^^^^^^^^^^^^^^
-   |
-note: argument has type `&i32`
-  --> $DIR/drop_ref.rs:91:18
-   |
-LL |             drop(println_and(&13)); // Lint, even if we only care about the side-effect, it's already in a block
-   |                  ^^^^^^^^^^^^^^^^
-
-error: calls to `std::mem::drop` with a reference instead of an owned value. Dropping a reference does nothing
-  --> $DIR/drop_ref.rs:93:14
-   |
-LL |         3 if drop(println_and(&14)) == () => (), // Lint, idiomatic use is only in body of `Arm`
-   |              ^^^^^^^^^^^^^^^^^^^^^^
-   |
-note: argument has type `&i32`
-  --> $DIR/drop_ref.rs:93:19
-   |
-LL |         3 if drop(println_and(&14)) == () => (), // Lint, idiomatic use is only in body of `Arm`
-   |                   ^^^^^^^^^^^^^^^^
-
-error: calls to `std::mem::drop` with a reference instead of an owned value. Dropping a reference does nothing
-  --> $DIR/drop_ref.rs:94:14
-   |
-LL |         4 => drop(&2),                           // Lint, not a fn/method call
-   |              ^^^^^^^^
-   |
-note: argument has type `&i32`
-  --> $DIR/drop_ref.rs:94:19
-   |
-LL |         4 => drop(&2),                           // Lint, not a fn/method call
-   |                   ^^
-
-error: aborting due to 12 previous errors
-
diff --git a/src/tools/clippy/tests/ui/empty_line_after_doc_comments.rs b/src/tools/clippy/tests/ui/empty_line_after_doc_comments.rs
new file mode 100644
index 00000000000..e843770f578
--- /dev/null
+++ b/src/tools/clippy/tests/ui/empty_line_after_doc_comments.rs
@@ -0,0 +1,132 @@
+//@aux-build:proc_macro_attr.rs
+#![warn(clippy::empty_line_after_doc_comments)]
+#![allow(clippy::assertions_on_constants)]
+#![feature(custom_inner_attributes)]
+#![rustfmt::skip]
+
+#[macro_use]
+extern crate proc_macro_attr;
+
+mod some_mod {
+    //! This doc comment should *NOT* produce a warning
+
+    mod some_inner_mod {
+        fn some_noop() {}
+    }
+}
+
+/// This should produce a warning
+
+fn with_doc_and_newline() { assert!(true)}
+
+// This should *NOT* produce a warning
+#[crate_type = "lib"]
+
+/// some comment
+fn with_one_newline_and_comment() { assert!(true) }
+
+// This should *NOT* produce a warning
+#[crate_type = "lib"]
+/// some comment
+fn with_no_newline_and_comment() { assert!(true) }
+
+
+// This should *NOT* produce a warning
+#[crate_type = "lib"]
+
+fn with_one_newline() { assert!(true) }
+
+// This should *NOT* produce a warning
+#[crate_type = "lib"]
+
+
+fn with_two_newlines() { assert!(true) }
+
+
+// This should *NOT* produce a warning
+#[crate_type = "lib"]
+
+enum Baz {
+    One,
+    Two
+}
+
+// This should *NOT* produce a warning
+#[crate_type = "lib"]
+
+struct Foo {
+    one: isize,
+    two: isize
+}
+
+// This should *NOT* produce a warning
+#[crate_type = "lib"]
+
+mod foo {
+}
+
+/// This doc comment should produce a warning
+
+/** This is also a doc comment and should produce a warning
+ */
+
+// This should *NOT* produce a warning
+#[allow(non_camel_case_types)]
+#[allow(missing_docs)]
+#[allow(missing_docs)]
+fn three_attributes() { assert!(true) }
+
+// This should *NOT* produce a warning
+#[doc = "
+Returns the escaped value of the textual representation of
+
+"]
+pub fn function() -> bool {
+    true
+}
+
+// This should *NOT* produce a warning
+#[derive(Clone, Copy)]
+pub enum FooFighter {
+    Bar1,
+
+    Bar2,
+
+    Bar3,
+
+    Bar4
+}
+
+// This should *NOT* produce a warning because the empty line is inside a block comment
+#[crate_type = "lib"]
+/*
+
+*/
+pub struct S;
+
+// This should *NOT* produce a warning
+#[crate_type = "lib"]
+/* test */
+pub struct T;
+
+// This should *NOT* produce a warning
+// See https://github.com/rust-lang/rust-clippy/issues/5567
+#[fake_async_trait]
+pub trait Bazz {
+    fn foo() -> Vec<u8> {
+        let _i = "";
+
+
+
+        vec![]
+    }
+}
+
+#[derive(Clone, Copy)]
+#[dummy(string = "first line
+
+second line
+")]
+pub struct Args;
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui/empty_line_after_doc_comments.stderr b/src/tools/clippy/tests/ui/empty_line_after_doc_comments.stderr
new file mode 100644
index 00000000000..2ca1b51679e
--- /dev/null
+++ b/src/tools/clippy/tests/ui/empty_line_after_doc_comments.stderr
@@ -0,0 +1,36 @@
+error: found an empty line after a doc comment. Perhaps you need to use `//!` to make a comment on a module, remove the empty line, or make a regular comment with `//`?
+  --> $DIR/empty_line_after_doc_comments.rs:18:1
+   |
+LL | / /// This should produce a warning
+LL | |
+LL | | fn with_doc_and_newline() { assert!(true)}
+   | |_
+   |
+   = note: `-D clippy::empty-line-after-doc-comments` implied by `-D warnings`
+
+error: found an empty line after a doc comment. Perhaps you need to use `//!` to make a comment on a module, remove the empty line, or make a regular comment with `//`?
+  --> $DIR/empty_line_after_doc_comments.rs:68:1
+   |
+LL | / /// This doc comment should produce a warning
+LL | |
+LL | | /** This is also a doc comment and should produce a warning
+LL | |  */
+...  |
+LL | | #[allow(missing_docs)]
+LL | | fn three_attributes() { assert!(true) }
+   | |_
+
+error: found an empty line after a doc comment. Perhaps you need to use `//!` to make a comment on a module, remove the empty line, or make a regular comment with `//`?
+  --> $DIR/empty_line_after_doc_comments.rs:70:1
+   |
+LL | / /** This is also a doc comment and should produce a warning
+LL | |  */
+LL | |
+LL | | // This should *NOT* produce a warning
+...  |
+LL | | #[allow(missing_docs)]
+LL | | fn three_attributes() { assert!(true) }
+   | |_
+
+error: aborting due to 3 previous errors
+
diff --git a/src/tools/clippy/tests/ui/float_arithmetic.rs b/src/tools/clippy/tests/ui/float_arithmetic.rs
index 60fa7569eb9..a928c35e8bc 100644
--- a/src/tools/clippy/tests/ui/float_arithmetic.rs
+++ b/src/tools/clippy/tests/ui/float_arithmetic.rs
@@ -1,4 +1,4 @@
-#![warn(clippy::integer_arithmetic, clippy::float_arithmetic)]
+#![warn(clippy::arithmetic_side_effects, clippy::float_arithmetic)]
 #![allow(
     unused,
     clippy::shadow_reuse,
diff --git a/src/tools/clippy/tests/ui/forget_ref.rs b/src/tools/clippy/tests/ui/forget_ref.rs
deleted file mode 100644
index 031b415f56f..00000000000
--- a/src/tools/clippy/tests/ui/forget_ref.rs
+++ /dev/null
@@ -1,50 +0,0 @@
-#![warn(clippy::forget_ref)]
-#![allow(clippy::toplevel_ref_arg)]
-#![allow(clippy::unnecessary_wraps, clippy::forget_non_drop)]
-#![allow(clippy::borrow_deref_ref)]
-
-use std::mem::forget;
-
-struct SomeStruct;
-
-fn main() {
-    forget(&SomeStruct);
-
-    let mut owned = SomeStruct;
-    forget(&owned);
-    forget(&&owned);
-    forget(&mut owned);
-    forget(owned); //OK
-
-    let reference1 = &SomeStruct;
-    forget(&*reference1);
-
-    let reference2 = &mut SomeStruct;
-    forget(reference2);
-
-    let ref reference3 = SomeStruct;
-    forget(reference3);
-}
-
-#[allow(dead_code)]
-fn test_generic_fn_forget<T>(val: T) {
-    forget(&val);
-    forget(val); //OK
-}
-
-#[allow(dead_code)]
-fn test_similarly_named_function() {
-    fn forget<T>(_val: T) {}
-    forget(&SomeStruct); //OK; call to unrelated function which happens to have the same name
-    std::mem::forget(&SomeStruct);
-}
-
-#[derive(Copy, Clone)]
-pub struct Error;
-fn produce_half_owl_error() -> Result<(), Error> {
-    Ok(())
-}
-
-fn produce_half_owl_ok() -> Result<bool, ()> {
-    Ok(true)
-}
diff --git a/src/tools/clippy/tests/ui/forget_ref.stderr b/src/tools/clippy/tests/ui/forget_ref.stderr
deleted file mode 100644
index 011cdefc665..00000000000
--- a/src/tools/clippy/tests/ui/forget_ref.stderr
+++ /dev/null
@@ -1,111 +0,0 @@
-error: calls to `std::mem::forget` with a reference instead of an owned value. Forgetting a reference does nothing
-  --> $DIR/forget_ref.rs:11:5
-   |
-LL |     forget(&SomeStruct);
-   |     ^^^^^^^^^^^^^^^^^^^
-   |
-note: argument has type `&SomeStruct`
-  --> $DIR/forget_ref.rs:11:12
-   |
-LL |     forget(&SomeStruct);
-   |            ^^^^^^^^^^^
-   = note: `-D clippy::forget-ref` implied by `-D warnings`
-
-error: calls to `std::mem::forget` with a reference instead of an owned value. Forgetting a reference does nothing
-  --> $DIR/forget_ref.rs:14:5
-   |
-LL |     forget(&owned);
-   |     ^^^^^^^^^^^^^^
-   |
-note: argument has type `&SomeStruct`
-  --> $DIR/forget_ref.rs:14:12
-   |
-LL |     forget(&owned);
-   |            ^^^^^^
-
-error: calls to `std::mem::forget` with a reference instead of an owned value. Forgetting a reference does nothing
-  --> $DIR/forget_ref.rs:15:5
-   |
-LL |     forget(&&owned);
-   |     ^^^^^^^^^^^^^^^
-   |
-note: argument has type `&&SomeStruct`
-  --> $DIR/forget_ref.rs:15:12
-   |
-LL |     forget(&&owned);
-   |            ^^^^^^^
-
-error: calls to `std::mem::forget` with a reference instead of an owned value. Forgetting a reference does nothing
-  --> $DIR/forget_ref.rs:16:5
-   |
-LL |     forget(&mut owned);
-   |     ^^^^^^^^^^^^^^^^^^
-   |
-note: argument has type `&mut SomeStruct`
-  --> $DIR/forget_ref.rs:16:12
-   |
-LL |     forget(&mut owned);
-   |            ^^^^^^^^^^
-
-error: calls to `std::mem::forget` with a reference instead of an owned value. Forgetting a reference does nothing
-  --> $DIR/forget_ref.rs:20:5
-   |
-LL |     forget(&*reference1);
-   |     ^^^^^^^^^^^^^^^^^^^^
-   |
-note: argument has type `&SomeStruct`
-  --> $DIR/forget_ref.rs:20:12
-   |
-LL |     forget(&*reference1);
-   |            ^^^^^^^^^^^^
-
-error: calls to `std::mem::forget` with a reference instead of an owned value. Forgetting a reference does nothing
-  --> $DIR/forget_ref.rs:23:5
-   |
-LL |     forget(reference2);
-   |     ^^^^^^^^^^^^^^^^^^
-   |
-note: argument has type `&mut SomeStruct`
-  --> $DIR/forget_ref.rs:23:12
-   |
-LL |     forget(reference2);
-   |            ^^^^^^^^^^
-
-error: calls to `std::mem::forget` with a reference instead of an owned value. Forgetting a reference does nothing
-  --> $DIR/forget_ref.rs:26:5
-   |
-LL |     forget(reference3);
-   |     ^^^^^^^^^^^^^^^^^^
-   |
-note: argument has type `&SomeStruct`
-  --> $DIR/forget_ref.rs:26:12
-   |
-LL |     forget(reference3);
-   |            ^^^^^^^^^^
-
-error: calls to `std::mem::forget` with a reference instead of an owned value. Forgetting a reference does nothing
-  --> $DIR/forget_ref.rs:31:5
-   |
-LL |     forget(&val);
-   |     ^^^^^^^^^^^^
-   |
-note: argument has type `&T`
-  --> $DIR/forget_ref.rs:31:12
-   |
-LL |     forget(&val);
-   |            ^^^^
-
-error: calls to `std::mem::forget` with a reference instead of an owned value. Forgetting a reference does nothing
-  --> $DIR/forget_ref.rs:39:5
-   |
-LL |     std::mem::forget(&SomeStruct);
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-note: argument has type `&SomeStruct`
-  --> $DIR/forget_ref.rs:39:22
-   |
-LL |     std::mem::forget(&SomeStruct);
-   |                      ^^^^^^^^^^^
-
-error: aborting due to 9 previous errors
-
diff --git a/src/tools/clippy/tests/ui/integer_arithmetic.rs b/src/tools/clippy/tests/ui/integer_arithmetic.rs
deleted file mode 100644
index ab9b6094c2c..00000000000
--- a/src/tools/clippy/tests/ui/integer_arithmetic.rs
+++ /dev/null
@@ -1,109 +0,0 @@
-//@aux-build:proc_macro_derive.rs
-
-#![warn(clippy::integer_arithmetic, clippy::float_arithmetic)]
-#![allow(clippy::no_effect, clippy::unnecessary_operation, clippy::op_ref)]
-
-extern crate proc_macro_derive;
-
-#[derive(proc_macro_derive::ShadowDerive)]
-pub struct Nothing;
-
-#[rustfmt::skip]
-fn main() {
-    let mut i = 1i32;
-    let mut var1 = 13i32;
-    let mut var2 = -1i32;
-    1 + i;
-    i * 2;
-    1 %
-    i / 2; // no error, this is part of the expression in the preceding line
-    i - 2 + 2 - i;
-    -i;
-    i >> 1;
-    i << 1;
-
-    // no error, overflows are checked by `overflowing_literals`
-    -1;
-    -(-1);
-
-    i & 1; // no wrapping
-    i | 1;
-    i ^ 1;
-
-    i += 1;
-    i -= 1;
-    i *= 2;
-    i /= 2;
-    i /= 0;
-    i /= -1;
-    i /= var1;
-    i /= var2;
-    i %= 2;
-    i %= 0;
-    i %= -1;
-    i %= var1;
-    i %= var2;
-    i <<= 3;
-    i >>= 2;
-
-    // no errors
-    i |= 1;
-    i &= 1;
-    i ^= i;
-
-    // No errors for the following items because they are constant expressions
-    enum Foo {
-        Bar = -2,
-    }
-    struct Baz([i32; 1 + 1]);
-    union Qux {
-        field: [i32; 1 + 1],
-    }
-    type Alias = [i32; 1 + 1];
-
-    const FOO: i32 = -2;
-    static BAR: i32 = -2;
-
-    let _: [i32; 1 + 1] = [0, 0];
-
-    let _: [i32; 1 + 1] = {
-        let a: [i32; 1 + 1] = [0, 0];
-        a
-    };
-
-    trait Trait {
-        const ASSOC: i32 = 1 + 1;
-    }
-
-    impl Trait for Foo {
-        const ASSOC: i32 = {
-            let _: [i32; 1 + 1];
-            fn foo() {}
-            1 + 1
-        };
-    }
-}
-
-// warn on references as well! (#5328)
-pub fn int_arith_ref() {
-    3 + &1;
-    &3 + 1;
-    &3 + &1;
-}
-
-pub fn foo(x: &i32) -> i32 {
-    let a = 5;
-    a + x
-}
-
-pub fn bar(x: &i32, y: &i32) -> i32 {
-    x + y
-}
-
-pub fn baz(x: i32, y: &i32) -> i32 {
-    x + y
-}
-
-pub fn qux(x: i32, y: i32) -> i32 {
-    (&x + &y)
-}
diff --git a/src/tools/clippy/tests/ui/integer_arithmetic.stderr b/src/tools/clippy/tests/ui/integer_arithmetic.stderr
deleted file mode 100644
index add3b6b90fa..00000000000
--- a/src/tools/clippy/tests/ui/integer_arithmetic.stderr
+++ /dev/null
@@ -1,169 +0,0 @@
-error: this operation will panic at runtime
-  --> $DIR/integer_arithmetic.rs:37:5
-   |
-LL |     i /= 0;
-   |     ^^^^^^ attempt to divide `_` by zero
-   |
-   = note: `#[deny(unconditional_panic)]` on by default
-
-error: this operation will panic at runtime
-  --> $DIR/integer_arithmetic.rs:42:5
-   |
-LL |     i %= 0;
-   |     ^^^^^^ attempt to calculate the remainder of `_` with a divisor of zero
-
-error: integer arithmetic detected
-  --> $DIR/integer_arithmetic.rs:16:5
-   |
-LL |     1 + i;
-   |     ^^^^^
-   |
-   = note: `-D clippy::integer-arithmetic` implied by `-D warnings`
-
-error: integer arithmetic detected
-  --> $DIR/integer_arithmetic.rs:17:5
-   |
-LL |     i * 2;
-   |     ^^^^^
-
-error: integer arithmetic detected
-  --> $DIR/integer_arithmetic.rs:18:5
-   |
-LL | /     1 %
-LL | |     i / 2; // no error, this is part of the expression in the preceding line
-   | |_____^
-
-error: integer arithmetic detected
-  --> $DIR/integer_arithmetic.rs:20:5
-   |
-LL |     i - 2 + 2 - i;
-   |     ^^^^^^^^^^^^^
-
-error: integer arithmetic detected
-  --> $DIR/integer_arithmetic.rs:21:5
-   |
-LL |     -i;
-   |     ^^
-
-error: integer arithmetic detected
-  --> $DIR/integer_arithmetic.rs:22:5
-   |
-LL |     i >> 1;
-   |     ^^^^^^
-
-error: integer arithmetic detected
-  --> $DIR/integer_arithmetic.rs:23:5
-   |
-LL |     i << 1;
-   |     ^^^^^^
-
-error: integer arithmetic detected
-  --> $DIR/integer_arithmetic.rs:33:5
-   |
-LL |     i += 1;
-   |     ^^^^^^
-
-error: integer arithmetic detected
-  --> $DIR/integer_arithmetic.rs:34:5
-   |
-LL |     i -= 1;
-   |     ^^^^^^
-
-error: integer arithmetic detected
-  --> $DIR/integer_arithmetic.rs:35:5
-   |
-LL |     i *= 2;
-   |     ^^^^^^
-
-error: integer arithmetic detected
-  --> $DIR/integer_arithmetic.rs:38:11
-   |
-LL |     i /= -1;
-   |           ^
-
-error: integer arithmetic detected
-  --> $DIR/integer_arithmetic.rs:39:5
-   |
-LL |     i /= var1;
-   |     ^^^^^^^^^
-
-error: integer arithmetic detected
-  --> $DIR/integer_arithmetic.rs:40:5
-   |
-LL |     i /= var2;
-   |     ^^^^^^^^^
-
-error: integer arithmetic detected
-  --> $DIR/integer_arithmetic.rs:43:11
-   |
-LL |     i %= -1;
-   |           ^
-
-error: integer arithmetic detected
-  --> $DIR/integer_arithmetic.rs:44:5
-   |
-LL |     i %= var1;
-   |     ^^^^^^^^^
-
-error: integer arithmetic detected
-  --> $DIR/integer_arithmetic.rs:45:5
-   |
-LL |     i %= var2;
-   |     ^^^^^^^^^
-
-error: integer arithmetic detected
-  --> $DIR/integer_arithmetic.rs:46:5
-   |
-LL |     i <<= 3;
-   |     ^^^^^^^
-
-error: integer arithmetic detected
-  --> $DIR/integer_arithmetic.rs:47:5
-   |
-LL |     i >>= 2;
-   |     ^^^^^^^
-
-error: integer arithmetic detected
-  --> $DIR/integer_arithmetic.rs:89:5
-   |
-LL |     3 + &1;
-   |     ^^^^^^
-
-error: integer arithmetic detected
-  --> $DIR/integer_arithmetic.rs:90:5
-   |
-LL |     &3 + 1;
-   |     ^^^^^^
-
-error: integer arithmetic detected
-  --> $DIR/integer_arithmetic.rs:91:5
-   |
-LL |     &3 + &1;
-   |     ^^^^^^^
-
-error: integer arithmetic detected
-  --> $DIR/integer_arithmetic.rs:96:5
-   |
-LL |     a + x
-   |     ^^^^^
-
-error: integer arithmetic detected
-  --> $DIR/integer_arithmetic.rs:100:5
-   |
-LL |     x + y
-   |     ^^^^^
-
-error: integer arithmetic detected
-  --> $DIR/integer_arithmetic.rs:104:5
-   |
-LL |     x + y
-   |     ^^^^^
-
-error: integer arithmetic detected
-  --> $DIR/integer_arithmetic.rs:108:5
-   |
-LL |     (&x + &y)
-   |     ^^^^^^^^^
-
-error: aborting due to 27 previous errors
-
diff --git a/src/tools/clippy/tests/ui/issue-111399.rs b/src/tools/clippy/tests/ui/issue-111399.rs
new file mode 100644
index 00000000000..b65e6c7261a
--- /dev/null
+++ b/src/tools/clippy/tests/ui/issue-111399.rs
@@ -0,0 +1,13 @@
+#![feature(inherent_associated_types)]
+#![allow(incomplete_features)]
+
+// Check that rustc doesn't crash on the trait bound `Self::Ty: std::marker::Freeze`.
+
+pub struct Struct;
+
+impl Struct {
+    pub type Ty = usize;
+    pub const CT: Self::Ty = 42;
+}
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui/let_underscore_untyped.rs b/src/tools/clippy/tests/ui/let_underscore_untyped.rs
index 8486137d3a6..2c313ff35d5 100644
--- a/src/tools/clippy/tests/ui/let_underscore_untyped.rs
+++ b/src/tools/clippy/tests/ui/let_underscore_untyped.rs
@@ -1,6 +1,12 @@
+//@aux-build: proc_macros.rs
+
 #![allow(unused)]
 #![warn(clippy::let_underscore_untyped)]
 
+extern crate proc_macros;
+use proc_macros::with_span;
+
+use clippy_utils::is_from_proc_macro;
 use std::future::Future;
 use std::{boxed::Box, fmt::Display};
 
@@ -32,6 +38,14 @@ fn g() -> impl Fn() {
     || {}
 }
 
+with_span!(
+    span
+
+    fn dont_lint_proc_macro() {
+        let _ = a();
+    }
+);
+
 fn main() {
     let _ = a();
     let _ = b(1);
@@ -40,6 +54,7 @@ fn main() {
     let _ = e();
     let _ = f();
     let _ = g();
+    let closure = || {};
 
     _ = a();
     _ = b(1);
diff --git a/src/tools/clippy/tests/ui/let_underscore_untyped.stderr b/src/tools/clippy/tests/ui/let_underscore_untyped.stderr
index 6844cb998f7..bbf2508af10 100644
--- a/src/tools/clippy/tests/ui/let_underscore_untyped.stderr
+++ b/src/tools/clippy/tests/ui/let_underscore_untyped.stderr
@@ -1,60 +1,60 @@
 error: non-binding `let` without a type annotation
-  --> $DIR/let_underscore_untyped.rs:36:5
+  --> $DIR/let_underscore_untyped.rs:50:5
    |
 LL |     let _ = a();
    |     ^^^^^^^^^^^^
    |
 help: consider adding a type annotation
-  --> $DIR/let_underscore_untyped.rs:36:10
+  --> $DIR/let_underscore_untyped.rs:50:10
    |
 LL |     let _ = a();
    |          ^
    = note: `-D clippy::let-underscore-untyped` implied by `-D warnings`
 
 error: non-binding `let` without a type annotation
-  --> $DIR/let_underscore_untyped.rs:37:5
+  --> $DIR/let_underscore_untyped.rs:51:5
    |
 LL |     let _ = b(1);
    |     ^^^^^^^^^^^^^
    |
 help: consider adding a type annotation
-  --> $DIR/let_underscore_untyped.rs:37:10
+  --> $DIR/let_underscore_untyped.rs:51:10
    |
 LL |     let _ = b(1);
    |          ^
 
 error: non-binding `let` without a type annotation
-  --> $DIR/let_underscore_untyped.rs:39:5
+  --> $DIR/let_underscore_untyped.rs:53:5
    |
 LL |     let _ = d(&1);
    |     ^^^^^^^^^^^^^^
    |
 help: consider adding a type annotation
-  --> $DIR/let_underscore_untyped.rs:39:10
+  --> $DIR/let_underscore_untyped.rs:53:10
    |
 LL |     let _ = d(&1);
    |          ^
 
 error: non-binding `let` without a type annotation
-  --> $DIR/let_underscore_untyped.rs:40:5
+  --> $DIR/let_underscore_untyped.rs:54:5
    |
 LL |     let _ = e();
    |     ^^^^^^^^^^^^
    |
 help: consider adding a type annotation
-  --> $DIR/let_underscore_untyped.rs:40:10
+  --> $DIR/let_underscore_untyped.rs:54:10
    |
 LL |     let _ = e();
    |          ^
 
 error: non-binding `let` without a type annotation
-  --> $DIR/let_underscore_untyped.rs:41:5
+  --> $DIR/let_underscore_untyped.rs:55:5
    |
 LL |     let _ = f();
    |     ^^^^^^^^^^^^
    |
 help: consider adding a type annotation
-  --> $DIR/let_underscore_untyped.rs:41:10
+  --> $DIR/let_underscore_untyped.rs:55:10
    |
 LL |     let _ = f();
    |          ^
diff --git a/src/tools/clippy/tests/ui/manual_let_else.rs b/src/tools/clippy/tests/ui/manual_let_else.rs
index d175597a44a..3996d775f55 100644
--- a/src/tools/clippy/tests/ui/manual_let_else.rs
+++ b/src/tools/clippy/tests/ui/manual_let_else.rs
@@ -8,6 +8,12 @@
 )]
 #![warn(clippy::manual_let_else)]
 
+enum Variant {
+    A(usize, usize),
+    B(usize),
+    C,
+}
+
 fn g() -> Option<()> {
     None
 }
@@ -135,6 +141,15 @@ fn fire() {
         };
     }
     create_binding_if_some!(w, g());
+
+    fn e() -> Variant {
+        Variant::A(0, 0)
+    }
+
+    // Should not be renamed
+    let v = if let Variant::A(a, 0) = e() { a } else { return };
+    // Should be renamed
+    let v = if let Variant::B(b) = e() { b } else { return };
 }
 
 fn not_fire() {
diff --git a/src/tools/clippy/tests/ui/manual_let_else.stderr b/src/tools/clippy/tests/ui/manual_let_else.stderr
index 52aac6bc673..f6f56f7b00e 100644
--- a/src/tools/clippy/tests/ui/manual_let_else.stderr
+++ b/src/tools/clippy/tests/ui/manual_let_else.stderr
@@ -1,13 +1,13 @@
 error: this could be rewritten as `let...else`
-  --> $DIR/manual_let_else.rs:18:5
+  --> $DIR/manual_let_else.rs:24:5
    |
 LL |     let v = if let Some(v_some) = g() { v_some } else { return };
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Some(v_some) = g() else { return };`
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Some(v) = g() else { return };`
    |
    = note: `-D clippy::manual-let-else` implied by `-D warnings`
 
 error: this could be rewritten as `let...else`
-  --> $DIR/manual_let_else.rs:19:5
+  --> $DIR/manual_let_else.rs:25:5
    |
 LL | /     let v = if let Some(v_some) = g() {
 LL | |         v_some
@@ -18,13 +18,13 @@ LL | |     };
    |
 help: consider writing
    |
-LL ~     let Some(v_some) = g() else {
+LL ~     let Some(v) = g() else {
 LL +         return;
 LL +     };
    |
 
 error: this could be rewritten as `let...else`
-  --> $DIR/manual_let_else.rs:25:5
+  --> $DIR/manual_let_else.rs:31:5
    |
 LL | /     let v = if let Some(v) = g() {
 LL | |         // Blocks around the identity should have no impact
@@ -45,25 +45,25 @@ LL +     };
    |
 
 error: this could be rewritten as `let...else`
-  --> $DIR/manual_let_else.rs:38:9
+  --> $DIR/manual_let_else.rs:44:9
    |
 LL |         let v = if let Some(v_some) = g() { v_some } else { continue };
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Some(v_some) = g() else { continue };`
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Some(v) = g() else { continue };`
 
 error: this could be rewritten as `let...else`
-  --> $DIR/manual_let_else.rs:39:9
+  --> $DIR/manual_let_else.rs:45:9
    |
 LL |         let v = if let Some(v_some) = g() { v_some } else { break };
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Some(v_some) = g() else { break };`
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Some(v) = g() else { break };`
 
 error: this could be rewritten as `let...else`
-  --> $DIR/manual_let_else.rs:43:5
+  --> $DIR/manual_let_else.rs:49:5
    |
 LL |     let v = if let Some(v_some) = g() { v_some } else { panic!() };
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Some(v_some) = g() else { panic!() };`
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Some(v) = g() else { panic!() };`
 
 error: this could be rewritten as `let...else`
-  --> $DIR/manual_let_else.rs:46:5
+  --> $DIR/manual_let_else.rs:52:5
    |
 LL | /     let v = if let Some(v_some) = g() {
 LL | |         v_some
@@ -74,13 +74,13 @@ LL | |     };
    |
 help: consider writing
    |
-LL ~     let Some(v_some) = g() else {
+LL ~     let Some(v) = g() else {
 LL +         std::process::abort()
 LL +     };
    |
 
 error: this could be rewritten as `let...else`
-  --> $DIR/manual_let_else.rs:53:5
+  --> $DIR/manual_let_else.rs:59:5
    |
 LL | /     let v = if let Some(v_some) = g() {
 LL | |         v_some
@@ -91,13 +91,13 @@ LL | |     };
    |
 help: consider writing
    |
-LL ~     let Some(v_some) = g() else {
+LL ~     let Some(v) = g() else {
 LL +         if true { return } else { panic!() }
 LL +     };
    |
 
 error: this could be rewritten as `let...else`
-  --> $DIR/manual_let_else.rs:60:5
+  --> $DIR/manual_let_else.rs:66:5
    |
 LL | /     let v = if let Some(v_some) = g() {
 LL | |         v_some
@@ -109,14 +109,14 @@ LL | |     };
    |
 help: consider writing
    |
-LL ~     let Some(v_some) = g() else {
+LL ~     let Some(v) = g() else {
 LL +         if true {}
 LL +         panic!();
 LL +     };
    |
 
 error: this could be rewritten as `let...else`
-  --> $DIR/manual_let_else.rs:70:5
+  --> $DIR/manual_let_else.rs:76:5
    |
 LL | /     let v = if let Some(v_some) = g() {
 LL | |         v_some
@@ -129,7 +129,7 @@ LL | |     };
    |
 help: consider writing
    |
-LL ~     let Some(v_some) = g() else {
+LL ~     let Some(v) = g() else {
 LL +         match () {
 LL +             _ if panic!() => {},
 LL +             _ => panic!(),
@@ -138,13 +138,13 @@ LL +     };
    |
 
 error: this could be rewritten as `let...else`
-  --> $DIR/manual_let_else.rs:80:5
+  --> $DIR/manual_let_else.rs:86:5
    |
 LL |     let v = if let Some(v_some) = g() { v_some } else { if panic!() {} };
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Some(v_some) = g() else { if panic!() {} };`
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Some(v) = g() else { if panic!() {} };`
 
 error: this could be rewritten as `let...else`
-  --> $DIR/manual_let_else.rs:83:5
+  --> $DIR/manual_let_else.rs:89:5
    |
 LL | /     let v = if let Some(v_some) = g() {
 LL | |         v_some
@@ -157,7 +157,7 @@ LL | |     };
    |
 help: consider writing
    |
-LL ~     let Some(v_some) = g() else {
+LL ~     let Some(v) = g() else {
 LL +         match panic!() {
 LL +             _ => {},
 LL +         }
@@ -165,7 +165,7 @@ LL +     };
    |
 
 error: this could be rewritten as `let...else`
-  --> $DIR/manual_let_else.rs:92:5
+  --> $DIR/manual_let_else.rs:98:5
    |
 LL | /     let v = if let Some(v_some) = g() {
 LL | |         v_some
@@ -178,7 +178,7 @@ LL | |     };
    |
 help: consider writing
    |
-LL ~     let Some(v_some) = g() else { if true {
+LL ~     let Some(v) = g() else { if true {
 LL +         return;
 LL +     } else {
 LL +         panic!("diverge");
@@ -186,7 +186,7 @@ LL +     } };
    |
 
 error: this could be rewritten as `let...else`
-  --> $DIR/manual_let_else.rs:101:5
+  --> $DIR/manual_let_else.rs:107:5
    |
 LL | /     let v = if let Some(v_some) = g() {
 LL | |         v_some
@@ -199,7 +199,7 @@ LL | |     };
    |
 help: consider writing
    |
-LL ~     let Some(v_some) = g() else {
+LL ~     let Some(v) = g() else {
 LL +         match (g(), g()) {
 LL +             (Some(_), None) => return,
 LL +             (None, Some(_)) => {
@@ -215,7 +215,7 @@ LL +     };
    |
 
 error: this could be rewritten as `let...else`
-  --> $DIR/manual_let_else.rs:118:5
+  --> $DIR/manual_let_else.rs:124:5
    |
 LL | /     let (v, w) = if let Some(v_some) = g().map(|v| (v, 42)) {
 LL | |         v_some
@@ -226,13 +226,13 @@ LL | |     };
    |
 help: consider writing
    |
-LL ~     let Some(v_some) = g().map(|v| (v, 42)) else {
+LL ~     let Some((v, w)) = g().map(|v| (v, 42)) else {
 LL +         return;
 LL +     };
    |
 
 error: this could be rewritten as `let...else`
-  --> $DIR/manual_let_else.rs:125:5
+  --> $DIR/manual_let_else.rs:131:5
    |
 LL | /     let v = if let (Some(v_some), w_some) = (g(), 0) {
 LL | |         (w_some, v_some)
@@ -249,10 +249,10 @@ LL +     };
    |
 
 error: this could be rewritten as `let...else`
-  --> $DIR/manual_let_else.rs:134:13
+  --> $DIR/manual_let_else.rs:140:13
    |
 LL |             let $n = if let Some(v) = $e { v } else { return };
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Some(v) = g() else { return };`
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Some($n) = g() else { return };`
 ...
 LL |     create_binding_if_some!(w, g());
    |     ------------------------------- in this macro invocation
@@ -260,13 +260,25 @@ LL |     create_binding_if_some!(w, g());
    = note: this error originates in the macro `create_binding_if_some` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: this could be rewritten as `let...else`
-  --> $DIR/manual_let_else.rs:247:5
+  --> $DIR/manual_let_else.rs:150:5
+   |
+LL |     let v = if let Variant::A(a, 0) = e() { a } else { return };
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Variant::A(a, 0) = e() else { return };`
+
+error: this could be rewritten as `let...else`
+  --> $DIR/manual_let_else.rs:152:5
+   |
+LL |     let v = if let Variant::B(b) = e() { b } else { return };
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Variant::B(v) = e() else { return };`
+
+error: this could be rewritten as `let...else`
+  --> $DIR/manual_let_else.rs:262:5
    |
 LL | /     let _ = match ff {
 LL | |         Some(value) => value,
 LL | |         _ => macro_call!(),
 LL | |     };
-   | |______^ help: consider writing: `let Some(value) = ff else { macro_call!() };`
+   | |______^ help: consider writing: `let Some(_) = ff else { macro_call!() };`
 
-error: aborting due to 18 previous errors
+error: aborting due to 20 previous errors
 
diff --git a/src/tools/clippy/tests/ui/manual_let_else_match.stderr b/src/tools/clippy/tests/ui/manual_let_else_match.stderr
index 7abaa0b85d2..bacc14dc967 100644
--- a/src/tools/clippy/tests/ui/manual_let_else_match.stderr
+++ b/src/tools/clippy/tests/ui/manual_let_else_match.stderr
@@ -5,7 +5,7 @@ LL | /     let v = match g() {
 LL | |         Some(v_some) => v_some,
 LL | |         None => return,
 LL | |     };
-   | |______^ help: consider writing: `let Some(v_some) = g() else { return };`
+   | |______^ help: consider writing: `let Some(v) = g() else { return };`
    |
    = note: `-D clippy::manual-let-else` implied by `-D warnings`
 
@@ -16,7 +16,7 @@ LL | /     let v = match g() {
 LL | |         Some(v_some) => v_some,
 LL | |         _ => return,
 LL | |     };
-   | |______^ help: consider writing: `let Some(v_some) = g() else { return };`
+   | |______^ help: consider writing: `let Some(v) = g() else { return };`
 
 error: this could be rewritten as `let...else`
   --> $DIR/manual_let_else_match.rs:44:9
diff --git a/src/tools/clippy/tests/ui/manual_next_back.fixed b/src/tools/clippy/tests/ui/manual_next_back.fixed
new file mode 100644
index 00000000000..e8a47063ad6
--- /dev/null
+++ b/src/tools/clippy/tests/ui/manual_next_back.fixed
@@ -0,0 +1,36 @@
+//@run-rustfix
+
+#![allow(unused)]
+#![warn(clippy::manual_next_back)]
+
+struct FakeIter(std::ops::Range<i32>);
+
+impl FakeIter {
+    fn rev(self) -> Self {
+        self
+    }
+
+    fn next(&self) {}
+}
+
+impl DoubleEndedIterator for FakeIter {
+    fn next_back(&mut self) -> Option<Self::Item> {
+        self.0.next_back()
+    }
+}
+
+impl Iterator for FakeIter {
+    type Item = i32;
+    fn next(&mut self) -> Option<Self::Item> {
+        self.0.next()
+    }
+}
+
+fn main() {
+    // should not lint
+    FakeIter(0..10).rev().next();
+
+    // should lint
+    let _ = (0..10).next_back().unwrap();
+    let _ = "something".bytes().next_back();
+}
diff --git a/src/tools/clippy/tests/ui/manual_next_back.rs b/src/tools/clippy/tests/ui/manual_next_back.rs
new file mode 100644
index 00000000000..9ec89242241
--- /dev/null
+++ b/src/tools/clippy/tests/ui/manual_next_back.rs
@@ -0,0 +1,36 @@
+//@run-rustfix
+
+#![allow(unused)]
+#![warn(clippy::manual_next_back)]
+
+struct FakeIter(std::ops::Range<i32>);
+
+impl FakeIter {
+    fn rev(self) -> Self {
+        self
+    }
+
+    fn next(&self) {}
+}
+
+impl DoubleEndedIterator for FakeIter {
+    fn next_back(&mut self) -> Option<Self::Item> {
+        self.0.next_back()
+    }
+}
+
+impl Iterator for FakeIter {
+    type Item = i32;
+    fn next(&mut self) -> Option<Self::Item> {
+        self.0.next()
+    }
+}
+
+fn main() {
+    // should not lint
+    FakeIter(0..10).rev().next();
+
+    // should lint
+    let _ = (0..10).rev().next().unwrap();
+    let _ = "something".bytes().rev().next();
+}
diff --git a/src/tools/clippy/tests/ui/manual_next_back.stderr b/src/tools/clippy/tests/ui/manual_next_back.stderr
new file mode 100644
index 00000000000..94ccaa9e4cc
--- /dev/null
+++ b/src/tools/clippy/tests/ui/manual_next_back.stderr
@@ -0,0 +1,16 @@
+error: manual backwards iteration
+  --> $DIR/manual_next_back.rs:34:20
+   |
+LL |     let _ = (0..10).rev().next().unwrap();
+   |                    ^^^^^^^^^^^^^ help: use: `.next_back()`
+   |
+   = note: `-D clippy::manual-next-back` implied by `-D warnings`
+
+error: manual backwards iteration
+  --> $DIR/manual_next_back.rs:35:32
+   |
+LL |     let _ = "something".bytes().rev().next();
+   |                                ^^^^^^^^^^^^^ help: use: `.next_back()`
+
+error: aborting due to 2 previous errors
+
diff --git a/src/tools/clippy/tests/ui/match_expr_like_matches_macro.fixed b/src/tools/clippy/tests/ui/match_expr_like_matches_macro.fixed
index 7215660da67..60f59066173 100644
--- a/src/tools/clippy/tests/ui/match_expr_like_matches_macro.fixed
+++ b/src/tools/clippy/tests/ui/match_expr_like_matches_macro.fixed
@@ -15,7 +15,7 @@ fn main() {
     let _y = matches!(x, Some(0));
 
     // Lint
-    let _w = matches!(x, Some(_));
+    let _w = x.is_some();
 
     // Turn into is_none
     let _z = x.is_none();
diff --git a/src/tools/clippy/tests/ui/match_expr_like_matches_macro.stderr b/src/tools/clippy/tests/ui/match_expr_like_matches_macro.stderr
index 46f67ef4900..b72fe10b748 100644
--- a/src/tools/clippy/tests/ui/match_expr_like_matches_macro.stderr
+++ b/src/tools/clippy/tests/ui/match_expr_like_matches_macro.stderr
@@ -10,7 +10,7 @@ LL | |     };
    |
    = note: `-D clippy::match-like-matches-macro` implied by `-D warnings`
 
-error: match expression looks like `matches!` macro
+error: redundant pattern matching, consider using `is_some()`
   --> $DIR/match_expr_like_matches_macro.rs:21:14
    |
 LL |       let _w = match x {
@@ -18,7 +18,9 @@ LL |       let _w = match x {
 LL | |         Some(_) => true,
 LL | |         _ => false,
 LL | |     };
-   | |_____^ help: try this: `matches!(x, Some(_))`
+   | |_____^ help: try this: `x.is_some()`
+   |
+   = note: `-D clippy::redundant-pattern-matching` implied by `-D warnings`
 
 error: redundant pattern matching, consider using `is_none()`
   --> $DIR/match_expr_like_matches_macro.rs:27:14
@@ -29,8 +31,6 @@ LL | |         Some(_) => false,
 LL | |         None => true,
 LL | |     };
    | |_____^ help: try this: `x.is_none()`
-   |
-   = note: `-D clippy::redundant-pattern-matching` implied by `-D warnings`
 
 error: match expression looks like `matches!` macro
   --> $DIR/match_expr_like_matches_macro.rs:33:15
diff --git a/src/tools/clippy/tests/ui/match_same_arms.rs b/src/tools/clippy/tests/ui/match_same_arms.rs
index 0b9342c9c42..3914b45464c 100644
--- a/src/tools/clippy/tests/ui/match_same_arms.rs
+++ b/src/tools/clippy/tests/ui/match_same_arms.rs
@@ -53,4 +53,84 @@ mod issue4244 {
     }
 }
 
-fn main() {}
+macro_rules! m {
+    (foo) => {};
+    (bar) => {};
+}
+macro_rules! foo {
+    () => {
+        1
+    };
+}
+macro_rules! bar {
+    () => {
+        1
+    };
+}
+
+fn main() {
+    let x = 0;
+    let _ = match 0 {
+        0 => {
+            m!(foo);
+            x
+        },
+        1 => {
+            m!(bar);
+            x
+        },
+        _ => 1,
+    };
+
+    let _ = match 0 {
+        0 => {
+            m!(foo);
+            0
+        },
+        1 => {
+            m!(bar);
+            0
+        },
+        _ => 1,
+    };
+
+    let _ = match 0 {
+        0 => {
+            let mut x = 0;
+            #[cfg(not_enabled)]
+            {
+                x = 5;
+            }
+            #[cfg(not(not_enabled))]
+            {
+                x = 6;
+            }
+            x
+        },
+        1 => {
+            let mut x = 0;
+            #[cfg(also_not_enabled)]
+            {
+                x = 5;
+            }
+            #[cfg(not(also_not_enabled))]
+            {
+                x = 6;
+            }
+            x
+        },
+        _ => 0,
+    };
+
+    let _ = match 0 {
+        0 => foo!(),
+        1 => bar!(),
+        _ => 1,
+    };
+
+    let _ = match 0 {
+        0 => cfg!(not_enabled),
+        1 => cfg!(also_not_enabled),
+        _ => false,
+    };
+}
diff --git a/src/tools/clippy/tests/ui/match_same_arms2.rs b/src/tools/clippy/tests/ui/match_same_arms2.rs
index 82b2c433d99..60b2975be04 100644
--- a/src/tools/clippy/tests/ui/match_same_arms2.rs
+++ b/src/tools/clippy/tests/ui/match_same_arms2.rs
@@ -239,4 +239,10 @@ fn main() {
         3 => core::convert::identity::<u32>(todo!()),
         _ => 5,
     };
+
+    let _ = match 0 {
+        0 => cfg!(not_enable),
+        1 => cfg!(not_enable),
+        _ => false,
+    };
 }
diff --git a/src/tools/clippy/tests/ui/match_same_arms2.stderr b/src/tools/clippy/tests/ui/match_same_arms2.stderr
index 06cd4300054..8fb461bd286 100644
--- a/src/tools/clippy/tests/ui/match_same_arms2.stderr
+++ b/src/tools/clippy/tests/ui/match_same_arms2.stderr
@@ -192,5 +192,20 @@ note: other arm here
 LL |         Some(Bar { x: 0, y: 5, .. }) => 1,
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 12 previous errors
+error: this match arm has an identical body to another arm
+  --> $DIR/match_same_arms2.rs:245:9
+   |
+LL |         1 => cfg!(not_enable),
+   |         -^^^^^^^^^^^^^^^^^^^^
+   |         |
+   |         help: try merging the arm patterns: `1 | 0`
+   |
+   = help: or try changing either arm body
+note: other arm here
+  --> $DIR/match_same_arms2.rs:244:9
+   |
+LL |         0 => cfg!(not_enable),
+   |         ^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 13 previous errors
 
diff --git a/src/tools/clippy/tests/ui/mem_forget.rs b/src/tools/clippy/tests/ui/mem_forget.rs
index e5b35c098a2..edb9d87d032 100644
--- a/src/tools/clippy/tests/ui/mem_forget.rs
+++ b/src/tools/clippy/tests/ui/mem_forget.rs
@@ -5,7 +5,7 @@ use std::mem as memstuff;
 use std::mem::forget as forgetSomething;
 
 #[warn(clippy::mem_forget)]
-#[allow(clippy::forget_copy)]
+#[allow(forgetting_copy_types)]
 fn main() {
     let five: i32 = 5;
     forgetSomething(five);
diff --git a/src/tools/clippy/tests/ui/multiple_unsafe_ops_per_block.rs b/src/tools/clippy/tests/ui/multiple_unsafe_ops_per_block.rs
index 73ef35c8c36..4ef6f0ca92f 100644
--- a/src/tools/clippy/tests/ui/multiple_unsafe_ops_per_block.rs
+++ b/src/tools/clippy/tests/ui/multiple_unsafe_ops_per_block.rs
@@ -2,7 +2,7 @@
 #![allow(unused)]
 #![allow(deref_nullptr)]
 #![allow(clippy::unnecessary_operation)]
-#![allow(clippy::drop_copy)]
+#![allow(dropping_copy_types)]
 #![warn(clippy::multiple_unsafe_ops_per_block)]
 
 extern crate proc_macros;
diff --git a/src/tools/clippy/tests/ui/needless_bool/fixable.fixed b/src/tools/clippy/tests/ui/needless_bool/fixable.fixed
index f860852e7b7..bf1911881c8 100644
--- a/src/tools/clippy/tests/ui/needless_bool/fixable.fixed
+++ b/src/tools/clippy/tests/ui/needless_bool/fixable.fixed
@@ -63,6 +63,13 @@ fn main() {
     needless_bool2(x);
     needless_bool3(x);
     needless_bool_condition();
+
+    if a == b {
+        true
+    } else {
+        // Do not lint as this comment might be important
+        false
+    };
 }
 
 fn bool_ret3(x: bool) -> bool {
diff --git a/src/tools/clippy/tests/ui/needless_bool/fixable.rs b/src/tools/clippy/tests/ui/needless_bool/fixable.rs
index 6680dab5b6d..a6c465d4fbd 100644
--- a/src/tools/clippy/tests/ui/needless_bool/fixable.rs
+++ b/src/tools/clippy/tests/ui/needless_bool/fixable.rs
@@ -99,6 +99,13 @@ fn main() {
     needless_bool2(x);
     needless_bool3(x);
     needless_bool_condition();
+
+    if a == b {
+        true
+    } else {
+        // Do not lint as this comment might be important
+        false
+    };
 }
 
 fn bool_ret3(x: bool) -> bool {
diff --git a/src/tools/clippy/tests/ui/needless_bool/fixable.stderr b/src/tools/clippy/tests/ui/needless_bool/fixable.stderr
index d2c48376f76..fa906374fb3 100644
--- a/src/tools/clippy/tests/ui/needless_bool/fixable.stderr
+++ b/src/tools/clippy/tests/ui/needless_bool/fixable.stderr
@@ -91,7 +91,7 @@ LL | |     };
    | |_____^ help: you can reduce it to: `a < b`
 
 error: this if-then-else expression returns a bool literal
-  --> $DIR/fixable.rs:105:5
+  --> $DIR/fixable.rs:112:5
    |
 LL | /     if x {
 LL | |         return true;
@@ -101,7 +101,7 @@ LL | |     };
    | |_____^ help: you can reduce it to: `return x`
 
 error: this if-then-else expression returns a bool literal
-  --> $DIR/fixable.rs:113:5
+  --> $DIR/fixable.rs:120:5
    |
 LL | /     if x {
 LL | |         return false;
@@ -111,7 +111,7 @@ LL | |     };
    | |_____^ help: you can reduce it to: `return !x`
 
 error: this if-then-else expression returns a bool literal
-  --> $DIR/fixable.rs:121:5
+  --> $DIR/fixable.rs:128:5
    |
 LL | /     if x && y {
 LL | |         return true;
@@ -121,7 +121,7 @@ LL | |     };
    | |_____^ help: you can reduce it to: `return x && y`
 
 error: this if-then-else expression returns a bool literal
-  --> $DIR/fixable.rs:129:5
+  --> $DIR/fixable.rs:136:5
    |
 LL | /     if x && y {
 LL | |         return false;
@@ -131,7 +131,7 @@ LL | |     };
    | |_____^ help: you can reduce it to: `return !(x && y)`
 
 error: equality checks against true are unnecessary
-  --> $DIR/fixable.rs:137:8
+  --> $DIR/fixable.rs:144:8
    |
 LL |     if x == true {};
    |        ^^^^^^^^^ help: try simplifying it as shown: `x`
@@ -139,25 +139,25 @@ LL |     if x == true {};
    = note: `-D clippy::bool-comparison` implied by `-D warnings`
 
 error: equality checks against false can be replaced by a negation
-  --> $DIR/fixable.rs:141:8
+  --> $DIR/fixable.rs:148:8
    |
 LL |     if x == false {};
    |        ^^^^^^^^^^ help: try simplifying it as shown: `!x`
 
 error: equality checks against true are unnecessary
-  --> $DIR/fixable.rs:151:8
+  --> $DIR/fixable.rs:158:8
    |
 LL |     if x == true {};
    |        ^^^^^^^^^ help: try simplifying it as shown: `x`
 
 error: equality checks against false can be replaced by a negation
-  --> $DIR/fixable.rs:152:8
+  --> $DIR/fixable.rs:159:8
    |
 LL |     if x == false {};
    |        ^^^^^^^^^^ help: try simplifying it as shown: `!x`
 
 error: this if-then-else expression returns a bool literal
-  --> $DIR/fixable.rs:161:12
+  --> $DIR/fixable.rs:168:12
    |
 LL |       } else if returns_bool() {
    |  ____________^
@@ -168,7 +168,7 @@ LL | |     };
    | |_____^ help: you can reduce it to: `{ !returns_bool() }`
 
 error: this if-then-else expression returns a bool literal
-  --> $DIR/fixable.rs:174:5
+  --> $DIR/fixable.rs:181:5
    |
 LL | /     if unsafe { no(4) } & 1 != 0 {
 LL | |         true
@@ -178,13 +178,13 @@ LL | |     };
    | |_____^ help: you can reduce it to: `(unsafe { no(4) } & 1 != 0)`
 
 error: this if-then-else expression returns a bool literal
-  --> $DIR/fixable.rs:179:30
+  --> $DIR/fixable.rs:186:30
    |
 LL |     let _brackets_unneeded = if unsafe { no(4) } & 1 != 0 { true } else { false };
    |                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: you can reduce it to: `unsafe { no(4) } & 1 != 0`
 
 error: this if-then-else expression returns a bool literal
-  --> $DIR/fixable.rs:182:9
+  --> $DIR/fixable.rs:189:9
    |
 LL |         if unsafe { no(4) } & 1 != 0 { true } else { false }
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: you can reduce it to: `(unsafe { no(4) } & 1 != 0)`
diff --git a/src/tools/clippy/tests/ui/needless_collect.fixed b/src/tools/clippy/tests/ui/needless_collect.fixed
index 024c22de225..b7e80af5015 100644
--- a/src/tools/clippy/tests/ui/needless_collect.fixed
+++ b/src/tools/clippy/tests/ui/needless_collect.fixed
@@ -62,4 +62,16 @@ fn main() {
 
     let _ = sample.iter().next().is_none();
     let _ = sample.iter().any(|x| x == &0);
+
+    #[allow(clippy::double_parens)]
+    {
+        Vec::<u8>::new().extend((0..10));
+        foo((0..10));
+        bar((0..10).collect::<Vec<_>>(), (0..10));
+        baz((0..10), (), ('a'..='z'))
+    }
 }
+
+fn foo(_: impl IntoIterator<Item = usize>) {}
+fn bar<I: IntoIterator<Item = usize>>(_: Vec<usize>, _: I) {}
+fn baz<I: IntoIterator<Item = usize>>(_: I, _: (), _: impl IntoIterator<Item = char>) {}
diff --git a/src/tools/clippy/tests/ui/needless_collect.rs b/src/tools/clippy/tests/ui/needless_collect.rs
index 7ed7babec30..680b6fa5b55 100644
--- a/src/tools/clippy/tests/ui/needless_collect.rs
+++ b/src/tools/clippy/tests/ui/needless_collect.rs
@@ -62,4 +62,16 @@ fn main() {
 
     let _ = sample.iter().collect::<VecWrapper<_>>().is_empty();
     let _ = sample.iter().collect::<VecWrapper<_>>().contains(&&0);
+
+    #[allow(clippy::double_parens)]
+    {
+        Vec::<u8>::new().extend((0..10).collect::<Vec<_>>());
+        foo((0..10).collect::<Vec<_>>());
+        bar((0..10).collect::<Vec<_>>(), (0..10).collect::<Vec<_>>());
+        baz((0..10), (), ('a'..='z').collect::<Vec<_>>())
+    }
 }
+
+fn foo(_: impl IntoIterator<Item = usize>) {}
+fn bar<I: IntoIterator<Item = usize>>(_: Vec<usize>, _: I) {}
+fn baz<I: IntoIterator<Item = usize>>(_: I, _: (), _: impl IntoIterator<Item = char>) {}
diff --git a/src/tools/clippy/tests/ui/needless_collect.stderr b/src/tools/clippy/tests/ui/needless_collect.stderr
index 584d2a1d835..ad22a7b057e 100644
--- a/src/tools/clippy/tests/ui/needless_collect.stderr
+++ b/src/tools/clippy/tests/ui/needless_collect.stderr
@@ -90,5 +90,29 @@ error: avoid using `collect()` when not needed
 LL |     let _ = sample.iter().collect::<VecWrapper<_>>().contains(&&0);
    |                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `any(|x| x == &0)`
 
-error: aborting due to 15 previous errors
+error: avoid using `collect()` when not needed
+  --> $DIR/needless_collect.rs:68:40
+   |
+LL |         Vec::<u8>::new().extend((0..10).collect::<Vec<_>>());
+   |                                        ^^^^^^^^^^^^^^^^^^^^ help: remove this call
+
+error: avoid using `collect()` when not needed
+  --> $DIR/needless_collect.rs:69:20
+   |
+LL |         foo((0..10).collect::<Vec<_>>());
+   |                    ^^^^^^^^^^^^^^^^^^^^ help: remove this call
+
+error: avoid using `collect()` when not needed
+  --> $DIR/needless_collect.rs:70:49
+   |
+LL |         bar((0..10).collect::<Vec<_>>(), (0..10).collect::<Vec<_>>());
+   |                                                 ^^^^^^^^^^^^^^^^^^^^ help: remove this call
+
+error: avoid using `collect()` when not needed
+  --> $DIR/needless_collect.rs:71:37
+   |
+LL |         baz((0..10), (), ('a'..='z').collect::<Vec<_>>())
+   |                                     ^^^^^^^^^^^^^^^^^^^^ help: remove this call
+
+error: aborting due to 19 previous errors
 
diff --git a/src/tools/clippy/tests/ui/needless_return.fixed b/src/tools/clippy/tests/ui/needless_return.fixed
index ee4e5007dc5..d49ae5d8636 100644
--- a/src/tools/clippy/tests/ui/needless_return.fixed
+++ b/src/tools/clippy/tests/ui/needless_return.fixed
@@ -231,8 +231,9 @@ fn needless_return_macro() -> String {
 }
 
 fn issue_9361() -> i32 {
-    #[allow(clippy::integer_arithmetic)]
-    return 1 + 2;
+    let n = 1;
+    #[allow(clippy::arithmetic_side_effects)]
+    return n + n;
 }
 
 fn issue8336(x: i32) -> bool {
diff --git a/src/tools/clippy/tests/ui/needless_return.rs b/src/tools/clippy/tests/ui/needless_return.rs
index cd999db4f40..36763826174 100644
--- a/src/tools/clippy/tests/ui/needless_return.rs
+++ b/src/tools/clippy/tests/ui/needless_return.rs
@@ -239,8 +239,9 @@ fn needless_return_macro() -> String {
 }
 
 fn issue_9361() -> i32 {
-    #[allow(clippy::integer_arithmetic)]
-    return 1 + 2;
+    let n = 1;
+    #[allow(clippy::arithmetic_side_effects)]
+    return n + n;
 }
 
 fn issue8336(x: i32) -> bool {
diff --git a/src/tools/clippy/tests/ui/needless_return.stderr b/src/tools/clippy/tests/ui/needless_return.stderr
index 87d0cd3e14c..05f6038cd25 100644
--- a/src/tools/clippy/tests/ui/needless_return.stderr
+++ b/src/tools/clippy/tests/ui/needless_return.stderr
@@ -328,7 +328,7 @@ LL |     return format!("Hello {}", "world!");
    = help: remove `return`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:249:9
+  --> $DIR/needless_return.rs:250:9
    |
 LL |         return true;
    |         ^^^^^^^^^^^
@@ -336,7 +336,7 @@ LL |         return true;
    = help: remove `return`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:251:9
+  --> $DIR/needless_return.rs:252:9
    |
 LL |         return false;
    |         ^^^^^^^^^^^^
@@ -344,7 +344,7 @@ LL |         return false;
    = help: remove `return`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:258:13
+  --> $DIR/needless_return.rs:259:13
    |
 LL |             return 10;
    |             ^^^^^^^^^
@@ -352,7 +352,7 @@ LL |             return 10;
    = help: remove `return`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:261:13
+  --> $DIR/needless_return.rs:262:13
    |
 LL |             return 100;
    |             ^^^^^^^^^^
@@ -360,7 +360,7 @@ LL |             return 100;
    = help: remove `return`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:269:9
+  --> $DIR/needless_return.rs:270:9
    |
 LL |         return 0;
    |         ^^^^^^^^
@@ -368,7 +368,7 @@ LL |         return 0;
    = help: remove `return`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:276:13
+  --> $DIR/needless_return.rs:277:13
    |
 LL |             return *(x as *const isize);
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -376,7 +376,7 @@ LL |             return *(x as *const isize);
    = help: remove `return`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:278:13
+  --> $DIR/needless_return.rs:279:13
    |
 LL |             return !*(x as *const isize);
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -384,7 +384,7 @@ LL |             return !*(x as *const isize);
    = help: remove `return`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:285:20
+  --> $DIR/needless_return.rs:286:20
    |
 LL |           let _ = 42;
    |  ____________________^
@@ -395,7 +395,7 @@ LL | |         return;
    = help: remove `return`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:292:20
+  --> $DIR/needless_return.rs:293:20
    |
 LL |         let _ = 42; return;
    |                    ^^^^^^^
@@ -403,7 +403,7 @@ LL |         let _ = 42; return;
    = help: remove `return`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:304:9
+  --> $DIR/needless_return.rs:305:9
    |
 LL |         return Ok(format!("ok!"));
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -411,7 +411,7 @@ LL |         return Ok(format!("ok!"));
    = help: remove `return`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:306:9
+  --> $DIR/needless_return.rs:307:9
    |
 LL |         return Err(format!("err!"));
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -419,7 +419,7 @@ LL |         return Err(format!("err!"));
    = help: remove `return`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:312:9
+  --> $DIR/needless_return.rs:313:9
    |
 LL |         return if true { 1 } else { 2 };
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -427,7 +427,7 @@ LL |         return if true { 1 } else { 2 };
    = help: remove `return`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:316:9
+  --> $DIR/needless_return.rs:317:9
    |
 LL |         return if b1 { 0 } else { 1 } | if b2 { 2 } else { 3 } | if b3 { 4 } else { 5 };
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/tools/clippy/tests/ui/non_minimal_cfg.fixed b/src/tools/clippy/tests/ui/non_minimal_cfg.fixed
new file mode 100644
index 00000000000..430caafb33e
--- /dev/null
+++ b/src/tools/clippy/tests/ui/non_minimal_cfg.fixed
@@ -0,0 +1,17 @@
+//@run-rustfix
+
+#![allow(unused)]
+
+#[cfg(windows)]
+fn hermit() {}
+
+#[cfg(windows)]
+fn wasi() {}
+
+#[cfg(all(unix, not(windows)))]
+fn the_end() {}
+
+#[cfg(any())]
+fn any() {}
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui/non_minimal_cfg.rs b/src/tools/clippy/tests/ui/non_minimal_cfg.rs
new file mode 100644
index 00000000000..a38ce1c21d6
--- /dev/null
+++ b/src/tools/clippy/tests/ui/non_minimal_cfg.rs
@@ -0,0 +1,17 @@
+//@run-rustfix
+
+#![allow(unused)]
+
+#[cfg(all(windows))]
+fn hermit() {}
+
+#[cfg(any(windows))]
+fn wasi() {}
+
+#[cfg(all(any(unix), all(not(windows))))]
+fn the_end() {}
+
+#[cfg(any())]
+fn any() {}
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui/non_minimal_cfg.stderr b/src/tools/clippy/tests/ui/non_minimal_cfg.stderr
new file mode 100644
index 00000000000..cdfd728aa61
--- /dev/null
+++ b/src/tools/clippy/tests/ui/non_minimal_cfg.stderr
@@ -0,0 +1,28 @@
+error: unneeded sub `cfg` when there is only one condition
+  --> $DIR/non_minimal_cfg.rs:5:7
+   |
+LL | #[cfg(all(windows))]
+   |       ^^^^^^^^^^^^ help: try: `windows`
+   |
+   = note: `-D clippy::non-minimal-cfg` implied by `-D warnings`
+
+error: unneeded sub `cfg` when there is only one condition
+  --> $DIR/non_minimal_cfg.rs:8:7
+   |
+LL | #[cfg(any(windows))]
+   |       ^^^^^^^^^^^^ help: try: `windows`
+
+error: unneeded sub `cfg` when there is only one condition
+  --> $DIR/non_minimal_cfg.rs:11:11
+   |
+LL | #[cfg(all(any(unix), all(not(windows))))]
+   |           ^^^^^^^^^ help: try: `unix`
+
+error: unneeded sub `cfg` when there is only one condition
+  --> $DIR/non_minimal_cfg.rs:11:22
+   |
+LL | #[cfg(all(any(unix), all(not(windows))))]
+   |                      ^^^^^^^^^^^^^^^^^ help: try: `not(windows)`
+
+error: aborting due to 4 previous errors
+
diff --git a/src/tools/clippy/tests/ui/non_minimal_cfg2.rs b/src/tools/clippy/tests/ui/non_minimal_cfg2.rs
new file mode 100644
index 00000000000..a4c6abce387
--- /dev/null
+++ b/src/tools/clippy/tests/ui/non_minimal_cfg2.rs
@@ -0,0 +1,6 @@
+#![allow(unused)]
+
+#[cfg(all())]
+fn all() {}
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui/non_minimal_cfg2.stderr b/src/tools/clippy/tests/ui/non_minimal_cfg2.stderr
new file mode 100644
index 00000000000..2a9a36fbcef
--- /dev/null
+++ b/src/tools/clippy/tests/ui/non_minimal_cfg2.stderr
@@ -0,0 +1,10 @@
+error: unneeded sub `cfg` when there is no condition
+  --> $DIR/non_minimal_cfg2.rs:3:7
+   |
+LL | #[cfg(all())]
+   |       ^^^^^
+   |
+   = note: `-D clippy::non-minimal-cfg` implied by `-D warnings`
+
+error: aborting due to previous error
+
diff --git a/src/tools/clippy/tests/ui/option_if_let_else.fixed b/src/tools/clippy/tests/ui/option_if_let_else.fixed
index 57f341e0276..2b8ce5477cc 100644
--- a/src/tools/clippy/tests/ui/option_if_let_else.fixed
+++ b/src/tools/clippy/tests/ui/option_if_let_else.fixed
@@ -92,6 +92,15 @@ fn pattern_to_vec(pattern: &str) -> Vec<String> {
         .collect::<Vec<_>>()
 }
 
+// #10335
+fn test_result_impure_else(variable: Result<u32, &str>) {
+    variable.map_or_else(|_| {
+        println!("Err");
+    }, |binding| {
+        println!("Ok {binding}");
+    })
+}
+
 enum DummyEnum {
     One(u8),
     Two,
@@ -113,6 +122,7 @@ fn main() {
     unop_bad(&None, None);
     let _ = longer_body(None);
     test_map_or_else(None);
+    test_result_impure_else(Ok(42));
     let _ = negative_tests(None);
     let _ = impure_else(None);
 
diff --git a/src/tools/clippy/tests/ui/option_if_let_else.rs b/src/tools/clippy/tests/ui/option_if_let_else.rs
index 19f9f704517..cfbec8cb27d 100644
--- a/src/tools/clippy/tests/ui/option_if_let_else.rs
+++ b/src/tools/clippy/tests/ui/option_if_let_else.rs
@@ -115,6 +115,15 @@ fn pattern_to_vec(pattern: &str) -> Vec<String> {
         .collect::<Vec<_>>()
 }
 
+// #10335
+fn test_result_impure_else(variable: Result<u32, &str>) {
+    if let Ok(binding) = variable {
+        println!("Ok {binding}");
+    } else {
+        println!("Err");
+    }
+}
+
 enum DummyEnum {
     One(u8),
     Two,
@@ -136,6 +145,7 @@ fn main() {
     unop_bad(&None, None);
     let _ = longer_body(None);
     test_map_or_else(None);
+    test_result_impure_else(Ok(42));
     let _ = negative_tests(None);
     let _ = impure_else(None);
 
diff --git a/src/tools/clippy/tests/ui/option_if_let_else.stderr b/src/tools/clippy/tests/ui/option_if_let_else.stderr
index f5e4affb672..91d52fc79b8 100644
--- a/src/tools/clippy/tests/ui/option_if_let_else.stderr
+++ b/src/tools/clippy/tests/ui/option_if_let_else.stderr
@@ -152,14 +152,33 @@ LL | |                 vec![s.to_string()]
 LL | |             }
    | |_____________^ help: try: `s.find('.').map_or_else(|| vec![s.to_string()], |idx| vec![s[..idx].to_string(), s[idx..].to_string()])`
 
+error: use Option::map_or_else instead of an if let/else
+  --> $DIR/option_if_let_else.rs:120:5
+   |
+LL | /     if let Ok(binding) = variable {
+LL | |         println!("Ok {binding}");
+LL | |     } else {
+LL | |         println!("Err");
+LL | |     }
+   | |_____^
+   |
+help: try
+   |
+LL ~     variable.map_or_else(|_| {
+LL +         println!("Err");
+LL +     }, |binding| {
+LL +         println!("Ok {binding}");
+LL +     })
+   |
+
 error: use Option::map_or instead of an if let/else
-  --> $DIR/option_if_let_else.rs:133:13
+  --> $DIR/option_if_let_else.rs:142:13
    |
 LL |     let _ = if let Some(x) = optional { x + 2 } else { 5 };
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `optional.map_or(5, |x| x + 2)`
 
 error: use Option::map_or instead of an if let/else
-  --> $DIR/option_if_let_else.rs:142:13
+  --> $DIR/option_if_let_else.rs:152:13
    |
 LL |       let _ = if let Some(x) = Some(0) {
    |  _____________^
@@ -181,13 +200,13 @@ LL ~         });
    |
 
 error: use Option::map_or instead of an if let/else
-  --> $DIR/option_if_let_else.rs:170:13
+  --> $DIR/option_if_let_else.rs:180:13
    |
 LL |     let _ = if let Some(x) = Some(0) { s.len() + x } else { s.len() };
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Some(0).map_or(s.len(), |x| s.len() + x)`
 
 error: use Option::map_or instead of an if let/else
-  --> $DIR/option_if_let_else.rs:174:13
+  --> $DIR/option_if_let_else.rs:184:13
    |
 LL |       let _ = if let Some(x) = Some(0) {
    |  _____________^
@@ -207,7 +226,7 @@ LL ~     });
    |
 
 error: use Option::map_or instead of an if let/else
-  --> $DIR/option_if_let_else.rs:213:13
+  --> $DIR/option_if_let_else.rs:223:13
    |
 LL |       let _ = match s {
    |  _____________^
@@ -217,7 +236,7 @@ LL | |     };
    | |_____^ help: try: `s.map_or(1, |string| string.len())`
 
 error: use Option::map_or instead of an if let/else
-  --> $DIR/option_if_let_else.rs:217:13
+  --> $DIR/option_if_let_else.rs:227:13
    |
 LL |       let _ = match Some(10) {
    |  _____________^
@@ -227,7 +246,7 @@ LL | |     };
    | |_____^ help: try: `Some(10).map_or(5, |a| a + 1)`
 
 error: use Option::map_or instead of an if let/else
-  --> $DIR/option_if_let_else.rs:223:13
+  --> $DIR/option_if_let_else.rs:233:13
    |
 LL |       let _ = match res {
    |  _____________^
@@ -237,7 +256,7 @@ LL | |     };
    | |_____^ help: try: `res.map_or(1, |a| a + 1)`
 
 error: use Option::map_or instead of an if let/else
-  --> $DIR/option_if_let_else.rs:227:13
+  --> $DIR/option_if_let_else.rs:237:13
    |
 LL |       let _ = match res {
    |  _____________^
@@ -247,10 +266,10 @@ LL | |     };
    | |_____^ help: try: `res.map_or(1, |a| a + 1)`
 
 error: use Option::map_or instead of an if let/else
-  --> $DIR/option_if_let_else.rs:231:13
+  --> $DIR/option_if_let_else.rs:241:13
    |
 LL |     let _ = if let Ok(a) = res { a + 1 } else { 5 };
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `res.map_or(5, |a| a + 1)`
 
-error: aborting due to 20 previous errors
+error: aborting due to 21 previous errors
 
diff --git a/src/tools/clippy/tests/ui/partialeq_to_none.fixed b/src/tools/clippy/tests/ui/partialeq_to_none.fixed
index 81a716bd276..2df87a26d6d 100644
--- a/src/tools/clippy/tests/ui/partialeq_to_none.fixed
+++ b/src/tools/clippy/tests/ui/partialeq_to_none.fixed
@@ -1,5 +1,6 @@
 //@run-rustfix
 #![warn(clippy::partialeq_to_none)]
+#![allow(clippy::eq_op)]
 
 struct Foobar;
 
diff --git a/src/tools/clippy/tests/ui/partialeq_to_none.rs b/src/tools/clippy/tests/ui/partialeq_to_none.rs
index f454715fa30..df6233b9afd 100644
--- a/src/tools/clippy/tests/ui/partialeq_to_none.rs
+++ b/src/tools/clippy/tests/ui/partialeq_to_none.rs
@@ -1,5 +1,6 @@
 //@run-rustfix
 #![warn(clippy::partialeq_to_none)]
+#![allow(clippy::eq_op)]
 
 struct Foobar;
 
diff --git a/src/tools/clippy/tests/ui/partialeq_to_none.stderr b/src/tools/clippy/tests/ui/partialeq_to_none.stderr
index d06ab7aee55..4f84862a22b 100644
--- a/src/tools/clippy/tests/ui/partialeq_to_none.stderr
+++ b/src/tools/clippy/tests/ui/partialeq_to_none.stderr
@@ -1,5 +1,5 @@
 error: binary comparison to literal `Option::None`
-  --> $DIR/partialeq_to_none.rs:14:8
+  --> $DIR/partialeq_to_none.rs:15:8
    |
 LL |     if f != None { "yay" } else { "nay" }
    |        ^^^^^^^^^ help: use `Option::is_some()` instead: `f.is_some()`
@@ -7,55 +7,55 @@ LL |     if f != None { "yay" } else { "nay" }
    = note: `-D clippy::partialeq-to-none` implied by `-D warnings`
 
 error: binary comparison to literal `Option::None`
-  --> $DIR/partialeq_to_none.rs:44:13
+  --> $DIR/partialeq_to_none.rs:45:13
    |
 LL |     let _ = x == None;
    |             ^^^^^^^^^ help: use `Option::is_none()` instead: `x.is_none()`
 
 error: binary comparison to literal `Option::None`
-  --> $DIR/partialeq_to_none.rs:45:13
+  --> $DIR/partialeq_to_none.rs:46:13
    |
 LL |     let _ = x != None;
    |             ^^^^^^^^^ help: use `Option::is_some()` instead: `x.is_some()`
 
 error: binary comparison to literal `Option::None`
-  --> $DIR/partialeq_to_none.rs:46:13
+  --> $DIR/partialeq_to_none.rs:47:13
    |
 LL |     let _ = None == x;
    |             ^^^^^^^^^ help: use `Option::is_none()` instead: `x.is_none()`
 
 error: binary comparison to literal `Option::None`
-  --> $DIR/partialeq_to_none.rs:47:13
+  --> $DIR/partialeq_to_none.rs:48:13
    |
 LL |     let _ = None != x;
    |             ^^^^^^^^^ help: use `Option::is_some()` instead: `x.is_some()`
 
 error: binary comparison to literal `Option::None`
-  --> $DIR/partialeq_to_none.rs:49:8
+  --> $DIR/partialeq_to_none.rs:50:8
    |
 LL |     if foobar() == None {}
    |        ^^^^^^^^^^^^^^^^ help: use `Option::is_none()` instead: `foobar().is_none()`
 
 error: binary comparison to literal `Option::None`
-  --> $DIR/partialeq_to_none.rs:51:8
+  --> $DIR/partialeq_to_none.rs:52:8
    |
 LL |     if bar().ok() != None {}
    |        ^^^^^^^^^^^^^^^^^^ help: use `Option::is_some()` instead: `bar().ok().is_some()`
 
 error: binary comparison to literal `Option::None`
-  --> $DIR/partialeq_to_none.rs:53:13
+  --> $DIR/partialeq_to_none.rs:54:13
    |
 LL |     let _ = Some(1 + 2) != None;
    |             ^^^^^^^^^^^^^^^^^^^ help: use `Option::is_some()` instead: `Some(1 + 2).is_some()`
 
 error: binary comparison to literal `Option::None`
-  --> $DIR/partialeq_to_none.rs:55:13
+  --> $DIR/partialeq_to_none.rs:56:13
    |
 LL |     let _ = { Some(0) } == None;
    |             ^^^^^^^^^^^^^^^^^^^ help: use `Option::is_none()` instead: `{ Some(0) }.is_none()`
 
 error: binary comparison to literal `Option::None`
-  --> $DIR/partialeq_to_none.rs:57:13
+  --> $DIR/partialeq_to_none.rs:58:13
    |
 LL |       let _ = {
    |  _____________^
@@ -77,31 +77,31 @@ LL ~     }.is_some();
    |
 
 error: binary comparison to literal `Option::None`
-  --> $DIR/partialeq_to_none.rs:67:13
+  --> $DIR/partialeq_to_none.rs:68:13
    |
 LL |     let _ = optref() == &&None;
    |             ^^^^^^^^^^^^^^^^^^ help: use `Option::is_none()` instead: `optref().is_none()`
 
 error: binary comparison to literal `Option::None`
-  --> $DIR/partialeq_to_none.rs:68:13
+  --> $DIR/partialeq_to_none.rs:69:13
    |
 LL |     let _ = &&None != optref();
    |             ^^^^^^^^^^^^^^^^^^ help: use `Option::is_some()` instead: `optref().is_some()`
 
 error: binary comparison to literal `Option::None`
-  --> $DIR/partialeq_to_none.rs:69:13
+  --> $DIR/partialeq_to_none.rs:70:13
    |
 LL |     let _ = **optref() == None;
    |             ^^^^^^^^^^^^^^^^^^ help: use `Option::is_none()` instead: `optref().is_none()`
 
 error: binary comparison to literal `Option::None`
-  --> $DIR/partialeq_to_none.rs:70:13
+  --> $DIR/partialeq_to_none.rs:71:13
    |
 LL |     let _ = &None != *optref();
    |             ^^^^^^^^^^^^^^^^^^ help: use `Option::is_some()` instead: `optref().is_some()`
 
 error: binary comparison to literal `Option::None`
-  --> $DIR/partialeq_to_none.rs:73:13
+  --> $DIR/partialeq_to_none.rs:74:13
    |
 LL |     let _ = None != *x;
    |             ^^^^^^^^^^ help: use `Option::is_some()` instead: `(*x).is_some()`
diff --git a/src/tools/clippy/tests/ui/redundant_pattern_matching_option.fixed b/src/tools/clippy/tests/ui/redundant_pattern_matching_option.fixed
index d62f7d26a35..accdf1da9dd 100644
--- a/src/tools/clippy/tests/ui/redundant_pattern_matching_option.fixed
+++ b/src/tools/clippy/tests/ui/redundant_pattern_matching_option.fixed
@@ -46,6 +46,7 @@ fn main() {
     let _ = if opt.is_some() { true } else { false };
 
     issue6067();
+    issue10726();
 
     let _ = if gen_opt().is_some() {
         1
@@ -88,3 +89,21 @@ fn issue7921() {
     if (&None::<()>).is_none() {}
     if (&None::<()>).is_none() {}
 }
+
+fn issue10726() {
+    let x = Some(42);
+
+    x.is_some();
+
+    x.is_none();
+
+    x.is_none();
+
+    x.is_some();
+
+    // Don't lint
+    match x {
+        Some(21) => true,
+        _ => false,
+    };
+}
diff --git a/src/tools/clippy/tests/ui/redundant_pattern_matching_option.rs b/src/tools/clippy/tests/ui/redundant_pattern_matching_option.rs
index d6429426573..ec684bdf71c 100644
--- a/src/tools/clippy/tests/ui/redundant_pattern_matching_option.rs
+++ b/src/tools/clippy/tests/ui/redundant_pattern_matching_option.rs
@@ -55,6 +55,7 @@ fn main() {
     let _ = if let Some(_) = opt { true } else { false };
 
     issue6067();
+    issue10726();
 
     let _ = if let Some(_) = gen_opt() {
         1
@@ -103,3 +104,33 @@ fn issue7921() {
     if let None = *(&None::<()>) {}
     if let None = *&None::<()> {}
 }
+
+fn issue10726() {
+    let x = Some(42);
+
+    match x {
+        Some(_) => true,
+        _ => false,
+    };
+
+    match x {
+        None => true,
+        _ => false,
+    };
+
+    match x {
+        Some(_) => false,
+        _ => true,
+    };
+
+    match x {
+        None => false,
+        _ => true,
+    };
+
+    // Don't lint
+    match x {
+        Some(21) => true,
+        _ => false,
+    };
+}
diff --git a/src/tools/clippy/tests/ui/redundant_pattern_matching_option.stderr b/src/tools/clippy/tests/ui/redundant_pattern_matching_option.stderr
index 7c5a047e455..a69eb390520 100644
--- a/src/tools/clippy/tests/ui/redundant_pattern_matching_option.stderr
+++ b/src/tools/clippy/tests/ui/redundant_pattern_matching_option.stderr
@@ -77,49 +77,49 @@ LL |     let _ = if let Some(_) = opt { true } else { false };
    |             -------^^^^^^^------ help: try this: `if opt.is_some()`
 
 error: redundant pattern matching, consider using `is_some()`
-  --> $DIR/redundant_pattern_matching_option.rs:59:20
+  --> $DIR/redundant_pattern_matching_option.rs:60:20
    |
 LL |     let _ = if let Some(_) = gen_opt() {
    |             -------^^^^^^^------------ help: try this: `if gen_opt().is_some()`
 
 error: redundant pattern matching, consider using `is_none()`
-  --> $DIR/redundant_pattern_matching_option.rs:61:19
+  --> $DIR/redundant_pattern_matching_option.rs:62:19
    |
 LL |     } else if let None = gen_opt() {
    |            -------^^^^------------ help: try this: `if gen_opt().is_none()`
 
 error: redundant pattern matching, consider using `is_some()`
-  --> $DIR/redundant_pattern_matching_option.rs:67:12
+  --> $DIR/redundant_pattern_matching_option.rs:68:12
    |
 LL |     if let Some(..) = gen_opt() {}
    |     -------^^^^^^^^------------ help: try this: `if gen_opt().is_some()`
 
 error: redundant pattern matching, consider using `is_some()`
-  --> $DIR/redundant_pattern_matching_option.rs:82:12
+  --> $DIR/redundant_pattern_matching_option.rs:83:12
    |
 LL |     if let Some(_) = Some(42) {}
    |     -------^^^^^^^----------- help: try this: `if Some(42).is_some()`
 
 error: redundant pattern matching, consider using `is_none()`
-  --> $DIR/redundant_pattern_matching_option.rs:84:12
+  --> $DIR/redundant_pattern_matching_option.rs:85:12
    |
 LL |     if let None = None::<()> {}
    |     -------^^^^------------- help: try this: `if None::<()>.is_none()`
 
 error: redundant pattern matching, consider using `is_some()`
-  --> $DIR/redundant_pattern_matching_option.rs:86:15
+  --> $DIR/redundant_pattern_matching_option.rs:87:15
    |
 LL |     while let Some(_) = Some(42) {}
    |     ----------^^^^^^^----------- help: try this: `while Some(42).is_some()`
 
 error: redundant pattern matching, consider using `is_none()`
-  --> $DIR/redundant_pattern_matching_option.rs:88:15
+  --> $DIR/redundant_pattern_matching_option.rs:89:15
    |
 LL |     while let None = None::<()> {}
    |     ----------^^^^------------- help: try this: `while None::<()>.is_none()`
 
 error: redundant pattern matching, consider using `is_some()`
-  --> $DIR/redundant_pattern_matching_option.rs:90:5
+  --> $DIR/redundant_pattern_matching_option.rs:91:5
    |
 LL | /     match Some(42) {
 LL | |         Some(_) => true,
@@ -128,7 +128,7 @@ LL | |     };
    | |_____^ help: try this: `Some(42).is_some()`
 
 error: redundant pattern matching, consider using `is_none()`
-  --> $DIR/redundant_pattern_matching_option.rs:95:5
+  --> $DIR/redundant_pattern_matching_option.rs:96:5
    |
 LL | /     match None::<()> {
 LL | |         Some(_) => false,
@@ -137,16 +137,52 @@ LL | |     };
    | |_____^ help: try this: `None::<()>.is_none()`
 
 error: redundant pattern matching, consider using `is_none()`
-  --> $DIR/redundant_pattern_matching_option.rs:103:12
+  --> $DIR/redundant_pattern_matching_option.rs:104:12
    |
 LL |     if let None = *(&None::<()>) {}
    |     -------^^^^----------------- help: try this: `if (&None::<()>).is_none()`
 
 error: redundant pattern matching, consider using `is_none()`
-  --> $DIR/redundant_pattern_matching_option.rs:104:12
+  --> $DIR/redundant_pattern_matching_option.rs:105:12
    |
 LL |     if let None = *&None::<()> {}
    |     -------^^^^--------------- help: try this: `if (&None::<()>).is_none()`
 
-error: aborting due to 22 previous errors
+error: redundant pattern matching, consider using `is_some()`
+  --> $DIR/redundant_pattern_matching_option.rs:111:5
+   |
+LL | /     match x {
+LL | |         Some(_) => true,
+LL | |         _ => false,
+LL | |     };
+   | |_____^ help: try this: `x.is_some()`
+
+error: redundant pattern matching, consider using `is_none()`
+  --> $DIR/redundant_pattern_matching_option.rs:116:5
+   |
+LL | /     match x {
+LL | |         None => true,
+LL | |         _ => false,
+LL | |     };
+   | |_____^ help: try this: `x.is_none()`
+
+error: redundant pattern matching, consider using `is_none()`
+  --> $DIR/redundant_pattern_matching_option.rs:121:5
+   |
+LL | /     match x {
+LL | |         Some(_) => false,
+LL | |         _ => true,
+LL | |     };
+   | |_____^ help: try this: `x.is_none()`
+
+error: redundant pattern matching, consider using `is_some()`
+  --> $DIR/redundant_pattern_matching_option.rs:126:5
+   |
+LL | /     match x {
+LL | |         None => false,
+LL | |         _ => true,
+LL | |     };
+   | |_____^ help: try this: `x.is_some()`
+
+error: aborting due to 26 previous errors
 
diff --git a/src/tools/clippy/tests/ui/redundant_pattern_matching_result.fixed b/src/tools/clippy/tests/ui/redundant_pattern_matching_result.fixed
index c48d1522935..e4032ae44b7 100644
--- a/src/tools/clippy/tests/ui/redundant_pattern_matching_result.fixed
+++ b/src/tools/clippy/tests/ui/redundant_pattern_matching_result.fixed
@@ -43,6 +43,7 @@ fn main() {
     issue5504();
     issue6067();
     issue6065();
+    issue10726();
 
     let _ = if gen_res().is_ok() {
         1
@@ -107,3 +108,28 @@ const fn issue6067() {
 
     Err::<i32, i32>(42).is_err();
 }
+
+fn issue10726() {
+    // This is optional, but it makes the examples easier
+    let x: Result<i32, i32> = Ok(42);
+
+    x.is_ok();
+
+    x.is_err();
+
+    x.is_err();
+
+    x.is_ok();
+
+    // Don't lint
+    match x {
+        Err(16) => false,
+        _ => true,
+    };
+
+    // Don't lint
+    match x {
+        Ok(16) => false,
+        _ => true,
+    };
+}
diff --git a/src/tools/clippy/tests/ui/redundant_pattern_matching_result.rs b/src/tools/clippy/tests/ui/redundant_pattern_matching_result.rs
index 26f37d169fa..39eb10df878 100644
--- a/src/tools/clippy/tests/ui/redundant_pattern_matching_result.rs
+++ b/src/tools/clippy/tests/ui/redundant_pattern_matching_result.rs
@@ -55,6 +55,7 @@ fn main() {
     issue5504();
     issue6067();
     issue6065();
+    issue10726();
 
     let _ = if let Ok(_) = gen_res() {
         1
@@ -125,3 +126,40 @@ const fn issue6067() {
         Err(_) => true,
     };
 }
+
+fn issue10726() {
+    // This is optional, but it makes the examples easier
+    let x: Result<i32, i32> = Ok(42);
+
+    match x {
+        Ok(_) => true,
+        _ => false,
+    };
+
+    match x {
+        Ok(_) => false,
+        _ => true,
+    };
+
+    match x {
+        Err(_) => true,
+        _ => false,
+    };
+
+    match x {
+        Err(_) => false,
+        _ => true,
+    };
+
+    // Don't lint
+    match x {
+        Err(16) => false,
+        _ => true,
+    };
+
+    // Don't lint
+    match x {
+        Ok(16) => false,
+        _ => true,
+    };
+}
diff --git a/src/tools/clippy/tests/ui/redundant_pattern_matching_result.stderr b/src/tools/clippy/tests/ui/redundant_pattern_matching_result.stderr
index d6a46babb77..5893ae4dcc4 100644
--- a/src/tools/clippy/tests/ui/redundant_pattern_matching_result.stderr
+++ b/src/tools/clippy/tests/ui/redundant_pattern_matching_result.stderr
@@ -73,67 +73,67 @@ LL |     let _ = if let Ok(_) = Ok::<usize, ()>(4) { true } else { false };
    |             -------^^^^^--------------------- help: try this: `if Ok::<usize, ()>(4).is_ok()`
 
 error: redundant pattern matching, consider using `is_ok()`
-  --> $DIR/redundant_pattern_matching_result.rs:59:20
+  --> $DIR/redundant_pattern_matching_result.rs:60:20
    |
 LL |     let _ = if let Ok(_) = gen_res() {
    |             -------^^^^^------------ help: try this: `if gen_res().is_ok()`
 
 error: redundant pattern matching, consider using `is_err()`
-  --> $DIR/redundant_pattern_matching_result.rs:61:19
+  --> $DIR/redundant_pattern_matching_result.rs:62:19
    |
 LL |     } else if let Err(_) = gen_res() {
    |            -------^^^^^^------------ help: try this: `if gen_res().is_err()`
 
 error: redundant pattern matching, consider using `is_some()`
-  --> $DIR/redundant_pattern_matching_result.rs:84:19
+  --> $DIR/redundant_pattern_matching_result.rs:85:19
    |
 LL |         while let Some(_) = r#try!(result_opt()) {}
    |         ----------^^^^^^^----------------------- help: try this: `while r#try!(result_opt()).is_some()`
 
 error: redundant pattern matching, consider using `is_some()`
-  --> $DIR/redundant_pattern_matching_result.rs:85:16
+  --> $DIR/redundant_pattern_matching_result.rs:86:16
    |
 LL |         if let Some(_) = r#try!(result_opt()) {}
    |         -------^^^^^^^----------------------- help: try this: `if r#try!(result_opt()).is_some()`
 
 error: redundant pattern matching, consider using `is_some()`
-  --> $DIR/redundant_pattern_matching_result.rs:91:12
+  --> $DIR/redundant_pattern_matching_result.rs:92:12
    |
 LL |     if let Some(_) = m!() {}
    |     -------^^^^^^^------- help: try this: `if m!().is_some()`
 
 error: redundant pattern matching, consider using `is_some()`
-  --> $DIR/redundant_pattern_matching_result.rs:92:15
+  --> $DIR/redundant_pattern_matching_result.rs:93:15
    |
 LL |     while let Some(_) = m!() {}
    |     ----------^^^^^^^------- help: try this: `while m!().is_some()`
 
 error: redundant pattern matching, consider using `is_ok()`
-  --> $DIR/redundant_pattern_matching_result.rs:110:12
+  --> $DIR/redundant_pattern_matching_result.rs:111:12
    |
 LL |     if let Ok(_) = Ok::<i32, i32>(42) {}
    |     -------^^^^^--------------------- help: try this: `if Ok::<i32, i32>(42).is_ok()`
 
 error: redundant pattern matching, consider using `is_err()`
-  --> $DIR/redundant_pattern_matching_result.rs:112:12
+  --> $DIR/redundant_pattern_matching_result.rs:113:12
    |
 LL |     if let Err(_) = Err::<i32, i32>(42) {}
    |     -------^^^^^^---------------------- help: try this: `if Err::<i32, i32>(42).is_err()`
 
 error: redundant pattern matching, consider using `is_ok()`
-  --> $DIR/redundant_pattern_matching_result.rs:114:15
+  --> $DIR/redundant_pattern_matching_result.rs:115:15
    |
 LL |     while let Ok(_) = Ok::<i32, i32>(10) {}
    |     ----------^^^^^--------------------- help: try this: `while Ok::<i32, i32>(10).is_ok()`
 
 error: redundant pattern matching, consider using `is_err()`
-  --> $DIR/redundant_pattern_matching_result.rs:116:15
+  --> $DIR/redundant_pattern_matching_result.rs:117:15
    |
 LL |     while let Err(_) = Ok::<i32, i32>(10) {}
    |     ----------^^^^^^--------------------- help: try this: `while Ok::<i32, i32>(10).is_err()`
 
 error: redundant pattern matching, consider using `is_ok()`
-  --> $DIR/redundant_pattern_matching_result.rs:118:5
+  --> $DIR/redundant_pattern_matching_result.rs:119:5
    |
 LL | /     match Ok::<i32, i32>(42) {
 LL | |         Ok(_) => true,
@@ -142,7 +142,7 @@ LL | |     };
    | |_____^ help: try this: `Ok::<i32, i32>(42).is_ok()`
 
 error: redundant pattern matching, consider using `is_err()`
-  --> $DIR/redundant_pattern_matching_result.rs:123:5
+  --> $DIR/redundant_pattern_matching_result.rs:124:5
    |
 LL | /     match Err::<i32, i32>(42) {
 LL | |         Ok(_) => false,
@@ -150,5 +150,41 @@ LL | |         Err(_) => true,
 LL | |     };
    | |_____^ help: try this: `Err::<i32, i32>(42).is_err()`
 
-error: aborting due to 22 previous errors
+error: redundant pattern matching, consider using `is_ok()`
+  --> $DIR/redundant_pattern_matching_result.rs:134:5
+   |
+LL | /     match x {
+LL | |         Ok(_) => true,
+LL | |         _ => false,
+LL | |     };
+   | |_____^ help: try this: `x.is_ok()`
+
+error: redundant pattern matching, consider using `is_err()`
+  --> $DIR/redundant_pattern_matching_result.rs:139:5
+   |
+LL | /     match x {
+LL | |         Ok(_) => false,
+LL | |         _ => true,
+LL | |     };
+   | |_____^ help: try this: `x.is_err()`
+
+error: redundant pattern matching, consider using `is_err()`
+  --> $DIR/redundant_pattern_matching_result.rs:144:5
+   |
+LL | /     match x {
+LL | |         Err(_) => true,
+LL | |         _ => false,
+LL | |     };
+   | |_____^ help: try this: `x.is_err()`
+
+error: redundant pattern matching, consider using `is_ok()`
+  --> $DIR/redundant_pattern_matching_result.rs:149:5
+   |
+LL | /     match x {
+LL | |         Err(_) => false,
+LL | |         _ => true,
+LL | |     };
+   | |_____^ help: try this: `x.is_ok()`
+
+error: aborting due to 26 previous errors
 
diff --git a/src/tools/clippy/tests/ui/ref_patterns.rs b/src/tools/clippy/tests/ui/ref_patterns.rs
new file mode 100644
index 00000000000..c51e0bc76ef
--- /dev/null
+++ b/src/tools/clippy/tests/ui/ref_patterns.rs
@@ -0,0 +1,19 @@
+#![allow(unused)]
+#![warn(clippy::ref_patterns)]
+
+fn use_in_pattern() {
+    let opt = Some(5);
+    match opt {
+        None => {},
+        Some(ref opt) => {},
+    }
+}
+
+fn use_in_binding() {
+    let x = 5;
+    let ref y = x;
+}
+
+fn use_in_parameter(ref x: i32) {}
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui/ref_patterns.stderr b/src/tools/clippy/tests/ui/ref_patterns.stderr
new file mode 100644
index 00000000000..aa007782683
--- /dev/null
+++ b/src/tools/clippy/tests/ui/ref_patterns.stderr
@@ -0,0 +1,27 @@
+error: usage of ref pattern
+  --> $DIR/ref_patterns.rs:8:14
+   |
+LL |         Some(ref opt) => {},
+   |              ^^^^^^^
+   |
+   = help: consider using `&` for clarity instead
+   = note: `-D clippy::ref-patterns` implied by `-D warnings`
+
+error: usage of ref pattern
+  --> $DIR/ref_patterns.rs:14:9
+   |
+LL |     let ref y = x;
+   |         ^^^^^
+   |
+   = help: consider using `&` for clarity instead
+
+error: usage of ref pattern
+  --> $DIR/ref_patterns.rs:17:21
+   |
+LL | fn use_in_parameter(ref x: i32) {}
+   |                     ^^^^^
+   |
+   = help: consider using `&` for clarity instead
+
+error: aborting due to 3 previous errors
+
diff --git a/src/tools/clippy/tests/ui/regex.rs b/src/tools/clippy/tests/ui/regex.rs
index ab8ac97a0e7..a5f79b139bc 100644
--- a/src/tools/clippy/tests/ui/regex.rs
+++ b/src/tools/clippy/tests/ui/regex.rs
@@ -34,8 +34,10 @@ fn syntax_error() {
     let set_error = RegexSet::new(&[OPENING_PAREN, r"[a-z]+\.(com|org|net)"]);
     let bset_error = BRegexSet::new(&[OPENING_PAREN, r"[a-z]+\.(com|org|net)"]);
 
+    // These following three cases are considering valid since regex-1.8.0
     let raw_string_error = Regex::new(r"[...\/...]");
     let raw_string_error = Regex::new(r#"[...\/...]"#);
+    let _ = Regex::new(r"(?<hi>hi)").unwrap();
 
     let escaped_string_span = Regex::new("\\b\\c");
 
diff --git a/src/tools/clippy/tests/ui/regex.stderr b/src/tools/clippy/tests/ui/regex.stderr
index c2440f39e0a..6b8a772e7f0 100644
--- a/src/tools/clippy/tests/ui/regex.stderr
+++ b/src/tools/clippy/tests/ui/regex.stderr
@@ -82,23 +82,11 @@ error: regex parse error:
 LL |     let bset_error = BRegexSet::new(&[OPENING_PAREN, r"[a-z]+/.(com|org|net)"]);
    |                                       ^^^^^^^^^^^^^
 
-error: regex syntax error: unrecognized escape sequence
-  --> $DIR/regex.rs:37:45
-   |
-LL |     let raw_string_error = Regex::new(r"[...//...]");
-   |                                             ^^
-
-error: regex syntax error: unrecognized escape sequence
-  --> $DIR/regex.rs:38:46
-   |
-LL |     let raw_string_error = Regex::new(r#"[...//...]"#);
-   |                                              ^^
-
 error: regex parse error:
            /b/c
              ^^
        error: unrecognized escape sequence
-  --> $DIR/regex.rs:40:42
+  --> $DIR/regex.rs:42:42
    |
 LL |     let escaped_string_span = Regex::new("/b/c");
    |                                          ^^^^^^^^
@@ -106,13 +94,13 @@ LL |     let escaped_string_span = Regex::new("/b/c");
    = help: consider using a raw string literal: `r".."`
 
 error: regex syntax error: duplicate flag
-  --> $DIR/regex.rs:42:34
+  --> $DIR/regex.rs:44:34
    |
 LL |     let aux_span = Regex::new("(?ixi)");
    |                                  ^ ^
 
 error: trivial regex
-  --> $DIR/regex.rs:46:33
+  --> $DIR/regex.rs:48:33
    |
 LL |     let trivial_eq = Regex::new("^foobar$");
    |                                 ^^^^^^^^^^
@@ -120,7 +108,7 @@ LL |     let trivial_eq = Regex::new("^foobar$");
    = help: consider using `==` on `str`s
 
 error: trivial regex
-  --> $DIR/regex.rs:48:48
+  --> $DIR/regex.rs:50:48
    |
 LL |     let trivial_eq_builder = RegexBuilder::new("^foobar$");
    |                                                ^^^^^^^^^^
@@ -128,7 +116,7 @@ LL |     let trivial_eq_builder = RegexBuilder::new("^foobar$");
    = help: consider using `==` on `str`s
 
 error: trivial regex
-  --> $DIR/regex.rs:50:42
+  --> $DIR/regex.rs:52:42
    |
 LL |     let trivial_starts_with = Regex::new("^foobar");
    |                                          ^^^^^^^^^
@@ -136,7 +124,7 @@ LL |     let trivial_starts_with = Regex::new("^foobar");
    = help: consider using `str::starts_with`
 
 error: trivial regex
-  --> $DIR/regex.rs:52:40
+  --> $DIR/regex.rs:54:40
    |
 LL |     let trivial_ends_with = Regex::new("foobar$");
    |                                        ^^^^^^^^^
@@ -144,7 +132,7 @@ LL |     let trivial_ends_with = Regex::new("foobar$");
    = help: consider using `str::ends_with`
 
 error: trivial regex
-  --> $DIR/regex.rs:54:39
+  --> $DIR/regex.rs:56:39
    |
 LL |     let trivial_contains = Regex::new("foobar");
    |                                       ^^^^^^^^
@@ -152,7 +140,7 @@ LL |     let trivial_contains = Regex::new("foobar");
    = help: consider using `str::contains`
 
 error: trivial regex
-  --> $DIR/regex.rs:56:39
+  --> $DIR/regex.rs:58:39
    |
 LL |     let trivial_contains = Regex::new(NOT_A_REAL_REGEX);
    |                                       ^^^^^^^^^^^^^^^^
@@ -160,7 +148,7 @@ LL |     let trivial_contains = Regex::new(NOT_A_REAL_REGEX);
    = help: consider using `str::contains`
 
 error: trivial regex
-  --> $DIR/regex.rs:58:40
+  --> $DIR/regex.rs:60:40
    |
 LL |     let trivial_backslash = Regex::new("a/.b");
    |                                        ^^^^^^^
@@ -168,7 +156,7 @@ LL |     let trivial_backslash = Regex::new("a/.b");
    = help: consider using `str::contains`
 
 error: trivial regex
-  --> $DIR/regex.rs:61:36
+  --> $DIR/regex.rs:63:36
    |
 LL |     let trivial_empty = Regex::new("");
    |                                    ^^
@@ -176,7 +164,7 @@ LL |     let trivial_empty = Regex::new("");
    = help: the regex is unlikely to be useful as it is
 
 error: trivial regex
-  --> $DIR/regex.rs:63:36
+  --> $DIR/regex.rs:65:36
    |
 LL |     let trivial_empty = Regex::new("^");
    |                                    ^^^
@@ -184,7 +172,7 @@ LL |     let trivial_empty = Regex::new("^");
    = help: the regex is unlikely to be useful as it is
 
 error: trivial regex
-  --> $DIR/regex.rs:65:36
+  --> $DIR/regex.rs:67:36
    |
 LL |     let trivial_empty = Regex::new("^$");
    |                                    ^^^^
@@ -192,12 +180,12 @@ LL |     let trivial_empty = Regex::new("^$");
    = help: consider using `str::is_empty`
 
 error: trivial regex
-  --> $DIR/regex.rs:67:44
+  --> $DIR/regex.rs:69:44
    |
 LL |     let binary_trivial_empty = BRegex::new("^$");
    |                                            ^^^^
    |
    = help: consider using `str::is_empty`
 
-error: aborting due to 25 previous errors
+error: aborting due to 23 previous errors
 
diff --git a/src/tools/clippy/tests/ui/rename.fixed b/src/tools/clippy/tests/ui/rename.fixed
index 42a59f6d43d..dfe45dec8a7 100644
--- a/src/tools/clippy/tests/ui/rename.fixed
+++ b/src/tools/clippy/tests/ui/rename.fixed
@@ -16,6 +16,7 @@
 #![allow(clippy::mixed_read_write_in_expression)]
 #![allow(clippy::useless_conversion)]
 #![allow(clippy::match_result_ok)]
+#![allow(clippy::arithmetic_side_effects)]
 #![allow(clippy::overly_complex_bool_expr)]
 #![allow(clippy::new_without_default)]
 #![allow(clippy::bind_instead_of_map)]
@@ -29,7 +30,11 @@
 #![allow(clippy::invisible_characters)]
 #![allow(suspicious_double_ref_op)]
 #![allow(drop_bounds)]
+#![allow(dropping_copy_types)]
+#![allow(dropping_references)]
 #![allow(for_loops_over_fallibles)]
+#![allow(forgetting_copy_types)]
+#![allow(forgetting_references)]
 #![allow(array_into_iter)]
 #![allow(invalid_atomic_ordering)]
 #![allow(invalid_value)]
@@ -54,6 +59,7 @@
 #![warn(clippy::mixed_read_write_in_expression)]
 #![warn(clippy::useless_conversion)]
 #![warn(clippy::match_result_ok)]
+#![warn(clippy::arithmetic_side_effects)]
 #![warn(clippy::overly_complex_bool_expr)]
 #![warn(clippy::new_without_default)]
 #![warn(clippy::bind_instead_of_map)]
@@ -71,9 +77,13 @@
 #![warn(clippy::invisible_characters)]
 #![warn(suspicious_double_ref_op)]
 #![warn(drop_bounds)]
+#![warn(dropping_copy_types)]
+#![warn(dropping_references)]
 #![warn(for_loops_over_fallibles)]
 #![warn(for_loops_over_fallibles)]
 #![warn(for_loops_over_fallibles)]
+#![warn(forgetting_copy_types)]
+#![warn(forgetting_references)]
 #![warn(array_into_iter)]
 #![warn(invalid_atomic_ordering)]
 #![warn(invalid_value)]
diff --git a/src/tools/clippy/tests/ui/rename.rs b/src/tools/clippy/tests/ui/rename.rs
index 4d173e8cbbf..ce8eca5a308 100644
--- a/src/tools/clippy/tests/ui/rename.rs
+++ b/src/tools/clippy/tests/ui/rename.rs
@@ -16,6 +16,7 @@
 #![allow(clippy::mixed_read_write_in_expression)]
 #![allow(clippy::useless_conversion)]
 #![allow(clippy::match_result_ok)]
+#![allow(clippy::arithmetic_side_effects)]
 #![allow(clippy::overly_complex_bool_expr)]
 #![allow(clippy::new_without_default)]
 #![allow(clippy::bind_instead_of_map)]
@@ -29,7 +30,11 @@
 #![allow(clippy::invisible_characters)]
 #![allow(suspicious_double_ref_op)]
 #![allow(drop_bounds)]
+#![allow(dropping_copy_types)]
+#![allow(dropping_references)]
 #![allow(for_loops_over_fallibles)]
+#![allow(forgetting_copy_types)]
+#![allow(forgetting_references)]
 #![allow(array_into_iter)]
 #![allow(invalid_atomic_ordering)]
 #![allow(invalid_value)]
@@ -54,6 +59,7 @@
 #![warn(clippy::eval_order_dependence)]
 #![warn(clippy::identity_conversion)]
 #![warn(clippy::if_let_some_result)]
+#![warn(clippy::integer_arithmetic)]
 #![warn(clippy::logic_bug)]
 #![warn(clippy::new_without_default_derive)]
 #![warn(clippy::option_and_then_some)]
@@ -71,9 +77,13 @@
 #![warn(clippy::zero_width_space)]
 #![warn(clippy::clone_double_ref)]
 #![warn(clippy::drop_bounds)]
+#![warn(clippy::drop_copy)]
+#![warn(clippy::drop_ref)]
 #![warn(clippy::for_loop_over_option)]
 #![warn(clippy::for_loop_over_result)]
 #![warn(clippy::for_loops_over_fallibles)]
+#![warn(clippy::forget_copy)]
+#![warn(clippy::forget_ref)]
 #![warn(clippy::into_iter_on_array)]
 #![warn(clippy::invalid_atomic_ordering)]
 #![warn(clippy::invalid_ref)]
diff --git a/src/tools/clippy/tests/ui/rename.stderr b/src/tools/clippy/tests/ui/rename.stderr
index 0da4ed7520c..3fca60aa2eb 100644
--- a/src/tools/clippy/tests/ui/rename.stderr
+++ b/src/tools/clippy/tests/ui/rename.stderr
@@ -1,5 +1,5 @@
 error: lint `clippy::almost_complete_letter_range` has been renamed to `clippy::almost_complete_range`
-  --> $DIR/rename.rs:44:9
+  --> $DIR/rename.rs:49:9
    |
 LL | #![warn(clippy::almost_complete_letter_range)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::almost_complete_range`
@@ -7,256 +7,286 @@ LL | #![warn(clippy::almost_complete_letter_range)]
    = note: `-D renamed-and-removed-lints` implied by `-D warnings`
 
 error: lint `clippy::blacklisted_name` has been renamed to `clippy::disallowed_names`
-  --> $DIR/rename.rs:45:9
+  --> $DIR/rename.rs:50:9
    |
 LL | #![warn(clippy::blacklisted_name)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::disallowed_names`
 
 error: lint `clippy::block_in_if_condition_expr` has been renamed to `clippy::blocks_in_if_conditions`
-  --> $DIR/rename.rs:46:9
+  --> $DIR/rename.rs:51:9
    |
 LL | #![warn(clippy::block_in_if_condition_expr)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::blocks_in_if_conditions`
 
 error: lint `clippy::block_in_if_condition_stmt` has been renamed to `clippy::blocks_in_if_conditions`
-  --> $DIR/rename.rs:47:9
+  --> $DIR/rename.rs:52:9
    |
 LL | #![warn(clippy::block_in_if_condition_stmt)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::blocks_in_if_conditions`
 
 error: lint `clippy::box_vec` has been renamed to `clippy::box_collection`
-  --> $DIR/rename.rs:48:9
+  --> $DIR/rename.rs:53:9
    |
 LL | #![warn(clippy::box_vec)]
    |         ^^^^^^^^^^^^^^^ help: use the new name: `clippy::box_collection`
 
 error: lint `clippy::const_static_lifetime` has been renamed to `clippy::redundant_static_lifetimes`
-  --> $DIR/rename.rs:49:9
+  --> $DIR/rename.rs:54:9
    |
 LL | #![warn(clippy::const_static_lifetime)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::redundant_static_lifetimes`
 
 error: lint `clippy::cyclomatic_complexity` has been renamed to `clippy::cognitive_complexity`
-  --> $DIR/rename.rs:50:9
+  --> $DIR/rename.rs:55:9
    |
 LL | #![warn(clippy::cyclomatic_complexity)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::cognitive_complexity`
 
 error: lint `clippy::derive_hash_xor_eq` has been renamed to `clippy::derived_hash_with_manual_eq`
-  --> $DIR/rename.rs:51:9
+  --> $DIR/rename.rs:56:9
    |
 LL | #![warn(clippy::derive_hash_xor_eq)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::derived_hash_with_manual_eq`
 
 error: lint `clippy::disallowed_method` has been renamed to `clippy::disallowed_methods`
-  --> $DIR/rename.rs:52:9
+  --> $DIR/rename.rs:57:9
    |
 LL | #![warn(clippy::disallowed_method)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::disallowed_methods`
 
 error: lint `clippy::disallowed_type` has been renamed to `clippy::disallowed_types`
-  --> $DIR/rename.rs:53:9
+  --> $DIR/rename.rs:58:9
    |
 LL | #![warn(clippy::disallowed_type)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::disallowed_types`
 
 error: lint `clippy::eval_order_dependence` has been renamed to `clippy::mixed_read_write_in_expression`
-  --> $DIR/rename.rs:54:9
+  --> $DIR/rename.rs:59:9
    |
 LL | #![warn(clippy::eval_order_dependence)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::mixed_read_write_in_expression`
 
 error: lint `clippy::identity_conversion` has been renamed to `clippy::useless_conversion`
-  --> $DIR/rename.rs:55:9
+  --> $DIR/rename.rs:60:9
    |
 LL | #![warn(clippy::identity_conversion)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::useless_conversion`
 
 error: lint `clippy::if_let_some_result` has been renamed to `clippy::match_result_ok`
-  --> $DIR/rename.rs:56:9
+  --> $DIR/rename.rs:61:9
    |
 LL | #![warn(clippy::if_let_some_result)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::match_result_ok`
 
+error: lint `clippy::integer_arithmetic` has been renamed to `clippy::arithmetic_side_effects`
+  --> $DIR/rename.rs:62:9
+   |
+LL | #![warn(clippy::integer_arithmetic)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::arithmetic_side_effects`
+
 error: lint `clippy::logic_bug` has been renamed to `clippy::overly_complex_bool_expr`
-  --> $DIR/rename.rs:57:9
+  --> $DIR/rename.rs:63:9
    |
 LL | #![warn(clippy::logic_bug)]
    |         ^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::overly_complex_bool_expr`
 
 error: lint `clippy::new_without_default_derive` has been renamed to `clippy::new_without_default`
-  --> $DIR/rename.rs:58:9
+  --> $DIR/rename.rs:64:9
    |
 LL | #![warn(clippy::new_without_default_derive)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::new_without_default`
 
 error: lint `clippy::option_and_then_some` has been renamed to `clippy::bind_instead_of_map`
-  --> $DIR/rename.rs:59:9
+  --> $DIR/rename.rs:65:9
    |
 LL | #![warn(clippy::option_and_then_some)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::bind_instead_of_map`
 
 error: lint `clippy::option_expect_used` has been renamed to `clippy::expect_used`
-  --> $DIR/rename.rs:60:9
+  --> $DIR/rename.rs:66:9
    |
 LL | #![warn(clippy::option_expect_used)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::expect_used`
 
 error: lint `clippy::option_map_unwrap_or` has been renamed to `clippy::map_unwrap_or`
-  --> $DIR/rename.rs:61:9
+  --> $DIR/rename.rs:67:9
    |
 LL | #![warn(clippy::option_map_unwrap_or)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::map_unwrap_or`
 
 error: lint `clippy::option_map_unwrap_or_else` has been renamed to `clippy::map_unwrap_or`
-  --> $DIR/rename.rs:62:9
+  --> $DIR/rename.rs:68:9
    |
 LL | #![warn(clippy::option_map_unwrap_or_else)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::map_unwrap_or`
 
 error: lint `clippy::option_unwrap_used` has been renamed to `clippy::unwrap_used`
-  --> $DIR/rename.rs:63:9
+  --> $DIR/rename.rs:69:9
    |
 LL | #![warn(clippy::option_unwrap_used)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::unwrap_used`
 
 error: lint `clippy::ref_in_deref` has been renamed to `clippy::needless_borrow`
-  --> $DIR/rename.rs:64:9
+  --> $DIR/rename.rs:70:9
    |
 LL | #![warn(clippy::ref_in_deref)]
    |         ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::needless_borrow`
 
 error: lint `clippy::result_expect_used` has been renamed to `clippy::expect_used`
-  --> $DIR/rename.rs:65:9
+  --> $DIR/rename.rs:71:9
    |
 LL | #![warn(clippy::result_expect_used)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::expect_used`
 
 error: lint `clippy::result_map_unwrap_or_else` has been renamed to `clippy::map_unwrap_or`
-  --> $DIR/rename.rs:66:9
+  --> $DIR/rename.rs:72:9
    |
 LL | #![warn(clippy::result_map_unwrap_or_else)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::map_unwrap_or`
 
 error: lint `clippy::result_unwrap_used` has been renamed to `clippy::unwrap_used`
-  --> $DIR/rename.rs:67:9
+  --> $DIR/rename.rs:73:9
    |
 LL | #![warn(clippy::result_unwrap_used)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::unwrap_used`
 
 error: lint `clippy::single_char_push_str` has been renamed to `clippy::single_char_add_str`
-  --> $DIR/rename.rs:68:9
+  --> $DIR/rename.rs:74:9
    |
 LL | #![warn(clippy::single_char_push_str)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::single_char_add_str`
 
 error: lint `clippy::stutter` has been renamed to `clippy::module_name_repetitions`
-  --> $DIR/rename.rs:69:9
+  --> $DIR/rename.rs:75:9
    |
 LL | #![warn(clippy::stutter)]
    |         ^^^^^^^^^^^^^^^ help: use the new name: `clippy::module_name_repetitions`
 
 error: lint `clippy::to_string_in_display` has been renamed to `clippy::recursive_format_impl`
-  --> $DIR/rename.rs:70:9
+  --> $DIR/rename.rs:76:9
    |
 LL | #![warn(clippy::to_string_in_display)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::recursive_format_impl`
 
 error: lint `clippy::zero_width_space` has been renamed to `clippy::invisible_characters`
-  --> $DIR/rename.rs:71:9
+  --> $DIR/rename.rs:77:9
    |
 LL | #![warn(clippy::zero_width_space)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::invisible_characters`
 
 error: lint `clippy::clone_double_ref` has been renamed to `suspicious_double_ref_op`
-  --> $DIR/rename.rs:72:9
+  --> $DIR/rename.rs:78:9
    |
 LL | #![warn(clippy::clone_double_ref)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `suspicious_double_ref_op`
 
 error: lint `clippy::drop_bounds` has been renamed to `drop_bounds`
-  --> $DIR/rename.rs:73:9
+  --> $DIR/rename.rs:79:9
    |
 LL | #![warn(clippy::drop_bounds)]
    |         ^^^^^^^^^^^^^^^^^^^ help: use the new name: `drop_bounds`
 
+error: lint `clippy::drop_copy` has been renamed to `dropping_copy_types`
+  --> $DIR/rename.rs:80:9
+   |
+LL | #![warn(clippy::drop_copy)]
+   |         ^^^^^^^^^^^^^^^^^ help: use the new name: `dropping_copy_types`
+
+error: lint `clippy::drop_ref` has been renamed to `dropping_references`
+  --> $DIR/rename.rs:81:9
+   |
+LL | #![warn(clippy::drop_ref)]
+   |         ^^^^^^^^^^^^^^^^ help: use the new name: `dropping_references`
+
 error: lint `clippy::for_loop_over_option` has been renamed to `for_loops_over_fallibles`
-  --> $DIR/rename.rs:74:9
+  --> $DIR/rename.rs:82:9
    |
 LL | #![warn(clippy::for_loop_over_option)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `for_loops_over_fallibles`
 
 error: lint `clippy::for_loop_over_result` has been renamed to `for_loops_over_fallibles`
-  --> $DIR/rename.rs:75:9
+  --> $DIR/rename.rs:83:9
    |
 LL | #![warn(clippy::for_loop_over_result)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `for_loops_over_fallibles`
 
 error: lint `clippy::for_loops_over_fallibles` has been renamed to `for_loops_over_fallibles`
-  --> $DIR/rename.rs:76:9
+  --> $DIR/rename.rs:84:9
    |
 LL | #![warn(clippy::for_loops_over_fallibles)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `for_loops_over_fallibles`
 
+error: lint `clippy::forget_copy` has been renamed to `forgetting_copy_types`
+  --> $DIR/rename.rs:85:9
+   |
+LL | #![warn(clippy::forget_copy)]
+   |         ^^^^^^^^^^^^^^^^^^^ help: use the new name: `forgetting_copy_types`
+
+error: lint `clippy::forget_ref` has been renamed to `forgetting_references`
+  --> $DIR/rename.rs:86:9
+   |
+LL | #![warn(clippy::forget_ref)]
+   |         ^^^^^^^^^^^^^^^^^^ help: use the new name: `forgetting_references`
+
 error: lint `clippy::into_iter_on_array` has been renamed to `array_into_iter`
-  --> $DIR/rename.rs:77:9
+  --> $DIR/rename.rs:87:9
    |
 LL | #![warn(clippy::into_iter_on_array)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `array_into_iter`
 
 error: lint `clippy::invalid_atomic_ordering` has been renamed to `invalid_atomic_ordering`
-  --> $DIR/rename.rs:78:9
+  --> $DIR/rename.rs:88:9
    |
 LL | #![warn(clippy::invalid_atomic_ordering)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_atomic_ordering`
 
 error: lint `clippy::invalid_ref` has been renamed to `invalid_value`
-  --> $DIR/rename.rs:79:9
+  --> $DIR/rename.rs:89:9
    |
 LL | #![warn(clippy::invalid_ref)]
    |         ^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_value`
 
 error: lint `clippy::let_underscore_drop` has been renamed to `let_underscore_drop`
-  --> $DIR/rename.rs:80:9
+  --> $DIR/rename.rs:90:9
    |
 LL | #![warn(clippy::let_underscore_drop)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `let_underscore_drop`
 
 error: lint `clippy::mem_discriminant_non_enum` has been renamed to `enum_intrinsics_non_enums`
-  --> $DIR/rename.rs:81:9
+  --> $DIR/rename.rs:91:9
    |
 LL | #![warn(clippy::mem_discriminant_non_enum)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `enum_intrinsics_non_enums`
 
 error: lint `clippy::panic_params` has been renamed to `non_fmt_panics`
-  --> $DIR/rename.rs:82:9
+  --> $DIR/rename.rs:92:9
    |
 LL | #![warn(clippy::panic_params)]
    |         ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `non_fmt_panics`
 
 error: lint `clippy::positional_named_format_parameters` has been renamed to `named_arguments_used_positionally`
-  --> $DIR/rename.rs:83:9
+  --> $DIR/rename.rs:93:9
    |
 LL | #![warn(clippy::positional_named_format_parameters)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `named_arguments_used_positionally`
 
 error: lint `clippy::temporary_cstring_as_ptr` has been renamed to `temporary_cstring_as_ptr`
-  --> $DIR/rename.rs:84:9
+  --> $DIR/rename.rs:94:9
    |
 LL | #![warn(clippy::temporary_cstring_as_ptr)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `temporary_cstring_as_ptr`
 
 error: lint `clippy::unknown_clippy_lints` has been renamed to `unknown_lints`
-  --> $DIR/rename.rs:85:9
+  --> $DIR/rename.rs:95:9
    |
 LL | #![warn(clippy::unknown_clippy_lints)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unknown_lints`
 
 error: lint `clippy::unused_label` has been renamed to `unused_labels`
-  --> $DIR/rename.rs:86:9
+  --> $DIR/rename.rs:96:9
    |
 LL | #![warn(clippy::unused_label)]
    |         ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unused_labels`
 
-error: aborting due to 43 previous errors
+error: aborting due to 48 previous errors
 
diff --git a/src/tools/clippy/tests/ui/trait_duplication_in_bounds.fixed b/src/tools/clippy/tests/ui/trait_duplication_in_bounds.fixed
index eef8024b131..fdac0e4cb1e 100644
--- a/src/tools/clippy/tests/ui/trait_duplication_in_bounds.fixed
+++ b/src/tools/clippy/tests/ui/trait_duplication_in_bounds.fixed
@@ -2,6 +2,8 @@
 #![deny(clippy::trait_duplication_in_bounds)]
 #![allow(unused)]
 
+use std::any::Any;
+
 fn bad_foo<T: Clone + Copy, U: Clone + Copy>(arg0: T, argo1: U) {
     unimplemented!();
 }
@@ -109,4 +111,12 @@ fn qualified_path<T: std::clone::Clone + foo::Clone>(arg0: T) {
     unimplemented!();
 }
 
+fn good_trait_object(arg0: &(dyn Any + Send)) {
+    unimplemented!();
+}
+
+fn bad_trait_object(arg0: &(dyn Any + Send)) {
+    unimplemented!();
+}
+
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/trait_duplication_in_bounds.rs b/src/tools/clippy/tests/ui/trait_duplication_in_bounds.rs
index a7a1caf2880..a0300da5555 100644
--- a/src/tools/clippy/tests/ui/trait_duplication_in_bounds.rs
+++ b/src/tools/clippy/tests/ui/trait_duplication_in_bounds.rs
@@ -2,6 +2,8 @@
 #![deny(clippy::trait_duplication_in_bounds)]
 #![allow(unused)]
 
+use std::any::Any;
+
 fn bad_foo<T: Clone + Clone + Clone + Copy, U: Clone + Copy>(arg0: T, argo1: U) {
     unimplemented!();
 }
@@ -109,4 +111,12 @@ fn qualified_path<T: std::clone::Clone + Clone + foo::Clone>(arg0: T) {
     unimplemented!();
 }
 
+fn good_trait_object(arg0: &(dyn Any + Send)) {
+    unimplemented!();
+}
+
+fn bad_trait_object(arg0: &(dyn Any + Send + Send)) {
+    unimplemented!();
+}
+
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/trait_duplication_in_bounds.stderr b/src/tools/clippy/tests/ui/trait_duplication_in_bounds.stderr
index af800ba7888..539b6114ca3 100644
--- a/src/tools/clippy/tests/ui/trait_duplication_in_bounds.stderr
+++ b/src/tools/clippy/tests/ui/trait_duplication_in_bounds.stderr
@@ -1,5 +1,5 @@
 error: these bounds contain repeated elements
-  --> $DIR/trait_duplication_in_bounds.rs:5:15
+  --> $DIR/trait_duplication_in_bounds.rs:7:15
    |
 LL | fn bad_foo<T: Clone + Clone + Clone + Copy, U: Clone + Copy>(arg0: T, argo1: U) {
    |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Clone + Copy`
@@ -11,46 +11,52 @@ LL | #![deny(clippy::trait_duplication_in_bounds)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: these where clauses contain repeated elements
-  --> $DIR/trait_duplication_in_bounds.rs:11:8
+  --> $DIR/trait_duplication_in_bounds.rs:13:8
    |
 LL |     T: Clone + Clone + Clone + Copy,
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Clone + Copy`
 
 error: these bounds contain repeated elements
-  --> $DIR/trait_duplication_in_bounds.rs:39:26
+  --> $DIR/trait_duplication_in_bounds.rs:41:26
    |
 LL | trait BadSelfTraitBound: Clone + Clone + Clone {
    |                          ^^^^^^^^^^^^^^^^^^^^^ help: try: `Clone`
 
 error: these where clauses contain repeated elements
-  --> $DIR/trait_duplication_in_bounds.rs:46:15
+  --> $DIR/trait_duplication_in_bounds.rs:48:15
    |
 LL |         Self: Clone + Clone + Clone;
    |               ^^^^^^^^^^^^^^^^^^^^^ help: try: `Clone`
 
 error: these bounds contain repeated elements
-  --> $DIR/trait_duplication_in_bounds.rs:60:24
+  --> $DIR/trait_duplication_in_bounds.rs:62:24
    |
 LL | trait BadTraitBound<T: Clone + Clone + Clone + Copy, U: Clone + Copy> {
    |                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Clone + Copy`
 
 error: these where clauses contain repeated elements
-  --> $DIR/trait_duplication_in_bounds.rs:67:12
+  --> $DIR/trait_duplication_in_bounds.rs:69:12
    |
 LL |         T: Clone + Clone + Clone + Copy,
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Clone + Copy`
 
 error: these bounds contain repeated elements
-  --> $DIR/trait_duplication_in_bounds.rs:100:19
+  --> $DIR/trait_duplication_in_bounds.rs:102:19
    |
 LL | fn bad_generic<T: GenericTrait<u64> + GenericTrait<u32> + GenericTrait<u64>>(arg0: T) {
    |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `GenericTrait<u64> + GenericTrait<u32>`
 
 error: these bounds contain repeated elements
-  --> $DIR/trait_duplication_in_bounds.rs:108:22
+  --> $DIR/trait_duplication_in_bounds.rs:110:22
    |
 LL | fn qualified_path<T: std::clone::Clone + Clone + foo::Clone>(arg0: T) {
    |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::clone::Clone + foo::Clone`
 
-error: aborting due to 8 previous errors
+error: this trait bound is already specified in trait declaration
+  --> $DIR/trait_duplication_in_bounds.rs:118:33
+   |
+LL | fn bad_trait_object(arg0: &(dyn Any + Send + Send)) {
+   |                                 ^^^^^^^^^^^^^^^^^ help: try: `Any + Send`
+
+error: aborting due to 9 previous errors
 
diff --git a/src/tools/clippy/tests/ui/unknown_clippy_lints.fixed b/src/tools/clippy/tests/ui/unknown_clippy_lints.fixed
index 0c269d650c8..49c0e4dc7eb 100644
--- a/src/tools/clippy/tests/ui/unknown_clippy_lints.fixed
+++ b/src/tools/clippy/tests/ui/unknown_clippy_lints.fixed
@@ -10,7 +10,7 @@
 #[warn(clippy::unnecessary_cast)]
 #[warn(clippy::useless_transmute)]
 // Shouldn't suggest rustc lint name(`dead_code`)
-#[warn(clippy::drop_copy)]
+#[warn(clippy::eq_op)]
 // Shouldn't suggest removed/deprecated clippy lint name(`unused_collect`)
 #[warn(clippy::unused_self)]
 // Shouldn't suggest renamed clippy lint name(`const_static_lifetime`)
diff --git a/src/tools/clippy/tests/ui/unknown_clippy_lints.stderr b/src/tools/clippy/tests/ui/unknown_clippy_lints.stderr
index 421bf5ffa9a..584c428932f 100644
--- a/src/tools/clippy/tests/ui/unknown_clippy_lints.stderr
+++ b/src/tools/clippy/tests/ui/unknown_clippy_lints.stderr
@@ -34,7 +34,7 @@ error: unknown lint: `clippy::dead_cod`
   --> $DIR/unknown_clippy_lints.rs:13:8
    |
 LL | #[warn(clippy::dead_cod)]
-   |        ^^^^^^^^^^^^^^^^ help: did you mean: `clippy::drop_copy`
+   |        ^^^^^^^^^^^^^^^^ help: did you mean: `clippy::eq_op`
 
 error: unknown lint: `clippy::unused_colle`
   --> $DIR/unknown_clippy_lints.rs:15:8
diff --git a/src/tools/clippy/tests/ui/useless_conversion.fixed b/src/tools/clippy/tests/ui/useless_conversion.fixed
index 01eb6c5b080..c16caa38fe9 100644
--- a/src/tools/clippy/tests/ui/useless_conversion.fixed
+++ b/src/tools/clippy/tests/ui/useless_conversion.fixed
@@ -33,6 +33,11 @@ fn test_issue_3913() -> Result<(), std::io::Error> {
     Ok(())
 }
 
+fn dont_lint_on_type_alias() {
+    type A = i32;
+    _ = A::from(0i32);
+}
+
 fn dont_lint_into_iter_on_immutable_local_implementing_iterator_in_expr() {
     let text = "foo\r\nbar\n\nbaz\n";
     let lines = text.lines();
@@ -106,6 +111,7 @@ fn main() {
     test_questionmark().unwrap();
     test_issue_3913().unwrap();
 
+    dont_lint_on_type_alias();
     dont_lint_into_iter_on_immutable_local_implementing_iterator_in_expr();
     lint_into_iter_on_mutable_local_implementing_iterator_in_expr();
     lint_into_iter_on_expr_implementing_iterator();
diff --git a/src/tools/clippy/tests/ui/useless_conversion.rs b/src/tools/clippy/tests/ui/useless_conversion.rs
index 34b43a6299b..c75a2bce4ca 100644
--- a/src/tools/clippy/tests/ui/useless_conversion.rs
+++ b/src/tools/clippy/tests/ui/useless_conversion.rs
@@ -33,6 +33,11 @@ fn test_issue_3913() -> Result<(), std::io::Error> {
     Ok(())
 }
 
+fn dont_lint_on_type_alias() {
+    type A = i32;
+    _ = A::from(0i32);
+}
+
 fn dont_lint_into_iter_on_immutable_local_implementing_iterator_in_expr() {
     let text = "foo\r\nbar\n\nbaz\n";
     let lines = text.lines();
@@ -106,6 +111,7 @@ fn main() {
     test_questionmark().unwrap();
     test_issue_3913().unwrap();
 
+    dont_lint_on_type_alias();
     dont_lint_into_iter_on_immutable_local_implementing_iterator_in_expr();
     lint_into_iter_on_mutable_local_implementing_iterator_in_expr();
     lint_into_iter_on_expr_implementing_iterator();
diff --git a/src/tools/clippy/tests/ui/useless_conversion.stderr b/src/tools/clippy/tests/ui/useless_conversion.stderr
index be067c6843a..4dca3aac533 100644
--- a/src/tools/clippy/tests/ui/useless_conversion.stderr
+++ b/src/tools/clippy/tests/ui/useless_conversion.stderr
@@ -23,97 +23,97 @@ LL |         let _: i32 = 0i32.into();
    |                      ^^^^^^^^^^^ help: consider removing `.into()`: `0i32`
 
 error: useless conversion to the same type: `std::str::Lines<'_>`
-  --> $DIR/useless_conversion.rs:45:22
+  --> $DIR/useless_conversion.rs:50:22
    |
 LL |     if Some("ok") == lines.into_iter().next() {}
    |                      ^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `lines`
 
 error: useless conversion to the same type: `std::str::Lines<'_>`
-  --> $DIR/useless_conversion.rs:50:21
+  --> $DIR/useless_conversion.rs:55:21
    |
 LL |     let mut lines = text.lines().into_iter();
    |                     ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `text.lines()`
 
 error: useless conversion to the same type: `std::str::Lines<'_>`
-  --> $DIR/useless_conversion.rs:56:22
+  --> $DIR/useless_conversion.rs:61:22
    |
 LL |     if Some("ok") == text.lines().into_iter().next() {}
    |                      ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `text.lines()`
 
 error: useless conversion to the same type: `std::ops::Range<i32>`
-  --> $DIR/useless_conversion.rs:62:13
+  --> $DIR/useless_conversion.rs:67:13
    |
 LL |     let _ = NUMBERS.into_iter().next();
    |             ^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `NUMBERS`
 
 error: useless conversion to the same type: `std::ops::Range<i32>`
-  --> $DIR/useless_conversion.rs:67:17
+  --> $DIR/useless_conversion.rs:72:17
    |
 LL |     let mut n = NUMBERS.into_iter();
    |                 ^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `NUMBERS`
 
 error: useless conversion to the same type: `std::string::String`
-  --> $DIR/useless_conversion.rs:128:21
+  --> $DIR/useless_conversion.rs:134:21
    |
 LL |     let _: String = "foo".to_string().into();
    |                     ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into()`: `"foo".to_string()`
 
 error: useless conversion to the same type: `std::string::String`
-  --> $DIR/useless_conversion.rs:129:21
+  --> $DIR/useless_conversion.rs:135:21
    |
 LL |     let _: String = From::from("foo".to_string());
    |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `From::from()`: `"foo".to_string()`
 
 error: useless conversion to the same type: `std::string::String`
-  --> $DIR/useless_conversion.rs:130:13
+  --> $DIR/useless_conversion.rs:136:13
    |
 LL |     let _ = String::from("foo".to_string());
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `String::from()`: `"foo".to_string()`
 
 error: useless conversion to the same type: `std::string::String`
-  --> $DIR/useless_conversion.rs:131:13
+  --> $DIR/useless_conversion.rs:137:13
    |
 LL |     let _ = String::from(format!("A: {:04}", 123));
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `String::from()`: `format!("A: {:04}", 123)`
 
 error: useless conversion to the same type: `std::str::Lines<'_>`
-  --> $DIR/useless_conversion.rs:132:13
+  --> $DIR/useless_conversion.rs:138:13
    |
 LL |     let _ = "".lines().into_iter();
    |             ^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `"".lines()`
 
 error: useless conversion to the same type: `std::vec::IntoIter<i32>`
-  --> $DIR/useless_conversion.rs:133:13
+  --> $DIR/useless_conversion.rs:139:13
    |
 LL |     let _ = vec![1, 2, 3].into_iter().into_iter();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `vec![1, 2, 3].into_iter()`
 
 error: useless conversion to the same type: `std::string::String`
-  --> $DIR/useless_conversion.rs:134:21
+  --> $DIR/useless_conversion.rs:140:21
    |
 LL |     let _: String = format!("Hello {}", "world").into();
    |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into()`: `format!("Hello {}", "world")`
 
 error: useless conversion to the same type: `i32`
-  --> $DIR/useless_conversion.rs:139:13
+  --> $DIR/useless_conversion.rs:145:13
    |
 LL |     let _ = i32::from(a + b) * 3;
    |             ^^^^^^^^^^^^^^^^ help: consider removing `i32::from()`: `(a + b)`
 
 error: useless conversion to the same type: `Foo<'a'>`
-  --> $DIR/useless_conversion.rs:145:23
+  --> $DIR/useless_conversion.rs:151:23
    |
 LL |     let _: Foo<'a'> = s2.into();
    |                       ^^^^^^^^^ help: consider removing `.into()`: `s2`
 
 error: useless conversion to the same type: `Foo<'a'>`
-  --> $DIR/useless_conversion.rs:147:13
+  --> $DIR/useless_conversion.rs:153:13
    |
 LL |     let _ = Foo::<'a'>::from(s3);
    |             ^^^^^^^^^^^^^^^^^^^^ help: consider removing `Foo::<'a'>::from()`: `s3`
 
 error: useless conversion to the same type: `std::vec::IntoIter<Foo<'a'>>`
-  --> $DIR/useless_conversion.rs:149:13
+  --> $DIR/useless_conversion.rs:155:13
    |
 LL |     let _ = vec![s4, s4, s4].into_iter().into_iter();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `vec![s4, s4, s4].into_iter()`
diff --git a/src/tools/clippy/tests/ui/wildcard_imports_cfgtest.rs b/src/tools/clippy/tests/ui/wildcard_imports_cfgtest.rs
new file mode 100644
index 00000000000..203c4e15b50
--- /dev/null
+++ b/src/tools/clippy/tests/ui/wildcard_imports_cfgtest.rs
@@ -0,0 +1,19 @@
+//@compile-flags: --test
+
+#![warn(clippy::wildcard_imports)]
+#![allow(unused, clippy::unnecessary_wraps, clippy::let_unit_value)]
+
+// Test for #10580, the lint should ignore it because of the crate's cfg test flag.
+
+fn foofoo() {}
+
+mod outer {
+    mod inner {
+        use super::super::*;
+        fn barbar() {
+            let _ = foofoo();
+        }
+    }
+}
+
+fn main() {}
diff --git a/src/tools/clippy/triagebot.toml b/src/tools/clippy/triagebot.toml
index 3f8f6a7b98c..c40b71f6ca7 100644
--- a/src/tools/clippy/triagebot.toml
+++ b/src/tools/clippy/triagebot.toml
@@ -17,9 +17,9 @@ contributing_url = "https://github.com/rust-lang/rust-clippy/blob/master/CONTRIB
 
 [assign.owners]
 "/.github" = ["@flip1995"]
+"/book" = ["@flip1995"]
 "/util/gh-pages" = ["@xFrednet"]
 "*" = [
-    "@flip1995",
     "@Manishearth",
     "@llogiq",
     "@giraffate",
diff --git a/src/tools/compiletest/Cargo.toml b/src/tools/compiletest/Cargo.toml
index 0d42504c7f4..e5297d41a61 100644
--- a/src/tools/compiletest/Cargo.toml
+++ b/src/tools/compiletest/Cargo.toml
@@ -20,6 +20,7 @@ once_cell = "1.16.0"
 walkdir = "2"
 glob = "0.3.0"
 lazycell = "1.3.0"
+anyhow = "1"
 
 [target.'cfg(unix)'.dependencies]
 libc = "0.2"
diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs
index 9059a145b43..ba68b5ee9d5 100644
--- a/src/tools/compiletest/src/common.rs
+++ b/src/tools/compiletest/src/common.rs
@@ -428,7 +428,6 @@ impl TargetCfgs {
         ))
         .unwrap();
 
-        let mut current = None;
         let mut all_targets = HashSet::new();
         let mut all_archs = HashSet::new();
         let mut all_oses = HashSet::new();
@@ -449,14 +448,11 @@ impl TargetCfgs {
             }
             all_pointer_widths.insert(format!("{}bit", cfg.pointer_width));
 
-            if target == config.target {
-                current = Some(cfg);
-            }
             all_targets.insert(target.into());
         }
 
         Self {
-            current: current.expect("current target not found"),
+            current: Self::get_current_target_config(config),
             all_targets,
             all_archs,
             all_oses,
@@ -467,6 +463,89 @@ impl TargetCfgs {
             all_pointer_widths,
         }
     }
+
+    fn get_current_target_config(config: &Config) -> TargetCfg {
+        let mut arch = None;
+        let mut os = None;
+        let mut env = None;
+        let mut abi = None;
+        let mut families = Vec::new();
+        let mut pointer_width = None;
+        let mut endian = None;
+        let mut panic = None;
+
+        for config in
+            rustc_output(config, &["--print=cfg", "--target", &config.target]).trim().lines()
+        {
+            let (name, value) = config
+                .split_once("=\"")
+                .map(|(name, value)| {
+                    (
+                        name,
+                        Some(
+                            value
+                                .strip_suffix("\"")
+                                .expect("key-value pair should be properly quoted"),
+                        ),
+                    )
+                })
+                .unwrap_or_else(|| (config, None));
+
+            match name {
+                "target_arch" => {
+                    arch = Some(value.expect("target_arch should be a key-value pair").to_string());
+                }
+                "target_os" => {
+                    os = Some(value.expect("target_os sould be a key-value pair").to_string());
+                }
+                "target_env" => {
+                    env = Some(value.expect("target_env should be a key-value pair").to_string());
+                }
+                "target_abi" => {
+                    abi = Some(value.expect("target_abi should be a key-value pair").to_string());
+                }
+                "target_family" => {
+                    families
+                        .push(value.expect("target_family should be a key-value pair").to_string());
+                }
+                "target_pointer_width" => {
+                    pointer_width = Some(
+                        value
+                            .expect("target_pointer_width should be a key-value pair")
+                            .parse::<u32>()
+                            .expect("target_pointer_width should be a valid u32"),
+                    );
+                }
+                "target_endian" => {
+                    endian = Some(match value.expect("target_endian should be a key-value pair") {
+                        "big" => Endian::Big,
+                        "little" => Endian::Little,
+                        _ => panic!("target_endian should be either 'big' or 'little'"),
+                    });
+                }
+                "panic" => {
+                    panic = Some(match value.expect("panic should be a key-value pair") {
+                        "abort" => PanicStrategy::Abort,
+                        "unwind" => PanicStrategy::Unwind,
+                        _ => panic!("panic should be either 'abort' or 'unwind'"),
+                    });
+                }
+                _ => (),
+            }
+        }
+
+        TargetCfg {
+            arch: arch.expect("target configuration should specify target_arch"),
+            os: os.expect("target configuration should specify target_os"),
+            env: env.expect("target configuration should specify target_env"),
+            abi: abi.expect("target configuration should specify target_abi"),
+            families,
+            pointer_width: pointer_width
+                .expect("target configuration should specify target_pointer_width"),
+            endian: endian.expect("target configuration should specify target_endian"),
+            panic: panic.expect("target configuration should specify panic"),
+        }
+    }
 }
 
 #[derive(Clone, Debug, serde::Deserialize)]
diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs
index 4ede4603789..5bc4d164265 100644
--- a/src/tools/compiletest/src/runtest.rs
+++ b/src/tools/compiletest/src/runtest.rs
@@ -32,6 +32,7 @@ use std::process::{Child, Command, ExitStatus, Output, Stdio};
 use std::str;
 use std::sync::Arc;
 
+use anyhow::Context;
 use glob::glob;
 use once_cell::sync::Lazy;
 use tracing::*;
@@ -131,7 +132,11 @@ pub fn run(config: Arc<Config>, testpaths: &TestPaths, revision: Option<&str>) {
     }
 
     let cx = TestCx { config: &config, props: &props, testpaths, revision };
-    create_dir_all(&cx.output_base_dir()).unwrap();
+    create_dir_all(&cx.output_base_dir())
+        .with_context(|| {
+            format!("failed to create output base directory {}", cx.output_base_dir().display())
+        })
+        .unwrap();
     if props.incremental {
         cx.init_incremental_test();
     }
diff --git a/src/tools/linkchecker/main.rs b/src/tools/linkchecker/main.rs
index 4170c32f1fe..c8a370085a0 100644
--- a/src/tools/linkchecker/main.rs
+++ b/src/tools/linkchecker/main.rs
@@ -139,18 +139,18 @@ enum FileEntry {
 type Cache = HashMap<String, FileEntry>;
 
 fn small_url_encode(s: &str) -> String {
-    s.replace("<", "%3C")
-        .replace(">", "%3E")
-        .replace(" ", "%20")
-        .replace("?", "%3F")
-        .replace("'", "%27")
-        .replace("&", "%26")
-        .replace(",", "%2C")
-        .replace(":", "%3A")
-        .replace(";", "%3B")
-        .replace("[", "%5B")
-        .replace("]", "%5D")
-        .replace("\"", "%22")
+    s.replace('<', "%3C")
+        .replace('>', "%3E")
+        .replace(' ', "%20")
+        .replace('?', "%3F")
+        .replace('\'', "%27")
+        .replace('&', "%26")
+        .replace(',', "%2C")
+        .replace(':', "%3A")
+        .replace(';', "%3B")
+        .replace('[', "%5B")
+        .replace(']', "%5D")
+        .replace('\"', "%22")
 }
 
 impl Checker {
@@ -267,7 +267,6 @@ impl Checker {
                 FileEntry::OtherFile => return,
                 FileEntry::Redirect { target } => {
                     let t = target.clone();
-                    drop(target);
                     let (target, redir_entry) = self.load_file(&t, report);
                     match redir_entry {
                         FileEntry::Missing => {
@@ -391,7 +390,7 @@ impl Checker {
         const ERROR_INVALID_NAME: i32 = 123;
 
         let pretty_path =
-            file.strip_prefix(&self.root).unwrap_or(&file).to_str().unwrap().to_string();
+            file.strip_prefix(&self.root).unwrap_or(file).to_str().unwrap().to_string();
 
         let entry =
             self.cache.entry(pretty_path.clone()).or_insert_with(|| match fs::metadata(file) {
@@ -470,10 +469,8 @@ fn is_exception(file: &Path, link: &str) -> bool {
         // NOTE: This cannot be added to `LINKCHECK_EXCEPTIONS` because the resolved path
         // calculated in `check` function is outside `build/<triple>/doc` dir.
         // So the `strip_prefix` method just returns the old absolute broken path.
-        if file.ends_with("std/primitive.slice.html") {
-            if link.ends_with("primitive.slice.html") {
-                return true;
-            }
+        if file.ends_with("std/primitive.slice.html") && link.ends_with("primitive.slice.html") {
+            return true;
         }
         false
     }
@@ -545,7 +542,7 @@ fn with_attrs_in_source<F: FnMut(&str, usize, &str)>(source: &str, attr: &str, m
 fn parse_ids(ids: &mut HashSet<String>, file: &str, source: &str, report: &mut Report) {
     if ids.is_empty() {
         with_attrs_in_source(source, " id", |fragment, i, _| {
-            let frag = fragment.trim_start_matches("#").to_owned();
+            let frag = fragment.trim_start_matches('#').to_owned();
             let encoded = small_url_encode(&frag);
             if !ids.insert(frag) {
                 report.errors += 1;
diff --git a/src/tools/miri/Cargo.lock b/src/tools/miri/Cargo.lock
index e2a7d484c23..737423a2cd1 100644
--- a/src/tools/miri/Cargo.lock
+++ b/src/tools/miri/Cargo.lock
@@ -820,9 +820,9 @@ dependencies = [
 
 [[package]]
 name = "ui_test"
-version = "0.9.0"
+version = "0.10.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "95033b0e41b8018013d99a6f1486c1ae5bd080378ced60c5f797e93842423b33"
+checksum = "191a442639ea102fa62671026047e51d574bfda44b7fdf32151d7314624c1cd2"
 dependencies = [
  "bstr",
  "cargo-platform",
diff --git a/src/tools/miri/Cargo.toml b/src/tools/miri/Cargo.toml
index f6f81836804..5987b0df8d6 100644
--- a/src/tools/miri/Cargo.toml
+++ b/src/tools/miri/Cargo.toml
@@ -39,7 +39,7 @@ libloading = "0.7"
 
 [dev-dependencies]
 colored = "2"
-ui_test = "0.9"
+ui_test = "0.10"
 rustc_version = "0.4"
 # Features chosen to match those required by env_logger, to avoid rebuilds
 regex = { version = "1.5.5", default-features = false, features = ["perf", "std"] }
diff --git a/src/tools/miri/ci.sh b/src/tools/miri/ci.sh
index 76cc2e94927..b5b3b211b05 100755
--- a/src/tools/miri/ci.sh
+++ b/src/tools/miri/ci.sh
@@ -45,8 +45,7 @@ function run_tests {
     # them. Also error locations change so we don't run the failing tests.
     # We explicitly enable debug-assertions here, they are disabled by -O but we have tests
     # which exist to check that we panic on debug assertion failures.
-    #FIXME: Disabled due to <https://github.com/rust-lang/rust/issues/111422>.
-    #MIRIFLAGS="${MIRIFLAGS:-} -O -Zmir-opt-level=4 -Cdebug-assertions=yes" MIRI_SKIP_UI_CHECKS=1 ./miri test -- tests/{pass,panic}
+    MIRIFLAGS="${MIRIFLAGS:-} -O -Zmir-opt-level=4 -Cdebug-assertions=yes" MIRI_SKIP_UI_CHECKS=1 ./miri test -- tests/{pass,panic}
 
     # Also run some many-seeds tests. 64 seeds means this takes around a minute per test.
     for FILE in tests/many-seeds/*.rs; do
diff --git a/src/tools/miri/miri b/src/tools/miri/miri
index 4be970b398d..48a46a76a12 100755
--- a/src/tools/miri/miri
+++ b/src/tools/miri/miri
@@ -306,7 +306,7 @@ test|bless)
     # Only in root project as `cargo-miri` has no tests.
     $CARGO test $CARGO_EXTRA_FLAGS --manifest-path "$MIRIDIR"/Cargo.toml "$@"
     ;;
-run)
+run|run-dep)
     # Scan for "--target" to overwrite the "MIRI_TEST_TARGET" env var so
     # that we set the MIRI_SYSROOT up the right way.
     FOUND_TARGET_OPT=0
@@ -323,11 +323,17 @@ run)
         # Make sure Miri actually uses this target.
         MIRIFLAGS="$MIRIFLAGS --target $MIRI_TEST_TARGET"
     fi
+
     # First build and get a sysroot.
     $CARGO build $CARGO_EXTRA_FLAGS --manifest-path "$MIRIDIR"/Cargo.toml
     find_sysroot
     # Then run the actual command.
-    exec $CARGO run $CARGO_EXTRA_FLAGS --manifest-path "$MIRIDIR"/Cargo.toml -- $MIRIFLAGS "$@"
+    
+    if [ "$COMMAND" = "run-dep" ]; then
+        exec $CARGO test --test compiletest $CARGO_EXTRA_FLAGS --manifest-path "$MIRIDIR"/Cargo.toml -- --miri-run-dep-mode $MIRIFLAGS "$@"
+    else
+        exec $CARGO run $CARGO_EXTRA_FLAGS --manifest-path "$MIRIDIR"/Cargo.toml -- $MIRIFLAGS "$@"
+    fi
     ;;
 fmt)
     find "$MIRIDIR" -not \( -name target -prune \) -name '*.rs' \
diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version
index 25304fc19f7..b450f986149 100644
--- a/src/tools/miri/rust-version
+++ b/src/tools/miri/rust-version
@@ -1 +1 @@
-65dfca8488d635552eb246eb8e15df646e987cff
+69fef92ab2f287f072b66fb7b4f62c8bb4acba43
diff --git a/src/tools/miri/src/bin/miri.rs b/src/tools/miri/src/bin/miri.rs
index 28f9912e283..083dd4800d9 100644
--- a/src/tools/miri/src/bin/miri.rs
+++ b/src/tools/miri/src/bin/miri.rs
@@ -28,8 +28,8 @@ use rustc_middle::{
     middle::exported_symbols::{
         ExportedSymbol, SymbolExportInfo, SymbolExportKind, SymbolExportLevel,
     },
-    query::LocalCrate,
-    ty::{query::ExternProviders, TyCtxt},
+    query::{ExternProviders, LocalCrate},
+    ty::TyCtxt,
 };
 use rustc_session::config::OptLevel;
 
diff --git a/src/tools/miri/src/borrow_tracker/stacked_borrows/stack.rs b/src/tools/miri/src/borrow_tracker/stacked_borrows/stack.rs
index 064dbe025af..a1e949183ad 100644
--- a/src/tools/miri/src/borrow_tracker/stacked_borrows/stack.rs
+++ b/src/tools/miri/src/borrow_tracker/stacked_borrows/stack.rs
@@ -83,7 +83,7 @@ impl Stack {
         self.borrows.truncate(write_idx);
 
         #[cfg(not(feature = "stack-cache"))]
-        drop(first_removed); // This is only needed for the stack-cache
+        let _unused = first_removed; // This is only needed for the stack-cache
 
         #[cfg(feature = "stack-cache")]
         if let Some(first_removed) = first_removed {
diff --git a/src/tools/miri/src/diagnostics.rs b/src/tools/miri/src/diagnostics.rs
index a93f3eb84f2..e3f81a78eea 100644
--- a/src/tools/miri/src/diagnostics.rs
+++ b/src/tools/miri/src/diagnostics.rs
@@ -289,7 +289,7 @@ pub fn report_error<'tcx, 'mir>(
                     (None, format!("see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information")),
                 ],
             InvalidProgram(
-                InvalidProgramInfo::AlreadyReported(rustc_errors::ErrorGuaranteed { .. })
+                InvalidProgramInfo::AlreadyReported(_)
             ) => {
                 // This got already reported. No point in reporting it again.
                 return None;
diff --git a/src/tools/miri/src/lib.rs b/src/tools/miri/src/lib.rs
index fc938080a0e..893a4dbd4c8 100644
--- a/src/tools/miri/src/lib.rs
+++ b/src/tools/miri/src/lib.rs
@@ -47,7 +47,6 @@ extern crate rustc_ast;
 extern crate rustc_middle;
 extern crate rustc_const_eval;
 extern crate rustc_data_structures;
-extern crate rustc_errors;
 extern crate rustc_hir;
 extern crate rustc_index;
 extern crate rustc_session;
diff --git a/src/tools/miri/src/shims/intrinsics/simd.rs b/src/tools/miri/src/shims/intrinsics/simd.rs
index d101f8d3111..114c66253f7 100644
--- a/src/tools/miri/src/shims/intrinsics/simd.rs
+++ b/src/tools/miri/src/shims/intrinsics/simd.rs
@@ -421,14 +421,18 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 }
             }
             #[rustfmt::skip]
-            "cast" | "as" => {
+            "cast" | "as" | "cast_ptr" | "expose_addr" | "from_exposed_addr" => {
                 let [op] = check_arg_count(args)?;
                 let (op, op_len) = this.operand_to_simd(op)?;
                 let (dest, dest_len) = this.place_to_simd(dest)?;
 
                 assert_eq!(dest_len, op_len);
 
+                let unsafe_cast = intrinsic_name == "cast";
                 let safe_cast = intrinsic_name == "as";
+                let ptr_cast = intrinsic_name == "cast_ptr";
+                let expose_cast = intrinsic_name == "expose_addr";
+                let from_exposed_cast = intrinsic_name == "from_exposed_addr";
 
                 for i in 0..dest_len {
                     let op = this.read_immediate(&this.mplace_index(&op, i)?.into())?;
@@ -436,19 +440,31 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
 
                     let val = match (op.layout.ty.kind(), dest.layout.ty.kind()) {
                         // Int-to-(int|float): always safe
-                        (ty::Int(_) | ty::Uint(_), ty::Int(_) | ty::Uint(_) | ty::Float(_)) =>
+                        (ty::Int(_) | ty::Uint(_), ty::Int(_) | ty::Uint(_) | ty::Float(_)) if safe_cast || unsafe_cast =>
                             this.int_to_int_or_float(&op, dest.layout.ty)?,
                         // Float-to-float: always safe
-                        (ty::Float(_), ty::Float(_)) =>
+                        (ty::Float(_), ty::Float(_)) if safe_cast || unsafe_cast =>
                             this.float_to_float_or_int(&op, dest.layout.ty)?,
                         // Float-to-int in safe mode
                         (ty::Float(_), ty::Int(_) | ty::Uint(_)) if safe_cast =>
                             this.float_to_float_or_int(&op, dest.layout.ty)?,
                         // Float-to-int in unchecked mode
-                        (ty::Float(FloatTy::F32), ty::Int(_) | ty::Uint(_)) if !safe_cast =>
+                        (ty::Float(FloatTy::F32), ty::Int(_) | ty::Uint(_)) if unsafe_cast =>
                             this.float_to_int_unchecked(op.to_scalar().to_f32()?, dest.layout.ty)?.into(),
-                        (ty::Float(FloatTy::F64), ty::Int(_) | ty::Uint(_)) if !safe_cast =>
+                        (ty::Float(FloatTy::F64), ty::Int(_) | ty::Uint(_)) if unsafe_cast =>
                             this.float_to_int_unchecked(op.to_scalar().to_f64()?, dest.layout.ty)?.into(),
+                        // Ptr-to-ptr cast
+                        (ty::RawPtr(..), ty::RawPtr(..)) if ptr_cast => {
+                            this.ptr_to_ptr(&op, dest.layout.ty)?
+                        }
+                        // Ptr/Int casts
+                        (ty::RawPtr(..), ty::Int(_) | ty::Uint(_)) if expose_cast => {
+                            this.pointer_expose_address_cast(&op, dest.layout.ty)?
+                        }
+                        (ty::Int(_) | ty::Uint(_), ty::RawPtr(..)) if from_exposed_cast => {
+                            this.pointer_from_exposed_address_cast(&op, dest.layout.ty)?
+                        }
+                        // Error otherwise
                         _ =>
                             throw_unsup_format!(
                                 "Unsupported SIMD cast from element type {from_ty} to {to_ty}",
diff --git a/src/tools/miri/tests/compiletest.rs b/src/tools/miri/tests/compiletest.rs
index fe70ab3f45a..fa06c4b6a12 100644
--- a/src/tools/miri/tests/compiletest.rs
+++ b/src/tools/miri/tests/compiletest.rs
@@ -1,5 +1,6 @@
 use colored::*;
 use regex::bytes::Regex;
+use std::ffi::OsString;
 use std::path::{Path, PathBuf};
 use std::{env, process::Command};
 use ui_test::status_emitter::StatusEmitter;
@@ -45,7 +46,7 @@ fn build_so_for_c_ffi_tests() -> PathBuf {
     so_file_path
 }
 
-fn run_tests(mode: Mode, path: &str, target: &str, with_dependencies: bool) -> Result<()> {
+fn test_config(target: &str, path: &str, mode: Mode, with_dependencies: bool) -> Config {
     // Miri is rustc-like, so we create a default builder for rustc and modify it
     let mut program = CommandBuilder::rustc();
     program.program = miri_path();
@@ -103,6 +104,26 @@ fn run_tests(mode: Mode, path: &str, target: &str, with_dependencies: bool) -> R
         ..Config::default()
     };
 
+    let use_std = env::var_os("MIRI_NO_STD").is_none();
+
+    if with_dependencies && use_std {
+        config.dependencies_crate_manifest_path =
+            Some(Path::new("test_dependencies").join("Cargo.toml"));
+        config.dependency_builder.args = vec![
+            "run".into(),
+            "--manifest-path".into(),
+            "cargo-miri/Cargo.toml".into(),
+            "--".into(),
+            "miri".into(),
+            "run".into(), // There is no `cargo miri build` so we just use `cargo miri run`.
+        ];
+    }
+    config
+}
+
+fn run_tests(mode: Mode, path: &str, target: &str, with_dependencies: bool) -> Result<()> {
+    let mut config = test_config(target, path, mode, with_dependencies);
+
     // Handle command-line arguments.
     let mut after_dashdash = false;
     config.path_filter.extend(std::env::args().skip(1).filter(|arg| {
@@ -126,20 +147,7 @@ fn run_tests(mode: Mode, path: &str, target: &str, with_dependencies: bool) -> R
         }
     }));
 
-    let use_std = env::var_os("MIRI_NO_STD").is_none();
-
-    if with_dependencies && use_std {
-        config.dependencies_crate_manifest_path =
-            Some(Path::new("test_dependencies").join("Cargo.toml"));
-        config.dependency_builder.args = vec![
-            "run".into(),
-            "--manifest-path".into(),
-            "cargo-miri/Cargo.toml".into(),
-            "--".into(),
-            "miri".into(),
-            "run".into(), // There is no `cargo miri build` so we just use `cargo miri run`.
-        ];
-    }
+    eprintln!("   Compiler: {}", config.program.display());
     ui_test::run_tests_generic(
         config,
         // The files we're actually interested in (all `.rs` files).
@@ -224,8 +232,18 @@ fn get_target() -> String {
 
 fn main() -> Result<()> {
     ui_test::color_eyre::install()?;
+
     let target = get_target();
 
+    let mut args = std::env::args_os();
+
+    // Skip the program name and check whether this is a `./miri run-dep` invocation
+    if let Some(first) = args.nth(1) {
+        if first == "--miri-run-dep-mode" {
+            return run_dep_mode(target, args);
+        }
+    }
+
     // Add a test env var to do environment communication tests.
     env::set_var("MIRI_ENV_VAR_TEST", "0");
     // Let the tests know where to store temp files (they might run for a different target, which can make this hard to find).
@@ -248,6 +266,21 @@ fn main() -> Result<()> {
     Ok(())
 }
 
+fn run_dep_mode(target: String, mut args: impl Iterator<Item = OsString>) -> Result<()> {
+    let path = args.next().expect("./miri run-dep must be followed by a file name");
+    let mut config = test_config(&target, "", Mode::Yolo, /* with dependencies */ true);
+    config.program.args.remove(0); // remove the `--error-format=json` argument
+    config.program.args.push("--color".into());
+    config.program.args.push("always".into());
+    let mut cmd = ui_test::test_command(config, Path::new(&path))?;
+    // Separate the arguments to the `cargo miri` invocation from
+    // the arguments to the interpreted prog
+    cmd.arg("--");
+    cmd.args(args);
+    println!("{cmd:?}");
+    if cmd.spawn()?.wait()?.success() { Ok(()) } else { std::process::exit(1) }
+}
+
 /// This is a custom renderer for `ui_test` output that does not emit github actions
 /// `group`s, while still producing regular github actions messages on test failures.
 struct TextAndGha;
diff --git a/src/tools/miri/tests/fail/intrinsics/simd-scatter.rs b/src/tools/miri/tests/fail/intrinsics/simd-scatter.rs
index 606a6b2798a..98b6749c584 100644
--- a/src/tools/miri/tests/fail/intrinsics/simd-scatter.rs
+++ b/src/tools/miri/tests/fail/intrinsics/simd-scatter.rs
@@ -5,7 +5,8 @@ fn main() {
     unsafe {
         let mut vec: Vec<i8> = vec![10, 11, 12, 13, 14, 15, 16, 17, 18];
         let idxs = Simd::from_array([9, 3, 0, 17]);
-        Simd::from_array([-27, 82, -41, 124]).scatter_select_unchecked( //~ERROR: pointer to 1 byte starting at offset 9 is out-of-bounds
+        Simd::from_array([-27, 82, -41, 124]).scatter_select_unchecked(
+            //~^ERROR: pointer to 1 byte starting at offset 9 is out-of-bounds
             &mut vec,
             Mask::splat(true),
             idxs,
diff --git a/src/tools/miri/tests/fail/intrinsics/simd-scatter.stderr b/src/tools/miri/tests/fail/intrinsics/simd-scatter.stderr
index 6d959af85fa..a745b61029d 100644
--- a/src/tools/miri/tests/fail/intrinsics/simd-scatter.stderr
+++ b/src/tools/miri/tests/fail/intrinsics/simd-scatter.stderr
@@ -2,6 +2,7 @@ error: Undefined Behavior: dereferencing pointer failed: ALLOC has size 9, so po
   --> $DIR/simd-scatter.rs:LL:CC
    |
 LL | /         Simd::from_array([-27, 82, -41, 124]).scatter_select_unchecked(
+LL | |
 LL | |             &mut vec,
 LL | |             Mask::splat(true),
 LL | |             idxs,
diff --git a/src/tools/miri/tests/fail/never_say_never.rs b/src/tools/miri/tests/fail/never_say_never.rs
index f6d3dc790bf..fd082e367a8 100644
--- a/src/tools/miri/tests/fail/never_say_never.rs
+++ b/src/tools/miri/tests/fail/never_say_never.rs
@@ -6,10 +6,8 @@
 
 fn main() {
     let y = &5;
-    let x: ! = unsafe {
-        *(y as *const _ as *const !) //~ ERROR: entering unreachable code
-    };
-    f(x)
+    let x: ! = unsafe { *(y as *const _ as *const !) };
+    f(x) //~ ERROR: entering unreachable code
 }
 
 fn f(x: !) -> ! {
diff --git a/src/tools/miri/tests/fail/never_say_never.stderr b/src/tools/miri/tests/fail/never_say_never.stderr
index a2a63b8baf5..9d3a8df525a 100644
--- a/src/tools/miri/tests/fail/never_say_never.stderr
+++ b/src/tools/miri/tests/fail/never_say_never.stderr
@@ -1,8 +1,8 @@
 error: Undefined Behavior: entering unreachable code
   --> $DIR/never_say_never.rs:LL:CC
    |
-LL |         *(y as *const _ as *const !)
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ entering unreachable code
+LL |     f(x)
+   |     ^^^^ entering unreachable code
    |
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
diff --git a/src/tools/miri/tests/fail/stacked_borrows/illegal_write2.rs b/src/tools/miri/tests/fail/stacked_borrows/illegal_write2.rs
index 70c51e671fe..a5a1930ed65 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/illegal_write2.rs
+++ b/src/tools/miri/tests/fail/stacked_borrows/illegal_write2.rs
@@ -1,3 +1,5 @@
+#![allow(dropping_references)]
+
 fn main() {
     let target = &mut 42;
     let target2 = target as *mut _;
diff --git a/src/tools/miri/tests/fail/uninit_buffer.rs b/src/tools/miri/tests/fail/uninit_buffer.rs
index 8819c53a4f9..d622b2fa7d8 100644
--- a/src/tools/miri/tests/fail/uninit_buffer.rs
+++ b/src/tools/miri/tests/fail/uninit_buffer.rs
@@ -1,5 +1,7 @@
 //@error-in-other-file: memory is uninitialized at [0x4..0x10]
 
+#![allow(dropping_copy_types)]
+
 use std::alloc::{alloc, dealloc, Layout};
 use std::slice::from_raw_parts;
 
diff --git a/src/tools/miri/tests/fail/uninit_buffer_with_provenance.rs b/src/tools/miri/tests/fail/uninit_buffer_with_provenance.rs
index e788c079cb4..ca825901372 100644
--- a/src/tools/miri/tests/fail/uninit_buffer_with_provenance.rs
+++ b/src/tools/miri/tests/fail/uninit_buffer_with_provenance.rs
@@ -1,6 +1,7 @@
 //@error-in-other-file: memory is uninitialized at [0x4..0x8]
 //@normalize-stderr-test: "a[0-9]+" -> "ALLOC"
 #![feature(strict_provenance)]
+#![allow(dropping_copy_types)]
 
 // Test printing allocations that contain single-byte provenance.
 
diff --git a/src/tools/miri/tests/pass/portable-simd-ptrs.rs b/src/tools/miri/tests/pass/portable-simd-ptrs.rs
new file mode 100644
index 00000000000..303c99834f5
--- /dev/null
+++ b/src/tools/miri/tests/pass/portable-simd-ptrs.rs
@@ -0,0 +1,12 @@
+// Separate test without strict provenance
+//@compile-flags: -Zmiri-permissive-provenance
+#![feature(portable_simd, platform_intrinsics)]
+use std::ptr;
+use std::simd::*;
+
+fn main() {
+    // Pointer casts
+    let _val: Simd<*const u8, 4> = Simd::<*const i32, 4>::splat(ptr::null()).cast_ptr();
+    let addrs = Simd::<*const i32, 4>::splat(ptr::null()).expose_addr();
+    let _ptrs = Simd::<*const i32, 4>::from_exposed_addr(addrs);
+}
diff --git a/src/tools/miri/tests/pass/stacked-borrows/zst-field-retagging-terminates.rs b/src/tools/miri/tests/pass/stacked-borrows/zst-field-retagging-terminates.rs
index ce3c8b7d5f1..6e13a9ea836 100644
--- a/src/tools/miri/tests/pass/stacked-borrows/zst-field-retagging-terminates.rs
+++ b/src/tools/miri/tests/pass/stacked-borrows/zst-field-retagging-terminates.rs
@@ -1,5 +1,8 @@
 //@compile-flags: -Zmiri-retag-fields
 // Checks that the test does not run forever (which relies on a fast path).
+
+#![allow(dropping_copy_types)]
+
 fn main() {
     let array = [(); usize::MAX];
     drop(array); // Pass the array to a function, retagging its fields
diff --git a/src/tools/replace-version-placeholder/src/main.rs b/src/tools/replace-version-placeholder/src/main.rs
index 0aebfc4aad2..5c9c18b9b36 100644
--- a/src/tools/replace-version-placeholder/src/main.rs
+++ b/src/tools/replace-version-placeholder/src/main.rs
@@ -8,15 +8,13 @@ fn main() {
     let version_path = root_path.join("src").join("version");
     let version_str = t!(std::fs::read_to_string(&version_path), version_path);
     let version_str = version_str.trim();
-    walk::walk(
-        &root_path,
+    walk::walk_many(
+        &[&root_path.join("compiler"), &root_path.join("library")],
         |path, _is_dir| {
             walk::filter_dirs(path)
                 // We exempt these as they require the placeholder
                 // for their operation
                 || path.ends_with("compiler/rustc_attr/src/builtin.rs")
-                || path.ends_with("src/tools/tidy/src/features/version.rs")
-                || path.ends_with("src/tools/replace-version-placeholder")
         },
         &mut |entry, contents| {
             if !contents.contains(VERSION_PLACEHOLDER) {
diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs
index afa6bce943f..2e778110931 100644
--- a/src/tools/tidy/src/deps.rs
+++ b/src/tools/tidy/src/deps.rs
@@ -117,6 +117,7 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[
     "autocfg",
     "bitflags",
     "block-buffer",
+    "byteorder", // via ruzstd in object in thorin-dwp
     "cc",
     "cfg-if",
     "chalk-derive",
@@ -145,6 +146,7 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[
     "expect-test",
     "fallible-iterator", // dependency of `thorin`
     "fastrand",
+    "field-offset",
     "fixedbitset",
     "flate2",
     "fluent-bundle",
@@ -216,6 +218,7 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[
     "rustc-rayon",
     "rustc-rayon-core",
     "rustc_version",
+    "ruzstd", // via object in thorin-dwp
     "ryu",
     "scoped-tls",
     "scopeguard",
diff --git a/src/tools/tidy/src/style.rs b/src/tools/tidy/src/style.rs
index 5f388ee47bb..d0257d71697 100644
--- a/src/tools/tidy/src/style.rs
+++ b/src/tools/tidy/src/style.rs
@@ -296,6 +296,12 @@ pub fn check(path: &Path, bad: &mut bool) {
         if filename.contains("ignore-tidy") {
             return;
         }
+        // Shell completions are automatically generated
+        if let Some(p) = file.parent() {
+            if p.ends_with(Path::new("src/etc/completions")) {
+                return;
+            }
+        }
         // apfloat shouldn't be changed because of license problems
         if is_in(file, "compiler", "rustc_apfloat") {
             return;
diff --git a/src/tools/tidy/src/ui_tests.rs b/src/tools/tidy/src/ui_tests.rs
index 9473eabe442..be3a5d3aa0f 100644
--- a/src/tools/tidy/src/ui_tests.rs
+++ b/src/tools/tidy/src/ui_tests.rs
@@ -4,13 +4,39 @@
 
 use ignore::Walk;
 use std::collections::HashMap;
+use std::ffi::OsStr;
 use std::fs;
 use std::path::{Path, PathBuf};
 
 const ENTRY_LIMIT: usize = 900;
 // FIXME: The following limits should be reduced eventually.
 const ISSUES_ENTRY_LIMIT: usize = 1920;
-const ROOT_ENTRY_LIMIT: usize = 895;
+const ROOT_ENTRY_LIMIT: usize = 896;
+
+const EXPECTED_TEST_FILE_EXTENSIONS: &[&str] = &[
+    "rs",     // test source files
+    "stderr", // expected stderr file, corresponds to a rs file
+    "stdout", // expected stdout file, corresponds to a rs file
+    "fixed",  // expected source file after applying fixes
+    "md",     // test directory descriptions
+    "ftl",    // translation tests
+];
+
+const EXTENSION_EXCEPTION_PATHS: &[&str] = &[
+    "tests/ui/asm/named-asm-labels.s", // loading an external asm file to test named labels lint
+    "tests/ui/check-cfg/my-awesome-platform.json", // testing custom targets with cfgs
+    "tests/ui/commandline-argfile-badutf8.args", // passing args via a file
+    "tests/ui/commandline-argfile.args", // passing args via a file
+    "tests/ui/crate-loading/auxiliary/libfoo.rlib", // testing loading a manually created rlib
+    "tests/ui/include-macros/data.bin", // testing including data with the include macros
+    "tests/ui/include-macros/file.txt", // testing including data with the include macros
+    "tests/ui/macros/macro-expanded-include/file.txt", // testing including data with the include macros
+    "tests/ui/macros/not-utf8.bin", // testing including data with the include macros
+    "tests/ui/macros/syntax-extension-source-utils-files/includeme.fragment", // more include
+    "tests/ui/unused-crate-deps/test.mk", // why would you use make
+    "tests/ui/proc-macro/auxiliary/included-file.txt", // more include
+    "tests/ui/invalid/foo.natvis.xml", // sample debugger visualizer
+];
 
 fn check_entries(tests_path: &Path, bad: &mut bool) {
     let mut directories: HashMap<PathBuf, usize> = HashMap::new();
@@ -66,7 +92,14 @@ pub fn check(path: &Path, bad: &mut bool) {
     let paths = [ui.as_path(), ui_fulldeps.as_path()];
     crate::walk::walk_no_read(&paths, |_, _| false, &mut |entry| {
         let file_path = entry.path();
-        if let Some(ext) = file_path.extension() {
+        if let Some(ext) = file_path.extension().and_then(OsStr::to_str) {
+            // files that are neither an expected extension or an exception should not exist
+            // they're probably typos or not meant to exist
+            if !(EXPECTED_TEST_FILE_EXTENSIONS.contains(&ext)
+                || EXTENSION_EXCEPTION_PATHS.iter().any(|path| file_path.ends_with(path)))
+            {
+                tidy_error!(bad, "file {} has unexpected extension {}", file_path.display(), ext);
+            }
             if ext == "stderr" || ext == "stdout" {
                 // Test output filenames have one of the formats:
                 // ```
diff --git a/tests/codegen/addr-of-mutate.rs b/tests/codegen/addr-of-mutate.rs
new file mode 100644
index 00000000000..bea1aad2352
--- /dev/null
+++ b/tests/codegen/addr-of-mutate.rs
@@ -0,0 +1,34 @@
+// compile-flags: -C opt-level=3 -C no-prepopulate-passes
+// min-llvm-version: 15.0 (for opaque pointers)
+
+#![crate_type = "lib"]
+
+// Test for the absence of `readonly` on the argument when it is mutated via `&raw const`.
+// See <https://github.com/rust-lang/rust/issues/111502>.
+
+// CHECK: i8 @foo(ptr noalias nocapture noundef dereferenceable(128) %x)
+#[no_mangle]
+pub fn foo(x: [u8; 128]) -> u8 {
+    let ptr = core::ptr::addr_of!(x).cast_mut();
+    unsafe {
+        (*ptr)[0] = 1;
+    }
+    x[0]
+}
+
+// CHECK: i1 @second(ptr noalias nocapture noundef dereferenceable({{[0-9]+}}) %a_ptr_and_b)
+#[no_mangle]
+pub unsafe fn second(a_ptr_and_b: (*mut (i32, bool), (i64, bool))) -> bool {
+    let b_bool_ptr = core::ptr::addr_of!(a_ptr_and_b.1.1).cast_mut();
+    (*b_bool_ptr) = true;
+    a_ptr_and_b.1.1
+}
+
+// If going through a deref (and there are no other mutating accesses), then `readonly` is fine.
+// CHECK: i1 @third(ptr noalias nocapture noundef readonly dereferenceable({{[0-9]+}}) %a_ptr_and_b)
+#[no_mangle]
+pub unsafe fn third(a_ptr_and_b: (*mut (i32, bool), (i64, bool))) -> bool {
+    let b_bool_ptr = core::ptr::addr_of!((*a_ptr_and_b.0).1).cast_mut();
+    (*b_bool_ptr) = true;
+    a_ptr_and_b.1.1
+}
diff --git a/tests/codegen/binary-search-index-no-bound-check.rs b/tests/codegen/binary-search-index-no-bound-check.rs
index c1766a4a44a..595969a8979 100644
--- a/tests/codegen/binary-search-index-no-bound-check.rs
+++ b/tests/codegen/binary-search-index-no-bound-check.rs
@@ -9,7 +9,9 @@
 #[no_mangle]
 pub fn binary_search_index_no_bounds_check(s: &[u8]) -> u8 {
     // CHECK-NOT: panic
-    // CHECK-NOT: slice_index_len_fail
+    // CHECK-NOT: slice_start_index_len_fail
+    // CHECK-NOT: slice_end_index_len_fail
+    // CHECK-NOT: panic_bounds_check
     if let Ok(idx) = s.binary_search(&b'\\') {
         s[idx]
     } else {
diff --git a/tests/codegen/fewer-names.rs b/tests/codegen/fewer-names.rs
index df1080bff2b..a09c795924c 100644
--- a/tests/codegen/fewer-names.rs
+++ b/tests/codegen/fewer-names.rs
@@ -13,8 +13,8 @@ pub fn sum(x: u32, y: u32) -> u32 {
 
     // NO-LABEL: define{{.*}}i32 @sum(i32 noundef %x, i32 noundef %y)
     // NO-NEXT:  start:
-    // NO-NEXT:    %z = add i32 %y, %x
-    // NO-NEXT:    ret i32 %z
+    // NO-NEXT:    %0 = add i32 %y, %x
+    // NO-NEXT:    ret i32 %0
     let z = x + y;
     z
 }
diff --git a/tests/codegen/issues/issue-111603.rs b/tests/codegen/issues/issue-111603.rs
new file mode 100644
index 00000000000..90b3c314d2f
--- /dev/null
+++ b/tests/codegen/issues/issue-111603.rs
@@ -0,0 +1,28 @@
+// compile-flags: -O
+
+#![crate_type = "lib"]
+#![feature(get_mut_unchecked, new_uninit)]
+
+use std::sync::Arc;
+
+// CHECK-LABEL: @new_uninit
+#[no_mangle]
+pub fn new_uninit(x: u64) -> Arc<[u64; 1000]> {
+    // CHECK: call alloc::sync::arcinner_layout_for_value_layout
+    // CHECK-NOT: call alloc::sync::arcinner_layout_for_value_layout
+    let mut arc = Arc::new_uninit();
+    unsafe { Arc::get_mut_unchecked(&mut arc) }.write([x; 1000]);
+    unsafe { arc.assume_init() }
+}
+
+// CHECK-LABEL: @new_uninit_slice
+#[no_mangle]
+pub fn new_uninit_slice(x: u64) -> Arc<[u64]> {
+    // CHECK: call alloc::sync::arcinner_layout_for_value_layout
+    // CHECK-NOT: call alloc::sync::arcinner_layout_for_value_layout
+    let mut arc = Arc::new_uninit_slice(1000);
+    for elem in unsafe { Arc::get_mut_unchecked(&mut arc) } {
+        elem.write(x);
+    }
+    unsafe { arc.assume_init() }
+}
diff --git a/tests/codegen/issues/issue-73396-bounds-check-after-position.rs b/tests/codegen/issues/issue-73396-bounds-check-after-position.rs
index 8d07a67a1b4..2d779788791 100644
--- a/tests/codegen/issues/issue-73396-bounds-check-after-position.rs
+++ b/tests/codegen/issues/issue-73396-bounds-check-after-position.rs
@@ -9,7 +9,10 @@
 #[no_mangle]
 pub fn position_slice_to_no_bounds_check(s: &[u8]) -> &[u8] {
     // CHECK-NOT: panic
-    // CHECK-NOT: slice_index_len_fail
+    // CHECK-NOT: slice_start_index_len_fail
+    // CHECK-NOT: slice_end_index_len_fail
+    // CHECK-NOT: panic_bounds_check
+    // CHECK-NOT: unreachable
     if let Some(idx) = s.iter().position(|b| *b == b'\\') {
         &s[..idx]
     } else {
@@ -21,7 +24,10 @@ pub fn position_slice_to_no_bounds_check(s: &[u8]) -> &[u8] {
 #[no_mangle]
 pub fn position_slice_from_no_bounds_check(s: &[u8]) -> &[u8] {
     // CHECK-NOT: panic
-    // CHECK-NOT: slice_index_len_fail
+    // CHECK-NOT: slice_start_index_len_fail
+    // CHECK-NOT: slice_end_index_len_fail
+    // CHECK-NOT: panic_bounds_check
+    // CHECK-NOT: unreachable
     if let Some(idx) = s.iter().position(|b| *b == b'\\') {
         &s[idx..]
     } else {
@@ -33,7 +39,10 @@ pub fn position_slice_from_no_bounds_check(s: &[u8]) -> &[u8] {
 #[no_mangle]
 pub fn position_index_no_bounds_check(s: &[u8]) -> u8 {
     // CHECK-NOT: panic
-    // CHECK-NOT: slice_index_len_fail
+    // CHECK-NOT: slice_start_index_len_fail
+    // CHECK-NOT: slice_end_index_len_fail
+    // CHECK-NOT: panic_bounds_check
+    // CHECK-NOT: unreachable
     if let Some(idx) = s.iter().position(|b| *b == b'\\') {
         s[idx]
     } else {
@@ -44,7 +53,10 @@ pub fn position_index_no_bounds_check(s: &[u8]) -> u8 {
 #[no_mangle]
 pub fn rposition_slice_to_no_bounds_check(s: &[u8]) -> &[u8] {
     // CHECK-NOT: panic
-    // CHECK-NOT: slice_index_len_fail
+    // CHECK-NOT: slice_start_index_len_fail
+    // CHECK-NOT: slice_end_index_len_fail
+    // CHECK-NOT: panic_bounds_check
+    // CHECK-NOT: unreachable
     if let Some(idx) = s.iter().rposition(|b| *b == b'\\') {
         &s[..idx]
     } else {
@@ -56,7 +68,10 @@ pub fn rposition_slice_to_no_bounds_check(s: &[u8]) -> &[u8] {
 #[no_mangle]
 pub fn rposition_slice_from_no_bounds_check(s: &[u8]) -> &[u8] {
     // CHECK-NOT: panic
-    // CHECK-NOT: slice_index_len_fail
+    // CHECK-NOT: slice_start_index_len_fail
+    // CHECK-NOT: slice_end_index_len_fail
+    // CHECK-NOT: panic_bounds_check
+    // CHECK-NOT: unreachable
     if let Some(idx) = s.iter().rposition(|b| *b == b'\\') {
         &s[idx..]
     } else {
@@ -68,7 +83,10 @@ pub fn rposition_slice_from_no_bounds_check(s: &[u8]) -> &[u8] {
 #[no_mangle]
 pub fn rposition_index_no_bounds_check(s: &[u8]) -> u8 {
     // CHECK-NOT: panic
-    // CHECK-NOT: slice_index_len_fail
+    // CHECK-NOT: slice_start_index_len_fail
+    // CHECK-NOT: slice_end_index_len_fail
+    // CHECK-NOT: panic_bounds_check
+    // CHECK-NOT: unreachable
     if let Some(idx) = s.iter().rposition(|b| *b == b'\\') {
         s[idx]
     } else {
diff --git a/tests/codegen/mem-replace-big-type.rs b/tests/codegen/mem-replace-big-type.rs
index acf759ebe54..c6b920cf599 100644
--- a/tests/codegen/mem-replace-big-type.rs
+++ b/tests/codegen/mem-replace-big-type.rs
@@ -13,8 +13,7 @@ pub struct Big([u64; 7]);
 pub fn replace_big(dst: &mut Big, src: Big) -> Big {
     // Back in 1.68, this emitted six `memcpy`s.
     // `read_via_copy` in 1.69 got that down to three.
-    // `write_via_move` it was originally down to the essential two, however
-    // with nrvo disabled it is back at 3
+    // `write_via_move` and nvro get this down to the essential two.
     std::mem::replace(dst, src)
 }
 
@@ -26,11 +25,9 @@ pub fn replace_big(dst: &mut Big, src: Big) -> Big {
 // For a large type, we expect exactly three `memcpy`s
 // CHECK-LABEL: define internal void @{{.+}}mem{{.+}}replace{{.+}}sret(%Big)
 // CHECK-NOT: call void @llvm.memcpy
-// CHECK: call void @llvm.memcpy.{{.+}}({{i8\*|ptr}} align 8 %result, {{i8\*|ptr}} align 8 %dest, i{{.*}} 56, i1 false)
+// CHECK: call void @llvm.memcpy.{{.+}}({{i8\*|ptr}} align 8 %0, {{i8\*|ptr}} align 8 %dest, i{{.*}} 56, i1 false)
 // CHECK-NOT: call void @llvm.memcpy
 // CHECK: call void @llvm.memcpy.{{.+}}({{i8\*|ptr}} align 8 %dest, {{i8\*|ptr}} align 8 %src, i{{.*}} 56, i1 false)
 // CHECK-NOT: call void @llvm.memcpy
-// CHECK: call void @llvm.memcpy.{{.+}}({{i8\*|ptr}} align 8 %0, {{i8\*|ptr}} align 8 %result, i{{.*}} 56, i1 false)
-// CHECK-NOT: call void @llvm.memcpy
 
 // CHECK-NOT: call void @llvm.memcpy
diff --git a/tests/codegen/sanitizer-cfi-emit-type-metadata-id-itanium-cxx-abi.rs b/tests/codegen/sanitizer-cfi-emit-type-metadata-id-itanium-cxx-abi.rs
index 71e26e3fe8a..3aa16d9f645 100644
--- a/tests/codegen/sanitizer-cfi-emit-type-metadata-id-itanium-cxx-abi.rs
+++ b/tests/codegen/sanitizer-cfi-emit-type-metadata-id-itanium-cxx-abi.rs
@@ -44,7 +44,7 @@ impl<T> Trait1<T> for i32 {
 }
 
 // Trait implementation
-impl<T> Trait1<T> for Struct1<T> {
+impl<T, U> Trait1<T> for Struct1<U> {
     fn foo(&self) { }
 }
 
@@ -536,15 +536,15 @@ pub fn foo149(_: Type14<Bar>, _: Type14<Bar>, _: Type14<Bar>) { }
 // CHECK: ![[TYPE93]] = !{i64 0, !"_ZTSFvPFu3i32S_EE"}
 // CHECK: ![[TYPE94]] = !{i64 0, !"_ZTSFvPFu3i32S_ES0_E"}
 // CHECK: ![[TYPE95]] = !{i64 0, !"_ZTSFvPFu3i32S_ES0_S0_E"}
-// CHECK: ![[TYPE96]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtNtNtC{{[[:print:]]+}}_4core3ops8function2FnIu5tupleIu3i32EEu{{[0-9]+}}NtNtNtNtC{{[[:print:]]+}}_4core3ops8function6FnOnce6OutputIS0_ES_u6regionEEE"}
-// CHECK: ![[TYPE97]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtNtNtC{{[[:print:]]+}}_4core3ops8function2FnIu5tupleIu3i32EEu{{[0-9]+}}NtNtNtNtC{{[[:print:]]+}}_4core3ops8function6FnOnce6OutputIS0_ES_u6regionEES5_E"}
-// CHECK: ![[TYPE98]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtNtNtC{{[[:print:]]+}}_4core3ops8function2FnIu5tupleIu3i32EEu{{[0-9]+}}NtNtNtNtC{{[[:print:]]+}}_4core3ops8function6FnOnce6OutputIS0_ES_u6regionEES5_S5_E"}
-// CHECK: ![[TYPE99]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtNtNtC{{[[:print:]]+}}_4core3ops8function5FnMutIu5tupleIu3i32EEu{{[0-9]+}}NtNtNtNtC{{[[:print:]]+}}_4core3ops8function6FnOnce6OutputIS0_ES_u6regionEEE"}
-// CHECK: ![[TYPE100]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtNtNtC{{[[:print:]]+}}_4core3ops8function5FnMutIu5tupleIu3i32EEu{{[0-9]+}}NtNtNtNtC{{[[:print:]]+}}_4core3ops8function6FnOnce6OutputIS0_ES_u6regionEES5_E"}
-// CHECK: ![[TYPE101]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtNtNtC{{[[:print:]]+}}_4core3ops8function5FnMutIu5tupleIu3i32EEu{{[0-9]+}}NtNtNtNtC{{[[:print:]]+}}_4core3ops8function6FnOnce6OutputIS0_ES_u6regionEES5_S5_E"}
-// CHECK: ![[TYPE102]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtNtNtC{{[[:print:]]+}}_4core3ops8function6FnOnceIu5tupleIu3i32EEu{{[0-9]+}}NtNtNtNtC{{[[:print:]]+}}_4core3ops8function6FnOnce6OutputIS0_ES_u6regionEEE"}
-// CHECK: ![[TYPE103]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtNtNtC{{[[:print:]]+}}_4core3ops8function6FnOnceIu5tupleIu3i32EEu{{[0-9]+}}NtNtNtNtC{{[[:print:]]+}}_4core3ops8function6FnOnce6OutputIS0_ES_u6regionEES5_E"}
-// CHECK: ![[TYPE104]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtNtNtC{{[[:print:]]+}}_4core3ops8function6FnOnceIu5tupleIu3i32EEu{{[0-9]+}}NtNtNtNtC{{[[:print:]]+}}_4core3ops8function6FnOnce6OutputIS0_ES_u6regionEES5_S5_E"}
+// CHECK: ![[TYPE96]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtNtNtC{{[[:print:]]+}}_4core3ops8function2FnIu5paramEu{{[0-9]+}}NtNtNtNtC{{[[:print:]]+}}_4core3ops8function6FnOnce6OutputIu5tupleIu3i32EES1_u6regionEEE"}
+// CHECK: ![[TYPE97]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtNtNtC{{[[:print:]]+}}_4core3ops8function2FnIu5paramEu{{[0-9]+}}NtNtNtNtC{{[[:print:]]+}}_4core3ops8function6FnOnce6OutputIu5tupleIu3i32EES1_u6regionEES6_E"}
+// CHECK: ![[TYPE98]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtNtNtC{{[[:print:]]+}}_4core3ops8function2FnIu5paramEu{{[0-9]+}}NtNtNtNtC{{[[:print:]]+}}_4core3ops8function6FnOnce6OutputIu5tupleIu3i32EES1_u6regionEES6_S6_E"}
+// CHECK: ![[TYPE99]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtNtNtC{{[[:print:]]+}}_4core3ops8function5FnMutIu5paramEu{{[0-9]+}}NtNtNtNtC{{[[:print:]]+}}_4core3ops8function6FnOnce6OutputIu5tupleIu3i32EES1_u6regionEEE"}
+// CHECK: ![[TYPE100]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtNtNtC{{[[:print:]]+}}_4core3ops8function5FnMutIu5paramEu{{[0-9]+}}NtNtNtNtC{{[[:print:]]+}}_4core3ops8function6FnOnce6OutputIu5tupleIu3i32EES1_u6regionEES6_E"}
+// CHECK: ![[TYPE101]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtNtNtC{{[[:print:]]+}}_4core3ops8function5FnMutIu5paramEu{{[0-9]+}}NtNtNtNtC{{[[:print:]]+}}_4core3ops8function6FnOnce6OutputIu5tupleIu3i32EES1_u6regionEES6_S6_E"}
+// CHECK: ![[TYPE102]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtNtNtC{{[[:print:]]+}}_4core3ops8function6FnOnceIu5paramEu{{[0-9]+}}NtNtNtNtC{{[[:print:]]+}}_4core3ops8function6FnOnce6OutputIu5tupleIu3i32EES1_u6regionEEE"}
+// CHECK: ![[TYPE103]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtNtNtC{{[[:print:]]+}}_4core3ops8function6FnOnceIu5paramEu{{[0-9]+}}NtNtNtNtC{{[[:print:]]+}}_4core3ops8function6FnOnce6OutputIu5tupleIu3i32EES1_u6regionEES6_E"}
+// CHECK: ![[TYPE104]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtNtNtC{{[[:print:]]+}}_4core3ops8function6FnOnceIu5paramEu{{[0-9]+}}NtNtNtNtC{{[[:print:]]+}}_4core3ops8function6FnOnce6OutputIu5tupleIu3i32EES1_u6regionEES6_S6_E"}
 // CHECK: ![[TYPE105]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtNtC{{[[:print:]]+}}_4core6marker4Sendu6regionEEE"}
 // CHECK: ![[TYPE106]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtNtC{{[[:print:]]+}}_4core6marker4Sendu6regionEES2_E"}
 // CHECK: ![[TYPE107]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtNtC{{[[:print:]]+}}_4core6marker4Sendu6regionEES2_S2_E"}
@@ -566,9 +566,9 @@ pub fn foo149(_: Type14<Bar>, _: Type14<Bar>, _: Type14<Bar>) { }
 // CHECK: ![[TYPE123]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NvNINvC{{[[:print:]]+}}_51sanitizer_cfi_emit_type_metadata_id_itanium_cxx_abi3fn18{{[{}][{}]}}impl{{[}][}]}}3fooIu3i32EE"}
 // CHECK: ![[TYPE124]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NvNINvC{{[[:print:]]+}}_51sanitizer_cfi_emit_type_metadata_id_itanium_cxx_abi3fn18{{[{}][{}]}}impl{{[}][}]}}3fooIu3i32ES0_E"}
 // CHECK: ![[TYPE125]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NvNINvC{{[[:print:]]+}}_51sanitizer_cfi_emit_type_metadata_id_itanium_cxx_abi3fn18{{[{}][{}]}}impl{{[}][}]}}3fooIu3i32ES0_S0_E"}
-// CHECK: ![[TYPE126]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NvNtC{{[[:print:]]+}}_51sanitizer_cfi_emit_type_metadata_id_itanium_cxx_abi6Trait13fooIu3dynIu{{[0-9]+}}NtC{{[[:print:]]+}}_51sanitizer_cfi_emit_type_metadata_id_itanium_cxx_abi6Trait1Iu3i32Eu6regionES_EE"}
-// CHECK: ![[TYPE127]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NvNtC{{[[:print:]]+}}_51sanitizer_cfi_emit_type_metadata_id_itanium_cxx_abi6Trait13fooIu3dynIu{{[0-9]+}}NtC{{[[:print:]]+}}_51sanitizer_cfi_emit_type_metadata_id_itanium_cxx_abi6Trait1Iu3i32Eu6regionES_ES3_E"}
-// CHECK: ![[TYPE128]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NvNtC{{[[:print:]]+}}_51sanitizer_cfi_emit_type_metadata_id_itanium_cxx_abi6Trait13fooIu3dynIu{{[0-9]+}}NtC{{[[:print:]]+}}_51sanitizer_cfi_emit_type_metadata_id_itanium_cxx_abi6Trait1Iu3i32Eu6regionES_ES3_S3_E"}
+// CHECK: ![[TYPE126]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NvNtC{{[[:print:]]+}}_51sanitizer_cfi_emit_type_metadata_id_itanium_cxx_abi6Trait13fooIu3dynIu{{[0-9]+}}NtC{{[[:print:]]+}}_51sanitizer_cfi_emit_type_metadata_id_itanium_cxx_abi6Trait1Iu5paramEu6regionEu3i32EE"}
+// CHECK: ![[TYPE127]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NvNtC{{[[:print:]]+}}_51sanitizer_cfi_emit_type_metadata_id_itanium_cxx_abi6Trait13fooIu3dynIu{{[0-9]+}}NtC{{[[:print:]]+}}_51sanitizer_cfi_emit_type_metadata_id_itanium_cxx_abi6Trait1Iu5paramEu6regionEu3i32ES4_E"}
+// CHECK: ![[TYPE128]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NvNtC{{[[:print:]]+}}_51sanitizer_cfi_emit_type_metadata_id_itanium_cxx_abi6Trait13fooIu3dynIu{{[0-9]+}}NtC{{[[:print:]]+}}_51sanitizer_cfi_emit_type_metadata_id_itanium_cxx_abi6Trait1Iu5paramEu6regionEu3i32ES4_S4_E"}
 // CHECK: ![[TYPE129]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NvNtC{{[[:print:]]+}}_51sanitizer_cfi_emit_type_metadata_id_itanium_cxx_abi6Trait13fooIu3i32S_EE"}
 // CHECK: ![[TYPE130]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NvNtC{{[[:print:]]+}}_51sanitizer_cfi_emit_type_metadata_id_itanium_cxx_abi6Trait13fooIu3i32S_ES0_E"}
 // CHECK: ![[TYPE131]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NvNtC{{[[:print:]]+}}_51sanitizer_cfi_emit_type_metadata_id_itanium_cxx_abi6Trait13fooIu3i32S_ES0_S0_E"}
diff --git a/tests/codegen/sanitizer-cfi-emit-type-metadata-trait-objects.rs b/tests/codegen/sanitizer-cfi-emit-type-metadata-trait-objects.rs
index ab5dcec7936..18914049a10 100644
--- a/tests/codegen/sanitizer-cfi-emit-type-metadata-trait-objects.rs
+++ b/tests/codegen/sanitizer-cfi-emit-type-metadata-trait-objects.rs
@@ -1,44 +1,89 @@
 // Verifies that type metadata identifiers for trait objects are emitted correctly.
 //
 // needs-sanitizer-cfi
-// compile-flags: -Clto -Cno-prepopulate-passes -Ctarget-feature=-crt-static -Zsanitizer=cfi
+// compile-flags: -Clto -Cno-prepopulate-passes -Copt-level=0 -Ctarget-feature=-crt-static -Zsanitizer=cfi
 
 #![crate_type="lib"]
 
-trait Trait1 {
+pub trait Trait1 {
     fn foo(&self);
 }
 
-struct Type1;
+#[derive(Clone, Copy)]
+pub struct Type1;
 
 impl Trait1 for Type1 {
     fn foo(&self) {
     }
 }
 
-pub fn foo() {
-    let a = Type1;
+pub trait Trait2<T> {
+    fn bar(&self);
+}
+
+pub struct Type2;
+
+impl Trait2<i32> for Type2 {
+    fn bar(&self) {
+    }
+}
+
+pub trait Trait3<T> {
+    fn baz(&self, _: &T);
+}
+
+pub struct Type3;
+
+impl<T, U> Trait3<U> for T {
+    fn baz(&self, _: &U) {
+    }
+}
+
+pub fn foo1(a: &dyn Trait1) {
     a.foo();
-    // CHECK-LABEL: define{{.*}}foo{{.*}}!type !{{[0-9]+}}
-    // CHECK:       call <sanitizer_cfi_emit_type_metadata_trait_objects::Type1 as sanitizer_cfi_emit_type_metadata_trait_objects::Trait1>::foo
+    // CHECK-LABEL: define{{.*}}4foo1{{.*}}!type !{{[0-9]+}}
+    // CHECK:       call i1 @llvm.type.test({{i8\*|ptr}} {{%f|%[0-9]}}, metadata !"[[TYPE1:[[:print:]]+]]")
 }
 
-pub fn bar() {
+pub fn bar1() {
     let a = Type1;
     let b = &a as &dyn Trait1;
     b.foo();
-    // CHECK-LABEL: define{{.*}}bar{{.*}}!type !{{[0-9]+}}
-    // CHECK:       call i1 @llvm.type.test({{i8\*|ptr}} {{%f|%0|%1}}, metadata !"[[TYPE1:[[:print:]]+]]")
+    // CHECK-LABEL: define{{.*}}4bar1{{.*}}!type !{{[0-9]+}}
+    // CHECK:       call i1 @llvm.type.test({{i8\*|ptr}} {{%f|%[0-9]}}, metadata !"[[TYPE2:[[:print:]]+]]")
 }
 
-pub fn baz() {
-    let a = Type1;
-    let b = &a as &dyn Trait1;
-    a.foo();
-    b.foo();
-    // CHECK-LABEL: define{{.*}}baz{{.*}}!type !{{[0-9]+}}
-    // CHECK:       call <sanitizer_cfi_emit_type_metadata_trait_objects::Type1 as sanitizer_cfi_emit_type_metadata_trait_objects::Trait1>::foo
-    // CHECK:       call i1 @llvm.type.test({{i8\*|ptr}} {{%f|%0|%1}}, metadata !"[[TYPE1:[[:print:]]+]]")
+pub fn foo2<T>(a: &dyn Trait2<T>) {
+    a.bar();
+    // CHECK-LABEL: define{{.*}}4foo2{{.*}}!type !{{[0-9]+}}
+    // CHECK:       call i1 @llvm.type.test({{i8\*|ptr}} {{%f|%[0-9]}}, metadata !"[[TYPE2:[[:print:]]+]]")
+}
+
+pub fn bar2() {
+    let a = Type2;
+    foo2(&a);
+    let b = &a as &dyn Trait2<i32>;
+    b.bar();
+    // CHECK-LABEL: define{{.*}}4bar2{{.*}}!type !{{[0-9]+}}
+    // CHECK:       call i1 @llvm.type.test({{i8\*|ptr}} {{%f|%[0-9]}}, metadata !"[[TYPE2:[[:print:]]+]]")
+}
+
+pub fn foo3(a: &dyn Trait3<Type3>) {
+    let b = Type3;
+    a.baz(&b);
+    // CHECK-LABEL: define{{.*}}4foo3{{.*}}!type !{{[0-9]+}}
+    // CHECK:       call i1 @llvm.type.test({{i8\*|ptr}} {{%f|%[0-9]}}, metadata !"[[TYPE3:[[:print:]]+]]")
+}
+
+pub fn bar3() {
+    let a = Type3;
+    foo3(&a);
+    let b = &a as &dyn Trait3<Type3>;
+    b.baz(&a);
+    // CHECK-LABEL: define{{.*}}4bar3{{.*}}!type !{{[0-9]+}}
+    // CHECK:       call i1 @llvm.type.test({{i8\*|ptr}} {{%f|%[0-9]}}, metadata !"[[TYPE3:[[:print:]]+]]")
 }
 
 // CHECK: !{{[0-9]+}} = !{i64 0, !"[[TYPE1]]"}
+// CHECK: !{{[0-9]+}} = !{i64 0, !"[[TYPE2]]"}
+// CHECK: !{{[0-9]+}} = !{i64 0, !"[[TYPE3]]"}
diff --git a/tests/codegen/sanitizer-kcfi-emit-type-metadata-trait-objects.rs b/tests/codegen/sanitizer-kcfi-emit-type-metadata-trait-objects.rs
index 81e0d9344f7..a46f0955696 100644
--- a/tests/codegen/sanitizer-kcfi-emit-type-metadata-trait-objects.rs
+++ b/tests/codegen/sanitizer-kcfi-emit-type-metadata-trait-objects.rs
@@ -30,40 +30,84 @@ trait Freeze { }
 #[lang="drop_in_place"]
 fn drop_in_place_fn<T>() { }
 
-trait Trait1 {
+pub trait Trait1 {
     fn foo(&self);
 }
 
-struct Type1;
+pub struct Type1;
 
 impl Trait1 for Type1 {
     fn foo(&self) {
     }
 }
 
-pub fn foo() {
-    let a = Type1;
+pub trait Trait2<T> {
+    fn bar(&self);
+}
+
+pub struct Type2;
+
+impl Trait2<i32> for Type2 {
+    fn bar(&self) {
+    }
+}
+
+pub trait Trait3<T> {
+    fn baz(&self, _: &T);
+}
+
+pub struct Type3;
+
+impl<T, U> Trait3<U> for T {
+    fn baz(&self, _: &U) {
+    }
+}
+
+pub fn foo1(a: &dyn Trait1) {
     a.foo();
-    // CHECK-LABEL: define{{.*}}foo{{.*}}!{{<unknown kind #36>|kcfi_type}} !{{[0-9]+}}
-    // CHECK:       call <sanitizer_kcfi_emit_type_metadata_trait_objects::Type1 as sanitizer_kcfi_emit_type_metadata_trait_objects::Trait1>::foo
+    // CHECK-LABEL: define{{.*}}4foo1{{.*}}!{{<unknown kind #36>|kcfi_type}} !{{[0-9]+}}
+    // CHECK:       call void %{{[0-9]}}({{\{\}\*|ptr}} align 1 {{%[a-z]\.0|%_[0-9]}}){{.*}}[ "kcfi"(i32 [[TYPE1:[[:print:]]+]]) ]
 }
 
-pub fn bar() {
+pub fn bar1() {
     let a = Type1;
     let b = &a as &dyn Trait1;
     b.foo();
-    // CHECK-LABEL: define{{.*}}bar{{.*}}!{{<unknown kind #36>|kcfi_type}} !{{[0-9]+}}
-    // CHECK:       call void %0({{\{\}\*|ptr}} align 1 {{%b\.0|%_1}}){{.*}}[ "kcfi"(i32 [[TYPE1:[[:print:]]+]]) ]
+    // CHECK-LABEL: define{{.*}}4bar1{{.*}}!{{<unknown kind #36>|kcfi_type}} !{{[0-9]+}}
+    // CHECK:       call void %{{[0-9]}}({{\{\}\*|ptr}} align 1 {{%[a-z]\.0|%_[0-9]}}){{.*}}[ "kcfi"(i32 [[TYPE1:[[:print:]]+]]) ]
 }
 
-pub fn baz() {
-    let a = Type1;
-    let b = &a as &dyn Trait1;
-    a.foo();
-    b.foo();
-    // CHECK-LABEL: define{{.*}}baz{{.*}}!{{<unknown kind #36>|kcfi_type}} !{{[0-9]+}}
-    // CHECK:       call <sanitizer_kcfi_emit_type_metadata_trait_objects::Type1 as sanitizer_kcfi_emit_type_metadata_trait_objects::Trait1>::foo
-    // CHECK:       call void %0({{\{\}\*|ptr}} align 1 {{%b\.0|%_1}}){{.*}}[ "kcfi"(i32 [[TYPE1:[[:print:]]+]]) ]
+pub fn foo2<T>(a: &dyn Trait2<T>) {
+    a.bar();
+    // CHECK-LABEL: define{{.*}}4foo2{{.*}}!{{<unknown kind #36>|kcfi_type}} !{{[0-9]+}}
+    // CHECK:       call void %{{[0-9]}}({{\{\}\*|ptr}} align 1 {{%[a-z]\.0|%_[0-9]}}){{.*}}[ "kcfi"(i32 [[TYPE2:[[:print:]]+]]) ]
+}
+
+pub fn bar2() {
+    let a = Type2;
+    foo2(&a);
+    let b = &a as &dyn Trait2<i32>;
+    b.bar();
+    // CHECK-LABEL: define{{.*}}4bar2{{.*}}!{{<unknown kind #36>|kcfi_type}} !{{[0-9]+}}
+    // CHECK:       call void %{{[0-9]}}({{\{\}\*|ptr}} align 1 {{%[a-z]\.0|%_[0-9]}}){{.*}}[ "kcfi"(i32 [[TYPE2:[[:print:]]+]]) ]
+}
+
+pub fn foo3(a: &dyn Trait3<Type3>) {
+    let b = Type3;
+    a.baz(&b);
+    // CHECK-LABEL: define{{.*}}4foo3{{.*}}!{{<unknown kind #36>|kcfi_type}} !{{[0-9]+}}
+    // CHECK:       call void %{{[0-9]}}({{\{\}\*|ptr}} align 1 {{%[a-z]\.0|%_[0-9]}}, {{\{\}\*|ptr|%Type3\*}} align 1 {{%[a-z]\.0|%_[0-9]}}){{.*}}[ "kcfi"(i32 [[TYPE3:[[:print:]]+]]) ]
+}
+
+pub fn bar3() {
+    let a = Type3;
+    foo3(&a);
+    let b = &a as &dyn Trait3<Type3>;
+    b.baz(&a);
+    // CHECK-LABEL: define{{.*}}4bar3{{.*}}!{{<unknown kind #36>|kcfi_type}} !{{[0-9]+}}
+    // CHECK:       call void %{{[0-9]}}({{\{\}\*|ptr}} align 1 {{%[a-z]\.0|%_[0-9]}}, {{\{\}\*|ptr|%Type3\*}} align 1 {{%[a-z]\.0|%_[0-9]}}){{.*}}[ "kcfi"(i32 [[TYPE3:[[:print:]]+]]) ]
 }
 
 // CHECK: !{{[0-9]+}} = !{i32 [[TYPE1]]}
+// CHECK: !{{[0-9]+}} = !{i32 [[TYPE2]]}
+// CHECK: !{{[0-9]+}} = !{i32 [[TYPE3]]}
diff --git a/tests/codegen/slice-iter-nonnull.rs b/tests/codegen/slice-iter-nonnull.rs
index 392e4338076..997bdaf5636 100644
--- a/tests/codegen/slice-iter-nonnull.rs
+++ b/tests/codegen/slice-iter-nonnull.rs
@@ -40,3 +40,38 @@ pub fn slice_iter_next_back<'a>(it: &mut std::slice::Iter<'a, u32>) -> Option<&'
 
     it.next_back()
 }
+
+// The slice iterator `new` methods used to `assume` that the pointer is non-null,
+// but passing slices already requires that, to the extent that LLVM actually
+// removed the `call @llvm.assume` anyway.  These tests just demonstrate that the
+// attribute is there, and confirms adding the assume back doesn't do anything.
+
+// CHECK-LABEL: @slice_iter_new
+// CHECK-SAME: (ptr noalias noundef nonnull {{.+}} %slice.0, {{.+}} noundef %slice.1)
+#[no_mangle]
+pub fn slice_iter_new(slice: &[u32]) -> std::slice::Iter<'_, u32> {
+    // CHECK-NOT: slice
+    // CHECK: %[[END:.+]] = getelementptr inbounds i32{{.+}} %slice.0{{.+}} %slice.1
+    // CHECK-NOT: slice
+    // CHECK: insertvalue {{.+}} ptr %slice.0, 0
+    // CHECK-NOT: slice
+    // CHECK: insertvalue {{.+}} ptr %[[END]], 1
+    // CHECK-NOT: slice
+    // CHECK: }
+    slice.iter()
+}
+
+// CHECK-LABEL: @slice_iter_mut_new
+// CHECK-SAME: (ptr noalias noundef nonnull {{.+}} %slice.0, {{.+}} noundef %slice.1)
+#[no_mangle]
+pub fn slice_iter_mut_new(slice: &mut [u32]) -> std::slice::IterMut<'_, u32> {
+    // CHECK-NOT: slice
+    // CHECK: %[[END:.+]] = getelementptr inbounds i32{{.+}} %slice.0{{.+}} %slice.1
+    // CHECK-NOT: slice
+    // CHECK: insertvalue {{.+}} ptr %slice.0, 0
+    // CHECK-NOT: slice
+    // CHECK: insertvalue {{.+}} ptr %[[END]], 1
+    // CHECK-NOT: slice
+    // CHECK: }
+    slice.iter_mut()
+}
diff --git a/tests/codegen/var-names.rs b/tests/codegen/var-names.rs
index d4715efad73..53841df32e8 100644
--- a/tests/codegen/var-names.rs
+++ b/tests/codegen/var-names.rs
@@ -9,7 +9,7 @@ pub fn test(a: u32, b: u32) -> u32 {
     // CHECK: %c = add i32 %a, %b
     let d = c;
     let e = d * a;
-    // CHECK-NEXT: %e = mul i32 %c, %a
+    // CHECK-NEXT: %0 = mul i32 %c, %a
     e
-    // CHECK-NEXT: ret i32 %e
+    // CHECK-NEXT: ret i32 %0
 }
diff --git a/tests/debuginfo/reference-debuginfo.rs b/tests/debuginfo/reference-debuginfo.rs
new file mode 100644
index 00000000000..85ade170ac6
--- /dev/null
+++ b/tests/debuginfo/reference-debuginfo.rs
@@ -0,0 +1,173 @@
+// Copy of `borrowed-basic.rs` which enables the `ReferencePropagation` MIR pass.
+// That pass replaces debuginfo for `a => _x` where `_x = &b` to be `a => &b`,
+// and leaves codegen to create a ladder of allocations so as `*a == b`.
+//
+// compile-flags:-g -Zmir-enable-passes=+ReferencePropagation,-ConstDebugInfo
+// min-lldb-version: 310
+
+// === GDB TESTS ===================================================================================
+
+// gdb-command:run
+// gdb-command:print *bool_ref
+// gdb-check:$1 = true
+
+// gdb-command:print *int_ref
+// gdb-check:$2 = -1
+
+// gdb-command:print/d *char_ref
+// gdb-check:$3 = 97
+
+// gdb-command:print *i8_ref
+// gdbg-check:$4 = 68 'D'
+// gdbr-check:$4 = 68
+
+// gdb-command:print *i16_ref
+// gdb-check:$5 = -16
+
+// gdb-command:print *i32_ref
+// gdb-check:$6 = -32
+
+// gdb-command:print *i64_ref
+// gdb-check:$7 = -64
+
+// gdb-command:print *uint_ref
+// gdb-check:$8 = 1
+
+// gdb-command:print *u8_ref
+// gdbg-check:$9 = 100 'd'
+// gdbr-check:$9 = 100
+
+// gdb-command:print *u16_ref
+// gdb-check:$10 = 16
+
+// gdb-command:print *u32_ref
+// gdb-check:$11 = 32
+
+// gdb-command:print *u64_ref
+// gdb-check:$12 = 64
+
+// gdb-command:print *f32_ref
+// gdb-check:$13 = 2.5
+
+// gdb-command:print *f64_ref
+// gdb-check:$14 = 3.5
+
+// gdb-command:print *f64_double_ref
+// gdb-check:$15 = 3.5
+
+
+// === LLDB TESTS ==================================================================================
+
+// lldb-command:run
+// lldb-command:print *bool_ref
+// lldbg-check:[...]$0 = true
+// lldbr-check:(bool) *bool_ref = true
+
+// lldb-command:print *int_ref
+// lldbg-check:[...]$1 = -1
+// lldbr-check:(isize) *int_ref = -1
+
+// NOTE: only rust-enabled lldb supports 32bit chars
+// lldbr-command:print *char_ref
+// lldbr-check:(char) *char_ref = 'a'
+
+// lldb-command:print *i8_ref
+// lldbg-check:[...]$2 = 'D'
+// lldbr-check:(i8) *i8_ref = 68
+
+// lldb-command:print *i16_ref
+// lldbg-check:[...]$3 = -16
+// lldbr-check:(i16) *i16_ref = -16
+
+// lldb-command:print *i32_ref
+// lldbg-check:[...]$4 = -32
+// lldbr-check:(i32) *i32_ref = -32
+
+// lldb-command:print *i64_ref
+// lldbg-check:[...]$5 = -64
+// lldbr-check:(i64) *i64_ref = -64
+
+// lldb-command:print *uint_ref
+// lldbg-check:[...]$6 = 1
+// lldbr-check:(usize) *uint_ref = 1
+
+// lldb-command:print *u8_ref
+// lldbg-check:[...]$7 = 'd'
+// lldbr-check:(u8) *u8_ref = 100
+
+// lldb-command:print *u16_ref
+// lldbg-check:[...]$8 = 16
+// lldbr-check:(u16) *u16_ref = 16
+
+// lldb-command:print *u32_ref
+// lldbg-check:[...]$9 = 32
+// lldbr-check:(u32) *u32_ref = 32
+
+// lldb-command:print *u64_ref
+// lldbg-check:[...]$10 = 64
+// lldbr-check:(u64) *u64_ref = 64
+
+// lldb-command:print *f32_ref
+// lldbg-check:[...]$11 = 2.5
+// lldbr-check:(f32) *f32_ref = 2.5
+
+// lldb-command:print *f64_ref
+// lldbg-check:[...]$12 = 3.5
+// lldbr-check:(f64) *f64_ref = 3.5
+
+// lldb-command:print *f64_double_ref
+// lldbg-check:[...]$13 = 3.5
+// lldbr-check:(f64) **f64_double_ref = 3.5
+
+#![allow(unused_variables)]
+#![feature(omit_gdb_pretty_printer_section)]
+#![omit_gdb_pretty_printer_section]
+
+fn main() {
+    let bool_val: bool = true;
+    let bool_ref: &bool = &bool_val;
+
+    let int_val: isize = -1;
+    let int_ref: &isize = &int_val;
+
+    let char_val: char = 'a';
+    let char_ref: &char = &char_val;
+
+    let i8_val: i8 = 68;
+    let i8_ref: &i8 = &i8_val;
+
+    let i16_val: i16 = -16;
+    let i16_ref: &i16 = &i16_val;
+
+    let i32_val: i32 = -32;
+    let i32_ref: &i32 = &i32_val;
+
+    let i64_val: i64 = -64;
+    let i64_ref: &i64 = &i64_val;
+
+    let uint_val: usize = 1;
+    let uint_ref: &usize = &uint_val;
+
+    let u8_val: u8 = 100;
+    let u8_ref: &u8 = &u8_val;
+
+    let u16_val: u16 = 16;
+    let u16_ref: &u16 = &u16_val;
+
+    let u32_val: u32 = 32;
+    let u32_ref: &u32 = &u32_val;
+
+    let u64_val: u64 = 64;
+    let u64_ref: &u64 = &u64_val;
+
+    let f32_val: f32 = 2.5;
+    let f32_ref: &f32 = &f32_val;
+
+    let f64_val: f64 = 3.5;
+    let f64_ref: &f64 = &f64_val;
+    let f64_double_ref: &f64 = &f64_ref;
+
+    zzz(); // #break
+}
+
+fn zzz() {()}
diff --git a/tests/incremental/const-generic-type-cycle.rs b/tests/incremental/const-generic-type-cycle.rs
new file mode 100644
index 00000000000..ca7b12e9e62
--- /dev/null
+++ b/tests/incremental/const-generic-type-cycle.rs
@@ -0,0 +1,17 @@
+// Verify that we do not ICE when we try to overwrite an anon-const's type because of a trait
+// cycle.
+//
+// compile-flags: -Zincremental-ignore-spans
+// revisions: cpass cfail
+// error-pattern: cycle detected when computing type of `Bar::N`
+
+#![feature(trait_alias)]
+#![crate_type="lib"]
+
+#[cfg(cpass)]
+trait Bar<const N: usize> {}
+
+#[cfg(cfail)]
+trait Bar<const N: dyn BB> {}
+
+trait BB = Bar<{ 2 + 1 }>;
diff --git a/tests/mir-opt/building/custom/projections.copy_for_deref.built.after.mir b/tests/mir-opt/building/custom/projections.copy_for_deref.built.after.mir
new file mode 100644
index 00000000000..5233d0489c6
--- /dev/null
+++ b/tests/mir-opt/building/custom/projections.copy_for_deref.built.after.mir
@@ -0,0 +1,12 @@
+// MIR for `copy_for_deref` after built
+
+fn copy_for_deref(_1: (&i32, i32)) -> i32 {
+    let mut _0: i32;                     // return place in scope 0 at $DIR/projections.rs:+0:38: +0:41
+    let mut _2: &i32;                    // in scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL
+
+    bb0: {
+        _2 = deref_copy (_1.0: &i32);    // scope 0 at $DIR/projections.rs:+4:13: +4:37
+        _0 = (*_2);                      // scope 0 at $DIR/projections.rs:+5:13: +5:24
+        return;                          // scope 0 at $DIR/projections.rs:+6:13: +6:21
+    }
+}
diff --git a/tests/mir-opt/building/custom/projections.rs b/tests/mir-opt/building/custom/projections.rs
index 5e472e531c7..3c155deae4b 100644
--- a/tests/mir-opt/building/custom/projections.rs
+++ b/tests/mir-opt/building/custom/projections.rs
@@ -21,13 +21,10 @@ fn unions(u: U) -> i32 {
 #[custom_mir(dialect = "analysis", phase = "post-cleanup")]
 fn tuples(i: (u32, i32)) -> (u32, i32) {
     mir!(
-        // FIXME(JakobDegen): This is necessary because we can't give type hints for `RET`
-        let temp: (u32, i32);
+        type RET = (u32, i32);
         {
-            temp.0 = i.0;
-            temp.1 = i.1;
-
-            RET = temp;
+            RET.0 = i.0;
+            RET.1 = i.1;
             Return()
         }
     )
@@ -71,6 +68,19 @@ fn simple_index(a: [i32; 10], b: &[i32]) -> i32 {
     })
 }
 
+// EMIT_MIR projections.copy_for_deref.built.after.mir
+#[custom_mir(dialect = "runtime", phase = "initial")]
+fn copy_for_deref(x: (&i32, i32)) -> i32 {
+    mir!(
+        let temp: &i32;
+        {
+            temp = CopyForDeref(x.0);
+            RET = *temp;
+            Return()
+        }
+    )
+}
+
 fn main() {
     assert_eq!(unions(U { a: 5 }), 5);
     assert_eq!(tuples((5, 6)), (5, 6));
@@ -82,4 +92,7 @@ fn main() {
     assert_eq!(o, Some(10));
 
     assert_eq!(simple_index([0; 10], &[0; 10]), 0);
+
+    let one = 1;
+    assert_eq!(copy_for_deref((&one, one)), 1);
 }
diff --git a/tests/mir-opt/building/custom/projections.tuples.built.after.mir b/tests/mir-opt/building/custom/projections.tuples.built.after.mir
index 65487d3c9ed..dec575200c6 100644
--- a/tests/mir-opt/building/custom/projections.tuples.built.after.mir
+++ b/tests/mir-opt/building/custom/projections.tuples.built.after.mir
@@ -2,12 +2,10 @@
 
 fn tuples(_1: (u32, i32)) -> (u32, i32) {
     let mut _0: (u32, i32);              // return place in scope 0 at $DIR/projections.rs:+0:29: +0:39
-    let mut _2: (u32, i32);              // in scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL
 
     bb0: {
-        (_2.0: u32) = (_1.0: u32);       // scope 0 at $DIR/projections.rs:+5:13: +5:25
-        (_2.1: i32) = (_1.1: i32);       // scope 0 at $DIR/projections.rs:+6:13: +6:25
-        _0 = _2;                         // scope 0 at $DIR/projections.rs:+8:13: +8:23
-        return;                          // scope 0 at $DIR/projections.rs:+9:13: +9:21
+        (_0.0: u32) = (_1.0: u32);       // scope 0 at $DIR/projections.rs:+4:13: +4:24
+        (_0.1: i32) = (_1.1: i32);       // scope 0 at $DIR/projections.rs:+5:13: +5:24
+        return;                          // scope 0 at $DIR/projections.rs:+6:13: +6:21
     }
 }
diff --git a/tests/mir-opt/combine_transmutes.adt_transmutes.InstSimplify.diff b/tests/mir-opt/combine_transmutes.adt_transmutes.InstSimplify.diff
index c5907e7cf18..15117ea890e 100644
--- a/tests/mir-opt/combine_transmutes.adt_transmutes.InstSimplify.diff
+++ b/tests/mir-opt/combine_transmutes.adt_transmutes.InstSimplify.diff
@@ -4,59 +4,29 @@
   fn adt_transmutes() -> () {
       let mut _0: ();                      // return place in scope 0 at $DIR/combine_transmutes.rs:+0:32: +0:32
       let _1: u8;                          // in scope 0 at $DIR/combine_transmutes.rs:+1:9: +1:11
-      let mut _2: EnumNoRepr;              // in scope 0 at $DIR/combine_transmutes.rs:+1:28: +1:41
-      let mut _4: EnumNoRepr;              // in scope 0 at $DIR/combine_transmutes.rs:+2:28: +2:41
-      let mut _6: EnumReprIsize;           // in scope 0 at $DIR/combine_transmutes.rs:+3:31: +3:47
-      let mut _8: EnumReprIsize;           // in scope 0 at $DIR/combine_transmutes.rs:+4:31: +4:47
-      let mut _10: std::cmp::Ordering;     // in scope 0 at $DIR/combine_transmutes.rs:+5:28: +5:52
-      let mut _12: std::cmp::Ordering;     // in scope 0 at $DIR/combine_transmutes.rs:+6:28: +6:52
-      let mut _14: std::option::Option<std::num::NonZeroU8>; // in scope 0 at $DIR/combine_transmutes.rs:+7:28: +7:58
-      let mut _16: std::num::Wrapping<i16>; // in scope 0 at $DIR/combine_transmutes.rs:+8:29: +8:54
-      let mut _18: std::num::Wrapping<i16>; // in scope 0 at $DIR/combine_transmutes.rs:+9:29: +9:54
-      let mut _20: Union32;                // in scope 0 at $DIR/combine_transmutes.rs:+10:29: +10:47
-      let mut _22: Union32;                // in scope 0 at $DIR/combine_transmutes.rs:+11:29: +11:47
-      let mut _24: std::mem::MaybeUninit<std::string::String>; // in scope 0 at $DIR/combine_transmutes.rs:+12:46: +12:77
+      let mut _2: std::option::Option<std::num::NonZeroU8>; // in scope 0 at $DIR/combine_transmutes.rs:+1:28: +1:58
+      let mut _4: std::num::Wrapping<i16>; // in scope 0 at $DIR/combine_transmutes.rs:+2:29: +2:54
+      let mut _6: std::num::Wrapping<i16>; // in scope 0 at $DIR/combine_transmutes.rs:+3:29: +3:54
+      let mut _8: Union32;                 // in scope 0 at $DIR/combine_transmutes.rs:+4:29: +4:47
+      let mut _10: Union32;                // in scope 0 at $DIR/combine_transmutes.rs:+5:29: +5:47
+      let mut _12: std::mem::MaybeUninit<std::string::String>; // in scope 0 at $DIR/combine_transmutes.rs:+6:46: +6:77
       scope 1 {
           debug _a => _1;                  // in scope 1 at $DIR/combine_transmutes.rs:+1:9: +1:11
-          let _3: i8;                      // in scope 1 at $DIR/combine_transmutes.rs:+2:9: +2:11
+          let _3: i16;                     // in scope 1 at $DIR/combine_transmutes.rs:+2:9: +2:11
           scope 2 {
               debug _a => _3;              // in scope 2 at $DIR/combine_transmutes.rs:+2:9: +2:11
-              let _5: usize;               // in scope 2 at $DIR/combine_transmutes.rs:+3:9: +3:11
+              let _5: u16;                 // in scope 2 at $DIR/combine_transmutes.rs:+3:9: +3:11
               scope 3 {
                   debug _a => _5;          // in scope 3 at $DIR/combine_transmutes.rs:+3:9: +3:11
-                  let _7: isize;           // in scope 3 at $DIR/combine_transmutes.rs:+4:9: +4:11
+                  let _7: u32;             // in scope 3 at $DIR/combine_transmutes.rs:+4:9: +4:11
                   scope 4 {
                       debug _a => _7;      // in scope 4 at $DIR/combine_transmutes.rs:+4:9: +4:11
-                      let _9: u8;          // in scope 4 at $DIR/combine_transmutes.rs:+5:9: +5:11
+                      let _9: i32;         // in scope 4 at $DIR/combine_transmutes.rs:+5:9: +5:11
                       scope 5 {
                           debug _a => _9;  // in scope 5 at $DIR/combine_transmutes.rs:+5:9: +5:11
-                          let _11: i8;     // in scope 5 at $DIR/combine_transmutes.rs:+6:9: +6:11
+                          let _11: std::mem::ManuallyDrop<std::string::String>; // in scope 5 at $DIR/combine_transmutes.rs:+6:9: +6:11
                           scope 6 {
                               debug _a => _11; // in scope 6 at $DIR/combine_transmutes.rs:+6:9: +6:11
-                              let _13: u8; // in scope 6 at $DIR/combine_transmutes.rs:+7:9: +7:11
-                              scope 7 {
-                                  debug _a => _13; // in scope 7 at $DIR/combine_transmutes.rs:+7:9: +7:11
-                                  let _15: i16; // in scope 7 at $DIR/combine_transmutes.rs:+8:9: +8:11
-                                  scope 8 {
-                                      debug _a => _15; // in scope 8 at $DIR/combine_transmutes.rs:+8:9: +8:11
-                                      let _17: u16; // in scope 8 at $DIR/combine_transmutes.rs:+9:9: +9:11
-                                      scope 9 {
-                                          debug _a => _17; // in scope 9 at $DIR/combine_transmutes.rs:+9:9: +9:11
-                                          let _19: u32; // in scope 9 at $DIR/combine_transmutes.rs:+10:9: +10:11
-                                          scope 10 {
-                                              debug _a => _19; // in scope 10 at $DIR/combine_transmutes.rs:+10:9: +10:11
-                                              let _21: i32; // in scope 10 at $DIR/combine_transmutes.rs:+11:9: +11:11
-                                              scope 11 {
-                                                  debug _a => _21; // in scope 11 at $DIR/combine_transmutes.rs:+11:9: +11:11
-                                                  let _23: std::mem::ManuallyDrop<std::string::String>; // in scope 11 at $DIR/combine_transmutes.rs:+12:9: +12:11
-                                                  scope 12 {
-                                                      debug _a => _23; // in scope 12 at $DIR/combine_transmutes.rs:+12:9: +12:11
-                                                  }
-                                              }
-                                          }
-                                      }
-                                  }
-                              }
                           }
                       }
                   }
@@ -66,93 +36,55 @@
   
       bb0: {
           StorageLive(_1);                 // scope 0 at $DIR/combine_transmutes.rs:+1:9: +1:11
-          StorageLive(_2);                 // scope 0 at $DIR/combine_transmutes.rs:+1:28: +1:41
-          _2 = EnumNoRepr::A;              // scope 0 at $DIR/combine_transmutes.rs:+1:28: +1:41
-          _1 = move _2 as u8 (Transmute);  // scope 0 at $DIR/combine_transmutes.rs:+1:18: +1:42
-          StorageDead(_2);                 // scope 0 at $DIR/combine_transmutes.rs:+1:41: +1:42
+          StorageLive(_2);                 // scope 0 at $DIR/combine_transmutes.rs:+1:28: +1:58
+          _2 = Option::<NonZeroU8>::Some(const _); // scope 0 at $DIR/combine_transmutes.rs:+1:28: +1:58
+                                           // mir::Constant
+                                           // + span: $DIR/combine_transmutes.rs:35:33: 35:57
+                                           // + literal: Const { ty: NonZeroU8, val: Unevaluated(NonZeroU8::MAX, [], None) }
+          _1 = move _2 as u8 (Transmute);  // scope 0 at $DIR/combine_transmutes.rs:+1:18: +1:59
+          StorageDead(_2);                 // scope 0 at $DIR/combine_transmutes.rs:+1:58: +1:59
           StorageLive(_3);                 // scope 1 at $DIR/combine_transmutes.rs:+2:9: +2:11
-          StorageLive(_4);                 // scope 1 at $DIR/combine_transmutes.rs:+2:28: +2:41
-          _4 = EnumNoRepr::B;              // scope 1 at $DIR/combine_transmutes.rs:+2:28: +2:41
-          _3 = move _4 as i8 (Transmute);  // scope 1 at $DIR/combine_transmutes.rs:+2:18: +2:42
-          StorageDead(_4);                 // scope 1 at $DIR/combine_transmutes.rs:+2:41: +2:42
+          StorageLive(_4);                 // scope 1 at $DIR/combine_transmutes.rs:+2:29: +2:54
+          _4 = Wrapping::<i16>(const 0_i16); // scope 1 at $DIR/combine_transmutes.rs:+2:29: +2:54
+-         _3 = move _4 as i16 (Transmute); // scope 1 at $DIR/combine_transmutes.rs:+2:19: +2:55
++         _3 = move (_4.0: i16);           // scope 1 at $DIR/combine_transmutes.rs:+2:19: +2:55
+          StorageDead(_4);                 // scope 1 at $DIR/combine_transmutes.rs:+2:54: +2:55
           StorageLive(_5);                 // scope 2 at $DIR/combine_transmutes.rs:+3:9: +3:11
-          StorageLive(_6);                 // scope 2 at $DIR/combine_transmutes.rs:+3:31: +3:47
-          _6 = EnumReprIsize::A;           // scope 2 at $DIR/combine_transmutes.rs:+3:31: +3:47
-          _5 = move _6 as usize (Transmute); // scope 2 at $DIR/combine_transmutes.rs:+3:21: +3:48
-          StorageDead(_6);                 // scope 2 at $DIR/combine_transmutes.rs:+3:47: +3:48
+          StorageLive(_6);                 // scope 2 at $DIR/combine_transmutes.rs:+3:29: +3:54
+          _6 = Wrapping::<i16>(const 0_i16); // scope 2 at $DIR/combine_transmutes.rs:+3:29: +3:54
+          _5 = move _6 as u16 (Transmute); // scope 2 at $DIR/combine_transmutes.rs:+3:19: +3:55
+          StorageDead(_6);                 // scope 2 at $DIR/combine_transmutes.rs:+3:54: +3:55
           StorageLive(_7);                 // scope 3 at $DIR/combine_transmutes.rs:+4:9: +4:11
-          StorageLive(_8);                 // scope 3 at $DIR/combine_transmutes.rs:+4:31: +4:47
-          _8 = EnumReprIsize::B;           // scope 3 at $DIR/combine_transmutes.rs:+4:31: +4:47
--         _7 = move _8 as isize (Transmute); // scope 3 at $DIR/combine_transmutes.rs:+4:21: +4:48
-+         _7 = discriminant(_8);           // scope 3 at $DIR/combine_transmutes.rs:+4:21: +4:48
+          StorageLive(_8);                 // scope 3 at $DIR/combine_transmutes.rs:+4:29: +4:47
+          _8 = Union32 { u32: const 0_i32 }; // scope 3 at $DIR/combine_transmutes.rs:+4:29: +4:47
+          _7 = move _8 as u32 (Transmute); // scope 3 at $DIR/combine_transmutes.rs:+4:19: +4:48
           StorageDead(_8);                 // scope 3 at $DIR/combine_transmutes.rs:+4:47: +4:48
           StorageLive(_9);                 // scope 4 at $DIR/combine_transmutes.rs:+5:9: +5:11
-          StorageLive(_10);                // scope 4 at $DIR/combine_transmutes.rs:+5:28: +5:52
-          _10 = Less;                      // scope 4 at $DIR/combine_transmutes.rs:+5:28: +5:52
-          _9 = move _10 as u8 (Transmute); // scope 4 at $DIR/combine_transmutes.rs:+5:18: +5:53
-          StorageDead(_10);                // scope 4 at $DIR/combine_transmutes.rs:+5:52: +5:53
+          StorageLive(_10);                // scope 4 at $DIR/combine_transmutes.rs:+5:29: +5:47
+          _10 = Union32 { u32: const 0_u32 }; // scope 4 at $DIR/combine_transmutes.rs:+5:29: +5:47
+          _9 = move _10 as i32 (Transmute); // scope 4 at $DIR/combine_transmutes.rs:+5:19: +5:48
+          StorageDead(_10);                // scope 4 at $DIR/combine_transmutes.rs:+5:47: +5:48
           StorageLive(_11);                // scope 5 at $DIR/combine_transmutes.rs:+6:9: +6:11
-          StorageLive(_12);                // scope 5 at $DIR/combine_transmutes.rs:+6:28: +6:52
-          _12 = Less;                      // scope 5 at $DIR/combine_transmutes.rs:+6:28: +6:52
--         _11 = move _12 as i8 (Transmute); // scope 5 at $DIR/combine_transmutes.rs:+6:18: +6:53
-+         _11 = discriminant(_12);         // scope 5 at $DIR/combine_transmutes.rs:+6:18: +6:53
-          StorageDead(_12);                // scope 5 at $DIR/combine_transmutes.rs:+6:52: +6:53
-          StorageLive(_13);                // scope 6 at $DIR/combine_transmutes.rs:+7:9: +7:11
-          StorageLive(_14);                // scope 6 at $DIR/combine_transmutes.rs:+7:28: +7:58
-          _14 = Option::<NonZeroU8>::Some(const _); // scope 6 at $DIR/combine_transmutes.rs:+7:28: +7:58
-                                           // mir::Constant
-                                           // + span: $DIR/combine_transmutes.rs:41:33: 41:57
-                                           // + literal: Const { ty: NonZeroU8, val: Unevaluated(NonZeroU8::MAX, [], None) }
-          _13 = move _14 as u8 (Transmute); // scope 6 at $DIR/combine_transmutes.rs:+7:18: +7:59
-          StorageDead(_14);                // scope 6 at $DIR/combine_transmutes.rs:+7:58: +7:59
-          StorageLive(_15);                // scope 7 at $DIR/combine_transmutes.rs:+8:9: +8:11
-          StorageLive(_16);                // scope 7 at $DIR/combine_transmutes.rs:+8:29: +8:54
-          _16 = Wrapping::<i16>(const 0_i16); // scope 7 at $DIR/combine_transmutes.rs:+8:29: +8:54
--         _15 = move _16 as i16 (Transmute); // scope 7 at $DIR/combine_transmutes.rs:+8:19: +8:55
-+         _15 = move (_16.0: i16);         // scope 7 at $DIR/combine_transmutes.rs:+8:19: +8:55
-          StorageDead(_16);                // scope 7 at $DIR/combine_transmutes.rs:+8:54: +8:55
-          StorageLive(_17);                // scope 8 at $DIR/combine_transmutes.rs:+9:9: +9:11
-          StorageLive(_18);                // scope 8 at $DIR/combine_transmutes.rs:+9:29: +9:54
-          _18 = Wrapping::<i16>(const 0_i16); // scope 8 at $DIR/combine_transmutes.rs:+9:29: +9:54
-          _17 = move _18 as u16 (Transmute); // scope 8 at $DIR/combine_transmutes.rs:+9:19: +9:55
-          StorageDead(_18);                // scope 8 at $DIR/combine_transmutes.rs:+9:54: +9:55
-          StorageLive(_19);                // scope 9 at $DIR/combine_transmutes.rs:+10:9: +10:11
-          StorageLive(_20);                // scope 9 at $DIR/combine_transmutes.rs:+10:29: +10:47
-          _20 = Union32 { u32: const 0_i32 }; // scope 9 at $DIR/combine_transmutes.rs:+10:29: +10:47
-          _19 = move _20 as u32 (Transmute); // scope 9 at $DIR/combine_transmutes.rs:+10:19: +10:48
-          StorageDead(_20);                // scope 9 at $DIR/combine_transmutes.rs:+10:47: +10:48
-          StorageLive(_21);                // scope 10 at $DIR/combine_transmutes.rs:+11:9: +11:11
-          StorageLive(_22);                // scope 10 at $DIR/combine_transmutes.rs:+11:29: +11:47
-          _22 = Union32 { u32: const 0_u32 }; // scope 10 at $DIR/combine_transmutes.rs:+11:29: +11:47
-          _21 = move _22 as i32 (Transmute); // scope 10 at $DIR/combine_transmutes.rs:+11:19: +11:48
-          StorageDead(_22);                // scope 10 at $DIR/combine_transmutes.rs:+11:47: +11:48
-          StorageLive(_23);                // scope 11 at $DIR/combine_transmutes.rs:+12:9: +12:11
-          StorageLive(_24);                // scope 11 at $DIR/combine_transmutes.rs:+12:46: +12:77
-          _24 = MaybeUninit::<String>::uninit() -> [return: bb1, unwind unreachable]; // scope 11 at $DIR/combine_transmutes.rs:+12:46: +12:77
+          StorageLive(_12);                // scope 5 at $DIR/combine_transmutes.rs:+6:46: +6:77
+          _12 = MaybeUninit::<String>::uninit() -> [return: bb1, unwind unreachable]; // scope 5 at $DIR/combine_transmutes.rs:+6:46: +6:77
                                            // mir::Constant
-                                           // + span: $DIR/combine_transmutes.rs:46:46: 46:75
-                                           // + user_ty: UserType(23)
+                                           // + span: $DIR/combine_transmutes.rs:40:46: 40:75
+                                           // + user_ty: UserType(11)
                                            // + literal: Const { ty: fn() -> MaybeUninit<String> {MaybeUninit::<String>::uninit}, val: Value(<ZST>) }
       }
   
       bb1: {
--         _23 = move _24 as std::mem::ManuallyDrop<std::string::String> (Transmute); // scope 11 at $DIR/combine_transmutes.rs:+12:36: +12:78
-+         _23 = move (_24.1: std::mem::ManuallyDrop<std::string::String>); // scope 11 at $DIR/combine_transmutes.rs:+12:36: +12:78
-          StorageDead(_24);                // scope 11 at $DIR/combine_transmutes.rs:+12:77: +12:78
-          _0 = const ();                   // scope 0 at $DIR/combine_transmutes.rs:+0:32: +13:2
-          StorageDead(_23);                // scope 11 at $DIR/combine_transmutes.rs:+13:1: +13:2
-          StorageDead(_21);                // scope 10 at $DIR/combine_transmutes.rs:+13:1: +13:2
-          StorageDead(_19);                // scope 9 at $DIR/combine_transmutes.rs:+13:1: +13:2
-          StorageDead(_17);                // scope 8 at $DIR/combine_transmutes.rs:+13:1: +13:2
-          StorageDead(_15);                // scope 7 at $DIR/combine_transmutes.rs:+13:1: +13:2
-          StorageDead(_13);                // scope 6 at $DIR/combine_transmutes.rs:+13:1: +13:2
-          StorageDead(_11);                // scope 5 at $DIR/combine_transmutes.rs:+13:1: +13:2
-          StorageDead(_9);                 // scope 4 at $DIR/combine_transmutes.rs:+13:1: +13:2
-          StorageDead(_7);                 // scope 3 at $DIR/combine_transmutes.rs:+13:1: +13:2
-          StorageDead(_5);                 // scope 2 at $DIR/combine_transmutes.rs:+13:1: +13:2
-          StorageDead(_3);                 // scope 1 at $DIR/combine_transmutes.rs:+13:1: +13:2
-          StorageDead(_1);                 // scope 0 at $DIR/combine_transmutes.rs:+13:1: +13:2
-          return;                          // scope 0 at $DIR/combine_transmutes.rs:+13:2: +13:2
+-         _11 = move _12 as std::mem::ManuallyDrop<std::string::String> (Transmute); // scope 5 at $DIR/combine_transmutes.rs:+6:36: +6:78
++         _11 = move (_12.1: std::mem::ManuallyDrop<std::string::String>); // scope 5 at $DIR/combine_transmutes.rs:+6:36: +6:78
+          StorageDead(_12);                // scope 5 at $DIR/combine_transmutes.rs:+6:77: +6:78
+          _0 = const ();                   // scope 0 at $DIR/combine_transmutes.rs:+0:32: +7:2
+          StorageDead(_11);                // scope 5 at $DIR/combine_transmutes.rs:+7:1: +7:2
+          StorageDead(_9);                 // scope 4 at $DIR/combine_transmutes.rs:+7:1: +7:2
+          StorageDead(_7);                 // scope 3 at $DIR/combine_transmutes.rs:+7:1: +7:2
+          StorageDead(_5);                 // scope 2 at $DIR/combine_transmutes.rs:+7:1: +7:2
+          StorageDead(_3);                 // scope 1 at $DIR/combine_transmutes.rs:+7:1: +7:2
+          StorageDead(_1);                 // scope 0 at $DIR/combine_transmutes.rs:+7:1: +7:2
+          return;                          // scope 0 at $DIR/combine_transmutes.rs:+7:2: +7:2
       }
   }
   
diff --git a/tests/mir-opt/combine_transmutes.rs b/tests/mir-opt/combine_transmutes.rs
index 7088488c1b8..403f9356ce2 100644
--- a/tests/mir-opt/combine_transmutes.rs
+++ b/tests/mir-opt/combine_transmutes.rs
@@ -32,12 +32,6 @@ pub unsafe fn integer_transmutes() {
 
 // EMIT_MIR combine_transmutes.adt_transmutes.InstSimplify.diff
 pub unsafe fn adt_transmutes() {
-    let _a: u8 = transmute(EnumNoRepr::A);
-    let _a: i8 = transmute(EnumNoRepr::B);
-    let _a: usize = transmute(EnumReprIsize::A);
-    let _a: isize = transmute(EnumReprIsize::B);
-    let _a: u8 = transmute(std::cmp::Ordering::Less);
-    let _a: i8 = transmute(std::cmp::Ordering::Less);
     let _a: u8 = transmute(Some(std::num::NonZeroU8::MAX));
     let _a: i16 = transmute(std::num::Wrapping(0_i16));
     let _a: u16 = transmute(std::num::Wrapping(0_i16));
@@ -46,20 +40,4 @@ pub unsafe fn adt_transmutes() {
     let _a: ManuallyDrop<String> = transmute(MaybeUninit::<String>::uninit());
 }
 
-#[inline(always)]
-#[custom_mir(dialect = "runtime", phase = "initial")]
-const unsafe fn mir_transmute<T, U>(x: T) -> U {
-    mir!{
-        {
-            RET = CastTransmute(x);
-            Return()
-        }
-    }
-}
-
-pub enum EnumNoRepr { A, B, C }
-
-#[repr(isize)]
-pub enum EnumReprIsize { A, B, C }
-
 pub union Union32 { u32: u32, i32: i32 }
diff --git a/tests/mir-opt/const_prop/transmute.unreachable_box.ConstProp.32bit.diff b/tests/mir-opt/const_prop/transmute.unreachable_box.ConstProp.32bit.diff
index bc41b5d0813..5258d75bdf7 100644
--- a/tests/mir-opt/const_prop/transmute.unreachable_box.ConstProp.32bit.diff
+++ b/tests/mir-opt/const_prop/transmute.unreachable_box.ConstProp.32bit.diff
@@ -3,24 +3,20 @@
   
   fn unreachable_box() -> ! {
       let mut _0: !;                       // return place in scope 0 at $DIR/transmute.rs:+0:36: +0:37
-      let mut _1: !;                       // in scope 0 at $DIR/transmute.rs:+0:38: +3:2
-      let _2: std::boxed::Box<Never>;      // in scope 0 at $DIR/transmute.rs:+1:9: +1:10
-      let mut _3: !;                       // in scope 0 at $DIR/transmute.rs:+2:5: +2:16
+      let _1: std::boxed::Box<Never>;      // in scope 0 at $DIR/transmute.rs:+1:9: +1:10
       scope 1 {
-          debug x => _2;                   // in scope 1 at $DIR/transmute.rs:+1:9: +1:10
+          debug x => _1;                   // in scope 1 at $DIR/transmute.rs:+1:9: +1:10
       }
       scope 2 {
       }
   
       bb0: {
-          StorageLive(_1);                 // scope 0 at $DIR/transmute.rs:+0:38: +3:2
-          StorageLive(_2);                 // scope 0 at $DIR/transmute.rs:+1:9: +1:10
--         _2 = const 1_usize as std::boxed::Box<Never> (Transmute); // scope 2 at $DIR/transmute.rs:+1:34: +1:52
-+         _2 = const Box::<Never>(Unique::<Never> {{ pointer: NonNull::<Never> {{ pointer: {0x1 as *const Never} }}, _marker: PhantomData::<Never> }}, std::alloc::Global); // scope 2 at $DIR/transmute.rs:+1:34: +1:52
+          StorageLive(_1);                 // scope 0 at $DIR/transmute.rs:+1:9: +1:10
+-         _1 = const 1_usize as std::boxed::Box<Never> (Transmute); // scope 2 at $DIR/transmute.rs:+1:34: +1:52
++         _1 = const Box::<Never>(Unique::<Never> {{ pointer: NonNull::<Never> {{ pointer: {0x1 as *const Never} }}, _marker: PhantomData::<Never> }}, std::alloc::Global); // scope 2 at $DIR/transmute.rs:+1:34: +1:52
 +                                          // mir::Constant
 +                                          // + span: no-location
 +                                          // + literal: Const { ty: Box<Never>, val: Value(Scalar(0x00000001)) }
-          StorageLive(_3);                 // scope 1 at $DIR/transmute.rs:+2:5: +2:16
           unreachable;                     // scope 1 at $DIR/transmute.rs:+2:11: +2:13
       }
   }
diff --git a/tests/mir-opt/const_prop/transmute.unreachable_box.ConstProp.64bit.diff b/tests/mir-opt/const_prop/transmute.unreachable_box.ConstProp.64bit.diff
index c4376e6e17a..7e57e06a5cf 100644
--- a/tests/mir-opt/const_prop/transmute.unreachable_box.ConstProp.64bit.diff
+++ b/tests/mir-opt/const_prop/transmute.unreachable_box.ConstProp.64bit.diff
@@ -3,24 +3,20 @@
   
   fn unreachable_box() -> ! {
       let mut _0: !;                       // return place in scope 0 at $DIR/transmute.rs:+0:36: +0:37
-      let mut _1: !;                       // in scope 0 at $DIR/transmute.rs:+0:38: +3:2
-      let _2: std::boxed::Box<Never>;      // in scope 0 at $DIR/transmute.rs:+1:9: +1:10
-      let mut _3: !;                       // in scope 0 at $DIR/transmute.rs:+2:5: +2:16
+      let _1: std::boxed::Box<Never>;      // in scope 0 at $DIR/transmute.rs:+1:9: +1:10
       scope 1 {
-          debug x => _2;                   // in scope 1 at $DIR/transmute.rs:+1:9: +1:10
+          debug x => _1;                   // in scope 1 at $DIR/transmute.rs:+1:9: +1:10
       }
       scope 2 {
       }
   
       bb0: {
-          StorageLive(_1);                 // scope 0 at $DIR/transmute.rs:+0:38: +3:2
-          StorageLive(_2);                 // scope 0 at $DIR/transmute.rs:+1:9: +1:10
--         _2 = const 1_usize as std::boxed::Box<Never> (Transmute); // scope 2 at $DIR/transmute.rs:+1:34: +1:52
-+         _2 = const Box::<Never>(Unique::<Never> {{ pointer: NonNull::<Never> {{ pointer: {0x1 as *const Never} }}, _marker: PhantomData::<Never> }}, std::alloc::Global); // scope 2 at $DIR/transmute.rs:+1:34: +1:52
+          StorageLive(_1);                 // scope 0 at $DIR/transmute.rs:+1:9: +1:10
+-         _1 = const 1_usize as std::boxed::Box<Never> (Transmute); // scope 2 at $DIR/transmute.rs:+1:34: +1:52
++         _1 = const Box::<Never>(Unique::<Never> {{ pointer: NonNull::<Never> {{ pointer: {0x1 as *const Never} }}, _marker: PhantomData::<Never> }}, std::alloc::Global); // scope 2 at $DIR/transmute.rs:+1:34: +1:52
 +                                          // mir::Constant
 +                                          // + span: no-location
 +                                          // + literal: Const { ty: Box<Never>, val: Value(Scalar(0x0000000000000001)) }
-          StorageLive(_3);                 // scope 1 at $DIR/transmute.rs:+2:5: +2:16
           unreachable;                     // scope 1 at $DIR/transmute.rs:+2:11: +2:13
       }
   }
diff --git a/tests/mir-opt/const_prop/transmute.unreachable_direct.ConstProp.32bit.diff b/tests/mir-opt/const_prop/transmute.unreachable_direct.ConstProp.32bit.diff
index 81b7b368993..032681f230b 100644
--- a/tests/mir-opt/const_prop/transmute.unreachable_direct.ConstProp.32bit.diff
+++ b/tests/mir-opt/const_prop/transmute.unreachable_direct.ConstProp.32bit.diff
@@ -3,22 +3,19 @@
   
   fn unreachable_direct() -> ! {
       let mut _0: !;                       // return place in scope 0 at $DIR/transmute.rs:+0:39: +0:40
-      let mut _1: !;                       // in scope 0 at $DIR/transmute.rs:+0:41: +3:2
-      let _2: Never;                       // in scope 0 at $DIR/transmute.rs:+1:9: +1:10
-      let mut _3: ();                      // in scope 0 at $DIR/transmute.rs:+1:39: +1:41
-      let mut _4: !;                       // in scope 0 at $DIR/transmute.rs:+2:5: +2:15
+      let _1: Never;                       // in scope 0 at $DIR/transmute.rs:+1:9: +1:10
+      let mut _2: ();                      // in scope 0 at $DIR/transmute.rs:+1:39: +1:41
       scope 1 {
-          debug x => _2;                   // in scope 1 at $DIR/transmute.rs:+1:9: +1:10
+          debug x => _1;                   // in scope 1 at $DIR/transmute.rs:+1:9: +1:10
       }
       scope 2 {
       }
   
       bb0: {
-          StorageLive(_1);                 // scope 0 at $DIR/transmute.rs:+0:41: +3:2
-          StorageLive(_2);                 // scope 0 at $DIR/transmute.rs:+1:9: +1:10
-          StorageLive(_3);                 // scope 2 at $DIR/transmute.rs:+1:39: +1:41
-          _3 = ();                         // scope 2 at $DIR/transmute.rs:+1:39: +1:41
-          _2 = move _3 as Never (Transmute); // scope 2 at $DIR/transmute.rs:+1:29: +1:42
+          StorageLive(_1);                 // scope 0 at $DIR/transmute.rs:+1:9: +1:10
+          StorageLive(_2);                 // scope 2 at $DIR/transmute.rs:+1:39: +1:41
+          _2 = ();                         // scope 2 at $DIR/transmute.rs:+1:39: +1:41
+          _1 = move _2 as Never (Transmute); // scope 2 at $DIR/transmute.rs:+1:29: +1:42
           unreachable;                     // scope 2 at $DIR/transmute.rs:+1:29: +1:42
       }
   }
diff --git a/tests/mir-opt/const_prop/transmute.unreachable_direct.ConstProp.64bit.diff b/tests/mir-opt/const_prop/transmute.unreachable_direct.ConstProp.64bit.diff
index 81b7b368993..032681f230b 100644
--- a/tests/mir-opt/const_prop/transmute.unreachable_direct.ConstProp.64bit.diff
+++ b/tests/mir-opt/const_prop/transmute.unreachable_direct.ConstProp.64bit.diff
@@ -3,22 +3,19 @@
   
   fn unreachable_direct() -> ! {
       let mut _0: !;                       // return place in scope 0 at $DIR/transmute.rs:+0:39: +0:40
-      let mut _1: !;                       // in scope 0 at $DIR/transmute.rs:+0:41: +3:2
-      let _2: Never;                       // in scope 0 at $DIR/transmute.rs:+1:9: +1:10
-      let mut _3: ();                      // in scope 0 at $DIR/transmute.rs:+1:39: +1:41
-      let mut _4: !;                       // in scope 0 at $DIR/transmute.rs:+2:5: +2:15
+      let _1: Never;                       // in scope 0 at $DIR/transmute.rs:+1:9: +1:10
+      let mut _2: ();                      // in scope 0 at $DIR/transmute.rs:+1:39: +1:41
       scope 1 {
-          debug x => _2;                   // in scope 1 at $DIR/transmute.rs:+1:9: +1:10
+          debug x => _1;                   // in scope 1 at $DIR/transmute.rs:+1:9: +1:10
       }
       scope 2 {
       }
   
       bb0: {
-          StorageLive(_1);                 // scope 0 at $DIR/transmute.rs:+0:41: +3:2
-          StorageLive(_2);                 // scope 0 at $DIR/transmute.rs:+1:9: +1:10
-          StorageLive(_3);                 // scope 2 at $DIR/transmute.rs:+1:39: +1:41
-          _3 = ();                         // scope 2 at $DIR/transmute.rs:+1:39: +1:41
-          _2 = move _3 as Never (Transmute); // scope 2 at $DIR/transmute.rs:+1:29: +1:42
+          StorageLive(_1);                 // scope 0 at $DIR/transmute.rs:+1:9: +1:10
+          StorageLive(_2);                 // scope 2 at $DIR/transmute.rs:+1:39: +1:41
+          _2 = ();                         // scope 2 at $DIR/transmute.rs:+1:39: +1:41
+          _1 = move _2 as Never (Transmute); // scope 2 at $DIR/transmute.rs:+1:29: +1:42
           unreachable;                     // scope 2 at $DIR/transmute.rs:+1:29: +1:42
       }
   }
diff --git a/tests/mir-opt/const_prop/transmute.unreachable_mut.ConstProp.32bit.diff b/tests/mir-opt/const_prop/transmute.unreachable_mut.ConstProp.32bit.diff
index 47f023cd93d..ec8a62bd62c 100644
--- a/tests/mir-opt/const_prop/transmute.unreachable_mut.ConstProp.32bit.diff
+++ b/tests/mir-opt/const_prop/transmute.unreachable_mut.ConstProp.32bit.diff
@@ -3,28 +3,24 @@
   
   fn unreachable_mut() -> ! {
       let mut _0: !;                       // return place in scope 0 at $DIR/transmute.rs:+0:36: +0:37
-      let mut _1: !;                       // in scope 0 at $DIR/transmute.rs:+0:38: +3:2
-      let _2: &mut Never;                  // in scope 0 at $DIR/transmute.rs:+1:9: +1:10
-      let mut _3: &mut Never;              // in scope 0 at $DIR/transmute.rs:+1:34: +1:52
-      let mut _4: !;                       // in scope 0 at $DIR/transmute.rs:+2:5: +2:16
+      let _1: &mut Never;                  // in scope 0 at $DIR/transmute.rs:+1:9: +1:10
+      let mut _2: &mut Never;              // in scope 0 at $DIR/transmute.rs:+1:34: +1:52
       scope 1 {
-          debug x => _2;                   // in scope 1 at $DIR/transmute.rs:+1:9: +1:10
+          debug x => _1;                   // in scope 1 at $DIR/transmute.rs:+1:9: +1:10
       }
       scope 2 {
       }
   
       bb0: {
-          StorageLive(_1);                 // scope 0 at $DIR/transmute.rs:+0:38: +3:2
-          StorageLive(_2);                 // scope 0 at $DIR/transmute.rs:+1:9: +1:10
-          StorageLive(_3);                 // scope 0 at $DIR/transmute.rs:+1:34: +1:52
--         _3 = const 1_usize as &mut Never (Transmute); // scope 2 at $DIR/transmute.rs:+1:34: +1:52
-+         _3 = const {0x1 as &mut Never};  // scope 2 at $DIR/transmute.rs:+1:34: +1:52
+          StorageLive(_1);                 // scope 0 at $DIR/transmute.rs:+1:9: +1:10
+          StorageLive(_2);                 // scope 0 at $DIR/transmute.rs:+1:34: +1:52
+-         _2 = const 1_usize as &mut Never (Transmute); // scope 2 at $DIR/transmute.rs:+1:34: +1:52
++         _2 = const {0x1 as &mut Never};  // scope 2 at $DIR/transmute.rs:+1:34: +1:52
 +                                          // mir::Constant
 +                                          // + span: no-location
 +                                          // + literal: Const { ty: &mut Never, val: Value(Scalar(0x00000001)) }
-          _2 = &mut (*_3);                 // scope 0 at $DIR/transmute.rs:+1:34: +1:52
-          StorageDead(_3);                 // scope 0 at $DIR/transmute.rs:+1:54: +1:55
-          StorageLive(_4);                 // scope 1 at $DIR/transmute.rs:+2:5: +2:16
+          _1 = &mut (*_2);                 // scope 0 at $DIR/transmute.rs:+1:34: +1:52
+          StorageDead(_2);                 // scope 0 at $DIR/transmute.rs:+1:54: +1:55
           unreachable;                     // scope 1 at $DIR/transmute.rs:+2:11: +2:13
       }
   }
diff --git a/tests/mir-opt/const_prop/transmute.unreachable_mut.ConstProp.64bit.diff b/tests/mir-opt/const_prop/transmute.unreachable_mut.ConstProp.64bit.diff
index 62300d2e313..288da6e56c5 100644
--- a/tests/mir-opt/const_prop/transmute.unreachable_mut.ConstProp.64bit.diff
+++ b/tests/mir-opt/const_prop/transmute.unreachable_mut.ConstProp.64bit.diff
@@ -3,28 +3,24 @@
   
   fn unreachable_mut() -> ! {
       let mut _0: !;                       // return place in scope 0 at $DIR/transmute.rs:+0:36: +0:37
-      let mut _1: !;                       // in scope 0 at $DIR/transmute.rs:+0:38: +3:2
-      let _2: &mut Never;                  // in scope 0 at $DIR/transmute.rs:+1:9: +1:10
-      let mut _3: &mut Never;              // in scope 0 at $DIR/transmute.rs:+1:34: +1:52
-      let mut _4: !;                       // in scope 0 at $DIR/transmute.rs:+2:5: +2:16
+      let _1: &mut Never;                  // in scope 0 at $DIR/transmute.rs:+1:9: +1:10
+      let mut _2: &mut Never;              // in scope 0 at $DIR/transmute.rs:+1:34: +1:52
       scope 1 {
-          debug x => _2;                   // in scope 1 at $DIR/transmute.rs:+1:9: +1:10
+          debug x => _1;                   // in scope 1 at $DIR/transmute.rs:+1:9: +1:10
       }
       scope 2 {
       }
   
       bb0: {
-          StorageLive(_1);                 // scope 0 at $DIR/transmute.rs:+0:38: +3:2
-          StorageLive(_2);                 // scope 0 at $DIR/transmute.rs:+1:9: +1:10
-          StorageLive(_3);                 // scope 0 at $DIR/transmute.rs:+1:34: +1:52
--         _3 = const 1_usize as &mut Never (Transmute); // scope 2 at $DIR/transmute.rs:+1:34: +1:52
-+         _3 = const {0x1 as &mut Never};  // scope 2 at $DIR/transmute.rs:+1:34: +1:52
+          StorageLive(_1);                 // scope 0 at $DIR/transmute.rs:+1:9: +1:10
+          StorageLive(_2);                 // scope 0 at $DIR/transmute.rs:+1:34: +1:52
+-         _2 = const 1_usize as &mut Never (Transmute); // scope 2 at $DIR/transmute.rs:+1:34: +1:52
++         _2 = const {0x1 as &mut Never};  // scope 2 at $DIR/transmute.rs:+1:34: +1:52
 +                                          // mir::Constant
 +                                          // + span: no-location
 +                                          // + literal: Const { ty: &mut Never, val: Value(Scalar(0x0000000000000001)) }
-          _2 = &mut (*_3);                 // scope 0 at $DIR/transmute.rs:+1:34: +1:52
-          StorageDead(_3);                 // scope 0 at $DIR/transmute.rs:+1:54: +1:55
-          StorageLive(_4);                 // scope 1 at $DIR/transmute.rs:+2:5: +2:16
+          _1 = &mut (*_2);                 // scope 0 at $DIR/transmute.rs:+1:34: +1:52
+          StorageDead(_2);                 // scope 0 at $DIR/transmute.rs:+1:54: +1:55
           unreachable;                     // scope 1 at $DIR/transmute.rs:+2:11: +2:13
       }
   }
diff --git a/tests/mir-opt/const_prop/transmute.unreachable_ref.ConstProp.32bit.diff b/tests/mir-opt/const_prop/transmute.unreachable_ref.ConstProp.32bit.diff
index 8578f898a7e..dcca0fca619 100644
--- a/tests/mir-opt/const_prop/transmute.unreachable_ref.ConstProp.32bit.diff
+++ b/tests/mir-opt/const_prop/transmute.unreachable_ref.ConstProp.32bit.diff
@@ -3,24 +3,20 @@
   
   fn unreachable_ref() -> ! {
       let mut _0: !;                       // return place in scope 0 at $DIR/transmute.rs:+0:36: +0:37
-      let mut _1: !;                       // in scope 0 at $DIR/transmute.rs:+0:38: +3:2
-      let _2: &Never;                      // in scope 0 at $DIR/transmute.rs:+1:9: +1:10
-      let mut _3: !;                       // in scope 0 at $DIR/transmute.rs:+2:5: +2:16
+      let _1: &Never;                      // in scope 0 at $DIR/transmute.rs:+1:9: +1:10
       scope 1 {
-          debug x => _2;                   // in scope 1 at $DIR/transmute.rs:+1:9: +1:10
+          debug x => _1;                   // in scope 1 at $DIR/transmute.rs:+1:9: +1:10
       }
       scope 2 {
       }
   
       bb0: {
-          StorageLive(_1);                 // scope 0 at $DIR/transmute.rs:+0:38: +3:2
-          StorageLive(_2);                 // scope 0 at $DIR/transmute.rs:+1:9: +1:10
--         _2 = const 1_usize as &Never (Transmute); // scope 2 at $DIR/transmute.rs:+1:30: +1:48
-+         _2 = const {0x1 as &Never};      // scope 2 at $DIR/transmute.rs:+1:30: +1:48
+          StorageLive(_1);                 // scope 0 at $DIR/transmute.rs:+1:9: +1:10
+-         _1 = const 1_usize as &Never (Transmute); // scope 2 at $DIR/transmute.rs:+1:30: +1:48
++         _1 = const {0x1 as &Never};      // scope 2 at $DIR/transmute.rs:+1:30: +1:48
 +                                          // mir::Constant
 +                                          // + span: no-location
 +                                          // + literal: Const { ty: &Never, val: Value(Scalar(0x00000001)) }
-          StorageLive(_3);                 // scope 1 at $DIR/transmute.rs:+2:5: +2:16
           unreachable;                     // scope 1 at $DIR/transmute.rs:+2:11: +2:13
       }
   }
diff --git a/tests/mir-opt/const_prop/transmute.unreachable_ref.ConstProp.64bit.diff b/tests/mir-opt/const_prop/transmute.unreachable_ref.ConstProp.64bit.diff
index 8b11cea9365..3a0b967e66f 100644
--- a/tests/mir-opt/const_prop/transmute.unreachable_ref.ConstProp.64bit.diff
+++ b/tests/mir-opt/const_prop/transmute.unreachable_ref.ConstProp.64bit.diff
@@ -3,24 +3,20 @@
   
   fn unreachable_ref() -> ! {
       let mut _0: !;                       // return place in scope 0 at $DIR/transmute.rs:+0:36: +0:37
-      let mut _1: !;                       // in scope 0 at $DIR/transmute.rs:+0:38: +3:2
-      let _2: &Never;                      // in scope 0 at $DIR/transmute.rs:+1:9: +1:10
-      let mut _3: !;                       // in scope 0 at $DIR/transmute.rs:+2:5: +2:16
+      let _1: &Never;                      // in scope 0 at $DIR/transmute.rs:+1:9: +1:10
       scope 1 {
-          debug x => _2;                   // in scope 1 at $DIR/transmute.rs:+1:9: +1:10
+          debug x => _1;                   // in scope 1 at $DIR/transmute.rs:+1:9: +1:10
       }
       scope 2 {
       }
   
       bb0: {
-          StorageLive(_1);                 // scope 0 at $DIR/transmute.rs:+0:38: +3:2
-          StorageLive(_2);                 // scope 0 at $DIR/transmute.rs:+1:9: +1:10
--         _2 = const 1_usize as &Never (Transmute); // scope 2 at $DIR/transmute.rs:+1:30: +1:48
-+         _2 = const {0x1 as &Never};      // scope 2 at $DIR/transmute.rs:+1:30: +1:48
+          StorageLive(_1);                 // scope 0 at $DIR/transmute.rs:+1:9: +1:10
+-         _1 = const 1_usize as &Never (Transmute); // scope 2 at $DIR/transmute.rs:+1:30: +1:48
++         _1 = const {0x1 as &Never};      // scope 2 at $DIR/transmute.rs:+1:30: +1:48
 +                                          // mir::Constant
 +                                          // + span: no-location
 +                                          // + literal: Const { ty: &Never, val: Value(Scalar(0x0000000000000001)) }
-          StorageLive(_3);                 // scope 1 at $DIR/transmute.rs:+2:5: +2:16
           unreachable;                     // scope 1 at $DIR/transmute.rs:+2:11: +2:13
       }
   }
diff --git a/tests/mir-opt/copy-prop/copy_propagation_arg.arg_src.CopyProp.diff b/tests/mir-opt/copy-prop/copy_propagation_arg.arg_src.CopyProp.diff
index 69acebf7642..1c7b6494d6d 100644
--- a/tests/mir-opt/copy-prop/copy_propagation_arg.arg_src.CopyProp.diff
+++ b/tests/mir-opt/copy-prop/copy_propagation_arg.arg_src.CopyProp.diff
@@ -6,15 +6,17 @@
       let mut _0: i32;                     // return place in scope 0 at $DIR/copy_propagation_arg.rs:+0:27: +0:30
       let _2: i32;                         // in scope 0 at $DIR/copy_propagation_arg.rs:+1:9: +1:10
       scope 1 {
-          debug y => _2;                   // in scope 1 at $DIR/copy_propagation_arg.rs:+1:9: +1:10
+-         debug y => _2;                   // in scope 1 at $DIR/copy_propagation_arg.rs:+1:9: +1:10
++         debug y => _0;                   // in scope 1 at $DIR/copy_propagation_arg.rs:+1:9: +1:10
       }
   
       bb0: {
-          StorageLive(_2);                 // scope 0 at $DIR/copy_propagation_arg.rs:+1:9: +1:10
-          _2 = _1;                         // scope 0 at $DIR/copy_propagation_arg.rs:+1:13: +1:14
+-         StorageLive(_2);                 // scope 0 at $DIR/copy_propagation_arg.rs:+1:9: +1:10
+-         _2 = _1;                         // scope 0 at $DIR/copy_propagation_arg.rs:+1:13: +1:14
++         _0 = _1;                         // scope 0 at $DIR/copy_propagation_arg.rs:+1:13: +1:14
           _1 = const 123_i32;              // scope 1 at $DIR/copy_propagation_arg.rs:+2:5: +2:12
-          _0 = _2;                         // scope 1 at $DIR/copy_propagation_arg.rs:+3:5: +3:6
-          StorageDead(_2);                 // scope 0 at $DIR/copy_propagation_arg.rs:+4:1: +4:2
+-         _0 = _2;                         // scope 1 at $DIR/copy_propagation_arg.rs:+3:5: +3:6
+-         StorageDead(_2);                 // scope 0 at $DIR/copy_propagation_arg.rs:+4:1: +4:2
           return;                          // scope 0 at $DIR/copy_propagation_arg.rs:+4:2: +4:2
       }
   }
diff --git a/tests/mir-opt/inline/inline_into_box_place.main.Inline.diff b/tests/mir-opt/inline/inline_into_box_place.main.Inline.diff
index 94f24b50ab7..a5129e0e8c8 100644
--- a/tests/mir-opt/inline/inline_into_box_place.main.Inline.diff
+++ b/tests/mir-opt/inline/inline_into_box_place.main.Inline.diff
@@ -16,8 +16,7 @@
 +         let mut _4: usize;               // in scope 3 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
 +         let mut _5: usize;               // in scope 3 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
 +         let mut _6: *mut u8;             // in scope 3 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
-+         let mut _7: std::boxed::Box<std::vec::Vec<u32>>; // in scope 3 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
-+         let mut _8: *const std::vec::Vec<u32>; // in scope 3 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
++         let mut _7: *const std::vec::Vec<u32>; // in scope 3 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
 +         scope 4 {
 +         }
 +     }
@@ -66,12 +65,9 @@
       bb3: {
 -         StorageDead(_1);                 // scope 0 at $DIR/inline_into_box_place.rs:+2:1: +2:2
 -         return;                          // scope 0 at $DIR/inline_into_box_place.rs:+2:2: +2:2
-+         StorageLive(_7);                 // scope 3 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
-+         _7 = ShallowInitBox(move _6, std::vec::Vec<u32>); // scope 3 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
-+         _8 = (((_7.0: std::ptr::Unique<std::vec::Vec<u32>>).0: std::ptr::NonNull<std::vec::Vec<u32>>).0: *const std::vec::Vec<u32>); // scope 3 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
-+         (*_8) = move _2;                 // scope 3 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
-+         _1 = move _7;                    // scope 3 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
-+         StorageDead(_7);                 // scope 3 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
++         _1 = ShallowInitBox(move _6, std::vec::Vec<u32>); // scope 3 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
++         _7 = (((_1.0: std::ptr::Unique<std::vec::Vec<u32>>).0: std::ptr::NonNull<std::vec::Vec<u32>>).0: *const std::vec::Vec<u32>); // scope 3 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
++         (*_7) = move _2;                 // scope 3 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
 +         StorageDead(_2);                 // scope 0 at $DIR/inline_into_box_place.rs:+1:48: +1:49
 +         _0 = const ();                   // scope 0 at $DIR/inline_into_box_place.rs:+0:11: +2:2
 +         drop(_1) -> [return: bb1, unwind: bb2]; // scope 0 at $DIR/inline_into_box_place.rs:+2:1: +2:2
diff --git a/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.b.Inline.after.mir b/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.b.Inline.after.mir
index 8c4ab2557a5..21570a88a6b 100644
--- a/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.b.Inline.after.mir
+++ b/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.b.Inline.after.mir
@@ -8,9 +8,8 @@ fn b(_1: &mut Box<T>) -> &mut T {
     let mut _4: &mut std::boxed::Box<T>; // in scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:5: +1:15
     scope 1 (inlined <Box<T> as AsMut<T>>::as_mut) { // at $DIR/issue_58867_inline_as_ref_as_mut.rs:8:7: 8:15
         debug self => _4;                // in scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
-        let mut _5: &mut T;              // in scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
-        let mut _6: std::boxed::Box<T>;  // in scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
-        let mut _7: *const T;            // in scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
+        let mut _5: std::boxed::Box<T>;  // in scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
+        let mut _6: *const T;            // in scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
     }
 
     bb0: {
@@ -18,12 +17,9 @@ fn b(_1: &mut Box<T>) -> &mut T {
         StorageLive(_3);                 // scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:5: +1:15
         StorageLive(_4);                 // scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:5: +1:15
         _4 = &mut (*_1);                 // scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:5: +1:15
-        StorageLive(_5);                 // scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:7: +1:15
-        _6 = deref_copy (*_4);           // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
-        _7 = (((_6.0: std::ptr::Unique<T>).0: std::ptr::NonNull<T>).0: *const T); // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
-        _5 = &mut (*_7);                 // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
-        _3 = _5;                         // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
-        StorageDead(_5);                 // scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:7: +1:15
+        _5 = deref_copy (*_4);           // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
+        _6 = (((_5.0: std::ptr::Unique<T>).0: std::ptr::NonNull<T>).0: *const T); // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
+        _3 = &mut (*_6);                 // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
         _2 = &mut (*_3);                 // scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:5: +1:15
         StorageDead(_4);                 // scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:14: +1:15
         _0 = &mut (*_2);                 // scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:5: +1:15
diff --git a/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.d.Inline.after.mir b/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.d.Inline.after.mir
index b18a41b622e..4f9342247d7 100644
--- a/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.d.Inline.after.mir
+++ b/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.d.Inline.after.mir
@@ -7,21 +7,17 @@ fn d(_1: &Box<T>) -> &T {
     let mut _3: &std::boxed::Box<T>;     // in scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:5: +1:15
     scope 1 (inlined <Box<T> as AsRef<T>>::as_ref) { // at $DIR/issue_58867_inline_as_ref_as_mut.rs:18:7: 18:15
         debug self => _3;                // in scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
-        let _4: &T;                      // in scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
-        let mut _5: std::boxed::Box<T>;  // in scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
-        let mut _6: *const T;            // in scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
+        let mut _4: std::boxed::Box<T>;  // in scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
+        let mut _5: *const T;            // in scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
     }
 
     bb0: {
         StorageLive(_2);                 // scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:5: +1:15
         StorageLive(_3);                 // scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:5: +1:15
         _3 = &(*_1);                     // scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:5: +1:15
-        StorageLive(_4);                 // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
-        _5 = deref_copy (*_3);           // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
-        _6 = (((_5.0: std::ptr::Unique<T>).0: std::ptr::NonNull<T>).0: *const T); // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
-        _4 = &(*_6);                     // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
-        _2 = _4;                         // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
-        StorageDead(_4);                 // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
+        _4 = deref_copy (*_3);           // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
+        _5 = (((_4.0: std::ptr::Unique<T>).0: std::ptr::NonNull<T>).0: *const T); // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
+        _2 = &(*_5);                     // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
         _0 = &(*_2);                     // scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:5: +1:15
         StorageDead(_3);                 // scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:14: +1:15
         StorageDead(_2);                 // scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+2:1: +2:2
diff --git a/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.Inline.diff b/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.Inline.diff
index 473e02f1cb1..d76cd0e2bb8 100644
--- a/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.Inline.diff
+++ b/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.Inline.diff
@@ -12,7 +12,51 @@
 +         debug rhs => _4;                 // in scope 1 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
 +         let mut _5: u16;                 // in scope 1 at $SRC_DIR/core/src/num/mod.rs:LL:COL
 +         let mut _6: (u32,);              // in scope 1 at $SRC_DIR/core/src/num/mod.rs:LL:COL
++         let mut _7: u32;                 // in scope 1 at $SRC_DIR/core/src/num/mod.rs:LL:COL
 +         scope 2 {
++             scope 3 (inlined core::num::<impl u16>::unchecked_shl::conv) { // at $SRC_DIR/core/src/num/mod.rs:LL:COL
++                 debug x => _7;           // in scope 3 at $SRC_DIR/core/src/num/mod.rs:LL:COL
++                 let mut _8: std::option::Option<u16>; // in scope 3 at $SRC_DIR/core/src/num/mod.rs:LL:COL
++                 let mut _9: std::result::Result<u16, std::num::TryFromIntError>; // in scope 3 at $SRC_DIR/core/src/num/mod.rs:LL:COL
++                 scope 4 {
++                     scope 5 (inlined <u32 as TryInto<u16>>::try_into) { // at $SRC_DIR/core/src/num/mod.rs:LL:COL
++                         debug self => _7; // in scope 5 at $SRC_DIR/core/src/convert/mod.rs:LL:COL
++                         scope 6 (inlined convert::num::<impl TryFrom<u32> for u16>::try_from) { // at $SRC_DIR/core/src/convert/mod.rs:LL:COL
++                             debug u => _7; // in scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++                             let mut _10: bool; // in scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++                             let mut _11: u32; // in scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++                             let mut _12: u16; // in scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++                         }
++                     }
++                     scope 7 (inlined Result::<u16, TryFromIntError>::ok) { // at $SRC_DIR/core/src/num/mod.rs:LL:COL
++                         debug self => _9; // in scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
++                         let mut _13: isize; // in scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
++                         let _14: u16;    // in scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
++                         scope 8 {
++                             debug x => _14; // in scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
++                         }
++                     }
++                     scope 9 (inlined #[track_caller] Option::<u16>::unwrap_unchecked) { // at $SRC_DIR/core/src/num/mod.rs:LL:COL
++                         debug self => _8; // in scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
++                         let mut _15: &std::option::Option<u16>; // in scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
++                         let mut _16: isize; // in scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
++                         scope 10 {
++                             debug val => _5; // in scope 10 at $SRC_DIR/core/src/option.rs:LL:COL
++                         }
++                         scope 11 {
++                             scope 13 (inlined unreachable_unchecked) { // at $SRC_DIR/core/src/option.rs:LL:COL
++                                 scope 14 {
++                                     scope 15 (inlined unreachable_unchecked::runtime) { // at $SRC_DIR/core/src/intrinsics.rs:LL:COL
++                                     }
++                                 }
++                             }
++                         }
++                         scope 12 (inlined Option::<u16>::is_some) { // at $SRC_DIR/core/src/option.rs:LL:COL
++                             debug self => _15; // in scope 12 at $SRC_DIR/core/src/option.rs:LL:COL
++                         }
++                     }
++                 }
++             }
 +         }
 +     }
   
@@ -22,30 +66,87 @@
           StorageLive(_4);                 // scope 0 at $DIR/unchecked_shifts.rs:+1:21: +1:22
           _4 = _2;                         // scope 0 at $DIR/unchecked_shifts.rs:+1:21: +1:22
 -         _0 = core::num::<impl u16>::unchecked_shl(move _3, move _4) -> bb1; // scope 0 at $DIR/unchecked_shifts.rs:+1:5: +1:23
+-                                          // mir::Constant
+-                                          // + span: $DIR/unchecked_shifts.rs:11:7: 11:20
+-                                          // + literal: Const { ty: unsafe fn(u16, u32) -> u16 {core::num::<impl u16>::unchecked_shl}, val: Value(<ZST>) }
 +         StorageLive(_5);                 // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
 +         StorageLive(_6);                 // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
 +         _6 = (_4,);                      // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
-+         _5 = core::num::<impl u16>::unchecked_shl::conv(move (_6.0: u32)) -> bb1; // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
-                                           // mir::Constant
--                                          // + span: $DIR/unchecked_shifts.rs:11:7: 11:20
--                                          // + literal: Const { ty: unsafe fn(u16, u32) -> u16 {core::num::<impl u16>::unchecked_shl}, val: Value(<ZST>) }
-+                                          // + span: $SRC_DIR/core/src/num/mod.rs:LL:COL
-+                                          // + literal: Const { ty: fn(u32) -> u16 {core::num::<impl u16>::unchecked_shl::conv}, val: Value(<ZST>) }
++         StorageLive(_7);                 // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
++         _7 = move (_6.0: u32);           // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
++         StorageLive(_8);                 // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
++         StorageLive(_9);                 // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
++         StorageLive(_10);                // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++         StorageLive(_11);                // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++         _11 = const 65535_u32;           // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++         _10 = Gt(_7, move _11);          // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++         StorageDead(_11);                // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++         switchInt(move _10) -> [0: bb3, otherwise: bb2]; // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
       }
   
       bb1: {
-+         StorageDead(_6);                 // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
-+         _0 = unchecked_shl::<u16>(_3, move _5) -> [return: bb2, unwind unreachable]; // scope 2 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
-+                                          // mir::Constant
-+                                          // + span: $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
-+                                          // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(u16, u16) -> u16 {unchecked_shl::<u16>}, val: Value(<ZST>) }
-+     }
-+ 
-+     bb2: {
 +         StorageDead(_5);                 // scope 2 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
           StorageDead(_4);                 // scope 0 at $DIR/unchecked_shifts.rs:+1:22: +1:23
           StorageDead(_3);                 // scope 0 at $DIR/unchecked_shifts.rs:+1:22: +1:23
           return;                          // scope 0 at $DIR/unchecked_shifts.rs:+2:2: +2:2
++     }
++ 
++     bb2: {
++         _9 = Result::<u16, TryFromIntError>::Err(const TryFromIntError(())); // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++                                          // mir::Constant
++                                          // + span: no-location
++                                          // + literal: Const { ty: TryFromIntError, val: Value(<ZST>) }
++         goto -> bb4;                     // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++     }
++ 
++     bb3: {
++         StorageLive(_12);                // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++         _12 = _7 as u16 (IntToInt);      // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++         _9 = Result::<u16, TryFromIntError>::Ok(move _12); // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++         StorageDead(_12);                // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++         goto -> bb4;                     // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++     }
++ 
++     bb4: {
++         StorageDead(_10);                // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++         StorageLive(_14);                // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
++         _13 = discriminant(_9);          // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
++         switchInt(move _13) -> [0: bb7, 1: bb5, otherwise: bb6]; // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
++     }
++ 
++     bb5: {
++         _8 = Option::<u16>::None;        // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
++         goto -> bb8;                     // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
++     }
++ 
++     bb6: {
++         unreachable;                     // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
++     }
++ 
++     bb7: {
++         _14 = move ((_9 as Ok).0: u16);  // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
++         _8 = Option::<u16>::Some(move _14); // scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
++         goto -> bb8;                     // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
++     }
++ 
++     bb8: {
++         StorageDead(_14);                // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
++         StorageDead(_9);                 // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
++         StorageLive(_15);                // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
++         _16 = discriminant(_8);          // scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
++         switchInt(move _16) -> [1: bb9, otherwise: bb6]; // scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
++     }
++ 
++     bb9: {
++         _5 = move ((_8 as Some).0: u16); // scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
++         StorageDead(_15);                // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
++         StorageDead(_8);                 // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
++         StorageDead(_7);                 // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
++         StorageDead(_6);                 // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
++         _0 = unchecked_shl::<u16>(_3, move _5) -> [return: bb1, unwind unreachable]; // scope 2 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
++                                          // mir::Constant
++                                          // + span: $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
++                                          // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(u16, u16) -> u16 {unchecked_shl::<u16>}, val: Value(<ZST>) }
       }
   }
   
diff --git a/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.PreCodegen.after.mir b/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.PreCodegen.after.mir
index 9b7b11ef659..3c175ed1504 100644
--- a/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.PreCodegen.after.mir
+++ b/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.PreCodegen.after.mir
@@ -9,7 +9,51 @@ fn unchecked_shl_unsigned_smaller(_1: u16, _2: u32) -> u16 {
         debug rhs => _2;                 // in scope 1 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
         let mut _3: u16;                 // in scope 1 at $SRC_DIR/core/src/num/mod.rs:LL:COL
         let mut _4: (u32,);              // in scope 1 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+        let mut _5: u32;                 // in scope 1 at $SRC_DIR/core/src/num/mod.rs:LL:COL
         scope 2 {
+            scope 3 (inlined core::num::<impl u16>::unchecked_shl::conv) { // at $SRC_DIR/core/src/num/mod.rs:LL:COL
+                debug x => _5;           // in scope 3 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+                let mut _6: std::option::Option<u16>; // in scope 3 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+                let mut _7: std::result::Result<u16, std::num::TryFromIntError>; // in scope 3 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+                scope 4 {
+                    scope 5 (inlined <u32 as TryInto<u16>>::try_into) { // at $SRC_DIR/core/src/num/mod.rs:LL:COL
+                        debug self => _5; // in scope 5 at $SRC_DIR/core/src/convert/mod.rs:LL:COL
+                        scope 6 (inlined convert::num::<impl TryFrom<u32> for u16>::try_from) { // at $SRC_DIR/core/src/convert/mod.rs:LL:COL
+                            debug u => _5; // in scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+                            let mut _8: bool; // in scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+                            let mut _9: u32; // in scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+                            let mut _10: u16; // in scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+                        }
+                    }
+                    scope 7 (inlined Result::<u16, TryFromIntError>::ok) { // at $SRC_DIR/core/src/num/mod.rs:LL:COL
+                        debug self => _7; // in scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
+                        let mut _11: isize; // in scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
+                        let _12: u16;    // in scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
+                        scope 8 {
+                            debug x => _12; // in scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
+                        }
+                    }
+                    scope 9 (inlined #[track_caller] Option::<u16>::unwrap_unchecked) { // at $SRC_DIR/core/src/num/mod.rs:LL:COL
+                        debug self => _6; // in scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
+                        let mut _13: &std::option::Option<u16>; // in scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
+                        let mut _14: isize; // in scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
+                        scope 10 {
+                            debug val => _3; // in scope 10 at $SRC_DIR/core/src/option.rs:LL:COL
+                        }
+                        scope 11 {
+                            scope 13 (inlined unreachable_unchecked) { // at $SRC_DIR/core/src/option.rs:LL:COL
+                                scope 14 {
+                                    scope 15 (inlined unreachable_unchecked::runtime) { // at $SRC_DIR/core/src/intrinsics.rs:LL:COL
+                                    }
+                                }
+                            }
+                        }
+                        scope 12 (inlined Option::<u16>::is_some) { // at $SRC_DIR/core/src/option.rs:LL:COL
+                            debug self => _13; // in scope 12 at $SRC_DIR/core/src/option.rs:LL:COL
+                        }
+                    }
+                }
+            }
         }
     }
 
@@ -17,22 +61,78 @@ fn unchecked_shl_unsigned_smaller(_1: u16, _2: u32) -> u16 {
         StorageLive(_3);                 // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
         StorageLive(_4);                 // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
         _4 = (_2,);                      // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
-        _3 = core::num::<impl u16>::unchecked_shl::conv(move (_4.0: u32)) -> bb1; // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
-                                         // mir::Constant
-                                         // + span: $SRC_DIR/core/src/num/mod.rs:LL:COL
-                                         // + literal: Const { ty: fn(u32) -> u16 {core::num::<impl u16>::unchecked_shl::conv}, val: Value(<ZST>) }
+        StorageLive(_5);                 // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+        _5 = move (_4.0: u32);           // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+        StorageLive(_6);                 // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+        StorageLive(_7);                 // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+        StorageLive(_8);                 // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        StorageLive(_9);                 // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        _9 = const 65535_u32;            // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        _8 = Gt(_5, move _9);            // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        StorageDead(_9);                 // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        switchInt(move _8) -> [0: bb3, otherwise: bb2]; // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
     }
 
     bb1: {
+        StorageDead(_3);                 // scope 2 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
+        return;                          // scope 0 at $DIR/unchecked_shifts.rs:+2:2: +2:2
+    }
+
+    bb2: {
+        _7 = Result::<u16, TryFromIntError>::Err(const TryFromIntError(())); // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+                                         // mir::Constant
+                                         // + span: no-location
+                                         // + literal: Const { ty: TryFromIntError, val: Value(<ZST>) }
+        goto -> bb4;                     // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+    }
+
+    bb3: {
+        StorageLive(_10);                // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        _10 = _5 as u16 (IntToInt);      // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        _7 = Result::<u16, TryFromIntError>::Ok(move _10); // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        StorageDead(_10);                // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        goto -> bb4;                     // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+    }
+
+    bb4: {
+        StorageDead(_8);                 // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        StorageLive(_12);                // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+        _11 = discriminant(_7);          // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
+        switchInt(move _11) -> [0: bb7, 1: bb5, otherwise: bb6]; // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
+    }
+
+    bb5: {
+        _6 = Option::<u16>::None;        // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
+        goto -> bb8;                     // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
+    }
+
+    bb6: {
+        unreachable;                     // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
+    }
+
+    bb7: {
+        _12 = move ((_7 as Ok).0: u16);  // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
+        _6 = Option::<u16>::Some(move _12); // scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
+        goto -> bb8;                     // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
+    }
+
+    bb8: {
+        StorageDead(_12);                // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+        StorageDead(_7);                 // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+        StorageLive(_13);                // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+        _14 = discriminant(_6);          // scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
+        switchInt(move _14) -> [1: bb9, otherwise: bb6]; // scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
+    }
+
+    bb9: {
+        _3 = move ((_6 as Some).0: u16); // scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
+        StorageDead(_13);                // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+        StorageDead(_6);                 // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+        StorageDead(_5);                 // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
         StorageDead(_4);                 // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
-        _0 = unchecked_shl::<u16>(_1, move _3) -> [return: bb2, unwind unreachable]; // scope 2 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
+        _0 = unchecked_shl::<u16>(_1, move _3) -> [return: bb1, unwind unreachable]; // scope 2 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
                                          // mir::Constant
                                          // + span: $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
                                          // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(u16, u16) -> u16 {unchecked_shl::<u16>}, val: Value(<ZST>) }
     }
-
-    bb2: {
-        StorageDead(_3);                 // scope 2 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
-        return;                          // scope 0 at $DIR/unchecked_shifts.rs:+2:2: +2:2
-    }
 }
diff --git a/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_smaller.Inline.diff b/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_smaller.Inline.diff
index 9638ddda46b..f3d3e6090bb 100644
--- a/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_smaller.Inline.diff
+++ b/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_smaller.Inline.diff
@@ -12,7 +12,51 @@
 +         debug rhs => _4;                 // in scope 1 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
 +         let mut _5: i16;                 // in scope 1 at $SRC_DIR/core/src/num/mod.rs:LL:COL
 +         let mut _6: (u32,);              // in scope 1 at $SRC_DIR/core/src/num/mod.rs:LL:COL
++         let mut _7: u32;                 // in scope 1 at $SRC_DIR/core/src/num/mod.rs:LL:COL
 +         scope 2 {
++             scope 3 (inlined core::num::<impl i16>::unchecked_shr::conv) { // at $SRC_DIR/core/src/num/mod.rs:LL:COL
++                 debug x => _7;           // in scope 3 at $SRC_DIR/core/src/num/mod.rs:LL:COL
++                 let mut _8: std::option::Option<i16>; // in scope 3 at $SRC_DIR/core/src/num/mod.rs:LL:COL
++                 let mut _9: std::result::Result<i16, std::num::TryFromIntError>; // in scope 3 at $SRC_DIR/core/src/num/mod.rs:LL:COL
++                 scope 4 {
++                     scope 5 (inlined <u32 as TryInto<i16>>::try_into) { // at $SRC_DIR/core/src/num/mod.rs:LL:COL
++                         debug self => _7; // in scope 5 at $SRC_DIR/core/src/convert/mod.rs:LL:COL
++                         scope 6 (inlined convert::num::<impl TryFrom<u32> for i16>::try_from) { // at $SRC_DIR/core/src/convert/mod.rs:LL:COL
++                             debug u => _7; // in scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++                             let mut _10: bool; // in scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++                             let mut _11: u32; // in scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++                             let mut _12: i16; // in scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++                         }
++                     }
++                     scope 7 (inlined Result::<i16, TryFromIntError>::ok) { // at $SRC_DIR/core/src/num/mod.rs:LL:COL
++                         debug self => _9; // in scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
++                         let mut _13: isize; // in scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
++                         let _14: i16;    // in scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
++                         scope 8 {
++                             debug x => _14; // in scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
++                         }
++                     }
++                     scope 9 (inlined #[track_caller] Option::<i16>::unwrap_unchecked) { // at $SRC_DIR/core/src/num/mod.rs:LL:COL
++                         debug self => _8; // in scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
++                         let mut _15: &std::option::Option<i16>; // in scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
++                         let mut _16: isize; // in scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
++                         scope 10 {
++                             debug val => _5; // in scope 10 at $SRC_DIR/core/src/option.rs:LL:COL
++                         }
++                         scope 11 {
++                             scope 13 (inlined unreachable_unchecked) { // at $SRC_DIR/core/src/option.rs:LL:COL
++                                 scope 14 {
++                                     scope 15 (inlined unreachable_unchecked::runtime) { // at $SRC_DIR/core/src/intrinsics.rs:LL:COL
++                                     }
++                                 }
++                             }
++                         }
++                         scope 12 (inlined Option::<i16>::is_some) { // at $SRC_DIR/core/src/option.rs:LL:COL
++                             debug self => _15; // in scope 12 at $SRC_DIR/core/src/option.rs:LL:COL
++                         }
++                     }
++                 }
++             }
 +         }
 +     }
   
@@ -22,30 +66,87 @@
           StorageLive(_4);                 // scope 0 at $DIR/unchecked_shifts.rs:+1:21: +1:22
           _4 = _2;                         // scope 0 at $DIR/unchecked_shifts.rs:+1:21: +1:22
 -         _0 = core::num::<impl i16>::unchecked_shr(move _3, move _4) -> bb1; // scope 0 at $DIR/unchecked_shifts.rs:+1:5: +1:23
+-                                          // mir::Constant
+-                                          // + span: $DIR/unchecked_shifts.rs:17:7: 17:20
+-                                          // + literal: Const { ty: unsafe fn(i16, u32) -> i16 {core::num::<impl i16>::unchecked_shr}, val: Value(<ZST>) }
 +         StorageLive(_5);                 // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
 +         StorageLive(_6);                 // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
 +         _6 = (_4,);                      // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
-+         _5 = core::num::<impl i16>::unchecked_shr::conv(move (_6.0: u32)) -> bb1; // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
-                                           // mir::Constant
--                                          // + span: $DIR/unchecked_shifts.rs:17:7: 17:20
--                                          // + literal: Const { ty: unsafe fn(i16, u32) -> i16 {core::num::<impl i16>::unchecked_shr}, val: Value(<ZST>) }
-+                                          // + span: $SRC_DIR/core/src/num/mod.rs:LL:COL
-+                                          // + literal: Const { ty: fn(u32) -> i16 {core::num::<impl i16>::unchecked_shr::conv}, val: Value(<ZST>) }
++         StorageLive(_7);                 // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
++         _7 = move (_6.0: u32);           // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
++         StorageLive(_8);                 // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
++         StorageLive(_9);                 // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
++         StorageLive(_10);                // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++         StorageLive(_11);                // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++         _11 = const 32767_u32;           // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++         _10 = Gt(_7, move _11);          // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++         StorageDead(_11);                // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++         switchInt(move _10) -> [0: bb3, otherwise: bb2]; // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
       }
   
       bb1: {
-+         StorageDead(_6);                 // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
-+         _0 = unchecked_shr::<i16>(_3, move _5) -> [return: bb2, unwind unreachable]; // scope 2 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
-+                                          // mir::Constant
-+                                          // + span: $SRC_DIR/core/src/num/int_macros.rs:LL:COL
-+                                          // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(i16, i16) -> i16 {unchecked_shr::<i16>}, val: Value(<ZST>) }
-+     }
-+ 
-+     bb2: {
 +         StorageDead(_5);                 // scope 2 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
           StorageDead(_4);                 // scope 0 at $DIR/unchecked_shifts.rs:+1:22: +1:23
           StorageDead(_3);                 // scope 0 at $DIR/unchecked_shifts.rs:+1:22: +1:23
           return;                          // scope 0 at $DIR/unchecked_shifts.rs:+2:2: +2:2
++     }
++ 
++     bb2: {
++         _9 = Result::<i16, TryFromIntError>::Err(const TryFromIntError(())); // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++                                          // mir::Constant
++                                          // + span: no-location
++                                          // + literal: Const { ty: TryFromIntError, val: Value(<ZST>) }
++         goto -> bb4;                     // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++     }
++ 
++     bb3: {
++         StorageLive(_12);                // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++         _12 = _7 as i16 (IntToInt);      // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++         _9 = Result::<i16, TryFromIntError>::Ok(move _12); // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++         StorageDead(_12);                // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++         goto -> bb4;                     // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++     }
++ 
++     bb4: {
++         StorageDead(_10);                // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++         StorageLive(_14);                // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
++         _13 = discriminant(_9);          // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
++         switchInt(move _13) -> [0: bb7, 1: bb5, otherwise: bb6]; // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
++     }
++ 
++     bb5: {
++         _8 = Option::<i16>::None;        // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
++         goto -> bb8;                     // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
++     }
++ 
++     bb6: {
++         unreachable;                     // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
++     }
++ 
++     bb7: {
++         _14 = move ((_9 as Ok).0: i16);  // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
++         _8 = Option::<i16>::Some(move _14); // scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
++         goto -> bb8;                     // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
++     }
++ 
++     bb8: {
++         StorageDead(_14);                // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
++         StorageDead(_9);                 // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
++         StorageLive(_15);                // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
++         _16 = discriminant(_8);          // scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
++         switchInt(move _16) -> [1: bb9, otherwise: bb6]; // scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
++     }
++ 
++     bb9: {
++         _5 = move ((_8 as Some).0: i16); // scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
++         StorageDead(_15);                // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
++         StorageDead(_8);                 // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
++         StorageDead(_7);                 // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
++         StorageDead(_6);                 // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
++         _0 = unchecked_shr::<i16>(_3, move _5) -> [return: bb1, unwind unreachable]; // scope 2 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
++                                          // mir::Constant
++                                          // + span: $SRC_DIR/core/src/num/int_macros.rs:LL:COL
++                                          // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(i16, i16) -> i16 {unchecked_shr::<i16>}, val: Value(<ZST>) }
       }
   }
   
diff --git a/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_smaller.PreCodegen.after.mir b/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_smaller.PreCodegen.after.mir
index afe6d08741b..724b3c56723 100644
--- a/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_smaller.PreCodegen.after.mir
+++ b/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_smaller.PreCodegen.after.mir
@@ -9,7 +9,51 @@ fn unchecked_shr_signed_smaller(_1: i16, _2: u32) -> i16 {
         debug rhs => _2;                 // in scope 1 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
         let mut _3: i16;                 // in scope 1 at $SRC_DIR/core/src/num/mod.rs:LL:COL
         let mut _4: (u32,);              // in scope 1 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+        let mut _5: u32;                 // in scope 1 at $SRC_DIR/core/src/num/mod.rs:LL:COL
         scope 2 {
+            scope 3 (inlined core::num::<impl i16>::unchecked_shr::conv) { // at $SRC_DIR/core/src/num/mod.rs:LL:COL
+                debug x => _5;           // in scope 3 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+                let mut _6: std::option::Option<i16>; // in scope 3 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+                let mut _7: std::result::Result<i16, std::num::TryFromIntError>; // in scope 3 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+                scope 4 {
+                    scope 5 (inlined <u32 as TryInto<i16>>::try_into) { // at $SRC_DIR/core/src/num/mod.rs:LL:COL
+                        debug self => _5; // in scope 5 at $SRC_DIR/core/src/convert/mod.rs:LL:COL
+                        scope 6 (inlined convert::num::<impl TryFrom<u32> for i16>::try_from) { // at $SRC_DIR/core/src/convert/mod.rs:LL:COL
+                            debug u => _5; // in scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+                            let mut _8: bool; // in scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+                            let mut _9: u32; // in scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+                            let mut _10: i16; // in scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+                        }
+                    }
+                    scope 7 (inlined Result::<i16, TryFromIntError>::ok) { // at $SRC_DIR/core/src/num/mod.rs:LL:COL
+                        debug self => _7; // in scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
+                        let mut _11: isize; // in scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
+                        let _12: i16;    // in scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
+                        scope 8 {
+                            debug x => _12; // in scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
+                        }
+                    }
+                    scope 9 (inlined #[track_caller] Option::<i16>::unwrap_unchecked) { // at $SRC_DIR/core/src/num/mod.rs:LL:COL
+                        debug self => _6; // in scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
+                        let mut _13: &std::option::Option<i16>; // in scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
+                        let mut _14: isize; // in scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
+                        scope 10 {
+                            debug val => _3; // in scope 10 at $SRC_DIR/core/src/option.rs:LL:COL
+                        }
+                        scope 11 {
+                            scope 13 (inlined unreachable_unchecked) { // at $SRC_DIR/core/src/option.rs:LL:COL
+                                scope 14 {
+                                    scope 15 (inlined unreachable_unchecked::runtime) { // at $SRC_DIR/core/src/intrinsics.rs:LL:COL
+                                    }
+                                }
+                            }
+                        }
+                        scope 12 (inlined Option::<i16>::is_some) { // at $SRC_DIR/core/src/option.rs:LL:COL
+                            debug self => _13; // in scope 12 at $SRC_DIR/core/src/option.rs:LL:COL
+                        }
+                    }
+                }
+            }
         }
     }
 
@@ -17,22 +61,78 @@ fn unchecked_shr_signed_smaller(_1: i16, _2: u32) -> i16 {
         StorageLive(_3);                 // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
         StorageLive(_4);                 // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
         _4 = (_2,);                      // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
-        _3 = core::num::<impl i16>::unchecked_shr::conv(move (_4.0: u32)) -> bb1; // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
-                                         // mir::Constant
-                                         // + span: $SRC_DIR/core/src/num/mod.rs:LL:COL
-                                         // + literal: Const { ty: fn(u32) -> i16 {core::num::<impl i16>::unchecked_shr::conv}, val: Value(<ZST>) }
+        StorageLive(_5);                 // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+        _5 = move (_4.0: u32);           // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+        StorageLive(_6);                 // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+        StorageLive(_7);                 // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+        StorageLive(_8);                 // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        StorageLive(_9);                 // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        _9 = const 32767_u32;            // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        _8 = Gt(_5, move _9);            // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        StorageDead(_9);                 // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        switchInt(move _8) -> [0: bb3, otherwise: bb2]; // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
     }
 
     bb1: {
+        StorageDead(_3);                 // scope 2 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
+        return;                          // scope 0 at $DIR/unchecked_shifts.rs:+2:2: +2:2
+    }
+
+    bb2: {
+        _7 = Result::<i16, TryFromIntError>::Err(const TryFromIntError(())); // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+                                         // mir::Constant
+                                         // + span: no-location
+                                         // + literal: Const { ty: TryFromIntError, val: Value(<ZST>) }
+        goto -> bb4;                     // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+    }
+
+    bb3: {
+        StorageLive(_10);                // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        _10 = _5 as i16 (IntToInt);      // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        _7 = Result::<i16, TryFromIntError>::Ok(move _10); // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        StorageDead(_10);                // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        goto -> bb4;                     // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+    }
+
+    bb4: {
+        StorageDead(_8);                 // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        StorageLive(_12);                // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+        _11 = discriminant(_7);          // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
+        switchInt(move _11) -> [0: bb7, 1: bb5, otherwise: bb6]; // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
+    }
+
+    bb5: {
+        _6 = Option::<i16>::None;        // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
+        goto -> bb8;                     // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
+    }
+
+    bb6: {
+        unreachable;                     // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
+    }
+
+    bb7: {
+        _12 = move ((_7 as Ok).0: i16);  // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
+        _6 = Option::<i16>::Some(move _12); // scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
+        goto -> bb8;                     // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
+    }
+
+    bb8: {
+        StorageDead(_12);                // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+        StorageDead(_7);                 // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+        StorageLive(_13);                // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+        _14 = discriminant(_6);          // scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
+        switchInt(move _14) -> [1: bb9, otherwise: bb6]; // scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
+    }
+
+    bb9: {
+        _3 = move ((_6 as Some).0: i16); // scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
+        StorageDead(_13);                // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+        StorageDead(_6);                 // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+        StorageDead(_5);                 // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
         StorageDead(_4);                 // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
-        _0 = unchecked_shr::<i16>(_1, move _3) -> [return: bb2, unwind unreachable]; // scope 2 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
+        _0 = unchecked_shr::<i16>(_1, move _3) -> [return: bb1, unwind unreachable]; // scope 2 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
                                          // mir::Constant
                                          // + span: $SRC_DIR/core/src/num/int_macros.rs:LL:COL
                                          // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(i16, i16) -> i16 {unchecked_shr::<i16>}, val: Value(<ZST>) }
     }
-
-    bb2: {
-        StorageDead(_3);                 // scope 2 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
-        return;                          // scope 0 at $DIR/unchecked_shifts.rs:+2:2: +2:2
-    }
 }
diff --git a/tests/mir-opt/inline/unsized_argument.caller.Inline.diff b/tests/mir-opt/inline/unsized_argument.caller.Inline.diff
new file mode 100644
index 00000000000..745f2bb193a
--- /dev/null
+++ b/tests/mir-opt/inline/unsized_argument.caller.Inline.diff
@@ -0,0 +1,50 @@
+- // MIR for `caller` before Inline
++ // MIR for `caller` after Inline
+  
+  fn caller(_1: Box<[i32]>) -> () {
+      debug x => _1;                       // in scope 0 at $DIR/unsized_argument.rs:+0:11: +0:12
+      let mut _0: ();                      // return place in scope 0 at $DIR/unsized_argument.rs:+0:26: +0:26
+      let _2: ();                          // in scope 0 at $DIR/unsized_argument.rs:+1:5: +1:15
+      let mut _3: std::boxed::Box<[i32]>;  // in scope 0 at $DIR/unsized_argument.rs:+1:13: +1:14
+      let mut _4: ();                      // in scope 0 at $DIR/unsized_argument.rs:+1:14: +1:15
+      let mut _5: ();                      // in scope 0 at $DIR/unsized_argument.rs:+1:14: +1:15
+      let mut _6: ();                      // in scope 0 at $DIR/unsized_argument.rs:+1:14: +1:15
+      let mut _7: *const [i32];            // in scope 0 at $DIR/unsized_argument.rs:+1:13: +1:14
+  
+      bb0: {
+          StorageLive(_2);                 // scope 0 at $DIR/unsized_argument.rs:+1:5: +1:15
+          StorageLive(_3);                 // scope 0 at $DIR/unsized_argument.rs:+1:13: +1:14
+          _3 = move _1;                    // scope 0 at $DIR/unsized_argument.rs:+1:13: +1:14
+          _7 = (((_3.0: std::ptr::Unique<[i32]>).0: std::ptr::NonNull<[i32]>).0: *const [i32]); // scope 0 at $DIR/unsized_argument.rs:+1:5: +1:15
+          _2 = callee(move (*_7)) -> [return: bb3, unwind: bb4]; // scope 0 at $DIR/unsized_argument.rs:+1:5: +1:15
+                                           // mir::Constant
+                                           // + span: $DIR/unsized_argument.rs:9:5: 9:11
+                                           // + literal: Const { ty: fn([i32]) {callee}, val: Value(<ZST>) }
+      }
+  
+      bb1: {
+          StorageDead(_3);                 // scope 0 at $DIR/unsized_argument.rs:+1:14: +1:15
+          StorageDead(_2);                 // scope 0 at $DIR/unsized_argument.rs:+1:15: +1:16
+          _0 = const ();                   // scope 0 at $DIR/unsized_argument.rs:+0:26: +2:2
+          return;                          // scope 0 at $DIR/unsized_argument.rs:+2:2: +2:2
+      }
+  
+      bb2 (cleanup): {
+          resume;                          // scope 0 at $DIR/unsized_argument.rs:+0:1: +2:2
+      }
+  
+      bb3: {
+          _4 = alloc::alloc::box_free::<[i32], std::alloc::Global>(move (_3.0: std::ptr::Unique<[i32]>), move (_3.1: std::alloc::Global)) -> bb1; // scope 0 at $DIR/unsized_argument.rs:+1:14: +1:15
+                                           // mir::Constant
+                                           // + span: $DIR/unsized_argument.rs:9:14: 9:15
+                                           // + literal: Const { ty: unsafe fn(Unique<[i32]>, std::alloc::Global) {alloc::alloc::box_free::<[i32], std::alloc::Global>}, val: Value(<ZST>) }
+      }
+  
+      bb4 (cleanup): {
+          _6 = alloc::alloc::box_free::<[i32], std::alloc::Global>(move (_3.0: std::ptr::Unique<[i32]>), move (_3.1: std::alloc::Global)) -> [return: bb2, unwind terminate]; // scope 0 at $DIR/unsized_argument.rs:+1:14: +1:15
+                                           // mir::Constant
+                                           // + span: $DIR/unsized_argument.rs:9:14: 9:15
+                                           // + literal: Const { ty: unsafe fn(Unique<[i32]>, std::alloc::Global) {alloc::alloc::box_free::<[i32], std::alloc::Global>}, val: Value(<ZST>) }
+      }
+  }
+  
diff --git a/tests/mir-opt/inline/unsized_argument.rs b/tests/mir-opt/inline/unsized_argument.rs
new file mode 100644
index 00000000000..b2c51407fd5
--- /dev/null
+++ b/tests/mir-opt/inline/unsized_argument.rs
@@ -0,0 +1,15 @@
+// needs-unwind
+#![feature(unsized_fn_params)]
+
+#[inline(always)]
+fn callee(y: [i32]) {}
+
+// EMIT_MIR unsized_argument.caller.Inline.diff
+fn caller(x: Box<[i32]>) {
+    callee(*x);
+}
+
+fn main() {
+    let b = Box::new([1]);
+    caller(b);
+}
diff --git a/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.diff b/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.diff
index 778ecc46d73..8a8cd896e85 100644
--- a/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.diff
+++ b/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.diff
@@ -9,9 +9,8 @@
 +         debug self => _2;                // in scope 1 at $SRC_DIR/core/src/option.rs:LL:COL
 +         let mut _3: &std::option::Option<T>; // in scope 1 at $SRC_DIR/core/src/option.rs:LL:COL
 +         let mut _4: isize;               // in scope 1 at $SRC_DIR/core/src/option.rs:LL:COL
-+         let _5: T;                       // in scope 1 at $SRC_DIR/core/src/option.rs:LL:COL
 +         scope 2 {
-+             debug val => _5;             // in scope 2 at $SRC_DIR/core/src/option.rs:LL:COL
++             debug val => _0;             // in scope 2 at $SRC_DIR/core/src/option.rs:LL:COL
 +         }
 +         scope 3 {
 +             scope 5 (inlined unreachable_unchecked) { // at $SRC_DIR/core/src/option.rs:LL:COL
@@ -47,10 +46,7 @@
 -     bb2 (cleanup): {
 -         resume;                          // scope 0 at $DIR/unwrap_unchecked.rs:+0:1: +2:2
 +     bb2: {
-+         StorageLive(_5);                 // scope 1 at $SRC_DIR/core/src/option.rs:LL:COL
-+         _5 = move ((_2 as Some).0: T);   // scope 1 at $SRC_DIR/core/src/option.rs:LL:COL
-+         _0 = move _5;                    // scope 2 at $SRC_DIR/core/src/option.rs:LL:COL
-+         StorageDead(_5);                 // scope 1 at $SRC_DIR/core/src/option.rs:LL:COL
++         _0 = move ((_2 as Some).0: T);   // scope 1 at $SRC_DIR/core/src/option.rs:LL:COL
 +         StorageDead(_3);                 // scope 0 at $DIR/unwrap_unchecked.rs:+1:9: +1:27
 +         StorageDead(_2);                 // scope 0 at $DIR/unwrap_unchecked.rs:+1:26: +1:27
 +         return;                          // scope 0 at $DIR/unwrap_unchecked.rs:+2:2: +2:2
diff --git a/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.mir b/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.mir
index 5cdf4fa46e3..c5e2469fc27 100644
--- a/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.mir
+++ b/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.mir
@@ -7,9 +7,8 @@ fn unwrap_unchecked(_1: Option<T>) -> T {
         debug self => _1;                // in scope 1 at $SRC_DIR/core/src/option.rs:LL:COL
         let mut _2: &std::option::Option<T>; // in scope 1 at $SRC_DIR/core/src/option.rs:LL:COL
         let mut _3: isize;               // in scope 1 at $SRC_DIR/core/src/option.rs:LL:COL
-        let _4: T;                       // in scope 1 at $SRC_DIR/core/src/option.rs:LL:COL
         scope 2 {
-            debug val => _4;             // in scope 2 at $SRC_DIR/core/src/option.rs:LL:COL
+            debug val => _0;             // in scope 2 at $SRC_DIR/core/src/option.rs:LL:COL
         }
         scope 3 {
             scope 5 (inlined unreachable_unchecked) { // at $SRC_DIR/core/src/option.rs:LL:COL
@@ -35,10 +34,7 @@ fn unwrap_unchecked(_1: Option<T>) -> T {
     }
 
     bb2: {
-        StorageLive(_4);                 // scope 1 at $SRC_DIR/core/src/option.rs:LL:COL
-        _4 = move ((_1 as Some).0: T);   // scope 1 at $SRC_DIR/core/src/option.rs:LL:COL
-        _0 = move _4;                    // scope 2 at $SRC_DIR/core/src/option.rs:LL:COL
-        StorageDead(_4);                 // scope 1 at $SRC_DIR/core/src/option.rs:LL:COL
+        _0 = move ((_1 as Some).0: T);   // scope 1 at $SRC_DIR/core/src/option.rs:LL:COL
         StorageDead(_2);                 // scope 0 at $DIR/unwrap_unchecked.rs:+1:9: +1:27
         return;                          // scope 0 at $DIR/unwrap_unchecked.rs:+2:2: +2:2
     }
diff --git a/tests/mir-opt/issue_72181_1.f.built.after.mir b/tests/mir-opt/issue_72181_1.f.built.after.mir
index 4086da52011..25f47225113 100644
--- a/tests/mir-opt/issue_72181_1.f.built.after.mir
+++ b/tests/mir-opt/issue_72181_1.f.built.after.mir
@@ -3,27 +3,13 @@
 fn f(_1: Void) -> ! {
     debug v => _1;                       // in scope 0 at $DIR/issue_72181_1.rs:+0:6: +0:7
     let mut _0: !;                       // return place in scope 0 at $DIR/issue_72181_1.rs:+0:18: +0:19
-    let mut _2: !;                       // in scope 0 at $DIR/issue_72181_1.rs:+0:20: +2:2
-    let mut _3: !;                       // in scope 0 at $DIR/issue_72181_1.rs:+1:5: +1:15
 
     bb0: {
-        StorageLive(_2);                 // scope 0 at $DIR/issue_72181_1.rs:+0:20: +2:2
-        StorageLive(_3);                 // scope 0 at $DIR/issue_72181_1.rs:+1:5: +1:15
         FakeRead(ForMatchedPlace(None), _1); // scope 0 at $DIR/issue_72181_1.rs:+1:11: +1:12
         unreachable;                     // scope 0 at $DIR/issue_72181_1.rs:+1:11: +1:12
     }
 
     bb1: {
-        unreachable;                     // scope 0 at $DIR/issue_72181_1.rs:+1:5: +1:15
-    }
-
-    bb2: {
-        StorageDead(_3);                 // scope 0 at $DIR/issue_72181_1.rs:+1:14: +1:15
-        unreachable;                     // scope 0 at $DIR/issue_72181_1.rs:+0:20: +2:2
-    }
-
-    bb3: {
-        StorageDead(_2);                 // scope 0 at $DIR/issue_72181_1.rs:+2:1: +2:2
         return;                          // scope 0 at $DIR/issue_72181_1.rs:+2:2: +2:2
     }
 }
diff --git a/tests/mir-opt/issue_76432.test.SimplifyComparisonIntegral.diff b/tests/mir-opt/issue_76432.test.SimplifyComparisonIntegral.diff
index abb89b91dd3..73b9ea46c44 100644
--- a/tests/mir-opt/issue_76432.test.SimplifyComparisonIntegral.diff
+++ b/tests/mir-opt/issue_76432.test.SimplifyComparisonIntegral.diff
@@ -21,9 +21,9 @@
           let _13: &T;                     // in scope 1 at $DIR/issue_76432.rs:+3:18: +3:24
           let _14: &T;                     // in scope 1 at $DIR/issue_76432.rs:+3:26: +3:32
           scope 2 {
-              debug v1 => _12;             // in scope 2 at $DIR/issue_76432.rs:+3:10: +3:16
-              debug v2 => _13;             // in scope 2 at $DIR/issue_76432.rs:+3:18: +3:24
-              debug v3 => _14;             // in scope 2 at $DIR/issue_76432.rs:+3:26: +3:32
+              debug v1 => &(*_2)[0 of 3];  // in scope 2 at $DIR/issue_76432.rs:+3:10: +3:16
+              debug v2 => &(*_2)[1 of 3];  // in scope 2 at $DIR/issue_76432.rs:+3:18: +3:24
+              debug v3 => &(*_2)[2 of 3];  // in scope 2 at $DIR/issue_76432.rs:+3:26: +3:32
           }
       }
   
@@ -52,15 +52,6 @@
       }
   
       bb2: {
-          StorageLive(_12);                // scope 1 at $DIR/issue_76432.rs:+3:10: +3:16
-          _12 = &(*_2)[0 of 3];            // scope 1 at $DIR/issue_76432.rs:+3:10: +3:16
-          StorageLive(_13);                // scope 1 at $DIR/issue_76432.rs:+3:18: +3:24
-          _13 = &(*_2)[1 of 3];            // scope 1 at $DIR/issue_76432.rs:+3:18: +3:24
-          StorageLive(_14);                // scope 1 at $DIR/issue_76432.rs:+3:26: +3:32
-          _14 = &(*_2)[2 of 3];            // scope 1 at $DIR/issue_76432.rs:+3:26: +3:32
-          StorageDead(_14);                // scope 1 at $DIR/issue_76432.rs:+3:84: +3:85
-          StorageDead(_13);                // scope 1 at $DIR/issue_76432.rs:+3:84: +3:85
-          StorageDead(_12);                // scope 1 at $DIR/issue_76432.rs:+3:84: +3:85
           StorageDead(_5);                 // scope 0 at $DIR/issue_76432.rs:+6:1: +6:2
           StorageDead(_2);                 // scope 0 at $DIR/issue_76432.rs:+6:1: +6:2
           return;                          // scope 0 at $DIR/issue_76432.rs:+6:2: +6:2
diff --git a/tests/mir-opt/issue_99325.main.built.after.mir b/tests/mir-opt/issue_99325.main.built.after.mir
index f0c9ef419bd..0424ce3abeb 100644
--- a/tests/mir-opt/issue_99325.main.built.after.mir
+++ b/tests/mir-opt/issue_99325.main.built.after.mir
@@ -1,8 +1,8 @@
 // MIR for `main` after built
 
 | User Type Annotations
-| 0: user_ty: Canonical { value: TypeOf(DefId(0:3 ~ issue_99325[22bb]::function_with_bytes), UserSubsts { substs: [Const { ty: &'static [u8; 4], kind: Value(Branch([Leaf(0x41), Leaf(0x41), Leaf(0x41), Leaf(0x41)])) }], user_self_ty: None }), max_universe: U0, variables: [] }, span: $DIR/issue_99325.rs:10:16: 10:46, inferred_ty: fn() -> &'static [u8] {function_with_bytes::<&*b"AAAA">}
-| 1: user_ty: Canonical { value: TypeOf(DefId(0:3 ~ issue_99325[22bb]::function_with_bytes), UserSubsts { substs: [Const { ty: &'static [u8; 4], kind: Unevaluated(UnevaluatedConst { def: DefId(0:8 ~ issue_99325[22bb]::main::{constant#1}), substs: [] }) }], user_self_ty: None }), max_universe: U0, variables: [] }, span: $DIR/issue_99325.rs:11:16: 11:68, inferred_ty: fn() -> &'static [u8] {function_with_bytes::<&*b"AAAA">}
+| 0: user_ty: Canonical { value: TypeOf(DefId(0:3 ~ issue_99325[22bb]::function_with_bytes), UserSubsts { substs: [Const { ty: &'static [u8; 4], kind: Branch([Leaf(0x41), Leaf(0x41), Leaf(0x41), Leaf(0x41)]) }], user_self_ty: None }), max_universe: U0, variables: [] }, span: $DIR/issue_99325.rs:10:16: 10:46, inferred_ty: fn() -> &'static [u8] {function_with_bytes::<&*b"AAAA">}
+| 1: user_ty: Canonical { value: TypeOf(DefId(0:3 ~ issue_99325[22bb]::function_with_bytes), UserSubsts { substs: [Const { ty: &'static [u8; 4], kind: Unevaluated([], DefId(0:8 ~ issue_99325[22bb]::main::{constant#1})) }], user_self_ty: None }), max_universe: U0, variables: [] }, span: $DIR/issue_99325.rs:11:16: 11:68, inferred_ty: fn() -> &'static [u8] {function_with_bytes::<&*b"AAAA">}
 |
 fn main() -> () {
     let mut _0: ();                      // return place in scope 0 at $DIR/issue_99325.rs:+0:15: +0:15
diff --git a/tests/mir-opt/lower_intrinsics.transmute_to_box_uninhabited.LowerIntrinsics.diff b/tests/mir-opt/lower_intrinsics.transmute_to_box_uninhabited.LowerIntrinsics.diff
index 8735a750060..aa5d9619d10 100644
--- a/tests/mir-opt/lower_intrinsics.transmute_to_box_uninhabited.LowerIntrinsics.diff
+++ b/tests/mir-opt/lower_intrinsics.transmute_to_box_uninhabited.LowerIntrinsics.diff
@@ -3,26 +3,22 @@
   
   fn transmute_to_box_uninhabited() -> ! {
       let mut _0: !;                       // return place in scope 0 at $DIR/lower_intrinsics.rs:+0:49: +0:50
-      let mut _1: !;                       // in scope 0 at $DIR/lower_intrinsics.rs:+0:51: +3:2
-      let _2: std::boxed::Box<Never>;      // in scope 0 at $DIR/lower_intrinsics.rs:+1:9: +1:10
-      let mut _3: !;                       // in scope 0 at $DIR/lower_intrinsics.rs:+2:5: +2:16
+      let _1: std::boxed::Box<Never>;      // in scope 0 at $DIR/lower_intrinsics.rs:+1:9: +1:10
       scope 1 {
-          debug x => _2;                   // in scope 1 at $DIR/lower_intrinsics.rs:+1:9: +1:10
+          debug x => _1;                   // in scope 1 at $DIR/lower_intrinsics.rs:+1:9: +1:10
       }
   
       bb0: {
-          StorageLive(_1);                 // scope 0 at $DIR/lower_intrinsics.rs:+0:51: +3:2
-          StorageLive(_2);                 // scope 0 at $DIR/lower_intrinsics.rs:+1:9: +1:10
--         _2 = transmute::<usize, Box<Never>>(const 1_usize) -> [return: bb1, unwind unreachable]; // scope 0 at $DIR/lower_intrinsics.rs:+1:25: +1:52
+          StorageLive(_1);                 // scope 0 at $DIR/lower_intrinsics.rs:+1:9: +1:10
+-         _1 = transmute::<usize, Box<Never>>(const 1_usize) -> [return: bb1, unwind unreachable]; // scope 0 at $DIR/lower_intrinsics.rs:+1:25: +1:52
 -                                          // mir::Constant
 -                                          // + span: $DIR/lower_intrinsics.rs:70:25: 70:44
 -                                          // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(usize) -> Box<Never> {transmute::<usize, Box<Never>>}, val: Value(<ZST>) }
-+         _2 = const 1_usize as std::boxed::Box<Never> (Transmute); // scope 0 at $DIR/lower_intrinsics.rs:+1:25: +1:52
++         _1 = const 1_usize as std::boxed::Box<Never> (Transmute); // scope 0 at $DIR/lower_intrinsics.rs:+1:25: +1:52
 +         goto -> bb1;                     // scope 0 at $DIR/lower_intrinsics.rs:+1:25: +1:52
       }
   
       bb1: {
-          StorageLive(_3);                 // scope 1 at $DIR/lower_intrinsics.rs:+2:5: +2:16
           unreachable;                     // scope 1 at $DIR/lower_intrinsics.rs:+2:11: +2:13
       }
   }
diff --git a/tests/mir-opt/lower_intrinsics.transmute_to_mut_uninhabited.LowerIntrinsics.diff b/tests/mir-opt/lower_intrinsics.transmute_to_mut_uninhabited.LowerIntrinsics.diff
index a772132770c..5fafd45fe85 100644
--- a/tests/mir-opt/lower_intrinsics.transmute_to_mut_uninhabited.LowerIntrinsics.diff
+++ b/tests/mir-opt/lower_intrinsics.transmute_to_mut_uninhabited.LowerIntrinsics.diff
@@ -3,26 +3,22 @@
   
   fn transmute_to_mut_uninhabited() -> ! {
       let mut _0: !;                       // return place in scope 0 at $DIR/lower_intrinsics.rs:+0:49: +0:50
-      let mut _1: !;                       // in scope 0 at $DIR/lower_intrinsics.rs:+0:51: +3:2
-      let _2: &mut Never;                  // in scope 0 at $DIR/lower_intrinsics.rs:+1:9: +1:10
-      let mut _3: !;                       // in scope 0 at $DIR/lower_intrinsics.rs:+2:5: +2:16
+      let _1: &mut Never;                  // in scope 0 at $DIR/lower_intrinsics.rs:+1:9: +1:10
       scope 1 {
-          debug x => _2;                   // in scope 1 at $DIR/lower_intrinsics.rs:+1:9: +1:10
+          debug x => _1;                   // in scope 1 at $DIR/lower_intrinsics.rs:+1:9: +1:10
       }
   
       bb0: {
-          StorageLive(_1);                 // scope 0 at $DIR/lower_intrinsics.rs:+0:51: +3:2
-          StorageLive(_2);                 // scope 0 at $DIR/lower_intrinsics.rs:+1:9: +1:10
--         _2 = transmute::<usize, &mut Never>(const 1_usize) -> [return: bb1, unwind unreachable]; // scope 0 at $DIR/lower_intrinsics.rs:+1:25: +1:52
+          StorageLive(_1);                 // scope 0 at $DIR/lower_intrinsics.rs:+1:9: +1:10
+-         _1 = transmute::<usize, &mut Never>(const 1_usize) -> [return: bb1, unwind unreachable]; // scope 0 at $DIR/lower_intrinsics.rs:+1:25: +1:52
 -                                          // mir::Constant
 -                                          // + span: $DIR/lower_intrinsics.rs:64:25: 64:44
 -                                          // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(usize) -> &mut Never {transmute::<usize, &mut Never>}, val: Value(<ZST>) }
-+         _2 = const 1_usize as &mut Never (Transmute); // scope 0 at $DIR/lower_intrinsics.rs:+1:25: +1:52
++         _1 = const 1_usize as &mut Never (Transmute); // scope 0 at $DIR/lower_intrinsics.rs:+1:25: +1:52
 +         goto -> bb1;                     // scope 0 at $DIR/lower_intrinsics.rs:+1:25: +1:52
       }
   
       bb1: {
-          StorageLive(_3);                 // scope 1 at $DIR/lower_intrinsics.rs:+2:5: +2:16
           unreachable;                     // scope 1 at $DIR/lower_intrinsics.rs:+2:11: +2:13
       }
   }
diff --git a/tests/mir-opt/lower_intrinsics.transmute_to_ref_uninhabited.LowerIntrinsics.diff b/tests/mir-opt/lower_intrinsics.transmute_to_ref_uninhabited.LowerIntrinsics.diff
index c4d53d4e8c7..08dead13211 100644
--- a/tests/mir-opt/lower_intrinsics.transmute_to_ref_uninhabited.LowerIntrinsics.diff
+++ b/tests/mir-opt/lower_intrinsics.transmute_to_ref_uninhabited.LowerIntrinsics.diff
@@ -3,26 +3,22 @@
   
   fn transmute_to_ref_uninhabited() -> ! {
       let mut _0: !;                       // return place in scope 0 at $DIR/lower_intrinsics.rs:+0:49: +0:50
-      let mut _1: !;                       // in scope 0 at $DIR/lower_intrinsics.rs:+0:51: +3:2
-      let _2: &Never;                      // in scope 0 at $DIR/lower_intrinsics.rs:+1:9: +1:10
-      let mut _3: !;                       // in scope 0 at $DIR/lower_intrinsics.rs:+2:5: +2:16
+      let _1: &Never;                      // in scope 0 at $DIR/lower_intrinsics.rs:+1:9: +1:10
       scope 1 {
-          debug x => _2;                   // in scope 1 at $DIR/lower_intrinsics.rs:+1:9: +1:10
+          debug x => _1;                   // in scope 1 at $DIR/lower_intrinsics.rs:+1:9: +1:10
       }
   
       bb0: {
-          StorageLive(_1);                 // scope 0 at $DIR/lower_intrinsics.rs:+0:51: +3:2
-          StorageLive(_2);                 // scope 0 at $DIR/lower_intrinsics.rs:+1:9: +1:10
--         _2 = transmute::<usize, &Never>(const 1_usize) -> [return: bb1, unwind unreachable]; // scope 0 at $DIR/lower_intrinsics.rs:+1:21: +1:48
+          StorageLive(_1);                 // scope 0 at $DIR/lower_intrinsics.rs:+1:9: +1:10
+-         _1 = transmute::<usize, &Never>(const 1_usize) -> [return: bb1, unwind unreachable]; // scope 0 at $DIR/lower_intrinsics.rs:+1:21: +1:48
 -                                          // mir::Constant
 -                                          // + span: $DIR/lower_intrinsics.rs:58:21: 58:40
 -                                          // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(usize) -> &Never {transmute::<usize, &Never>}, val: Value(<ZST>) }
-+         _2 = const 1_usize as &Never (Transmute); // scope 0 at $DIR/lower_intrinsics.rs:+1:21: +1:48
++         _1 = const 1_usize as &Never (Transmute); // scope 0 at $DIR/lower_intrinsics.rs:+1:21: +1:48
 +         goto -> bb1;                     // scope 0 at $DIR/lower_intrinsics.rs:+1:21: +1:48
       }
   
       bb1: {
-          StorageLive(_3);                 // scope 1 at $DIR/lower_intrinsics.rs:+2:5: +2:16
           unreachable;                     // scope 1 at $DIR/lower_intrinsics.rs:+2:11: +2:13
       }
   }
diff --git a/tests/mir-opt/lower_intrinsics.unreachable.LowerIntrinsics.diff b/tests/mir-opt/lower_intrinsics.unreachable.LowerIntrinsics.diff
index c0cc698c481..28e45909c33 100644
--- a/tests/mir-opt/lower_intrinsics.unreachable.LowerIntrinsics.diff
+++ b/tests/mir-opt/lower_intrinsics.unreachable.LowerIntrinsics.diff
@@ -3,16 +3,15 @@
   
   fn unreachable() -> ! {
       let mut _0: !;                       // return place in scope 0 at $DIR/lower_intrinsics.rs:+0:25: +0:26
-      let mut _1: !;                       // in scope 0 at $DIR/lower_intrinsics.rs:+0:27: +2:2
-      let _2: ();                          // in scope 0 at $DIR/lower_intrinsics.rs:+1:14: +1:45
-      let mut _3: !;                       // in scope 0 at $DIR/lower_intrinsics.rs:+1:14: +1:45
+      let _1: ();                          // in scope 0 at $DIR/lower_intrinsics.rs:+1:14: +1:45
+      let mut _2: !;                       // in scope 0 at $DIR/lower_intrinsics.rs:+1:14: +1:45
       scope 1 {
       }
   
       bb0: {
-          StorageLive(_2);                 // scope 0 at $DIR/lower_intrinsics.rs:+1:5: +1:47
-          StorageLive(_3);                 // scope 1 at $DIR/lower_intrinsics.rs:+1:14: +1:45
--         _3 = std::intrinsics::unreachable() -> unwind unreachable; // scope 1 at $DIR/lower_intrinsics.rs:+1:14: +1:45
+          StorageLive(_1);                 // scope 0 at $DIR/lower_intrinsics.rs:+1:5: +1:47
+          StorageLive(_2);                 // scope 1 at $DIR/lower_intrinsics.rs:+1:14: +1:45
+-         _2 = std::intrinsics::unreachable() -> unwind unreachable; // scope 1 at $DIR/lower_intrinsics.rs:+1:14: +1:45
 -                                          // mir::Constant
 -                                          // + span: $DIR/lower_intrinsics.rs:31:14: 31:43
 -                                          // + literal: Const { ty: unsafe extern "rust-intrinsic" fn() -> ! {std::intrinsics::unreachable}, val: Value(<ZST>) }
diff --git a/tests/mir-opt/nll/region_subtyping_basic.main.nll.0.32bit.mir b/tests/mir-opt/nll/region_subtyping_basic.main.nll.0.32bit.mir
index 71bdfcc5c49..c425f3cd506 100644
--- a/tests/mir-opt/nll/region_subtyping_basic.main.nll.0.32bit.mir
+++ b/tests/mir-opt/nll/region_subtyping_basic.main.nll.0.32bit.mir
@@ -22,7 +22,7 @@
 |
 fn main() -> () {
     let mut _0: ();                      // return place in scope 0 at $DIR/region_subtyping_basic.rs:+0:11: +0:11
-    let mut _1: [usize; Const(Value(Leaf(0x00000003)): usize)]; // in scope 0 at $DIR/region_subtyping_basic.rs:+1:9: +1:14
+    let mut _1: [usize; Const { ty: usize, kind: Leaf(0x00000003) }]; // in scope 0 at $DIR/region_subtyping_basic.rs:+1:9: +1:14
     let _3: usize;                       // in scope 0 at $DIR/region_subtyping_basic.rs:+2:16: +2:17
     let mut _4: usize;                   // in scope 0 at $DIR/region_subtyping_basic.rs:+2:14: +2:18
     let mut _5: bool;                    // in scope 0 at $DIR/region_subtyping_basic.rs:+2:14: +2:18
diff --git a/tests/mir-opt/nll/region_subtyping_basic.main.nll.0.64bit.mir b/tests/mir-opt/nll/region_subtyping_basic.main.nll.0.64bit.mir
index 9fa8609b751..22ad24f8d77 100644
--- a/tests/mir-opt/nll/region_subtyping_basic.main.nll.0.64bit.mir
+++ b/tests/mir-opt/nll/region_subtyping_basic.main.nll.0.64bit.mir
@@ -22,7 +22,7 @@
 |
 fn main() -> () {
     let mut _0: ();                      // return place in scope 0 at $DIR/region_subtyping_basic.rs:+0:11: +0:11
-    let mut _1: [usize; Const(Value(Leaf(0x0000000000000003)): usize)]; // in scope 0 at $DIR/region_subtyping_basic.rs:+1:9: +1:14
+    let mut _1: [usize; Const { ty: usize, kind: Leaf(0x0000000000000003) }]; // in scope 0 at $DIR/region_subtyping_basic.rs:+1:9: +1:14
     let _3: usize;                       // in scope 0 at $DIR/region_subtyping_basic.rs:+2:16: +2:17
     let mut _4: usize;                   // in scope 0 at $DIR/region_subtyping_basic.rs:+2:14: +2:18
     let mut _5: bool;                    // in scope 0 at $DIR/region_subtyping_basic.rs:+2:14: +2:18
diff --git a/tests/mir-opt/pre-codegen/mem_replace.manual_replace.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/mem_replace.manual_replace.PreCodegen.after.mir
index 4fddd50702c..1d23871029d 100644
--- a/tests/mir-opt/pre-codegen/mem_replace.manual_replace.PreCodegen.after.mir
+++ b/tests/mir-opt/pre-codegen/mem_replace.manual_replace.PreCodegen.after.mir
@@ -4,17 +4,13 @@ fn manual_replace(_1: &mut u32, _2: u32) -> u32 {
     debug r => _1;                       // in scope 0 at $DIR/mem_replace.rs:+0:23: +0:24
     debug v => _2;                       // in scope 0 at $DIR/mem_replace.rs:+0:36: +0:37
     let mut _0: u32;                     // return place in scope 0 at $DIR/mem_replace.rs:+0:47: +0:50
-    let _3: u32;                         // in scope 0 at $DIR/mem_replace.rs:+1:9: +1:13
     scope 1 {
-        debug temp => _3;                // in scope 1 at $DIR/mem_replace.rs:+1:9: +1:13
+        debug temp => _0;                // in scope 1 at $DIR/mem_replace.rs:+1:9: +1:13
     }
 
     bb0: {
-        StorageLive(_3);                 // scope 0 at $DIR/mem_replace.rs:+1:9: +1:13
-        _3 = (*_1);                      // scope 0 at $DIR/mem_replace.rs:+1:16: +1:18
+        _0 = (*_1);                      // scope 0 at $DIR/mem_replace.rs:+1:16: +1:18
         (*_1) = _2;                      // scope 1 at $DIR/mem_replace.rs:+2:5: +2:11
-        _0 = _3;                         // scope 1 at $DIR/mem_replace.rs:+3:5: +3:9
-        StorageDead(_3);                 // scope 0 at $DIR/mem_replace.rs:+4:1: +4:2
         return;                          // scope 0 at $DIR/mem_replace.rs:+4:2: +4:2
     }
 }
diff --git a/tests/mir-opt/pre-codegen/mem_replace.mem_replace.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/mem_replace.mem_replace.PreCodegen.after.mir
index 619db12c48b..50e0538c133 100644
--- a/tests/mir-opt/pre-codegen/mem_replace.mem_replace.PreCodegen.after.mir
+++ b/tests/mir-opt/pre-codegen/mem_replace.mem_replace.PreCodegen.after.mir
@@ -7,29 +7,28 @@ fn mem_replace(_1: &mut u32, _2: u32) -> u32 {
     scope 1 (inlined std::mem::replace::<u32>) { // at $DIR/mem_replace.rs:16:5: 16:28
         debug dest => _1;                // in scope 1 at $SRC_DIR/core/src/mem/mod.rs:LL:COL
         debug src => _2;                 // in scope 1 at $SRC_DIR/core/src/mem/mod.rs:LL:COL
-        let mut _4: *const u32;          // in scope 1 at $SRC_DIR/core/src/mem/mod.rs:LL:COL
-        let mut _5: *mut u32;            // in scope 1 at $SRC_DIR/core/src/mem/mod.rs:LL:COL
+        let mut _3: *const u32;          // in scope 1 at $SRC_DIR/core/src/mem/mod.rs:LL:COL
+        let mut _4: *mut u32;            // in scope 1 at $SRC_DIR/core/src/mem/mod.rs:LL:COL
         scope 2 {
-            let _3: u32;                 // in scope 2 at $SRC_DIR/core/src/mem/mod.rs:LL:COL
             scope 3 {
-                debug result => _3;      // in scope 3 at $SRC_DIR/core/src/mem/mod.rs:LL:COL
+                debug result => _0;      // in scope 3 at $SRC_DIR/core/src/mem/mod.rs:LL:COL
                 scope 7 (inlined std::ptr::write::<u32>) { // at $SRC_DIR/core/src/mem/mod.rs:LL:COL
-                    debug dst => _5;     // in scope 7 at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
+                    debug dst => _4;     // in scope 7 at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
                     debug src => _2;     // in scope 7 at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
-                    let mut _7: *mut u32; // in scope 7 at $SRC_DIR/core/src/intrinsics.rs:LL:COL
+                    let mut _6: *mut u32; // in scope 7 at $SRC_DIR/core/src/intrinsics.rs:LL:COL
                     scope 8 {
                         scope 9 (inlined std::ptr::write::runtime::<u32>) { // at $SRC_DIR/core/src/intrinsics.rs:LL:COL
-                            debug dst => _7; // in scope 9 at $SRC_DIR/core/src/intrinsics.rs:LL:COL
+                            debug dst => _6; // in scope 9 at $SRC_DIR/core/src/intrinsics.rs:LL:COL
                         }
                     }
                 }
             }
             scope 4 (inlined std::ptr::read::<u32>) { // at $SRC_DIR/core/src/mem/mod.rs:LL:COL
-                debug src => _4;         // in scope 4 at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
-                let mut _6: *const u32;  // in scope 4 at $SRC_DIR/core/src/intrinsics.rs:LL:COL
+                debug src => _3;         // in scope 4 at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
+                let mut _5: *const u32;  // in scope 4 at $SRC_DIR/core/src/intrinsics.rs:LL:COL
                 scope 5 {
                     scope 6 (inlined std::ptr::read::runtime::<u32>) { // at $SRC_DIR/core/src/intrinsics.rs:LL:COL
-                        debug src => _6; // in scope 6 at $SRC_DIR/core/src/intrinsics.rs:LL:COL
+                        debug src => _5; // in scope 6 at $SRC_DIR/core/src/intrinsics.rs:LL:COL
                     }
                 }
             }
@@ -38,20 +37,17 @@ fn mem_replace(_1: &mut u32, _2: u32) -> u32 {
 
     bb0: {
         StorageLive(_3);                 // scope 2 at $SRC_DIR/core/src/mem/mod.rs:LL:COL
-        StorageLive(_4);                 // scope 2 at $SRC_DIR/core/src/mem/mod.rs:LL:COL
-        _4 = &raw const (*_1);           // scope 2 at $SRC_DIR/core/src/mem/mod.rs:LL:COL
-        StorageLive(_6);                 // scope 2 at $SRC_DIR/core/src/mem/mod.rs:LL:COL
-        _3 = (*_4);                      // scope 5 at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
-        StorageDead(_6);                 // scope 2 at $SRC_DIR/core/src/mem/mod.rs:LL:COL
-        StorageDead(_4);                 // scope 2 at $SRC_DIR/core/src/mem/mod.rs:LL:COL
-        StorageLive(_5);                 // scope 3 at $SRC_DIR/core/src/mem/mod.rs:LL:COL
-        _5 = &raw mut (*_1);             // scope 3 at $SRC_DIR/core/src/mem/mod.rs:LL:COL
-        StorageLive(_7);                 // scope 3 at $SRC_DIR/core/src/mem/mod.rs:LL:COL
-        (*_5) = _2;                      // scope 8 at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
-        StorageDead(_7);                 // scope 3 at $SRC_DIR/core/src/mem/mod.rs:LL:COL
-        StorageDead(_5);                 // scope 3 at $SRC_DIR/core/src/mem/mod.rs:LL:COL
-        _0 = move _3;                    // scope 3 at $SRC_DIR/core/src/mem/mod.rs:LL:COL
+        _3 = &raw const (*_1);           // scope 2 at $SRC_DIR/core/src/mem/mod.rs:LL:COL
+        StorageLive(_5);                 // scope 2 at $SRC_DIR/core/src/mem/mod.rs:LL:COL
+        _0 = (*_3);                      // scope 5 at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
+        StorageDead(_5);                 // scope 2 at $SRC_DIR/core/src/mem/mod.rs:LL:COL
         StorageDead(_3);                 // scope 2 at $SRC_DIR/core/src/mem/mod.rs:LL:COL
+        StorageLive(_4);                 // scope 3 at $SRC_DIR/core/src/mem/mod.rs:LL:COL
+        _4 = &raw mut (*_1);             // scope 3 at $SRC_DIR/core/src/mem/mod.rs:LL:COL
+        StorageLive(_6);                 // scope 3 at $SRC_DIR/core/src/mem/mod.rs:LL:COL
+        (*_4) = _2;                      // scope 8 at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
+        StorageDead(_6);                 // scope 3 at $SRC_DIR/core/src/mem/mod.rs:LL:COL
+        StorageDead(_4);                 // scope 3 at $SRC_DIR/core/src/mem/mod.rs:LL:COL
         return;                          // scope 0 at $DIR/mem_replace.rs:+2:2: +2:2
     }
 }
diff --git a/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.mir
index 7d4766ee5cc..7a10b929ebd 100644
--- a/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.mir
+++ b/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.mir
@@ -7,63 +7,62 @@ fn slice_get_unchecked_mut_range(_1: &mut [u32], _2: std::ops::Range<usize>) ->
     scope 1 (inlined core::slice::<impl [u32]>::get_unchecked_mut::<std::ops::Range<usize>>) { // at $DIR/slice_index.rs:26:11: 26:35
         debug self => _1;                // in scope 1 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
         debug index => _2;               // in scope 1 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
-        let mut _3: &mut [u32];          // in scope 1 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
+        let mut _3: *mut [u32];          // in scope 1 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
         let mut _4: *mut [u32];          // in scope 1 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
-        let mut _5: *mut [u32];          // in scope 1 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
         scope 2 {
             scope 3 (inlined <std::ops::Range<usize> as SliceIndex<[u32]>>::get_unchecked_mut) { // at $SRC_DIR/core/src/slice/mod.rs:LL:COL
                 debug self => _2;        // in scope 3 at $SRC_DIR/core/src/slice/index.rs:LL:COL
-                debug slice => _5;       // in scope 3 at $SRC_DIR/core/src/slice/index.rs:LL:COL
-                let _6: std::ops::Range<usize>; // in scope 3 at $SRC_DIR/core/src/slice/index.rs:LL:COL
+                debug slice => _4;       // in scope 3 at $SRC_DIR/core/src/slice/index.rs:LL:COL
+                let _5: std::ops::Range<usize>; // in scope 3 at $SRC_DIR/core/src/slice/index.rs:LL:COL
+                let mut _7: usize;       // in scope 3 at $SRC_DIR/core/src/slice/index.rs:LL:COL
                 let mut _8: usize;       // in scope 3 at $SRC_DIR/core/src/slice/index.rs:LL:COL
-                let mut _9: usize;       // in scope 3 at $SRC_DIR/core/src/slice/index.rs:LL:COL
+                let mut _9: *mut u32;    // in scope 3 at $SRC_DIR/core/src/slice/index.rs:LL:COL
                 let mut _10: *mut u32;   // in scope 3 at $SRC_DIR/core/src/slice/index.rs:LL:COL
-                let mut _11: *mut u32;   // in scope 3 at $SRC_DIR/core/src/slice/index.rs:LL:COL
+                let mut _11: usize;      // in scope 3 at $SRC_DIR/core/src/slice/index.rs:LL:COL
                 let mut _12: usize;      // in scope 3 at $SRC_DIR/core/src/slice/index.rs:LL:COL
-                let mut _13: usize;      // in scope 3 at $SRC_DIR/core/src/slice/index.rs:LL:COL
-                let mut _14: std::ops::Range<usize>; // in scope 3 at $SRC_DIR/core/src/intrinsics.rs:LL:COL
-                let mut _15: *mut [u32]; // in scope 3 at $SRC_DIR/core/src/intrinsics.rs:LL:COL
+                let mut _13: std::ops::Range<usize>; // in scope 3 at $SRC_DIR/core/src/intrinsics.rs:LL:COL
+                let mut _14: *mut [u32]; // in scope 3 at $SRC_DIR/core/src/intrinsics.rs:LL:COL
                 scope 4 {
-                    debug this => _6;    // in scope 4 at $SRC_DIR/core/src/slice/index.rs:LL:COL
+                    debug this => _5;    // in scope 4 at $SRC_DIR/core/src/slice/index.rs:LL:COL
                     scope 5 {
-                        let _7: usize;   // in scope 5 at $SRC_DIR/core/src/slice/index.rs:LL:COL
+                        let _6: usize;   // in scope 5 at $SRC_DIR/core/src/slice/index.rs:LL:COL
                         scope 6 {
-                            debug new_len => _7; // in scope 6 at $SRC_DIR/core/src/slice/index.rs:LL:COL
+                            debug new_len => _6; // in scope 6 at $SRC_DIR/core/src/slice/index.rs:LL:COL
                             scope 11 (inlined ptr::mut_ptr::<impl *mut [u32]>::as_mut_ptr) { // at $SRC_DIR/core/src/slice/index.rs:LL:COL
-                                debug self => _5; // in scope 11 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
+                                debug self => _4; // in scope 11 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
                             }
                             scope 12 (inlined ptr::mut_ptr::<impl *mut u32>::add) { // at $SRC_DIR/core/src/slice/index.rs:LL:COL
-                                debug self => _11; // in scope 12 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
-                                debug count => _12; // in scope 12 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
+                                debug self => _10; // in scope 12 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
+                                debug count => _11; // in scope 12 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
                                 scope 13 {
                                 }
                             }
                             scope 14 (inlined slice_from_raw_parts_mut::<u32>) { // at $SRC_DIR/core/src/slice/index.rs:LL:COL
-                                debug data => _10; // in scope 14 at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
-                                debug len => _13; // in scope 14 at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
+                                debug data => _9; // in scope 14 at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
+                                debug len => _12; // in scope 14 at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
+                                let mut _16: *mut (); // in scope 14 at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
                                 scope 15 (inlined ptr::mut_ptr::<impl *mut u32>::cast::<()>) { // at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
-                                    debug self => _10; // in scope 15 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
-                                    let mut _17: *mut (); // in scope 15 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
+                                    debug self => _9; // in scope 15 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
                                 }
                                 scope 16 (inlined std::ptr::from_raw_parts_mut::<[u32]>) { // at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
-                                    debug data_address => _17; // in scope 16 at $SRC_DIR/core/src/ptr/metadata.rs:LL:COL
-                                    debug metadata => _13; // in scope 16 at $SRC_DIR/core/src/ptr/metadata.rs:LL:COL
-                                    let mut _18: std::ptr::metadata::PtrRepr<[u32]>; // in scope 16 at $SRC_DIR/core/src/ptr/metadata.rs:LL:COL
-                                    let mut _19: std::ptr::metadata::PtrComponents<[u32]>; // in scope 16 at $SRC_DIR/core/src/ptr/metadata.rs:LL:COL
-                                    let mut _20: *const (); // in scope 16 at $SRC_DIR/core/src/ptr/metadata.rs:LL:COL
+                                    debug data_address => _16; // in scope 16 at $SRC_DIR/core/src/ptr/metadata.rs:LL:COL
+                                    debug metadata => _12; // in scope 16 at $SRC_DIR/core/src/ptr/metadata.rs:LL:COL
+                                    let mut _17: std::ptr::metadata::PtrRepr<[u32]>; // in scope 16 at $SRC_DIR/core/src/ptr/metadata.rs:LL:COL
+                                    let mut _18: std::ptr::metadata::PtrComponents<[u32]>; // in scope 16 at $SRC_DIR/core/src/ptr/metadata.rs:LL:COL
+                                    let mut _19: *const (); // in scope 16 at $SRC_DIR/core/src/ptr/metadata.rs:LL:COL
                                     scope 17 {
                                     }
                                 }
                             }
                         }
                         scope 7 (inlined <std::ops::Range<usize> as SliceIndex<[T]>>::get_unchecked_mut::runtime::<u32>) { // at $SRC_DIR/core/src/intrinsics.rs:LL:COL
-                            debug this => _14; // in scope 7 at $SRC_DIR/core/src/intrinsics.rs:LL:COL
-                            debug slice => _15; // in scope 7 at $SRC_DIR/core/src/intrinsics.rs:LL:COL
+                            debug this => _13; // in scope 7 at $SRC_DIR/core/src/intrinsics.rs:LL:COL
+                            debug slice => _14; // in scope 7 at $SRC_DIR/core/src/intrinsics.rs:LL:COL
                             scope 8 (inlined ptr::mut_ptr::<impl *mut [u32]>::len) { // at $SRC_DIR/core/src/slice/index.rs:LL:COL
-                                debug self => _15; // in scope 8 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
-                                let mut _16: *const [u32]; // in scope 8 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
+                                debug self => _14; // in scope 8 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
+                                let mut _15: *const [u32]; // in scope 8 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
                                 scope 9 (inlined std::ptr::metadata::<[u32]>) { // at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
-                                    debug ptr => _16; // in scope 9 at $SRC_DIR/core/src/ptr/metadata.rs:LL:COL
+                                    debug ptr => _15; // in scope 9 at $SRC_DIR/core/src/ptr/metadata.rs:LL:COL
                                     scope 10 {
                                     }
                                 }
@@ -76,61 +75,60 @@ fn slice_get_unchecked_mut_range(_1: &mut [u32], _2: std::ops::Range<usize>) ->
     }
 
     bb0: {
+        StorageLive(_3);                 // scope 2 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
         StorageLive(_4);                 // scope 2 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
+        _4 = &raw mut (*_1);             // scope 2 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
         StorageLive(_5);                 // scope 2 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
-        _5 = &raw mut (*_1);             // scope 2 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
-        StorageLive(_6);                 // scope 2 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
+        StorageLive(_13);                // scope 2 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
         StorageLive(_14);                // scope 2 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
         StorageLive(_15);                // scope 2 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
-        StorageLive(_16);                // scope 2 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
+        StorageLive(_6);                 // scope 5 at $SRC_DIR/core/src/slice/index.rs:LL:COL
         StorageLive(_7);                 // scope 5 at $SRC_DIR/core/src/slice/index.rs:LL:COL
+        _7 = (_2.1: usize);              // scope 5 at $SRC_DIR/core/src/slice/index.rs:LL:COL
         StorageLive(_8);                 // scope 5 at $SRC_DIR/core/src/slice/index.rs:LL:COL
-        _8 = (_2.1: usize);              // scope 5 at $SRC_DIR/core/src/slice/index.rs:LL:COL
-        StorageLive(_9);                 // scope 5 at $SRC_DIR/core/src/slice/index.rs:LL:COL
-        _9 = (_2.0: usize);              // scope 5 at $SRC_DIR/core/src/slice/index.rs:LL:COL
-        _7 = unchecked_sub::<usize>(move _8, move _9) -> [return: bb1, unwind unreachable]; // scope 5 at $SRC_DIR/core/src/slice/index.rs:LL:COL
+        _8 = (_2.0: usize);              // scope 5 at $SRC_DIR/core/src/slice/index.rs:LL:COL
+        _6 = unchecked_sub::<usize>(move _7, move _8) -> [return: bb1, unwind unreachable]; // scope 5 at $SRC_DIR/core/src/slice/index.rs:LL:COL
                                          // mir::Constant
                                          // + span: $SRC_DIR/core/src/slice/index.rs:LL:COL
                                          // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(usize, usize) -> usize {unchecked_sub::<usize>}, val: Value(<ZST>) }
     }
 
     bb1: {
-        StorageDead(_9);                 // scope 5 at $SRC_DIR/core/src/slice/index.rs:LL:COL
         StorageDead(_8);                 // scope 5 at $SRC_DIR/core/src/slice/index.rs:LL:COL
+        StorageDead(_7);                 // scope 5 at $SRC_DIR/core/src/slice/index.rs:LL:COL
+        StorageLive(_9);                 // scope 6 at $SRC_DIR/core/src/slice/index.rs:LL:COL
         StorageLive(_10);                // scope 6 at $SRC_DIR/core/src/slice/index.rs:LL:COL
+        _10 = _4 as *mut u32 (PtrToPtr); // scope 11 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
         StorageLive(_11);                // scope 6 at $SRC_DIR/core/src/slice/index.rs:LL:COL
-        _11 = _5 as *mut u32 (PtrToPtr); // scope 11 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
-        StorageLive(_12);                // scope 6 at $SRC_DIR/core/src/slice/index.rs:LL:COL
-        _12 = (_2.0: usize);             // scope 6 at $SRC_DIR/core/src/slice/index.rs:LL:COL
-        _10 = Offset(_11, _12);          // scope 13 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
-        StorageDead(_12);                // scope 6 at $SRC_DIR/core/src/slice/index.rs:LL:COL
+        _11 = (_2.0: usize);             // scope 6 at $SRC_DIR/core/src/slice/index.rs:LL:COL
+        _9 = Offset(_10, _11);           // scope 13 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
         StorageDead(_11);                // scope 6 at $SRC_DIR/core/src/slice/index.rs:LL:COL
-        StorageLive(_13);                // scope 6 at $SRC_DIR/core/src/slice/index.rs:LL:COL
-        _13 = _7;                        // scope 6 at $SRC_DIR/core/src/slice/index.rs:LL:COL
-        StorageLive(_17);                // scope 6 at $SRC_DIR/core/src/slice/index.rs:LL:COL
-        _17 = _10 as *mut () (PtrToPtr); // scope 15 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
+        StorageDead(_10);                // scope 6 at $SRC_DIR/core/src/slice/index.rs:LL:COL
+        StorageLive(_12);                // scope 6 at $SRC_DIR/core/src/slice/index.rs:LL:COL
+        _12 = _6;                        // scope 6 at $SRC_DIR/core/src/slice/index.rs:LL:COL
+        StorageLive(_16);                // scope 14 at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
+        _16 = _9 as *mut () (PtrToPtr);  // scope 15 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
+        StorageLive(_17);                // scope 17 at $SRC_DIR/core/src/ptr/metadata.rs:LL:COL
         StorageLive(_18);                // scope 17 at $SRC_DIR/core/src/ptr/metadata.rs:LL:COL
         StorageLive(_19);                // scope 17 at $SRC_DIR/core/src/ptr/metadata.rs:LL:COL
-        StorageLive(_20);                // scope 17 at $SRC_DIR/core/src/ptr/metadata.rs:LL:COL
-        _20 = _17 as *const () (Pointer(MutToConstPointer)); // scope 17 at $SRC_DIR/core/src/ptr/metadata.rs:LL:COL
-        _19 = ptr::metadata::PtrComponents::<[u32]> { data_address: move _20, metadata: _13 }; // scope 17 at $SRC_DIR/core/src/ptr/metadata.rs:LL:COL
-        StorageDead(_20);                // scope 17 at $SRC_DIR/core/src/ptr/metadata.rs:LL:COL
-        _18 = ptr::metadata::PtrRepr::<[u32]> { const_ptr: move _19 }; // scope 17 at $SRC_DIR/core/src/ptr/metadata.rs:LL:COL
+        _19 = _16 as *const () (Pointer(MutToConstPointer)); // scope 17 at $SRC_DIR/core/src/ptr/metadata.rs:LL:COL
+        _18 = ptr::metadata::PtrComponents::<[u32]> { data_address: move _19, metadata: _12 }; // scope 17 at $SRC_DIR/core/src/ptr/metadata.rs:LL:COL
         StorageDead(_19);                // scope 17 at $SRC_DIR/core/src/ptr/metadata.rs:LL:COL
-        _4 = (_18.1: *mut [u32]);        // scope 17 at $SRC_DIR/core/src/ptr/metadata.rs:LL:COL
-        StorageDead(_18);                // scope 16 at $SRC_DIR/core/src/ptr/metadata.rs:LL:COL
-        StorageDead(_17);                // scope 6 at $SRC_DIR/core/src/slice/index.rs:LL:COL
-        StorageDead(_13);                // scope 6 at $SRC_DIR/core/src/slice/index.rs:LL:COL
-        StorageDead(_10);                // scope 6 at $SRC_DIR/core/src/slice/index.rs:LL:COL
-        StorageDead(_7);                 // scope 5 at $SRC_DIR/core/src/slice/index.rs:LL:COL
-        StorageDead(_16);                // scope 2 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
+        _17 = ptr::metadata::PtrRepr::<[u32]> { const_ptr: move _18 }; // scope 17 at $SRC_DIR/core/src/ptr/metadata.rs:LL:COL
+        StorageDead(_18);                // scope 17 at $SRC_DIR/core/src/ptr/metadata.rs:LL:COL
+        _3 = (_17.1: *mut [u32]);        // scope 17 at $SRC_DIR/core/src/ptr/metadata.rs:LL:COL
+        StorageDead(_17);                // scope 16 at $SRC_DIR/core/src/ptr/metadata.rs:LL:COL
+        StorageDead(_16);                // scope 14 at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
+        StorageDead(_12);                // scope 6 at $SRC_DIR/core/src/slice/index.rs:LL:COL
+        StorageDead(_9);                 // scope 6 at $SRC_DIR/core/src/slice/index.rs:LL:COL
+        StorageDead(_6);                 // scope 5 at $SRC_DIR/core/src/slice/index.rs:LL:COL
         StorageDead(_15);                // scope 2 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
         StorageDead(_14);                // scope 2 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
-        StorageDead(_6);                 // scope 2 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
+        StorageDead(_13);                // scope 2 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
         StorageDead(_5);                 // scope 2 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
-        _3 = &mut (*_4);                 // scope 2 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
-        StorageDead(_4);                 // scope 1 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
-        _0 = _3;                         // scope 0 at $DIR/slice_index.rs:+1:5: +1:35
+        StorageDead(_4);                 // scope 2 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
+        _0 = &mut (*_3);                 // scope 2 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
+        StorageDead(_3);                 // scope 1 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
         return;                          // scope 0 at $DIR/slice_index.rs:+2:2: +2:2
     }
 }
diff --git a/tests/mir-opt/pre-codegen/slice_index.slice_index_range.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/slice_index.slice_index_range.PreCodegen.after.mir
index d3b59e265b2..dcf79a4a4e7 100644
--- a/tests/mir-opt/pre-codegen/slice_index.slice_index_range.PreCodegen.after.mir
+++ b/tests/mir-opt/pre-codegen/slice_index.slice_index_range.PreCodegen.after.mir
@@ -4,25 +4,23 @@ fn slice_index_range(_1: &[u32], _2: std::ops::Range<usize>) -> &[u32] {
     debug slice => _1;                   // in scope 0 at $DIR/slice_index.rs:+0:26: +0:31
     debug index => _2;                   // in scope 0 at $DIR/slice_index.rs:+0:41: +0:46
     let mut _0: &[u32];                  // return place in scope 0 at $DIR/slice_index.rs:+0:65: +0:71
-    let _3: &[u32];                      // in scope 0 at $DIR/slice_index.rs:+1:6: +1:18
     scope 1 (inlined #[track_caller] core::slice::index::<impl Index<std::ops::Range<usize>> for [u32]>::index) { // at $DIR/slice_index.rs:21:6: 21:18
         debug self => _1;                // in scope 1 at $SRC_DIR/core/src/slice/index.rs:LL:COL
         debug index => _2;               // in scope 1 at $SRC_DIR/core/src/slice/index.rs:LL:COL
-        let _4: &[u32];                  // in scope 1 at $SRC_DIR/core/src/slice/index.rs:LL:COL
+        let _3: &[u32];                  // in scope 1 at $SRC_DIR/core/src/slice/index.rs:LL:COL
     }
 
     bb0: {
-        StorageLive(_4);                 // scope 1 at $SRC_DIR/core/src/slice/index.rs:LL:COL
-        _4 = <std::ops::Range<usize> as SliceIndex<[u32]>>::index(move _2, _1) -> bb1; // scope 1 at $SRC_DIR/core/src/slice/index.rs:LL:COL
+        StorageLive(_3);                 // scope 1 at $SRC_DIR/core/src/slice/index.rs:LL:COL
+        _3 = <std::ops::Range<usize> as SliceIndex<[u32]>>::index(move _2, _1) -> bb1; // scope 1 at $SRC_DIR/core/src/slice/index.rs:LL:COL
                                          // mir::Constant
                                          // + span: $SRC_DIR/core/src/slice/index.rs:LL:COL
                                          // + literal: Const { ty: for<'a> fn(std::ops::Range<usize>, &'a [u32]) -> &'a <std::ops::Range<usize> as SliceIndex<[u32]>>::Output {<std::ops::Range<usize> as SliceIndex<[u32]>>::index}, val: Value(<ZST>) }
     }
 
     bb1: {
-        _3 = _4;                         // scope 1 at $SRC_DIR/core/src/slice/index.rs:LL:COL
-        StorageDead(_4);                 // scope 1 at $SRC_DIR/core/src/slice/index.rs:LL:COL
-        _0 = _3;                         // scope 0 at $DIR/slice_index.rs:+1:5: +1:18
+        _0 = _3;                         // scope 1 at $SRC_DIR/core/src/slice/index.rs:LL:COL
+        StorageDead(_3);                 // scope 1 at $SRC_DIR/core/src/slice/index.rs:LL:COL
         return;                          // scope 0 at $DIR/slice_index.rs:+2:2: +2:2
     }
 }
diff --git a/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.mir
index f27525bf3d9..0da7e5536ae 100644
--- a/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.mir
+++ b/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.mir
@@ -6,58 +6,120 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () {
     let mut _0: ();                      // return place in scope 0 at $DIR/slice_iter.rs:+0:60: +0:60
     let mut _3: std::slice::Iter<'_, T>; // in scope 0 at $DIR/slice_iter.rs:+1:14: +1:26
     let mut _4: std::slice::Iter<'_, T>; // in scope 0 at $DIR/slice_iter.rs:+1:14: +1:26
-    let mut _5: std::slice::Iter<'_, T>; // in scope 0 at $DIR/slice_iter.rs:+1:14: +1:26
-    let _6: ();                          // in scope 0 at $DIR/slice_iter.rs:+1:14: +1:26
-    let mut _7: std::option::Option<&T>; // in scope 0 at $DIR/slice_iter.rs:+1:14: +1:26
-    let mut _8: &mut std::slice::Iter<'_, T>; // in scope 0 at $DIR/slice_iter.rs:+1:14: +1:26
-    let mut _9: isize;                   // in scope 0 at $DIR/slice_iter.rs:+1:5: +3:6
-    let mut _11: &impl Fn(&T);           // in scope 0 at $DIR/slice_iter.rs:+2:9: +2:10
-    let mut _12: (&T,);                  // in scope 0 at $DIR/slice_iter.rs:+2:9: +2:13
+    let _5: ();                          // in scope 0 at $DIR/slice_iter.rs:+1:14: +1:26
+    let mut _6: std::option::Option<&T>; // in scope 0 at $DIR/slice_iter.rs:+1:14: +1:26
+    let mut _7: &mut std::slice::Iter<'_, T>; // in scope 0 at $DIR/slice_iter.rs:+1:14: +1:26
+    let mut _8: isize;                   // in scope 0 at $DIR/slice_iter.rs:+1:5: +3:6
+    let mut _10: &impl Fn(&T);           // in scope 0 at $DIR/slice_iter.rs:+2:9: +2:10
+    let mut _11: (&T,);                  // in scope 0 at $DIR/slice_iter.rs:+2:9: +2:13
     scope 1 {
-        debug iter => _5;                // in scope 1 at $DIR/slice_iter.rs:+1:14: +1:26
-        let _10: &T;                     // in scope 1 at $DIR/slice_iter.rs:+1:9: +1:10
+        debug iter => _4;                // in scope 1 at $DIR/slice_iter.rs:+1:14: +1:26
+        let _9: &T;                      // in scope 1 at $DIR/slice_iter.rs:+1:9: +1:10
         scope 2 {
-            debug x => _10;              // in scope 2 at $DIR/slice_iter.rs:+1:9: +1:10
+            debug x => _9;               // in scope 2 at $DIR/slice_iter.rs:+1:9: +1:10
         }
     }
     scope 3 (inlined core::slice::<impl [T]>::iter) { // at $DIR/slice_iter.rs:28:20: 28:26
         debug self => _1;                // in scope 3 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
+        scope 4 (inlined std::slice::Iter::<'_, T>::new) { // at $SRC_DIR/core/src/slice/mod.rs:LL:COL
+            debug slice => _1;           // in scope 4 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+            let _12: *const T;           // in scope 4 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+            let mut _14: bool;           // in scope 4 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+            let mut _15: usize;          // in scope 4 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+            let mut _16: usize;          // in scope 4 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+            let mut _17: std::ptr::NonNull<T>; // in scope 4 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+            let mut _18: *mut T;         // in scope 4 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+            let mut _19: *const T;       // in scope 4 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+            scope 5 {
+                debug ptr => _12;        // in scope 5 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+                scope 6 {
+                    let _13: *const T;   // in scope 6 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+                    scope 7 {
+                        debug end => _13; // in scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+                        scope 13 (inlined NonNull::<T>::new_unchecked) { // at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+                            debug ptr => _18; // in scope 13 at $SRC_DIR/core/src/ptr/non_null.rs:LL:COL
+                            let mut _21: *const T; // in scope 13 at $SRC_DIR/core/src/ptr/non_null.rs:LL:COL
+                            let mut _22: *mut T; // in scope 13 at $SRC_DIR/core/src/intrinsics.rs:LL:COL
+                            scope 14 {
+                                scope 15 (inlined NonNull::<T>::new_unchecked::runtime::<T>) { // at $SRC_DIR/core/src/intrinsics.rs:LL:COL
+                                    debug ptr => _22; // in scope 15 at $SRC_DIR/core/src/intrinsics.rs:LL:COL
+                                    scope 16 (inlined ptr::mut_ptr::<impl *mut T>::is_null) { // at $SRC_DIR/core/src/ptr/non_null.rs:LL:COL
+                                        debug self => _22; // in scope 16 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
+                                        let mut _23: *mut u8; // in scope 16 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
+                                        scope 17 {
+                                            scope 18 (inlined ptr::mut_ptr::<impl *mut T>::is_null::runtime_impl) { // at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
+                                                debug ptr => _23; // in scope 18 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
+                                                scope 19 (inlined ptr::mut_ptr::<impl *mut u8>::addr) { // at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
+                                                    debug self => _23; // in scope 19 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
+                                                    scope 20 {
+                                                        scope 21 (inlined ptr::mut_ptr::<impl *mut u8>::cast::<()>) { // at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
+                                                            debug self => _23; // in scope 21 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
+                                                        }
+                                                    }
+                                                }
+                                            }
+                                        }
+                                    }
+                                }
+                            }
+                        }
+                    }
+                    scope 9 (inlined invalid::<T>) { // at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+                        debug addr => _15; // in scope 9 at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
+                        scope 10 {
+                        }
+                    }
+                    scope 11 (inlined ptr::const_ptr::<impl *const T>::add) { // at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+                        debug self => _12; // in scope 11 at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+                        debug count => _16; // in scope 11 at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+                        scope 12 {
+                        }
+                    }
+                }
+            }
+            scope 8 (inlined core::slice::<impl [T]>::as_ptr) { // at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+                debug self => _1;        // in scope 8 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
+                let mut _20: *const [T]; // in scope 8 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
+            }
+        }
     }
-    scope 4 (inlined <std::slice::Iter<'_, T> as IntoIterator>::into_iter) { // at $DIR/slice_iter.rs:28:14: 28:26
-        debug self => _4;                // in scope 4 at $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
+    scope 22 (inlined <std::slice::Iter<'_, T> as IntoIterator>::into_iter) { // at $DIR/slice_iter.rs:28:14: 28:26
+        debug self => _3;                // in scope 22 at $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
     }
 
     bb0: {
-        StorageLive(_3);                 // scope 0 at $DIR/slice_iter.rs:+1:14: +1:26
-        StorageLive(_4);                 // scope 0 at $DIR/slice_iter.rs:+1:14: +1:26
-        _4 = std::slice::Iter::<'_, T>::new(_1) -> [return: bb10, unwind: bb8]; // scope 3 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
-                                         // mir::Constant
-                                         // + span: $SRC_DIR/core/src/slice/mod.rs:LL:COL
-                                         // + user_ty: UserType(0)
-                                         // + literal: Const { ty: fn(&[T]) -> std::slice::Iter<'_, T> {std::slice::Iter::<'_, T>::new}, val: Value(<ZST>) }
+        StorageLive(_12);                // scope 3 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
+        StorageLive(_20);                // scope 8 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
+        _20 = &raw const (*_1);          // scope 8 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
+        _12 = move _20 as *const T (PtrToPtr); // scope 8 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
+        StorageDead(_20);                // scope 8 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
+        StorageLive(_13);                // scope 6 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+        StorageLive(_14);                // scope 6 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+        _14 = const _;                   // scope 6 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+        switchInt(move _14) -> [0: bb11, otherwise: bb10]; // scope 6 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
     }
 
     bb1: {
-        StorageLive(_7);                 // scope 1 at $DIR/slice_iter.rs:+1:14: +1:26
-        _8 = &mut _5;                    // scope 1 at $DIR/slice_iter.rs:+1:14: +1:26
-        _7 = <std::slice::Iter<'_, T> as Iterator>::next(_8) -> [return: bb2, unwind: bb8]; // scope 1 at $DIR/slice_iter.rs:+1:14: +1:26
+        StorageLive(_6);                 // scope 1 at $DIR/slice_iter.rs:+1:14: +1:26
+        _7 = &mut _4;                    // scope 1 at $DIR/slice_iter.rs:+1:14: +1:26
+        _6 = <std::slice::Iter<'_, T> as Iterator>::next(_7) -> [return: bb2, unwind: bb8]; // scope 1 at $DIR/slice_iter.rs:+1:14: +1:26
                                          // mir::Constant
                                          // + span: $DIR/slice_iter.rs:28:14: 28:26
                                          // + literal: Const { ty: for<'a> fn(&'a mut std::slice::Iter<'_, T>) -> Option<<std::slice::Iter<'_, T> as Iterator>::Item> {<std::slice::Iter<'_, T> as Iterator>::next}, val: Value(<ZST>) }
     }
 
     bb2: {
-        _9 = discriminant(_7);           // scope 1 at $DIR/slice_iter.rs:+1:14: +1:26
-        switchInt(move _9) -> [0: bb5, 1: bb3, otherwise: bb4]; // scope 1 at $DIR/slice_iter.rs:+1:14: +1:26
+        _8 = discriminant(_6);           // scope 1 at $DIR/slice_iter.rs:+1:14: +1:26
+        switchInt(move _8) -> [0: bb5, 1: bb3, otherwise: bb4]; // scope 1 at $DIR/slice_iter.rs:+1:14: +1:26
     }
 
     bb3: {
-        _10 = ((_7 as Some).0: &T);      // scope 1 at $DIR/slice_iter.rs:+1:9: +1:10
-        StorageLive(_11);                // scope 2 at $DIR/slice_iter.rs:+2:9: +2:10
-        _11 = &_2;                       // scope 2 at $DIR/slice_iter.rs:+2:9: +2:10
-        StorageLive(_12);                // scope 2 at $DIR/slice_iter.rs:+2:9: +2:13
-        _12 = (_10,);                    // scope 2 at $DIR/slice_iter.rs:+2:9: +2:13
-        _6 = <impl Fn(&T) as Fn<(&T,)>>::call(move _11, move _12) -> [return: bb6, unwind: bb8]; // scope 2 at $DIR/slice_iter.rs:+2:9: +2:13
+        _9 = ((_6 as Some).0: &T);       // scope 1 at $DIR/slice_iter.rs:+1:9: +1:10
+        StorageLive(_10);                // scope 2 at $DIR/slice_iter.rs:+2:9: +2:10
+        _10 = &_2;                       // scope 2 at $DIR/slice_iter.rs:+2:9: +2:10
+        StorageLive(_11);                // scope 2 at $DIR/slice_iter.rs:+2:9: +2:13
+        _11 = (_9,);                     // scope 2 at $DIR/slice_iter.rs:+2:9: +2:13
+        _5 = <impl Fn(&T) as Fn<(&T,)>>::call(move _10, move _11) -> [return: bb6, unwind: bb8]; // scope 2 at $DIR/slice_iter.rs:+2:9: +2:13
                                          // mir::Constant
                                          // + span: $DIR/slice_iter.rs:29:9: 29:10
                                          // + literal: Const { ty: for<'a> extern "rust-call" fn(&'a impl Fn(&T), (&T,)) -> <impl Fn(&T) as FnOnce<(&T,)>>::Output {<impl Fn(&T) as Fn<(&T,)>>::call}, val: Value(<ZST>) }
@@ -68,16 +130,15 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () {
     }
 
     bb5: {
-        StorageDead(_7);                 // scope 1 at $DIR/slice_iter.rs:+3:5: +3:6
-        StorageDead(_5);                 // scope 0 at $DIR/slice_iter.rs:+3:5: +3:6
-        StorageDead(_3);                 // scope 0 at $DIR/slice_iter.rs:+3:5: +3:6
+        StorageDead(_6);                 // scope 1 at $DIR/slice_iter.rs:+3:5: +3:6
+        StorageDead(_4);                 // scope 0 at $DIR/slice_iter.rs:+3:5: +3:6
         drop(_2) -> bb7;                 // scope 0 at $DIR/slice_iter.rs:+4:1: +4:2
     }
 
     bb6: {
-        StorageDead(_12);                // scope 2 at $DIR/slice_iter.rs:+2:12: +2:13
         StorageDead(_11);                // scope 2 at $DIR/slice_iter.rs:+2:12: +2:13
-        StorageDead(_7);                 // scope 1 at $DIR/slice_iter.rs:+3:5: +3:6
+        StorageDead(_10);                // scope 2 at $DIR/slice_iter.rs:+2:12: +2:13
+        StorageDead(_6);                 // scope 1 at $DIR/slice_iter.rs:+3:5: +3:6
         goto -> bb1;                     // scope 1 at $DIR/slice_iter.rs:+1:5: +3:6
     }
 
@@ -94,10 +155,49 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () {
     }
 
     bb10: {
-        _3 = move _4;                    // scope 4 at $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
-        StorageDead(_4);                 // scope 0 at $DIR/slice_iter.rs:+1:25: +1:26
-        StorageLive(_5);                 // scope 0 at $DIR/slice_iter.rs:+1:14: +1:26
-        _5 = move _3;                    // scope 0 at $DIR/slice_iter.rs:+1:14: +1:26
+        StorageLive(_15);                // scope 6 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+        _15 = Len((*_1));                // scope 6 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+        _13 = _15 as *const T (Transmute); // scope 10 at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
+        StorageDead(_15);                // scope 6 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+        goto -> bb12;                    // scope 6 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+    }
+
+    bb11: {
+        StorageLive(_16);                // scope 6 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+        _16 = Len((*_1));                // scope 6 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+        _13 = Offset(_12, _16);          // scope 12 at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+        StorageDead(_16);                // scope 6 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+        goto -> bb12;                    // scope 6 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+    }
+
+    bb12: {
+        StorageDead(_14);                // scope 6 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+        StorageLive(_17);                // scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+        StorageLive(_18);                // scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+        _18 = _12 as *mut T (PtrToPtr);  // scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+        StorageLive(_21);                // scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+        StorageLive(_22);                // scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+        StorageLive(_23);                // scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+        _21 = _18 as *const T (Pointer(MutToConstPointer)); // scope 14 at $SRC_DIR/core/src/ptr/non_null.rs:LL:COL
+        _17 = NonNull::<T> { pointer: _21 }; // scope 14 at $SRC_DIR/core/src/ptr/non_null.rs:LL:COL
+        StorageDead(_23);                // scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+        StorageDead(_22);                // scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+        StorageDead(_21);                // scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+        StorageDead(_18);                // scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+        StorageLive(_19);                // scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+        _19 = _13;                       // scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+        _3 = std::slice::Iter::<'_, T> { ptr: move _17, end: move _19, _marker: const ZeroSized: PhantomData<&T> }; // scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+                                         // mir::Constant
+                                         // + span: no-location
+                                         // + literal: Const { ty: PhantomData<&T>, val: Value(<ZST>) }
+                                         // adt
+                                         // + user_ty: UserType(1)
+        StorageDead(_19);                // scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+        StorageDead(_17);                // scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+        StorageDead(_13);                // scope 6 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+        StorageDead(_12);                // scope 3 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
+        StorageLive(_4);                 // scope 0 at $DIR/slice_iter.rs:+1:14: +1:26
+        _4 = move _3;                    // scope 0 at $DIR/slice_iter.rs:+1:14: +1:26
         goto -> bb1;                     // scope 1 at $DIR/slice_iter.rs:+1:5: +3:6
     }
 }
diff --git a/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.mir
index 62dd9667d96..45b41b54c8b 100644
--- a/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.mir
+++ b/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.mir
@@ -19,39 +19,104 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () {
         scope 2 {
             debug x => _10;              // in scope 2 at $DIR/slice_iter.rs:+1:9: +1:10
         }
-        scope 7 (inlined <Rev<std::slice::Iter<'_, T>> as Iterator>::next) { // at $DIR/slice_iter.rs:35:14: 35:32
-            debug self => _8;            // in scope 7 at $SRC_DIR/core/src/iter/adapters/rev.rs:LL:COL
-            let mut _13: &mut std::slice::Iter<'_, T>; // in scope 7 at $SRC_DIR/core/src/iter/adapters/rev.rs:LL:COL
+        scope 25 (inlined <Rev<std::slice::Iter<'_, T>> as Iterator>::next) { // at $DIR/slice_iter.rs:35:14: 35:32
+            debug self => _8;            // in scope 25 at $SRC_DIR/core/src/iter/adapters/rev.rs:LL:COL
+            let mut _25: &mut std::slice::Iter<'_, T>; // in scope 25 at $SRC_DIR/core/src/iter/adapters/rev.rs:LL:COL
         }
     }
     scope 3 (inlined core::slice::<impl [T]>::iter) { // at $DIR/slice_iter.rs:35:20: 35:26
         debug self => _1;                // in scope 3 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
+        scope 4 (inlined std::slice::Iter::<'_, T>::new) { // at $SRC_DIR/core/src/slice/mod.rs:LL:COL
+            debug slice => _1;           // in scope 4 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+            let _13: *const T;           // in scope 4 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+            let mut _15: bool;           // in scope 4 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+            let mut _16: usize;          // in scope 4 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+            let mut _17: usize;          // in scope 4 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+            let mut _18: std::ptr::NonNull<T>; // in scope 4 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+            let mut _19: *mut T;         // in scope 4 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+            let mut _20: *const T;       // in scope 4 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+            scope 5 {
+                debug ptr => _13;        // in scope 5 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+                scope 6 {
+                    let _14: *const T;   // in scope 6 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+                    scope 7 {
+                        debug end => _14; // in scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+                        scope 13 (inlined NonNull::<T>::new_unchecked) { // at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+                            debug ptr => _19; // in scope 13 at $SRC_DIR/core/src/ptr/non_null.rs:LL:COL
+                            let mut _22: *const T; // in scope 13 at $SRC_DIR/core/src/ptr/non_null.rs:LL:COL
+                            let mut _23: *mut T; // in scope 13 at $SRC_DIR/core/src/intrinsics.rs:LL:COL
+                            scope 14 {
+                                scope 15 (inlined NonNull::<T>::new_unchecked::runtime::<T>) { // at $SRC_DIR/core/src/intrinsics.rs:LL:COL
+                                    debug ptr => _23; // in scope 15 at $SRC_DIR/core/src/intrinsics.rs:LL:COL
+                                    scope 16 (inlined ptr::mut_ptr::<impl *mut T>::is_null) { // at $SRC_DIR/core/src/ptr/non_null.rs:LL:COL
+                                        debug self => _23; // in scope 16 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
+                                        let mut _24: *mut u8; // in scope 16 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
+                                        scope 17 {
+                                            scope 18 (inlined ptr::mut_ptr::<impl *mut T>::is_null::runtime_impl) { // at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
+                                                debug ptr => _24; // in scope 18 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
+                                                scope 19 (inlined ptr::mut_ptr::<impl *mut u8>::addr) { // at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
+                                                    debug self => _24; // in scope 19 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
+                                                    scope 20 {
+                                                        scope 21 (inlined ptr::mut_ptr::<impl *mut u8>::cast::<()>) { // at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
+                                                            debug self => _24; // in scope 21 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
+                                                        }
+                                                    }
+                                                }
+                                            }
+                                        }
+                                    }
+                                }
+                            }
+                        }
+                    }
+                    scope 9 (inlined invalid::<T>) { // at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+                        debug addr => _16; // in scope 9 at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
+                        scope 10 {
+                        }
+                    }
+                    scope 11 (inlined ptr::const_ptr::<impl *const T>::add) { // at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+                        debug self => _13; // in scope 11 at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+                        debug count => _17; // in scope 11 at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+                        scope 12 {
+                        }
+                    }
+                }
+            }
+            scope 8 (inlined core::slice::<impl [T]>::as_ptr) { // at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+                debug self => _1;        // in scope 8 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
+                let mut _21: *const [T]; // in scope 8 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
+            }
+        }
     }
-    scope 4 (inlined <std::slice::Iter<'_, T> as Iterator>::rev) { // at $DIR/slice_iter.rs:35:27: 35:32
-        debug self => _4;                // in scope 4 at $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
-        scope 5 (inlined Rev::<std::slice::Iter<'_, T>>::new) { // at $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
-            debug iter => _4;            // in scope 5 at $SRC_DIR/core/src/iter/adapters/rev.rs:LL:COL
+    scope 22 (inlined <std::slice::Iter<'_, T> as Iterator>::rev) { // at $DIR/slice_iter.rs:35:27: 35:32
+        debug self => _4;                // in scope 22 at $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
+        scope 23 (inlined Rev::<std::slice::Iter<'_, T>>::new) { // at $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
+            debug iter => _4;            // in scope 23 at $SRC_DIR/core/src/iter/adapters/rev.rs:LL:COL
         }
     }
-    scope 6 (inlined <Rev<std::slice::Iter<'_, T>> as IntoIterator>::into_iter) { // at $DIR/slice_iter.rs:35:14: 35:32
-        debug self => _3;                // in scope 6 at $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
+    scope 24 (inlined <Rev<std::slice::Iter<'_, T>> as IntoIterator>::into_iter) { // at $DIR/slice_iter.rs:35:14: 35:32
+        debug self => _3;                // in scope 24 at $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
     }
 
     bb0: {
         StorageLive(_4);                 // scope 0 at $DIR/slice_iter.rs:+1:14: +1:26
-        _4 = std::slice::Iter::<'_, T>::new(_1) -> [return: bb9, unwind: bb7]; // scope 3 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
-                                         // mir::Constant
-                                         // + span: $SRC_DIR/core/src/slice/mod.rs:LL:COL
-                                         // + user_ty: UserType(0)
-                                         // + literal: Const { ty: fn(&[T]) -> std::slice::Iter<'_, T> {std::slice::Iter::<'_, T>::new}, val: Value(<ZST>) }
+        StorageLive(_13);                // scope 3 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
+        StorageLive(_21);                // scope 8 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
+        _21 = &raw const (*_1);          // scope 8 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
+        _13 = move _21 as *const T (PtrToPtr); // scope 8 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
+        StorageDead(_21);                // scope 8 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
+        StorageLive(_14);                // scope 6 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+        StorageLive(_15);                // scope 6 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+        _15 = const _;                   // scope 6 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+        switchInt(move _15) -> [0: bb10, otherwise: bb9]; // scope 6 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
     }
 
     bb1: {
         StorageLive(_7);                 // scope 1 at $DIR/slice_iter.rs:+1:14: +1:32
         _8 = &mut _5;                    // scope 1 at $DIR/slice_iter.rs:+1:14: +1:32
-        StorageLive(_13);                // scope 7 at $SRC_DIR/core/src/iter/adapters/rev.rs:LL:COL
-        _13 = &mut ((*_8).0: std::slice::Iter<'_, T>); // scope 7 at $SRC_DIR/core/src/iter/adapters/rev.rs:LL:COL
-        _7 = <std::slice::Iter<'_, T> as DoubleEndedIterator>::next_back(move _13) -> [return: bb10, unwind: bb7]; // scope 7 at $SRC_DIR/core/src/iter/adapters/rev.rs:LL:COL
+        StorageLive(_25);                // scope 25 at $SRC_DIR/core/src/iter/adapters/rev.rs:LL:COL
+        _25 = &mut ((*_8).0: std::slice::Iter<'_, T>); // scope 25 at $SRC_DIR/core/src/iter/adapters/rev.rs:LL:COL
+        _7 = <std::slice::Iter<'_, T> as DoubleEndedIterator>::next_back(move _25) -> [return: bb12, unwind: bb7]; // scope 25 at $SRC_DIR/core/src/iter/adapters/rev.rs:LL:COL
                                          // mir::Constant
                                          // + span: $SRC_DIR/core/src/iter/adapters/rev.rs:LL:COL
                                          // + literal: Const { ty: for<'a> fn(&'a mut std::slice::Iter<'_, T>) -> Option<<std::slice::Iter<'_, T> as Iterator>::Item> {<std::slice::Iter<'_, T> as DoubleEndedIterator>::next_back}, val: Value(<ZST>) }
@@ -99,15 +164,56 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () {
     }
 
     bb9: {
-        _3 = Rev::<std::slice::Iter<'_, T>> { iter: move _4 }; // scope 5 at $SRC_DIR/core/src/iter/adapters/rev.rs:LL:COL
+        StorageLive(_16);                // scope 6 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+        _16 = Len((*_1));                // scope 6 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+        _14 = _16 as *const T (Transmute); // scope 10 at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
+        StorageDead(_16);                // scope 6 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+        goto -> bb11;                    // scope 6 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+    }
+
+    bb10: {
+        StorageLive(_17);                // scope 6 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+        _17 = Len((*_1));                // scope 6 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+        _14 = Offset(_13, _17);          // scope 12 at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+        StorageDead(_17);                // scope 6 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+        goto -> bb11;                    // scope 6 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+    }
+
+    bb11: {
+        StorageDead(_15);                // scope 6 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+        StorageLive(_18);                // scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+        StorageLive(_19);                // scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+        _19 = _13 as *mut T (PtrToPtr);  // scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+        StorageLive(_22);                // scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+        StorageLive(_23);                // scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+        StorageLive(_24);                // scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+        _22 = _19 as *const T (Pointer(MutToConstPointer)); // scope 14 at $SRC_DIR/core/src/ptr/non_null.rs:LL:COL
+        _18 = NonNull::<T> { pointer: _22 }; // scope 14 at $SRC_DIR/core/src/ptr/non_null.rs:LL:COL
+        StorageDead(_24);                // scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+        StorageDead(_23);                // scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+        StorageDead(_22);                // scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+        StorageDead(_19);                // scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+        StorageLive(_20);                // scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+        _20 = _14;                       // scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+        _4 = std::slice::Iter::<'_, T> { ptr: move _18, end: move _20, _marker: const ZeroSized: PhantomData<&T> }; // scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+                                         // mir::Constant
+                                         // + span: no-location
+                                         // + literal: Const { ty: PhantomData<&T>, val: Value(<ZST>) }
+                                         // adt
+                                         // + user_ty: UserType(1)
+        StorageDead(_20);                // scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+        StorageDead(_18);                // scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+        StorageDead(_14);                // scope 6 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+        StorageDead(_13);                // scope 3 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
+        _3 = Rev::<std::slice::Iter<'_, T>> { iter: move _4 }; // scope 23 at $SRC_DIR/core/src/iter/adapters/rev.rs:LL:COL
         StorageDead(_4);                 // scope 0 at $DIR/slice_iter.rs:+1:31: +1:32
         StorageLive(_5);                 // scope 0 at $DIR/slice_iter.rs:+1:14: +1:32
         _5 = move _3;                    // scope 0 at $DIR/slice_iter.rs:+1:14: +1:32
         goto -> bb1;                     // scope 1 at $DIR/slice_iter.rs:+1:5: +3:6
     }
 
-    bb10: {
-        StorageDead(_13);                // scope 7 at $SRC_DIR/core/src/iter/adapters/rev.rs:LL:COL
+    bb12: {
+        StorageDead(_25);                // scope 25 at $SRC_DIR/core/src/iter/adapters/rev.rs:LL:COL
         _9 = discriminant(_7);           // scope 1 at $DIR/slice_iter.rs:+1:14: +1:32
         switchInt(move _9) -> [0: bb4, 1: bb2, otherwise: bb3]; // scope 1 at $DIR/slice_iter.rs:+1:14: +1:32
     }
diff --git a/tests/mir-opt/reference_prop.debuginfo.ReferencePropagation.diff b/tests/mir-opt/reference_prop.debuginfo.ReferencePropagation.diff
new file mode 100644
index 00000000000..07bd48fc846
--- /dev/null
+++ b/tests/mir-opt/reference_prop.debuginfo.ReferencePropagation.diff
@@ -0,0 +1,175 @@
+- // MIR for `debuginfo` before ReferencePropagation
++ // MIR for `debuginfo` after ReferencePropagation
+  
+  fn debuginfo() -> () {
+      let mut _0: ();                      // return place in scope 0 at $DIR/reference_prop.rs:+0:16: +0:16
+      let _1: &mut u8;                     // in scope 0 at $DIR/reference_prop.rs:+3:9: +3:19
+      let mut _2: u8;                      // in scope 0 at $DIR/reference_prop.rs:+3:27: +3:31
+      let _4: debuginfo::T;                // in scope 0 at $DIR/reference_prop.rs:+4:18: +4:22
+      let _6: ();                          // in scope 0 at $DIR/reference_prop.rs:+9:5: +12:6
+      let mut _7: std::option::Option<i32>; // in scope 0 at $DIR/reference_prop.rs:+9:11: +9:18
+      let mut _8: isize;                   // in scope 0 at $DIR/reference_prop.rs:+10:9: +10:13
+      let _10: ();                         // in scope 0 at $DIR/reference_prop.rs:+16:5: +17:6
+      let mut _11: &[i32];                 // in scope 0 at $DIR/reference_prop.rs:+16:82: +16:94
+      let _12: &[i32];                     // in scope 0 at $DIR/reference_prop.rs:+16:83: +16:94
+      let mut _13: &[i32; 10];             // in scope 0 at $DIR/reference_prop.rs:+16:83: +16:90
+      let _14: [i32; 10];                  // in scope 0 at $DIR/reference_prop.rs:+16:83: +16:90
+      let mut _15: std::ops::RangeFull;    // in scope 0 at $DIR/reference_prop.rs:+16:91: +16:93
+      let mut _16: usize;                  // in scope 0 at $DIR/reference_prop.rs:+16:12: +16:79
+      let mut _17: usize;                  // in scope 0 at $DIR/reference_prop.rs:+16:12: +16:79
+      let mut _18: bool;                   // in scope 0 at $DIR/reference_prop.rs:+16:12: +16:79
+      let _23: &&mut u8;                   // in scope 0 at $DIR/reference_prop.rs:+19:28: +19:40
+      let _24: &mut u8;                    // in scope 0 at $DIR/reference_prop.rs:+19:29: +19:40
+      let mut _25: debuginfo::T;           // in scope 0 at $DIR/reference_prop.rs:+19:34: +19:38
+      scope 1 {
+-         debug ref_mut_u8 => _1;          // in scope 1 at $DIR/reference_prop.rs:+3:9: +3:19
++         debug ref_mut_u8 => &_2;         // in scope 1 at $DIR/reference_prop.rs:+3:9: +3:19
+          let _3: &u8;                     // in scope 1 at $DIR/reference_prop.rs:+4:9: +4:14
+          let mut _28: &debuginfo::T;      // in scope 1 at $DIR/reference_prop.rs:+4:17: +4:24
+          scope 2 {
+-             debug field => _3;           // in scope 2 at $DIR/reference_prop.rs:+4:9: +4:14
++             debug field => &((*_28).0: u8); // in scope 2 at $DIR/reference_prop.rs:+4:9: +4:14
+              let _5: &u8;                 // in scope 2 at $DIR/reference_prop.rs:+7:9: +7:17
+              scope 3 {
+-                 debug reborrow => _5;    // in scope 3 at $DIR/reference_prop.rs:+7:9: +7:17
++                 debug reborrow => &_2;   // in scope 3 at $DIR/reference_prop.rs:+7:9: +7:17
+                  let _9: &i32;            // in scope 3 at $DIR/reference_prop.rs:+11:14: +11:31
+                  let _22: &&&mut u8;      // in scope 3 at $DIR/reference_prop.rs:+19:9: +19:24
+                  let mut _27: &std::option::Option<i32>; // in scope 3 at $DIR/reference_prop.rs:+11:14: +11:31
+                  scope 4 {
+-                     debug variant_field => _9; // in scope 4 at $DIR/reference_prop.rs:+11:14: +11:31
++                     debug variant_field => &(((*_27) as Some).0: i32); // in scope 4 at $DIR/reference_prop.rs:+11:14: +11:31
+                  }
+                  scope 5 {
+-                     debug constant_index => _19; // in scope 5 at $DIR/reference_prop.rs:+16:16: +16:34
++                     debug constant_index => &(*_11)[1 of 3]; // in scope 5 at $DIR/reference_prop.rs:+16:16: +16:34
+                      debug subslice => _20; // in scope 5 at $DIR/reference_prop.rs:+16:36: +16:44
+                      debug constant_index_from_end => _21; // in scope 5 at $DIR/reference_prop.rs:+16:51: +16:78
+                      let _19: &i32;       // in scope 5 at $DIR/reference_prop.rs:+16:16: +16:34
+                      let _20: &[i32];     // in scope 5 at $DIR/reference_prop.rs:+16:36: +16:44
+                      let _21: &i32;       // in scope 5 at $DIR/reference_prop.rs:+16:51: +16:78
+                      let mut _26: &[i32; 10]; // in scope 5 at $DIR/reference_prop.rs:+16:83: +16:90
+                  }
+                  scope 6 {
+-                     debug multiple_borrow => _22; // in scope 6 at $DIR/reference_prop.rs:+19:9: +19:24
++                     debug multiple_borrow => &&&(_25.0: u8); // in scope 6 at $DIR/reference_prop.rs:+19:9: +19:24
+                  }
+              }
+          }
+      }
+  
+      bb0: {
+-         StorageLive(_1);                 // scope 0 at $DIR/reference_prop.rs:+3:9: +3:19
+          StorageLive(_2);                 // scope 0 at $DIR/reference_prop.rs:+3:27: +3:31
+          _2 = const 5_u8;                 // scope 0 at $DIR/reference_prop.rs:+3:27: +3:31
+-         _1 = &mut _2;                    // scope 0 at $DIR/reference_prop.rs:+3:22: +3:31
+-         StorageLive(_3);                 // scope 1 at $DIR/reference_prop.rs:+4:9: +4:14
+          _28 = const _;                   // scope 1 at $DIR/reference_prop.rs:+4:17: +4:24
+                                           // mir::Constant
+                                           // + span: $DIR/reference_prop.rs:535:17: 535:24
+                                           // + literal: Const { ty: &T, val: Unevaluated(debuginfo, [], Some(promoted[2])) }
+-         _3 = &((*_28).0: u8);            // scope 1 at $DIR/reference_prop.rs:+4:17: +4:24
+-         StorageLive(_5);                 // scope 2 at $DIR/reference_prop.rs:+7:9: +7:17
+-         _5 = &(*_1);                     // scope 2 at $DIR/reference_prop.rs:+7:20: +7:32
+-         StorageLive(_6);                 // scope 3 at $DIR/reference_prop.rs:+9:5: +12:6
+          StorageLive(_7);                 // scope 3 at $DIR/reference_prop.rs:+9:11: +9:18
+          _7 = Option::<i32>::Some(const 0_i32); // scope 3 at $DIR/reference_prop.rs:+9:11: +9:18
+          _8 = discriminant(_7);           // scope 3 at $DIR/reference_prop.rs:+9:11: +9:18
+          switchInt(move _8) -> [0: bb3, 1: bb1, otherwise: bb2]; // scope 3 at $DIR/reference_prop.rs:+9:5: +9:18
+      }
+  
+      bb1: {
+-         StorageLive(_9);                 // scope 3 at $DIR/reference_prop.rs:+11:14: +11:31
+          _27 = const _;                   // scope 3 at $DIR/reference_prop.rs:+11:14: +11:31
+                                           // mir::Constant
+                                           // + span: $DIR/reference_prop.rs:542:14: 542:31
+                                           // + literal: Const { ty: &Option<i32>, val: Unevaluated(debuginfo, [], Some(promoted[1])) }
+-         _9 = &(((*_27) as Some).0: i32); // scope 3 at $DIR/reference_prop.rs:+11:14: +11:31
+-         _6 = const ();                   // scope 4 at $DIR/reference_prop.rs:+11:36: +11:38
+-         StorageDead(_9);                 // scope 3 at $DIR/reference_prop.rs:+11:37: +11:38
+          goto -> bb4;                     // scope 3 at $DIR/reference_prop.rs:+11:37: +11:38
+      }
+  
+      bb2: {
+          unreachable;                     // scope 3 at $DIR/reference_prop.rs:+9:11: +9:18
+      }
+  
+      bb3: {
+-         _6 = const ();                   // scope 3 at $DIR/reference_prop.rs:+10:17: +10:19
+          goto -> bb4;                     // scope 3 at $DIR/reference_prop.rs:+10:17: +10:19
+      }
+  
+      bb4: {
+          StorageDead(_7);                 // scope 3 at $DIR/reference_prop.rs:+12:5: +12:6
+-         StorageDead(_6);                 // scope 3 at $DIR/reference_prop.rs:+12:5: +12:6
+-         StorageLive(_10);                // scope 3 at $DIR/reference_prop.rs:+16:5: +17:6
+          StorageLive(_11);                // scope 5 at $DIR/reference_prop.rs:+16:82: +16:94
+          StorageLive(_12);                // scope 5 at $DIR/reference_prop.rs:+16:83: +16:94
+          StorageLive(_13);                // scope 5 at $DIR/reference_prop.rs:+16:83: +16:90
+          _26 = const _;                   // scope 5 at $DIR/reference_prop.rs:+16:83: +16:90
+                                           // mir::Constant
+                                           // + span: $DIR/reference_prop.rs:547:83: 547:90
+                                           // + literal: Const { ty: &[i32; 10], val: Unevaluated(debuginfo, [], Some(promoted[0])) }
+          _13 = &(*_26);                   // scope 5 at $DIR/reference_prop.rs:+16:83: +16:90
+          StorageLive(_15);                // scope 5 at $DIR/reference_prop.rs:+16:91: +16:93
+          _15 = RangeFull;                 // scope 5 at $DIR/reference_prop.rs:+16:91: +16:93
+          _12 = <[i32; 10] as Index<RangeFull>>::index(move _13, move _15) -> bb5; // scope 5 at $DIR/reference_prop.rs:+16:83: +16:94
+                                           // mir::Constant
+                                           // + span: $DIR/reference_prop.rs:547:83: 547:94
+                                           // + literal: Const { ty: for<'a> fn(&'a [i32; 10], RangeFull) -> &'a <[i32; 10] as Index<RangeFull>>::Output {<[i32; 10] as Index<RangeFull>>::index}, val: Value(<ZST>) }
+      }
+  
+      bb5: {
+          StorageDead(_15);                // scope 5 at $DIR/reference_prop.rs:+16:93: +16:94
+          StorageDead(_13);                // scope 5 at $DIR/reference_prop.rs:+16:93: +16:94
+          _11 = &(*_12);                   // scope 5 at $DIR/reference_prop.rs:+16:82: +16:94
+          _16 = Len((*_11));               // scope 5 at $DIR/reference_prop.rs:+16:12: +16:79
+          _17 = const 3_usize;             // scope 5 at $DIR/reference_prop.rs:+16:12: +16:79
+          _18 = Ge(move _16, move _17);    // scope 5 at $DIR/reference_prop.rs:+16:12: +16:79
+          switchInt(move _18) -> [0: bb7, otherwise: bb6]; // scope 5 at $DIR/reference_prop.rs:+16:12: +16:79
+      }
+  
+      bb6: {
+-         StorageLive(_19);                // scope 5 at $DIR/reference_prop.rs:+16:16: +16:34
+-         _19 = &(*_11)[1 of 3];           // scope 5 at $DIR/reference_prop.rs:+16:16: +16:34
+          StorageLive(_20);                // scope 5 at $DIR/reference_prop.rs:+16:36: +16:44
+          _20 = &(*_11)[2:-1];             // scope 5 at $DIR/reference_prop.rs:+16:36: +16:44
+          StorageLive(_21);                // scope 5 at $DIR/reference_prop.rs:+16:51: +16:78
+          _21 = &(*_11)[-1 of 3];          // scope 5 at $DIR/reference_prop.rs:+16:51: +16:78
+-         _10 = const ();                  // scope 5 at $DIR/reference_prop.rs:+16:95: +17:6
+          StorageDead(_21);                // scope 3 at $DIR/reference_prop.rs:+17:5: +17:6
+          StorageDead(_20);                // scope 3 at $DIR/reference_prop.rs:+17:5: +17:6
+-         StorageDead(_19);                // scope 3 at $DIR/reference_prop.rs:+17:5: +17:6
+          goto -> bb8;                     // scope 3 at $DIR/reference_prop.rs:+16:5: +17:6
+      }
+  
+      bb7: {
+-         _10 = const ();                  // scope 3 at $DIR/reference_prop.rs:+17:6: +17:6
+          goto -> bb8;                     // scope 3 at $DIR/reference_prop.rs:+16:5: +17:6
+      }
+  
+      bb8: {
+          StorageDead(_12);                // scope 3 at $DIR/reference_prop.rs:+17:5: +17:6
+          StorageDead(_11);                // scope 3 at $DIR/reference_prop.rs:+17:5: +17:6
+-         StorageDead(_10);                // scope 3 at $DIR/reference_prop.rs:+17:5: +17:6
+-         StorageLive(_22);                // scope 3 at $DIR/reference_prop.rs:+19:9: +19:24
+-         StorageLive(_23);                // scope 3 at $DIR/reference_prop.rs:+19:28: +19:40
+-         StorageLive(_24);                // scope 3 at $DIR/reference_prop.rs:+19:29: +19:40
+          StorageLive(_25);                // scope 3 at $DIR/reference_prop.rs:+19:34: +19:38
+          _25 = T(const 6_u8);             // scope 3 at $DIR/reference_prop.rs:+19:34: +19:38
+-         _24 = &mut (_25.0: u8);          // scope 3 at $DIR/reference_prop.rs:+19:29: +19:40
+-         _23 = &_24;                      // scope 3 at $DIR/reference_prop.rs:+19:28: +19:40
+-         _22 = &_23;                      // scope 3 at $DIR/reference_prop.rs:+19:27: +19:40
+          _0 = const ();                   // scope 0 at $DIR/reference_prop.rs:+0:16: +20:2
+          StorageDead(_25);                // scope 3 at $DIR/reference_prop.rs:+20:1: +20:2
+-         StorageDead(_24);                // scope 3 at $DIR/reference_prop.rs:+20:1: +20:2
+-         StorageDead(_23);                // scope 3 at $DIR/reference_prop.rs:+20:1: +20:2
+-         StorageDead(_22);                // scope 3 at $DIR/reference_prop.rs:+20:1: +20:2
+-         StorageDead(_5);                 // scope 2 at $DIR/reference_prop.rs:+20:1: +20:2
+-         StorageDead(_3);                 // scope 1 at $DIR/reference_prop.rs:+20:1: +20:2
+          StorageDead(_2);                 // scope 0 at $DIR/reference_prop.rs:+20:1: +20:2
+-         StorageDead(_1);                 // scope 0 at $DIR/reference_prop.rs:+20:1: +20:2
+          return;                          // scope 0 at $DIR/reference_prop.rs:+20:2: +20:2
+      }
+  }
+  
diff --git a/tests/mir-opt/reference_prop.dominate_storage.ReferencePropagation.diff b/tests/mir-opt/reference_prop.dominate_storage.ReferencePropagation.diff
index 8edc83cbf67..e158f64e9c3 100644
--- a/tests/mir-opt/reference_prop.dominate_storage.ReferencePropagation.diff
+++ b/tests/mir-opt/reference_prop.dominate_storage.ReferencePropagation.diff
@@ -24,7 +24,7 @@
           _5 = (*_2);                      // scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL
           _0 = opaque::<i32>(_5) -> bb3;   // scope 0 at $DIR/reference_prop.rs:+16:13: +16:38
                                            // mir::Constant
-                                           // + span: $DIR/reference_prop.rs:383:28: 383:34
+                                           // + span: $DIR/reference_prop.rs:455:28: 455:34
                                            // + literal: Const { ty: fn(i32) {opaque::<i32>}, val: Value(<ZST>) }
       }
   
diff --git a/tests/mir-opt/reference_prop.maybe_dead.ReferencePropagation.diff b/tests/mir-opt/reference_prop.maybe_dead.ReferencePropagation.diff
index 920755bdd1d..38ab16cedb7 100644
--- a/tests/mir-opt/reference_prop.maybe_dead.ReferencePropagation.diff
+++ b/tests/mir-opt/reference_prop.maybe_dead.ReferencePropagation.diff
@@ -29,7 +29,7 @@
           StorageDead(_3);                 // scope 0 at $DIR/reference_prop.rs:+21:13: +21:27
           _0 = opaque::<i32>(_6) -> bb2;   // scope 0 at $DIR/reference_prop.rs:+22:13: +22:38
                                            // mir::Constant
-                                           // + span: $DIR/reference_prop.rs:417:28: 417:34
+                                           // + span: $DIR/reference_prop.rs:489:28: 489:34
                                            // + literal: Const { ty: fn(i32) {opaque::<i32>}, val: Value(<ZST>) }
       }
   
@@ -37,7 +37,7 @@
           _7 = (*_4);                      // scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL
           _0 = opaque::<i32>(_7) -> bb3;   // scope 0 at $DIR/reference_prop.rs:+27:13: +27:38
                                            // mir::Constant
-                                           // + span: $DIR/reference_prop.rs:422:28: 422:34
+                                           // + span: $DIR/reference_prop.rs:494:28: 494:34
                                            // + literal: Const { ty: fn(i32) {opaque::<i32>}, val: Value(<ZST>) }
       }
   
@@ -45,7 +45,7 @@
           _8 = (*_5);                      // scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL
           _0 = opaque::<i32>(_8) -> bb4;   // scope 0 at $DIR/reference_prop.rs:+33:13: +33:43
                                            // mir::Constant
-                                           // + span: $DIR/reference_prop.rs:428:33: 428:39
+                                           // + span: $DIR/reference_prop.rs:500:33: 500:39
                                            // + literal: Const { ty: fn(i32) {opaque::<i32>}, val: Value(<ZST>) }
       }
   
diff --git a/tests/mir-opt/reference_prop.multiple_storage.ReferencePropagation.diff b/tests/mir-opt/reference_prop.multiple_storage.ReferencePropagation.diff
index 07bfdf0b2f1..6e451786870 100644
--- a/tests/mir-opt/reference_prop.multiple_storage.ReferencePropagation.diff
+++ b/tests/mir-opt/reference_prop.multiple_storage.ReferencePropagation.diff
@@ -16,7 +16,7 @@
           _3 = (*_2);                      // scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL
           _0 = opaque::<i32>(_3) -> bb1;   // scope 0 at $DIR/reference_prop.rs:+14:13: +14:43
                                            // mir::Constant
-                                           // + span: $DIR/reference_prop.rs:357:33: 357:39
+                                           // + span: $DIR/reference_prop.rs:429:33: 429:39
                                            // + literal: Const { ty: fn(i32) {opaque::<i32>}, val: Value(<ZST>) }
       }
   
diff --git a/tests/mir-opt/reference_prop.mut_raw_then_mut_shr.ReferencePropagation.diff b/tests/mir-opt/reference_prop.mut_raw_then_mut_shr.ReferencePropagation.diff
index af8ee2411d3..d99e110359f 100644
--- a/tests/mir-opt/reference_prop.mut_raw_then_mut_shr.ReferencePropagation.diff
+++ b/tests/mir-opt/reference_prop.mut_raw_then_mut_shr.ReferencePropagation.diff
@@ -13,13 +13,16 @@
           debug x => _1;                   // in scope 1 at $DIR/reference_prop.rs:+1:9: +1:14
           let _2: &mut i32;                // in scope 1 at $DIR/reference_prop.rs:+2:9: +2:13
           scope 2 {
-              debug xref => _2;            // in scope 2 at $DIR/reference_prop.rs:+2:9: +2:13
+-             debug xref => _2;            // in scope 2 at $DIR/reference_prop.rs:+2:9: +2:13
++             debug xref => &_1;           // in scope 2 at $DIR/reference_prop.rs:+2:9: +2:13
               let _3: *mut i32;            // in scope 2 at $DIR/reference_prop.rs:+3:9: +3:13
               scope 3 {
-                  debug xraw => _3;        // in scope 3 at $DIR/reference_prop.rs:+3:9: +3:13
+-                 debug xraw => _3;        // in scope 3 at $DIR/reference_prop.rs:+3:9: +3:13
++                 debug xraw => &_1;       // in scope 3 at $DIR/reference_prop.rs:+3:9: +3:13
                   let _6: &i32;            // in scope 3 at $DIR/reference_prop.rs:+4:9: +4:13
                   scope 4 {
-                      debug xshr => _6;    // in scope 4 at $DIR/reference_prop.rs:+4:9: +4:13
+-                     debug xshr => _6;    // in scope 4 at $DIR/reference_prop.rs:+4:9: +4:13
++                     debug xshr => &_1;   // in scope 4 at $DIR/reference_prop.rs:+4:9: +4:13
                       let _7: i32;         // in scope 4 at $DIR/reference_prop.rs:+6:9: +6:10
                       scope 5 {
                           debug a => _7;   // in scope 5 at $DIR/reference_prop.rs:+6:9: +6:10
@@ -35,19 +38,17 @@
           StorageLive(_1);                 // scope 0 at $DIR/reference_prop.rs:+1:9: +1:14
           _1 = const 2_i32;                // scope 0 at $DIR/reference_prop.rs:+1:17: +1:18
 -         StorageLive(_2);                 // scope 1 at $DIR/reference_prop.rs:+2:9: +2:13
-          _2 = &mut _1;                    // scope 1 at $DIR/reference_prop.rs:+2:16: +2:22
-          StorageLive(_3);                 // scope 2 at $DIR/reference_prop.rs:+3:9: +3:13
+-         _2 = &mut _1;                    // scope 1 at $DIR/reference_prop.rs:+2:16: +2:22
+-         StorageLive(_3);                 // scope 2 at $DIR/reference_prop.rs:+3:9: +3:13
 -         StorageLive(_4);                 // scope 2 at $DIR/reference_prop.rs:+3:16: +3:36
 -         StorageLive(_5);                 // scope 2 at $DIR/reference_prop.rs:+3:16: +3:26
 -         _5 = &mut (*_2);                 // scope 2 at $DIR/reference_prop.rs:+3:16: +3:26
 -         _4 = &raw mut (*_5);             // scope 2 at $DIR/reference_prop.rs:+3:16: +3:26
-+         _4 = &raw mut _1;                // scope 2 at $DIR/reference_prop.rs:+3:16: +3:26
-          _3 = _4;                         // scope 2 at $DIR/reference_prop.rs:+3:16: +3:36
+-         _3 = _4;                         // scope 2 at $DIR/reference_prop.rs:+3:16: +3:36
 -         StorageDead(_5);                 // scope 2 at $DIR/reference_prop.rs:+3:36: +3:37
 -         StorageDead(_4);                 // scope 2 at $DIR/reference_prop.rs:+3:36: +3:37
-          StorageLive(_6);                 // scope 3 at $DIR/reference_prop.rs:+4:9: +4:13
+-         StorageLive(_6);                 // scope 3 at $DIR/reference_prop.rs:+4:9: +4:13
 -         _6 = &(*_2);                     // scope 3 at $DIR/reference_prop.rs:+4:16: +4:22
-+         _6 = &_1;                        // scope 3 at $DIR/reference_prop.rs:+4:16: +4:22
           StorageLive(_7);                 // scope 4 at $DIR/reference_prop.rs:+6:9: +6:10
 -         _7 = (*_6);                      // scope 4 at $DIR/reference_prop.rs:+6:13: +6:18
 -         StorageLive(_8);                 // scope 5 at $DIR/reference_prop.rs:+7:5: +7:26
@@ -64,8 +65,8 @@
           StorageDead(_10);                // scope 5 at $DIR/reference_prop.rs:+8:10: +8:11
           StorageDead(_9);                 // scope 5 at $DIR/reference_prop.rs:+8:10: +8:11
           StorageDead(_7);                 // scope 4 at $DIR/reference_prop.rs:+9:1: +9:2
-          StorageDead(_6);                 // scope 3 at $DIR/reference_prop.rs:+9:1: +9:2
-          StorageDead(_3);                 // scope 2 at $DIR/reference_prop.rs:+9:1: +9:2
+-         StorageDead(_6);                 // scope 3 at $DIR/reference_prop.rs:+9:1: +9:2
+-         StorageDead(_3);                 // scope 2 at $DIR/reference_prop.rs:+9:1: +9:2
 -         StorageDead(_2);                 // scope 1 at $DIR/reference_prop.rs:+9:1: +9:2
           StorageDead(_1);                 // scope 0 at $DIR/reference_prop.rs:+9:1: +9:2
           return;                          // scope 0 at $DIR/reference_prop.rs:+9:2: +9:2
diff --git a/tests/mir-opt/reference_prop.reference_propagation.ReferencePropagation.diff b/tests/mir-opt/reference_prop.reference_propagation.ReferencePropagation.diff
index e41fc28461a..7b31ee695ce 100644
--- a/tests/mir-opt/reference_prop.reference_propagation.ReferencePropagation.diff
+++ b/tests/mir-opt/reference_prop.reference_propagation.ReferencePropagation.diff
@@ -17,12 +17,12 @@
       let mut _17: ();                     // in scope 0 at $DIR/reference_prop.rs:+17:16: +17:18
       let _18: ();                         // in scope 0 at $DIR/reference_prop.rs:+21:5: +27:6
       let _19: usize;                      // in scope 0 at $DIR/reference_prop.rs:+22:13: +22:14
-      let _23: ();                         // in scope 0 at $DIR/reference_prop.rs:+26:9: +26:19
-      let mut _24: ();                     // in scope 0 at $DIR/reference_prop.rs:+26:16: +26:18
+      let _23: ();                         // in scope 0 at $DIR/reference_prop.rs:+26:9: +26:18
+      let mut _24: &&usize;                // in scope 0 at $DIR/reference_prop.rs:+26:16: +26:17
       let _25: ();                         // in scope 0 at $DIR/reference_prop.rs:+30:5: +36:6
       let _26: usize;                      // in scope 0 at $DIR/reference_prop.rs:+31:13: +31:14
-      let _30: ();                         // in scope 0 at $DIR/reference_prop.rs:+35:9: +35:19
-      let mut _31: ();                     // in scope 0 at $DIR/reference_prop.rs:+35:16: +35:18
+      let _30: ();                         // in scope 0 at $DIR/reference_prop.rs:+35:9: +35:18
+      let mut _31: *mut &usize;            // in scope 0 at $DIR/reference_prop.rs:+35:16: +35:17
       let _32: ();                         // in scope 0 at $DIR/reference_prop.rs:+39:5: +44:6
       let _33: usize;                      // in scope 0 at $DIR/reference_prop.rs:+40:13: +40:14
       let _36: ();                         // in scope 0 at $DIR/reference_prop.rs:+43:9: +43:18
@@ -35,16 +35,25 @@
       let _48: &T;                         // in scope 0 at $DIR/reference_prop.rs:+61:13: +61:14
       let _50: ();                         // in scope 0 at $DIR/reference_prop.rs:+63:9: +63:19
       let mut _51: ();                     // in scope 0 at $DIR/reference_prop.rs:+63:16: +63:18
-      let _52: &T;                         // in scope 0 at $DIR/reference_prop.rs:+68:13: +68:14
-      let mut _53: &T;                     // in scope 0 at $DIR/reference_prop.rs:+69:20: +69:28
-      let _54: &T;                         // in scope 0 at $DIR/reference_prop.rs:+69:20: +69:28
-      let _56: ();                         // in scope 0 at $DIR/reference_prop.rs:+71:9: +71:19
-      let mut _57: ();                     // in scope 0 at $DIR/reference_prop.rs:+71:16: +71:18
+      let _52: ();                         // in scope 0 at $DIR/reference_prop.rs:+67:5: +72:6
+      let _53: &T;                         // in scope 0 at $DIR/reference_prop.rs:+68:13: +68:14
+      let mut _54: &T;                     // in scope 0 at $DIR/reference_prop.rs:+69:20: +69:28
+      let _55: &T;                         // in scope 0 at $DIR/reference_prop.rs:+69:20: +69:28
+      let _57: ();                         // in scope 0 at $DIR/reference_prop.rs:+71:9: +71:19
+      let mut _58: ();                     // in scope 0 at $DIR/reference_prop.rs:+71:16: +71:18
+      let _59: ();                         // in scope 0 at $DIR/reference_prop.rs:+75:5: +81:6
+      let _60: usize;                      // in scope 0 at $DIR/reference_prop.rs:+76:13: +76:14
+      let _64: ();                         // in scope 0 at $DIR/reference_prop.rs:+80:9: +80:19
+      let mut _65: ();                     // in scope 0 at $DIR/reference_prop.rs:+80:16: +80:18
+      let _66: usize;                      // in scope 0 at $DIR/reference_prop.rs:+85:13: +85:14
+      let _70: ();                         // in scope 0 at $DIR/reference_prop.rs:+89:9: +89:19
+      let mut _71: ();                     // in scope 0 at $DIR/reference_prop.rs:+89:16: +89:18
       scope 1 {
           debug a => _4;                   // in scope 1 at $DIR/reference_prop.rs:+3:13: +3:14
           let _5: &usize;                  // in scope 1 at $DIR/reference_prop.rs:+4:13: +4:14
           scope 2 {
-              debug b => _5;               // in scope 2 at $DIR/reference_prop.rs:+4:13: +4:14
+-             debug b => _5;               // in scope 2 at $DIR/reference_prop.rs:+4:13: +4:14
++             debug b => &_4;              // in scope 2 at $DIR/reference_prop.rs:+4:13: +4:14
               let _6: usize;               // in scope 2 at $DIR/reference_prop.rs:+5:13: +5:14
               scope 3 {
                   debug c => _6;           // in scope 3 at $DIR/reference_prop.rs:+5:13: +5:14
@@ -86,7 +95,7 @@
           let mut _27: &usize;             // in scope 12 at $DIR/reference_prop.rs:+32:13: +32:18
           scope 13 {
               debug b => _27;              // in scope 13 at $DIR/reference_prop.rs:+32:13: +32:18
-              let _28: &mut &usize;        // in scope 13 at $DIR/reference_prop.rs:+33:13: +33:14
+              let _28: *mut &usize;        // in scope 13 at $DIR/reference_prop.rs:+33:13: +33:14
               scope 14 {
                   debug d => _28;          // in scope 14 at $DIR/reference_prop.rs:+33:13: +33:14
                   let _29: usize;          // in scope 14 at $DIR/reference_prop.rs:+34:13: +34:14
@@ -131,17 +140,52 @@
           }
       }
       scope 25 {
-          debug a => _48;                  // in scope 25 at $DIR/reference_prop.rs:+61:13: +61:14
+-         debug a => _48;                  // in scope 25 at $DIR/reference_prop.rs:+61:13: +61:14
++         debug a => _1;                   // in scope 25 at $DIR/reference_prop.rs:+61:13: +61:14
           let _49: T;                      // in scope 25 at $DIR/reference_prop.rs:+62:13: +62:14
           scope 26 {
               debug b => _49;              // in scope 26 at $DIR/reference_prop.rs:+62:13: +62:14
           }
       }
       scope 27 {
-          debug a => _52;                  // in scope 27 at $DIR/reference_prop.rs:+68:13: +68:14
-          let _55: T;                      // in scope 27 at $DIR/reference_prop.rs:+70:13: +70:14
+          debug a => _53;                  // in scope 27 at $DIR/reference_prop.rs:+68:13: +68:14
+          let _56: T;                      // in scope 27 at $DIR/reference_prop.rs:+70:13: +70:14
           scope 28 {
-              debug b => _55;              // in scope 28 at $DIR/reference_prop.rs:+70:13: +70:14
+              debug b => _56;              // in scope 28 at $DIR/reference_prop.rs:+70:13: +70:14
+          }
+      }
+      scope 29 {
+          debug a => _60;                  // in scope 29 at $DIR/reference_prop.rs:+76:13: +76:14
+          let _61: &usize;                 // in scope 29 at $DIR/reference_prop.rs:+77:13: +77:14
+          scope 30 {
+-             debug b => _61;              // in scope 30 at $DIR/reference_prop.rs:+77:13: +77:14
++             debug b => &_60;             // in scope 30 at $DIR/reference_prop.rs:+77:13: +77:14
+              let _62: &&usize;            // in scope 30 at $DIR/reference_prop.rs:+78:13: +78:14
+              scope 31 {
+-                 debug d => _62;          // in scope 31 at $DIR/reference_prop.rs:+78:13: +78:14
++                 debug d => &&_60;        // in scope 31 at $DIR/reference_prop.rs:+78:13: +78:14
+                  let _63: usize;          // in scope 31 at $DIR/reference_prop.rs:+79:13: +79:14
+                  scope 32 {
+                      debug c => _63;      // in scope 32 at $DIR/reference_prop.rs:+79:13: +79:14
+                  }
+              }
+          }
+      }
+      scope 33 {
+          debug a => _66;                  // in scope 33 at $DIR/reference_prop.rs:+85:13: +85:14
+          let mut _67: &usize;             // in scope 33 at $DIR/reference_prop.rs:+86:13: +86:18
+          scope 34 {
+-             debug b => _67;              // in scope 34 at $DIR/reference_prop.rs:+86:13: +86:18
++             debug b => &_66;             // in scope 34 at $DIR/reference_prop.rs:+86:13: +86:18
+              let _68: &mut &usize;        // in scope 34 at $DIR/reference_prop.rs:+87:13: +87:14
+              scope 35 {
+-                 debug d => _68;          // in scope 35 at $DIR/reference_prop.rs:+87:13: +87:14
++                 debug d => &&_66;        // in scope 35 at $DIR/reference_prop.rs:+87:13: +87:14
+                  let _69: usize;          // in scope 35 at $DIR/reference_prop.rs:+88:13: +88:14
+                  scope 36 {
+                      debug c => _69;      // in scope 36 at $DIR/reference_prop.rs:+88:13: +88:14
+                  }
+              }
           }
       }
   
@@ -149,8 +193,8 @@
 -         StorageLive(_3);                 // scope 0 at $DIR/reference_prop.rs:+2:5: +7:6
           StorageLive(_4);                 // scope 0 at $DIR/reference_prop.rs:+3:13: +3:14
           _4 = const 5_usize;              // scope 0 at $DIR/reference_prop.rs:+3:17: +3:24
-          StorageLive(_5);                 // scope 1 at $DIR/reference_prop.rs:+4:13: +4:14
-          _5 = &_4;                        // scope 1 at $DIR/reference_prop.rs:+4:17: +4:19
+-         StorageLive(_5);                 // scope 1 at $DIR/reference_prop.rs:+4:13: +4:14
+-         _5 = &_4;                        // scope 1 at $DIR/reference_prop.rs:+4:17: +4:19
           StorageLive(_6);                 // scope 2 at $DIR/reference_prop.rs:+5:13: +5:14
 -         _6 = (*_5);                      // scope 2 at $DIR/reference_prop.rs:+5:17: +5:19
 +         _6 = _4;                         // scope 2 at $DIR/reference_prop.rs:+5:17: +5:19
@@ -168,7 +212,7 @@
           StorageDead(_7);                 // scope 3 at $DIR/reference_prop.rs:+6:19: +6:20
 -         _3 = const ();                   // scope 0 at $DIR/reference_prop.rs:+2:5: +7:6
           StorageDead(_6);                 // scope 2 at $DIR/reference_prop.rs:+7:5: +7:6
-          StorageDead(_5);                 // scope 1 at $DIR/reference_prop.rs:+7:5: +7:6
+-         StorageDead(_5);                 // scope 1 at $DIR/reference_prop.rs:+7:5: +7:6
           StorageDead(_4);                 // scope 0 at $DIR/reference_prop.rs:+7:5: +7:6
 -         StorageDead(_3);                 // scope 0 at $DIR/reference_prop.rs:+7:5: +7:6
 -         StorageLive(_9);                 // scope 0 at $DIR/reference_prop.rs:+10:5: +18:6
@@ -215,18 +259,18 @@
           _21 = &_20;                      // scope 9 at $DIR/reference_prop.rs:+24:17: +24:19
           StorageLive(_22);                // scope 10 at $DIR/reference_prop.rs:+25:13: +25:14
           _22 = (*_20);                    // scope 10 at $DIR/reference_prop.rs:+25:17: +25:19
-          StorageLive(_23);                // scope 11 at $DIR/reference_prop.rs:+26:9: +26:19
-          StorageLive(_24);                // scope 11 at $DIR/reference_prop.rs:+26:16: +26:18
-          _24 = ();                        // scope 11 at $DIR/reference_prop.rs:+26:16: +26:18
-          _23 = opaque::<()>(move _24) -> bb3; // scope 11 at $DIR/reference_prop.rs:+26:9: +26:19
+          StorageLive(_23);                // scope 11 at $DIR/reference_prop.rs:+26:9: +26:18
+          StorageLive(_24);                // scope 11 at $DIR/reference_prop.rs:+26:16: +26:17
+          _24 = _21;                       // scope 11 at $DIR/reference_prop.rs:+26:16: +26:17
+          _23 = opaque::<&&usize>(move _24) -> bb3; // scope 11 at $DIR/reference_prop.rs:+26:9: +26:18
                                            // mir::Constant
                                            // + span: $DIR/reference_prop.rs:36:9: 36:15
-                                           // + literal: Const { ty: fn(()) {opaque::<()>}, val: Value(<ZST>) }
+                                           // + literal: Const { ty: fn(&&usize) {opaque::<&&usize>}, val: Value(<ZST>) }
       }
   
       bb3: {
-          StorageDead(_24);                // scope 11 at $DIR/reference_prop.rs:+26:18: +26:19
-          StorageDead(_23);                // scope 11 at $DIR/reference_prop.rs:+26:19: +26:20
+          StorageDead(_24);                // scope 11 at $DIR/reference_prop.rs:+26:17: +26:18
+          StorageDead(_23);                // scope 11 at $DIR/reference_prop.rs:+26:18: +26:19
 -         _18 = const ();                  // scope 0 at $DIR/reference_prop.rs:+21:5: +27:6
           StorageDead(_22);                // scope 10 at $DIR/reference_prop.rs:+27:5: +27:6
           StorageDead(_21);                // scope 9 at $DIR/reference_prop.rs:+27:5: +27:6
@@ -239,21 +283,21 @@
           StorageLive(_27);                // scope 12 at $DIR/reference_prop.rs:+32:13: +32:18
           _27 = &_26;                      // scope 12 at $DIR/reference_prop.rs:+32:21: +32:23
           StorageLive(_28);                // scope 13 at $DIR/reference_prop.rs:+33:13: +33:14
-          _28 = &mut _27;                  // scope 13 at $DIR/reference_prop.rs:+33:17: +33:23
+          _28 = &raw mut _27;              // scope 13 at $DIR/reference_prop.rs:+33:17: +33:27
           StorageLive(_29);                // scope 14 at $DIR/reference_prop.rs:+34:13: +34:14
           _29 = (*_27);                    // scope 14 at $DIR/reference_prop.rs:+34:17: +34:19
-          StorageLive(_30);                // scope 15 at $DIR/reference_prop.rs:+35:9: +35:19
-          StorageLive(_31);                // scope 15 at $DIR/reference_prop.rs:+35:16: +35:18
-          _31 = ();                        // scope 15 at $DIR/reference_prop.rs:+35:16: +35:18
-          _30 = opaque::<()>(move _31) -> bb4; // scope 15 at $DIR/reference_prop.rs:+35:9: +35:19
+          StorageLive(_30);                // scope 15 at $DIR/reference_prop.rs:+35:9: +35:18
+          StorageLive(_31);                // scope 15 at $DIR/reference_prop.rs:+35:16: +35:17
+          _31 = _28;                       // scope 15 at $DIR/reference_prop.rs:+35:16: +35:17
+          _30 = opaque::<*mut &usize>(move _31) -> bb4; // scope 15 at $DIR/reference_prop.rs:+35:9: +35:18
                                            // mir::Constant
                                            // + span: $DIR/reference_prop.rs:45:9: 45:15
-                                           // + literal: Const { ty: fn(()) {opaque::<()>}, val: Value(<ZST>) }
+                                           // + literal: Const { ty: fn(*mut &usize) {opaque::<*mut &usize>}, val: Value(<ZST>) }
       }
   
       bb4: {
-          StorageDead(_31);                // scope 15 at $DIR/reference_prop.rs:+35:18: +35:19
-          StorageDead(_30);                // scope 15 at $DIR/reference_prop.rs:+35:19: +35:20
+          StorageDead(_31);                // scope 15 at $DIR/reference_prop.rs:+35:17: +35:18
+          StorageDead(_30);                // scope 15 at $DIR/reference_prop.rs:+35:18: +35:19
 -         _25 = const ();                  // scope 0 at $DIR/reference_prop.rs:+30:5: +36:6
           StorageDead(_29);                // scope 14 at $DIR/reference_prop.rs:+36:5: +36:6
           StorageDead(_28);                // scope 13 at $DIR/reference_prop.rs:+36:5: +36:6
@@ -321,8 +365,8 @@
           StorageDead(_39);                // scope 0 at $DIR/reference_prop.rs:+57:5: +57:6
 -         StorageDead(_38);                // scope 0 at $DIR/reference_prop.rs:+57:5: +57:6
 -         StorageLive(_47);                // scope 0 at $DIR/reference_prop.rs:+60:5: +64:6
-          StorageLive(_48);                // scope 0 at $DIR/reference_prop.rs:+61:13: +61:14
-          _48 = &(*_1);                    // scope 0 at $DIR/reference_prop.rs:+61:17: +61:25
+-         StorageLive(_48);                // scope 0 at $DIR/reference_prop.rs:+61:13: +61:14
+-         _48 = &(*_1);                    // scope 0 at $DIR/reference_prop.rs:+61:17: +61:25
           StorageLive(_49);                // scope 25 at $DIR/reference_prop.rs:+62:13: +62:14
 -         _49 = (*_48);                    // scope 25 at $DIR/reference_prop.rs:+62:17: +62:19
 +         _49 = (*_1);                     // scope 25 at $DIR/reference_prop.rs:+62:17: +62:19
@@ -340,36 +384,92 @@
           StorageDead(_50);                // scope 26 at $DIR/reference_prop.rs:+63:19: +63:20
 -         _47 = const ();                  // scope 0 at $DIR/reference_prop.rs:+60:5: +64:6
           StorageDead(_49);                // scope 25 at $DIR/reference_prop.rs:+64:5: +64:6
-          StorageDead(_48);                // scope 0 at $DIR/reference_prop.rs:+64:5: +64:6
+-         StorageDead(_48);                // scope 0 at $DIR/reference_prop.rs:+64:5: +64:6
 -         StorageDead(_47);                // scope 0 at $DIR/reference_prop.rs:+64:5: +64:6
-          StorageLive(_52);                // scope 0 at $DIR/reference_prop.rs:+68:13: +68:14
-          _52 = &(*_2);                    // scope 0 at $DIR/reference_prop.rs:+68:17: +68:27
-          StorageLive(_53);                // scope 27 at $DIR/reference_prop.rs:+69:20: +69:28
--         StorageLive(_54);                // scope 27 at $DIR/reference_prop.rs:+69:20: +69:28
--         _54 = &(*_1);                    // scope 27 at $DIR/reference_prop.rs:+69:20: +69:28
--         _53 = &(*_54);                   // scope 27 at $DIR/reference_prop.rs:+69:20: +69:28
-+         _53 = &(*_1);                    // scope 27 at $DIR/reference_prop.rs:+69:20: +69:28
-          _2 = move _53;                   // scope 27 at $DIR/reference_prop.rs:+69:9: +69:28
-          StorageDead(_53);                // scope 27 at $DIR/reference_prop.rs:+69:27: +69:28
--         StorageDead(_54);                // scope 27 at $DIR/reference_prop.rs:+69:28: +69:29
-          StorageLive(_55);                // scope 27 at $DIR/reference_prop.rs:+70:13: +70:14
-          _55 = (*_52);                    // scope 27 at $DIR/reference_prop.rs:+70:17: +70:19
-          StorageLive(_56);                // scope 28 at $DIR/reference_prop.rs:+71:9: +71:19
-          StorageLive(_57);                // scope 28 at $DIR/reference_prop.rs:+71:16: +71:18
-          _57 = ();                        // scope 28 at $DIR/reference_prop.rs:+71:16: +71:18
-          _56 = opaque::<()>(move _57) -> bb8; // scope 28 at $DIR/reference_prop.rs:+71:9: +71:19
+-         StorageLive(_52);                // scope 0 at $DIR/reference_prop.rs:+67:5: +72:6
+          StorageLive(_53);                // scope 0 at $DIR/reference_prop.rs:+68:13: +68:14
+          _53 = &(*_2);                    // scope 0 at $DIR/reference_prop.rs:+68:17: +68:27
+          StorageLive(_54);                // scope 27 at $DIR/reference_prop.rs:+69:20: +69:28
+-         StorageLive(_55);                // scope 27 at $DIR/reference_prop.rs:+69:20: +69:28
+-         _55 = &(*_1);                    // scope 27 at $DIR/reference_prop.rs:+69:20: +69:28
+-         _54 = &(*_55);                   // scope 27 at $DIR/reference_prop.rs:+69:20: +69:28
++         _54 = &(*_1);                    // scope 27 at $DIR/reference_prop.rs:+69:20: +69:28
+          _2 = move _54;                   // scope 27 at $DIR/reference_prop.rs:+69:9: +69:28
+          StorageDead(_54);                // scope 27 at $DIR/reference_prop.rs:+69:27: +69:28
+-         StorageDead(_55);                // scope 27 at $DIR/reference_prop.rs:+69:28: +69:29
+          StorageLive(_56);                // scope 27 at $DIR/reference_prop.rs:+70:13: +70:14
+          _56 = (*_53);                    // scope 27 at $DIR/reference_prop.rs:+70:17: +70:19
+          StorageLive(_57);                // scope 28 at $DIR/reference_prop.rs:+71:9: +71:19
+          StorageLive(_58);                // scope 28 at $DIR/reference_prop.rs:+71:16: +71:18
+          _58 = ();                        // scope 28 at $DIR/reference_prop.rs:+71:16: +71:18
+          _57 = opaque::<()>(move _58) -> bb8; // scope 28 at $DIR/reference_prop.rs:+71:9: +71:19
                                            // mir::Constant
                                            // + span: $DIR/reference_prop.rs:81:9: 81:15
                                            // + literal: Const { ty: fn(()) {opaque::<()>}, val: Value(<ZST>) }
       }
   
       bb8: {
-          StorageDead(_57);                // scope 28 at $DIR/reference_prop.rs:+71:18: +71:19
-          StorageDead(_56);                // scope 28 at $DIR/reference_prop.rs:+71:19: +71:20
-          _0 = const ();                   // scope 0 at $DIR/reference_prop.rs:+67:5: +72:6
-          StorageDead(_55);                // scope 27 at $DIR/reference_prop.rs:+72:5: +72:6
-          StorageDead(_52);                // scope 0 at $DIR/reference_prop.rs:+72:5: +72:6
-          return;                          // scope 0 at $DIR/reference_prop.rs:+73:2: +73:2
+          StorageDead(_58);                // scope 28 at $DIR/reference_prop.rs:+71:18: +71:19
+          StorageDead(_57);                // scope 28 at $DIR/reference_prop.rs:+71:19: +71:20
+-         _52 = const ();                  // scope 0 at $DIR/reference_prop.rs:+67:5: +72:6
+          StorageDead(_56);                // scope 27 at $DIR/reference_prop.rs:+72:5: +72:6
+          StorageDead(_53);                // scope 0 at $DIR/reference_prop.rs:+72:5: +72:6
+-         StorageDead(_52);                // scope 0 at $DIR/reference_prop.rs:+72:5: +72:6
+-         StorageLive(_59);                // scope 0 at $DIR/reference_prop.rs:+75:5: +81:6
+          StorageLive(_60);                // scope 0 at $DIR/reference_prop.rs:+76:13: +76:14
+          _60 = const 5_usize;             // scope 0 at $DIR/reference_prop.rs:+76:17: +76:24
+-         StorageLive(_61);                // scope 29 at $DIR/reference_prop.rs:+77:13: +77:14
+-         _61 = &_60;                      // scope 29 at $DIR/reference_prop.rs:+77:17: +77:19
+-         StorageLive(_62);                // scope 30 at $DIR/reference_prop.rs:+78:13: +78:14
+-         _62 = &_61;                      // scope 30 at $DIR/reference_prop.rs:+78:17: +78:19
+          StorageLive(_63);                // scope 31 at $DIR/reference_prop.rs:+79:13: +79:14
+-         _63 = (*_61);                    // scope 31 at $DIR/reference_prop.rs:+79:17: +79:19
++         _63 = _60;                       // scope 31 at $DIR/reference_prop.rs:+79:17: +79:19
+          StorageLive(_64);                // scope 32 at $DIR/reference_prop.rs:+80:9: +80:19
+          StorageLive(_65);                // scope 32 at $DIR/reference_prop.rs:+80:16: +80:18
+          _65 = ();                        // scope 32 at $DIR/reference_prop.rs:+80:16: +80:18
+          _64 = opaque::<()>(move _65) -> bb9; // scope 32 at $DIR/reference_prop.rs:+80:9: +80:19
+                                           // mir::Constant
+                                           // + span: $DIR/reference_prop.rs:90:9: 90:15
+                                           // + literal: Const { ty: fn(()) {opaque::<()>}, val: Value(<ZST>) }
+      }
+  
+      bb9: {
+          StorageDead(_65);                // scope 32 at $DIR/reference_prop.rs:+80:18: +80:19
+          StorageDead(_64);                // scope 32 at $DIR/reference_prop.rs:+80:19: +80:20
+-         _59 = const ();                  // scope 0 at $DIR/reference_prop.rs:+75:5: +81:6
+          StorageDead(_63);                // scope 31 at $DIR/reference_prop.rs:+81:5: +81:6
+-         StorageDead(_62);                // scope 30 at $DIR/reference_prop.rs:+81:5: +81:6
+-         StorageDead(_61);                // scope 29 at $DIR/reference_prop.rs:+81:5: +81:6
+          StorageDead(_60);                // scope 0 at $DIR/reference_prop.rs:+81:5: +81:6
+-         StorageDead(_59);                // scope 0 at $DIR/reference_prop.rs:+81:5: +81:6
+          StorageLive(_66);                // scope 0 at $DIR/reference_prop.rs:+85:13: +85:14
+          _66 = const 5_usize;             // scope 0 at $DIR/reference_prop.rs:+85:17: +85:24
+-         StorageLive(_67);                // scope 33 at $DIR/reference_prop.rs:+86:13: +86:18
+-         _67 = &_66;                      // scope 33 at $DIR/reference_prop.rs:+86:21: +86:23
+-         StorageLive(_68);                // scope 34 at $DIR/reference_prop.rs:+87:13: +87:14
+-         _68 = &mut _67;                  // scope 34 at $DIR/reference_prop.rs:+87:17: +87:23
+          StorageLive(_69);                // scope 35 at $DIR/reference_prop.rs:+88:13: +88:14
+-         _69 = (*_67);                    // scope 35 at $DIR/reference_prop.rs:+88:17: +88:19
++         _69 = _66;                       // scope 35 at $DIR/reference_prop.rs:+88:17: +88:19
+          StorageLive(_70);                // scope 36 at $DIR/reference_prop.rs:+89:9: +89:19
+          StorageLive(_71);                // scope 36 at $DIR/reference_prop.rs:+89:16: +89:18
+          _71 = ();                        // scope 36 at $DIR/reference_prop.rs:+89:16: +89:18
+          _70 = opaque::<()>(move _71) -> bb10; // scope 36 at $DIR/reference_prop.rs:+89:9: +89:19
+                                           // mir::Constant
+                                           // + span: $DIR/reference_prop.rs:99:9: 99:15
+                                           // + literal: Const { ty: fn(()) {opaque::<()>}, val: Value(<ZST>) }
+      }
+  
+      bb10: {
+          StorageDead(_71);                // scope 36 at $DIR/reference_prop.rs:+89:18: +89:19
+          StorageDead(_70);                // scope 36 at $DIR/reference_prop.rs:+89:19: +89:20
+          _0 = const ();                   // scope 0 at $DIR/reference_prop.rs:+84:5: +90:6
+          StorageDead(_69);                // scope 35 at $DIR/reference_prop.rs:+90:5: +90:6
+-         StorageDead(_68);                // scope 34 at $DIR/reference_prop.rs:+90:5: +90:6
+-         StorageDead(_67);                // scope 33 at $DIR/reference_prop.rs:+90:5: +90:6
+          StorageDead(_66);                // scope 0 at $DIR/reference_prop.rs:+90:5: +90:6
+          return;                          // scope 0 at $DIR/reference_prop.rs:+91:2: +91:2
       }
   }
   
diff --git a/tests/mir-opt/reference_prop.reference_propagation_const_ptr.ReferencePropagation.diff b/tests/mir-opt/reference_prop.reference_propagation_const_ptr.ReferencePropagation.diff
index 712727915d0..ddeb04e50c7 100644
--- a/tests/mir-opt/reference_prop.reference_propagation_const_ptr.ReferencePropagation.diff
+++ b/tests/mir-opt/reference_prop.reference_propagation_const_ptr.ReferencePropagation.diff
@@ -13,11 +13,11 @@
       let _15: ();                         // in scope 0 at $DIR/reference_prop.rs:+17:9: +17:19
       let mut _16: ();                     // in scope 0 at $DIR/reference_prop.rs:+17:16: +17:18
       let _17: ();                         // in scope 0 at $DIR/reference_prop.rs:+21:5: +27:6
-      let _22: ();                         // in scope 0 at $DIR/reference_prop.rs:+26:9: +26:19
-      let mut _23: ();                     // in scope 0 at $DIR/reference_prop.rs:+26:16: +26:18
+      let _22: ();                         // in scope 0 at $DIR/reference_prop.rs:+26:9: +26:18
+      let mut _23: &*const usize;          // in scope 0 at $DIR/reference_prop.rs:+26:16: +26:17
       let _24: ();                         // in scope 0 at $DIR/reference_prop.rs:+30:5: +36:6
-      let _29: ();                         // in scope 0 at $DIR/reference_prop.rs:+35:9: +35:19
-      let mut _30: ();                     // in scope 0 at $DIR/reference_prop.rs:+35:16: +35:18
+      let _29: ();                         // in scope 0 at $DIR/reference_prop.rs:+35:9: +35:18
+      let mut _30: *mut *const usize;      // in scope 0 at $DIR/reference_prop.rs:+35:16: +35:17
       let _31: ();                         // in scope 0 at $DIR/reference_prop.rs:+39:5: +44:6
       let _35: ();                         // in scope 0 at $DIR/reference_prop.rs:+43:9: +43:18
       let mut _36: *const usize;           // in scope 0 at $DIR/reference_prop.rs:+43:16: +43:17
@@ -31,15 +31,22 @@
       let mut _53: *const T;               // in scope 0 at $DIR/reference_prop.rs:+69:20: +69:38
       let _55: ();                         // in scope 0 at $DIR/reference_prop.rs:+71:9: +71:19
       let mut _56: ();                     // in scope 0 at $DIR/reference_prop.rs:+71:16: +71:18
-      let _61: ();                         // in scope 0 at $DIR/reference_prop.rs:+80:9: +80:19
-      let mut _62: ();                     // in scope 0 at $DIR/reference_prop.rs:+80:16: +80:18
+      let _57: ();                         // in scope 0 at $DIR/reference_prop.rs:+75:5: +81:6
+      let _62: ();                         // in scope 0 at $DIR/reference_prop.rs:+80:9: +80:19
+      let mut _63: ();                     // in scope 0 at $DIR/reference_prop.rs:+80:16: +80:18
+      let _64: ();                         // in scope 0 at $DIR/reference_prop.rs:+84:5: +90:6
+      let _69: ();                         // in scope 0 at $DIR/reference_prop.rs:+89:9: +89:19
+      let mut _70: ();                     // in scope 0 at $DIR/reference_prop.rs:+89:16: +89:18
+      let _75: ();                         // in scope 0 at $DIR/reference_prop.rs:+98:9: +98:19
+      let mut _76: ();                     // in scope 0 at $DIR/reference_prop.rs:+98:16: +98:18
       scope 1 {
           let _4: usize;                   // in scope 1 at $DIR/reference_prop.rs:+3:13: +3:14
           scope 2 {
               debug a => _4;               // in scope 2 at $DIR/reference_prop.rs:+3:13: +3:14
               let _5: *const usize;        // in scope 2 at $DIR/reference_prop.rs:+4:13: +4:14
               scope 3 {
-                  debug b => _5;           // in scope 3 at $DIR/reference_prop.rs:+4:13: +4:14
+-                 debug b => _5;           // in scope 3 at $DIR/reference_prop.rs:+4:13: +4:14
++                 debug b => &_4;          // in scope 3 at $DIR/reference_prop.rs:+4:13: +4:14
                   let _6: usize;           // in scope 3 at $DIR/reference_prop.rs:+5:13: +5:14
                   scope 4 {
                       debug c => _6;       // in scope 4 at $DIR/reference_prop.rs:+5:13: +5:14
@@ -90,7 +97,7 @@
               let mut _26: *const usize;   // in scope 16 at $DIR/reference_prop.rs:+32:13: +32:18
               scope 17 {
                   debug b => _26;          // in scope 17 at $DIR/reference_prop.rs:+32:13: +32:18
-                  let _27: &mut *const usize; // in scope 17 at $DIR/reference_prop.rs:+33:13: +33:14
+                  let _27: *mut *const usize; // in scope 17 at $DIR/reference_prop.rs:+33:13: +33:14
                   scope 18 {
                       debug d => _27;      // in scope 18 at $DIR/reference_prop.rs:+33:13: +33:14
                       let _28: usize;      // in scope 18 at $DIR/reference_prop.rs:+34:13: +34:14
@@ -144,7 +151,8 @@
       scope 31 {
           let _47: *const T;               // in scope 31 at $DIR/reference_prop.rs:+61:13: +61:14
           scope 32 {
-              debug a => _47;              // in scope 32 at $DIR/reference_prop.rs:+61:13: +61:14
+-             debug a => _47;              // in scope 32 at $DIR/reference_prop.rs:+61:13: +61:14
++             debug a => _1;               // in scope 32 at $DIR/reference_prop.rs:+61:13: +61:14
               let _48: T;                  // in scope 32 at $DIR/reference_prop.rs:+62:13: +62:14
               scope 33 {
                   debug b => _48;          // in scope 33 at $DIR/reference_prop.rs:+62:13: +62:14
@@ -162,18 +170,60 @@
           }
       }
       scope 37 {
-          let _57: usize;                  // in scope 37 at $DIR/reference_prop.rs:+76:13: +76:14
+          let _58: usize;                  // in scope 37 at $DIR/reference_prop.rs:+76:13: +76:14
           scope 38 {
-              debug a => _57;              // in scope 38 at $DIR/reference_prop.rs:+76:13: +76:14
-              let _58: *const usize;       // in scope 38 at $DIR/reference_prop.rs:+77:13: +77:14
+              debug a => _58;              // in scope 38 at $DIR/reference_prop.rs:+76:13: +76:14
+              let _59: *const usize;       // in scope 38 at $DIR/reference_prop.rs:+77:13: +77:14
               scope 39 {
-                  debug b => _58;          // in scope 39 at $DIR/reference_prop.rs:+77:13: +77:14
-                  let _59: *const usize;   // in scope 39 at $DIR/reference_prop.rs:+78:13: +78:14
+-                 debug b => _59;          // in scope 39 at $DIR/reference_prop.rs:+77:13: +77:14
++                 debug b => &_58;         // in scope 39 at $DIR/reference_prop.rs:+77:13: +77:14
+                  let _60: *const usize;   // in scope 39 at $DIR/reference_prop.rs:+78:13: +78:14
                   scope 40 {
-                      debug c => _59;      // in scope 40 at $DIR/reference_prop.rs:+78:13: +78:14
-                      let _60: usize;      // in scope 40 at $DIR/reference_prop.rs:+79:13: +79:14
+-                     debug c => _60;      // in scope 40 at $DIR/reference_prop.rs:+78:13: +78:14
++                     debug c => &_58;     // in scope 40 at $DIR/reference_prop.rs:+78:13: +78:14
+                      let _61: usize;      // in scope 40 at $DIR/reference_prop.rs:+79:13: +79:14
                       scope 41 {
-                          debug e => _60;  // in scope 41 at $DIR/reference_prop.rs:+79:13: +79:14
+                          debug e => _61;  // in scope 41 at $DIR/reference_prop.rs:+79:13: +79:14
+                      }
+                  }
+              }
+          }
+      }
+      scope 42 {
+          let _65: usize;                  // in scope 42 at $DIR/reference_prop.rs:+85:13: +85:14
+          scope 43 {
+              debug a => _65;              // in scope 43 at $DIR/reference_prop.rs:+85:13: +85:14
+              let _66: *const usize;       // in scope 43 at $DIR/reference_prop.rs:+86:13: +86:14
+              scope 44 {
+-                 debug b => _66;          // in scope 44 at $DIR/reference_prop.rs:+86:13: +86:14
++                 debug b => &_65;         // in scope 44 at $DIR/reference_prop.rs:+86:13: +86:14
+                  let _67: &*const usize;  // in scope 44 at $DIR/reference_prop.rs:+87:13: +87:14
+                  scope 45 {
+-                     debug d => _67;      // in scope 45 at $DIR/reference_prop.rs:+87:13: +87:14
++                     debug d => &&_65;    // in scope 45 at $DIR/reference_prop.rs:+87:13: +87:14
+                      let _68: usize;      // in scope 45 at $DIR/reference_prop.rs:+88:13: +88:14
+                      scope 46 {
+                          debug c => _68;  // in scope 46 at $DIR/reference_prop.rs:+88:13: +88:14
+                      }
+                  }
+              }
+          }
+      }
+      scope 47 {
+          let _71: usize;                  // in scope 47 at $DIR/reference_prop.rs:+94:13: +94:14
+          scope 48 {
+              debug a => _71;              // in scope 48 at $DIR/reference_prop.rs:+94:13: +94:14
+              let mut _72: *const usize;   // in scope 48 at $DIR/reference_prop.rs:+95:13: +95:18
+              scope 49 {
+-                 debug b => _72;          // in scope 49 at $DIR/reference_prop.rs:+95:13: +95:18
++                 debug b => &_71;         // in scope 49 at $DIR/reference_prop.rs:+95:13: +95:18
+                  let _73: &mut *const usize; // in scope 49 at $DIR/reference_prop.rs:+96:13: +96:14
+                  scope 50 {
+-                     debug d => _73;      // in scope 50 at $DIR/reference_prop.rs:+96:13: +96:14
++                     debug d => &&_71;    // in scope 50 at $DIR/reference_prop.rs:+96:13: +96:14
+                      let _74: usize;      // in scope 50 at $DIR/reference_prop.rs:+97:13: +97:14
+                      scope 51 {
+                          debug c => _74;  // in scope 51 at $DIR/reference_prop.rs:+97:13: +97:14
                       }
                   }
               }
@@ -184,8 +234,8 @@
 -         StorageLive(_3);                 // scope 0 at $DIR/reference_prop.rs:+2:5: +7:6
           StorageLive(_4);                 // scope 1 at $DIR/reference_prop.rs:+3:13: +3:14
           _4 = const 5_usize;              // scope 1 at $DIR/reference_prop.rs:+3:17: +3:24
-          StorageLive(_5);                 // scope 2 at $DIR/reference_prop.rs:+4:13: +4:14
-          _5 = &raw const _4;              // scope 2 at $DIR/reference_prop.rs:+4:17: +4:29
+-         StorageLive(_5);                 // scope 2 at $DIR/reference_prop.rs:+4:13: +4:14
+-         _5 = &raw const _4;              // scope 2 at $DIR/reference_prop.rs:+4:17: +4:29
           StorageLive(_6);                 // scope 3 at $DIR/reference_prop.rs:+5:13: +5:14
 -         _6 = (*_5);                      // scope 3 at $DIR/reference_prop.rs:+5:17: +5:19
 +         _6 = _4;                         // scope 3 at $DIR/reference_prop.rs:+5:17: +5:19
@@ -194,7 +244,7 @@
           _8 = ();                         // scope 4 at $DIR/reference_prop.rs:+6:16: +6:18
           _7 = opaque::<()>(move _8) -> bb1; // scope 4 at $DIR/reference_prop.rs:+6:9: +6:19
                                            // mir::Constant
-                                           // + span: $DIR/reference_prop.rs:166:9: 166:15
+                                           // + span: $DIR/reference_prop.rs:202:9: 202:15
                                            // + literal: Const { ty: fn(()) {opaque::<()>}, val: Value(<ZST>) }
       }
   
@@ -203,7 +253,7 @@
           StorageDead(_7);                 // scope 4 at $DIR/reference_prop.rs:+6:19: +6:20
 -         _3 = const ();                   // scope 1 at $DIR/reference_prop.rs:+2:5: +7:6
           StorageDead(_6);                 // scope 3 at $DIR/reference_prop.rs:+7:5: +7:6
-          StorageDead(_5);                 // scope 2 at $DIR/reference_prop.rs:+7:5: +7:6
+-         StorageDead(_5);                 // scope 2 at $DIR/reference_prop.rs:+7:5: +7:6
           StorageDead(_4);                 // scope 1 at $DIR/reference_prop.rs:+7:5: +7:6
 -         StorageDead(_3);                 // scope 0 at $DIR/reference_prop.rs:+7:5: +7:6
 -         StorageLive(_9);                 // scope 0 at $DIR/reference_prop.rs:+10:5: +18:6
@@ -224,7 +274,7 @@
           _16 = ();                        // scope 9 at $DIR/reference_prop.rs:+17:16: +17:18
           _15 = opaque::<()>(move _16) -> bb2; // scope 9 at $DIR/reference_prop.rs:+17:9: +17:19
                                            // mir::Constant
-                                           // + span: $DIR/reference_prop.rs:177:9: 177:15
+                                           // + span: $DIR/reference_prop.rs:213:9: 213:15
                                            // + literal: Const { ty: fn(()) {opaque::<()>}, val: Value(<ZST>) }
       }
   
@@ -246,18 +296,18 @@
           _20 = &_19;                      // scope 12 at $DIR/reference_prop.rs:+24:17: +24:19
           StorageLive(_21);                // scope 13 at $DIR/reference_prop.rs:+25:13: +25:14
           _21 = (*_19);                    // scope 13 at $DIR/reference_prop.rs:+25:17: +25:19
-          StorageLive(_22);                // scope 14 at $DIR/reference_prop.rs:+26:9: +26:19
-          StorageLive(_23);                // scope 14 at $DIR/reference_prop.rs:+26:16: +26:18
-          _23 = ();                        // scope 14 at $DIR/reference_prop.rs:+26:16: +26:18
-          _22 = opaque::<()>(move _23) -> bb3; // scope 14 at $DIR/reference_prop.rs:+26:9: +26:19
+          StorageLive(_22);                // scope 14 at $DIR/reference_prop.rs:+26:9: +26:18
+          StorageLive(_23);                // scope 14 at $DIR/reference_prop.rs:+26:16: +26:17
+          _23 = _20;                       // scope 14 at $DIR/reference_prop.rs:+26:16: +26:17
+          _22 = opaque::<&*const usize>(move _23) -> bb3; // scope 14 at $DIR/reference_prop.rs:+26:9: +26:18
                                            // mir::Constant
-                                           // + span: $DIR/reference_prop.rs:186:9: 186:15
-                                           // + literal: Const { ty: fn(()) {opaque::<()>}, val: Value(<ZST>) }
+                                           // + span: $DIR/reference_prop.rs:222:9: 222:15
+                                           // + literal: Const { ty: fn(&*const usize) {opaque::<&*const usize>}, val: Value(<ZST>) }
       }
   
       bb3: {
-          StorageDead(_23);                // scope 14 at $DIR/reference_prop.rs:+26:18: +26:19
-          StorageDead(_22);                // scope 14 at $DIR/reference_prop.rs:+26:19: +26:20
+          StorageDead(_23);                // scope 14 at $DIR/reference_prop.rs:+26:17: +26:18
+          StorageDead(_22);                // scope 14 at $DIR/reference_prop.rs:+26:18: +26:19
 -         _17 = const ();                  // scope 10 at $DIR/reference_prop.rs:+21:5: +27:6
           StorageDead(_21);                // scope 13 at $DIR/reference_prop.rs:+27:5: +27:6
           StorageDead(_20);                // scope 12 at $DIR/reference_prop.rs:+27:5: +27:6
@@ -270,21 +320,21 @@
           StorageLive(_26);                // scope 16 at $DIR/reference_prop.rs:+32:13: +32:18
           _26 = &raw const _25;            // scope 16 at $DIR/reference_prop.rs:+32:21: +32:33
           StorageLive(_27);                // scope 17 at $DIR/reference_prop.rs:+33:13: +33:14
-          _27 = &mut _26;                  // scope 17 at $DIR/reference_prop.rs:+33:17: +33:23
+          _27 = &raw mut _26;              // scope 17 at $DIR/reference_prop.rs:+33:17: +33:27
           StorageLive(_28);                // scope 18 at $DIR/reference_prop.rs:+34:13: +34:14
           _28 = (*_26);                    // scope 18 at $DIR/reference_prop.rs:+34:17: +34:19
-          StorageLive(_29);                // scope 19 at $DIR/reference_prop.rs:+35:9: +35:19
-          StorageLive(_30);                // scope 19 at $DIR/reference_prop.rs:+35:16: +35:18
-          _30 = ();                        // scope 19 at $DIR/reference_prop.rs:+35:16: +35:18
-          _29 = opaque::<()>(move _30) -> bb4; // scope 19 at $DIR/reference_prop.rs:+35:9: +35:19
+          StorageLive(_29);                // scope 19 at $DIR/reference_prop.rs:+35:9: +35:18
+          StorageLive(_30);                // scope 19 at $DIR/reference_prop.rs:+35:16: +35:17
+          _30 = _27;                       // scope 19 at $DIR/reference_prop.rs:+35:16: +35:17
+          _29 = opaque::<*mut *const usize>(move _30) -> bb4; // scope 19 at $DIR/reference_prop.rs:+35:9: +35:18
                                            // mir::Constant
-                                           // + span: $DIR/reference_prop.rs:195:9: 195:15
-                                           // + literal: Const { ty: fn(()) {opaque::<()>}, val: Value(<ZST>) }
+                                           // + span: $DIR/reference_prop.rs:231:9: 231:15
+                                           // + literal: Const { ty: fn(*mut *const usize) {opaque::<*mut *const usize>}, val: Value(<ZST>) }
       }
   
       bb4: {
-          StorageDead(_30);                // scope 19 at $DIR/reference_prop.rs:+35:18: +35:19
-          StorageDead(_29);                // scope 19 at $DIR/reference_prop.rs:+35:19: +35:20
+          StorageDead(_30);                // scope 19 at $DIR/reference_prop.rs:+35:17: +35:18
+          StorageDead(_29);                // scope 19 at $DIR/reference_prop.rs:+35:18: +35:19
 -         _24 = const ();                  // scope 15 at $DIR/reference_prop.rs:+30:5: +36:6
           StorageDead(_28);                // scope 18 at $DIR/reference_prop.rs:+36:5: +36:6
           StorageDead(_27);                // scope 17 at $DIR/reference_prop.rs:+36:5: +36:6
@@ -304,7 +354,7 @@
           _36 = _33;                       // scope 23 at $DIR/reference_prop.rs:+43:16: +43:17
           _35 = opaque::<*const usize>(move _36) -> bb5; // scope 23 at $DIR/reference_prop.rs:+43:9: +43:18
                                            // mir::Constant
-                                           // + span: $DIR/reference_prop.rs:203:9: 203:15
+                                           // + span: $DIR/reference_prop.rs:239:9: 239:15
                                            // + literal: Const { ty: fn(*const usize) {opaque::<*const usize>}, val: Value(<ZST>) }
       }
   
@@ -336,7 +386,7 @@
           _45 = _43;                       // scope 30 at $DIR/reference_prop.rs:+56:16: +56:18
           _44 = opaque::<*const usize>(move _45) -> bb6; // scope 30 at $DIR/reference_prop.rs:+56:9: +56:19
                                            // mir::Constant
-                                           // + span: $DIR/reference_prop.rs:216:9: 216:15
+                                           // + span: $DIR/reference_prop.rs:252:9: 252:15
                                            // + literal: Const { ty: fn(*const usize) {opaque::<*const usize>}, val: Value(<ZST>) }
       }
   
@@ -352,8 +402,8 @@
           StorageDead(_38);                // scope 24 at $DIR/reference_prop.rs:+57:5: +57:6
 -         StorageDead(_37);                // scope 0 at $DIR/reference_prop.rs:+57:5: +57:6
 -         StorageLive(_46);                // scope 0 at $DIR/reference_prop.rs:+60:5: +64:6
-          StorageLive(_47);                // scope 31 at $DIR/reference_prop.rs:+61:13: +61:14
-          _47 = &raw const (*_1);          // scope 31 at $DIR/reference_prop.rs:+61:17: +61:35
+-         StorageLive(_47);                // scope 31 at $DIR/reference_prop.rs:+61:13: +61:14
+-         _47 = &raw const (*_1);          // scope 31 at $DIR/reference_prop.rs:+61:17: +61:35
           StorageLive(_48);                // scope 32 at $DIR/reference_prop.rs:+62:13: +62:14
 -         _48 = (*_47);                    // scope 32 at $DIR/reference_prop.rs:+62:17: +62:19
 +         _48 = (*_1);                     // scope 32 at $DIR/reference_prop.rs:+62:17: +62:19
@@ -362,7 +412,7 @@
           _50 = ();                        // scope 33 at $DIR/reference_prop.rs:+63:16: +63:18
           _49 = opaque::<()>(move _50) -> bb7; // scope 33 at $DIR/reference_prop.rs:+63:9: +63:19
                                            // mir::Constant
-                                           // + span: $DIR/reference_prop.rs:223:9: 223:15
+                                           // + span: $DIR/reference_prop.rs:259:9: 259:15
                                            // + literal: Const { ty: fn(()) {opaque::<()>}, val: Value(<ZST>) }
       }
   
@@ -371,7 +421,7 @@
           StorageDead(_49);                // scope 33 at $DIR/reference_prop.rs:+63:19: +63:20
 -         _46 = const ();                  // scope 31 at $DIR/reference_prop.rs:+60:5: +64:6
           StorageDead(_48);                // scope 32 at $DIR/reference_prop.rs:+64:5: +64:6
-          StorageDead(_47);                // scope 31 at $DIR/reference_prop.rs:+64:5: +64:6
+-         StorageDead(_47);                // scope 31 at $DIR/reference_prop.rs:+64:5: +64:6
 -         StorageDead(_46);                // scope 0 at $DIR/reference_prop.rs:+64:5: +64:6
 -         StorageLive(_51);                // scope 0 at $DIR/reference_prop.rs:+67:5: +72:6
           StorageLive(_52);                // scope 34 at $DIR/reference_prop.rs:+68:13: +68:14
@@ -387,7 +437,7 @@
           _56 = ();                        // scope 36 at $DIR/reference_prop.rs:+71:16: +71:18
           _55 = opaque::<()>(move _56) -> bb8; // scope 36 at $DIR/reference_prop.rs:+71:9: +71:19
                                            // mir::Constant
-                                           // + span: $DIR/reference_prop.rs:231:9: 231:15
+                                           // + span: $DIR/reference_prop.rs:267:9: 267:15
                                            // + literal: Const { ty: fn(()) {opaque::<()>}, val: Value(<ZST>) }
       }
   
@@ -398,34 +448,89 @@
           StorageDead(_54);                // scope 35 at $DIR/reference_prop.rs:+72:5: +72:6
           StorageDead(_52);                // scope 34 at $DIR/reference_prop.rs:+72:5: +72:6
 -         StorageDead(_51);                // scope 0 at $DIR/reference_prop.rs:+72:5: +72:6
-          StorageLive(_57);                // scope 37 at $DIR/reference_prop.rs:+76:13: +76:14
-          _57 = const 13_usize;            // scope 37 at $DIR/reference_prop.rs:+76:17: +76:25
-          StorageLive(_58);                // scope 38 at $DIR/reference_prop.rs:+77:13: +77:14
-          _58 = &raw const _57;            // scope 38 at $DIR/reference_prop.rs:+77:17: +77:29
-          StorageLive(_59);                // scope 39 at $DIR/reference_prop.rs:+78:13: +78:14
--         _59 = &raw const (*_58);         // scope 39 at $DIR/reference_prop.rs:+78:17: +78:30
-+         _59 = &raw const _57;            // scope 39 at $DIR/reference_prop.rs:+78:17: +78:30
-          StorageLive(_60);                // scope 40 at $DIR/reference_prop.rs:+79:13: +79:14
--         _60 = (*_59);                    // scope 40 at $DIR/reference_prop.rs:+79:17: +79:19
-+         _60 = _57;                       // scope 40 at $DIR/reference_prop.rs:+79:17: +79:19
-          StorageLive(_61);                // scope 41 at $DIR/reference_prop.rs:+80:9: +80:19
-          StorageLive(_62);                // scope 41 at $DIR/reference_prop.rs:+80:16: +80:18
-          _62 = ();                        // scope 41 at $DIR/reference_prop.rs:+80:16: +80:18
-          _61 = opaque::<()>(move _62) -> bb9; // scope 41 at $DIR/reference_prop.rs:+80:9: +80:19
+-         StorageLive(_57);                // scope 0 at $DIR/reference_prop.rs:+75:5: +81:6
+          StorageLive(_58);                // scope 37 at $DIR/reference_prop.rs:+76:13: +76:14
+          _58 = const 13_usize;            // scope 37 at $DIR/reference_prop.rs:+76:17: +76:25
+-         StorageLive(_59);                // scope 38 at $DIR/reference_prop.rs:+77:13: +77:14
+-         _59 = &raw const _58;            // scope 38 at $DIR/reference_prop.rs:+77:17: +77:29
+-         StorageLive(_60);                // scope 39 at $DIR/reference_prop.rs:+78:13: +78:14
+-         _60 = &raw const (*_59);         // scope 39 at $DIR/reference_prop.rs:+78:17: +78:30
+          StorageLive(_61);                // scope 40 at $DIR/reference_prop.rs:+79:13: +79:14
+-         _61 = (*_60);                    // scope 40 at $DIR/reference_prop.rs:+79:17: +79:19
++         _61 = _58;                       // scope 40 at $DIR/reference_prop.rs:+79:17: +79:19
+          StorageLive(_62);                // scope 41 at $DIR/reference_prop.rs:+80:9: +80:19
+          StorageLive(_63);                // scope 41 at $DIR/reference_prop.rs:+80:16: +80:18
+          _63 = ();                        // scope 41 at $DIR/reference_prop.rs:+80:16: +80:18
+          _62 = opaque::<()>(move _63) -> bb9; // scope 41 at $DIR/reference_prop.rs:+80:9: +80:19
                                            // mir::Constant
-                                           // + span: $DIR/reference_prop.rs:240:9: 240:15
+                                           // + span: $DIR/reference_prop.rs:276:9: 276:15
                                            // + literal: Const { ty: fn(()) {opaque::<()>}, val: Value(<ZST>) }
       }
   
       bb9: {
-          StorageDead(_62);                // scope 41 at $DIR/reference_prop.rs:+80:18: +80:19
-          StorageDead(_61);                // scope 41 at $DIR/reference_prop.rs:+80:19: +80:20
-          _0 = const ();                   // scope 37 at $DIR/reference_prop.rs:+75:5: +81:6
-          StorageDead(_60);                // scope 40 at $DIR/reference_prop.rs:+81:5: +81:6
-          StorageDead(_59);                // scope 39 at $DIR/reference_prop.rs:+81:5: +81:6
-          StorageDead(_58);                // scope 38 at $DIR/reference_prop.rs:+81:5: +81:6
-          StorageDead(_57);                // scope 37 at $DIR/reference_prop.rs:+81:5: +81:6
-          return;                          // scope 0 at $DIR/reference_prop.rs:+82:2: +82:2
+          StorageDead(_63);                // scope 41 at $DIR/reference_prop.rs:+80:18: +80:19
+          StorageDead(_62);                // scope 41 at $DIR/reference_prop.rs:+80:19: +80:20
+-         _57 = const ();                  // scope 37 at $DIR/reference_prop.rs:+75:5: +81:6
+          StorageDead(_61);                // scope 40 at $DIR/reference_prop.rs:+81:5: +81:6
+-         StorageDead(_60);                // scope 39 at $DIR/reference_prop.rs:+81:5: +81:6
+-         StorageDead(_59);                // scope 38 at $DIR/reference_prop.rs:+81:5: +81:6
+          StorageDead(_58);                // scope 37 at $DIR/reference_prop.rs:+81:5: +81:6
+-         StorageDead(_57);                // scope 0 at $DIR/reference_prop.rs:+81:5: +81:6
+-         StorageLive(_64);                // scope 0 at $DIR/reference_prop.rs:+84:5: +90:6
+          StorageLive(_65);                // scope 42 at $DIR/reference_prop.rs:+85:13: +85:14
+          _65 = const 5_usize;             // scope 42 at $DIR/reference_prop.rs:+85:17: +85:24
+-         StorageLive(_66);                // scope 43 at $DIR/reference_prop.rs:+86:13: +86:14
+-         _66 = &raw const _65;            // scope 43 at $DIR/reference_prop.rs:+86:17: +86:29
+-         StorageLive(_67);                // scope 44 at $DIR/reference_prop.rs:+87:13: +87:14
+-         _67 = &_66;                      // scope 44 at $DIR/reference_prop.rs:+87:17: +87:19
+          StorageLive(_68);                // scope 45 at $DIR/reference_prop.rs:+88:13: +88:14
+-         _68 = (*_66);                    // scope 45 at $DIR/reference_prop.rs:+88:17: +88:19
++         _68 = _65;                       // scope 45 at $DIR/reference_prop.rs:+88:17: +88:19
+          StorageLive(_69);                // scope 46 at $DIR/reference_prop.rs:+89:9: +89:19
+          StorageLive(_70);                // scope 46 at $DIR/reference_prop.rs:+89:16: +89:18
+          _70 = ();                        // scope 46 at $DIR/reference_prop.rs:+89:16: +89:18
+          _69 = opaque::<()>(move _70) -> bb10; // scope 46 at $DIR/reference_prop.rs:+89:9: +89:19
+                                           // mir::Constant
+                                           // + span: $DIR/reference_prop.rs:285:9: 285:15
+                                           // + literal: Const { ty: fn(()) {opaque::<()>}, val: Value(<ZST>) }
+      }
+  
+      bb10: {
+          StorageDead(_70);                // scope 46 at $DIR/reference_prop.rs:+89:18: +89:19
+          StorageDead(_69);                // scope 46 at $DIR/reference_prop.rs:+89:19: +89:20
+-         _64 = const ();                  // scope 42 at $DIR/reference_prop.rs:+84:5: +90:6
+          StorageDead(_68);                // scope 45 at $DIR/reference_prop.rs:+90:5: +90:6
+-         StorageDead(_67);                // scope 44 at $DIR/reference_prop.rs:+90:5: +90:6
+-         StorageDead(_66);                // scope 43 at $DIR/reference_prop.rs:+90:5: +90:6
+          StorageDead(_65);                // scope 42 at $DIR/reference_prop.rs:+90:5: +90:6
+-         StorageDead(_64);                // scope 0 at $DIR/reference_prop.rs:+90:5: +90:6
+          StorageLive(_71);                // scope 47 at $DIR/reference_prop.rs:+94:13: +94:14
+          _71 = const 5_usize;             // scope 47 at $DIR/reference_prop.rs:+94:17: +94:24
+-         StorageLive(_72);                // scope 48 at $DIR/reference_prop.rs:+95:13: +95:18
+-         _72 = &raw const _71;            // scope 48 at $DIR/reference_prop.rs:+95:21: +95:33
+-         StorageLive(_73);                // scope 49 at $DIR/reference_prop.rs:+96:13: +96:14
+-         _73 = &mut _72;                  // scope 49 at $DIR/reference_prop.rs:+96:17: +96:23
+          StorageLive(_74);                // scope 50 at $DIR/reference_prop.rs:+97:13: +97:14
+-         _74 = (*_72);                    // scope 50 at $DIR/reference_prop.rs:+97:17: +97:19
++         _74 = _71;                       // scope 50 at $DIR/reference_prop.rs:+97:17: +97:19
+          StorageLive(_75);                // scope 51 at $DIR/reference_prop.rs:+98:9: +98:19
+          StorageLive(_76);                // scope 51 at $DIR/reference_prop.rs:+98:16: +98:18
+          _76 = ();                        // scope 51 at $DIR/reference_prop.rs:+98:16: +98:18
+          _75 = opaque::<()>(move _76) -> bb11; // scope 51 at $DIR/reference_prop.rs:+98:9: +98:19
+                                           // mir::Constant
+                                           // + span: $DIR/reference_prop.rs:294:9: 294:15
+                                           // + literal: Const { ty: fn(()) {opaque::<()>}, val: Value(<ZST>) }
+      }
+  
+      bb11: {
+          StorageDead(_76);                // scope 51 at $DIR/reference_prop.rs:+98:18: +98:19
+          StorageDead(_75);                // scope 51 at $DIR/reference_prop.rs:+98:19: +98:20
+          _0 = const ();                   // scope 47 at $DIR/reference_prop.rs:+93:5: +99:6
+          StorageDead(_74);                // scope 50 at $DIR/reference_prop.rs:+99:5: +99:6
+-         StorageDead(_73);                // scope 49 at $DIR/reference_prop.rs:+99:5: +99:6
+-         StorageDead(_72);                // scope 48 at $DIR/reference_prop.rs:+99:5: +99:6
+          StorageDead(_71);                // scope 47 at $DIR/reference_prop.rs:+99:5: +99:6
+          return;                          // scope 0 at $DIR/reference_prop.rs:+100:2: +100:2
       }
   }
   
diff --git a/tests/mir-opt/reference_prop.reference_propagation_mut.ReferencePropagation.diff b/tests/mir-opt/reference_prop.reference_propagation_mut.ReferencePropagation.diff
index 44ddbbc3066..8d059de5b87 100644
--- a/tests/mir-opt/reference_prop.reference_propagation_mut.ReferencePropagation.diff
+++ b/tests/mir-opt/reference_prop.reference_propagation_mut.ReferencePropagation.diff
@@ -17,12 +17,12 @@
       let mut _17: ();                     // in scope 0 at $DIR/reference_prop.rs:+17:16: +17:18
       let _18: ();                         // in scope 0 at $DIR/reference_prop.rs:+21:5: +27:6
       let mut _19: usize;                  // in scope 0 at $DIR/reference_prop.rs:+22:13: +22:18
-      let _23: ();                         // in scope 0 at $DIR/reference_prop.rs:+26:9: +26:19
-      let mut _24: ();                     // in scope 0 at $DIR/reference_prop.rs:+26:16: +26:18
+      let _23: ();                         // in scope 0 at $DIR/reference_prop.rs:+26:9: +26:18
+      let mut _24: &&mut usize;            // in scope 0 at $DIR/reference_prop.rs:+26:16: +26:17
       let _25: ();                         // in scope 0 at $DIR/reference_prop.rs:+30:5: +36:6
       let mut _26: usize;                  // in scope 0 at $DIR/reference_prop.rs:+31:13: +31:18
-      let _30: ();                         // in scope 0 at $DIR/reference_prop.rs:+35:9: +35:19
-      let mut _31: ();                     // in scope 0 at $DIR/reference_prop.rs:+35:16: +35:18
+      let _30: ();                         // in scope 0 at $DIR/reference_prop.rs:+35:9: +35:18
+      let mut _31: *mut &mut usize;        // in scope 0 at $DIR/reference_prop.rs:+35:16: +35:17
       let _32: ();                         // in scope 0 at $DIR/reference_prop.rs:+39:5: +44:6
       let mut _33: usize;                  // in scope 0 at $DIR/reference_prop.rs:+40:13: +40:18
       let _36: ();                         // in scope 0 at $DIR/reference_prop.rs:+43:9: +43:18
@@ -35,16 +35,25 @@
       let _48: &mut T;                     // in scope 0 at $DIR/reference_prop.rs:+61:13: +61:14
       let _50: ();                         // in scope 0 at $DIR/reference_prop.rs:+63:9: +63:19
       let mut _51: ();                     // in scope 0 at $DIR/reference_prop.rs:+63:16: +63:18
-      let _52: &mut T;                     // in scope 0 at $DIR/reference_prop.rs:+68:13: +68:14
-      let mut _53: &mut T;                 // in scope 0 at $DIR/reference_prop.rs:+69:20: +69:32
+      let _52: ();                         // in scope 0 at $DIR/reference_prop.rs:+67:5: +72:6
+      let _53: &mut T;                     // in scope 0 at $DIR/reference_prop.rs:+68:13: +68:14
       let mut _54: &mut T;                 // in scope 0 at $DIR/reference_prop.rs:+69:20: +69:32
-      let _56: ();                         // in scope 0 at $DIR/reference_prop.rs:+71:9: +71:19
-      let mut _57: ();                     // in scope 0 at $DIR/reference_prop.rs:+71:16: +71:18
+      let mut _55: &mut T;                 // in scope 0 at $DIR/reference_prop.rs:+69:20: +69:32
+      let _57: ();                         // in scope 0 at $DIR/reference_prop.rs:+71:9: +71:19
+      let mut _58: ();                     // in scope 0 at $DIR/reference_prop.rs:+71:16: +71:18
+      let _59: ();                         // in scope 0 at $DIR/reference_prop.rs:+75:5: +81:6
+      let mut _60: usize;                  // in scope 0 at $DIR/reference_prop.rs:+76:13: +76:18
+      let _64: ();                         // in scope 0 at $DIR/reference_prop.rs:+80:9: +80:19
+      let mut _65: ();                     // in scope 0 at $DIR/reference_prop.rs:+80:16: +80:18
+      let mut _66: usize;                  // in scope 0 at $DIR/reference_prop.rs:+85:13: +85:18
+      let _70: ();                         // in scope 0 at $DIR/reference_prop.rs:+89:9: +89:19
+      let mut _71: ();                     // in scope 0 at $DIR/reference_prop.rs:+89:16: +89:18
       scope 1 {
           debug a => _4;                   // in scope 1 at $DIR/reference_prop.rs:+3:13: +3:18
           let _5: &mut usize;              // in scope 1 at $DIR/reference_prop.rs:+4:13: +4:14
           scope 2 {
-              debug b => _5;               // in scope 2 at $DIR/reference_prop.rs:+4:13: +4:14
+-             debug b => _5;               // in scope 2 at $DIR/reference_prop.rs:+4:13: +4:14
++             debug b => &_4;              // in scope 2 at $DIR/reference_prop.rs:+4:13: +4:14
               let _6: usize;               // in scope 2 at $DIR/reference_prop.rs:+5:13: +5:14
               scope 3 {
                   debug c => _6;           // in scope 3 at $DIR/reference_prop.rs:+5:13: +5:14
@@ -86,7 +95,7 @@
           let mut _27: &mut usize;         // in scope 12 at $DIR/reference_prop.rs:+32:13: +32:18
           scope 13 {
               debug b => _27;              // in scope 13 at $DIR/reference_prop.rs:+32:13: +32:18
-              let _28: &mut &mut usize;    // in scope 13 at $DIR/reference_prop.rs:+33:13: +33:14
+              let _28: *mut &mut usize;    // in scope 13 at $DIR/reference_prop.rs:+33:13: +33:14
               scope 14 {
                   debug d => _28;          // in scope 14 at $DIR/reference_prop.rs:+33:13: +33:14
                   let _29: usize;          // in scope 14 at $DIR/reference_prop.rs:+34:13: +34:14
@@ -131,17 +140,52 @@
           }
       }
       scope 25 {
-          debug a => _48;                  // in scope 25 at $DIR/reference_prop.rs:+61:13: +61:14
+-         debug a => _48;                  // in scope 25 at $DIR/reference_prop.rs:+61:13: +61:14
++         debug a => _1;                   // in scope 25 at $DIR/reference_prop.rs:+61:13: +61:14
           let _49: T;                      // in scope 25 at $DIR/reference_prop.rs:+62:13: +62:14
           scope 26 {
               debug b => _49;              // in scope 26 at $DIR/reference_prop.rs:+62:13: +62:14
           }
       }
       scope 27 {
-          debug a => _52;                  // in scope 27 at $DIR/reference_prop.rs:+68:13: +68:14
-          let _55: T;                      // in scope 27 at $DIR/reference_prop.rs:+70:13: +70:14
+          debug a => _53;                  // in scope 27 at $DIR/reference_prop.rs:+68:13: +68:14
+          let _56: T;                      // in scope 27 at $DIR/reference_prop.rs:+70:13: +70:14
           scope 28 {
-              debug b => _55;              // in scope 28 at $DIR/reference_prop.rs:+70:13: +70:14
+              debug b => _56;              // in scope 28 at $DIR/reference_prop.rs:+70:13: +70:14
+          }
+      }
+      scope 29 {
+          debug a => _60;                  // in scope 29 at $DIR/reference_prop.rs:+76:13: +76:18
+          let _61: &mut usize;             // in scope 29 at $DIR/reference_prop.rs:+77:13: +77:14
+          scope 30 {
+-             debug b => _61;              // in scope 30 at $DIR/reference_prop.rs:+77:13: +77:14
++             debug b => &_60;             // in scope 30 at $DIR/reference_prop.rs:+77:13: +77:14
+              let _62: &&mut usize;        // in scope 30 at $DIR/reference_prop.rs:+78:13: +78:14
+              scope 31 {
+-                 debug d => _62;          // in scope 31 at $DIR/reference_prop.rs:+78:13: +78:14
++                 debug d => &&_60;        // in scope 31 at $DIR/reference_prop.rs:+78:13: +78:14
+                  let _63: usize;          // in scope 31 at $DIR/reference_prop.rs:+79:13: +79:14
+                  scope 32 {
+                      debug c => _63;      // in scope 32 at $DIR/reference_prop.rs:+79:13: +79:14
+                  }
+              }
+          }
+      }
+      scope 33 {
+          debug a => _66;                  // in scope 33 at $DIR/reference_prop.rs:+85:13: +85:18
+          let mut _67: &mut usize;         // in scope 33 at $DIR/reference_prop.rs:+86:13: +86:18
+          scope 34 {
+-             debug b => _67;              // in scope 34 at $DIR/reference_prop.rs:+86:13: +86:18
++             debug b => &_66;             // in scope 34 at $DIR/reference_prop.rs:+86:13: +86:18
+              let _68: &mut &mut usize;    // in scope 34 at $DIR/reference_prop.rs:+87:13: +87:14
+              scope 35 {
+-                 debug d => _68;          // in scope 35 at $DIR/reference_prop.rs:+87:13: +87:14
++                 debug d => &&_66;        // in scope 35 at $DIR/reference_prop.rs:+87:13: +87:14
+                  let _69: usize;          // in scope 35 at $DIR/reference_prop.rs:+88:13: +88:14
+                  scope 36 {
+                      debug c => _69;      // in scope 36 at $DIR/reference_prop.rs:+88:13: +88:14
+                  }
+              }
           }
       }
   
@@ -149,8 +193,8 @@
 -         StorageLive(_3);                 // scope 0 at $DIR/reference_prop.rs:+2:5: +7:6
           StorageLive(_4);                 // scope 0 at $DIR/reference_prop.rs:+3:13: +3:18
           _4 = const 5_usize;              // scope 0 at $DIR/reference_prop.rs:+3:21: +3:28
-          StorageLive(_5);                 // scope 1 at $DIR/reference_prop.rs:+4:13: +4:14
-          _5 = &mut _4;                    // scope 1 at $DIR/reference_prop.rs:+4:17: +4:23
+-         StorageLive(_5);                 // scope 1 at $DIR/reference_prop.rs:+4:13: +4:14
+-         _5 = &mut _4;                    // scope 1 at $DIR/reference_prop.rs:+4:17: +4:23
           StorageLive(_6);                 // scope 2 at $DIR/reference_prop.rs:+5:13: +5:14
 -         _6 = (*_5);                      // scope 2 at $DIR/reference_prop.rs:+5:17: +5:19
 +         _6 = _4;                         // scope 2 at $DIR/reference_prop.rs:+5:17: +5:19
@@ -159,7 +203,7 @@
           _8 = ();                         // scope 3 at $DIR/reference_prop.rs:+6:16: +6:18
           _7 = opaque::<()>(move _8) -> bb1; // scope 3 at $DIR/reference_prop.rs:+6:9: +6:19
                                            // mir::Constant
-                                           // + span: $DIR/reference_prop.rs:91:9: 91:15
+                                           // + span: $DIR/reference_prop.rs:109:9: 109:15
                                            // + literal: Const { ty: fn(()) {opaque::<()>}, val: Value(<ZST>) }
       }
   
@@ -168,7 +212,7 @@
           StorageDead(_7);                 // scope 3 at $DIR/reference_prop.rs:+6:19: +6:20
 -         _3 = const ();                   // scope 0 at $DIR/reference_prop.rs:+2:5: +7:6
           StorageDead(_6);                 // scope 2 at $DIR/reference_prop.rs:+7:5: +7:6
-          StorageDead(_5);                 // scope 1 at $DIR/reference_prop.rs:+7:5: +7:6
+-         StorageDead(_5);                 // scope 1 at $DIR/reference_prop.rs:+7:5: +7:6
           StorageDead(_4);                 // scope 0 at $DIR/reference_prop.rs:+7:5: +7:6
 -         StorageDead(_3);                 // scope 0 at $DIR/reference_prop.rs:+7:5: +7:6
 -         StorageLive(_9);                 // scope 0 at $DIR/reference_prop.rs:+10:5: +18:6
@@ -193,7 +237,7 @@
           _17 = ();                        // scope 7 at $DIR/reference_prop.rs:+17:16: +17:18
           _16 = opaque::<()>(move _17) -> bb2; // scope 7 at $DIR/reference_prop.rs:+17:9: +17:19
                                            // mir::Constant
-                                           // + span: $DIR/reference_prop.rs:102:9: 102:15
+                                           // + span: $DIR/reference_prop.rs:120:9: 120:15
                                            // + literal: Const { ty: fn(()) {opaque::<()>}, val: Value(<ZST>) }
       }
   
@@ -215,18 +259,18 @@
           _21 = &_20;                      // scope 9 at $DIR/reference_prop.rs:+24:17: +24:19
           StorageLive(_22);                // scope 10 at $DIR/reference_prop.rs:+25:13: +25:14
           _22 = (*_20);                    // scope 10 at $DIR/reference_prop.rs:+25:17: +25:19
-          StorageLive(_23);                // scope 11 at $DIR/reference_prop.rs:+26:9: +26:19
-          StorageLive(_24);                // scope 11 at $DIR/reference_prop.rs:+26:16: +26:18
-          _24 = ();                        // scope 11 at $DIR/reference_prop.rs:+26:16: +26:18
-          _23 = opaque::<()>(move _24) -> bb3; // scope 11 at $DIR/reference_prop.rs:+26:9: +26:19
+          StorageLive(_23);                // scope 11 at $DIR/reference_prop.rs:+26:9: +26:18
+          StorageLive(_24);                // scope 11 at $DIR/reference_prop.rs:+26:16: +26:17
+          _24 = _21;                       // scope 11 at $DIR/reference_prop.rs:+26:16: +26:17
+          _23 = opaque::<&&mut usize>(move _24) -> bb3; // scope 11 at $DIR/reference_prop.rs:+26:9: +26:18
                                            // mir::Constant
-                                           // + span: $DIR/reference_prop.rs:111:9: 111:15
-                                           // + literal: Const { ty: fn(()) {opaque::<()>}, val: Value(<ZST>) }
+                                           // + span: $DIR/reference_prop.rs:129:9: 129:15
+                                           // + literal: Const { ty: fn(&&mut usize) {opaque::<&&mut usize>}, val: Value(<ZST>) }
       }
   
       bb3: {
-          StorageDead(_24);                // scope 11 at $DIR/reference_prop.rs:+26:18: +26:19
-          StorageDead(_23);                // scope 11 at $DIR/reference_prop.rs:+26:19: +26:20
+          StorageDead(_24);                // scope 11 at $DIR/reference_prop.rs:+26:17: +26:18
+          StorageDead(_23);                // scope 11 at $DIR/reference_prop.rs:+26:18: +26:19
 -         _18 = const ();                  // scope 0 at $DIR/reference_prop.rs:+21:5: +27:6
           StorageDead(_22);                // scope 10 at $DIR/reference_prop.rs:+27:5: +27:6
           StorageDead(_21);                // scope 9 at $DIR/reference_prop.rs:+27:5: +27:6
@@ -239,21 +283,21 @@
           StorageLive(_27);                // scope 12 at $DIR/reference_prop.rs:+32:13: +32:18
           _27 = &mut _26;                  // scope 12 at $DIR/reference_prop.rs:+32:21: +32:27
           StorageLive(_28);                // scope 13 at $DIR/reference_prop.rs:+33:13: +33:14
-          _28 = &mut _27;                  // scope 13 at $DIR/reference_prop.rs:+33:17: +33:23
+          _28 = &raw mut _27;              // scope 13 at $DIR/reference_prop.rs:+33:17: +33:27
           StorageLive(_29);                // scope 14 at $DIR/reference_prop.rs:+34:13: +34:14
           _29 = (*_27);                    // scope 14 at $DIR/reference_prop.rs:+34:17: +34:19
-          StorageLive(_30);                // scope 15 at $DIR/reference_prop.rs:+35:9: +35:19
-          StorageLive(_31);                // scope 15 at $DIR/reference_prop.rs:+35:16: +35:18
-          _31 = ();                        // scope 15 at $DIR/reference_prop.rs:+35:16: +35:18
-          _30 = opaque::<()>(move _31) -> bb4; // scope 15 at $DIR/reference_prop.rs:+35:9: +35:19
+          StorageLive(_30);                // scope 15 at $DIR/reference_prop.rs:+35:9: +35:18
+          StorageLive(_31);                // scope 15 at $DIR/reference_prop.rs:+35:16: +35:17
+          _31 = _28;                       // scope 15 at $DIR/reference_prop.rs:+35:16: +35:17
+          _30 = opaque::<*mut &mut usize>(move _31) -> bb4; // scope 15 at $DIR/reference_prop.rs:+35:9: +35:18
                                            // mir::Constant
-                                           // + span: $DIR/reference_prop.rs:120:9: 120:15
-                                           // + literal: Const { ty: fn(()) {opaque::<()>}, val: Value(<ZST>) }
+                                           // + span: $DIR/reference_prop.rs:138:9: 138:15
+                                           // + literal: Const { ty: fn(*mut &mut usize) {opaque::<*mut &mut usize>}, val: Value(<ZST>) }
       }
   
       bb4: {
-          StorageDead(_31);                // scope 15 at $DIR/reference_prop.rs:+35:18: +35:19
-          StorageDead(_30);                // scope 15 at $DIR/reference_prop.rs:+35:19: +35:20
+          StorageDead(_31);                // scope 15 at $DIR/reference_prop.rs:+35:17: +35:18
+          StorageDead(_30);                // scope 15 at $DIR/reference_prop.rs:+35:18: +35:19
 -         _25 = const ();                  // scope 0 at $DIR/reference_prop.rs:+30:5: +36:6
           StorageDead(_29);                // scope 14 at $DIR/reference_prop.rs:+36:5: +36:6
           StorageDead(_28);                // scope 13 at $DIR/reference_prop.rs:+36:5: +36:6
@@ -272,7 +316,7 @@
           _37 = move _34;                  // scope 18 at $DIR/reference_prop.rs:+43:16: +43:17
           _36 = opaque::<&mut usize>(move _37) -> bb5; // scope 18 at $DIR/reference_prop.rs:+43:9: +43:18
                                            // mir::Constant
-                                           // + span: $DIR/reference_prop.rs:128:9: 128:15
+                                           // + span: $DIR/reference_prop.rs:146:9: 146:15
                                            // + literal: Const { ty: fn(&mut usize) {opaque::<&mut usize>}, val: Value(<ZST>) }
       }
   
@@ -302,7 +346,7 @@
           _46 = move _44;                  // scope 24 at $DIR/reference_prop.rs:+56:16: +56:18
           _45 = opaque::<&mut usize>(move _46) -> bb6; // scope 24 at $DIR/reference_prop.rs:+56:9: +56:19
                                            // mir::Constant
-                                           // + span: $DIR/reference_prop.rs:141:9: 141:15
+                                           // + span: $DIR/reference_prop.rs:159:9: 159:15
                                            // + literal: Const { ty: fn(&mut usize) {opaque::<&mut usize>}, val: Value(<ZST>) }
       }
   
@@ -318,8 +362,8 @@
           StorageDead(_39);                // scope 0 at $DIR/reference_prop.rs:+57:5: +57:6
 -         StorageDead(_38);                // scope 0 at $DIR/reference_prop.rs:+57:5: +57:6
 -         StorageLive(_47);                // scope 0 at $DIR/reference_prop.rs:+60:5: +64:6
-          StorageLive(_48);                // scope 0 at $DIR/reference_prop.rs:+61:13: +61:14
-          _48 = &mut (*_1);                // scope 0 at $DIR/reference_prop.rs:+61:17: +61:29
+-         StorageLive(_48);                // scope 0 at $DIR/reference_prop.rs:+61:13: +61:14
+-         _48 = &mut (*_1);                // scope 0 at $DIR/reference_prop.rs:+61:17: +61:29
           StorageLive(_49);                // scope 25 at $DIR/reference_prop.rs:+62:13: +62:14
 -         _49 = (*_48);                    // scope 25 at $DIR/reference_prop.rs:+62:17: +62:19
 +         _49 = (*_1);                     // scope 25 at $DIR/reference_prop.rs:+62:17: +62:19
@@ -328,7 +372,7 @@
           _51 = ();                        // scope 26 at $DIR/reference_prop.rs:+63:16: +63:18
           _50 = opaque::<()>(move _51) -> bb7; // scope 26 at $DIR/reference_prop.rs:+63:9: +63:19
                                            // mir::Constant
-                                           // + span: $DIR/reference_prop.rs:148:9: 148:15
+                                           // + span: $DIR/reference_prop.rs:166:9: 166:15
                                            // + literal: Const { ty: fn(()) {opaque::<()>}, val: Value(<ZST>) }
       }
   
@@ -337,36 +381,92 @@
           StorageDead(_50);                // scope 26 at $DIR/reference_prop.rs:+63:19: +63:20
 -         _47 = const ();                  // scope 0 at $DIR/reference_prop.rs:+60:5: +64:6
           StorageDead(_49);                // scope 25 at $DIR/reference_prop.rs:+64:5: +64:6
-          StorageDead(_48);                // scope 0 at $DIR/reference_prop.rs:+64:5: +64:6
+-         StorageDead(_48);                // scope 0 at $DIR/reference_prop.rs:+64:5: +64:6
 -         StorageDead(_47);                // scope 0 at $DIR/reference_prop.rs:+64:5: +64:6
-          StorageLive(_52);                // scope 0 at $DIR/reference_prop.rs:+68:13: +68:14
-          _52 = &mut (*_2);                // scope 0 at $DIR/reference_prop.rs:+68:17: +68:31
-          StorageLive(_53);                // scope 27 at $DIR/reference_prop.rs:+69:20: +69:32
--         StorageLive(_54);                // scope 27 at $DIR/reference_prop.rs:+69:20: +69:32
--         _54 = &mut (*_1);                // scope 27 at $DIR/reference_prop.rs:+69:20: +69:32
--         _53 = &mut (*_54);               // scope 27 at $DIR/reference_prop.rs:+69:20: +69:32
-+         _53 = &mut (*_1);                // scope 27 at $DIR/reference_prop.rs:+69:20: +69:32
-          _2 = move _53;                   // scope 27 at $DIR/reference_prop.rs:+69:9: +69:32
-          StorageDead(_53);                // scope 27 at $DIR/reference_prop.rs:+69:31: +69:32
--         StorageDead(_54);                // scope 27 at $DIR/reference_prop.rs:+69:32: +69:33
-          StorageLive(_55);                // scope 27 at $DIR/reference_prop.rs:+70:13: +70:14
-          _55 = (*_52);                    // scope 27 at $DIR/reference_prop.rs:+70:17: +70:19
-          StorageLive(_56);                // scope 28 at $DIR/reference_prop.rs:+71:9: +71:19
-          StorageLive(_57);                // scope 28 at $DIR/reference_prop.rs:+71:16: +71:18
-          _57 = ();                        // scope 28 at $DIR/reference_prop.rs:+71:16: +71:18
-          _56 = opaque::<()>(move _57) -> bb8; // scope 28 at $DIR/reference_prop.rs:+71:9: +71:19
+-         StorageLive(_52);                // scope 0 at $DIR/reference_prop.rs:+67:5: +72:6
+          StorageLive(_53);                // scope 0 at $DIR/reference_prop.rs:+68:13: +68:14
+          _53 = &mut (*_2);                // scope 0 at $DIR/reference_prop.rs:+68:17: +68:31
+          StorageLive(_54);                // scope 27 at $DIR/reference_prop.rs:+69:20: +69:32
+-         StorageLive(_55);                // scope 27 at $DIR/reference_prop.rs:+69:20: +69:32
+-         _55 = &mut (*_1);                // scope 27 at $DIR/reference_prop.rs:+69:20: +69:32
+-         _54 = &mut (*_55);               // scope 27 at $DIR/reference_prop.rs:+69:20: +69:32
++         _54 = &mut (*_1);                // scope 27 at $DIR/reference_prop.rs:+69:20: +69:32
+          _2 = move _54;                   // scope 27 at $DIR/reference_prop.rs:+69:9: +69:32
+          StorageDead(_54);                // scope 27 at $DIR/reference_prop.rs:+69:31: +69:32
+-         StorageDead(_55);                // scope 27 at $DIR/reference_prop.rs:+69:32: +69:33
+          StorageLive(_56);                // scope 27 at $DIR/reference_prop.rs:+70:13: +70:14
+          _56 = (*_53);                    // scope 27 at $DIR/reference_prop.rs:+70:17: +70:19
+          StorageLive(_57);                // scope 28 at $DIR/reference_prop.rs:+71:9: +71:19
+          StorageLive(_58);                // scope 28 at $DIR/reference_prop.rs:+71:16: +71:18
+          _58 = ();                        // scope 28 at $DIR/reference_prop.rs:+71:16: +71:18
+          _57 = opaque::<()>(move _58) -> bb8; // scope 28 at $DIR/reference_prop.rs:+71:9: +71:19
                                            // mir::Constant
-                                           // + span: $DIR/reference_prop.rs:156:9: 156:15
+                                           // + span: $DIR/reference_prop.rs:174:9: 174:15
                                            // + literal: Const { ty: fn(()) {opaque::<()>}, val: Value(<ZST>) }
       }
   
       bb8: {
-          StorageDead(_57);                // scope 28 at $DIR/reference_prop.rs:+71:18: +71:19
-          StorageDead(_56);                // scope 28 at $DIR/reference_prop.rs:+71:19: +71:20
-          _0 = const ();                   // scope 0 at $DIR/reference_prop.rs:+67:5: +72:6
-          StorageDead(_55);                // scope 27 at $DIR/reference_prop.rs:+72:5: +72:6
-          StorageDead(_52);                // scope 0 at $DIR/reference_prop.rs:+72:5: +72:6
-          return;                          // scope 0 at $DIR/reference_prop.rs:+73:2: +73:2
+          StorageDead(_58);                // scope 28 at $DIR/reference_prop.rs:+71:18: +71:19
+          StorageDead(_57);                // scope 28 at $DIR/reference_prop.rs:+71:19: +71:20
+-         _52 = const ();                  // scope 0 at $DIR/reference_prop.rs:+67:5: +72:6
+          StorageDead(_56);                // scope 27 at $DIR/reference_prop.rs:+72:5: +72:6
+          StorageDead(_53);                // scope 0 at $DIR/reference_prop.rs:+72:5: +72:6
+-         StorageDead(_52);                // scope 0 at $DIR/reference_prop.rs:+72:5: +72:6
+-         StorageLive(_59);                // scope 0 at $DIR/reference_prop.rs:+75:5: +81:6
+          StorageLive(_60);                // scope 0 at $DIR/reference_prop.rs:+76:13: +76:18
+          _60 = const 5_usize;             // scope 0 at $DIR/reference_prop.rs:+76:21: +76:28
+-         StorageLive(_61);                // scope 29 at $DIR/reference_prop.rs:+77:13: +77:14
+-         _61 = &mut _60;                  // scope 29 at $DIR/reference_prop.rs:+77:17: +77:23
+-         StorageLive(_62);                // scope 30 at $DIR/reference_prop.rs:+78:13: +78:14
+-         _62 = &_61;                      // scope 30 at $DIR/reference_prop.rs:+78:17: +78:19
+          StorageLive(_63);                // scope 31 at $DIR/reference_prop.rs:+79:13: +79:14
+-         _63 = (*_61);                    // scope 31 at $DIR/reference_prop.rs:+79:17: +79:19
++         _63 = _60;                       // scope 31 at $DIR/reference_prop.rs:+79:17: +79:19
+          StorageLive(_64);                // scope 32 at $DIR/reference_prop.rs:+80:9: +80:19
+          StorageLive(_65);                // scope 32 at $DIR/reference_prop.rs:+80:16: +80:18
+          _65 = ();                        // scope 32 at $DIR/reference_prop.rs:+80:16: +80:18
+          _64 = opaque::<()>(move _65) -> bb9; // scope 32 at $DIR/reference_prop.rs:+80:9: +80:19
+                                           // mir::Constant
+                                           // + span: $DIR/reference_prop.rs:183:9: 183:15
+                                           // + literal: Const { ty: fn(()) {opaque::<()>}, val: Value(<ZST>) }
+      }
+  
+      bb9: {
+          StorageDead(_65);                // scope 32 at $DIR/reference_prop.rs:+80:18: +80:19
+          StorageDead(_64);                // scope 32 at $DIR/reference_prop.rs:+80:19: +80:20
+-         _59 = const ();                  // scope 0 at $DIR/reference_prop.rs:+75:5: +81:6
+          StorageDead(_63);                // scope 31 at $DIR/reference_prop.rs:+81:5: +81:6
+-         StorageDead(_62);                // scope 30 at $DIR/reference_prop.rs:+81:5: +81:6
+-         StorageDead(_61);                // scope 29 at $DIR/reference_prop.rs:+81:5: +81:6
+          StorageDead(_60);                // scope 0 at $DIR/reference_prop.rs:+81:5: +81:6
+-         StorageDead(_59);                // scope 0 at $DIR/reference_prop.rs:+81:5: +81:6
+          StorageLive(_66);                // scope 0 at $DIR/reference_prop.rs:+85:13: +85:18
+          _66 = const 5_usize;             // scope 0 at $DIR/reference_prop.rs:+85:21: +85:28
+-         StorageLive(_67);                // scope 33 at $DIR/reference_prop.rs:+86:13: +86:18
+-         _67 = &mut _66;                  // scope 33 at $DIR/reference_prop.rs:+86:21: +86:27
+-         StorageLive(_68);                // scope 34 at $DIR/reference_prop.rs:+87:13: +87:14
+-         _68 = &mut _67;                  // scope 34 at $DIR/reference_prop.rs:+87:17: +87:23
+          StorageLive(_69);                // scope 35 at $DIR/reference_prop.rs:+88:13: +88:14
+-         _69 = (*_67);                    // scope 35 at $DIR/reference_prop.rs:+88:17: +88:19
++         _69 = _66;                       // scope 35 at $DIR/reference_prop.rs:+88:17: +88:19
+          StorageLive(_70);                // scope 36 at $DIR/reference_prop.rs:+89:9: +89:19
+          StorageLive(_71);                // scope 36 at $DIR/reference_prop.rs:+89:16: +89:18
+          _71 = ();                        // scope 36 at $DIR/reference_prop.rs:+89:16: +89:18
+          _70 = opaque::<()>(move _71) -> bb10; // scope 36 at $DIR/reference_prop.rs:+89:9: +89:19
+                                           // mir::Constant
+                                           // + span: $DIR/reference_prop.rs:192:9: 192:15
+                                           // + literal: Const { ty: fn(()) {opaque::<()>}, val: Value(<ZST>) }
+      }
+  
+      bb10: {
+          StorageDead(_71);                // scope 36 at $DIR/reference_prop.rs:+89:18: +89:19
+          StorageDead(_70);                // scope 36 at $DIR/reference_prop.rs:+89:19: +89:20
+          _0 = const ();                   // scope 0 at $DIR/reference_prop.rs:+84:5: +90:6
+          StorageDead(_69);                // scope 35 at $DIR/reference_prop.rs:+90:5: +90:6
+-         StorageDead(_68);                // scope 34 at $DIR/reference_prop.rs:+90:5: +90:6
+-         StorageDead(_67);                // scope 33 at $DIR/reference_prop.rs:+90:5: +90:6
+          StorageDead(_66);                // scope 0 at $DIR/reference_prop.rs:+90:5: +90:6
+          return;                          // scope 0 at $DIR/reference_prop.rs:+91:2: +91:2
       }
   }
   
diff --git a/tests/mir-opt/reference_prop.reference_propagation_mut_ptr.ReferencePropagation.diff b/tests/mir-opt/reference_prop.reference_propagation_mut_ptr.ReferencePropagation.diff
index c55b5eb4bed..c93aa52be11 100644
--- a/tests/mir-opt/reference_prop.reference_propagation_mut_ptr.ReferencePropagation.diff
+++ b/tests/mir-opt/reference_prop.reference_propagation_mut_ptr.ReferencePropagation.diff
@@ -13,11 +13,11 @@
       let _15: ();                         // in scope 0 at $DIR/reference_prop.rs:+17:9: +17:19
       let mut _16: ();                     // in scope 0 at $DIR/reference_prop.rs:+17:16: +17:18
       let _17: ();                         // in scope 0 at $DIR/reference_prop.rs:+21:5: +27:6
-      let _22: ();                         // in scope 0 at $DIR/reference_prop.rs:+26:9: +26:19
-      let mut _23: ();                     // in scope 0 at $DIR/reference_prop.rs:+26:16: +26:18
+      let _22: ();                         // in scope 0 at $DIR/reference_prop.rs:+26:9: +26:18
+      let mut _23: &*mut usize;            // in scope 0 at $DIR/reference_prop.rs:+26:16: +26:17
       let _24: ();                         // in scope 0 at $DIR/reference_prop.rs:+30:5: +36:6
-      let _29: ();                         // in scope 0 at $DIR/reference_prop.rs:+35:9: +35:19
-      let mut _30: ();                     // in scope 0 at $DIR/reference_prop.rs:+35:16: +35:18
+      let _29: ();                         // in scope 0 at $DIR/reference_prop.rs:+35:9: +35:18
+      let mut _30: *mut *mut usize;        // in scope 0 at $DIR/reference_prop.rs:+35:16: +35:17
       let _31: ();                         // in scope 0 at $DIR/reference_prop.rs:+39:5: +44:6
       let _35: ();                         // in scope 0 at $DIR/reference_prop.rs:+43:9: +43:18
       let mut _36: *mut usize;             // in scope 0 at $DIR/reference_prop.rs:+43:16: +43:17
@@ -27,16 +27,23 @@
       let _46: ();                         // in scope 0 at $DIR/reference_prop.rs:+60:5: +64:6
       let _49: ();                         // in scope 0 at $DIR/reference_prop.rs:+63:9: +63:19
       let mut _50: ();                     // in scope 0 at $DIR/reference_prop.rs:+63:16: +63:18
-      let mut _52: *mut T;                 // in scope 0 at $DIR/reference_prop.rs:+69:20: +69:36
-      let _54: ();                         // in scope 0 at $DIR/reference_prop.rs:+71:9: +71:19
-      let mut _55: ();                     // in scope 0 at $DIR/reference_prop.rs:+71:16: +71:18
+      let _51: ();                         // in scope 0 at $DIR/reference_prop.rs:+67:5: +72:6
+      let mut _53: *mut T;                 // in scope 0 at $DIR/reference_prop.rs:+69:20: +69:36
+      let _55: ();                         // in scope 0 at $DIR/reference_prop.rs:+71:9: +71:19
+      let mut _56: ();                     // in scope 0 at $DIR/reference_prop.rs:+71:16: +71:18
+      let _57: ();                         // in scope 0 at $DIR/reference_prop.rs:+75:5: +81:6
+      let _62: ();                         // in scope 0 at $DIR/reference_prop.rs:+80:9: +80:19
+      let mut _63: ();                     // in scope 0 at $DIR/reference_prop.rs:+80:16: +80:18
+      let _68: ();                         // in scope 0 at $DIR/reference_prop.rs:+89:9: +89:19
+      let mut _69: ();                     // in scope 0 at $DIR/reference_prop.rs:+89:16: +89:18
       scope 1 {
           let mut _4: usize;               // in scope 1 at $DIR/reference_prop.rs:+3:13: +3:18
           scope 2 {
               debug a => _4;               // in scope 2 at $DIR/reference_prop.rs:+3:13: +3:18
               let _5: *mut usize;          // in scope 2 at $DIR/reference_prop.rs:+4:13: +4:14
               scope 3 {
-                  debug b => _5;           // in scope 3 at $DIR/reference_prop.rs:+4:13: +4:14
+-                 debug b => _5;           // in scope 3 at $DIR/reference_prop.rs:+4:13: +4:14
++                 debug b => &_4;          // in scope 3 at $DIR/reference_prop.rs:+4:13: +4:14
                   let _6: usize;           // in scope 3 at $DIR/reference_prop.rs:+5:13: +5:14
                   scope 4 {
                       debug c => _6;       // in scope 4 at $DIR/reference_prop.rs:+5:13: +5:14
@@ -87,7 +94,7 @@
               let mut _26: *mut usize;     // in scope 16 at $DIR/reference_prop.rs:+32:13: +32:18
               scope 17 {
                   debug b => _26;          // in scope 17 at $DIR/reference_prop.rs:+32:13: +32:18
-                  let _27: &mut *mut usize; // in scope 17 at $DIR/reference_prop.rs:+33:13: +33:14
+                  let _27: *mut *mut usize; // in scope 17 at $DIR/reference_prop.rs:+33:13: +33:14
                   scope 18 {
                       debug d => _27;      // in scope 18 at $DIR/reference_prop.rs:+33:13: +33:14
                       let _28: usize;      // in scope 18 at $DIR/reference_prop.rs:+34:13: +34:14
@@ -141,7 +148,8 @@
       scope 31 {
           let _47: *mut T;                 // in scope 31 at $DIR/reference_prop.rs:+61:13: +61:14
           scope 32 {
-              debug a => _47;              // in scope 32 at $DIR/reference_prop.rs:+61:13: +61:14
+-             debug a => _47;              // in scope 32 at $DIR/reference_prop.rs:+61:13: +61:14
++             debug a => _1;               // in scope 32 at $DIR/reference_prop.rs:+61:13: +61:14
               let _48: T;                  // in scope 32 at $DIR/reference_prop.rs:+62:13: +62:14
               scope 33 {
                   debug b => _48;          // in scope 33 at $DIR/reference_prop.rs:+62:13: +62:14
@@ -149,12 +157,52 @@
           }
       }
       scope 34 {
-          let _51: *mut T;                 // in scope 34 at $DIR/reference_prop.rs:+68:13: +68:14
+          let _52: *mut T;                 // in scope 34 at $DIR/reference_prop.rs:+68:13: +68:14
           scope 35 {
-              debug a => _51;              // in scope 35 at $DIR/reference_prop.rs:+68:13: +68:14
-              let _53: T;                  // in scope 35 at $DIR/reference_prop.rs:+70:13: +70:14
+              debug a => _52;              // in scope 35 at $DIR/reference_prop.rs:+68:13: +68:14
+              let _54: T;                  // in scope 35 at $DIR/reference_prop.rs:+70:13: +70:14
               scope 36 {
-                  debug b => _53;          // in scope 36 at $DIR/reference_prop.rs:+70:13: +70:14
+                  debug b => _54;          // in scope 36 at $DIR/reference_prop.rs:+70:13: +70:14
+              }
+          }
+      }
+      scope 37 {
+          let mut _58: usize;              // in scope 37 at $DIR/reference_prop.rs:+76:13: +76:18
+          scope 38 {
+              debug a => _58;              // in scope 38 at $DIR/reference_prop.rs:+76:13: +76:18
+              let _59: *mut usize;         // in scope 38 at $DIR/reference_prop.rs:+77:13: +77:14
+              scope 39 {
+-                 debug b => _59;          // in scope 39 at $DIR/reference_prop.rs:+77:13: +77:14
++                 debug b => &_58;         // in scope 39 at $DIR/reference_prop.rs:+77:13: +77:14
+                  let _60: &*mut usize;    // in scope 39 at $DIR/reference_prop.rs:+78:13: +78:14
+                  scope 40 {
+-                     debug d => _60;      // in scope 40 at $DIR/reference_prop.rs:+78:13: +78:14
++                     debug d => &&_58;    // in scope 40 at $DIR/reference_prop.rs:+78:13: +78:14
+                      let _61: usize;      // in scope 40 at $DIR/reference_prop.rs:+79:13: +79:14
+                      scope 41 {
+                          debug c => _61;  // in scope 41 at $DIR/reference_prop.rs:+79:13: +79:14
+                      }
+                  }
+              }
+          }
+      }
+      scope 42 {
+          let mut _64: usize;              // in scope 42 at $DIR/reference_prop.rs:+85:13: +85:18
+          scope 43 {
+              debug a => _64;              // in scope 43 at $DIR/reference_prop.rs:+85:13: +85:18
+              let mut _65: *mut usize;     // in scope 43 at $DIR/reference_prop.rs:+86:13: +86:18
+              scope 44 {
+-                 debug b => _65;          // in scope 44 at $DIR/reference_prop.rs:+86:13: +86:18
++                 debug b => &_64;         // in scope 44 at $DIR/reference_prop.rs:+86:13: +86:18
+                  let _66: &mut *mut usize; // in scope 44 at $DIR/reference_prop.rs:+87:13: +87:14
+                  scope 45 {
+-                     debug d => _66;      // in scope 45 at $DIR/reference_prop.rs:+87:13: +87:14
++                     debug d => &&_64;    // in scope 45 at $DIR/reference_prop.rs:+87:13: +87:14
+                      let _67: usize;      // in scope 45 at $DIR/reference_prop.rs:+88:13: +88:14
+                      scope 46 {
+                          debug c => _67;  // in scope 46 at $DIR/reference_prop.rs:+88:13: +88:14
+                      }
+                  }
               }
           }
       }
@@ -163,8 +211,8 @@
 -         StorageLive(_3);                 // scope 0 at $DIR/reference_prop.rs:+2:5: +7:6
           StorageLive(_4);                 // scope 1 at $DIR/reference_prop.rs:+3:13: +3:18
           _4 = const 5_usize;              // scope 1 at $DIR/reference_prop.rs:+3:21: +3:28
-          StorageLive(_5);                 // scope 2 at $DIR/reference_prop.rs:+4:13: +4:14
-          _5 = &raw mut _4;                // scope 2 at $DIR/reference_prop.rs:+4:17: +4:27
+-         StorageLive(_5);                 // scope 2 at $DIR/reference_prop.rs:+4:13: +4:14
+-         _5 = &raw mut _4;                // scope 2 at $DIR/reference_prop.rs:+4:17: +4:27
           StorageLive(_6);                 // scope 3 at $DIR/reference_prop.rs:+5:13: +5:14
 -         _6 = (*_5);                      // scope 3 at $DIR/reference_prop.rs:+5:17: +5:19
 +         _6 = _4;                         // scope 3 at $DIR/reference_prop.rs:+5:17: +5:19
@@ -173,7 +221,7 @@
           _8 = ();                         // scope 4 at $DIR/reference_prop.rs:+6:16: +6:18
           _7 = opaque::<()>(move _8) -> bb1; // scope 4 at $DIR/reference_prop.rs:+6:9: +6:19
                                            // mir::Constant
-                                           // + span: $DIR/reference_prop.rs:250:9: 250:15
+                                           // + span: $DIR/reference_prop.rs:304:9: 304:15
                                            // + literal: Const { ty: fn(()) {opaque::<()>}, val: Value(<ZST>) }
       }
   
@@ -182,7 +230,7 @@
           StorageDead(_7);                 // scope 4 at $DIR/reference_prop.rs:+6:19: +6:20
 -         _3 = const ();                   // scope 1 at $DIR/reference_prop.rs:+2:5: +7:6
           StorageDead(_6);                 // scope 3 at $DIR/reference_prop.rs:+7:5: +7:6
-          StorageDead(_5);                 // scope 2 at $DIR/reference_prop.rs:+7:5: +7:6
+-         StorageDead(_5);                 // scope 2 at $DIR/reference_prop.rs:+7:5: +7:6
           StorageDead(_4);                 // scope 1 at $DIR/reference_prop.rs:+7:5: +7:6
 -         StorageDead(_3);                 // scope 0 at $DIR/reference_prop.rs:+7:5: +7:6
 -         StorageLive(_9);                 // scope 0 at $DIR/reference_prop.rs:+10:5: +18:6
@@ -203,7 +251,7 @@
           _16 = ();                        // scope 9 at $DIR/reference_prop.rs:+17:16: +17:18
           _15 = opaque::<()>(move _16) -> bb2; // scope 9 at $DIR/reference_prop.rs:+17:9: +17:19
                                            // mir::Constant
-                                           // + span: $DIR/reference_prop.rs:261:9: 261:15
+                                           // + span: $DIR/reference_prop.rs:315:9: 315:15
                                            // + literal: Const { ty: fn(()) {opaque::<()>}, val: Value(<ZST>) }
       }
   
@@ -225,18 +273,18 @@
           _20 = &_19;                      // scope 12 at $DIR/reference_prop.rs:+24:17: +24:19
           StorageLive(_21);                // scope 13 at $DIR/reference_prop.rs:+25:13: +25:14
           _21 = (*_19);                    // scope 13 at $DIR/reference_prop.rs:+25:17: +25:19
-          StorageLive(_22);                // scope 14 at $DIR/reference_prop.rs:+26:9: +26:19
-          StorageLive(_23);                // scope 14 at $DIR/reference_prop.rs:+26:16: +26:18
-          _23 = ();                        // scope 14 at $DIR/reference_prop.rs:+26:16: +26:18
-          _22 = opaque::<()>(move _23) -> bb3; // scope 14 at $DIR/reference_prop.rs:+26:9: +26:19
+          StorageLive(_22);                // scope 14 at $DIR/reference_prop.rs:+26:9: +26:18
+          StorageLive(_23);                // scope 14 at $DIR/reference_prop.rs:+26:16: +26:17
+          _23 = _20;                       // scope 14 at $DIR/reference_prop.rs:+26:16: +26:17
+          _22 = opaque::<&*mut usize>(move _23) -> bb3; // scope 14 at $DIR/reference_prop.rs:+26:9: +26:18
                                            // mir::Constant
-                                           // + span: $DIR/reference_prop.rs:270:9: 270:15
-                                           // + literal: Const { ty: fn(()) {opaque::<()>}, val: Value(<ZST>) }
+                                           // + span: $DIR/reference_prop.rs:324:9: 324:15
+                                           // + literal: Const { ty: fn(&*mut usize) {opaque::<&*mut usize>}, val: Value(<ZST>) }
       }
   
       bb3: {
-          StorageDead(_23);                // scope 14 at $DIR/reference_prop.rs:+26:18: +26:19
-          StorageDead(_22);                // scope 14 at $DIR/reference_prop.rs:+26:19: +26:20
+          StorageDead(_23);                // scope 14 at $DIR/reference_prop.rs:+26:17: +26:18
+          StorageDead(_22);                // scope 14 at $DIR/reference_prop.rs:+26:18: +26:19
 -         _17 = const ();                  // scope 10 at $DIR/reference_prop.rs:+21:5: +27:6
           StorageDead(_21);                // scope 13 at $DIR/reference_prop.rs:+27:5: +27:6
           StorageDead(_20);                // scope 12 at $DIR/reference_prop.rs:+27:5: +27:6
@@ -249,21 +297,21 @@
           StorageLive(_26);                // scope 16 at $DIR/reference_prop.rs:+32:13: +32:18
           _26 = &raw mut _25;              // scope 16 at $DIR/reference_prop.rs:+32:21: +32:31
           StorageLive(_27);                // scope 17 at $DIR/reference_prop.rs:+33:13: +33:14
-          _27 = &mut _26;                  // scope 17 at $DIR/reference_prop.rs:+33:17: +33:23
+          _27 = &raw mut _26;              // scope 17 at $DIR/reference_prop.rs:+33:17: +33:27
           StorageLive(_28);                // scope 18 at $DIR/reference_prop.rs:+34:13: +34:14
           _28 = (*_26);                    // scope 18 at $DIR/reference_prop.rs:+34:17: +34:19
-          StorageLive(_29);                // scope 19 at $DIR/reference_prop.rs:+35:9: +35:19
-          StorageLive(_30);                // scope 19 at $DIR/reference_prop.rs:+35:16: +35:18
-          _30 = ();                        // scope 19 at $DIR/reference_prop.rs:+35:16: +35:18
-          _29 = opaque::<()>(move _30) -> bb4; // scope 19 at $DIR/reference_prop.rs:+35:9: +35:19
+          StorageLive(_29);                // scope 19 at $DIR/reference_prop.rs:+35:9: +35:18
+          StorageLive(_30);                // scope 19 at $DIR/reference_prop.rs:+35:16: +35:17
+          _30 = _27;                       // scope 19 at $DIR/reference_prop.rs:+35:16: +35:17
+          _29 = opaque::<*mut *mut usize>(move _30) -> bb4; // scope 19 at $DIR/reference_prop.rs:+35:9: +35:18
                                            // mir::Constant
-                                           // + span: $DIR/reference_prop.rs:279:9: 279:15
-                                           // + literal: Const { ty: fn(()) {opaque::<()>}, val: Value(<ZST>) }
+                                           // + span: $DIR/reference_prop.rs:333:9: 333:15
+                                           // + literal: Const { ty: fn(*mut *mut usize) {opaque::<*mut *mut usize>}, val: Value(<ZST>) }
       }
   
       bb4: {
-          StorageDead(_30);                // scope 19 at $DIR/reference_prop.rs:+35:18: +35:19
-          StorageDead(_29);                // scope 19 at $DIR/reference_prop.rs:+35:19: +35:20
+          StorageDead(_30);                // scope 19 at $DIR/reference_prop.rs:+35:17: +35:18
+          StorageDead(_29);                // scope 19 at $DIR/reference_prop.rs:+35:18: +35:19
 -         _24 = const ();                  // scope 15 at $DIR/reference_prop.rs:+30:5: +36:6
           StorageDead(_28);                // scope 18 at $DIR/reference_prop.rs:+36:5: +36:6
           StorageDead(_27);                // scope 17 at $DIR/reference_prop.rs:+36:5: +36:6
@@ -282,7 +330,7 @@
           _36 = _33;                       // scope 23 at $DIR/reference_prop.rs:+43:16: +43:17
           _35 = opaque::<*mut usize>(move _36) -> bb5; // scope 23 at $DIR/reference_prop.rs:+43:9: +43:18
                                            // mir::Constant
-                                           // + span: $DIR/reference_prop.rs:287:9: 287:15
+                                           // + span: $DIR/reference_prop.rs:341:9: 341:15
                                            // + literal: Const { ty: fn(*mut usize) {opaque::<*mut usize>}, val: Value(<ZST>) }
       }
   
@@ -312,7 +360,7 @@
           _45 = _43;                       // scope 30 at $DIR/reference_prop.rs:+56:16: +56:18
           _44 = opaque::<*mut usize>(move _45) -> bb6; // scope 30 at $DIR/reference_prop.rs:+56:9: +56:19
                                            // mir::Constant
-                                           // + span: $DIR/reference_prop.rs:300:9: 300:15
+                                           // + span: $DIR/reference_prop.rs:354:9: 354:15
                                            // + literal: Const { ty: fn(*mut usize) {opaque::<*mut usize>}, val: Value(<ZST>) }
       }
   
@@ -328,8 +376,8 @@
           StorageDead(_38);                // scope 24 at $DIR/reference_prop.rs:+57:5: +57:6
 -         StorageDead(_37);                // scope 0 at $DIR/reference_prop.rs:+57:5: +57:6
 -         StorageLive(_46);                // scope 0 at $DIR/reference_prop.rs:+60:5: +64:6
-          StorageLive(_47);                // scope 31 at $DIR/reference_prop.rs:+61:13: +61:14
-          _47 = &raw mut (*_1);            // scope 31 at $DIR/reference_prop.rs:+61:17: +61:33
+-         StorageLive(_47);                // scope 31 at $DIR/reference_prop.rs:+61:13: +61:14
+-         _47 = &raw mut (*_1);            // scope 31 at $DIR/reference_prop.rs:+61:17: +61:33
           StorageLive(_48);                // scope 32 at $DIR/reference_prop.rs:+62:13: +62:14
 -         _48 = (*_47);                    // scope 32 at $DIR/reference_prop.rs:+62:17: +62:19
 +         _48 = (*_1);                     // scope 32 at $DIR/reference_prop.rs:+62:17: +62:19
@@ -338,7 +386,7 @@
           _50 = ();                        // scope 33 at $DIR/reference_prop.rs:+63:16: +63:18
           _49 = opaque::<()>(move _50) -> bb7; // scope 33 at $DIR/reference_prop.rs:+63:9: +63:19
                                            // mir::Constant
-                                           // + span: $DIR/reference_prop.rs:307:9: 307:15
+                                           // + span: $DIR/reference_prop.rs:361:9: 361:15
                                            // + literal: Const { ty: fn(()) {opaque::<()>}, val: Value(<ZST>) }
       }
   
@@ -347,32 +395,88 @@
           StorageDead(_49);                // scope 33 at $DIR/reference_prop.rs:+63:19: +63:20
 -         _46 = const ();                  // scope 31 at $DIR/reference_prop.rs:+60:5: +64:6
           StorageDead(_48);                // scope 32 at $DIR/reference_prop.rs:+64:5: +64:6
-          StorageDead(_47);                // scope 31 at $DIR/reference_prop.rs:+64:5: +64:6
+-         StorageDead(_47);                // scope 31 at $DIR/reference_prop.rs:+64:5: +64:6
 -         StorageDead(_46);                // scope 0 at $DIR/reference_prop.rs:+64:5: +64:6
-          StorageLive(_51);                // scope 34 at $DIR/reference_prop.rs:+68:13: +68:14
-          _51 = &raw mut (*_2);            // scope 34 at $DIR/reference_prop.rs:+68:17: +68:35
-          StorageLive(_52);                // scope 35 at $DIR/reference_prop.rs:+69:20: +69:36
-          _52 = &raw mut (*_1);            // scope 35 at $DIR/reference_prop.rs:+69:20: +69:36
-          _2 = move _52;                   // scope 35 at $DIR/reference_prop.rs:+69:9: +69:36
-          StorageDead(_52);                // scope 35 at $DIR/reference_prop.rs:+69:35: +69:36
-          StorageLive(_53);                // scope 35 at $DIR/reference_prop.rs:+70:13: +70:14
-          _53 = (*_51);                    // scope 35 at $DIR/reference_prop.rs:+70:17: +70:19
-          StorageLive(_54);                // scope 36 at $DIR/reference_prop.rs:+71:9: +71:19
-          StorageLive(_55);                // scope 36 at $DIR/reference_prop.rs:+71:16: +71:18
-          _55 = ();                        // scope 36 at $DIR/reference_prop.rs:+71:16: +71:18
-          _54 = opaque::<()>(move _55) -> bb8; // scope 36 at $DIR/reference_prop.rs:+71:9: +71:19
+-         StorageLive(_51);                // scope 0 at $DIR/reference_prop.rs:+67:5: +72:6
+          StorageLive(_52);                // scope 34 at $DIR/reference_prop.rs:+68:13: +68:14
+          _52 = &raw mut (*_2);            // scope 34 at $DIR/reference_prop.rs:+68:17: +68:35
+          StorageLive(_53);                // scope 35 at $DIR/reference_prop.rs:+69:20: +69:36
+          _53 = &raw mut (*_1);            // scope 35 at $DIR/reference_prop.rs:+69:20: +69:36
+          _2 = move _53;                   // scope 35 at $DIR/reference_prop.rs:+69:9: +69:36
+          StorageDead(_53);                // scope 35 at $DIR/reference_prop.rs:+69:35: +69:36
+          StorageLive(_54);                // scope 35 at $DIR/reference_prop.rs:+70:13: +70:14
+          _54 = (*_52);                    // scope 35 at $DIR/reference_prop.rs:+70:17: +70:19
+          StorageLive(_55);                // scope 36 at $DIR/reference_prop.rs:+71:9: +71:19
+          StorageLive(_56);                // scope 36 at $DIR/reference_prop.rs:+71:16: +71:18
+          _56 = ();                        // scope 36 at $DIR/reference_prop.rs:+71:16: +71:18
+          _55 = opaque::<()>(move _56) -> bb8; // scope 36 at $DIR/reference_prop.rs:+71:9: +71:19
                                            // mir::Constant
-                                           // + span: $DIR/reference_prop.rs:315:9: 315:15
+                                           // + span: $DIR/reference_prop.rs:369:9: 369:15
                                            // + literal: Const { ty: fn(()) {opaque::<()>}, val: Value(<ZST>) }
       }
   
       bb8: {
-          StorageDead(_55);                // scope 36 at $DIR/reference_prop.rs:+71:18: +71:19
-          StorageDead(_54);                // scope 36 at $DIR/reference_prop.rs:+71:19: +71:20
-          _0 = const ();                   // scope 34 at $DIR/reference_prop.rs:+67:5: +72:6
-          StorageDead(_53);                // scope 35 at $DIR/reference_prop.rs:+72:5: +72:6
-          StorageDead(_51);                // scope 34 at $DIR/reference_prop.rs:+72:5: +72:6
-          return;                          // scope 0 at $DIR/reference_prop.rs:+73:2: +73:2
+          StorageDead(_56);                // scope 36 at $DIR/reference_prop.rs:+71:18: +71:19
+          StorageDead(_55);                // scope 36 at $DIR/reference_prop.rs:+71:19: +71:20
+-         _51 = const ();                  // scope 34 at $DIR/reference_prop.rs:+67:5: +72:6
+          StorageDead(_54);                // scope 35 at $DIR/reference_prop.rs:+72:5: +72:6
+          StorageDead(_52);                // scope 34 at $DIR/reference_prop.rs:+72:5: +72:6
+-         StorageDead(_51);                // scope 0 at $DIR/reference_prop.rs:+72:5: +72:6
+-         StorageLive(_57);                // scope 0 at $DIR/reference_prop.rs:+75:5: +81:6
+          StorageLive(_58);                // scope 37 at $DIR/reference_prop.rs:+76:13: +76:18
+          _58 = const 5_usize;             // scope 37 at $DIR/reference_prop.rs:+76:21: +76:28
+-         StorageLive(_59);                // scope 38 at $DIR/reference_prop.rs:+77:13: +77:14
+-         _59 = &raw mut _58;              // scope 38 at $DIR/reference_prop.rs:+77:17: +77:27
+-         StorageLive(_60);                // scope 39 at $DIR/reference_prop.rs:+78:13: +78:14
+-         _60 = &_59;                      // scope 39 at $DIR/reference_prop.rs:+78:17: +78:19
+          StorageLive(_61);                // scope 40 at $DIR/reference_prop.rs:+79:13: +79:14
+-         _61 = (*_59);                    // scope 40 at $DIR/reference_prop.rs:+79:17: +79:19
++         _61 = _58;                       // scope 40 at $DIR/reference_prop.rs:+79:17: +79:19
+          StorageLive(_62);                // scope 41 at $DIR/reference_prop.rs:+80:9: +80:19
+          StorageLive(_63);                // scope 41 at $DIR/reference_prop.rs:+80:16: +80:18
+          _63 = ();                        // scope 41 at $DIR/reference_prop.rs:+80:16: +80:18
+          _62 = opaque::<()>(move _63) -> bb9; // scope 41 at $DIR/reference_prop.rs:+80:9: +80:19
+                                           // mir::Constant
+                                           // + span: $DIR/reference_prop.rs:378:9: 378:15
+                                           // + literal: Const { ty: fn(()) {opaque::<()>}, val: Value(<ZST>) }
+      }
+  
+      bb9: {
+          StorageDead(_63);                // scope 41 at $DIR/reference_prop.rs:+80:18: +80:19
+          StorageDead(_62);                // scope 41 at $DIR/reference_prop.rs:+80:19: +80:20
+-         _57 = const ();                  // scope 37 at $DIR/reference_prop.rs:+75:5: +81:6
+          StorageDead(_61);                // scope 40 at $DIR/reference_prop.rs:+81:5: +81:6
+-         StorageDead(_60);                // scope 39 at $DIR/reference_prop.rs:+81:5: +81:6
+-         StorageDead(_59);                // scope 38 at $DIR/reference_prop.rs:+81:5: +81:6
+          StorageDead(_58);                // scope 37 at $DIR/reference_prop.rs:+81:5: +81:6
+-         StorageDead(_57);                // scope 0 at $DIR/reference_prop.rs:+81:5: +81:6
+          StorageLive(_64);                // scope 42 at $DIR/reference_prop.rs:+85:13: +85:18
+          _64 = const 5_usize;             // scope 42 at $DIR/reference_prop.rs:+85:21: +85:28
+-         StorageLive(_65);                // scope 43 at $DIR/reference_prop.rs:+86:13: +86:18
+-         _65 = &raw mut _64;              // scope 43 at $DIR/reference_prop.rs:+86:21: +86:31
+-         StorageLive(_66);                // scope 44 at $DIR/reference_prop.rs:+87:13: +87:14
+-         _66 = &mut _65;                  // scope 44 at $DIR/reference_prop.rs:+87:17: +87:23
+          StorageLive(_67);                // scope 45 at $DIR/reference_prop.rs:+88:13: +88:14
+-         _67 = (*_65);                    // scope 45 at $DIR/reference_prop.rs:+88:17: +88:19
++         _67 = _64;                       // scope 45 at $DIR/reference_prop.rs:+88:17: +88:19
+          StorageLive(_68);                // scope 46 at $DIR/reference_prop.rs:+89:9: +89:19
+          StorageLive(_69);                // scope 46 at $DIR/reference_prop.rs:+89:16: +89:18
+          _69 = ();                        // scope 46 at $DIR/reference_prop.rs:+89:16: +89:18
+          _68 = opaque::<()>(move _69) -> bb10; // scope 46 at $DIR/reference_prop.rs:+89:9: +89:19
+                                           // mir::Constant
+                                           // + span: $DIR/reference_prop.rs:387:9: 387:15
+                                           // + literal: Const { ty: fn(()) {opaque::<()>}, val: Value(<ZST>) }
+      }
+  
+      bb10: {
+          StorageDead(_69);                // scope 46 at $DIR/reference_prop.rs:+89:18: +89:19
+          StorageDead(_68);                // scope 46 at $DIR/reference_prop.rs:+89:19: +89:20
+          _0 = const ();                   // scope 42 at $DIR/reference_prop.rs:+84:5: +90:6
+          StorageDead(_67);                // scope 45 at $DIR/reference_prop.rs:+90:5: +90:6
+-         StorageDead(_66);                // scope 44 at $DIR/reference_prop.rs:+90:5: +90:6
+-         StorageDead(_65);                // scope 43 at $DIR/reference_prop.rs:+90:5: +90:6
+          StorageDead(_64);                // scope 42 at $DIR/reference_prop.rs:+90:5: +90:6
+          return;                          // scope 0 at $DIR/reference_prop.rs:+91:2: +91:2
       }
   }
   
diff --git a/tests/mir-opt/reference_prop.rs b/tests/mir-opt/reference_prop.rs
index 93f8d1df8e8..4083b45470b 100644
--- a/tests/mir-opt/reference_prop.rs
+++ b/tests/mir-opt/reference_prop.rs
@@ -33,16 +33,16 @@ fn reference_propagation<'a, T: Copy>(single: &'a T, mut multiple: &'a T) {
         let b = &a;
         let d = &b;
         let c = *b; // `b` is immutably borrowed, we know its value, but do not propagate it
-        opaque(());
+        opaque(d); // prevent `d` from being removed.
     }
 
     // Propagation through a borrowed reference.
     {
         let a = 5_usize;
         let mut b = &a;
-        let d = &mut b;
+        let d = &raw mut b;
         let c = *b; // `b` is mutably borrowed, we cannot know its value.
-        opaque(());
+        opaque(d); // prevent `d` from being removed.
     }
 
     // Propagation through an escaping borrow.
@@ -80,6 +80,24 @@ fn reference_propagation<'a, T: Copy>(single: &'a T, mut multiple: &'a T) {
         let b = *a; // This should not be optimized.
         opaque(());
     }
+
+    // Fixed-point propagation through a borrowed reference.
+    {
+        let a = 5_usize;
+        let b = &a;
+        let d = &b; // first round promotes debuginfo for `d`
+        let c = *b; // second round propagates this dereference
+        opaque(());
+    }
+
+    // Fixed-point propagation through a borrowed reference.
+    {
+        let a = 5_usize;
+        let mut b = &a;
+        let d = &mut b; // first round promotes debuginfo for `d`
+        let c = *b; // second round propagates this dereference
+        opaque(());
+    }
 }
 
 fn reference_propagation_mut<'a, T: Copy>(single: &'a mut T, mut multiple: &'a mut T) {
@@ -108,16 +126,16 @@ fn reference_propagation_mut<'a, T: Copy>(single: &'a mut T, mut multiple: &'a m
         let b = &mut a;
         let d = &b;
         let c = *b; // `b` is immutably borrowed, we know its value, but cannot be removed.
-        opaque(());
+        opaque(d); // prevent `d` from being removed.
     }
 
     // Propagation through a borrowed reference.
     {
         let mut a = 5_usize;
         let mut b = &mut a;
-        let d = &mut b;
+        let d = &raw mut b;
         let c = *b; // `b` is mutably borrowed, we cannot know its value.
-        opaque(());
+        opaque(d); // prevent `d` from being removed.
     }
 
     // Propagation through an escaping borrow.
@@ -155,6 +173,24 @@ fn reference_propagation_mut<'a, T: Copy>(single: &'a mut T, mut multiple: &'a m
         let b = *a; // This should not be optimized.
         opaque(());
     }
+
+    // Fixed-point propagation through a borrowed reference.
+    {
+        let mut a = 5_usize;
+        let b = &mut a;
+        let d = &b; // first round promotes debuginfo for `d`
+        let c = *b; // second round propagates this dereference
+        opaque(());
+    }
+
+    // Fixed-point propagation through a borrowed reference.
+    {
+        let mut a = 5_usize;
+        let mut b = &mut a;
+        let d = &mut b; // first round promotes debuginfo for `d`
+        let c = *b; // second round propagates this dereference
+        opaque(());
+    }
 }
 
 fn reference_propagation_const_ptr<T: Copy>(single: *const T, mut multiple: *const T) {
@@ -183,16 +219,16 @@ fn reference_propagation_const_ptr<T: Copy>(single: *const T, mut multiple: *con
         let b = &raw const a;
         let d = &b;
         let c = *b; // `b` is immutably borrowed, we know its value, but cannot be removed.
-        opaque(());
+        opaque(d); // prevent `d` from being removed.
     }
 
     // Propagation through a borrowed reference.
     unsafe {
         let a = 5_usize;
         let mut b = &raw const a;
-        let d = &mut b;
+        let d = &raw mut b;
         let c = *b; // `b` is mutably borrowed, we cannot know its value.
-        opaque(());
+        opaque(d); // prevent `d` from being removed.
     }
 
     // Propagation through an escaping borrow.
@@ -239,6 +275,24 @@ fn reference_propagation_const_ptr<T: Copy>(single: *const T, mut multiple: *con
         let e = *c;
         opaque(());
     }
+
+    // Fixed-point propagation through a borrowed reference.
+    unsafe {
+        let a = 5_usize;
+        let b = &raw const a;
+        let d = &b; // first round promotes debuginfo for `d`
+        let c = *b; // second round propagates this dereference
+        opaque(());
+    }
+
+    // Fixed-point propagation through a borrowed reference.
+    unsafe {
+        let a = 5_usize;
+        let mut b = &raw const a;
+        let d = &mut b; // first round promotes debuginfo for `d`
+        let c = *b; // second round propagates this dereference
+        opaque(());
+    }
 }
 
 fn reference_propagation_mut_ptr<T: Copy>(single: *mut T, mut multiple: *mut T) {
@@ -267,16 +321,16 @@ fn reference_propagation_mut_ptr<T: Copy>(single: *mut T, mut multiple: *mut T)
         let b = &raw mut a;
         let d = &b;
         let c = *b; // `b` is immutably borrowed, we know its value, but cannot be removed.
-        opaque(());
+        opaque(d); // prevent `d` from being removed.
     }
 
     // Propagation through a borrowed reference.
     unsafe {
         let mut a = 5_usize;
         let mut b = &raw mut a;
-        let d = &mut b;
+        let d = &raw mut b;
         let c = *b; // `b` is mutably borrowed, we cannot know its value.
-        opaque(());
+        opaque(d); // prevent `d` from being removed.
     }
 
     // Propagation through an escaping borrow.
@@ -314,6 +368,24 @@ fn reference_propagation_mut_ptr<T: Copy>(single: *mut T, mut multiple: *mut T)
         let b = *a; // This should not be optimized.
         opaque(());
     }
+
+    // Fixed-point propagation through a borrowed reference.
+    unsafe {
+        let mut a = 5_usize;
+        let b = &raw mut a;
+        let d = &b; // first round promotes debuginfo for `d`
+        let c = *b; // second round propagates this dereference
+        opaque(());
+    }
+
+    // Fixed-point propagation through a borrowed reference.
+    unsafe {
+        let mut a = 5_usize;
+        let mut b = &raw mut a;
+        let d = &mut b; // first round promotes debuginfo for `d`
+        let c = *b; // second round propagates this dereference
+        opaque(());
+    }
 }
 
 #[custom_mir(dialect = "runtime", phase = "post-cleanup")]
@@ -456,6 +528,40 @@ fn unique_with_copies() {
     unsafe { opaque(*y) };
 }
 
+fn debuginfo() {
+    struct T(u8);
+
+    let ref_mut_u8 = &mut 5_u8;
+    let field = &T(0).0;
+
+    // Verify that we don't emit `&*` in debuginfo.
+    let reborrow = &*ref_mut_u8;
+
+    match Some(0) {
+        None => {}
+        Some(ref variant_field) => {}
+    }
+
+    // `constant_index_from_end` and `subslice` should not be promoted, as their value depends
+    // on the slice length.
+    if let [_, ref constant_index, subslice @ .., ref constant_index_from_end] = &[6; 10][..] {
+    }
+
+    let multiple_borrow = &&&mut T(6).0;
+}
+
+fn many_debuginfo() {
+    let a = 0;
+
+    // Verify that we do not ICE on deeply nested borrows.
+    let many_borrow =
+        &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
+        &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
+        &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
+        &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
+        &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&a;
+}
+
 fn main() {
     let mut x = 5_usize;
     let mut y = 7_usize;
@@ -469,6 +575,8 @@ fn main() {
     maybe_dead(true);
     mut_raw_then_mut_shr();
     unique_with_copies();
+    debuginfo();
+    many_debuginfo();
 }
 
 // EMIT_MIR reference_prop.reference_propagation.ReferencePropagation.diff
@@ -481,3 +589,4 @@ fn main() {
 // EMIT_MIR reference_prop.maybe_dead.ReferencePropagation.diff
 // EMIT_MIR reference_prop.mut_raw_then_mut_shr.ReferencePropagation.diff
 // EMIT_MIR reference_prop.unique_with_copies.ReferencePropagation.diff
+// EMIT_MIR reference_prop.debuginfo.ReferencePropagation.diff
diff --git a/tests/mir-opt/reference_prop.unique_with_copies.ReferencePropagation.diff b/tests/mir-opt/reference_prop.unique_with_copies.ReferencePropagation.diff
index 2cda2409e80..b754aff4755 100644
--- a/tests/mir-opt/reference_prop.unique_with_copies.ReferencePropagation.diff
+++ b/tests/mir-opt/reference_prop.unique_with_copies.ReferencePropagation.diff
@@ -10,7 +10,8 @@
       let _6: ();                          // in scope 0 at $DIR/reference_prop.rs:+9:14: +9:24
       let mut _7: i32;                     // in scope 0 at $DIR/reference_prop.rs:+9:21: +9:23
       scope 1 {
-          debug y => _1;                   // in scope 1 at $DIR/reference_prop.rs:+1:9: +1:10
+-         debug y => _1;                   // in scope 1 at $DIR/reference_prop.rs:+1:9: +1:10
++         debug y => _3;                   // in scope 1 at $DIR/reference_prop.rs:+1:9: +1:10
           scope 5 {
           }
       }
@@ -25,7 +26,7 @@
       }
   
       bb0: {
-          StorageLive(_1);                 // scope 0 at $DIR/reference_prop.rs:+1:9: +1:10
+-         StorageLive(_1);                 // scope 0 at $DIR/reference_prop.rs:+1:9: +1:10
           StorageLive(_2);                 // scope 0 at $DIR/reference_prop.rs:+2:13: +2:18
           _2 = const 0_i32;                // scope 0 at $DIR/reference_prop.rs:+2:21: +2:22
 -         StorageLive(_3);                 // scope 2 at $DIR/reference_prop.rs:+3:13: +3:14
@@ -35,14 +36,14 @@
           _5 = (*_3);                      // scope 4 at $DIR/reference_prop.rs:+5:25: +5:27
           _4 = opaque::<i32>(move _5) -> bb1; // scope 4 at $DIR/reference_prop.rs:+5:18: +5:28
                                            // mir::Constant
-                                           // + span: $DIR/reference_prop.rs:452:18: 452:24
+                                           // + span: $DIR/reference_prop.rs:524:18: 524:24
                                            // + literal: Const { ty: fn(i32) {opaque::<i32>}, val: Value(<ZST>) }
       }
   
       bb1: {
           StorageDead(_5);                 // scope 4 at $DIR/reference_prop.rs:+5:27: +5:28
           StorageDead(_4);                 // scope 3 at $DIR/reference_prop.rs:+5:30: +5:31
-          _1 = _3;                         // scope 3 at $DIR/reference_prop.rs:+6:9: +6:10
+-         _1 = _3;                         // scope 3 at $DIR/reference_prop.rs:+6:9: +6:10
 -         StorageDead(_3);                 // scope 2 at $DIR/reference_prop.rs:+7:5: +7:6
           StorageDead(_2);                 // scope 0 at $DIR/reference_prop.rs:+7:5: +7:6
           StorageLive(_6);                 // scope 1 at $DIR/reference_prop.rs:+9:5: +9:26
@@ -51,7 +52,7 @@
 +         _7 = (*_3);                      // scope 5 at $DIR/reference_prop.rs:+9:21: +9:23
           _6 = opaque::<i32>(move _7) -> bb2; // scope 5 at $DIR/reference_prop.rs:+9:14: +9:24
                                            // mir::Constant
-                                           // + span: $DIR/reference_prop.rs:456:14: 456:20
+                                           // + span: $DIR/reference_prop.rs:528:14: 528:20
                                            // + literal: Const { ty: fn(i32) {opaque::<i32>}, val: Value(<ZST>) }
       }
   
@@ -59,7 +60,7 @@
           StorageDead(_7);                 // scope 5 at $DIR/reference_prop.rs:+9:23: +9:24
           StorageDead(_6);                 // scope 1 at $DIR/reference_prop.rs:+9:26: +9:27
           _0 = const ();                   // scope 0 at $DIR/reference_prop.rs:+0:25: +10:2
-          StorageDead(_1);                 // scope 0 at $DIR/reference_prop.rs:+10:1: +10:2
+-         StorageDead(_1);                 // scope 0 at $DIR/reference_prop.rs:+10:1: +10:2
           return;                          // scope 0 at $DIR/reference_prop.rs:+10:2: +10:2
       }
   }
diff --git a/tests/mir-opt/slice_filter.variant_a-{closure#0}.DestinationPropagation.diff b/tests/mir-opt/slice_filter.variant_a-{closure#0}.DestinationPropagation.diff
index 7ad1ccf28a6..afdcf57815f 100644
--- a/tests/mir-opt/slice_filter.variant_a-{closure#0}.DestinationPropagation.diff
+++ b/tests/mir-opt/slice_filter.variant_a-{closure#0}.DestinationPropagation.diff
@@ -3,136 +3,79 @@
   
   fn variant_a::{closure#0}(_1: &mut [closure@$DIR/slice_filter.rs:8:25: 8:39], _2: &&(usize, usize, usize, usize)) -> bool {
       let mut _0: bool;                    // return place in scope 0 at $DIR/slice_filter.rs:+0:40: +0:40
-      let _3: &usize;                      // in scope 0 at $DIR/slice_filter.rs:+0:27: +0:28
-      let _4: &usize;                      // in scope 0 at $DIR/slice_filter.rs:+0:30: +0:31
-      let _5: &usize;                      // in scope 0 at $DIR/slice_filter.rs:+0:33: +0:34
-      let _6: &usize;                      // in scope 0 at $DIR/slice_filter.rs:+0:36: +0:37
-      let mut _7: bool;                    // in scope 0 at $DIR/slice_filter.rs:+0:40: +0:56
-      let mut _8: bool;                    // in scope 0 at $DIR/slice_filter.rs:+0:40: +0:46
-      let mut _9: &&usize;                 // in scope 0 at $DIR/slice_filter.rs:+0:40: +0:41
-      let mut _10: &&usize;                // in scope 0 at $DIR/slice_filter.rs:+0:45: +0:46
-      let _11: &usize;                     // in scope 0 at $DIR/slice_filter.rs:+0:45: +0:46
-      let mut _12: bool;                   // in scope 0 at $DIR/slice_filter.rs:+0:50: +0:56
-      let mut _13: &&usize;                // in scope 0 at $DIR/slice_filter.rs:+0:50: +0:51
-      let mut _14: &&usize;                // in scope 0 at $DIR/slice_filter.rs:+0:55: +0:56
-      let _15: &usize;                     // in scope 0 at $DIR/slice_filter.rs:+0:55: +0:56
-      let mut _16: bool;                   // in scope 0 at $DIR/slice_filter.rs:+0:60: +0:76
-      let mut _17: bool;                   // in scope 0 at $DIR/slice_filter.rs:+0:60: +0:66
-      let mut _18: &&usize;                // in scope 0 at $DIR/slice_filter.rs:+0:60: +0:61
-      let mut _19: &&usize;                // in scope 0 at $DIR/slice_filter.rs:+0:65: +0:66
-      let _20: &usize;                     // in scope 0 at $DIR/slice_filter.rs:+0:65: +0:66
-      let mut _21: bool;                   // in scope 0 at $DIR/slice_filter.rs:+0:70: +0:76
-      let mut _22: &&usize;                // in scope 0 at $DIR/slice_filter.rs:+0:70: +0:71
-      let mut _23: &&usize;                // in scope 0 at $DIR/slice_filter.rs:+0:75: +0:76
-      let _24: &usize;                     // in scope 0 at $DIR/slice_filter.rs:+0:75: +0:76
-      let mut _25: &(usize, usize, usize, usize); // in scope 0 at $DIR/slice_filter.rs:+0:26: +0:38
-      let mut _26: &(usize, usize, usize, usize); // in scope 0 at $DIR/slice_filter.rs:+0:26: +0:38
-      let mut _27: &(usize, usize, usize, usize); // in scope 0 at $DIR/slice_filter.rs:+0:26: +0:38
-      let mut _28: &(usize, usize, usize, usize); // in scope 0 at $DIR/slice_filter.rs:+0:26: +0:38
+      let mut _3: bool;                    // in scope 0 at $DIR/slice_filter.rs:+0:40: +0:56
+      let mut _4: bool;                    // in scope 0 at $DIR/slice_filter.rs:+0:40: +0:46
+      let mut _5: bool;                    // in scope 0 at $DIR/slice_filter.rs:+0:50: +0:56
+      let mut _6: bool;                    // in scope 0 at $DIR/slice_filter.rs:+0:60: +0:76
+      let mut _7: bool;                    // in scope 0 at $DIR/slice_filter.rs:+0:60: +0:66
+      let mut _8: bool;                    // in scope 0 at $DIR/slice_filter.rs:+0:70: +0:76
+      let mut _9: &(usize, usize, usize, usize); // in scope 0 at $DIR/slice_filter.rs:+0:26: +0:38
+      let mut _10: &(usize, usize, usize, usize); // in scope 0 at $DIR/slice_filter.rs:+0:26: +0:38
+      let mut _11: &(usize, usize, usize, usize); // in scope 0 at $DIR/slice_filter.rs:+0:26: +0:38
+      let mut _12: &(usize, usize, usize, usize); // in scope 0 at $DIR/slice_filter.rs:+0:26: +0:38
       scope 1 {
--         debug a => _3;                   // in scope 1 at $DIR/slice_filter.rs:+0:27: +0:28
--         debug b => _4;                   // in scope 1 at $DIR/slice_filter.rs:+0:30: +0:31
--         debug c => _5;                   // in scope 1 at $DIR/slice_filter.rs:+0:33: +0:34
--         debug d => _6;                   // in scope 1 at $DIR/slice_filter.rs:+0:36: +0:37
-+         debug a => _20;                  // in scope 1 at $DIR/slice_filter.rs:+0:27: +0:28
-+         debug b => _15;                  // in scope 1 at $DIR/slice_filter.rs:+0:30: +0:31
-+         debug c => _11;                  // in scope 1 at $DIR/slice_filter.rs:+0:33: +0:34
-+         debug d => _24;                  // in scope 1 at $DIR/slice_filter.rs:+0:36: +0:37
+          debug a => &((*_9).0: usize);    // in scope 1 at $DIR/slice_filter.rs:+0:27: +0:28
+          debug b => &((*_10).1: usize);   // in scope 1 at $DIR/slice_filter.rs:+0:30: +0:31
+          debug c => &((*_11).2: usize);   // in scope 1 at $DIR/slice_filter.rs:+0:33: +0:34
+          debug d => &((*_12).3: usize);   // in scope 1 at $DIR/slice_filter.rs:+0:36: +0:37
           scope 2 (inlined cmp::impls::<impl PartialOrd for &usize>::le) { // at $DIR/slice_filter.rs:8:40: 8:46
-              debug self => _9;            // in scope 2 at $SRC_DIR/core/src/cmp.rs:LL:COL
-              debug other => _10;          // in scope 2 at $SRC_DIR/core/src/cmp.rs:LL:COL
-              let mut _29: &usize;         // in scope 2 at $SRC_DIR/core/src/cmp.rs:LL:COL
-              let mut _30: &usize;         // in scope 2 at $SRC_DIR/core/src/cmp.rs:LL:COL
+              debug self => &&((*_9).0: usize); // in scope 2 at $SRC_DIR/core/src/cmp.rs:LL:COL
+              debug other => &&((*_11).2: usize); // in scope 2 at $SRC_DIR/core/src/cmp.rs:LL:COL
               scope 3 (inlined cmp::impls::<impl PartialOrd for usize>::le) { // at $SRC_DIR/core/src/cmp.rs:LL:COL
-                  debug self => _29;       // in scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
-                  debug other => _30;      // in scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
-                  let mut _31: usize;      // in scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
-                  let mut _32: usize;      // in scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
+                  debug self => &((*_9).0: usize); // in scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
+                  debug other => &((*_11).2: usize); // in scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
+                  let mut _13: usize;      // in scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
+                  let mut _14: usize;      // in scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
               }
           }
           scope 4 (inlined cmp::impls::<impl PartialOrd for &usize>::le) { // at $DIR/slice_filter.rs:8:60: 8:66
-              debug self => _18;           // in scope 4 at $SRC_DIR/core/src/cmp.rs:LL:COL
-              debug other => _19;          // in scope 4 at $SRC_DIR/core/src/cmp.rs:LL:COL
-              let mut _33: &usize;         // in scope 4 at $SRC_DIR/core/src/cmp.rs:LL:COL
-              let mut _34: &usize;         // in scope 4 at $SRC_DIR/core/src/cmp.rs:LL:COL
+              debug self => &&((*_11).2: usize); // in scope 4 at $SRC_DIR/core/src/cmp.rs:LL:COL
+              debug other => &&((*_9).0: usize); // in scope 4 at $SRC_DIR/core/src/cmp.rs:LL:COL
               scope 5 (inlined cmp::impls::<impl PartialOrd for usize>::le) { // at $SRC_DIR/core/src/cmp.rs:LL:COL
-                  debug self => _33;       // in scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
-                  debug other => _34;      // in scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
-                  let mut _35: usize;      // in scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
-                  let mut _36: usize;      // in scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
+                  debug self => &((*_11).2: usize); // in scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
+                  debug other => &((*_9).0: usize); // in scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
+                  let mut _15: usize;      // in scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
+                  let mut _16: usize;      // in scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
               }
           }
           scope 6 (inlined cmp::impls::<impl PartialOrd for &usize>::le) { // at $DIR/slice_filter.rs:8:50: 8:56
-              debug self => _13;           // in scope 6 at $SRC_DIR/core/src/cmp.rs:LL:COL
-              debug other => _14;          // in scope 6 at $SRC_DIR/core/src/cmp.rs:LL:COL
-              let mut _37: &usize;         // in scope 6 at $SRC_DIR/core/src/cmp.rs:LL:COL
-              let mut _38: &usize;         // in scope 6 at $SRC_DIR/core/src/cmp.rs:LL:COL
+              debug self => &&((*_12).3: usize); // in scope 6 at $SRC_DIR/core/src/cmp.rs:LL:COL
+              debug other => &&((*_10).1: usize); // in scope 6 at $SRC_DIR/core/src/cmp.rs:LL:COL
               scope 7 (inlined cmp::impls::<impl PartialOrd for usize>::le) { // at $SRC_DIR/core/src/cmp.rs:LL:COL
-                  debug self => _37;       // in scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
-                  debug other => _38;      // in scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
-                  let mut _39: usize;      // in scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
-                  let mut _40: usize;      // in scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
+                  debug self => &((*_12).3: usize); // in scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
+                  debug other => &((*_10).1: usize); // in scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
+                  let mut _17: usize;      // in scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
+                  let mut _18: usize;      // in scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
               }
           }
           scope 8 (inlined cmp::impls::<impl PartialOrd for &usize>::le) { // at $DIR/slice_filter.rs:8:70: 8:76
-              debug self => _22;           // in scope 8 at $SRC_DIR/core/src/cmp.rs:LL:COL
-              debug other => _23;          // in scope 8 at $SRC_DIR/core/src/cmp.rs:LL:COL
-              let mut _41: &usize;         // in scope 8 at $SRC_DIR/core/src/cmp.rs:LL:COL
-              let mut _42: &usize;         // in scope 8 at $SRC_DIR/core/src/cmp.rs:LL:COL
+              debug self => &&((*_10).1: usize); // in scope 8 at $SRC_DIR/core/src/cmp.rs:LL:COL
+              debug other => &&((*_12).3: usize); // in scope 8 at $SRC_DIR/core/src/cmp.rs:LL:COL
               scope 9 (inlined cmp::impls::<impl PartialOrd for usize>::le) { // at $SRC_DIR/core/src/cmp.rs:LL:COL
-                  debug self => _41;       // in scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
-                  debug other => _42;      // in scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
-                  let mut _43: usize;      // in scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
-                  let mut _44: usize;      // in scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
+                  debug self => &((*_10).1: usize); // in scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
+                  debug other => &((*_12).3: usize); // in scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
+                  let mut _19: usize;      // in scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
+                  let mut _20: usize;      // in scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
               }
           }
       }
   
       bb0: {
--         StorageLive(_3);                 // scope 0 at $DIR/slice_filter.rs:+0:27: +0:28
-+         nop;                             // scope 0 at $DIR/slice_filter.rs:+0:27: +0:28
-          _25 = deref_copy (*_2);          // scope 0 at $DIR/slice_filter.rs:+0:27: +0:28
--         _3 = &((*_25).0: usize);         // scope 0 at $DIR/slice_filter.rs:+0:27: +0:28
--         StorageLive(_4);                 // scope 0 at $DIR/slice_filter.rs:+0:30: +0:31
-+         _20 = &((*_25).0: usize);        // scope 0 at $DIR/slice_filter.rs:+0:27: +0:28
-+         nop;                             // scope 0 at $DIR/slice_filter.rs:+0:30: +0:31
-          _26 = deref_copy (*_2);          // scope 0 at $DIR/slice_filter.rs:+0:30: +0:31
--         _4 = &((*_26).1: usize);         // scope 0 at $DIR/slice_filter.rs:+0:30: +0:31
--         StorageLive(_5);                 // scope 0 at $DIR/slice_filter.rs:+0:33: +0:34
-+         _15 = &((*_26).1: usize);        // scope 0 at $DIR/slice_filter.rs:+0:30: +0:31
-+         nop;                             // scope 0 at $DIR/slice_filter.rs:+0:33: +0:34
-          _27 = deref_copy (*_2);          // scope 0 at $DIR/slice_filter.rs:+0:33: +0:34
--         _5 = &((*_27).2: usize);         // scope 0 at $DIR/slice_filter.rs:+0:33: +0:34
--         StorageLive(_6);                 // scope 0 at $DIR/slice_filter.rs:+0:36: +0:37
-+         _11 = &((*_27).2: usize);        // scope 0 at $DIR/slice_filter.rs:+0:33: +0:34
-+         nop;                             // scope 0 at $DIR/slice_filter.rs:+0:36: +0:37
-          _28 = deref_copy (*_2);          // scope 0 at $DIR/slice_filter.rs:+0:36: +0:37
--         _6 = &((*_28).3: usize);         // scope 0 at $DIR/slice_filter.rs:+0:36: +0:37
--         StorageLive(_7);                 // scope 1 at $DIR/slice_filter.rs:+0:40: +0:56
-+         _24 = &((*_28).3: usize);        // scope 0 at $DIR/slice_filter.rs:+0:36: +0:37
+          _9 = deref_copy (*_2);           // scope 0 at $DIR/slice_filter.rs:+0:27: +0:28
+          _10 = deref_copy (*_2);          // scope 0 at $DIR/slice_filter.rs:+0:30: +0:31
+          _11 = deref_copy (*_2);          // scope 0 at $DIR/slice_filter.rs:+0:33: +0:34
+          _12 = deref_copy (*_2);          // scope 0 at $DIR/slice_filter.rs:+0:36: +0:37
+-         StorageLive(_3);                 // scope 1 at $DIR/slice_filter.rs:+0:40: +0:56
 +         nop;                             // scope 1 at $DIR/slice_filter.rs:+0:40: +0:56
-          StorageLive(_8);                 // scope 1 at $DIR/slice_filter.rs:+0:40: +0:46
-          StorageLive(_9);                 // scope 1 at $DIR/slice_filter.rs:+0:40: +0:41
-          StorageLive(_10);                // scope 1 at $DIR/slice_filter.rs:+0:45: +0:46
--         StorageLive(_11);                // scope 1 at $DIR/slice_filter.rs:+0:45: +0:46
--         _11 = _5;                        // scope 1 at $DIR/slice_filter.rs:+0:45: +0:46
--         _29 = deref_copy _3;             // scope 2 at $SRC_DIR/core/src/cmp.rs:LL:COL
-+         nop;                             // scope 1 at $DIR/slice_filter.rs:+0:45: +0:46
-+         nop;                             // scope 1 at $DIR/slice_filter.rs:+0:45: +0:46
-+         _29 = deref_copy _20;            // scope 2 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          _30 = deref_copy _11;            // scope 2 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          StorageLive(_31);                // scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          _31 = (*_29);                    // scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          StorageLive(_32);                // scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          _32 = (*_30);                    // scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          _8 = Le(move _31, move _32);     // scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          StorageDead(_32);                // scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          StorageDead(_31);                // scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
--         StorageDead(_11);                // scope 1 at $DIR/slice_filter.rs:+0:45: +0:46
-+         nop;                             // scope 1 at $DIR/slice_filter.rs:+0:45: +0:46
-          StorageDead(_10);                // scope 1 at $DIR/slice_filter.rs:+0:45: +0:46
-          StorageDead(_9);                 // scope 1 at $DIR/slice_filter.rs:+0:45: +0:46
-          switchInt(move _8) -> [0: bb4, otherwise: bb5]; // scope 1 at $DIR/slice_filter.rs:+0:40: +0:56
+          StorageLive(_4);                 // scope 1 at $DIR/slice_filter.rs:+0:40: +0:46
+          StorageLive(_13);                // scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
+          _13 = ((*_9).0: usize);          // scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
+          StorageLive(_14);                // scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
+          _14 = ((*_11).2: usize);         // scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
+          _4 = Le(move _13, move _14);     // scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
+          StorageDead(_14);                // scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
+          StorageDead(_13);                // scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
+          switchInt(move _4) -> [0: bb4, otherwise: bb5]; // scope 1 at $DIR/slice_filter.rs:+0:40: +0:56
       }
   
       bb1: {
@@ -141,127 +84,80 @@
       }
   
       bb2: {
--         StorageLive(_16);                // scope 1 at $DIR/slice_filter.rs:+0:60: +0:76
+-         StorageLive(_6);                 // scope 1 at $DIR/slice_filter.rs:+0:60: +0:76
 +         nop;                             // scope 1 at $DIR/slice_filter.rs:+0:60: +0:76
-          StorageLive(_17);                // scope 1 at $DIR/slice_filter.rs:+0:60: +0:66
-          StorageLive(_18);                // scope 1 at $DIR/slice_filter.rs:+0:60: +0:61
-          StorageLive(_19);                // scope 1 at $DIR/slice_filter.rs:+0:65: +0:66
--         StorageLive(_20);                // scope 1 at $DIR/slice_filter.rs:+0:65: +0:66
--         _20 = _3;                        // scope 1 at $DIR/slice_filter.rs:+0:65: +0:66
--         _33 = deref_copy _5;             // scope 4 at $SRC_DIR/core/src/cmp.rs:LL:COL
-+         nop;                             // scope 1 at $DIR/slice_filter.rs:+0:65: +0:66
-+         nop;                             // scope 1 at $DIR/slice_filter.rs:+0:65: +0:66
-+         _33 = deref_copy _11;            // scope 4 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          _34 = deref_copy _20;            // scope 4 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          StorageLive(_35);                // scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          _35 = (*_33);                    // scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          StorageLive(_36);                // scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          _36 = (*_34);                    // scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          _17 = Le(move _35, move _36);    // scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          StorageDead(_36);                // scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          StorageDead(_35);                // scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
--         StorageDead(_20);                // scope 1 at $DIR/slice_filter.rs:+0:65: +0:66
-+         nop;                             // scope 1 at $DIR/slice_filter.rs:+0:65: +0:66
-          StorageDead(_19);                // scope 1 at $DIR/slice_filter.rs:+0:65: +0:66
-          StorageDead(_18);                // scope 1 at $DIR/slice_filter.rs:+0:65: +0:66
-          switchInt(move _17) -> [0: bb6, otherwise: bb7]; // scope 1 at $DIR/slice_filter.rs:+0:60: +0:76
+          StorageLive(_7);                 // scope 1 at $DIR/slice_filter.rs:+0:60: +0:66
+          StorageLive(_15);                // scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
+          _15 = ((*_11).2: usize);         // scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
+          StorageLive(_16);                // scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
+          _16 = ((*_9).0: usize);          // scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
+          _7 = Le(move _15, move _16);     // scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
+          StorageDead(_16);                // scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
+          StorageDead(_15);                // scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
+          switchInt(move _7) -> [0: bb6, otherwise: bb7]; // scope 1 at $DIR/slice_filter.rs:+0:60: +0:76
       }
   
       bb3: {
--         StorageDead(_16);                // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
--         StorageDead(_7);                 // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
--         StorageDead(_6);                 // scope 0 at $DIR/slice_filter.rs:+0:75: +0:76
--         StorageDead(_5);                 // scope 0 at $DIR/slice_filter.rs:+0:75: +0:76
--         StorageDead(_4);                 // scope 0 at $DIR/slice_filter.rs:+0:75: +0:76
--         StorageDead(_3);                 // scope 0 at $DIR/slice_filter.rs:+0:75: +0:76
+-         StorageDead(_6);                 // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
+-         StorageDead(_3);                 // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
 +         nop;                             // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
 +         nop;                             // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
-+         nop;                             // scope 0 at $DIR/slice_filter.rs:+0:75: +0:76
-+         nop;                             // scope 0 at $DIR/slice_filter.rs:+0:75: +0:76
-+         nop;                             // scope 0 at $DIR/slice_filter.rs:+0:75: +0:76
-+         nop;                             // scope 0 at $DIR/slice_filter.rs:+0:75: +0:76
           return;                          // scope 0 at $DIR/slice_filter.rs:+0:76: +0:76
       }
   
       bb4: {
--         StorageDead(_12);                // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
+-         StorageDead(_5);                 // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
 +         nop;                             // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
-          StorageDead(_8);                 // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
+          StorageDead(_4);                 // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
           goto -> bb2;                     // scope 1 at $DIR/slice_filter.rs:+0:40: +0:56
       }
   
       bb5: {
--         StorageLive(_12);                // scope 1 at $DIR/slice_filter.rs:+0:50: +0:56
+-         StorageLive(_5);                 // scope 1 at $DIR/slice_filter.rs:+0:50: +0:56
 +         nop;                             // scope 1 at $DIR/slice_filter.rs:+0:50: +0:56
-          StorageLive(_13);                // scope 1 at $DIR/slice_filter.rs:+0:50: +0:51
-          StorageLive(_14);                // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
--         StorageLive(_15);                // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
--         _15 = _4;                        // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
--         _37 = deref_copy _6;             // scope 6 at $SRC_DIR/core/src/cmp.rs:LL:COL
-+         nop;                             // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
-+         nop;                             // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
-+         _37 = deref_copy _24;            // scope 6 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          _38 = deref_copy _15;            // scope 6 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          StorageLive(_39);                // scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          _39 = (*_37);                    // scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          StorageLive(_40);                // scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          _40 = (*_38);                    // scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          _12 = Le(move _39, move _40);    // scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          StorageDead(_40);                // scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          StorageDead(_39);                // scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
--         StorageDead(_15);                // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
-+         nop;                             // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
-          StorageDead(_14);                // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
-          StorageDead(_13);                // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
--         _7 = move _12;                   // scope 1 at $DIR/slice_filter.rs:+0:40: +0:56
--         StorageDead(_12);                // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
+          StorageLive(_17);                // scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
+          _17 = ((*_12).3: usize);         // scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
+          StorageLive(_18);                // scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
+          _18 = ((*_10).1: usize);         // scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
+          _5 = Le(move _17, move _18);     // scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
+          StorageDead(_18);                // scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
+          StorageDead(_17);                // scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
+-         _3 = move _5;                    // scope 1 at $DIR/slice_filter.rs:+0:40: +0:56
+-         StorageDead(_5);                 // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
 +         nop;                             // scope 1 at $DIR/slice_filter.rs:+0:40: +0:56
 +         nop;                             // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
-          StorageDead(_8);                 // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
--         switchInt(move _7) -> [0: bb2, otherwise: bb1]; // scope 1 at $DIR/slice_filter.rs:+0:40: +0:76
-+         switchInt(move _12) -> [0: bb2, otherwise: bb1]; // scope 1 at $DIR/slice_filter.rs:+0:40: +0:76
+          StorageDead(_4);                 // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
+-         switchInt(move _3) -> [0: bb2, otherwise: bb1]; // scope 1 at $DIR/slice_filter.rs:+0:40: +0:76
++         switchInt(move _5) -> [0: bb2, otherwise: bb1]; // scope 1 at $DIR/slice_filter.rs:+0:40: +0:76
       }
   
       bb6: {
--         _16 = const false;               // scope 1 at $DIR/slice_filter.rs:+0:60: +0:76
+-         _6 = const false;                // scope 1 at $DIR/slice_filter.rs:+0:60: +0:76
 +         _0 = const false;                // scope 1 at $DIR/slice_filter.rs:+0:60: +0:76
           goto -> bb8;                     // scope 1 at $DIR/slice_filter.rs:+0:60: +0:76
       }
   
       bb7: {
--         StorageLive(_21);                // scope 1 at $DIR/slice_filter.rs:+0:70: +0:76
+-         StorageLive(_8);                 // scope 1 at $DIR/slice_filter.rs:+0:70: +0:76
 +         nop;                             // scope 1 at $DIR/slice_filter.rs:+0:70: +0:76
-          StorageLive(_22);                // scope 1 at $DIR/slice_filter.rs:+0:70: +0:71
-          StorageLive(_23);                // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
--         StorageLive(_24);                // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
--         _24 = _6;                        // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
--         _41 = deref_copy _4;             // scope 8 at $SRC_DIR/core/src/cmp.rs:LL:COL
-+         nop;                             // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
-+         nop;                             // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
-+         _41 = deref_copy _15;            // scope 8 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          _42 = deref_copy _24;            // scope 8 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          StorageLive(_43);                // scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          _43 = (*_41);                    // scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          StorageLive(_44);                // scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          _44 = (*_42);                    // scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
--         _21 = Le(move _43, move _44);    // scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
-+         _0 = Le(move _43, move _44);     // scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          StorageDead(_44);                // scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          StorageDead(_43);                // scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
--         StorageDead(_24);                // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
-+         nop;                             // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
-          StorageDead(_23);                // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
-          StorageDead(_22);                // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
--         _16 = move _21;                  // scope 1 at $DIR/slice_filter.rs:+0:60: +0:76
+          StorageLive(_19);                // scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
+          _19 = ((*_10).1: usize);         // scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
+          StorageLive(_20);                // scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
+          _20 = ((*_12).3: usize);         // scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
+-         _8 = Le(move _19, move _20);     // scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
++         _0 = Le(move _19, move _20);     // scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
+          StorageDead(_20);                // scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
+          StorageDead(_19);                // scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
+-         _6 = move _8;                    // scope 1 at $DIR/slice_filter.rs:+0:60: +0:76
 +         nop;                             // scope 1 at $DIR/slice_filter.rs:+0:60: +0:76
           goto -> bb8;                     // scope 1 at $DIR/slice_filter.rs:+0:60: +0:76
       }
   
       bb8: {
--         StorageDead(_21);                // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
+-         StorageDead(_8);                 // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
 +         nop;                             // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
-          StorageDead(_17);                // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
--         _0 = move _16;                   // scope 1 at $DIR/slice_filter.rs:+0:40: +0:76
+          StorageDead(_7);                 // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
+-         _0 = move _6;                    // scope 1 at $DIR/slice_filter.rs:+0:40: +0:76
 +         nop;                             // scope 1 at $DIR/slice_filter.rs:+0:40: +0:76
           goto -> bb3;                     // scope 1 at $DIR/slice_filter.rs:+0:40: +0:76
       }
diff --git a/tests/mir-opt/slice_filter.variant_a-{closure#0}.ReferencePropagation.diff b/tests/mir-opt/slice_filter.variant_a-{closure#0}.ReferencePropagation.diff
index f6350b3812a..2534eeef432 100644
--- a/tests/mir-opt/slice_filter.variant_a-{closure#0}.ReferencePropagation.diff
+++ b/tests/mir-opt/slice_filter.variant_a-{closure#0}.ReferencePropagation.diff
@@ -38,54 +38,74 @@
       let mut _49: &usize;                 // in scope 0 at $SRC_DIR/core/src/cmp.rs:LL:COL
       let mut _50: &usize;                 // in scope 0 at $SRC_DIR/core/src/cmp.rs:LL:COL
       scope 1 {
-          debug a => _3;                   // in scope 1 at $DIR/slice_filter.rs:+0:27: +0:28
-          debug b => _4;                   // in scope 1 at $DIR/slice_filter.rs:+0:30: +0:31
-          debug c => _5;                   // in scope 1 at $DIR/slice_filter.rs:+0:33: +0:34
-          debug d => _6;                   // in scope 1 at $DIR/slice_filter.rs:+0:36: +0:37
+-         debug a => _3;                   // in scope 1 at $DIR/slice_filter.rs:+0:27: +0:28
+-         debug b => _4;                   // in scope 1 at $DIR/slice_filter.rs:+0:30: +0:31
+-         debug c => _5;                   // in scope 1 at $DIR/slice_filter.rs:+0:33: +0:34
+-         debug d => _6;                   // in scope 1 at $DIR/slice_filter.rs:+0:36: +0:37
++         debug a => &((*_25).0: usize);   // in scope 1 at $DIR/slice_filter.rs:+0:27: +0:28
++         debug b => &((*_26).1: usize);   // in scope 1 at $DIR/slice_filter.rs:+0:30: +0:31
++         debug c => &((*_27).2: usize);   // in scope 1 at $DIR/slice_filter.rs:+0:33: +0:34
++         debug d => &((*_28).3: usize);   // in scope 1 at $DIR/slice_filter.rs:+0:36: +0:37
           scope 2 (inlined cmp::impls::<impl PartialOrd for &usize>::le) { // at $DIR/slice_filter.rs:8:40: 8:46
-              debug self => _9;            // in scope 2 at $SRC_DIR/core/src/cmp.rs:LL:COL
-              debug other => _10;          // in scope 2 at $SRC_DIR/core/src/cmp.rs:LL:COL
+-             debug self => _9;            // in scope 2 at $SRC_DIR/core/src/cmp.rs:LL:COL
+-             debug other => _10;          // in scope 2 at $SRC_DIR/core/src/cmp.rs:LL:COL
++             debug self => &&((*_25).0: usize); // in scope 2 at $SRC_DIR/core/src/cmp.rs:LL:COL
++             debug other => &&((*_27).2: usize); // in scope 2 at $SRC_DIR/core/src/cmp.rs:LL:COL
               let mut _29: &usize;         // in scope 2 at $SRC_DIR/core/src/cmp.rs:LL:COL
               let mut _30: &usize;         // in scope 2 at $SRC_DIR/core/src/cmp.rs:LL:COL
               scope 3 (inlined cmp::impls::<impl PartialOrd for usize>::le) { // at $SRC_DIR/core/src/cmp.rs:LL:COL
-                  debug self => _29;       // in scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
-                  debug other => _30;      // in scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
+-                 debug self => _29;       // in scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
+-                 debug other => _30;      // in scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
++                 debug self => &((*_25).0: usize); // in scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
++                 debug other => &((*_27).2: usize); // in scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
                   let mut _33: usize;      // in scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
                   let mut _34: usize;      // in scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
               }
           }
           scope 4 (inlined cmp::impls::<impl PartialOrd for &usize>::le) { // at $DIR/slice_filter.rs:8:60: 8:66
-              debug self => _18;           // in scope 4 at $SRC_DIR/core/src/cmp.rs:LL:COL
-              debug other => _19;          // in scope 4 at $SRC_DIR/core/src/cmp.rs:LL:COL
+-             debug self => _18;           // in scope 4 at $SRC_DIR/core/src/cmp.rs:LL:COL
+-             debug other => _19;          // in scope 4 at $SRC_DIR/core/src/cmp.rs:LL:COL
++             debug self => &&((*_27).2: usize); // in scope 4 at $SRC_DIR/core/src/cmp.rs:LL:COL
++             debug other => &&((*_25).0: usize); // in scope 4 at $SRC_DIR/core/src/cmp.rs:LL:COL
               let mut _35: &usize;         // in scope 4 at $SRC_DIR/core/src/cmp.rs:LL:COL
               let mut _36: &usize;         // in scope 4 at $SRC_DIR/core/src/cmp.rs:LL:COL
               scope 5 (inlined cmp::impls::<impl PartialOrd for usize>::le) { // at $SRC_DIR/core/src/cmp.rs:LL:COL
-                  debug self => _35;       // in scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
-                  debug other => _36;      // in scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
+-                 debug self => _35;       // in scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
+-                 debug other => _36;      // in scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
++                 debug self => &((*_27).2: usize); // in scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
++                 debug other => &((*_25).0: usize); // in scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
                   let mut _39: usize;      // in scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
                   let mut _40: usize;      // in scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
               }
           }
           scope 6 (inlined cmp::impls::<impl PartialOrd for &usize>::le) { // at $DIR/slice_filter.rs:8:50: 8:56
-              debug self => _13;           // in scope 6 at $SRC_DIR/core/src/cmp.rs:LL:COL
-              debug other => _14;          // in scope 6 at $SRC_DIR/core/src/cmp.rs:LL:COL
+-             debug self => _13;           // in scope 6 at $SRC_DIR/core/src/cmp.rs:LL:COL
+-             debug other => _14;          // in scope 6 at $SRC_DIR/core/src/cmp.rs:LL:COL
++             debug self => &&((*_28).3: usize); // in scope 6 at $SRC_DIR/core/src/cmp.rs:LL:COL
++             debug other => &&((*_26).1: usize); // in scope 6 at $SRC_DIR/core/src/cmp.rs:LL:COL
               let mut _41: &usize;         // in scope 6 at $SRC_DIR/core/src/cmp.rs:LL:COL
               let mut _42: &usize;         // in scope 6 at $SRC_DIR/core/src/cmp.rs:LL:COL
               scope 7 (inlined cmp::impls::<impl PartialOrd for usize>::le) { // at $SRC_DIR/core/src/cmp.rs:LL:COL
-                  debug self => _41;       // in scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
-                  debug other => _42;      // in scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
+-                 debug self => _41;       // in scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
+-                 debug other => _42;      // in scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
++                 debug self => &((*_28).3: usize); // in scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
++                 debug other => &((*_26).1: usize); // in scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
                   let mut _45: usize;      // in scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
                   let mut _46: usize;      // in scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
               }
           }
           scope 8 (inlined cmp::impls::<impl PartialOrd for &usize>::le) { // at $DIR/slice_filter.rs:8:70: 8:76
-              debug self => _22;           // in scope 8 at $SRC_DIR/core/src/cmp.rs:LL:COL
-              debug other => _23;          // in scope 8 at $SRC_DIR/core/src/cmp.rs:LL:COL
+-             debug self => _22;           // in scope 8 at $SRC_DIR/core/src/cmp.rs:LL:COL
+-             debug other => _23;          // in scope 8 at $SRC_DIR/core/src/cmp.rs:LL:COL
++             debug self => &&((*_26).1: usize); // in scope 8 at $SRC_DIR/core/src/cmp.rs:LL:COL
++             debug other => &&((*_28).3: usize); // in scope 8 at $SRC_DIR/core/src/cmp.rs:LL:COL
               let mut _47: &usize;         // in scope 8 at $SRC_DIR/core/src/cmp.rs:LL:COL
               let mut _48: &usize;         // in scope 8 at $SRC_DIR/core/src/cmp.rs:LL:COL
               scope 9 (inlined cmp::impls::<impl PartialOrd for usize>::le) { // at $SRC_DIR/core/src/cmp.rs:LL:COL
-                  debug self => _47;       // in scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
-                  debug other => _48;      // in scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
+-                 debug self => _47;       // in scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
+-                 debug other => _48;      // in scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
++                 debug self => &((*_26).1: usize); // in scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
++                 debug other => &((*_28).3: usize); // in scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
                   let mut _51: usize;      // in scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
                   let mut _52: usize;      // in scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
               }
@@ -93,40 +113,40 @@
       }
   
       bb0: {
-          StorageLive(_3);                 // scope 0 at $DIR/slice_filter.rs:+0:27: +0:28
+-         StorageLive(_3);                 // scope 0 at $DIR/slice_filter.rs:+0:27: +0:28
           _25 = deref_copy (*_2);          // scope 0 at $DIR/slice_filter.rs:+0:27: +0:28
-          _3 = &((*_25).0: usize);         // scope 0 at $DIR/slice_filter.rs:+0:27: +0:28
-          StorageLive(_4);                 // scope 0 at $DIR/slice_filter.rs:+0:30: +0:31
+-         _3 = &((*_25).0: usize);         // scope 0 at $DIR/slice_filter.rs:+0:27: +0:28
+-         StorageLive(_4);                 // scope 0 at $DIR/slice_filter.rs:+0:30: +0:31
           _26 = deref_copy (*_2);          // scope 0 at $DIR/slice_filter.rs:+0:30: +0:31
-          _4 = &((*_26).1: usize);         // scope 0 at $DIR/slice_filter.rs:+0:30: +0:31
-          StorageLive(_5);                 // scope 0 at $DIR/slice_filter.rs:+0:33: +0:34
+-         _4 = &((*_26).1: usize);         // scope 0 at $DIR/slice_filter.rs:+0:30: +0:31
+-         StorageLive(_5);                 // scope 0 at $DIR/slice_filter.rs:+0:33: +0:34
           _27 = deref_copy (*_2);          // scope 0 at $DIR/slice_filter.rs:+0:33: +0:34
-          _5 = &((*_27).2: usize);         // scope 0 at $DIR/slice_filter.rs:+0:33: +0:34
-          StorageLive(_6);                 // scope 0 at $DIR/slice_filter.rs:+0:36: +0:37
+-         _5 = &((*_27).2: usize);         // scope 0 at $DIR/slice_filter.rs:+0:33: +0:34
+-         StorageLive(_6);                 // scope 0 at $DIR/slice_filter.rs:+0:36: +0:37
           _28 = deref_copy (*_2);          // scope 0 at $DIR/slice_filter.rs:+0:36: +0:37
-          _6 = &((*_28).3: usize);         // scope 0 at $DIR/slice_filter.rs:+0:36: +0:37
+-         _6 = &((*_28).3: usize);         // scope 0 at $DIR/slice_filter.rs:+0:36: +0:37
           StorageLive(_7);                 // scope 1 at $DIR/slice_filter.rs:+0:40: +0:56
           StorageLive(_8);                 // scope 1 at $DIR/slice_filter.rs:+0:40: +0:46
-          StorageLive(_9);                 // scope 1 at $DIR/slice_filter.rs:+0:40: +0:41
-          _9 = &_3;                        // scope 1 at $DIR/slice_filter.rs:+0:40: +0:41
-          StorageLive(_10);                // scope 1 at $DIR/slice_filter.rs:+0:45: +0:46
-          StorageLive(_11);                // scope 1 at $DIR/slice_filter.rs:+0:45: +0:46
-          _11 = _5;                        // scope 1 at $DIR/slice_filter.rs:+0:45: +0:46
-          _10 = &_11;                      // scope 1 at $DIR/slice_filter.rs:+0:45: +0:46
+-         StorageLive(_9);                 // scope 1 at $DIR/slice_filter.rs:+0:40: +0:41
+-         _9 = &_3;                        // scope 1 at $DIR/slice_filter.rs:+0:40: +0:41
+-         StorageLive(_10);                // scope 1 at $DIR/slice_filter.rs:+0:45: +0:46
+-         StorageLive(_11);                // scope 1 at $DIR/slice_filter.rs:+0:45: +0:46
+-         _11 = _5;                        // scope 1 at $DIR/slice_filter.rs:+0:45: +0:46
+-         _10 = &_11;                      // scope 1 at $DIR/slice_filter.rs:+0:45: +0:46
 -         _29 = deref_copy (*_9);          // scope 2 at $SRC_DIR/core/src/cmp.rs:LL:COL
 -         _30 = deref_copy (*_10);         // scope 2 at $SRC_DIR/core/src/cmp.rs:LL:COL
-+         _29 = deref_copy _3;             // scope 2 at $SRC_DIR/core/src/cmp.rs:LL:COL
-+         _30 = deref_copy _11;            // scope 2 at $SRC_DIR/core/src/cmp.rs:LL:COL
           StorageLive(_33);                // scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          _33 = (*_29);                    // scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
+-         _33 = (*_29);                    // scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
++         _33 = ((*_25).0: usize);         // scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
           StorageLive(_34);                // scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          _34 = (*_30);                    // scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
+-         _34 = (*_30);                    // scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
++         _34 = ((*_27).2: usize);         // scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
           _8 = Le(move _33, move _34);     // scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
           StorageDead(_34);                // scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
           StorageDead(_33);                // scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          StorageDead(_11);                // scope 1 at $DIR/slice_filter.rs:+0:45: +0:46
-          StorageDead(_10);                // scope 1 at $DIR/slice_filter.rs:+0:45: +0:46
-          StorageDead(_9);                 // scope 1 at $DIR/slice_filter.rs:+0:45: +0:46
+-         StorageDead(_11);                // scope 1 at $DIR/slice_filter.rs:+0:45: +0:46
+-         StorageDead(_10);                // scope 1 at $DIR/slice_filter.rs:+0:45: +0:46
+-         StorageDead(_9);                 // scope 1 at $DIR/slice_filter.rs:+0:45: +0:46
           switchInt(move _8) -> [0: bb4, otherwise: bb5]; // scope 1 at $DIR/slice_filter.rs:+0:40: +0:56
       }
   
@@ -138,36 +158,36 @@
       bb2: {
           StorageLive(_16);                // scope 1 at $DIR/slice_filter.rs:+0:60: +0:76
           StorageLive(_17);                // scope 1 at $DIR/slice_filter.rs:+0:60: +0:66
-          StorageLive(_18);                // scope 1 at $DIR/slice_filter.rs:+0:60: +0:61
-          _18 = &_5;                       // scope 1 at $DIR/slice_filter.rs:+0:60: +0:61
-          StorageLive(_19);                // scope 1 at $DIR/slice_filter.rs:+0:65: +0:66
-          StorageLive(_20);                // scope 1 at $DIR/slice_filter.rs:+0:65: +0:66
-          _20 = _3;                        // scope 1 at $DIR/slice_filter.rs:+0:65: +0:66
-          _19 = &_20;                      // scope 1 at $DIR/slice_filter.rs:+0:65: +0:66
+-         StorageLive(_18);                // scope 1 at $DIR/slice_filter.rs:+0:60: +0:61
+-         _18 = &_5;                       // scope 1 at $DIR/slice_filter.rs:+0:60: +0:61
+-         StorageLive(_19);                // scope 1 at $DIR/slice_filter.rs:+0:65: +0:66
+-         StorageLive(_20);                // scope 1 at $DIR/slice_filter.rs:+0:65: +0:66
+-         _20 = _3;                        // scope 1 at $DIR/slice_filter.rs:+0:65: +0:66
+-         _19 = &_20;                      // scope 1 at $DIR/slice_filter.rs:+0:65: +0:66
 -         _35 = deref_copy (*_18);         // scope 4 at $SRC_DIR/core/src/cmp.rs:LL:COL
 -         _36 = deref_copy (*_19);         // scope 4 at $SRC_DIR/core/src/cmp.rs:LL:COL
-+         _35 = deref_copy _5;             // scope 4 at $SRC_DIR/core/src/cmp.rs:LL:COL
-+         _36 = deref_copy _20;            // scope 4 at $SRC_DIR/core/src/cmp.rs:LL:COL
           StorageLive(_39);                // scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          _39 = (*_35);                    // scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
+-         _39 = (*_35);                    // scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
++         _39 = ((*_27).2: usize);         // scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
           StorageLive(_40);                // scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          _40 = (*_36);                    // scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
+-         _40 = (*_36);                    // scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
++         _40 = ((*_25).0: usize);         // scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
           _17 = Le(move _39, move _40);    // scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
           StorageDead(_40);                // scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
           StorageDead(_39);                // scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          StorageDead(_20);                // scope 1 at $DIR/slice_filter.rs:+0:65: +0:66
-          StorageDead(_19);                // scope 1 at $DIR/slice_filter.rs:+0:65: +0:66
-          StorageDead(_18);                // scope 1 at $DIR/slice_filter.rs:+0:65: +0:66
+-         StorageDead(_20);                // scope 1 at $DIR/slice_filter.rs:+0:65: +0:66
+-         StorageDead(_19);                // scope 1 at $DIR/slice_filter.rs:+0:65: +0:66
+-         StorageDead(_18);                // scope 1 at $DIR/slice_filter.rs:+0:65: +0:66
           switchInt(move _17) -> [0: bb6, otherwise: bb7]; // scope 1 at $DIR/slice_filter.rs:+0:60: +0:76
       }
   
       bb3: {
           StorageDead(_16);                // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
           StorageDead(_7);                 // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
-          StorageDead(_6);                 // scope 0 at $DIR/slice_filter.rs:+0:75: +0:76
-          StorageDead(_5);                 // scope 0 at $DIR/slice_filter.rs:+0:75: +0:76
-          StorageDead(_4);                 // scope 0 at $DIR/slice_filter.rs:+0:75: +0:76
-          StorageDead(_3);                 // scope 0 at $DIR/slice_filter.rs:+0:75: +0:76
+-         StorageDead(_6);                 // scope 0 at $DIR/slice_filter.rs:+0:75: +0:76
+-         StorageDead(_5);                 // scope 0 at $DIR/slice_filter.rs:+0:75: +0:76
+-         StorageDead(_4);                 // scope 0 at $DIR/slice_filter.rs:+0:75: +0:76
+-         StorageDead(_3);                 // scope 0 at $DIR/slice_filter.rs:+0:75: +0:76
           return;                          // scope 0 at $DIR/slice_filter.rs:+0:76: +0:76
       }
   
@@ -180,26 +200,26 @@
   
       bb5: {
           StorageLive(_12);                // scope 1 at $DIR/slice_filter.rs:+0:50: +0:56
-          StorageLive(_13);                // scope 1 at $DIR/slice_filter.rs:+0:50: +0:51
-          _13 = &_6;                       // scope 1 at $DIR/slice_filter.rs:+0:50: +0:51
-          StorageLive(_14);                // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
-          StorageLive(_15);                // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
-          _15 = _4;                        // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
-          _14 = &_15;                      // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
+-         StorageLive(_13);                // scope 1 at $DIR/slice_filter.rs:+0:50: +0:51
+-         _13 = &_6;                       // scope 1 at $DIR/slice_filter.rs:+0:50: +0:51
+-         StorageLive(_14);                // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
+-         StorageLive(_15);                // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
+-         _15 = _4;                        // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
+-         _14 = &_15;                      // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
 -         _41 = deref_copy (*_13);         // scope 6 at $SRC_DIR/core/src/cmp.rs:LL:COL
 -         _42 = deref_copy (*_14);         // scope 6 at $SRC_DIR/core/src/cmp.rs:LL:COL
-+         _41 = deref_copy _6;             // scope 6 at $SRC_DIR/core/src/cmp.rs:LL:COL
-+         _42 = deref_copy _15;            // scope 6 at $SRC_DIR/core/src/cmp.rs:LL:COL
           StorageLive(_45);                // scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          _45 = (*_41);                    // scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
+-         _45 = (*_41);                    // scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
++         _45 = ((*_28).3: usize);         // scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
           StorageLive(_46);                // scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          _46 = (*_42);                    // scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
+-         _46 = (*_42);                    // scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
++         _46 = ((*_26).1: usize);         // scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
           _12 = Le(move _45, move _46);    // scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
           StorageDead(_46);                // scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
           StorageDead(_45);                // scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          StorageDead(_15);                // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
-          StorageDead(_14);                // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
-          StorageDead(_13);                // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
+-         StorageDead(_15);                // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
+-         StorageDead(_14);                // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
+-         StorageDead(_13);                // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
           _7 = move _12;                   // scope 1 at $DIR/slice_filter.rs:+0:40: +0:56
           StorageDead(_12);                // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
           StorageDead(_8);                 // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
@@ -213,26 +233,26 @@
   
       bb7: {
           StorageLive(_21);                // scope 1 at $DIR/slice_filter.rs:+0:70: +0:76
-          StorageLive(_22);                // scope 1 at $DIR/slice_filter.rs:+0:70: +0:71
-          _22 = &_4;                       // scope 1 at $DIR/slice_filter.rs:+0:70: +0:71
-          StorageLive(_23);                // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
-          StorageLive(_24);                // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
-          _24 = _6;                        // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
-          _23 = &_24;                      // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
+-         StorageLive(_22);                // scope 1 at $DIR/slice_filter.rs:+0:70: +0:71
+-         _22 = &_4;                       // scope 1 at $DIR/slice_filter.rs:+0:70: +0:71
+-         StorageLive(_23);                // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
+-         StorageLive(_24);                // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
+-         _24 = _6;                        // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
+-         _23 = &_24;                      // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
 -         _47 = deref_copy (*_22);         // scope 8 at $SRC_DIR/core/src/cmp.rs:LL:COL
 -         _48 = deref_copy (*_23);         // scope 8 at $SRC_DIR/core/src/cmp.rs:LL:COL
-+         _47 = deref_copy _4;             // scope 8 at $SRC_DIR/core/src/cmp.rs:LL:COL
-+         _48 = deref_copy _24;            // scope 8 at $SRC_DIR/core/src/cmp.rs:LL:COL
           StorageLive(_51);                // scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          _51 = (*_47);                    // scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
+-         _51 = (*_47);                    // scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
++         _51 = ((*_26).1: usize);         // scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
           StorageLive(_52);                // scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          _52 = (*_48);                    // scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
+-         _52 = (*_48);                    // scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
++         _52 = ((*_28).3: usize);         // scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
           _21 = Le(move _51, move _52);    // scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
           StorageDead(_52);                // scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
           StorageDead(_51);                // scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          StorageDead(_24);                // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
-          StorageDead(_23);                // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
-          StorageDead(_22);                // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
+-         StorageDead(_24);                // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
+-         StorageDead(_23);                // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
+-         StorageDead(_22);                // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
           _16 = move _21;                  // scope 1 at $DIR/slice_filter.rs:+0:60: +0:76
           goto -> bb8;                     // scope 1 at $DIR/slice_filter.rs:+0:60: +0:76
       }
diff --git a/tests/mir-opt/uninhabited_enum.process_void.SimplifyLocals-final.after.mir b/tests/mir-opt/uninhabited_enum.process_void.SimplifyLocals-final.after.mir
index 2af864998cb..4b2a16b50b4 100644
--- a/tests/mir-opt/uninhabited_enum.process_void.SimplifyLocals-final.after.mir
+++ b/tests/mir-opt/uninhabited_enum.process_void.SimplifyLocals-final.after.mir
@@ -3,16 +3,13 @@
 fn process_void(_1: *const Void) -> () {
     debug input => _1;                   // in scope 0 at $DIR/uninhabited_enum.rs:+0:21: +0:26
     let mut _0: ();                      // return place in scope 0 at $DIR/uninhabited_enum.rs:+0:41: +0:41
-    let _2: &Void;                       // in scope 0 at $DIR/uninhabited_enum.rs:+1:8: +1:14
     scope 1 {
-        debug _input => _2;              // in scope 1 at $DIR/uninhabited_enum.rs:+1:8: +1:14
+        debug _input => _1;              // in scope 1 at $DIR/uninhabited_enum.rs:+1:8: +1:14
     }
     scope 2 {
     }
 
     bb0: {
-        StorageLive(_2);                 // scope 0 at $DIR/uninhabited_enum.rs:+1:8: +1:14
-        StorageDead(_2);                 // scope 0 at $DIR/uninhabited_enum.rs:+4:1: +4:2
         return;                          // scope 0 at $DIR/uninhabited_enum.rs:+4:2: +4:2
     }
 }
diff --git a/tests/run-make-fulldeps/obtain-borrowck/driver.rs b/tests/run-make-fulldeps/obtain-borrowck/driver.rs
index 7bd7bb7c1ea..d342b2ff6d9 100644
--- a/tests/run-make-fulldeps/obtain-borrowck/driver.rs
+++ b/tests/run-make-fulldeps/obtain-borrowck/driver.rs
@@ -24,8 +24,8 @@ use rustc_hir::def::DefKind;
 use rustc_hir::def_id::LocalDefId;
 use rustc_interface::interface::Compiler;
 use rustc_interface::{Config, Queries};
-use rustc_middle::ty::query::query_values::mir_borrowck;
-use rustc_middle::ty::query::{ExternProviders, Providers};
+use rustc_middle::query::queries::mir_borrowck::ProvidedValue;
+use rustc_middle::query::{ExternProviders, Providers};
 use rustc_middle::ty::TyCtxt;
 use rustc_session::Session;
 use std::cell::RefCell;
@@ -126,7 +126,7 @@ thread_local! {
         RefCell::new(HashMap::new());
 }
 
-fn mir_borrowck<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> mir_borrowck<'tcx> {
+fn mir_borrowck<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> ProvidedValue<'tcx> {
     let body_with_facts = rustc_borrowck::consumers::get_body_with_borrowck_facts(tcx, def_id);
     // SAFETY: The reader casts the 'static lifetime to 'tcx before using it.
     let body_with_facts: BodyWithBorrowckFacts<'static> =
diff --git a/tests/run-make/CURRENT_RUSTC_VERSION/Makefile b/tests/run-make/CURRENT_RUSTC_VERSION/Makefile
new file mode 100644
index 00000000000..7940dae207b
--- /dev/null
+++ b/tests/run-make/CURRENT_RUSTC_VERSION/Makefile
@@ -0,0 +1,6 @@
+include ../tools.mk
+
+all:
+	$(RUSTC) --emit=metadata --crate-type lib stable.rs
+	$(RUSTC) --emit=metadata --extern stable=$(TMPDIR)/libstable.rmeta main.rs 2>&1 >/dev/null \
+		| $(CGREP) -e "stable since $$(cat $(S)/src/version)(-[a-zA-Z]+)?"
diff --git a/tests/run-make/CURRENT_RUSTC_VERSION/main.rs b/tests/run-make/CURRENT_RUSTC_VERSION/main.rs
new file mode 100644
index 00000000000..466aaa82bd4
--- /dev/null
+++ b/tests/run-make/CURRENT_RUSTC_VERSION/main.rs
@@ -0,0 +1,4 @@
+#![feature(foo)]
+extern crate stable;
+
+fn main() {}
diff --git a/tests/run-make/CURRENT_RUSTC_VERSION/stable.rs b/tests/run-make/CURRENT_RUSTC_VERSION/stable.rs
new file mode 100644
index 00000000000..2fd09aded60
--- /dev/null
+++ b/tests/run-make/CURRENT_RUSTC_VERSION/stable.rs
@@ -0,0 +1,5 @@
+#![feature(staged_api)]
+#![stable(since = "1.0.0", feature = "rust1")]
+
+#[stable(since = "CURRENT_RUSTC_VERSION", feature = "foo")]
+pub fn foo() {}
diff --git a/tests/run-make/coverage-llvmir/filecheck.testprog.txt b/tests/run-make/coverage-llvmir/filecheck.testprog.txt
index c943261d799..b3a8808df05 100644
--- a/tests/run-make/coverage-llvmir/filecheck.testprog.txt
+++ b/tests/run-make/coverage-llvmir/filecheck.testprog.txt
@@ -36,7 +36,7 @@ CHECK-SAME:   section "llvm.metadata"
 CHECK:        [[DEFINE_INTERNAL]] { {{.*}} } @_R{{[a-zA-Z0-9_]+}}testprog14will_be_called() unnamed_addr #{{[0-9]+}} {
 CHECK-NEXT:   start:
 CHECK-NOT:    [[DEFINE_INTERNAL]]
-CHECK:        %pgocount = load i64, {{i64\*|ptr}}
+CHECK:        atomicrmw add ptr
 CHECK-SAME:   @__profc__R{{[a-zA-Z0-9_]+}}testprog14will_be_called,
 
 CHECK:        declare void @llvm.instrprof.increment({{i8\*|ptr}}, i64, i32, i32) #[[LLVM_INSTRPROF_INCREMENT_ATTR:[0-9]+]]
diff --git a/tests/run-make/debugger-visualizer-dep-info/Makefile b/tests/run-make/debugger-visualizer-dep-info/Makefile
new file mode 100644
index 00000000000..0877998a74f
--- /dev/null
+++ b/tests/run-make/debugger-visualizer-dep-info/Makefile
@@ -0,0 +1,9 @@
+include ../tools.mk
+
+# This test makes sure that files referenced via #[debugger_visualizer] are
+# included in `--emit dep-info` output.
+
+all:
+	$(RUSTC) --emit dep-info main.rs
+	$(CGREP) "foo.py" < $(TMPDIR)/main.d
+	$(CGREP) "my_visualizers/bar.natvis" < $(TMPDIR)/main.d
diff --git a/tests/run-make/debugger-visualizer-dep-info/foo.py b/tests/run-make/debugger-visualizer-dep-info/foo.py
new file mode 100644
index 00000000000..1bb8bf6d7fd
--- /dev/null
+++ b/tests/run-make/debugger-visualizer-dep-info/foo.py
@@ -0,0 +1 @@
+# empty
diff --git a/tests/run-make/debugger-visualizer-dep-info/main.rs b/tests/run-make/debugger-visualizer-dep-info/main.rs
new file mode 100644
index 00000000000..3aede2215ea
--- /dev/null
+++ b/tests/run-make/debugger-visualizer-dep-info/main.rs
@@ -0,0 +1,12 @@
+#![debugger_visualizer(gdb_script_file = "foo.py")]
+
+fn main() {
+    const _UNUSED: u32 = {
+        mod inner {
+            #![debugger_visualizer(natvis_file = "my_visualizers/bar.natvis")]
+            pub const XYZ: u32 = 123;
+        }
+
+        inner::XYZ + 1
+    };
+}
diff --git a/tests/run-make/debugger-visualizer-dep-info/my_visualizers/bar.natvis b/tests/run-make/debugger-visualizer-dep-info/my_visualizers/bar.natvis
new file mode 100644
index 00000000000..c341a403902
--- /dev/null
+++ b/tests/run-make/debugger-visualizer-dep-info/my_visualizers/bar.natvis
@@ -0,0 +1 @@
+<!-- empty -->
diff --git a/tests/run-make/incremental-debugger-visualizer/Makefile b/tests/run-make/incremental-debugger-visualizer/Makefile
new file mode 100644
index 00000000000..8cfe41597ad
--- /dev/null
+++ b/tests/run-make/incremental-debugger-visualizer/Makefile
@@ -0,0 +1,49 @@
+include ../tools.mk
+
+# This test makes sure that changes to files referenced via #[debugger_visualizer]
+# are picked up when compiling incrementally.
+
+# We have to copy the source to $(TMPDIR) because Github CI mounts the source
+# directory as readonly. We need to apply modifications to some of the source
+# file.
+SRC_DIR := $(TMPDIR)/src
+INCR_CACHE_DIR := $(TMPDIR)/incremental
+
+all:
+	rm -rf $(TMPDIR)/*
+	mkdir $(SRC_DIR)
+	cp ./foo.rs $(SRC_DIR)
+	echo "GDB script v1" > $(SRC_DIR)/foo.py
+	echo "Natvis v1" > $(SRC_DIR)/foo.natvis
+	$(RUSTC) $(SRC_DIR)/foo.rs \
+	  --crate-type=rlib \
+	  --emit metadata \
+	  -C incremental=$(INCR_CACHE_DIR) \
+	  -Z incremental-verify-ich
+	$(CGREP) "GDB script v1" < $(TMPDIR)/libfoo.rmeta
+	$(CGREP) "Natvis v1" < $(TMPDIR)/libfoo.rmeta
+
+	# Change only the GDB script and check that the change has been picked up
+	echo "GDB script v2" > $(SRC_DIR)/foo.py
+	$(RUSTC) $(SRC_DIR)/foo.rs \
+	  --crate-type=rlib \
+	  --emit metadata \
+	  -C incremental=$(INCR_CACHE_DIR) \
+	  -Z incremental-verify-ich
+
+	$(CGREP) "GDB script v2" < $(TMPDIR)/libfoo.rmeta
+	$(CGREP) -v "GDB script v1" < $(TMPDIR)/libfoo.rmeta
+	$(CGREP) "Natvis v1" < $(TMPDIR)/libfoo.rmeta
+
+	# Now change the Natvis version and check that the change has been picked up
+	echo "Natvis v2" > $(SRC_DIR)/foo.natvis
+	$(RUSTC) $(SRC_DIR)/foo.rs \
+	  --crate-type=rlib \
+	  --emit metadata \
+	  -C incremental=$(INCR_CACHE_DIR) \
+	  -Z incremental-verify-ich
+
+	$(CGREP) "GDB script v2" < $(TMPDIR)/libfoo.rmeta
+	$(CGREP) -v "GDB script v1" < $(TMPDIR)/libfoo.rmeta
+	$(CGREP) "Natvis v2" < $(TMPDIR)/libfoo.rmeta
+	$(CGREP) -v "Natvis v1" < $(TMPDIR)/libfoo.rmeta
diff --git a/tests/run-make/incremental-debugger-visualizer/foo.rs b/tests/run-make/incremental-debugger-visualizer/foo.rs
new file mode 100644
index 00000000000..8daa36a12d3
--- /dev/null
+++ b/tests/run-make/incremental-debugger-visualizer/foo.rs
@@ -0,0 +1,6 @@
+#![debugger_visualizer(natvis_file = "./foo.natvis")]
+#![debugger_visualizer(gdb_script_file = "./foo.py")]
+
+pub struct Foo {
+    pub x: u32,
+}
diff --git a/tests/run-make/print-native-static-libs/Makefile b/tests/run-make/print-native-static-libs/Makefile
new file mode 100644
index 00000000000..98e72d7696f
--- /dev/null
+++ b/tests/run-make/print-native-static-libs/Makefile
@@ -0,0 +1,15 @@
+include ../tools.mk
+
+# ignore-cross-compile
+# ignore-wasm
+
+all:
+	$(RUSTC) --crate-type rlib -lbar_cli bar.rs
+	$(RUSTC) foo.rs -lfoo_cli --crate-type staticlib --print native-static-libs 2>&1 \
+		| grep 'note: native-static-libs: ' \
+		| sed 's/note: native-static-libs: \(.*\)/\1/' > $(TMPDIR)/libs.txt
+
+	cat $(TMPDIR)/libs.txt | grep -F "glib-2.0" # in bar.rs
+	cat $(TMPDIR)/libs.txt | grep -F "systemd" # in foo.rs
+	cat $(TMPDIR)/libs.txt | grep -F "bar_cli"
+	cat $(TMPDIR)/libs.txt | grep -F "foo_cli"
diff --git a/tests/run-make/print-native-static-libs/bar.rs b/tests/run-make/print-native-static-libs/bar.rs
new file mode 100644
index 00000000000..a563bbc2a22
--- /dev/null
+++ b/tests/run-make/print-native-static-libs/bar.rs
@@ -0,0 +1,13 @@
+#[no_mangle]
+pub extern "C" fn my_bar_add(left: i32, right: i32) -> i32 {
+    // Obviously makes no sense but...
+    unsafe {
+        g_free(std::ptr::null_mut());
+    }
+    left + right
+}
+
+#[link(name = "glib-2.0")]
+extern "C" {
+    fn g_free(p: *mut ());
+}
diff --git a/tests/run-make/print-native-static-libs/foo.rs b/tests/run-make/print-native-static-libs/foo.rs
new file mode 100644
index 00000000000..6acaee20ed4
--- /dev/null
+++ b/tests/run-make/print-native-static-libs/foo.rs
@@ -0,0 +1,15 @@
+extern crate bar;
+
+#[no_mangle]
+pub extern "C" fn my_foo_add(left: i32, right: i32) -> i32 {
+    // Obviously makes no sense but...
+    unsafe {
+        init(std::ptr::null_mut());
+    }
+    bar::my_bar_add(left, right)
+}
+
+#[link(name = "systemd")]
+extern "C" {
+    fn init(p: *mut ());
+}
diff --git a/tests/run-make/short-ice/Makefile b/tests/run-make/short-ice/Makefile
new file mode 100644
index 00000000000..4f33d590237
--- /dev/null
+++ b/tests/run-make/short-ice/Makefile
@@ -0,0 +1,9 @@
+include ../tools.mk
+
+# ignore-windows
+
+export RUSTC := $(RUSTC_ORIGINAL)
+export TMPDIR := $(TMPDIR)
+
+all:
+	bash check.sh
diff --git a/tests/run-make/short-ice/check.sh b/tests/run-make/short-ice/check.sh
new file mode 100644
index 00000000000..96cd8fe86bc
--- /dev/null
+++ b/tests/run-make/short-ice/check.sh
@@ -0,0 +1,36 @@
+#!/bin/sh
+
+RUST_BACKTRACE=1 $RUSTC src/lib.rs -Z treat-err-as-bug=1 1>$TMPDIR/rust-test-1.log 2>&1
+RUST_BACKTRACE=full $RUSTC src/lib.rs -Z treat-err-as-bug=1 1>$TMPDIR/rust-test-2.log 2>&1
+
+short=$(cat $TMPDIR/rust-test-1.log | wc -l)
+full=$(cat $TMPDIR/rust-test-2.log | wc -l)
+rustc_query_count=$(cat $TMPDIR/rust-test-1.log | grep rustc_query_ | wc -l)
+rustc_query_count_full=$(cat $TMPDIR/rust-test-2.log | grep rustc_query_ | wc -l)
+
+begin_count=$(cat $TMPDIR/rust-test-2.log | grep __rust_begin_short_backtrace | wc -l)
+end_count=$(cat $TMPDIR/rust-test-2.log | grep __rust_end_short_backtrace | wc -l)
+
+cat $TMPDIR/rust-test-1.log
+echo "====================="
+cat $TMPDIR/rust-test-2.log
+echo "====================="
+
+echo "short backtrace: $short"
+echo "full  backtrace: $full"
+echo "begin_count: $begin_count"
+echo "end_count  : $end_count"
+echo "rustc_query_count: $rustc_query_count"
+echo "rustc_query_count_full: $rustc_query_count_full"
+
+## backtraces to vary a bit depending on platform and configuration options,
+## here we make sure that the short backtrace of rustc_query is shorter than the full,
+## and marks are in pairs.
+if [ $short -lt $full ] &&
+    [ $begin_count -eq $end_count ] &&
+    [ $(($rustc_query_count + 10)) -lt $rustc_query_count_full ] &&
+    [ $rustc_query_count_full -gt 10 ]; then
+    exit 0
+else
+    exit 1
+fi
diff --git a/tests/run-make/short-ice/src/lib.rs b/tests/run-make/short-ice/src/lib.rs
new file mode 100644
index 00000000000..b23b7f830d7
--- /dev/null
+++ b/tests/run-make/short-ice/src/lib.rs
@@ -0,0 +1,7 @@
+fn func(s: &str) {
+    println!("{}", s);
+}
+
+fn main() {
+    func(1);
+}
diff --git a/tests/rustdoc-gui/anchors.goml b/tests/rustdoc-gui/anchors.goml
index 0904aa90e1b..e9b77296917 100644
--- a/tests/rustdoc-gui/anchors.goml
+++ b/tests/rustdoc-gui/anchors.goml
@@ -75,35 +75,35 @@ call-function: (
     "check-colors",
     {
         "theme": "ayu",
-        "main_color": "rgb(197, 197, 197)",
-        "title_color": "rgb(255, 255, 255)",
-        "main_heading_color": "rgb(255, 255, 255)",
-        "main_heading_type_color": "rgb(255, 160, 165)",
-        "src_link_color": "rgb(57, 175, 215)",
-        "sidebar_link_color": "rgb(83, 177, 219)",
+        "main_color": "#c5c5c5",
+        "title_color": "#fff",
+        "main_heading_color": "#fff",
+        "main_heading_type_color": "#ffa0a5",
+        "src_link_color": "#39afd7",
+        "sidebar_link_color": "#53b1db",
     },
 )
 call-function: (
     "check-colors",
     {
         "theme": "dark",
-        "main_color": "rgb(221, 221, 221)",
-        "title_color": "rgb(221, 221, 221)",
-        "main_heading_color": "rgb(221, 221, 221)",
-        "main_heading_type_color": "rgb(45, 191, 184)",
-        "src_link_color": "rgb(210, 153, 29)",
-        "sidebar_link_color": "rgb(253, 191, 53)",
+        "main_color": "#ddd",
+        "title_color": "#ddd",
+        "main_heading_color": "#ddd",
+        "main_heading_type_color": "#2dbfb8",
+        "src_link_color": "#d2991d",
+        "sidebar_link_color": "#fdbf35",
     },
 )
 call-function: (
     "check-colors",
     {
         "theme": "light",
-        "main_color": "rgb(0, 0, 0)",
-        "title_color": "rgb(0, 0, 0)",
-        "main_heading_color": "rgb(0, 0, 0)",
-        "main_heading_type_color": "rgb(173, 55, 138)",
-        "src_link_color": "rgb(56, 115, 173)",
-        "sidebar_link_color": "rgb(53, 109, 164)",
+        "main_color": "black",
+        "title_color": "black",
+        "main_heading_color": "black",
+        "main_heading_type_color": "#ad378a",
+        "src_link_color": "#3873ad",
+        "sidebar_link_color": "#356da4",
     },
 )
diff --git a/tests/rustdoc-gui/codeblock-tooltip.goml b/tests/rustdoc-gui/codeblock-tooltip.goml
index 2ed0579d314..e1c81ed79e4 100644
--- a/tests/rustdoc-gui/codeblock-tooltip.goml
+++ b/tests/rustdoc-gui/codeblock-tooltip.goml
@@ -109,19 +109,19 @@ define-function: (
 
 call-function: ("check-colors", {
     "theme": "ayu",
-    "background": "rgb(15, 20, 25)",
-    "color": "rgb(197, 197, 197)",
-    "border": "rgb(92, 103, 115)",
+    "background": "#0f1419",
+    "color": "#c5c5c5",
+    "border": "#5c6773",
 })
 call-function: ("check-colors", {
     "theme": "dark",
-    "background": "rgb(53, 53, 53)",
-    "color": "rgb(221, 221, 221)",
-    "border": "rgb(224, 224, 224)",
+    "background": "#353535",
+    "color": "#ddd",
+    "border": "#e0e0e0",
 })
 call-function: ("check-colors", {
     "theme": "light",
-    "background": "rgb(255, 255, 255)",
-    "color": "rgb(0, 0, 0)",
-    "border": "rgb(224, 224, 224)",
+    "background": "white",
+    "color": "black",
+    "border": "#e0e0e0",
 })
diff --git a/tests/rustdoc-gui/scrape-examples-color.goml b/tests/rustdoc-gui/scrape-examples-color.goml
index 8ddb06fccfc..0052d18dc56 100644
--- a/tests/rustdoc-gui/scrape-examples-color.goml
+++ b/tests/rustdoc-gui/scrape-examples-color.goml
@@ -33,30 +33,30 @@ define-function: (
 
 call-function: ("check-colors", {
     "theme": "ayu",
-    "highlight": "rgb(91, 59, 1)",
-    "highlight_focus": "rgb(124, 75, 15)",
-    "help_border": "rgb(170, 170, 170)",
-    "help_color": "rgb(238, 238, 238)",
-    "help_hover_border": "rgb(255, 255, 255)",
-    "help_hover_color": "rgb(255, 255, 255)",
+    "highlight": "#5b3b01",
+    "highlight_focus": "#7c4b0f",
+    "help_border": "#aaa",
+    "help_color": "#eee",
+    "help_hover_border": "#fff",
+    "help_hover_color": "#fff",
 })
 call-function: ("check-colors", {
     "theme": "dark",
-    "highlight": "rgb(91, 59, 1)",
-    "highlight_focus": "rgb(124, 75, 15)",
-    "help_border": "rgb(170, 170, 170)",
-    "help_color": "rgb(238, 238, 238)",
-    "help_hover_border": "rgb(255, 255, 255)",
-    "help_hover_color": "rgb(255, 255, 255)",
+    "highlight": "#5b3b01",
+    "highlight_focus": "#7c4b0f",
+    "help_border": "#aaa",
+    "help_color": "#eee",
+    "help_hover_border": "#fff",
+    "help_hover_color": "#fff",
 })
 call-function: ("check-colors", {
     "theme": "light",
-    "highlight": "rgb(252, 255, 214)",
-    "highlight_focus": "rgb(246, 253, 176)",
-    "help_border": "rgb(85, 85, 85)",
-    "help_color": "rgb(51, 51, 51)",
-    "help_hover_border": "rgb(0, 0, 0)",
-    "help_hover_color": "rgb(0, 0, 0)",
+    "highlight": "#fcffd6",
+    "highlight_focus": "#f6fdb0",
+    "help_border": "#555",
+    "help_color": "#333",
+    "help_hover_border": "#000",
+    "help_hover_color": "#000",
 })
 
 // Now testing the top and bottom background in case there is only one scraped examples.
@@ -81,16 +81,16 @@ define-function: (
 
 call-function: ("check-background", {
     "theme": "ayu",
-    "background_color_start": "rgb(15, 20, 25)",
+    "background_color_start": "rgba(15, 20, 25, 1)",
     "background_color_end": "rgba(15, 20, 25, 0)",
 })
 call-function: ("check-background", {
     "theme": "dark",
-    "background_color_start": "rgb(53, 53, 53)",
+    "background_color_start": "rgba(53, 53, 53, 1)",
     "background_color_end": "rgba(53, 53, 53, 0)",
 })
 call-function: ("check-background", {
     "theme": "light",
-    "background_color_start": "rgb(255, 255, 255)",
+    "background_color_start": "rgba(255, 255, 255, 1)",
     "background_color_end": "rgba(255, 255, 255, 0)",
 })
diff --git a/tests/rustdoc-gui/search-result-color.goml b/tests/rustdoc-gui/search-result-color.goml
index da46a90df90..90f7160b724 100644
--- a/tests/rustdoc-gui/search-result-color.goml
+++ b/tests/rustdoc-gui/search-result-color.goml
@@ -47,89 +47,89 @@ reload:
 wait-for: "#search-tabs"
 assert-css: (
     "#search-tabs > button > .count",
-    {"color": "rgb(136, 136, 136)"},
+    {"color": "#888"},
     ALL,
 )
 assert-css: (
     "//*[@class='desc'][text()='Just a normal struct.']",
-    {"color": "rgb(197, 197, 197)"},
+    {"color": "#c5c5c5"},
 )
 assert-css: (
     "//*[@class='result-name']/*[text()='test_docs::']",
-    {"color": "rgb(0, 150, 207)"},
+    {"color": "#0096cf"},
 )
 
 // Checking the color of the bottom border.
 assert-css: (
     ".search-results > a",
-    {"border-bottom-color": "rgba(170, 170, 170, 0.2)"}
+    {"border-bottom-color": "#aaa3"}
 )
 
 // Checking the color of "keyword" text.
 assert-css: (
     "//*[@class='result-name']//*[text()='(keyword)']",
-    {"color": "rgb(120, 135, 151)"},
+    {"color": "#788797"},
 )
 
-store-value: (entry_color, "rgb(0, 150, 207)") // color of the search entry
-store-value: (hover_entry_color, "rgb(255, 255, 255)") // color of the hovered/focused search entry
-store-value: (background_color, "rgba(0, 0, 0, 0)") // background color
-store-value: (hover_background_color, "rgb(60, 60, 60)") // hover background color
+store-value: (entry_color, "#0096cf") // color of the search entry
+store-value: (hover_entry_color, "#fff") // color of the hovered/focused search entry
+store-value: (background_color, "transparent") // background color
+store-value: (hover_background_color, "#3c3c3c") // hover background color
 
 call-function: (
     "check-result-color", (
         "keyword", // item kind
-        "rgb(57, 175, 215)", // color of item kind
-        "rgb(57, 175, 215)", // color of hovered/focused item kind
+        "#39afd7", // color of item kind
+        "#39afd7", // color of hovered/focused item kind
     ),
 )
 call-function: (
     "check-result-color", (
         "struct", // item kind
-        "rgb(255, 160, 165)", // color of item kind
-        "rgb(255, 160, 165)", // color of hovered/focused item kind
+        "#ffa0a5", // color of item kind
+        "#ffa0a5", // color of hovered/focused item kind
     ),
 )
 call-function: (
     "check-result-color", (
         "associatedtype", // item kind
-        "rgb(57, 175, 215)", // color of item kind
-        "rgb(57, 175, 215)", // color of hovered/focused item kind
+        "#39afd7", // color of item kind
+        "#39afd7", // color of hovered/focused item kind
     ),
 )
 call-function: (
     "check-result-color", (
         "tymethod", // item kind
-        "rgb(253, 214, 135)", // color of item kind
-        "rgb(253, 214, 135)", // color of hovered/focused item kind
+        "#fdd687", // color of item kind
+        "#fdd687", // color of hovered/focused item kind
     ),
 )
 call-function: (
     "check-result-color", (
         "method", // item kind
-        "rgb(253, 214, 135)", // color of item kind
-        "rgb(253, 214, 135)", // color of hovered/focused item kind
+        "#fdd687", // color of item kind
+        "#fdd687", // color of hovered/focused item kind
     ),
 )
 call-function: (
     "check-result-color", (
         "structfield", // item kind
-        "rgb(0, 150, 207)", // color of item kind
-        "rgb(255, 255, 255)", // color of hovered/focused item kind
+        "#0096cf", // color of item kind
+        "#fff", // color of hovered/focused item kind
     ),
 )
 call-function: (
     "check-result-color", (
         "macro", // item kind
-        "rgb(163, 122, 204)", // color of item kind
-        "rgb(163, 122, 204)", // color of hovered/focused item kind
+        "#a37acc", // color of item kind
+        "#a37acc", // color of hovered/focused item kind
     ),
 )
 call-function: (
     "check-result-color", (
         "fn", // item kind
-        "rgb(253, 214, 135)", // color of item kind
-        "rgb(253, 214, 135)", // color of hovered/focused item kind
+        "#fdd687", // color of item kind
+        "#fdd687", // color of hovered/focused item kind
     ),
 )
 
@@ -138,7 +138,7 @@ move-cursor-to: ".search-input"
 focus: ".search-input" // To ensure the `<a>` container isnt focus or hover.
 assert-css: (
     "//*[@class='result-name']/*[text()='test_docs::']/ancestor::a",
-    {"color": "rgb(0, 150, 207)", "background-color": "rgba(0, 0, 0, 0)"},
+    {"color": "#0096cf", "background-color": "transparent"},
     ALL,
 )
 
@@ -146,11 +146,11 @@ assert-css: (
 move-cursor-to: "//*[@class='desc'][text()='Just a normal struct.']"
 assert-css: (
     "//*[@class='result-name']/*[text()='test_docs::']",
-    {"color": "rgb(255, 255, 255)"},
+    {"color": "#fff"},
 )
 assert-css: (
     "//*[@class='result-name']/*[text()='test_docs::']/ancestor::a",
-    {"color": "rgb(255, 255, 255)", "background-color": "rgb(60, 60, 60)"},
+    {"color": "#fff", "background-color": "rgb(60, 60, 60)"},
 )
 
 // Dark theme
@@ -164,89 +164,89 @@ reload:
 wait-for: "#search-tabs"
 assert-css: (
     "#search-tabs > button > .count",
-    {"color": "rgb(136, 136, 136)"},
+    {"color": "#888"},
     ALL,
 )
 assert-css: (
     "//*[@class='desc'][text()='Just a normal struct.']",
-    {"color": "rgb(221, 221, 221)"},
+    {"color": "#ddd"},
 )
 assert-css: (
     "//*[@class='result-name']/*[text()='test_docs::']",
-    {"color": "rgb(221, 221, 221)"},
+    {"color": "#ddd"},
 )
 
 // Checking the color of the bottom border.
 assert-css: (
     ".search-results > a",
-    {"border-bottom-color": "rgba(170, 170, 170, 0.2)"}
+    {"border-bottom-color": "#aaa3"}
 )
 
 // Checking the color for "keyword" text.
 assert-css: (
     "//*[@class='result-name']//*[text()='(keyword)']",
-    {"color": "rgb(221, 221, 221)"},
+    {"color": "#ddd"},
 )
 
-store-value: (entry_color, "rgb(221, 221, 221)") // color of the search entry
-store-value: (hover_entry_color, "rgb(221, 221, 221)") // color of the hovered/focused search entry
-store-value: (background_color, "rgba(0, 0, 0, 0)") // background color
-store-value: (hover_background_color, "rgb(97, 97, 97)") // hover background color
+store-value: (entry_color, "#ddd") // color of the search entry
+store-value: (hover_entry_color, "#ddd") // color of the hovered/focused search entry
+store-value: (background_color, "transparent") // background color
+store-value: (hover_background_color, "#616161") // hover background color
 
 call-function: (
     "check-result-color", (
         "keyword", // item kind
-        "rgb(210, 153, 29)", // color of item kind
-        "rgb(210, 153, 29)", // color of hovered/focused item kind
+        "#d2991d", // color of item kind
+        "#d2991d", // color of hovered/focused item kind
     ),
 )
 call-function: (
     "check-result-color", (
         "struct", // item kind
-        "rgb(45, 191, 184)", // color of item kind
-        "rgb(45, 191, 184)", // color of hovered/focused item kind
+        "#2dbfb8", // color of item kind
+        "#2dbfb8", // color of hovered/focused item kind
     ),
 )
 call-function: (
     "check-result-color", (
         "associatedtype", // item kind
-        "rgb(210, 153, 29)", // color of item kind
-        "rgb(210, 153, 29)", // color of hovered/focused item kind
+        "#d2991d", // color of item kind
+        "#d2991d", // color of hovered/focused item kind
     ),
 )
 call-function: (
     "check-result-color", (
         "tymethod", // item kind
-        "rgb(43, 171, 99)", // color of item kind
-        "rgb(43, 171, 99)", // color of hovered/focused item kind
+        "#2bab63", // color of item kind
+        "#2bab63", // color of hovered/focused item kind
     ),
 )
 call-function: (
     "check-result-color", (
         "method", // item kind
-        "rgb(43, 171, 99)", // color of item kind
-        "rgb(43, 171, 99)", // color of hovered/focused item kind
+        "#2bab63", // color of item kind
+        "#2bab63", // color of hovered/focused item kind
     ),
 )
 call-function: (
     "check-result-color", (
         "structfield", // item kind
-        "rgb(221, 221, 221)", // color of item kind
-        "rgb(221, 221, 221)", // color of hovered/focused item kind
+        "#ddd", // color of item kind
+        "#ddd", // color of hovered/focused item kind
     ),
 )
 call-function: (
     "check-result-color", (
         "macro", // item kind
-        "rgb(9, 189, 0)", // color of item kind
-        "rgb(9, 189, 0)", // color of hovered/focused item kind
+        "#09bd00", // color of item kind
+        "#09bd00", // color of hovered/focused item kind
     ),
 )
 call-function: (
     "check-result-color", (
         "fn", // item kind
-        "rgb(43, 171, 99)", // color of item kind
-        "rgb(43, 171, 99)", // color of hovered/focused item kind
+        "#2bab63", // color of item kind
+        "#2bab63", // color of hovered/focused item kind
     ),
 )
 
@@ -255,7 +255,7 @@ move-cursor-to: ".search-input"
 focus: ".search-input" // To ensure the `<a>` container isnt focus or hover.
 assert-css: (
     "//*[@class='result-name']/*[text()='test_docs::']/ancestor::a",
-    {"color": "rgb(221, 221, 221)", "background-color": "rgba(0, 0, 0, 0)"},
+    {"color": "#ddd", "background-color": "transparent"},
 )
 
 // Light theme
@@ -266,89 +266,89 @@ reload:
 wait-for: "#search-tabs"
 assert-css: (
     "#search-tabs > button > .count",
-    {"color": "rgb(136, 136, 136)"},
+    {"color": "#888"},
     ALL,
 )
 assert-css: (
     "//*[@class='desc'][text()='Just a normal struct.']",
-    {"color": "rgb(0, 0, 0)"},
+    {"color": "#000"},
 )
 assert-css: (
     "//*[@class='result-name']/*[text()='test_docs::']",
-    {"color": "rgb(0, 0, 0)"},
+    {"color": "#000"},
 )
 
 // Checking the color of the bottom border.
 assert-css: (
     ".search-results > a",
-    {"border-bottom-color": "rgba(170, 170, 170, 0.2)"}
+    {"border-bottom-color": "#aaa3"}
 )
 
 // Checking the color for "keyword" text.
 assert-css: (
     "//*[@class='result-name']//*[text()='(keyword)']",
-    {"color": "rgb(0, 0, 0)"},
+    {"color": "#000"},
 )
 
-store-value: (entry_color, "rgb(0, 0, 0)") // color of the search entry
-store-value: (hover_entry_color, "rgb(0, 0, 0)") // color of the hovered/focused search entry
-store-value: (background_color, "rgba(0, 0, 0, 0)") // background color
-store-value: (hover_background_color, "rgb(204, 204, 204)") // hover background color
+store-value: (entry_color, "#000") // color of the search entry
+store-value: (hover_entry_color, "#000") // color of the hovered/focused search entry
+store-value: (background_color, "transparent") // background color
+store-value: (hover_background_color, "#ccc") // hover background color
 
 call-function: (
     "check-result-color", (
         "keyword", // item kind
-        "rgb(56, 115, 173)", // color of item kind
-        "rgb(56, 115, 173)", // color of hovered/focused item kind
+        "#3873ad", // color of item kind
+        "#3873ad", // color of hovered/focused item kind
     ),
 )
 call-function: (
     "check-result-color", (
         "struct", // item kind
-        "rgb(173, 55, 138)", // color of item kind
-        "rgb(173, 55, 138)", // color of hovered/focused item kind
+        "#ad378a", // color of item kind
+        "#ad378a", // color of hovered/focused item kind
     ),
 )
 call-function: (
     "check-result-color", (
         "associatedtype", // item kind
-        "rgb(56, 115, 173)", // color of item kind
-        "rgb(56, 115, 173)", // color of hovered/focused item kind
+        "#3873ad", // color of item kind
+        "#3873ad", // color of hovered/focused item kind
     ),
 )
 call-function: (
     "check-result-color", (
         "tymethod", // item kind
-        "rgb(173, 124, 55)", // color of item kind
-        "rgb(173, 124, 55)", // color of hovered/focused item kind
+        "#ad7c37", // color of item kind
+        "#ad7c37", // color of hovered/focused item kind
     ),
 )
 call-function: (
     "check-result-color", (
         "method", // item kind
-        "rgb(173, 124, 55)", // color of item kind
-        "rgb(173, 124, 55)", // color of hovered/focused item kind
+        "#ad7c37", // color of item kind
+        "#ad7c37", // color of hovered/focused item kind
     ),
 )
 call-function: (
     "check-result-color", (
         "structfield", // item kind
-        "rgb(0, 0, 0)", // color of item kind
-        "rgb(0, 0, 0)", // color of hovered/focused item kind
+        "#000", // color of item kind
+        "#000", // color of hovered/focused item kind
     ),
 )
 call-function: (
     "check-result-color", (
         "macro", // item kind
-        "rgb(6, 128, 0)", // color of item kind
-        "rgb(6, 128, 0)", // color of hovered/focused item kind
+        "#068000", // color of item kind
+        "#068000", // color of hovered/focused item kind
     ),
 )
 call-function: (
     "check-result-color", (
         "fn", // item kind
-        "rgb(173, 124, 55)", // color of item kind
-        "rgb(173, 124, 55)", // color of hovered/focused item kind
+        "#ad7c37", // color of item kind
+        "#ad7c37", // color of hovered/focused item kind
     ),
 )
 
@@ -357,7 +357,7 @@ move-cursor-to: ".search-input"
 focus: ".search-input" // To ensure the `<a>` container isnt focus or hover.
 assert-css: (
     "//*[@class='result-name']/*[text()='test_docs::']/ancestor::a",
-    {"color": "rgb(0, 0, 0)", "background-color": "rgba(0, 0, 0, 0)"},
+    {"color": "#000", "background-color": "transparent"},
 )
 
 // Check the alias.
@@ -386,16 +386,16 @@ define-function: (
 
 call-function: ("check-alias", {
     "theme": "ayu",
-    "alias": "rgb(197, 197, 197)",
-    "grey": "rgb(153, 153, 153)",
+    "alias": "#c5c5c5",
+    "grey": "#999",
 })
 call-function: ("check-alias", {
     "theme": "dark",
-    "alias": "rgb(255, 255, 255)",
-    "grey": "rgb(204, 204, 204)",
+    "alias": "#fff",
+    "grey": "#ccc",
 })
 call-function: ("check-alias", {
     "theme": "light",
-    "alias": "rgb(0, 0, 0)",
-    "grey": "rgb(153, 153, 153)",
+    "alias": "#000",
+    "grey": "#999",
 })
diff --git a/tests/rustdoc-gui/source-code-page.goml b/tests/rustdoc-gui/source-code-page.goml
index 5c795928bdc..d5dd511b1d3 100644
--- a/tests/rustdoc-gui/source-code-page.goml
+++ b/tests/rustdoc-gui/source-code-page.goml
@@ -40,24 +40,24 @@ define-function: (
 
 call-function: ("check-colors", {
     "theme": "ayu",
-    "color": "rgb(92, 103, 115)",
-    "background_color": "rgba(0, 0, 0, 0)",
-    "highlight_color": "rgb(112, 128, 144)",
+    "color": "#5c6773",
+    "background_color": "transparent",
+    "highlight_color": "#708090",
     "highlight_background_color": "rgba(255, 236, 164, 0.06)",
 })
 call-function: ("check-colors", {
     "theme": "dark",
-    "color": "rgb(59, 145, 226)",
-    "background_color": "rgba(0, 0, 0, 0)",
-    "highlight_color": "rgb(59, 145, 226)",
-    "highlight_background_color": "rgb(10, 4, 47)",
+    "color": "#3b91e2",
+    "background_color": "transparent",
+    "highlight_color": "#3b91e2",
+    "highlight_background_color": "#0a042f",
 })
 call-function: ("check-colors", {
     "theme": "light",
-    "color": "rgb(198, 126, 45)",
-    "background_color": "rgba(0, 0, 0, 0)",
-    "highlight_color": "rgb(198, 126, 45)",
-    "highlight_background_color": "rgb(253, 255, 211)",
+    "color": "#c67e2d",
+    "background_color": "transparent",
+    "highlight_color": "#c67e2d",
+    "highlight_background_color": "#fdffd3",
 })
 
 // This is to ensure that the content is correctly align with the line numbers.
diff --git a/tests/rustdoc-json/impls/impl_item_visibility.rs b/tests/rustdoc-json/impls/impl_item_visibility.rs
new file mode 100644
index 00000000000..efa54d91dca
--- /dev/null
+++ b/tests/rustdoc-json/impls/impl_item_visibility.rs
@@ -0,0 +1,26 @@
+#![feature(no_core)]
+#![no_core]
+
+pub struct Foo;
+
+/// impl Foo priv
+impl Foo {
+    fn baz() {}
+}
+// @!has '$.index[*][?(@.docs=="impl Foo priv")]'
+
+
+/// impl Foo pub
+impl Foo {
+    pub fn qux() {}
+}
+// @is '$.index[*][?(@.docs=="impl Foo pub")].visibility' '"default"'
+
+
+/// impl Foo hidden
+impl Foo {
+    #[doc(hidden)]
+    pub fn __quazl(){}
+}
+// FIXME(#111564): Is this the right behaviour?
+// @is '$.index[*][?(@.docs=="impl Foo hidden")].visibility' '"default"'
diff --git a/tests/rustdoc-json/impls/impl_item_visibility_show_hidden.rs b/tests/rustdoc-json/impls/impl_item_visibility_show_hidden.rs
new file mode 100644
index 00000000000..3c6fefc4ca2
--- /dev/null
+++ b/tests/rustdoc-json/impls/impl_item_visibility_show_hidden.rs
@@ -0,0 +1,28 @@
+// compile-flags: --document-hidden-items
+#![feature(no_core)]
+#![no_core]
+
+pub struct Foo;
+
+/// impl Foo priv
+impl Foo {
+    fn baz() {}
+}
+// FIXME(#111564): Is this the right behaviour?
+// @is '$.index[*][?(@.docs=="impl Foo priv")].visibility' '"default"'
+
+
+/// impl Foo pub
+impl Foo {
+    pub fn qux() {}
+}
+// @is '$.index[*][?(@.docs=="impl Foo pub")].visibility' '"default"'
+
+
+/// impl Foo hidden
+impl Foo {
+    #[doc(hidden)]
+    pub fn __quazl(){}
+}
+// FIXME(#111564): Is this the right behaviour?
+// @is '$.index[*][?(@.docs=="impl Foo hidden")].visibility' '"default"'
diff --git a/tests/rustdoc-json/impls/impl_item_visibility_show_private.rs b/tests/rustdoc-json/impls/impl_item_visibility_show_private.rs
new file mode 100644
index 00000000000..b98d1e4167c
--- /dev/null
+++ b/tests/rustdoc-json/impls/impl_item_visibility_show_private.rs
@@ -0,0 +1,27 @@
+// compile-flags: --document-private-items
+#![feature(no_core)]
+#![no_core]
+
+pub struct Foo;
+
+/// impl Foo priv
+impl Foo {
+    fn baz() {}
+}
+// @is '$.index[*][?(@.docs=="impl Foo priv")].visibility' '"default"'
+
+
+/// impl Foo pub
+impl Foo {
+    pub fn qux() {}
+}
+// @is '$.index[*][?(@.docs=="impl Foo pub")].visibility' '"default"'
+
+
+/// impl Foo hidden
+impl Foo {
+    #[doc(hidden)]
+    pub fn __quazl(){}
+}
+// FIXME(#111564): Is this the right behaviour?
+// @is '$.index[*][?(@.docs=="impl Foo hidden")].visibility' '"default"'
diff --git a/tests/rustdoc-json/type/inherent_associated_type.rs b/tests/rustdoc-json/type/inherent_associated_type.rs
new file mode 100644
index 00000000000..ed63def93df
--- /dev/null
+++ b/tests/rustdoc-json/type/inherent_associated_type.rs
@@ -0,0 +1,29 @@
+// ignore-tidy-linelength
+#![feature(inherent_associated_types)]
+#![feature(no_core)]
+#![allow(incomplete_features)]
+#![no_core]
+
+// @set OwnerMetadata = '$.index[*][?(@.name=="OwnerMetadata")].id'
+pub struct OwnerMetadata;
+// @set Owner = '$.index[*][?(@.name=="Owner")].id'
+pub struct Owner;
+
+pub fn create() -> Owner::Metadata {
+    OwnerMetadata
+}
+// @is '$.index[*][?(@.name=="create")].inner.decl.output.kind' '"qualified_path"'
+// @is '$.index[*][?(@.name=="create")].inner.decl.output.inner.name' '"Metadata"'
+// @is '$.index[*][?(@.name=="create")].inner.decl.output.inner.trait' null
+// @is '$.index[*][?(@.name=="create")].inner.decl.output.inner.self_type.kind' '"resolved_path"'
+// @is '$.index[*][?(@.name=="create")].inner.decl.output.inner.self_type.inner.id' $Owner
+
+/// impl
+impl Owner {
+    /// iat
+    pub type Metadata = OwnerMetadata;
+}
+// @set iat = '$.index[*][?(@.docs=="iat")].id'
+// @is '$.index[*][?(@.docs=="impl")].inner.items[*]' $iat
+// @is '$.index[*][?(@.docs=="iat")].kind' '"assoc_type"'
+// @is '$.index[*][?(@.docs=="iat")].inner.default.inner.id' $OwnerMetadata
diff --git a/tests/rustdoc-json/type/inherent_associated_type_bound.rs b/tests/rustdoc-json/type/inherent_associated_type_bound.rs
new file mode 100644
index 00000000000..a089600b692
--- /dev/null
+++ b/tests/rustdoc-json/type/inherent_associated_type_bound.rs
@@ -0,0 +1,21 @@
+// ignore-tidy-linelength
+#![feature(inherent_associated_types)]
+#![allow(incomplete_features)]
+
+// @set Carrier = '$.index[*][?(@.name=="Carrier")].id'
+pub struct Carrier<'a>(&'a ());
+
+// @is '$.index[*][?(@.name=="User")].inner.type.kind' '"function_pointer"'
+// @is '$.index[*][?(@.name=="User")].inner.type.inner.generic_params[*].name' \""'b"\"
+// @is '$.index[*][?(@.name=="User")].inner.type.inner.decl.inputs[0][1].kind' '"qualified_path"'
+// @is '$.index[*][?(@.name=="User")].inner.type.inner.decl.inputs[0][1].inner.self_type.inner.id' $Carrier
+// @is '$.index[*][?(@.name=="User")].inner.type.inner.decl.inputs[0][1].inner.self_type.inner.args.angle_bracketed.args[0].lifetime' \""'b"\"
+// @is '$.index[*][?(@.name=="User")].inner.type.inner.decl.inputs[0][1].inner.name' '"Focus"'
+// @is '$.index[*][?(@.name=="User")].inner.type.inner.decl.inputs[0][1].inner.trait' null
+// @is '$.index[*][?(@.name=="User")].inner.type.inner.decl.inputs[0][1].inner.args.angle_bracketed.args[0].type.inner' '"i32"'
+
+pub type User = for<'b> fn(Carrier<'b>::Focus<i32>);
+
+impl<'a> Carrier<'a> {
+    pub type Focus<T> = &'a mut T;
+}
diff --git a/tests/rustdoc-json/type/inherent_associated_type_projections.rs b/tests/rustdoc-json/type/inherent_associated_type_projections.rs
new file mode 100644
index 00000000000..30c68bfe56c
--- /dev/null
+++ b/tests/rustdoc-json/type/inherent_associated_type_projections.rs
@@ -0,0 +1,33 @@
+// ignore-tidy-linelength
+#![feature(inherent_associated_types)]
+#![allow(incomplete_features)]
+
+// @set Parametrized = '$.index[*][?(@.name=="Parametrized")].id'
+pub struct Parametrized<T>(T);
+
+// @is '$.index[*][?(@.name=="Test")].inner.type.kind' '"qualified_path"'
+// @is '$.index[*][?(@.name=="Test")].inner.type.inner.self_type.inner.id' $Parametrized
+// @is '$.index[*][?(@.name=="Test")].inner.type.inner.self_type.inner.args.angle_bracketed.args[0].type' '{"inner": "i32", "kind": "primitive"}'
+// @is '$.index[*][?(@.name=="Test")].inner.type.inner.name' '"Proj"'
+// @is '$.index[*][?(@.name=="Test")].inner.type.inner.trait' null
+pub type Test = Parametrized<i32>::Proj;
+
+/// param_bool
+impl Parametrized<bool> {
+    /// param_bool_proj
+    pub type Proj = ();
+}
+
+/// param_i32
+impl Parametrized<i32> {
+    /// param_i32_proj
+    pub type Proj = String;
+}
+
+// @set param_bool = '$.index[*][?(@.docs=="param_bool")].id'
+// @set param_i32 = '$.index[*][?(@.docs=="param_i32")].id'
+// @set param_bool_proj = '$.index[*][?(@.docs=="param_bool_proj")].id'
+// @set param_i32_proj = '$.index[*][?(@.docs=="param_i32_proj")].id'
+
+// @is '$.index[*][?(@.docs=="param_bool")].inner.items[*]' $param_bool_proj
+// @is '$.index[*][?(@.docs=="param_i32")].inner.items[*]' $param_i32_proj
diff --git a/tests/rustdoc/nested-items-issue-111415.rs b/tests/rustdoc/nested-items-issue-111415.rs
new file mode 100644
index 00000000000..9b7688c332c
--- /dev/null
+++ b/tests/rustdoc/nested-items-issue-111415.rs
@@ -0,0 +1,36 @@
+// Regression test for <https://github.com/rust-lang/rust/issues/111415>.
+// This test ensures that only impl blocks are documented in bodies.
+
+#![crate_name = "foo"]
+
+// @has 'foo/index.html'
+// Checking there are only three sections.
+// @count - '//*[@id="main-content"]/*[@class="small-section-header"]' 3
+// @has - '//*[@id="main-content"]/*[@class="small-section-header"]' 'Structs'
+// @has - '//*[@id="main-content"]/*[@class="small-section-header"]' 'Functions'
+// @has - '//*[@id="main-content"]/*[@class="small-section-header"]' 'Traits'
+// Checking that there are only three items.
+// @count - '//*[@id="main-content"]//*[@class="item-name"]' 3
+// @has - '//*[@id="main-content"]//a[@href="struct.Bar.html"]' 'Bar'
+// @has - '//*[@id="main-content"]//a[@href="fn.foo.html"]' 'foo'
+// @has - '//*[@id="main-content"]//a[@href="trait.Foo.html"]' 'Foo'
+
+// Now checking that the `foo` method is visible in `Bar` page.
+// @has 'foo/struct.Bar.html'
+// @has - '//*[@id="method.foo"]/*[@class="code-header"]' 'pub fn foo()'
+// @has - '//*[@id="method.bar"]/*[@class="code-header"]' 'fn bar()'
+pub struct Bar;
+
+pub trait Foo {
+    fn bar() {}
+}
+
+pub fn foo() {
+    pub mod inaccessible {}
+    pub fn inner() {}
+    pub const BAR: u32 = 0;
+    impl Bar {
+        pub fn foo() {}
+    }
+    impl Foo for Bar {}
+}
diff --git a/tests/rustdoc/strikethrough-in-summary.rs b/tests/rustdoc/strikethrough-in-summary.rs
new file mode 100644
index 00000000000..cb6cd0e7ba6
--- /dev/null
+++ b/tests/rustdoc/strikethrough-in-summary.rs
@@ -0,0 +1,6 @@
+#![crate_name = "foo"]
+
+// @has foo/index.html '//del' 'strike'
+
+/// ~~strike~~
+pub fn strike() {}
diff --git a/tests/ui/associated-inherent-types/inference.rs b/tests/ui/associated-inherent-types/inference.rs
index 38179214fa1..ebd8e1d5594 100644
--- a/tests/ui/associated-inherent-types/inference.rs
+++ b/tests/ui/associated-inherent-types/inference.rs
@@ -3,6 +3,7 @@
 
 #![feature(inherent_associated_types)]
 #![allow(incomplete_features)]
+#![allow(dropping_copy_types)]
 
 use std::convert::identity;
 
diff --git a/tests/ui/associated-types/associated-types-eq-3.stderr b/tests/ui/associated-types/associated-types-eq-3.stderr
index 15ce4fc91cb..c3377eed20a 100644
--- a/tests/ui/associated-types/associated-types-eq-3.stderr
+++ b/tests/ui/associated-types/associated-types-eq-3.stderr
@@ -43,7 +43,7 @@ note: expected this to be `Bar`
    |
 LL |     type A = usize;
    |              ^^^^^
-   = note: required for the cast from `isize` to the object type `dyn Foo<A = Bar>`
+   = note: required for the cast from `&isize` to `&dyn Foo<A = Bar>`
 
 error: aborting due to 3 previous errors
 
diff --git a/tests/ui/associated-types/associated-types-overridden-binding-2.stderr b/tests/ui/associated-types/associated-types-overridden-binding-2.stderr
index a28a0b74e4a..fdec01b95e3 100644
--- a/tests/ui/associated-types/associated-types-overridden-binding-2.stderr
+++ b/tests/ui/associated-types/associated-types-overridden-binding-2.stderr
@@ -4,7 +4,7 @@ error[E0271]: expected `IntoIter<u32>` to be an iterator that yields `i32`, but
 LL |     let _: &dyn I32Iterator<Item = u32> = &vec![42].into_iter();
    |                                           ^^^^^^^^^^^^^^^^^^^^^ expected `i32`, found `u32`
    |
-   = note: required for the cast from `std::vec::IntoIter<u32>` to the object type `dyn Iterator<Item = u32, Item = i32>`
+   = note: required for the cast from `&std::vec::IntoIter<u32>` to `&dyn Iterator<Item = u32, Item = i32>`
 
 error: aborting due to previous error
 
diff --git a/tests/ui/associated-types/issue-65774-1.stderr b/tests/ui/associated-types/issue-65774-1.stderr
index 91b557555d5..9c77a25c432 100644
--- a/tests/ui/associated-types/issue-65774-1.stderr
+++ b/tests/ui/associated-types/issue-65774-1.stderr
@@ -25,7 +25,7 @@ LL | impl<'a, T: MyDisplay> MyDisplay for &'a mut T { }
    |             ---------  ^^^^^^^^^     ^^^^^^^^^
    |             |
    |             unsatisfied trait bound introduced here
-   = note: required for the cast from `&mut T` to the object type `dyn MyDisplay`
+   = note: required for the cast from `&&mut T` to `&dyn MyDisplay`
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/associated-types/issue-65774-2.stderr b/tests/ui/associated-types/issue-65774-2.stderr
index c22302cdc26..ca8a727f0fe 100644
--- a/tests/ui/associated-types/issue-65774-2.stderr
+++ b/tests/ui/associated-types/issue-65774-2.stderr
@@ -18,7 +18,7 @@ LL |         writer.my_write(valref)
    |                         ^^^^^^ the trait `MyDisplay` is not implemented for `T`
    |
    = help: the trait `MyDisplay` is implemented for `&'a mut T`
-   = note: required for the cast from `T` to the object type `dyn MyDisplay`
+   = note: required for the cast from `&mut T` to `&dyn MyDisplay`
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/async-await/async-block-control-flow-static-semantics.stderr b/tests/ui/async-await/async-block-control-flow-static-semantics.stderr
index a6dbb071614..bbd5a822d8d 100644
--- a/tests/ui/async-await/async-block-control-flow-static-semantics.stderr
+++ b/tests/ui/async-await/async-block-control-flow-static-semantics.stderr
@@ -35,7 +35,7 @@ error[E0271]: expected `[async block@$DIR/async-block-control-flow-static-semant
 LL |     let _: &dyn Future<Output = ()> = &block;
    |                                       ^^^^^^ expected `()`, found `u8`
    |
-   = note: required for the cast from `[async block@$DIR/async-block-control-flow-static-semantics.rs:23:17: 25:6]` to the object type `dyn Future<Output = ()>`
+   = note: required for the cast from `&[async block@$DIR/async-block-control-flow-static-semantics.rs:23:17: 25:6]` to `&dyn Future<Output = ()>`
 
 error[E0308]: mismatched types
   --> $DIR/async-block-control-flow-static-semantics.rs:12:43
@@ -51,7 +51,7 @@ error[E0271]: expected `[async block@$DIR/async-block-control-flow-static-semant
 LL |     let _: &dyn Future<Output = ()> = &block;
    |                                       ^^^^^^ expected `()`, found `u8`
    |
-   = note: required for the cast from `[async block@$DIR/async-block-control-flow-static-semantics.rs:14:17: 16:6]` to the object type `dyn Future<Output = ()>`
+   = note: required for the cast from `&[async block@$DIR/async-block-control-flow-static-semantics.rs:14:17: 16:6]` to `&dyn Future<Output = ()>`
 
 error[E0308]: mismatched types
   --> $DIR/async-block-control-flow-static-semantics.rs:49:44
diff --git a/tests/ui/async-await/issue-86507.drop_tracking.stderr b/tests/ui/async-await/issue-86507.drop_tracking.stderr
index 5c8b7ef1b71..adb7b9bf4bf 100644
--- a/tests/ui/async-await/issue-86507.drop_tracking.stderr
+++ b/tests/ui/async-await/issue-86507.drop_tracking.stderr
@@ -13,7 +13,7 @@ note: captured value is not `Send` because `&` references cannot be sent unless
    |
 LL |                     let x = x;
    |                             ^ has type `&T` which is not `Send`, because `T` is not `Sync`
-   = note: required for the cast from `[async block@$DIR/issue-86507.rs:21:17: 23:18]` to the object type `dyn Future<Output = ()> + Send`
+   = note: required for the cast from `Pin<Box<[async block@$DIR/issue-86507.rs:21:17: 23:18]>>` to `Pin<Box<(dyn Future<Output = ()> + Send + 'async_trait)>>`
 help: consider further restricting this bound
    |
 LL |     fn bar<'me, 'async_trait, T: Send + std::marker::Sync>(x: &'me T)
diff --git a/tests/ui/async-await/issue-86507.drop_tracking_mir.stderr b/tests/ui/async-await/issue-86507.drop_tracking_mir.stderr
index 5c8b7ef1b71..adb7b9bf4bf 100644
--- a/tests/ui/async-await/issue-86507.drop_tracking_mir.stderr
+++ b/tests/ui/async-await/issue-86507.drop_tracking_mir.stderr
@@ -13,7 +13,7 @@ note: captured value is not `Send` because `&` references cannot be sent unless
    |
 LL |                     let x = x;
    |                             ^ has type `&T` which is not `Send`, because `T` is not `Sync`
-   = note: required for the cast from `[async block@$DIR/issue-86507.rs:21:17: 23:18]` to the object type `dyn Future<Output = ()> + Send`
+   = note: required for the cast from `Pin<Box<[async block@$DIR/issue-86507.rs:21:17: 23:18]>>` to `Pin<Box<(dyn Future<Output = ()> + Send + 'async_trait)>>`
 help: consider further restricting this bound
    |
 LL |     fn bar<'me, 'async_trait, T: Send + std::marker::Sync>(x: &'me T)
diff --git a/tests/ui/async-await/issue-86507.no_drop_tracking.stderr b/tests/ui/async-await/issue-86507.no_drop_tracking.stderr
index 5c8b7ef1b71..adb7b9bf4bf 100644
--- a/tests/ui/async-await/issue-86507.no_drop_tracking.stderr
+++ b/tests/ui/async-await/issue-86507.no_drop_tracking.stderr
@@ -13,7 +13,7 @@ note: captured value is not `Send` because `&` references cannot be sent unless
    |
 LL |                     let x = x;
    |                             ^ has type `&T` which is not `Send`, because `T` is not `Sync`
-   = note: required for the cast from `[async block@$DIR/issue-86507.rs:21:17: 23:18]` to the object type `dyn Future<Output = ()> + Send`
+   = note: required for the cast from `Pin<Box<[async block@$DIR/issue-86507.rs:21:17: 23:18]>>` to `Pin<Box<(dyn Future<Output = ()> + Send + 'async_trait)>>`
 help: consider further restricting this bound
    |
 LL |     fn bar<'me, 'async_trait, T: Send + std::marker::Sync>(x: &'me T)
diff --git a/tests/ui/async-await/multiple-lifetimes/partial-relation.rs b/tests/ui/async-await/multiple-lifetimes/partial-relation.rs
index 02b105999f5..7375cb6d3a0 100644
--- a/tests/ui/async-await/multiple-lifetimes/partial-relation.rs
+++ b/tests/ui/async-await/multiple-lifetimes/partial-relation.rs
@@ -4,7 +4,7 @@
 async fn lotsa_lifetimes<'a, 'b, 'c>(a: &'a u32, b: &'b u32, c: &'c u32) -> (&'a u32, &'b u32)
     where 'b: 'a
 {
-    drop((a, c));
+    let _ = (a, c);
     (b, b)
 }
 
diff --git a/tests/ui/attr-bad-crate-attr.rc b/tests/ui/attr-bad-crate-attr.rs
index 89ba26dfd6f..89ba26dfd6f 100644
--- a/tests/ui/attr-bad-crate-attr.rc
+++ b/tests/ui/attr-bad-crate-attr.rs
diff --git a/tests/ui/attr-bad-crate-attr.stderr b/tests/ui/attr-bad-crate-attr.stderr
new file mode 100644
index 00000000000..ff420eeea4a
--- /dev/null
+++ b/tests/ui/attr-bad-crate-attr.stderr
@@ -0,0 +1,8 @@
+error: expected item after attributes
+  --> $DIR/attr-bad-crate-attr.rs:4:1
+   |
+LL | #[attr = "val"] // Unterminated
+   | ^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/tests/ui/borrowck/borrowck-closures-slice-patterns-ok.rs b/tests/ui/borrowck/borrowck-closures-slice-patterns-ok.rs
index 0229ca37a69..60128c9419d 100644
--- a/tests/ui/borrowck/borrowck-closures-slice-patterns-ok.rs
+++ b/tests/ui/borrowck/borrowck-closures-slice-patterns-ok.rs
@@ -1,6 +1,7 @@
 // Check that closure captures for slice patterns are inferred correctly
 
 #![allow(unused_variables)]
+#![allow(dropping_references)]
 
 // run-pass
 
diff --git a/tests/ui/borrowck/borrowck-field-sensitivity-rpass.rs b/tests/ui/borrowck/borrowck-field-sensitivity-rpass.rs
index dd6708582c1..78e965cc4bc 100644
--- a/tests/ui/borrowck/borrowck-field-sensitivity-rpass.rs
+++ b/tests/ui/borrowck/borrowck-field-sensitivity-rpass.rs
@@ -1,6 +1,7 @@
 // run-pass
 #![allow(unused_mut)]
 #![allow(unused_variables)]
+#![allow(dropping_copy_types)]
 // pretty-expanded FIXME #23616
 
 struct A { a: isize, b: Box<isize> }
diff --git a/tests/ui/borrowck/borrowck-use-mut-borrow-rpass.rs b/tests/ui/borrowck/borrowck-use-mut-borrow-rpass.rs
index 1cf763f66fd..9acb1ec5e43 100644
--- a/tests/ui/borrowck/borrowck-use-mut-borrow-rpass.rs
+++ b/tests/ui/borrowck/borrowck-use-mut-borrow-rpass.rs
@@ -1,6 +1,8 @@
 // run-pass
 // pretty-expanded FIXME #23616
 
+#![allow(dropping_copy_types)]
+
 struct A { a: isize, b: Box<isize> }
 
 fn field_copy_after_field_borrow() {
diff --git a/tests/ui/borrowck/erase-error-in-mir-drop-tracking.rs b/tests/ui/borrowck/erase-error-in-mir-drop-tracking.rs
new file mode 100644
index 00000000000..addbe5d658a
--- /dev/null
+++ b/tests/ui/borrowck/erase-error-in-mir-drop-tracking.rs
@@ -0,0 +1,23 @@
+// compile-flags: -Zdrop-tracking-mir
+// edition:2021
+
+use std::future::Future;
+
+trait Client {
+    type Connecting<'a>: Future + Send
+    where
+        Self: 'a;
+
+    fn connect(&'_ self) -> Self::Connecting<'a>;
+    //~^ ERROR use of undeclared lifetime name `'a`
+}
+
+fn call_connect<C>(c: &'_ C) -> impl '_ + Future + Send
+where
+    C: Client + Send + Sync,
+{
+    async move { c.connect().await }
+    //~^ ERROR `C` does not live long enough
+}
+
+fn main() {}
diff --git a/tests/ui/borrowck/erase-error-in-mir-drop-tracking.stderr b/tests/ui/borrowck/erase-error-in-mir-drop-tracking.stderr
new file mode 100644
index 00000000000..53abe3dc952
--- /dev/null
+++ b/tests/ui/borrowck/erase-error-in-mir-drop-tracking.stderr
@@ -0,0 +1,24 @@
+error[E0261]: use of undeclared lifetime name `'a`
+  --> $DIR/erase-error-in-mir-drop-tracking.rs:11:46
+   |
+LL |     fn connect(&'_ self) -> Self::Connecting<'a>;
+   |                                              ^^ undeclared lifetime
+   |
+help: consider introducing lifetime `'a` here
+   |
+LL |     fn connect<'a>(&'_ self) -> Self::Connecting<'a>;
+   |               ++++
+help: consider introducing lifetime `'a` here
+   |
+LL | trait Client<'a> {
+   |             ++++
+
+error: `C` does not live long enough
+  --> $DIR/erase-error-in-mir-drop-tracking.rs:19:5
+   |
+LL |     async move { c.connect().await }
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0261`.
diff --git a/tests/ui/cfg/cfg-stmt-recovery.rs b/tests/ui/cfg/cfg-stmt-recovery.rs
new file mode 100644
index 00000000000..2e0839d2a15
--- /dev/null
+++ b/tests/ui/cfg/cfg-stmt-recovery.rs
@@ -0,0 +1,13 @@
+// Verify that we do not ICE when failing to parse a statement in `cfg_eval`.
+
+#![feature(cfg_eval)]
+#![feature(stmt_expr_attributes)]
+
+#[cfg_eval]
+fn main() {
+    #[cfg_eval]
+    let _ = #[cfg(FALSE)] 0;
+    //~^ ERROR removing an expression is not supported in this position
+    //~| ERROR expected expression, found `;`
+    //~| ERROR removing an expression is not supported in this position
+}
diff --git a/tests/ui/cfg/cfg-stmt-recovery.stderr b/tests/ui/cfg/cfg-stmt-recovery.stderr
new file mode 100644
index 00000000000..cb15e21fac6
--- /dev/null
+++ b/tests/ui/cfg/cfg-stmt-recovery.stderr
@@ -0,0 +1,20 @@
+error: removing an expression is not supported in this position
+  --> $DIR/cfg-stmt-recovery.rs:9:13
+   |
+LL |     let _ = #[cfg(FALSE)] 0;
+   |             ^^^^^^^^^^^^^
+
+error: expected expression, found `;`
+  --> $DIR/cfg-stmt-recovery.rs:9:28
+   |
+LL |     let _ = #[cfg(FALSE)] 0;
+   |                            ^ expected expression
+
+error: removing an expression is not supported in this position
+  --> $DIR/cfg-stmt-recovery.rs:9:13
+   |
+LL |     let _ = #[cfg(FALSE)] 0;
+   |             ^^^^^^^^^^^^^
+
+error: aborting due to 3 previous errors
+
diff --git a/tests/ui/closure_context/issue-26046-fn-mut.stderr b/tests/ui/closure_context/issue-26046-fn-mut.stderr
index f744b71c284..e468f6be791 100644
--- a/tests/ui/closure_context/issue-26046-fn-mut.stderr
+++ b/tests/ui/closure_context/issue-26046-fn-mut.stderr
@@ -9,7 +9,7 @@ LL |         num += 1;
 LL |     Box::new(closure)
    |     ----------------- the requirement to implement `Fn` derives from here
    |
-   = note: required for the cast from `[closure@$DIR/issue-26046-fn-mut.rs:4:19: 4:21]` to the object type `dyn Fn()`
+   = note: required for the cast from `Box<[closure@$DIR/issue-26046-fn-mut.rs:4:19: 4:21]>` to `Box<(dyn Fn() + 'static)>`
 
 error: aborting due to previous error
 
diff --git a/tests/ui/closure_context/issue-26046-fn-once.stderr b/tests/ui/closure_context/issue-26046-fn-once.stderr
index 34f94f9dca6..41f60327ce0 100644
--- a/tests/ui/closure_context/issue-26046-fn-once.stderr
+++ b/tests/ui/closure_context/issue-26046-fn-once.stderr
@@ -9,7 +9,7 @@ LL |         vec
 LL |     Box::new(closure)
    |     ----------------- the requirement to implement `Fn` derives from here
    |
-   = note: required for the cast from `[closure@$DIR/issue-26046-fn-once.rs:4:19: 4:26]` to the object type `dyn Fn() -> Vec<u8>`
+   = note: required for the cast from `Box<[closure@$DIR/issue-26046-fn-once.rs:4:19: 4:26]>` to `Box<(dyn Fn() -> Vec<u8> + 'static)>`
 
 error: aborting due to previous error
 
diff --git a/tests/ui/closures/2229_closure_analysis/migrations/issue-78720.rs b/tests/ui/closures/2229_closure_analysis/migrations/issue-78720.rs
index ff5d284614b..98f8d5d4733 100644
--- a/tests/ui/closures/2229_closure_analysis/migrations/issue-78720.rs
+++ b/tests/ui/closures/2229_closure_analysis/migrations/issue-78720.rs
@@ -1,6 +1,7 @@
 // run-pass
 
 #![warn(rust_2021_incompatible_closure_captures)]
+#![allow(dropping_references, dropping_copy_types)]
 
 fn main() {
     if let a = "" {
diff --git a/tests/ui/closures/2229_closure_analysis/migrations/issue-78720.stderr b/tests/ui/closures/2229_closure_analysis/migrations/issue-78720.stderr
index 36a80e694e8..2609e2951ec 100644
--- a/tests/ui/closures/2229_closure_analysis/migrations/issue-78720.stderr
+++ b/tests/ui/closures/2229_closure_analysis/migrations/issue-78720.stderr
@@ -1,5 +1,5 @@
 warning: irrefutable `if let` pattern
-  --> $DIR/issue-78720.rs:6:8
+  --> $DIR/issue-78720.rs:7:8
    |
 LL |     if let a = "" {
    |        ^^^^^^^^^^
diff --git a/tests/ui/closures/2229_closure_analysis/optimization/edge_case_run_pass.rs b/tests/ui/closures/2229_closure_analysis/optimization/edge_case_run_pass.rs
index 033fd6f1775..5496d0e5fc7 100644
--- a/tests/ui/closures/2229_closure_analysis/optimization/edge_case_run_pass.rs
+++ b/tests/ui/closures/2229_closure_analysis/optimization/edge_case_run_pass.rs
@@ -3,6 +3,7 @@
 
 #![allow(unused)]
 #![allow(dead_code)]
+#![allow(dropping_references)]
 
 struct Int(i32);
 struct B<'a>(&'a i32);
diff --git a/tests/ui/closures/2229_closure_analysis/run_pass/drop_then_use_fake_reads.rs b/tests/ui/closures/2229_closure_analysis/run_pass/drop_then_use_fake_reads.rs
index 477fdd613f5..b5e97ec1c1b 100644
--- a/tests/ui/closures/2229_closure_analysis/run_pass/drop_then_use_fake_reads.rs
+++ b/tests/ui/closures/2229_closure_analysis/run_pass/drop_then_use_fake_reads.rs
@@ -1,6 +1,8 @@
 // edition:2021
 // check-pass
+
 #![feature(rustc_attrs)]
+#![allow(dropping_references)]
 
 fn main() {
     let mut x = 1;
diff --git a/tests/ui/coercion/coerce-issue-49593-box-never-windows.nofallback.stderr b/tests/ui/coercion/coerce-issue-49593-box-never-windows.nofallback.stderr
index 980da536034..b976f70acf7 100644
--- a/tests/ui/coercion/coerce-issue-49593-box-never-windows.nofallback.stderr
+++ b/tests/ui/coercion/coerce-issue-49593-box-never-windows.nofallback.stderr
@@ -4,7 +4,7 @@ error[E0277]: the trait bound `(): std::error::Error` is not satisfied
 LL |     /* *mut $0 is coerced to Box<dyn Error> here */ Box::<_ /* ! */>::new(x)
    |                                                     ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::error::Error` is not implemented for `()`
    |
-   = note: required for the cast from `()` to the object type `dyn std::error::Error`
+   = note: required for the cast from `Box<()>` to `Box<(dyn std::error::Error + 'static)>`
 
 error[E0277]: the trait bound `(): std::error::Error` is not satisfied
   --> $DIR/coerce-issue-49593-box-never-windows.rs:23:49
@@ -12,7 +12,7 @@ error[E0277]: the trait bound `(): std::error::Error` is not satisfied
 LL |     /* *mut $0 is coerced to *mut Error here */ raw_ptr_box::<_ /* ! */>(x)
    |                                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::error::Error` is not implemented for `()`
    |
-   = note: required for the cast from `()` to the object type `(dyn std::error::Error + 'static)`
+   = note: required for the cast from `*mut ()` to `*mut (dyn std::error::Error + 'static)`
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/coercion/coerce-issue-49593-box-never.nofallback.stderr b/tests/ui/coercion/coerce-issue-49593-box-never.nofallback.stderr
index 322681b97bc..0d98fa93e5a 100644
--- a/tests/ui/coercion/coerce-issue-49593-box-never.nofallback.stderr
+++ b/tests/ui/coercion/coerce-issue-49593-box-never.nofallback.stderr
@@ -4,7 +4,7 @@ error[E0277]: the trait bound `(): std::error::Error` is not satisfied
 LL |     /* *mut $0 is coerced to Box<dyn Error> here */ Box::<_ /* ! */>::new(x)
    |                                                     ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::error::Error` is not implemented for `()`
    |
-   = note: required for the cast from `()` to the object type `dyn std::error::Error`
+   = note: required for the cast from `Box<()>` to `Box<(dyn std::error::Error + 'static)>`
 
 error[E0277]: the trait bound `(): std::error::Error` is not satisfied
   --> $DIR/coerce-issue-49593-box-never.rs:23:49
@@ -12,7 +12,7 @@ error[E0277]: the trait bound `(): std::error::Error` is not satisfied
 LL |     /* *mut $0 is coerced to *mut Error here */ raw_ptr_box::<_ /* ! */>(x)
    |                                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::error::Error` is not implemented for `()`
    |
-   = note: required for the cast from `()` to the object type `(dyn std::error::Error + 'static)`
+   = note: required for the cast from `*mut ()` to `*mut (dyn std::error::Error + 'static)`
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/const-generics/adt_const_params/const_param_ty_good.rs b/tests/ui/const-generics/adt_const_params/const_param_ty_good.rs
index a1b711a3024..87ae83dd966 100644
--- a/tests/ui/const-generics/adt_const_params/const_param_ty_good.rs
+++ b/tests/ui/const-generics/adt_const_params/const_param_ty_good.rs
@@ -11,6 +11,13 @@ struct S<T> {
 
 impl<T: ConstParamTy> ConstParamTy for S<T> {}
 
+#[derive(PartialEq, Eq, ConstParamTy)]
+struct D<T> {
+    field: u8,
+    gen: T,
+}
+
+
 fn check<T: ConstParamTy + ?Sized>() {}
 
 fn main() {
@@ -39,5 +46,8 @@ fn main() {
     check::<S<u8>>();
     check::<S<[&[bool]; 8]>>();
 
+    check::<D<u8>>();
+    check::<D<[&[bool]; 8]>>();
+
     // FIXME: test tuples
 }
diff --git a/tests/ui/const-generics/adt_const_params/const_param_ty_impl_bad_field.rs b/tests/ui/const-generics/adt_const_params/const_param_ty_impl_bad_field.rs
index 07fd243737e..74283a37afc 100644
--- a/tests/ui/const-generics/adt_const_params/const_param_ty_impl_bad_field.rs
+++ b/tests/ui/const-generics/adt_const_params/const_param_ty_impl_bad_field.rs
@@ -10,4 +10,8 @@ struct CantParam(NotParam);
 impl std::marker::ConstParamTy for CantParam {}
 //~^ error: the trait `ConstParamTy` cannot be implemented for this type
 
+#[derive(std::marker::ConstParamTy, Eq, PartialEq)]
+//~^ error: the trait `ConstParamTy` cannot be implemented for this type
+struct CantParamDerive(NotParam);
+
 fn main() {}
diff --git a/tests/ui/const-generics/adt_const_params/const_param_ty_impl_bad_field.stderr b/tests/ui/const-generics/adt_const_params/const_param_ty_impl_bad_field.stderr
index c8e065848b1..52b65d6061a 100644
--- a/tests/ui/const-generics/adt_const_params/const_param_ty_impl_bad_field.stderr
+++ b/tests/ui/const-generics/adt_const_params/const_param_ty_impl_bad_field.stderr
@@ -7,6 +7,17 @@ LL |
 LL | impl std::marker::ConstParamTy for CantParam {}
    |                                    ^^^^^^^^^
 
-error: aborting due to previous error
+error[E0204]: the trait `ConstParamTy` cannot be implemented for this type
+  --> $DIR/const_param_ty_impl_bad_field.rs:13:10
+   |
+LL | #[derive(std::marker::ConstParamTy, Eq, PartialEq)]
+   |          ^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |
+LL | struct CantParamDerive(NotParam);
+   |                        -------- this field does not implement `ConstParamTy`
+   |
+   = note: this error originates in the derive macro `std::marker::ConstParamTy` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0204`.
diff --git a/tests/ui/const-generics/adt_const_params/const_param_ty_impl_no_structural_eq.rs b/tests/ui/const-generics/adt_const_params/const_param_ty_impl_no_structural_eq.rs
index 17ef396164e..37986de481f 100644
--- a/tests/ui/const-generics/adt_const_params/const_param_ty_impl_no_structural_eq.rs
+++ b/tests/ui/const-generics/adt_const_params/const_param_ty_impl_no_structural_eq.rs
@@ -10,6 +10,10 @@ struct CantParam(ImplementsConstParamTy);
 impl std::marker::ConstParamTy for CantParam {}
 //~^ error: the type `CantParam` does not `#[derive(Eq)]`
 
+#[derive(std::marker::ConstParamTy)]
+//~^ error: the type `CantParamDerive` does not `#[derive(Eq)]`
+struct CantParamDerive(ImplementsConstParamTy);
+
 fn check<T: std::marker::ConstParamTy>() {}
 
 fn main() {
diff --git a/tests/ui/const-generics/adt_const_params/const_param_ty_impl_no_structural_eq.stderr b/tests/ui/const-generics/adt_const_params/const_param_ty_impl_no_structural_eq.stderr
index ca5abf5e254..52701d55914 100644
--- a/tests/ui/const-generics/adt_const_params/const_param_ty_impl_no_structural_eq.stderr
+++ b/tests/ui/const-generics/adt_const_params/const_param_ty_impl_no_structural_eq.stderr
@@ -7,6 +7,16 @@ LL | impl std::marker::ConstParamTy for CantParam {}
 note: required by a bound in `ConstParamTy`
   --> $SRC_DIR/core/src/marker.rs:LL:COL
 
-error: aborting due to previous error
+error[E0277]: the type `CantParamDerive` does not `#[derive(Eq)]`
+  --> $DIR/const_param_ty_impl_no_structural_eq.rs:13:10
+   |
+LL | #[derive(std::marker::ConstParamTy)]
+   |          ^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `StructuralEq` is not implemented for `CantParamDerive`
+   |
+note: required by a bound in `ConstParamTy`
+  --> $SRC_DIR/core/src/marker.rs:LL:COL
+   = note: this error originates in the derive macro `std::marker::ConstParamTy` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/const-generics/adt_const_params/const_param_ty_impl_union.rs b/tests/ui/const-generics/adt_const_params/const_param_ty_impl_union.rs
new file mode 100644
index 00000000000..d70377a20c1
--- /dev/null
+++ b/tests/ui/const-generics/adt_const_params/const_param_ty_impl_union.rs
@@ -0,0 +1,33 @@
+#![allow(incomplete_features)]
+#![feature(adt_const_params, structural_match)]
+
+union Union {
+    a: u8,
+}
+
+impl PartialEq for Union {
+    fn eq(&self, other: &Union) -> bool {
+        true
+    }
+}
+impl Eq for Union {}
+impl std::marker::StructuralEq for Union {}
+
+impl std::marker::ConstParamTy for Union {}
+
+#[derive(std::marker::ConstParamTy)]
+//~^ ERROR this trait cannot be derived for unions
+union UnionDerive {
+    a: u8,
+}
+
+impl PartialEq for UnionDerive {
+    fn eq(&self, other: &UnionDerive) -> bool {
+        true
+    }
+}
+impl Eq for UnionDerive {}
+impl std::marker::StructuralEq for UnionDerive {}
+
+
+fn main() {}
diff --git a/tests/ui/const-generics/adt_const_params/const_param_ty_impl_union.stderr b/tests/ui/const-generics/adt_const_params/const_param_ty_impl_union.stderr
new file mode 100644
index 00000000000..29370304605
--- /dev/null
+++ b/tests/ui/const-generics/adt_const_params/const_param_ty_impl_union.stderr
@@ -0,0 +1,8 @@
+error: this trait cannot be derived for unions
+  --> $DIR/const_param_ty_impl_union.rs:18:10
+   |
+LL | #[derive(std::marker::ConstParamTy)]
+   |          ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/tests/ui/const-generics/defaults/trait_objects_fail.stderr b/tests/ui/const-generics/defaults/trait_objects_fail.stderr
index 0e8334d0338..481d77728b9 100644
--- a/tests/ui/const-generics/defaults/trait_objects_fail.stderr
+++ b/tests/ui/const-generics/defaults/trait_objects_fail.stderr
@@ -5,7 +5,7 @@ LL |     foo(&10_u32);
    |         ^^^^^^^ the trait `Trait` is not implemented for `u32`
    |
    = help: the trait `Trait<2>` is implemented for `u32`
-   = note: required for the cast from `u32` to the object type `dyn Trait`
+   = note: required for the cast from `&u32` to `&dyn Trait`
 
 error[E0277]: the trait bound `bool: Traitor<_>` is not satisfied
   --> $DIR/trait_objects_fail.rs:28:9
@@ -14,7 +14,7 @@ LL |     bar(&true);
    |         ^^^^^ the trait `Traitor<_>` is not implemented for `bool`
    |
    = help: the trait `Traitor<2, 3>` is implemented for `bool`
-   = note: required for the cast from `bool` to the object type `dyn Traitor<_>`
+   = note: required for the cast from `&bool` to `&dyn Traitor<_>`
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/consts/const-eval/format.stderr b/tests/ui/consts/const-eval/format.stderr
index 70a1abb0a95..434b0744304 100644
--- a/tests/ui/consts/const-eval/format.stderr
+++ b/tests/ui/consts/const-eval/format.stderr
@@ -43,62 +43,6 @@ LL |     println!("{:?}", 0);
    = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
    = note: this error originates in the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-note: erroneous constant used
-  --> $DIR/format.rs:2:12
-   |
-LL |     panic!("{:?}", 0);
-   |            ^^^^^^
-
-note: erroneous constant used
-  --> $DIR/format.rs:2:12
-   |
-LL |     panic!("{:?}", 0);
-   |            ^^^^^^
-
-note: erroneous constant used
-  --> $DIR/format.rs:2:20
-   |
-LL |     panic!("{:?}", 0);
-   |                    ^
-   |
-   = note: this note originates in the macro `$crate::const_format_args` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info)
-
-note: erroneous constant used
-  --> $DIR/format.rs:2:20
-   |
-LL |     panic!("{:?}", 0);
-   |                    ^
-   |
-   = note: this note originates in the macro `$crate::const_format_args` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info)
-
-note: erroneous constant used
-  --> $DIR/format.rs:8:14
-   |
-LL |     println!("{:?}", 0);
-   |              ^^^^^^
-
-note: erroneous constant used
-  --> $DIR/format.rs:8:14
-   |
-LL |     println!("{:?}", 0);
-   |              ^^^^^^
-
-note: erroneous constant used
-  --> $DIR/format.rs:8:22
-   |
-LL |     println!("{:?}", 0);
-   |                      ^
-   |
-   = note: this note 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)
-
-note: erroneous constant used
-  --> $DIR/format.rs:8:22
-   |
-LL |     println!("{:?}", 0);
-   |                      ^
-   |
-   = note: this note 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)
-
 error: aborting due to 5 previous errors
 
 For more information about this error, try `rustc --explain E0015`.
diff --git a/tests/ui/consts/const-integer-bool-ops.rs b/tests/ui/consts/const-integer-bool-ops.rs
index 4110ae3e456..35915a7a606 100644
--- a/tests/ui/consts/const-integer-bool-ops.rs
+++ b/tests/ui/consts/const-integer-bool-ops.rs
@@ -6,7 +6,6 @@ const X: usize = 42 && 39;
 //~| ERROR mismatched types
 //~| expected `usize`, found `bool`
 const ARR: [i32; X] = [99; 34];
-//~^ constant
 
 const X1: usize = 42 || 39;
 //~^ ERROR mismatched types
@@ -16,7 +15,6 @@ const X1: usize = 42 || 39;
 //~| ERROR mismatched types
 //~| expected `usize`, found `bool`
 const ARR1: [i32; X1] = [99; 47];
-//~^ constant
 
 const X2: usize = -42 || -39;
 //~^ ERROR mismatched types
@@ -26,7 +24,6 @@ const X2: usize = -42 || -39;
 //~| ERROR mismatched types
 //~| expected `usize`, found `bool`
 const ARR2: [i32; X2] = [99; 18446744073709551607];
-//~^ constant
 
 const X3: usize = -42 && -39;
 //~^ ERROR mismatched types
@@ -36,43 +33,36 @@ const X3: usize = -42 && -39;
 //~| ERROR mismatched types
 //~| expected `usize`, found `bool`
 const ARR3: [i32; X3] = [99; 6];
-//~^ constant
 
 const Y: usize = 42.0 == 42.0;
 //~^ ERROR mismatched types
 //~| expected `usize`, found `bool`
 const ARRR: [i32; Y] = [99; 1];
-//~^ constant
 
 const Y1: usize = 42.0 >= 42.0;
 //~^ ERROR mismatched types
 //~| expected `usize`, found `bool`
 const ARRR1: [i32; Y1] = [99; 1];
-//~^ constant
 
 const Y2: usize = 42.0 <= 42.0;
 //~^ ERROR mismatched types
 //~| expected `usize`, found `bool`
 const ARRR2: [i32; Y2] = [99; 1];
-//~^ constant
 
 const Y3: usize = 42.0 > 42.0;
 //~^ ERROR mismatched types
 //~| expected `usize`, found `bool`
 const ARRR3: [i32; Y3] = [99; 0];
-//~^ constant
 
 const Y4: usize = 42.0 < 42.0;
 //~^ ERROR mismatched types
 //~| expected `usize`, found `bool`
 const ARRR4: [i32; Y4] = [99; 0];
-//~^ constant
 
 const Y5: usize = 42.0 != 42.0;
 //~^ ERROR mismatched types
 //~| expected `usize`, found `bool`
 const ARRR5: [i32; Y5] = [99; 0];
-//~^ constant
 
 fn main() {
     let _ = ARR;
diff --git a/tests/ui/consts/const-integer-bool-ops.stderr b/tests/ui/consts/const-integer-bool-ops.stderr
index b5c3b22fdbe..4e503e5a5c0 100644
--- a/tests/ui/consts/const-integer-bool-ops.stderr
+++ b/tests/ui/consts/const-integer-bool-ops.stderr
@@ -16,156 +16,96 @@ error[E0308]: mismatched types
 LL | const X: usize = 42 && 39;
    |                  ^^^^^^^^ expected `usize`, found `bool`
 
-note: erroneous constant used
-  --> $DIR/const-integer-bool-ops.rs:8:18
-   |
-LL | const ARR: [i32; X] = [99; 34];
-   |                  ^
-
 error[E0308]: mismatched types
-  --> $DIR/const-integer-bool-ops.rs:11:19
+  --> $DIR/const-integer-bool-ops.rs:10:19
    |
 LL | const X1: usize = 42 || 39;
    |                   ^^ expected `bool`, found integer
 
 error[E0308]: mismatched types
-  --> $DIR/const-integer-bool-ops.rs:11:25
+  --> $DIR/const-integer-bool-ops.rs:10:25
    |
 LL | const X1: usize = 42 || 39;
    |                         ^^ expected `bool`, found integer
 
 error[E0308]: mismatched types
-  --> $DIR/const-integer-bool-ops.rs:11:19
+  --> $DIR/const-integer-bool-ops.rs:10:19
    |
 LL | const X1: usize = 42 || 39;
    |                   ^^^^^^^^ expected `usize`, found `bool`
 
-note: erroneous constant used
-  --> $DIR/const-integer-bool-ops.rs:18:19
-   |
-LL | const ARR1: [i32; X1] = [99; 47];
-   |                   ^^
-
 error[E0308]: mismatched types
-  --> $DIR/const-integer-bool-ops.rs:21:19
+  --> $DIR/const-integer-bool-ops.rs:19:19
    |
 LL | const X2: usize = -42 || -39;
    |                   ^^^ expected `bool`, found integer
 
 error[E0308]: mismatched types
-  --> $DIR/const-integer-bool-ops.rs:21:26
+  --> $DIR/const-integer-bool-ops.rs:19:26
    |
 LL | const X2: usize = -42 || -39;
    |                          ^^^ expected `bool`, found integer
 
 error[E0308]: mismatched types
-  --> $DIR/const-integer-bool-ops.rs:21:19
+  --> $DIR/const-integer-bool-ops.rs:19:19
    |
 LL | const X2: usize = -42 || -39;
    |                   ^^^^^^^^^^ expected `usize`, found `bool`
 
-note: erroneous constant used
-  --> $DIR/const-integer-bool-ops.rs:28:19
-   |
-LL | const ARR2: [i32; X2] = [99; 18446744073709551607];
-   |                   ^^
-
 error[E0308]: mismatched types
-  --> $DIR/const-integer-bool-ops.rs:31:19
+  --> $DIR/const-integer-bool-ops.rs:28:19
    |
 LL | const X3: usize = -42 && -39;
    |                   ^^^ expected `bool`, found integer
 
 error[E0308]: mismatched types
-  --> $DIR/const-integer-bool-ops.rs:31:26
+  --> $DIR/const-integer-bool-ops.rs:28:26
    |
 LL | const X3: usize = -42 && -39;
    |                          ^^^ expected `bool`, found integer
 
 error[E0308]: mismatched types
-  --> $DIR/const-integer-bool-ops.rs:31:19
+  --> $DIR/const-integer-bool-ops.rs:28:19
    |
 LL | const X3: usize = -42 && -39;
    |                   ^^^^^^^^^^ expected `usize`, found `bool`
 
-note: erroneous constant used
-  --> $DIR/const-integer-bool-ops.rs:38:19
-   |
-LL | const ARR3: [i32; X3] = [99; 6];
-   |                   ^^
-
 error[E0308]: mismatched types
-  --> $DIR/const-integer-bool-ops.rs:41:18
+  --> $DIR/const-integer-bool-ops.rs:37:18
    |
 LL | const Y: usize = 42.0 == 42.0;
    |                  ^^^^^^^^^^^^ expected `usize`, found `bool`
 
-note: erroneous constant used
-  --> $DIR/const-integer-bool-ops.rs:44:19
-   |
-LL | const ARRR: [i32; Y] = [99; 1];
-   |                   ^
-
 error[E0308]: mismatched types
-  --> $DIR/const-integer-bool-ops.rs:47:19
+  --> $DIR/const-integer-bool-ops.rs:42:19
    |
 LL | const Y1: usize = 42.0 >= 42.0;
    |                   ^^^^^^^^^^^^ expected `usize`, found `bool`
 
-note: erroneous constant used
-  --> $DIR/const-integer-bool-ops.rs:50:20
-   |
-LL | const ARRR1: [i32; Y1] = [99; 1];
-   |                    ^^
-
 error[E0308]: mismatched types
-  --> $DIR/const-integer-bool-ops.rs:53:19
+  --> $DIR/const-integer-bool-ops.rs:47:19
    |
 LL | const Y2: usize = 42.0 <= 42.0;
    |                   ^^^^^^^^^^^^ expected `usize`, found `bool`
 
-note: erroneous constant used
-  --> $DIR/const-integer-bool-ops.rs:56:20
-   |
-LL | const ARRR2: [i32; Y2] = [99; 1];
-   |                    ^^
-
 error[E0308]: mismatched types
-  --> $DIR/const-integer-bool-ops.rs:59:19
+  --> $DIR/const-integer-bool-ops.rs:52:19
    |
 LL | const Y3: usize = 42.0 > 42.0;
    |                   ^^^^^^^^^^^ expected `usize`, found `bool`
 
-note: erroneous constant used
-  --> $DIR/const-integer-bool-ops.rs:62:20
-   |
-LL | const ARRR3: [i32; Y3] = [99; 0];
-   |                    ^^
-
 error[E0308]: mismatched types
-  --> $DIR/const-integer-bool-ops.rs:65:19
+  --> $DIR/const-integer-bool-ops.rs:57:19
    |
 LL | const Y4: usize = 42.0 < 42.0;
    |                   ^^^^^^^^^^^ expected `usize`, found `bool`
 
-note: erroneous constant used
-  --> $DIR/const-integer-bool-ops.rs:68:20
-   |
-LL | const ARRR4: [i32; Y4] = [99; 0];
-   |                    ^^
-
 error[E0308]: mismatched types
-  --> $DIR/const-integer-bool-ops.rs:71:19
+  --> $DIR/const-integer-bool-ops.rs:62:19
    |
 LL | const Y5: usize = 42.0 != 42.0;
    |                   ^^^^^^^^^^^^ expected `usize`, found `bool`
 
-note: erroneous constant used
-  --> $DIR/const-integer-bool-ops.rs:74:20
-   |
-LL | const ARRR5: [i32; Y5] = [99; 0];
-   |                    ^^
-
 error: aborting due to 18 previous errors
 
 For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/consts/const-mut-refs/issue-76510.32bit.stderr b/tests/ui/consts/const-mut-refs/issue-76510.32bit.stderr
index 109d15a8e4d..61b00be345f 100644
--- a/tests/ui/consts/const-mut-refs/issue-76510.32bit.stderr
+++ b/tests/ui/consts/const-mut-refs/issue-76510.32bit.stderr
@@ -19,12 +19,6 @@ error[E0596]: cannot borrow data in a `&` reference as mutable
 LL | const S: &'static mut str = &mut " hello ";
    |                             ^^^^^^^^^^^^^^ cannot borrow as mutable
 
-note: erroneous constant used
-  --> $DIR/issue-76510.rs:11:70
-   |
-LL |         let s = transmute::<(*const u8, usize), &ManuallyDrop<str>>((S.as_ptr(), 3));
-   |                                                                      ^
-
 error: aborting due to 3 previous errors
 
 Some errors have detailed explanations: E0596, E0658, E0764.
diff --git a/tests/ui/consts/const-mut-refs/issue-76510.64bit.stderr b/tests/ui/consts/const-mut-refs/issue-76510.64bit.stderr
index 109d15a8e4d..61b00be345f 100644
--- a/tests/ui/consts/const-mut-refs/issue-76510.64bit.stderr
+++ b/tests/ui/consts/const-mut-refs/issue-76510.64bit.stderr
@@ -19,12 +19,6 @@ error[E0596]: cannot borrow data in a `&` reference as mutable
 LL | const S: &'static mut str = &mut " hello ";
    |                             ^^^^^^^^^^^^^^ cannot borrow as mutable
 
-note: erroneous constant used
-  --> $DIR/issue-76510.rs:11:70
-   |
-LL |         let s = transmute::<(*const u8, usize), &ManuallyDrop<str>>((S.as_ptr(), 3));
-   |                                                                      ^
-
 error: aborting due to 3 previous errors
 
 Some errors have detailed explanations: E0596, E0658, E0764.
diff --git a/tests/ui/consts/const-mut-refs/issue-76510.rs b/tests/ui/consts/const-mut-refs/issue-76510.rs
index b853e2737f1..143d2fb6b9a 100644
--- a/tests/ui/consts/const-mut-refs/issue-76510.rs
+++ b/tests/ui/consts/const-mut-refs/issue-76510.rs
@@ -9,7 +9,6 @@ const S: &'static mut str = &mut " hello ";
 
 const fn trigger() -> [(); unsafe {
         let s = transmute::<(*const u8, usize), &ManuallyDrop<str>>((S.as_ptr(), 3));
-        //~^ constant
         0
     }] {
     [(); 0]
diff --git a/tests/ui/consts/const-tup-index-span.rs b/tests/ui/consts/const-tup-index-span.rs
index 18f4f59d378..e77d392e694 100644
--- a/tests/ui/consts/const-tup-index-span.rs
+++ b/tests/ui/consts/const-tup-index-span.rs
@@ -4,7 +4,6 @@ const TUP: (usize,) = 5usize << 64;
 //~^ ERROR mismatched types
 //~| expected `(usize,)`, found `usize`
 const ARR: [i32; TUP.0] = [];
-//~^ constant
 
 fn main() {
 }
diff --git a/tests/ui/consts/const-tup-index-span.stderr b/tests/ui/consts/const-tup-index-span.stderr
index 65f0520f8a4..d5df0df9525 100644
--- a/tests/ui/consts/const-tup-index-span.stderr
+++ b/tests/ui/consts/const-tup-index-span.stderr
@@ -11,12 +11,6 @@ help: use a trailing comma to create a tuple with one element
 LL | const TUP: (usize,) = (5usize << 64,);
    |                       +            ++
 
-note: erroneous constant used
-  --> $DIR/const-tup-index-span.rs:6:18
-   |
-LL | const ARR: [i32; TUP.0] = [];
-   |                  ^^^
-
 error: aborting due to previous error
 
 For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/consts/const_forget.rs b/tests/ui/consts/const_forget.rs
index ec7dde8c9ec..f06149f2cb9 100644
--- a/tests/ui/consts/const_forget.rs
+++ b/tests/ui/consts/const_forget.rs
@@ -1,5 +1,7 @@
 // check-pass
 
+#![allow(forgetting_copy_types)]
+
 use std::mem::forget;
 
 const _: () = forget(0i32);
diff --git a/tests/ui/consts/issue-104155.rs b/tests/ui/consts/issue-104155.rs
index 1cc8f81b0d2..7b375dc0566 100644
--- a/tests/ui/consts/issue-104155.rs
+++ b/tests/ui/consts/issue-104155.rs
@@ -1,4 +1,7 @@
 // check-pass
+
+#![allow(forgetting_copy_types)]
+
 const _: () = core::mem::forget(Box::<u32>::default);
 const _: () = core::mem::forget(|| Box::<u32>::default());
 
diff --git a/tests/ui/consts/issue-54954.rs b/tests/ui/consts/issue-54954.rs
index 520bf508ff3..7bcfa057019 100644
--- a/tests/ui/consts/issue-54954.rs
+++ b/tests/ui/consts/issue-54954.rs
@@ -9,8 +9,6 @@ trait Tt {
 }
 
 fn f(z: [f32; ARR_LEN]) -> [f32; ARR_LEN] {
-  //~^ constant
-  //~| constant
     z
 }
 
diff --git a/tests/ui/consts/issue-54954.stderr b/tests/ui/consts/issue-54954.stderr
index 85055828737..b0701bab793 100644
--- a/tests/ui/consts/issue-54954.stderr
+++ b/tests/ui/consts/issue-54954.stderr
@@ -16,18 +16,6 @@ LL | |         core::mem::size_of::<T>()
 LL | |     }
    | |_____- `Tt::const_val` defined here
 
-note: erroneous constant used
-  --> $DIR/issue-54954.rs:11:15
-   |
-LL | fn f(z: [f32; ARR_LEN]) -> [f32; ARR_LEN] {
-   |               ^^^^^^^
-
-note: erroneous constant used
-  --> $DIR/issue-54954.rs:11:34
-   |
-LL | fn f(z: [f32; ARR_LEN]) -> [f32; ARR_LEN] {
-   |                                  ^^^^^^^
-
 error: aborting due to 2 previous errors
 
 Some errors have detailed explanations: E0379, E0790.
diff --git a/tests/ui/consts/issue-56164.stderr b/tests/ui/consts/issue-56164.stderr
index 003f8474463..e46c649faf0 100644
--- a/tests/ui/consts/issue-56164.stderr
+++ b/tests/ui/consts/issue-56164.stderr
@@ -28,18 +28,6 @@ error: function pointer calls are not allowed in constant functions
 LL |     input()
    |     ^^^^^^^
 
-note: erroneous constant used
-  --> $DIR/issue-56164.rs:1:18
-   |
-LL | const fn foo() { (||{})() }
-   |                  ^^^^^^
-
-note: erroneous constant used
-  --> $DIR/issue-56164.rs:1:18
-   |
-LL | const fn foo() { (||{})() }
-   |                  ^^^^^^
-
 error: aborting due to 3 previous errors
 
 Some errors have detailed explanations: E0015, E0277.
diff --git a/tests/ui/consts/issue-66693.stderr b/tests/ui/consts/issue-66693.stderr
index e9a3fced61c..f4898fd9732 100644
--- a/tests/ui/consts/issue-66693.stderr
+++ b/tests/ui/consts/issue-66693.stderr
@@ -22,17 +22,5 @@ LL |     panic!(&1);
    |
    = note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-note: erroneous constant used
-  --> $DIR/issue-66693.rs:11:12
-   |
-LL |     panic!(&1);
-   |            ^^
-
-note: erroneous constant used
-  --> $DIR/issue-66693.rs:11:12
-   |
-LL |     panic!(&1);
-   |            ^^
-
 error: aborting due to 3 previous errors
 
diff --git a/tests/ui/crate-leading-sep.rs b/tests/ui/crate-leading-sep.rs
index ca5905fab41..fce97d9ba23 100644
--- a/tests/ui/crate-leading-sep.rs
+++ b/tests/ui/crate-leading-sep.rs
@@ -1,6 +1,8 @@
 // run-pass
 // pretty-expanded FIXME #23616
 
+#![allow(dropping_copy_types)]
+
 fn main() {
     use ::std::mem;
     mem::drop(2_usize);
diff --git a/tests/ui/custom_test_frameworks/mismatch.stderr b/tests/ui/custom_test_frameworks/mismatch.stderr
index 61061ae529d..31b18b2df98 100644
--- a/tests/ui/custom_test_frameworks/mismatch.stderr
+++ b/tests/ui/custom_test_frameworks/mismatch.stderr
@@ -6,7 +6,7 @@ LL | #[test]
 LL | fn wrong_kind(){}
    | ^^^^^^^^^^^^^^^^^ the trait `Testable` is not implemented for `TestDescAndFn`
    |
-   = note: required for the cast from `TestDescAndFn` to the object type `dyn Testable`
+   = note: required for the cast from `&TestDescAndFn` to `&dyn Testable`
    = note: this error originates in the attribute macro `test` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to previous error
diff --git a/tests/ui/diagnostic-width/E0271.stderr b/tests/ui/diagnostic-width/E0271.stderr
index ed7b6651d01..52f415037d3 100644
--- a/tests/ui/diagnostic-width/E0271.stderr
+++ b/tests/ui/diagnostic-width/E0271.stderr
@@ -15,8 +15,8 @@ note: expected this to be `Foo`
    |
 LL |     type Error = E;
    |                  ^
-   = note: required for the cast from `Result<Result<..., ...>, ...>` to the object type `dyn Future<Error = Foo>`
-   = note: the full name for the casted type has been written to '$TEST_BUILD_DIR/diagnostic-width/E0271/E0271.long-type-hash.txt'
+   = note: required for the cast from `Box<Result<..., ...>>` to `Box<(dyn Future<Error = Foo> + 'static)>`
+   = note: the full name for the source type has been written to '$TEST_BUILD_DIR/diagnostic-width/E0271/E0271.long-type-hash.txt'
 
 error: aborting due to previous error
 
diff --git a/tests/ui/drop/dropck-eyepatch-manuallydrop.rs b/tests/ui/drop/dropck-eyepatch-manuallydrop.rs
new file mode 100644
index 00000000000..ff100cd941f
--- /dev/null
+++ b/tests/ui/drop/dropck-eyepatch-manuallydrop.rs
@@ -0,0 +1,22 @@
+// check-pass
+//! This test checks that dropck knows that ManuallyDrop does not drop its field.
+#![feature(dropck_eyepatch)]
+
+use std::mem::ManuallyDrop;
+
+struct S<T>(ManuallyDrop<T>);
+
+unsafe impl<#[may_dangle] T> Drop for S<T> {
+    fn drop(&mut self) {}
+}
+
+struct NonTrivialDrop<'a>(&'a str);
+impl<'a> Drop for NonTrivialDrop<'a> {
+    fn drop(&mut self) {}
+}
+
+fn main() {
+    let s = String::from("string");
+    let _t = S(ManuallyDrop::new(NonTrivialDrop(&s)));
+    drop(s);
+}
diff --git a/tests/ui/drop/issue-110682.rs b/tests/ui/drop/issue-110682.rs
new file mode 100644
index 00000000000..35f9c7e8d9b
--- /dev/null
+++ b/tests/ui/drop/issue-110682.rs
@@ -0,0 +1,92 @@
+// build-pass
+// compile-flags: -Zmir-opt-level=3
+
+use std::fmt::Debug;
+use std::mem::ManuallyDrop;
+use std::ptr;
+
+pub trait BitRegister {}
+
+macro_rules! register {
+    ($($t:ty),+ $(,)?) => { $(
+        impl BitRegister for $t {
+        }
+    )* };
+}
+
+register!(u8, u16, u32);
+
+pub trait BitStore: Sized + Debug {
+    /// The register type that the implementor describes.
+    type Mem: BitRegister + Into<Self>;
+}
+
+macro_rules! store {
+    ($($t:ty),+ $(,)?) => { $(
+        impl BitStore for $t {
+            type Mem = Self;
+        }
+    )+ };
+}
+
+store!(u8, u16, u32,);
+
+#[repr(C)]
+pub struct BitVec<T>
+where
+    T: BitStore,
+{
+    /// Region pointer describing the live portion of the owned buffer.
+    pointer: ptr::NonNull<T>,
+    /// Allocated capacity, in elements `T`, of the owned buffer.
+    capacity: usize,
+}
+
+impl<T> BitVec<T>
+where
+    T: BitStore,
+{
+    pub fn new() -> Self {
+        let pointer = ptr::NonNull::<T>::new(ptr::null_mut()).unwrap();
+
+        BitVec { pointer, capacity: 10 }
+    }
+
+    pub fn clear(&mut self) {
+        unsafe {
+            self.set_len(0);
+        }
+    }
+
+    #[inline]
+    pub unsafe fn set_len(&mut self, new_len: usize) {}
+
+    fn with_vec<F, R>(&mut self, func: F) -> R
+    where
+        F: FnOnce(&mut ManuallyDrop<Vec<T::Mem>>) -> R,
+    {
+        let cap = self.capacity;
+        let elts = 10;
+        let mut vec = ManuallyDrop::new(unsafe { Vec::from_raw_parts(ptr::null_mut(), elts, cap) });
+        let out = func(&mut vec);
+
+        out
+    }
+}
+
+impl<T> Drop for BitVec<T>
+where
+    T: BitStore,
+{
+    #[inline]
+    fn drop(&mut self) {
+        //  The buffer elements do not have destructors.
+        self.clear();
+        //  Run the `Vec` destructor to deällocate the buffer.
+        self.with_vec(|vec| unsafe { ManuallyDrop::drop(vec) });
+    }
+}
+
+fn main() {
+    let bitvec = BitVec::<u32>::new();
+}
diff --git a/tests/ui/drop/repeat-drop.rs b/tests/ui/drop/repeat-drop.rs
index 8fd46ecaf44..0afb4bb11bc 100644
--- a/tests/ui/drop/repeat-drop.rs
+++ b/tests/ui/drop/repeat-drop.rs
@@ -1,6 +1,8 @@
 // run-pass
 // needs-unwind
 
+#![allow(dropping_references, dropping_copy_types)]
+
 static mut CHECK: usize = 0;
 
 struct DropChecker(usize);
diff --git a/tests/ui/dst/dst-bad-coerce1.stderr b/tests/ui/dst/dst-bad-coerce1.stderr
index ff77bd4cef8..2c75518c298 100644
--- a/tests/ui/dst/dst-bad-coerce1.stderr
+++ b/tests/ui/dst/dst-bad-coerce1.stderr
@@ -15,7 +15,7 @@ error[E0277]: the trait bound `Foo: Bar` is not satisfied
 LL |     let f3: &Fat<dyn Bar> = f2;
    |                             ^^ the trait `Bar` is not implemented for `Foo`
    |
-   = note: required for the cast from `Foo` to the object type `dyn Bar`
+   = note: required for the cast from `&Fat<Foo>` to `&Fat<dyn Bar>`
 
 error[E0308]: mismatched types
   --> $DIR/dst-bad-coerce1.rs:28:27
@@ -34,7 +34,7 @@ error[E0277]: the trait bound `Foo: Bar` is not satisfied
 LL |     let f3: &(dyn Bar,) = f2;
    |                           ^^ the trait `Bar` is not implemented for `Foo`
    |
-   = note: required for the cast from `Foo` to the object type `dyn Bar`
+   = note: required for the cast from `&(Foo,)` to `&(dyn Bar,)`
 
 error: aborting due to 4 previous errors
 
diff --git a/tests/ui/dst/dst-object-from-unsized-type.stderr b/tests/ui/dst/dst-object-from-unsized-type.stderr
index e24c96ebed6..d5e464aed4b 100644
--- a/tests/ui/dst/dst-object-from-unsized-type.stderr
+++ b/tests/ui/dst/dst-object-from-unsized-type.stderr
@@ -6,7 +6,7 @@ LL | fn test1<T: ?Sized + Foo>(t: &T) {
 LL |     let u: &dyn Foo = t;
    |                       ^ doesn't have a size known at compile-time
    |
-   = note: required for the cast from `T` to the object type `dyn Foo`
+   = note: required for the cast from `&T` to `&dyn Foo`
 help: consider removing the `?Sized` bound to make the type parameter `Sized`
    |
 LL - fn test1<T: ?Sized + Foo>(t: &T) {
@@ -21,7 +21,7 @@ LL | fn test2<T: ?Sized + Foo>(t: &T) {
 LL |     let v: &dyn Foo = t as &dyn Foo;
    |                       ^ doesn't have a size known at compile-time
    |
-   = note: required for the cast from `T` to the object type `dyn Foo`
+   = note: required for the cast from `&T` to `&dyn Foo`
 help: consider removing the `?Sized` bound to make the type parameter `Sized`
    |
 LL - fn test2<T: ?Sized + Foo>(t: &T) {
@@ -35,7 +35,7 @@ LL |     let _: &[&dyn Foo] = &["hi"];
    |                            ^^^^ doesn't have a size known at compile-time
    |
    = help: the trait `Sized` is not implemented for `str`
-   = note: required for the cast from `str` to the object type `dyn Foo`
+   = note: required for the cast from `&'static str` to `&dyn Foo`
 
 error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
   --> $DIR/dst-object-from-unsized-type.rs:23:23
@@ -44,7 +44,7 @@ LL |     let _: &dyn Foo = x as &dyn Foo;
    |                       ^ doesn't have a size known at compile-time
    |
    = help: the trait `Sized` is not implemented for `[u8]`
-   = note: required for the cast from `[u8]` to the object type `dyn Foo`
+   = note: required for the cast from `&[u8]` to `&dyn Foo`
 
 error: aborting due to 4 previous errors
 
diff --git a/tests/ui/dupe-first-attr.rc b/tests/ui/dupe-first-attr.rs
index 8b7025b7be7..d950743b41c 100644
--- a/tests/ui/dupe-first-attr.rc
+++ b/tests/ui/dupe-first-attr.rs
@@ -1,24 +1,26 @@
+// run-pass
+
 // Regression test for a problem with the first mod attribute
 // being applied to every mod
 
 // pretty-expanded FIXME #23616
 
 #[cfg(target_os = "linux")]
-mod hello;
+mod hello {}
 
 #[cfg(target_os = "macos")]
-mod hello;
+mod hello {}
 
 #[cfg(target_os = "windows")]
-mod hello;
+mod hello {}
 
 #[cfg(target_os = "freebsd")]
-mod hello;
+mod hello {}
 
 #[cfg(target_os = "dragonfly")]
-mod hello;
+mod hello {}
 
 #[cfg(target_os = "android")]
-mod hello;
+mod hello {}
 
-pub fn main() { }
+fn main() {}
diff --git a/tests/ui/enum-discriminant/auxiliary/discr-foreign-dep.rs b/tests/ui/enum-discriminant/auxiliary/discr-foreign-dep.rs
new file mode 100644
index 00000000000..a2cc10a4b22
--- /dev/null
+++ b/tests/ui/enum-discriminant/auxiliary/discr-foreign-dep.rs
@@ -0,0 +1,7 @@
+#[derive(Default)]
+pub enum Foo {
+    A(u32),
+    #[default]
+    B,
+    C(u32),
+}
diff --git a/tests/ui/enum-discriminant/discr-foreign.rs b/tests/ui/enum-discriminant/discr-foreign.rs
new file mode 100644
index 00000000000..e7123b34452
--- /dev/null
+++ b/tests/ui/enum-discriminant/discr-foreign.rs
@@ -0,0 +1,11 @@
+// aux-build:discr-foreign-dep.rs
+// build-pass
+
+extern crate discr_foreign_dep;
+
+fn main() {
+    match Default::default() {
+        discr_foreign_dep::Foo::A(_) => {}
+        _ => {}
+    }
+}
diff --git a/tests/ui/enum-discriminant/issue-41394.rs b/tests/ui/enum-discriminant/issue-41394.rs
index 07cad8796e1..06a33081340 100644
--- a/tests/ui/enum-discriminant/issue-41394.rs
+++ b/tests/ui/enum-discriminant/issue-41394.rs
@@ -5,7 +5,6 @@ enum Foo {
 
 enum Bar {
     A = Foo::A as isize
-    //~^ const
 }
 
 fn main() {}
diff --git a/tests/ui/enum-discriminant/issue-41394.stderr b/tests/ui/enum-discriminant/issue-41394.stderr
index 1b5c64628a1..fa95ca9c18a 100644
--- a/tests/ui/enum-discriminant/issue-41394.stderr
+++ b/tests/ui/enum-discriminant/issue-41394.stderr
@@ -6,12 +6,6 @@ LL |     A = "" + 1
    |         |
    |         &str
 
-note: erroneous constant used
-  --> $DIR/issue-41394.rs:7:9
-   |
-LL |     A = Foo::A as isize
-   |         ^^^^^^^^^^^^^^^
-
 error: aborting due to previous error
 
 For more information about this error, try `rustc --explain E0369`.
diff --git a/tests/ui/explicit/explicit-call-to-supertrait-dtor.fixed b/tests/ui/explicit/explicit-call-to-supertrait-dtor.fixed
index 47c4c9f67b6..bb093a4af4a 100644
--- a/tests/ui/explicit/explicit-call-to-supertrait-dtor.fixed
+++ b/tests/ui/explicit/explicit-call-to-supertrait-dtor.fixed
@@ -1,4 +1,7 @@
 // run-rustfix
+
+#![allow(dropping_references)]
+
 struct Foo {
     x: isize
 }
diff --git a/tests/ui/explicit/explicit-call-to-supertrait-dtor.rs b/tests/ui/explicit/explicit-call-to-supertrait-dtor.rs
index c698de50c75..1a9f89c054f 100644
--- a/tests/ui/explicit/explicit-call-to-supertrait-dtor.rs
+++ b/tests/ui/explicit/explicit-call-to-supertrait-dtor.rs
@@ -1,4 +1,7 @@
 // run-rustfix
+
+#![allow(dropping_references)]
+
 struct Foo {
     x: isize
 }
diff --git a/tests/ui/explicit/explicit-call-to-supertrait-dtor.stderr b/tests/ui/explicit/explicit-call-to-supertrait-dtor.stderr
index 7f5106eb57e..c7067117349 100644
--- a/tests/ui/explicit/explicit-call-to-supertrait-dtor.stderr
+++ b/tests/ui/explicit/explicit-call-to-supertrait-dtor.stderr
@@ -1,5 +1,5 @@
 error[E0040]: explicit use of destructor method
-  --> $DIR/explicit-call-to-supertrait-dtor.rs:19:14
+  --> $DIR/explicit-call-to-supertrait-dtor.rs:22:14
    |
 LL |         self.drop();
    |         -----^^^^--
diff --git a/tests/ui/extenv/extenv-escaped-var.rs b/tests/ui/extenv/extenv-escaped-var.rs
new file mode 100644
index 00000000000..d898feb78c6
--- /dev/null
+++ b/tests/ui/extenv/extenv-escaped-var.rs
@@ -0,0 +1,3 @@
+fn main() {
+    env!("\t"); //~ERROR environment variable `\t` not defined at compile time
+}
diff --git a/tests/ui/extenv/extenv-escaped-var.stderr b/tests/ui/extenv/extenv-escaped-var.stderr
new file mode 100644
index 00000000000..25e218c63f3
--- /dev/null
+++ b/tests/ui/extenv/extenv-escaped-var.stderr
@@ -0,0 +1,11 @@
+error: environment variable `\t` not defined at compile time
+  --> $DIR/extenv-escaped-var.rs:2:5
+   |
+LL |     env!("\t");
+   |     ^^^^^^^^^^
+   |
+   = help: use `std::env::var("\t")` to read the variable at run time
+   = note: this error originates in the macro `env` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to previous error
+
diff --git a/tests/ui/extenv/issue-110547.stderr b/tests/ui/extenv/issue-110547.stderr
index 1219630d346..10589ec2f54 100644
--- a/tests/ui/extenv/issue-110547.stderr
+++ b/tests/ui/extenv/issue-110547.stderr
@@ -1,28 +1,28 @@
-error: environment variable `    ` not defined at compile time
+error: environment variable `\t` not defined at compile time
   --> $DIR/issue-110547.rs:4:5
    |
 LL |     env!{"\t"};
    |     ^^^^^^^^^^
    |
-   = help: use `std::env::var("    ")` to read the variable at run time
+   = help: use `std::env::var("\t")` to read the variable at run time
    = note: this error originates in the macro `env` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error: environment variable `    ` not defined at compile time
+error: environment variable `\t` not defined at compile time
   --> $DIR/issue-110547.rs:5:5
    |
 LL |     env!("\t");
    |     ^^^^^^^^^^
    |
-   = help: use `std::env::var("    ")` to read the variable at run time
+   = help: use `std::env::var("\t")` to read the variable at run time
    = note: this error originates in the macro `env` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error: environment variable `` not defined at compile time
+error: environment variable `\u{2069}` not defined at compile time
   --> $DIR/issue-110547.rs:6:5
    |
 LL |     env!("\u{2069}");
    |     ^^^^^^^^^^^^^^^^
    |
-   = help: use `std::env::var("")` to read the variable at run time
+   = help: use `std::env::var("\u{2069}")` to read the variable at run time
    = note: this error originates in the macro `env` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to 3 previous errors
diff --git a/tests/ui/extern/auxiliary/invalid-utf8.txt b/tests/ui/extern/auxiliary/invalid-utf8.txt
deleted file mode 100644
index dc1115b82db..00000000000
--- a/tests/ui/extern/auxiliary/invalid-utf8.txt
+++ /dev/null
@@ -1 +0,0 @@
-Ã(
\ No newline at end of file
diff --git a/tests/ui/feature-gates/auxiliary/debugger-visualizer.natvis b/tests/ui/feature-gates/auxiliary/debugger-visualizer.natvis
deleted file mode 100644
index 6eb47e3d85b..00000000000
--- a/tests/ui/feature-gates/auxiliary/debugger-visualizer.natvis
+++ /dev/null
@@ -1,3 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010">
-</AutoVisualizer>
diff --git a/tests/ui/feature-gates/feature-gate-cfg_overflow_checks.rs b/tests/ui/feature-gates/feature-gate-cfg_overflow_checks.rs
new file mode 100644
index 00000000000..cb265aa7f25
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-cfg_overflow_checks.rs
@@ -0,0 +1,6 @@
+#![crate_type = "lib"]
+
+#[cfg(overflow_checks)] //~ ERROR `cfg(overflow_checks)` is experimental
+pub fn cast(v: i64)->u32{
+    todo!()
+}
diff --git a/tests/ui/feature-gates/feature-gate-cfg_overflow_checks.stderr b/tests/ui/feature-gates/feature-gate-cfg_overflow_checks.stderr
new file mode 100644
index 00000000000..79aba7945f6
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-cfg_overflow_checks.stderr
@@ -0,0 +1,12 @@
+error[E0658]: `cfg(overflow_checks)` is experimental and subject to change
+  --> $DIR/feature-gate-cfg_overflow_checks.rs:3:7
+   |
+LL | #[cfg(overflow_checks)]
+   |       ^^^^^^^^^^^^^^^
+   |
+   = note: see issue #111466 <https://github.com/rust-lang/rust/issues/111466> for more information
+   = help: add `#![feature(cfg_overflow_checks)]` to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/feature-gates/feature-gate-dispatch-from-dyn-missing-impl.stderr b/tests/ui/feature-gates/feature-gate-dispatch-from-dyn-missing-impl.stderr
index d81eade8e9b..303700c7ab4 100644
--- a/tests/ui/feature-gates/feature-gate-dispatch-from-dyn-missing-impl.stderr
+++ b/tests/ui/feature-gates/feature-gate-dispatch-from-dyn-missing-impl.stderr
@@ -31,14 +31,7 @@ LL | trait Trait {
    |       ----- this trait cannot be made into an object...
 LL |     fn ptr(self: Ptr<Self>);
    |                  ^^^^^^^^^ ...because method `ptr`'s `self` parameter cannot be dispatched on
-note: required for `Ptr<{integer}>` to implement `CoerceUnsized<Ptr<dyn Trait>>`
-  --> $DIR/feature-gate-dispatch-from-dyn-missing-impl.rs:20:40
-   |
-LL | impl<T: Unsize<U> + ?Sized, U: ?Sized> CoerceUnsized<Ptr<U>> for Ptr<T> {}
-   |         ---------                      ^^^^^^^^^^^^^^^^^^^^^     ^^^^^^
-   |         |
-   |         unsatisfied trait bound introduced here
-   = note: required by cast to type `Ptr<dyn Trait>`
+   = note: required for the cast from `Ptr<{integer}>` to `Ptr<dyn Trait>`
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/feature-gates/feature-gate-unsafe_pin_internals.rs b/tests/ui/feature-gates/feature-gate-unsafe_pin_internals.rs
index 0680d234403..dce94c9eab2 100644
--- a/tests/ui/feature-gates/feature-gate-unsafe_pin_internals.rs
+++ b/tests/ui/feature-gates/feature-gate-unsafe_pin_internals.rs
@@ -13,5 +13,4 @@ fn non_unsafe_pin_new_unchecked<T>(pointer: &mut T) -> Pin<&mut T> {
 fn main() {
     let mut self_referential = PhantomPinned;
     let _: Pin<&mut PhantomPinned> = non_unsafe_pin_new_unchecked(&mut self_referential);
-    core::mem::forget(self_referential); // move and disable drop glue!
 }
diff --git a/tests/ui/generator/drop-env.rs b/tests/ui/generator/drop-env.rs
index 66dfb8c2c09..137a407931a 100644
--- a/tests/ui/generator/drop-env.rs
+++ b/tests/ui/generator/drop-env.rs
@@ -4,6 +4,7 @@
 //[nomiropt]compile-flags: -Z mir-opt-level=0
 
 #![feature(generators, generator_trait)]
+#![allow(dropping_copy_types)]
 
 use std::ops::Generator;
 use std::pin::Pin;
diff --git a/tests/ui/generator/drop-tracking-error-body.rs b/tests/ui/generator/drop-tracking-error-body.rs
new file mode 100644
index 00000000000..f99d9ab6bf8
--- /dev/null
+++ b/tests/ui/generator/drop-tracking-error-body.rs
@@ -0,0 +1,18 @@
+// compile-flags: -Zdrop-tracking-mir --edition=2021
+
+#![feature(generators)]
+
+pub async fn async_bad_body() {
+    match true {} //~ ERROR non-exhaustive patterns: type `bool` is non-empty
+}
+
+pub fn generator_bad_body() {
+    || {
+        // 'non-exhaustive pattern' only seems to be reported once, so this annotation doesn't work
+        // keep the function around so we can make sure it doesn't ICE
+        match true {}; // ERROR non-exhaustive patterns: type `bool` is non-empty
+        yield ();
+    };
+}
+
+fn main() {}
diff --git a/tests/ui/generator/drop-tracking-error-body.stderr b/tests/ui/generator/drop-tracking-error-body.stderr
new file mode 100644
index 00000000000..28a6892336f
--- /dev/null
+++ b/tests/ui/generator/drop-tracking-error-body.stderr
@@ -0,0 +1,17 @@
+error[E0004]: non-exhaustive patterns: type `bool` is non-empty
+  --> $DIR/drop-tracking-error-body.rs:6:11
+   |
+LL |     match true {}
+   |           ^^^^
+   |
+   = note: the matched value is of type `bool`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
+   |
+LL ~     match true {
+LL +         _ => todo!(),
+LL ~     }
+   |
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0004`.
diff --git a/tests/ui/generator/issue-57017.no_drop_tracking.stderr b/tests/ui/generator/issue-57017.no_drop_tracking.stderr
index 06d2d23b9ef..f7b8e198cc4 100644
--- a/tests/ui/generator/issue-57017.no_drop_tracking.stderr
+++ b/tests/ui/generator/issue-57017.no_drop_tracking.stderr
@@ -1,5 +1,5 @@
 error: generator cannot be sent between threads safely
-  --> $DIR/issue-57017.rs:31:25
+  --> $DIR/issue-57017.rs:32:25
    |
 LL |               assert_send(g);
    |                           ^ generator is not `Send`
@@ -15,7 +15,7 @@ LL | |     );
    |
    = help: the trait `Sync` is not implemented for `copy::unsync::Client`
 note: generator is not `Send` as this value is used across a yield
-  --> $DIR/issue-57017.rs:29:28
+  --> $DIR/issue-57017.rs:30:28
    |
 LL |               let g = move || match drop(&$name::unsync::Client::default()) {
    |                                          --------------------------------- has type `&copy::unsync::Client` which is not `Send`
@@ -33,14 +33,14 @@ LL | |         }
 LL | |     );
    | |_____- in this macro invocation
 note: required by a bound in `assert_send`
-  --> $DIR/issue-57017.rs:51:19
+  --> $DIR/issue-57017.rs:52:19
    |
 LL | fn assert_send<T: Send>(_thing: T) {}
    |                   ^^^^ required by this bound in `assert_send`
    = note: this error originates in the macro `type_combinations` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: generator cannot be sent between threads safely
-  --> $DIR/issue-57017.rs:43:25
+  --> $DIR/issue-57017.rs:44:25
    |
 LL |               assert_send(g);
    |                           ^ generator is not `Send`
@@ -54,9 +54,9 @@ LL | |         }
 LL | |     );
    | |_____- in this macro invocation
    |
-   = help: within `[generator@$DIR/issue-57017.rs:40:21: 40:28]`, the trait `Send` is not implemented for `copy::unsend::Client`
+   = help: within `[generator@$DIR/issue-57017.rs:41:21: 41:28]`, the trait `Send` is not implemented for `copy::unsend::Client`
 note: generator is not `Send` as this value is used across a yield
-  --> $DIR/issue-57017.rs:41:28
+  --> $DIR/issue-57017.rs:42:28
    |
 LL |               let g = move || match drop($name::unsend::Client::default()) {
    |                                          -------------------------------- has type `copy::unsend::Client` which is not `Send`
@@ -74,14 +74,14 @@ LL | |         }
 LL | |     );
    | |_____- in this macro invocation
 note: required by a bound in `assert_send`
-  --> $DIR/issue-57017.rs:51:19
+  --> $DIR/issue-57017.rs:52:19
    |
 LL | fn assert_send<T: Send>(_thing: T) {}
    |                   ^^^^ required by this bound in `assert_send`
    = note: this error originates in the macro `type_combinations` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: generator cannot be sent between threads safely
-  --> $DIR/issue-57017.rs:31:25
+  --> $DIR/issue-57017.rs:32:25
    |
 LL |               assert_send(g);
    |                           ^ generator is not `Send`
@@ -97,7 +97,7 @@ LL | |     );
    |
    = help: the trait `Sync` is not implemented for `derived_drop::unsync::Client`
 note: generator is not `Send` as this value is used across a yield
-  --> $DIR/issue-57017.rs:29:28
+  --> $DIR/issue-57017.rs:30:28
    |
 LL |               let g = move || match drop(&$name::unsync::Client::default()) {
    |                                          --------------------------------- has type `&derived_drop::unsync::Client` which is not `Send`
@@ -115,14 +115,14 @@ LL | |         }
 LL | |     );
    | |_____- in this macro invocation
 note: required by a bound in `assert_send`
-  --> $DIR/issue-57017.rs:51:19
+  --> $DIR/issue-57017.rs:52:19
    |
 LL | fn assert_send<T: Send>(_thing: T) {}
    |                   ^^^^ required by this bound in `assert_send`
    = note: this error originates in the macro `type_combinations` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: generator cannot be sent between threads safely
-  --> $DIR/issue-57017.rs:43:25
+  --> $DIR/issue-57017.rs:44:25
    |
 LL |               assert_send(g);
    |                           ^ generator is not `Send`
@@ -136,9 +136,9 @@ LL | |         }
 LL | |     );
    | |_____- in this macro invocation
    |
-   = help: within `[generator@$DIR/issue-57017.rs:40:21: 40:28]`, the trait `Send` is not implemented for `derived_drop::unsend::Client`
+   = help: within `[generator@$DIR/issue-57017.rs:41:21: 41:28]`, the trait `Send` is not implemented for `derived_drop::unsend::Client`
 note: generator is not `Send` as this value is used across a yield
-  --> $DIR/issue-57017.rs:41:28
+  --> $DIR/issue-57017.rs:42:28
    |
 LL |               let g = move || match drop($name::unsend::Client::default()) {
    |                                          -------------------------------- has type `derived_drop::unsend::Client` which is not `Send`
@@ -156,14 +156,14 @@ LL | |         }
 LL | |     );
    | |_____- in this macro invocation
 note: required by a bound in `assert_send`
-  --> $DIR/issue-57017.rs:51:19
+  --> $DIR/issue-57017.rs:52:19
    |
 LL | fn assert_send<T: Send>(_thing: T) {}
    |                   ^^^^ required by this bound in `assert_send`
    = note: this error originates in the macro `type_combinations` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: generator cannot be sent between threads safely
-  --> $DIR/issue-57017.rs:31:25
+  --> $DIR/issue-57017.rs:32:25
    |
 LL |               assert_send(g);
    |                           ^ generator is not `Send`
@@ -179,7 +179,7 @@ LL | |     );
    |
    = help: the trait `Sync` is not implemented for `significant_drop::unsync::Client`
 note: generator is not `Send` as this value is used across a yield
-  --> $DIR/issue-57017.rs:29:28
+  --> $DIR/issue-57017.rs:30:28
    |
 LL |               let g = move || match drop(&$name::unsync::Client::default()) {
    |                                          --------------------------------- has type `&significant_drop::unsync::Client` which is not `Send`
@@ -197,14 +197,14 @@ LL | |         }
 LL | |     );
    | |_____- in this macro invocation
 note: required by a bound in `assert_send`
-  --> $DIR/issue-57017.rs:51:19
+  --> $DIR/issue-57017.rs:52:19
    |
 LL | fn assert_send<T: Send>(_thing: T) {}
    |                   ^^^^ required by this bound in `assert_send`
    = note: this error originates in the macro `type_combinations` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: generator cannot be sent between threads safely
-  --> $DIR/issue-57017.rs:43:25
+  --> $DIR/issue-57017.rs:44:25
    |
 LL |               assert_send(g);
    |                           ^ generator is not `Send`
@@ -218,9 +218,9 @@ LL | |         }
 LL | |     );
    | |_____- in this macro invocation
    |
-   = help: within `[generator@$DIR/issue-57017.rs:40:21: 40:28]`, the trait `Send` is not implemented for `significant_drop::unsend::Client`
+   = help: within `[generator@$DIR/issue-57017.rs:41:21: 41:28]`, the trait `Send` is not implemented for `significant_drop::unsend::Client`
 note: generator is not `Send` as this value is used across a yield
-  --> $DIR/issue-57017.rs:41:28
+  --> $DIR/issue-57017.rs:42:28
    |
 LL |               let g = move || match drop($name::unsend::Client::default()) {
    |                                          -------------------------------- has type `significant_drop::unsend::Client` which is not `Send`
@@ -238,7 +238,7 @@ LL | |         }
 LL | |     );
    | |_____- in this macro invocation
 note: required by a bound in `assert_send`
-  --> $DIR/issue-57017.rs:51:19
+  --> $DIR/issue-57017.rs:52:19
    |
 LL | fn assert_send<T: Send>(_thing: T) {}
    |                   ^^^^ required by this bound in `assert_send`
diff --git a/tests/ui/generator/issue-57017.rs b/tests/ui/generator/issue-57017.rs
index 03b00ac99ad..381897c77a5 100644
--- a/tests/ui/generator/issue-57017.rs
+++ b/tests/ui/generator/issue-57017.rs
@@ -5,6 +5,7 @@
 // [drop_tracking_mir] build-pass
 
 #![feature(generators, negative_impls)]
+#![allow(dropping_references, dropping_copy_types)]
 
 macro_rules! type_combinations {
     (
diff --git a/tests/ui/generator/non-static-is-unpin.rs b/tests/ui/generator/non-static-is-unpin.rs
index 17e23f5bcd2..a5dde3912cc 100644
--- a/tests/ui/generator/non-static-is-unpin.rs
+++ b/tests/ui/generator/non-static-is-unpin.rs
@@ -3,6 +3,7 @@
 // run-pass
 
 #![feature(generators, generator_trait)]
+#![allow(dropping_copy_types)]
 
 use std::marker::{PhantomPinned, Unpin};
 
diff --git a/tests/ui/generator/resume-arg-size.rs b/tests/ui/generator/resume-arg-size.rs
index b93dc54f7a9..195166f975b 100644
--- a/tests/ui/generator/resume-arg-size.rs
+++ b/tests/ui/generator/resume-arg-size.rs
@@ -1,4 +1,5 @@
 #![feature(generators)]
+#![allow(dropping_copy_types)]
 
 // run-pass
 
diff --git a/tests/ui/generic-associated-types/equality-bound.stderr b/tests/ui/generic-associated-types/equality-bound.stderr
index d78f7a7fbce..b21ff30a27d 100644
--- a/tests/ui/generic-associated-types/equality-bound.stderr
+++ b/tests/ui/generic-associated-types/equality-bound.stderr
@@ -36,7 +36,10 @@ error[E0433]: failed to resolve: use of undeclared type `I`
   --> $DIR/equality-bound.rs:9:41
    |
 LL | fn sum3<J: Iterator>(i: J) -> i32 where I::Item = i32 {
-   |                                         ^ use of undeclared type `I`
+   |                                         ^
+   |                                         |
+   |                                         use of undeclared type `I`
+   |                                         help: a type parameter with a similar name exists: `J`
 
 error: aborting due to 4 previous errors
 
diff --git a/tests/ui/generic-associated-types/issue-76535.base.stderr b/tests/ui/generic-associated-types/issue-76535.base.stderr
index 52c6e3eec60..370329b9f83 100644
--- a/tests/ui/generic-associated-types/issue-76535.base.stderr
+++ b/tests/ui/generic-associated-types/issue-76535.base.stderr
@@ -43,8 +43,7 @@ LL | pub trait SuperTrait {
 LL |     type SubType<'a>: SubTrait where Self: 'a;
    |          ^^^^^^^ ...because it contains the generic associated type `SubType`
    = help: consider moving `SubType` to another trait
-   = note: required for `Box<SuperStruct>` to implement `CoerceUnsized<Box<dyn SuperTrait<SubType = SubStruct<'_>>>>`
-   = note: required by cast to type `Box<dyn SuperTrait<SubType = SubStruct<'_>>>`
+   = note: required for the cast from `Box<SuperStruct>` to `Box<dyn SuperTrait<SubType = SubStruct<'_>>>`
 
 error: aborting due to 3 previous errors
 
diff --git a/tests/ui/generic-associated-types/issue-79422.base.stderr b/tests/ui/generic-associated-types/issue-79422.base.stderr
index f1de77bc3c0..ad704f5e9f0 100644
--- a/tests/ui/generic-associated-types/issue-79422.base.stderr
+++ b/tests/ui/generic-associated-types/issue-79422.base.stderr
@@ -43,8 +43,7 @@ LL | trait MapLike<K, V> {
 LL |     type VRefCont<'a>: RefCont<'a, V> where Self: 'a;
    |          ^^^^^^^^ ...because it contains the generic associated type `VRefCont`
    = help: consider moving `VRefCont` to another trait
-   = note: required for `Box<BTreeMap<u8, u8>>` to implement `CoerceUnsized<Box<dyn MapLike<u8, u8, VRefCont = (dyn RefCont<'_, u8> + 'static)>>>`
-   = note: required by cast to type `Box<dyn MapLike<u8, u8, VRefCont = (dyn RefCont<'_, u8> + 'static)>>`
+   = note: required for the cast from `Box<BTreeMap<u8, u8>>` to `Box<dyn MapLike<u8, u8, VRefCont = (dyn RefCont<'_, u8> + 'static)>>`
 
 error: aborting due to 3 previous errors
 
diff --git a/tests/ui/generic-associated-types/issue-79422.extended.stderr b/tests/ui/generic-associated-types/issue-79422.extended.stderr
index 04184fce921..14492266cda 100644
--- a/tests/ui/generic-associated-types/issue-79422.extended.stderr
+++ b/tests/ui/generic-associated-types/issue-79422.extended.stderr
@@ -27,7 +27,7 @@ LL |     type VRefCont<'a> = &'a V where Self: 'a;
    |                         ^^^^^
    = note: expected trait object `(dyn RefCont<'_, u8> + 'static)`
                  found reference `&u8`
-   = note: required for the cast from `BTreeMap<u8, u8>` to the object type `dyn MapLike<u8, u8, VRefCont = (dyn RefCont<'_, u8> + 'static)>`
+   = note: required for the cast from `Box<BTreeMap<u8, u8>>` to `Box<dyn MapLike<u8, u8, VRefCont = (dyn RefCont<'_, u8> + 'static)>>`
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/generic-associated-types/issue-88595.rs b/tests/ui/generic-associated-types/issue-88595.rs
index 5a40a612972..7de906e7ef3 100644
--- a/tests/ui/generic-associated-types/issue-88595.rs
+++ b/tests/ui/generic-associated-types/issue-88595.rs
@@ -19,4 +19,5 @@ impl<'a> A<'a> for C {
     type B<'b> = impl Clone;
 
     fn a(&'a self) -> Self::B<'a> {} //~ ERROR: non-defining opaque type use in defining scope
+    //~^ ERROR: mismatched types
 }
diff --git a/tests/ui/generic-associated-types/issue-88595.stderr b/tests/ui/generic-associated-types/issue-88595.stderr
index 79d3479af8c..d6caed85459 100644
--- a/tests/ui/generic-associated-types/issue-88595.stderr
+++ b/tests/ui/generic-associated-types/issue-88595.stderr
@@ -1,16 +1,34 @@
 error: non-defining opaque type use in defining scope
-  --> $DIR/issue-88595.rs:21:35
+  --> $DIR/issue-88595.rs:21:5
    |
 LL |     fn a(&'a self) -> Self::B<'a> {}
-   |                                   ^^
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ generic argument `'a` used twice
    |
-note: lifetime used multiple times
-  --> $DIR/issue-88595.rs:18:6
+note: for this opaque type
+  --> $DIR/issue-88595.rs:19:18
    |
-LL | impl<'a> A<'a> for C {
-   |      ^^
 LL |     type B<'b> = impl Clone;
-   |            ^^
+   |                  ^^^^^^^^^^
 
-error: aborting due to previous error
+error[E0308]: mismatched types
+  --> $DIR/issue-88595.rs:21:23
+   |
+LL |     type B<'b> = impl Clone;
+   |                  ---------- the expected opaque type
+LL |
+LL |     fn a(&'a self) -> Self::B<'a> {}
+   |        -              ^^^^^^^^^^^ expected opaque type, found `()`
+   |        |
+   |        implicitly returns `()` as its body has no tail or `return` expression
+   |
+   = note: expected opaque type `<C as A<'a>>::B<'a>`
+                found unit type `()`
+note: this item must have the opaque type in its signature in order to be able to register hidden types
+  --> $DIR/issue-88595.rs:21:5
+   |
+LL |     fn a(&'a self) -> Self::B<'a> {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
 
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/hygiene/stdlib-prelude-from-opaque-late.rs b/tests/ui/hygiene/stdlib-prelude-from-opaque-late.rs
index cf65de2bc23..721bb7281c0 100644
--- a/tests/ui/hygiene/stdlib-prelude-from-opaque-late.rs
+++ b/tests/ui/hygiene/stdlib-prelude-from-opaque-late.rs
@@ -1,6 +1,7 @@
 // check-pass
 
 #![feature(decl_macro)]
+#![allow(dropping_copy_types)]
 
 macro mac() {
     mod m {
diff --git a/tests/ui/illegal-ufcs-drop.fixed b/tests/ui/illegal-ufcs-drop.fixed
index d73b391be06..c088c82791b 100644
--- a/tests/ui/illegal-ufcs-drop.fixed
+++ b/tests/ui/illegal-ufcs-drop.fixed
@@ -1,4 +1,7 @@
 // run-rustfix
+
+#![allow(dropping_references)]
+
 struct Foo;
 
 impl Drop for Foo {
diff --git a/tests/ui/illegal-ufcs-drop.rs b/tests/ui/illegal-ufcs-drop.rs
index 11411f55494..1389b112188 100644
--- a/tests/ui/illegal-ufcs-drop.rs
+++ b/tests/ui/illegal-ufcs-drop.rs
@@ -1,4 +1,7 @@
 // run-rustfix
+
+#![allow(dropping_references)]
+
 struct Foo;
 
 impl Drop for Foo {
diff --git a/tests/ui/illegal-ufcs-drop.stderr b/tests/ui/illegal-ufcs-drop.stderr
index 91f47d5e456..7a5c0612c07 100644
--- a/tests/ui/illegal-ufcs-drop.stderr
+++ b/tests/ui/illegal-ufcs-drop.stderr
@@ -1,5 +1,5 @@
 error[E0040]: explicit use of destructor method
-  --> $DIR/illegal-ufcs-drop.rs:9:5
+  --> $DIR/illegal-ufcs-drop.rs:12:5
    |
 LL |     Drop::drop(&mut Foo)
    |     ^^^^^^^^^^
diff --git a/tests/ui/impl-trait/extra-impl-in-trait-impl.fixed b/tests/ui/impl-trait/extra-impl-in-trait-impl.fixed
new file mode 100644
index 00000000000..cd4f2610d3f
--- /dev/null
+++ b/tests/ui/impl-trait/extra-impl-in-trait-impl.fixed
@@ -0,0 +1,19 @@
+// run-rustfix
+
+struct S<T>(T);
+struct S2;
+
+impl<T: Default> Default for S<T> {
+    //~^ ERROR: unexpected `impl` keyword
+    //~| HELP: remove the extra `impl`
+    fn default() -> Self { todo!() }
+}
+
+impl Default for S2 {
+    //~^ ERROR: unexpected `impl` keyword
+    //~| HELP: remove the extra `impl`
+    fn default() -> Self { todo!() }
+}
+
+
+fn main() {}
diff --git a/tests/ui/impl-trait/extra-impl-in-trait-impl.rs b/tests/ui/impl-trait/extra-impl-in-trait-impl.rs
new file mode 100644
index 00000000000..024b703e6f2
--- /dev/null
+++ b/tests/ui/impl-trait/extra-impl-in-trait-impl.rs
@@ -0,0 +1,19 @@
+// run-rustfix
+
+struct S<T>(T);
+struct S2;
+
+impl<T: Default> impl Default for S<T> {
+    //~^ ERROR: unexpected `impl` keyword
+    //~| HELP: remove the extra `impl`
+    fn default() -> Self { todo!() }
+}
+
+impl impl Default for S2 {
+    //~^ ERROR: unexpected `impl` keyword
+    //~| HELP: remove the extra `impl`
+    fn default() -> Self { todo!() }
+}
+
+
+fn main() {}
diff --git a/tests/ui/impl-trait/extra-impl-in-trait-impl.stderr b/tests/ui/impl-trait/extra-impl-in-trait-impl.stderr
new file mode 100644
index 00000000000..5aafc8b64d4
--- /dev/null
+++ b/tests/ui/impl-trait/extra-impl-in-trait-impl.stderr
@@ -0,0 +1,26 @@
+error: unexpected `impl` keyword
+  --> $DIR/extra-impl-in-trait-impl.rs:6:18
+   |
+LL | impl<T: Default> impl Default for S<T> {
+   |                  ^^^^^ help: remove the extra `impl`
+   |
+note: this is parsed as an `impl Trait` type, but a trait is expected at this position
+  --> $DIR/extra-impl-in-trait-impl.rs:6:18
+   |
+LL | impl<T: Default> impl Default for S<T> {
+   |                  ^^^^^^^^^^^^
+
+error: unexpected `impl` keyword
+  --> $DIR/extra-impl-in-trait-impl.rs:12:6
+   |
+LL | impl impl Default for S2 {
+   |      ^^^^^ help: remove the extra `impl`
+   |
+note: this is parsed as an `impl Trait` type, but a trait is expected at this position
+  --> $DIR/extra-impl-in-trait-impl.rs:12:6
+   |
+LL | impl impl Default for S2 {
+   |      ^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/impl-trait/in-assoc-type-unconstrained.rs b/tests/ui/impl-trait/in-assoc-type-unconstrained.rs
new file mode 100644
index 00000000000..c395b4195a0
--- /dev/null
+++ b/tests/ui/impl-trait/in-assoc-type-unconstrained.rs
@@ -0,0 +1,27 @@
+#![feature(impl_trait_in_assoc_type)]
+
+mod compare_ty {
+    trait Trait {
+        type Ty: IntoIterator<Item = ()>;
+    }
+    impl Trait for () {
+        type Ty = Option<impl Sized>;
+        //~^ ERROR: unconstrained opaque type
+        //~| ERROR: type mismatch resolving `<Option<<() as Trait>::Ty::{opaque#0}> as IntoIterator>::Item == ()`
+    }
+}
+
+mod compare_method {
+    trait Trait {
+        type Ty;
+        fn method() -> Self::Ty;
+    }
+    impl Trait for () {
+        type Ty = impl Sized;
+        //~^ ERROR: unconstrained opaque type
+        fn method() -> () {}
+        //~^ ERROR: method `method` has an incompatible type for trait
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/impl-trait/in-assoc-type-unconstrained.stderr b/tests/ui/impl-trait/in-assoc-type-unconstrained.stderr
new file mode 100644
index 00000000000..1097cd0f452
--- /dev/null
+++ b/tests/ui/impl-trait/in-assoc-type-unconstrained.stderr
@@ -0,0 +1,59 @@
+error[E0271]: type mismatch resolving `<Option<<() as Trait>::Ty::{opaque#0}> as IntoIterator>::Item == ()`
+  --> $DIR/in-assoc-type-unconstrained.rs:8:19
+   |
+LL |         type Ty = Option<impl Sized>;
+   |                   ^^^^^^^^^^^^^^^^^^ expected `()`, found opaque type
+   |
+   = note: expected unit type `()`
+            found opaque type `<() as compare_ty::Trait>::Ty::{opaque#0}`
+note: required by a bound in `compare_ty::Trait::Ty`
+  --> $DIR/in-assoc-type-unconstrained.rs:5:31
+   |
+LL |         type Ty: IntoIterator<Item = ()>;
+   |                               ^^^^^^^^^ required by this bound in `Trait::Ty`
+
+error: unconstrained opaque type
+  --> $DIR/in-assoc-type-unconstrained.rs:8:26
+   |
+LL |         type Ty = Option<impl Sized>;
+   |                          ^^^^^^^^^^
+   |
+   = note: `Ty` must be used in combination with a concrete type within the same impl
+
+error[E0053]: method `method` has an incompatible type for trait
+  --> $DIR/in-assoc-type-unconstrained.rs:22:24
+   |
+LL |         type Ty = impl Sized;
+   |                   ---------- the expected opaque type
+LL |
+LL |         fn method() -> () {}
+   |                        ^^
+   |                        |
+   |                        expected opaque type, found `()`
+   |                        help: change the output type to match the trait: `<() as compare_method::Trait>::Ty`
+   |
+note: type in trait
+  --> $DIR/in-assoc-type-unconstrained.rs:17:24
+   |
+LL |         fn method() -> Self::Ty;
+   |                        ^^^^^^^^
+   = note: expected signature `fn() -> <() as compare_method::Trait>::Ty`
+              found signature `fn()`
+note: this item must have the opaque type in its signature in order to be able to register hidden types
+  --> $DIR/in-assoc-type-unconstrained.rs:22:9
+   |
+LL |         fn method() -> () {}
+   |         ^^^^^^^^^^^^^^^^^
+
+error: unconstrained opaque type
+  --> $DIR/in-assoc-type-unconstrained.rs:20:19
+   |
+LL |         type Ty = impl Sized;
+   |                   ^^^^^^^^^^
+   |
+   = note: `Ty` must be used in combination with a concrete type within the same impl
+
+error: aborting due to 4 previous errors
+
+Some errors have detailed explanations: E0053, E0271.
+For more information about an error, try `rustc --explain E0053`.
diff --git a/tests/ui/impl-trait/in-assoc-type.rs b/tests/ui/impl-trait/in-assoc-type.rs
new file mode 100644
index 00000000000..36c54bdd6de
--- /dev/null
+++ b/tests/ui/impl-trait/in-assoc-type.rs
@@ -0,0 +1,21 @@
+#![feature(impl_trait_in_assoc_type)]
+
+trait Foo<T> {
+    type Bar;
+    fn foo(&self) -> <Self as Foo<()>>::Bar
+    where
+        Self: Foo<()>;
+}
+
+impl Foo<()> for () {
+    type Bar = impl std::fmt::Debug;
+    fn foo(&self) -> Self::Bar {}
+}
+
+impl Foo<i32> for () {
+    type Bar = u32;
+    fn foo(&self) -> <Self as Foo<()>>::Bar {}
+    //~^ ERROR: mismatched types
+}
+
+fn main() {}
diff --git a/tests/ui/impl-trait/in-assoc-type.stderr b/tests/ui/impl-trait/in-assoc-type.stderr
new file mode 100644
index 00000000000..f0a272dc2d5
--- /dev/null
+++ b/tests/ui/impl-trait/in-assoc-type.stderr
@@ -0,0 +1,22 @@
+error[E0308]: mismatched types
+  --> $DIR/in-assoc-type.rs:17:22
+   |
+LL |     type Bar = impl std::fmt::Debug;
+   |                -------------------- the expected opaque type
+...
+LL |     fn foo(&self) -> <Self as Foo<()>>::Bar {}
+   |        ---           ^^^^^^^^^^^^^^^^^^^^^^ expected opaque type, found `()`
+   |        |
+   |        implicitly returns `()` as its body has no tail or `return` expression
+   |
+   = note: expected opaque type `<() as Foo<()>>::Bar`
+                found unit type `()`
+note: this item must have the opaque type in its signature in order to be able to register hidden types
+  --> $DIR/in-assoc-type.rs:17:5
+   |
+LL |     fn foo(&self) -> <Self as Foo<()>>::Bar {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/impl-trait/in-trait/object-safety.current.stderr b/tests/ui/impl-trait/in-trait/object-safety.current.stderr
index b7f2b019a77..2c340a02319 100644
--- a/tests/ui/impl-trait/in-trait/object-safety.current.stderr
+++ b/tests/ui/impl-trait/in-trait/object-safety.current.stderr
@@ -42,8 +42,7 @@ LL | trait Foo {
 LL |     fn baz(&self) -> impl Debug;
    |                      ^^^^^^^^^^ ...because method `baz` references an `impl Trait` type in its return type
    = help: consider moving `baz` to another trait
-   = note: required for `Box<u32>` to implement `CoerceUnsized<Box<dyn Foo>>`
-   = note: required by cast to type `Box<dyn Foo>`
+   = note: required for the cast from `Box<u32>` to `Box<dyn Foo>`
 
 error: aborting due to 3 previous errors
 
diff --git a/tests/ui/impl-trait/in-trait/object-safety.next.stderr b/tests/ui/impl-trait/in-trait/object-safety.next.stderr
index b7f2b019a77..2c340a02319 100644
--- a/tests/ui/impl-trait/in-trait/object-safety.next.stderr
+++ b/tests/ui/impl-trait/in-trait/object-safety.next.stderr
@@ -42,8 +42,7 @@ LL | trait Foo {
 LL |     fn baz(&self) -> impl Debug;
    |                      ^^^^^^^^^^ ...because method `baz` references an `impl Trait` type in its return type
    = help: consider moving `baz` to another trait
-   = note: required for `Box<u32>` to implement `CoerceUnsized<Box<dyn Foo>>`
-   = note: required by cast to type `Box<dyn Foo>`
+   = note: required for the cast from `Box<u32>` to `Box<dyn Foo>`
 
 error: aborting due to 3 previous errors
 
diff --git a/tests/ui/impl-trait/issue-103181-1.stderr b/tests/ui/impl-trait/issue-103181-1.current.stderr
index cd026607d52..e87a9d28ae1 100644
--- a/tests/ui/impl-trait/issue-103181-1.stderr
+++ b/tests/ui/impl-trait/issue-103181-1.current.stderr
@@ -1,5 +1,5 @@
 error[E0046]: not all trait items implemented, missing: `Error`
-  --> $DIR/issue-103181-1.rs:9:5
+  --> $DIR/issue-103181-1.rs:11:5
    |
 LL |         type Error;
    |         ---------- `Error` from trait
diff --git a/tests/ui/impl-trait/issue-103181-1.next.stderr b/tests/ui/impl-trait/issue-103181-1.next.stderr
new file mode 100644
index 00000000000..e87a9d28ae1
--- /dev/null
+++ b/tests/ui/impl-trait/issue-103181-1.next.stderr
@@ -0,0 +1,12 @@
+error[E0046]: not all trait items implemented, missing: `Error`
+  --> $DIR/issue-103181-1.rs:11:5
+   |
+LL |         type Error;
+   |         ---------- `Error` from trait
+LL |     }
+LL |     impl HttpBody for () {
+   |     ^^^^^^^^^^^^^^^^^^^^ missing `Error` in implementation
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0046`.
diff --git a/tests/ui/impl-trait/issue-103181-1.rs b/tests/ui/impl-trait/issue-103181-1.rs
index 197aedf9d98..5154abcd690 100644
--- a/tests/ui/impl-trait/issue-103181-1.rs
+++ b/tests/ui/impl-trait/issue-103181-1.rs
@@ -1,3 +1,5 @@
+// revisions: current next
+//[next] compile-flags: -Ztrait-solver=next
 // edition:2021
 
 mod hyper {
diff --git a/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.stderr b/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.stderr
index f7aff419544..fe62a8f3288 100644
--- a/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.stderr
+++ b/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.stderr
@@ -43,6 +43,11 @@ LL |         fn eq(&self, _other: &(Bar, i32)) -> bool {
    |
    = note: expected signature `fn(&b::Bar, &(b::Foo, i32)) -> _`
               found signature `fn(&b::Bar, &(b::Bar, i32)) -> _`
+note: this item must have the opaque type in its signature in order to be able to register hidden types
+  --> $DIR/recursive-type-alias-impl-trait-declaration-too-subtle.rs:24:9
+   |
+LL |         fn eq(&self, _other: &(Bar, i32)) -> bool {
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 4 previous errors
 
diff --git a/tests/ui/imports/issue-109343.rs b/tests/ui/imports/issue-109343.rs
new file mode 100644
index 00000000000..0c10259bcd7
--- /dev/null
+++ b/tests/ui/imports/issue-109343.rs
@@ -0,0 +1,10 @@
+#![crate_type = "lib"]
+
+pub mod f {}
+pub use unresolved::f;
+//~^ ERROR unresolved import `unresolved`
+
+/// [g]
+pub use f as g;
+
+fn main() {}
diff --git a/tests/ui/imports/issue-109343.stderr b/tests/ui/imports/issue-109343.stderr
new file mode 100644
index 00000000000..8d9a3aee980
--- /dev/null
+++ b/tests/ui/imports/issue-109343.stderr
@@ -0,0 +1,11 @@
+error[E0432]: unresolved import `unresolved`
+  --> $DIR/issue-109343.rs:4:9
+   |
+LL | pub use unresolved::f;
+   |         ^^^^^^^^^^ maybe a missing crate `unresolved`?
+   |
+   = help: consider adding `extern crate unresolved` to use the `unresolved` crate
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0432`.
diff --git a/tests/ui/invalid/foo.natvis.xml b/tests/ui/invalid/foo.natvis.xml
new file mode 100644
index 00000000000..c341a403902
--- /dev/null
+++ b/tests/ui/invalid/foo.natvis.xml
@@ -0,0 +1 @@
+<!-- empty -->
diff --git a/tests/ui/invalid/invalid-debugger-visualizer-target.rs b/tests/ui/invalid/invalid-debugger-visualizer-target.rs
index f9dd20dbfed..1efb9555c24 100644
--- a/tests/ui/invalid/invalid-debugger-visualizer-target.rs
+++ b/tests/ui/invalid/invalid-debugger-visualizer-target.rs
@@ -1,2 +1,2 @@
-#[debugger_visualizer(natvis_file = "../foo.natvis")] //~ ERROR attribute should be applied to a module
+#[debugger_visualizer(natvis_file = "./foo.natvis.xml")] //~ ERROR attribute should be applied to a module
 fn main() {}
diff --git a/tests/ui/invalid/invalid-debugger-visualizer-target.stderr b/tests/ui/invalid/invalid-debugger-visualizer-target.stderr
index 7944f751859..c8a4d681379 100644
--- a/tests/ui/invalid/invalid-debugger-visualizer-target.stderr
+++ b/tests/ui/invalid/invalid-debugger-visualizer-target.stderr
@@ -1,8 +1,8 @@
 error: attribute should be applied to a module
   --> $DIR/invalid-debugger-visualizer-target.rs:1:1
    |
-LL | #[debugger_visualizer(natvis_file = "../foo.natvis")]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #[debugger_visualizer(natvis_file = "./foo.natvis.xml")]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/tests/ui/issues/auxiliary/issue-3136-a.rc b/tests/ui/issues/auxiliary/issue-3136-a.rc
deleted file mode 100644
index cd5fd314505..00000000000
--- a/tests/ui/issues/auxiliary/issue-3136-a.rc
+++ /dev/null
@@ -1,4 +0,0 @@
-#![crate_type = "lib"]
-
-#[path = "issue-3136-a.rs"]
-pub mod issue_3136_a;
diff --git a/tests/ui/issues/auxiliary/issue-3136-a.rs b/tests/ui/issues/auxiliary/issue-3136-a.rs
index 9bb546ab393..22bb1c8f977 100644
--- a/tests/ui/issues/auxiliary/issue-3136-a.rs
+++ b/tests/ui/issues/auxiliary/issue-3136-a.rs
@@ -1,11 +1,14 @@
+#![crate_type = "lib"]
+
 trait x {
     fn use_x<T>(&self);
 }
 struct y(());
 impl x for y {
     fn use_x<T>(&self) {
-        struct foo { //~ ERROR quux
-            i: ()
+        struct foo {
+            //~ ERROR quux
+            i: (),
         }
         fn new_foo<T>(i: ()) -> foo {
             foo { i: i }
diff --git a/tests/ui/issues/issue-14366.stderr b/tests/ui/issues/issue-14366.stderr
index 10a73b245ac..df61aabf00a 100644
--- a/tests/ui/issues/issue-14366.stderr
+++ b/tests/ui/issues/issue-14366.stderr
@@ -5,8 +5,8 @@ LL |     let _x = "test" as &dyn (::std::any::Any);
    |              ^^^^^^ doesn't have a size known at compile-time
    |
    = help: the trait `Sized` is not implemented for `str`
-   = note: required for the cast from `str` to the object type `dyn Any`
-help: consider borrowing the value, since `&str` can be coerced into `dyn Any`
+   = note: required for the cast from `&'static str` to `&(dyn Any + 'static)`
+help: consider borrowing the value, since `&&'static str` can be coerced into `&(dyn Any + 'static)`
    |
 LL |     let _x = &"test" as &dyn (::std::any::Any);
    |              +
diff --git a/tests/ui/issues/issue-22034.stderr b/tests/ui/issues/issue-22034.stderr
index b32de5b24b9..9833e559cbc 100644
--- a/tests/ui/issues/issue-22034.stderr
+++ b/tests/ui/issues/issue-22034.stderr
@@ -6,7 +6,7 @@ LL |         &mut *(ptr as *mut dyn Fn())
    |
    = help: the trait `Fn<()>` is not implemented for `()`
    = note: wrap the `()` in a closure with no arguments: `|| { /* code */ }`
-   = note: required for the cast from `()` to the object type `dyn Fn()`
+   = note: required for the cast from `*mut ()` to `*mut dyn Fn()`
 
 error: aborting due to previous error
 
diff --git a/tests/ui/issues/issue-22872.stderr b/tests/ui/issues/issue-22872.stderr
index 9510197197a..63222d25c01 100644
--- a/tests/ui/issues/issue-22872.stderr
+++ b/tests/ui/issues/issue-22872.stderr
@@ -13,7 +13,7 @@ LL | impl<'b, P> Wrap<'b> for Wrapper<P>
 LL | where P: Process<'b>,
 LL |       <P as Process<'b>>::Item: Iterator {
    |                                 -------- unsatisfied trait bound introduced here
-   = note: required for the cast from `Wrapper<P>` to the object type `dyn for<'b> Wrap<'b>`
+   = note: required for the cast from `Box<Wrapper<P>>` to `Box<dyn for<'b> Wrap<'b>>`
 help: consider further restricting the associated type
    |
 LL | fn push_process<P>(process: P) where P: Process<'static>, <P as Process<'_>>::Item: Iterator {
diff --git a/tests/ui/issues/issue-3136-b.rs b/tests/ui/issues/issue-3136-b.rs
index c4ca7236e76..33d97fe7c83 100644
--- a/tests/ui/issues/issue-3136-b.rs
+++ b/tests/ui/issues/issue-3136-b.rs
@@ -1,5 +1,5 @@
 // run-pass
-// aux-build:issue-3136-a.rc
+// aux-build:issue-3136-a.rs
 
 // pretty-expanded FIXME #23616
 
diff --git a/tests/ui/iterators/collect-into-slice.rs b/tests/ui/iterators/collect-into-slice.rs
index 5a8aacb1a6d..045d40a6f71 100644
--- a/tests/ui/iterators/collect-into-slice.rs
+++ b/tests/ui/iterators/collect-into-slice.rs
@@ -14,4 +14,10 @@ fn main() {
     //~| NOTE doesn't have a size known at compile-time
     //~| NOTE doesn't have a size known at compile-time
     process_slice(&some_generated_vec);
+
+    let some_generated_vec = (0..10).collect();
+    //~^ ERROR a slice of type `&[i32]` cannot be built since we need to store the elements somewhere
+    //~| NOTE try explicitly collecting into a `Vec<{integer}>`
+    //~| NOTE required by a bound in `collect`
+    process_slice(some_generated_vec);
 }
diff --git a/tests/ui/iterators/collect-into-slice.stderr b/tests/ui/iterators/collect-into-slice.stderr
index 29fff8c51c6..07dc561f06a 100644
--- a/tests/ui/iterators/collect-into-slice.stderr
+++ b/tests/ui/iterators/collect-into-slice.stderr
@@ -28,6 +28,16 @@ LL |     let some_generated_vec = (0..10).collect();
 note: required by a bound in `collect`
   --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
 
-error: aborting due to 3 previous errors
+error[E0277]: a slice of type `&[i32]` cannot be built since we need to store the elements somewhere
+  --> $DIR/collect-into-slice.rs:18:38
+   |
+LL |     let some_generated_vec = (0..10).collect();
+   |                                      ^^^^^^^ try explicitly collecting into a `Vec<{integer}>`
+   |
+   = help: the trait `FromIterator<{integer}>` is not implemented for `&[i32]`
+note: required by a bound in `collect`
+  --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
+
+error: aborting due to 4 previous errors
 
 For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/kindck/kindck-impl-type-params.stderr b/tests/ui/kindck/kindck-impl-type-params.stderr
index efb25bf83e1..53c1940491f 100644
--- a/tests/ui/kindck/kindck-impl-type-params.stderr
+++ b/tests/ui/kindck/kindck-impl-type-params.stderr
@@ -11,7 +11,7 @@ LL | impl<T: Send + Copy + 'static> Gettable<T> for S<T> {}
    |         ----                   ^^^^^^^^^^^     ^^^^
    |         |
    |         unsatisfied trait bound introduced here
-   = note: required for the cast from `S<T>` to the object type `dyn Gettable<T>`
+   = note: required for the cast from `&S<T>` to `&dyn Gettable<T>`
 help: consider restricting type parameter `T`
    |
 LL | fn f<T: std::marker::Send>(val: T) {
@@ -30,7 +30,7 @@ LL | impl<T: Send + Copy + 'static> Gettable<T> for S<T> {}
    |                ----            ^^^^^^^^^^^     ^^^^
    |                |
    |                unsatisfied trait bound introduced here
-   = note: required for the cast from `S<T>` to the object type `dyn Gettable<T>`
+   = note: required for the cast from `&S<T>` to `&dyn Gettable<T>`
 help: consider restricting type parameter `T`
    |
 LL | fn f<T: std::marker::Copy>(val: T) {
@@ -49,7 +49,7 @@ LL | impl<T: Send + Copy + 'static> Gettable<T> for S<T> {}
    |         ----                   ^^^^^^^^^^^     ^^^^
    |         |
    |         unsatisfied trait bound introduced here
-   = note: required for the cast from `S<T>` to the object type `dyn Gettable<T>`
+   = note: required for the cast from `&S<T>` to `&dyn Gettable<T>`
 help: consider restricting type parameter `T`
    |
 LL | fn g<T: std::marker::Send>(val: T) {
@@ -68,7 +68,7 @@ LL | impl<T: Send + Copy + 'static> Gettable<T> for S<T> {}
    |                ----            ^^^^^^^^^^^     ^^^^
    |                |
    |                unsatisfied trait bound introduced here
-   = note: required for the cast from `S<T>` to the object type `dyn Gettable<T>`
+   = note: required for the cast from `&S<T>` to `&dyn Gettable<T>`
 help: consider restricting type parameter `T`
    |
 LL | fn g<T: std::marker::Copy>(val: T) {
@@ -88,7 +88,7 @@ LL | impl<T: Send + Copy + 'static> Gettable<T> for S<T> {}
    |                ----            ^^^^^^^^^^^     ^^^^
    |                |
    |                unsatisfied trait bound introduced here
-   = note: required for the cast from `S<String>` to the object type `dyn Gettable<String>`
+   = note: required for the cast from `Box<S<String>>` to `Box<dyn Gettable<String>>`
 
 error[E0277]: the trait bound `Foo: Copy` is not satisfied
   --> $DIR/kindck-impl-type-params.rs:43:37
@@ -104,7 +104,7 @@ LL | impl<T: Send + Copy + 'static> Gettable<T> for S<T> {}
    |                ----            ^^^^^^^^^^^     ^^^^
    |                |
    |                unsatisfied trait bound introduced here
-   = note: required for the cast from `S<Foo>` to the object type `dyn Gettable<Foo>`
+   = note: required for the cast from `Box<S<Foo>>` to `Box<dyn Gettable<Foo>>`
 help: consider annotating `Foo` with `#[derive(Copy)]`
    |
 LL +     #[derive(Copy)]
diff --git a/tests/ui/kindck/kindck-inherited-copy-bound.curr.stderr b/tests/ui/kindck/kindck-inherited-copy-bound.curr.stderr
index 8d45748a6c4..29495176556 100644
--- a/tests/ui/kindck/kindck-inherited-copy-bound.curr.stderr
+++ b/tests/ui/kindck/kindck-inherited-copy-bound.curr.stderr
@@ -46,8 +46,7 @@ LL | trait Foo : Copy {
    |       ---   ^^^^ ...because it requires `Self: Sized`
    |       |
    |       this trait cannot be made into an object...
-   = note: required for `&Box<{integer}>` to implement `CoerceUnsized<&dyn Foo>`
-   = note: required by cast to type `&dyn Foo`
+   = note: required for the cast from `&Box<{integer}>` to `&dyn Foo`
 
 error: aborting due to 3 previous errors
 
diff --git a/tests/ui/kindck/kindck-inherited-copy-bound.object_safe_for_dispatch.stderr b/tests/ui/kindck/kindck-inherited-copy-bound.object_safe_for_dispatch.stderr
index 2fbb5a98a8d..3e164ebf514 100644
--- a/tests/ui/kindck/kindck-inherited-copy-bound.object_safe_for_dispatch.stderr
+++ b/tests/ui/kindck/kindck-inherited-copy-bound.object_safe_for_dispatch.stderr
@@ -32,8 +32,7 @@ LL | trait Foo : Copy {
    |       ---   ^^^^ ...because it requires `Self: Sized`
    |       |
    |       this trait cannot be made into an object...
-   = note: required for `&Box<i32>` to implement `CoerceUnsized<&dyn Foo>`
-   = note: required by cast to type `&dyn Foo`
+   = note: required for the cast from `&Box<i32>` to `&dyn Foo`
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/kindck/kindck-send-unsafe.rs b/tests/ui/kindck/kindck-send-unsafe.rs
index 4ef30a71fa3..eb1f2a549b1 100644
--- a/tests/ui/kindck/kindck-send-unsafe.rs
+++ b/tests/ui/kindck/kindck-send-unsafe.rs
@@ -1,11 +1,15 @@
 extern crate core;
 
-fn assert_send<T:Send>() { }
+fn assert_send<T: Send>() {}
+
+fn test70() {
+    assert_send::<*mut isize>();
+    //~^ ERROR `*mut isize` cannot be sent between threads safely
+}
 
 fn test71<'a>() {
     assert_send::<*mut &'a isize>();
     //~^ ERROR `*mut &'a isize` cannot be sent between threads safely
 }
 
-fn main() {
-}
+fn main() {}
diff --git a/tests/ui/kindck/kindck-send-unsafe.rs~rust-lang_master b/tests/ui/kindck/kindck-send-unsafe.rs~rust-lang_master
deleted file mode 100644
index 3f0444ec9c8..00000000000
--- a/tests/ui/kindck/kindck-send-unsafe.rs~rust-lang_master
+++ /dev/null
@@ -1,12 +0,0 @@
-fn assert_send<T:Send>() { }
-
-// unsafe ptrs are ok unless they point at unsendable things
-fn test70() {
-    assert_send::<*mut int>();
-}
-fn test71<'a>() {
-    assert_send::<*mut &'a int>(); //~ ERROR does not fulfill the required lifetime
-}
-
-fn main() {
-}
diff --git a/tests/ui/kindck/kindck-send-unsafe.stderr b/tests/ui/kindck/kindck-send-unsafe.stderr
index ceed0053caa..f1a5054abbc 100644
--- a/tests/ui/kindck/kindck-send-unsafe.stderr
+++ b/tests/ui/kindck/kindck-send-unsafe.stderr
@@ -1,16 +1,29 @@
-error[E0277]: `*mut &'a isize` cannot be sent between threads safely
+error[E0277]: `*mut isize` cannot be sent between threads safely
   --> $DIR/kindck-send-unsafe.rs:6:19
    |
+LL |     assert_send::<*mut isize>();
+   |                   ^^^^^^^^^^ `*mut isize` cannot be sent between threads safely
+   |
+   = help: the trait `Send` is not implemented for `*mut isize`
+note: required by a bound in `assert_send`
+  --> $DIR/kindck-send-unsafe.rs:3:19
+   |
+LL | fn assert_send<T: Send>() {}
+   |                   ^^^^ required by this bound in `assert_send`
+
+error[E0277]: `*mut &'a isize` cannot be sent between threads safely
+  --> $DIR/kindck-send-unsafe.rs:11:19
+   |
 LL |     assert_send::<*mut &'a isize>();
    |                   ^^^^^^^^^^^^^^ `*mut &'a isize` cannot be sent between threads safely
    |
    = help: the trait `Send` is not implemented for `*mut &'a isize`
 note: required by a bound in `assert_send`
-  --> $DIR/kindck-send-unsafe.rs:3:18
+  --> $DIR/kindck-send-unsafe.rs:3:19
    |
-LL | fn assert_send<T:Send>() { }
-   |                  ^^^^ required by this bound in `assert_send`
+LL | fn assert_send<T: Send>() {}
+   |                   ^^^^ required by this bound in `assert_send`
 
-error: aborting due to previous error
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/lint/dropping_copy_types.rs b/tests/ui/lint/dropping_copy_types.rs
new file mode 100644
index 00000000000..2937320e5d8
--- /dev/null
+++ b/tests/ui/lint/dropping_copy_types.rs
@@ -0,0 +1,79 @@
+// check-pass
+
+#![warn(dropping_copy_types)]
+
+use std::mem::drop;
+use std::vec::Vec;
+
+#[derive(Copy, Clone)]
+struct SomeStruct;
+
+struct AnotherStruct {
+    x: u8,
+    y: u8,
+    z: Vec<u8>,
+}
+
+impl Clone for AnotherStruct {
+    fn clone(&self) -> AnotherStruct {
+        AnotherStruct {
+            x: self.x,
+            y: self.y,
+            z: self.z.clone(),
+        }
+    }
+}
+
+fn main() {
+    let s1 = SomeStruct {};
+    let s2 = s1;
+    let s3 = &s1;
+    let mut s4 = s1;
+    let ref s5 = s1;
+
+    drop(s1); //~ WARN calls to `std::mem::drop`
+    drop(s2); //~ WARN calls to `std::mem::drop`
+    drop(s3); //~ WARN calls to `std::mem::drop`
+    drop(s4); //~ WARN calls to `std::mem::drop`
+    drop(s5); //~ WARN calls to `std::mem::drop`
+
+    let a1 = AnotherStruct {
+        x: 255,
+        y: 0,
+        z: vec![1, 2, 3],
+    };
+    let a2 = &a1;
+    let mut a3 = a1.clone();
+    let ref a4 = a1;
+    let a5 = a1.clone();
+
+    drop(a2); //~ WARN calls to `std::mem::drop`
+    drop(a3);
+    drop(a4); //~ WARN calls to `std::mem::drop`
+    drop(a5);
+}
+
+#[allow(unused)]
+#[allow(clippy::unit_cmp)]
+fn issue9482(x: u8) {
+    fn println_and<T>(t: T) -> T {
+        println!("foo");
+        t
+    }
+
+    match x {
+        // Don't lint (copy type), we only care about side-effects
+        0 => drop(println_and(12)),
+        // Don't lint (no copy type), we only care about side-effects
+        1 => drop(println_and(String::new())),
+        2 => {
+            // Lint, even if we only care about the side-effect, it's already in a block
+            drop(println_and(13)); //~ WARN calls to `std::mem::drop`
+        },
+         // Lint, idiomatic use is only in body of `Arm`
+        3 if drop(println_and(14)) == () => (), //~ WARN calls to `std::mem::drop`
+        // Lint, not a fn/method call
+        4 => drop(2),//~ WARN calls to `std::mem::drop`
+        _ => (),
+    }
+}
diff --git a/tests/ui/lint/dropping_copy_types.stderr b/tests/ui/lint/dropping_copy_types.stderr
new file mode 100644
index 00000000000..b6291aa5ed6
--- /dev/null
+++ b/tests/ui/lint/dropping_copy_types.stderr
@@ -0,0 +1,108 @@
+warning: calls to `std::mem::drop` with a value that implements `Copy` does nothing
+  --> $DIR/dropping_copy_types.rs:34:5
+   |
+LL |     drop(s1);
+   |     ^^^^^--^
+   |          |
+   |          argument has type `SomeStruct`
+   |
+   = note: use `let _ = ...` to ignore the expression or result
+note: the lint level is defined here
+  --> $DIR/dropping_copy_types.rs:3:9
+   |
+LL | #![warn(dropping_copy_types)]
+   |         ^^^^^^^^^^^^^^^^^^^
+
+warning: calls to `std::mem::drop` with a value that implements `Copy` does nothing
+  --> $DIR/dropping_copy_types.rs:35:5
+   |
+LL |     drop(s2);
+   |     ^^^^^--^
+   |          |
+   |          argument has type `SomeStruct`
+   |
+   = note: use `let _ = ...` to ignore the expression or result
+
+warning: calls to `std::mem::drop` with a reference instead of an owned value does nothing
+  --> $DIR/dropping_copy_types.rs:36:5
+   |
+LL |     drop(s3);
+   |     ^^^^^--^
+   |          |
+   |          argument has type `&SomeStruct`
+   |
+   = note: use `let _ = ...` to ignore the expression or result
+   = note: `#[warn(dropping_references)]` on by default
+
+warning: calls to `std::mem::drop` with a value that implements `Copy` does nothing
+  --> $DIR/dropping_copy_types.rs:37:5
+   |
+LL |     drop(s4);
+   |     ^^^^^--^
+   |          |
+   |          argument has type `SomeStruct`
+   |
+   = note: use `let _ = ...` to ignore the expression or result
+
+warning: calls to `std::mem::drop` with a reference instead of an owned value does nothing
+  --> $DIR/dropping_copy_types.rs:38:5
+   |
+LL |     drop(s5);
+   |     ^^^^^--^
+   |          |
+   |          argument has type `&SomeStruct`
+   |
+   = note: use `let _ = ...` to ignore the expression or result
+
+warning: calls to `std::mem::drop` with a reference instead of an owned value does nothing
+  --> $DIR/dropping_copy_types.rs:50:5
+   |
+LL |     drop(a2);
+   |     ^^^^^--^
+   |          |
+   |          argument has type `&AnotherStruct`
+   |
+   = note: use `let _ = ...` to ignore the expression or result
+
+warning: calls to `std::mem::drop` with a reference instead of an owned value does nothing
+  --> $DIR/dropping_copy_types.rs:52:5
+   |
+LL |     drop(a4);
+   |     ^^^^^--^
+   |          |
+   |          argument has type `&AnotherStruct`
+   |
+   = note: use `let _ = ...` to ignore the expression or result
+
+warning: calls to `std::mem::drop` with a value that implements `Copy` does nothing
+  --> $DIR/dropping_copy_types.rs:71:13
+   |
+LL |             drop(println_and(13));
+   |             ^^^^^---------------^
+   |                  |
+   |                  argument has type `i32`
+   |
+   = note: use `let _ = ...` to ignore the expression or result
+
+warning: calls to `std::mem::drop` with a value that implements `Copy` does nothing
+  --> $DIR/dropping_copy_types.rs:74:14
+   |
+LL |         3 if drop(println_and(14)) == () => (),
+   |              ^^^^^---------------^
+   |                   |
+   |                   argument has type `i32`
+   |
+   = note: use `let _ = ...` to ignore the expression or result
+
+warning: calls to `std::mem::drop` with a value that implements `Copy` does nothing
+  --> $DIR/dropping_copy_types.rs:76:14
+   |
+LL |         4 => drop(2),
+   |              ^^^^^-^
+   |                   |
+   |                   argument has type `i32`
+   |
+   = note: use `let _ = ...` to ignore the expression or result
+
+warning: 10 warnings emitted
+
diff --git a/src/tools/clippy/tests/ui/drop_ref.rs b/tests/ui/lint/dropping_references.rs
index 10044e65f11..0d5d484f451 100644
--- a/src/tools/clippy/tests/ui/drop_ref.rs
+++ b/tests/ui/lint/dropping_references.rs
@@ -1,42 +1,39 @@
-#![warn(clippy::drop_ref)]
-#![allow(clippy::toplevel_ref_arg)]
-#![allow(clippy::map_err_ignore)]
-#![allow(clippy::unnecessary_wraps, clippy::drop_non_drop)]
+// check-pass
 
-use std::mem::drop;
+#![warn(dropping_references)]
 
 struct SomeStruct;
 
 fn main() {
-    drop(&SomeStruct);
+    drop(&SomeStruct); //~ WARN calls to `std::mem::drop`
 
     let mut owned1 = SomeStruct;
-    drop(&owned1);
-    drop(&&owned1);
-    drop(&mut owned1);
-    drop(owned1); //OK
+    drop(&owned1); //~ WARN calls to `std::mem::drop`
+    drop(&&owned1); //~ WARN calls to `std::mem::drop`
+    drop(&mut owned1); //~ WARN calls to `std::mem::drop`
+    drop(owned1);
 
     let reference1 = &SomeStruct;
-    drop(reference1);
+    drop(reference1); //~ WARN calls to `std::mem::drop`
 
     let reference2 = &mut SomeStruct;
-    drop(reference2);
+    drop(reference2); //~ WARN calls to `std::mem::drop`
 
     let ref reference3 = SomeStruct;
-    drop(reference3);
+    drop(reference3); //~ WARN calls to `std::mem::drop`
 }
 
 #[allow(dead_code)]
 fn test_generic_fn_drop<T>(val: T) {
-    drop(&val);
-    drop(val); //OK
+    drop(&val); //~ WARN calls to `std::mem::drop`
+    drop(val);
 }
 
 #[allow(dead_code)]
 fn test_similarly_named_function() {
     fn drop<T>(_val: T) {}
     drop(&SomeStruct); //OK; call to unrelated function which happens to have the same name
-    std::mem::drop(&SomeStruct);
+    std::mem::drop(&SomeStruct); //~ WARN calls to `std::mem::drop`
 }
 
 #[derive(Copy, Clone)]
@@ -77,21 +74,26 @@ fn test_owl_result_2() -> Result<u8, ()> {
 #[allow(clippy::unit_cmp)]
 fn issue10122(x: u8) {
     // This is a function which returns a reference and has a side-effect, which means
-    // that calling drop() on the function is considered an idiomatic way of achieving the side-effect
-    // in a match arm.
+    // that calling drop() on the function is considered an idiomatic way of achieving
+    // the side-effect in a match arm.
     fn println_and<T>(t: &T) -> &T {
         println!("foo");
         t
     }
 
     match x {
-        0 => drop(println_and(&12)), // Don't lint (copy type), we only care about side-effects
-        1 => drop(println_and(&String::new())), // Don't lint (no copy type), we only care about side-effects
+        // Don't lint (copy type), we only care about side-effects
+        0 => drop(println_and(&12)),
+        // Don't lint (no copy type), we only care about side-effects
+        1 => drop(println_and(&String::new())),
         2 => {
-            drop(println_and(&13)); // Lint, even if we only care about the side-effect, it's already in a block
+            // Lint, even if we only care about the side-effect, it's already in a block
+            drop(println_and(&13)); //~ WARN calls to `std::mem::drop`
         },
-        3 if drop(println_and(&14)) == () => (), // Lint, idiomatic use is only in body of `Arm`
-        4 => drop(&2),                           // Lint, not a fn/method call
+        // Lint, idiomatic use is only in body of `Arm`
+        3 if drop(println_and(&14)) == () => (), //~ WARN calls to `std::mem::drop`
+         // Lint, not a fn/method call
+        4 => drop(&2), //~ WARN calls to `std::mem::drop`
         _ => (),
     }
 }
diff --git a/tests/ui/lint/dropping_references.stderr b/tests/ui/lint/dropping_references.stderr
new file mode 100644
index 00000000000..7e25a46216e
--- /dev/null
+++ b/tests/ui/lint/dropping_references.stderr
@@ -0,0 +1,127 @@
+warning: calls to `std::mem::drop` with a reference instead of an owned value does nothing
+  --> $DIR/dropping_references.rs:8:5
+   |
+LL |     drop(&SomeStruct);
+   |     ^^^^^-----------^
+   |          |
+   |          argument has type `&SomeStruct`
+   |
+   = note: use `let _ = ...` to ignore the expression or result
+note: the lint level is defined here
+  --> $DIR/dropping_references.rs:3:9
+   |
+LL | #![warn(dropping_references)]
+   |         ^^^^^^^^^^^^^^^^^^^
+
+warning: calls to `std::mem::drop` with a reference instead of an owned value does nothing
+  --> $DIR/dropping_references.rs:11:5
+   |
+LL |     drop(&owned1);
+   |     ^^^^^-------^
+   |          |
+   |          argument has type `&SomeStruct`
+   |
+   = note: use `let _ = ...` to ignore the expression or result
+
+warning: calls to `std::mem::drop` with a reference instead of an owned value does nothing
+  --> $DIR/dropping_references.rs:12:5
+   |
+LL |     drop(&&owned1);
+   |     ^^^^^--------^
+   |          |
+   |          argument has type `&&SomeStruct`
+   |
+   = note: use `let _ = ...` to ignore the expression or result
+
+warning: calls to `std::mem::drop` with a reference instead of an owned value does nothing
+  --> $DIR/dropping_references.rs:13:5
+   |
+LL |     drop(&mut owned1);
+   |     ^^^^^-----------^
+   |          |
+   |          argument has type `&mut SomeStruct`
+   |
+   = note: use `let _ = ...` to ignore the expression or result
+
+warning: calls to `std::mem::drop` with a reference instead of an owned value does nothing
+  --> $DIR/dropping_references.rs:17:5
+   |
+LL |     drop(reference1);
+   |     ^^^^^----------^
+   |          |
+   |          argument has type `&SomeStruct`
+   |
+   = note: use `let _ = ...` to ignore the expression or result
+
+warning: calls to `std::mem::drop` with a reference instead of an owned value does nothing
+  --> $DIR/dropping_references.rs:20:5
+   |
+LL |     drop(reference2);
+   |     ^^^^^----------^
+   |          |
+   |          argument has type `&mut SomeStruct`
+   |
+   = note: use `let _ = ...` to ignore the expression or result
+
+warning: calls to `std::mem::drop` with a reference instead of an owned value does nothing
+  --> $DIR/dropping_references.rs:23:5
+   |
+LL |     drop(reference3);
+   |     ^^^^^----------^
+   |          |
+   |          argument has type `&SomeStruct`
+   |
+   = note: use `let _ = ...` to ignore the expression or result
+
+warning: calls to `std::mem::drop` with a reference instead of an owned value does nothing
+  --> $DIR/dropping_references.rs:28:5
+   |
+LL |     drop(&val);
+   |     ^^^^^----^
+   |          |
+   |          argument has type `&T`
+   |
+   = note: use `let _ = ...` to ignore the expression or result
+
+warning: calls to `std::mem::drop` with a reference instead of an owned value does nothing
+  --> $DIR/dropping_references.rs:36:5
+   |
+LL |     std::mem::drop(&SomeStruct);
+   |     ^^^^^^^^^^^^^^^-----------^
+   |                    |
+   |                    argument has type `&SomeStruct`
+   |
+   = note: use `let _ = ...` to ignore the expression or result
+
+warning: calls to `std::mem::drop` with a reference instead of an owned value does nothing
+  --> $DIR/dropping_references.rs:91:13
+   |
+LL |             drop(println_and(&13));
+   |             ^^^^^----------------^
+   |                  |
+   |                  argument has type `&i32`
+   |
+   = note: use `let _ = ...` to ignore the expression or result
+
+warning: calls to `std::mem::drop` with a reference instead of an owned value does nothing
+  --> $DIR/dropping_references.rs:94:14
+   |
+LL |         3 if drop(println_and(&14)) == () => (),
+   |              ^^^^^----------------^
+   |                   |
+   |                   argument has type `&i32`
+   |
+   = note: use `let _ = ...` to ignore the expression or result
+
+warning: calls to `std::mem::drop` with a reference instead of an owned value does nothing
+  --> $DIR/dropping_references.rs:96:14
+   |
+LL |         4 => drop(&2),
+   |              ^^^^^--^
+   |                   |
+   |                   argument has type `&i32`
+   |
+   = note: use `let _ = ...` to ignore the expression or result
+
+warning: 12 warnings emitted
+
diff --git a/tests/ui/lint/forgetting_copy_types.rs b/tests/ui/lint/forgetting_copy_types.rs
new file mode 100644
index 00000000000..224c7bcd5f6
--- /dev/null
+++ b/tests/ui/lint/forgetting_copy_types.rs
@@ -0,0 +1,56 @@
+// check-pass
+
+#![warn(forgetting_copy_types)]
+
+use std::mem::forget;
+use std::vec::Vec;
+
+#[derive(Copy, Clone)]
+struct SomeStruct;
+
+struct AnotherStruct {
+    x: u8,
+    y: u8,
+    z: Vec<u8>,
+}
+
+impl Clone for AnotherStruct {
+    fn clone(&self) -> AnotherStruct {
+        AnotherStruct {
+            x: self.x,
+            y: self.y,
+            z: self.z.clone(),
+        }
+    }
+}
+
+fn main() {
+    let s1 = SomeStruct {};
+    let s2 = s1;
+    let s3 = &s1;
+    let mut s4 = s1;
+    let ref s5 = s1;
+
+    forget(s1); //~ WARN calls to `std::mem::forget`
+    forget(s2); //~ WARN calls to `std::mem::forget`
+    forget(s3); //~ WARN calls to `std::mem::forget`
+    forget(s4); //~ WARN calls to `std::mem::forget`
+    forget(s5); //~ WARN calls to `std::mem::forget`
+
+    let a1 = AnotherStruct {
+        x: 255,
+        y: 0,
+        z: vec![1, 2, 3],
+    };
+    let a2 = &a1;
+    let mut a3 = a1.clone();
+    let ref a4 = a1;
+    let a5 = a1.clone();
+
+    forget(a2); //~ WARN calls to `std::mem::forget`
+    let a3 = &a1;
+    forget(a3); //~ WARN calls to `std::mem::forget`
+    forget(a4); //~ WARN calls to `std::mem::forget`
+    let a5 = a1.clone();
+    forget(a5);
+}
diff --git a/tests/ui/lint/forgetting_copy_types.stderr b/tests/ui/lint/forgetting_copy_types.stderr
new file mode 100644
index 00000000000..36d1ef5c53e
--- /dev/null
+++ b/tests/ui/lint/forgetting_copy_types.stderr
@@ -0,0 +1,88 @@
+warning: calls to `std::mem::forget` with a value that implements `Copy` does nothing
+  --> $DIR/forgetting_copy_types.rs:34:5
+   |
+LL |     forget(s1);
+   |     ^^^^^^^--^
+   |            |
+   |            argument has type `SomeStruct`
+   |
+   = note: use `let _ = ...` to ignore the expression or result
+note: the lint level is defined here
+  --> $DIR/forgetting_copy_types.rs:3:9
+   |
+LL | #![warn(forgetting_copy_types)]
+   |         ^^^^^^^^^^^^^^^^^^^^^
+
+warning: calls to `std::mem::forget` with a value that implements `Copy` does nothing
+  --> $DIR/forgetting_copy_types.rs:35:5
+   |
+LL |     forget(s2);
+   |     ^^^^^^^--^
+   |            |
+   |            argument has type `SomeStruct`
+   |
+   = note: use `let _ = ...` to ignore the expression or result
+
+warning: calls to `std::mem::forget` with a reference instead of an owned value does nothing
+  --> $DIR/forgetting_copy_types.rs:36:5
+   |
+LL |     forget(s3);
+   |     ^^^^^^^--^
+   |            |
+   |            argument has type `&SomeStruct`
+   |
+   = note: use `let _ = ...` to ignore the expression or result
+   = note: `#[warn(forgetting_references)]` on by default
+
+warning: calls to `std::mem::forget` with a value that implements `Copy` does nothing
+  --> $DIR/forgetting_copy_types.rs:37:5
+   |
+LL |     forget(s4);
+   |     ^^^^^^^--^
+   |            |
+   |            argument has type `SomeStruct`
+   |
+   = note: use `let _ = ...` to ignore the expression or result
+
+warning: calls to `std::mem::forget` with a reference instead of an owned value does nothing
+  --> $DIR/forgetting_copy_types.rs:38:5
+   |
+LL |     forget(s5);
+   |     ^^^^^^^--^
+   |            |
+   |            argument has type `&SomeStruct`
+   |
+   = note: use `let _ = ...` to ignore the expression or result
+
+warning: calls to `std::mem::forget` with a reference instead of an owned value does nothing
+  --> $DIR/forgetting_copy_types.rs:50:5
+   |
+LL |     forget(a2);
+   |     ^^^^^^^--^
+   |            |
+   |            argument has type `&AnotherStruct`
+   |
+   = note: use `let _ = ...` to ignore the expression or result
+
+warning: calls to `std::mem::forget` with a reference instead of an owned value does nothing
+  --> $DIR/forgetting_copy_types.rs:52:5
+   |
+LL |     forget(a3);
+   |     ^^^^^^^--^
+   |            |
+   |            argument has type `&AnotherStruct`
+   |
+   = note: use `let _ = ...` to ignore the expression or result
+
+warning: calls to `std::mem::forget` with a reference instead of an owned value does nothing
+  --> $DIR/forgetting_copy_types.rs:53:5
+   |
+LL |     forget(a4);
+   |     ^^^^^^^--^
+   |            |
+   |            argument has type `&AnotherStruct`
+   |
+   = note: use `let _ = ...` to ignore the expression or result
+
+warning: 8 warnings emitted
+
diff --git a/tests/ui/lint/forgetting_references.rs b/tests/ui/lint/forgetting_references.rs
new file mode 100644
index 00000000000..bd51e980031
--- /dev/null
+++ b/tests/ui/lint/forgetting_references.rs
@@ -0,0 +1,39 @@
+// check-pass
+
+#![warn(forgetting_references)]
+
+use std::mem::forget;
+
+struct SomeStruct;
+
+fn main() {
+    forget(&SomeStruct); //~ WARN calls to `std::mem::forget`
+
+    let mut owned = SomeStruct;
+    forget(&owned); //~ WARN calls to `std::mem::forget`
+    forget(&&owned); //~ WARN calls to `std::mem::forget`
+    forget(&mut owned); //~ WARN calls to `std::mem::forget`
+    forget(owned);
+
+    let reference1 = &SomeStruct;
+    forget(&*reference1); //~ WARN calls to `std::mem::forget`
+
+    let reference2 = &mut SomeStruct;
+    forget(reference2); //~ WARN calls to `std::mem::forget`
+
+    let ref reference3 = SomeStruct;
+    forget(reference3); //~ WARN calls to `std::mem::forget`
+}
+
+#[allow(dead_code)]
+fn test_generic_fn_forget<T>(val: T) {
+    forget(&val); //~ WARN calls to `std::mem::forget`
+    forget(val);
+}
+
+#[allow(dead_code)]
+fn test_similarly_named_function() {
+    fn forget<T>(_val: T) {}
+    forget(&SomeStruct); //OK; call to unrelated function which happens to have the same name
+    std::mem::forget(&SomeStruct); //~ WARN calls to `std::mem::forget`
+}
diff --git a/tests/ui/lint/forgetting_references.stderr b/tests/ui/lint/forgetting_references.stderr
new file mode 100644
index 00000000000..5624b690789
--- /dev/null
+++ b/tests/ui/lint/forgetting_references.stderr
@@ -0,0 +1,97 @@
+warning: calls to `std::mem::forget` with a reference instead of an owned value does nothing
+  --> $DIR/forgetting_references.rs:10:5
+   |
+LL |     forget(&SomeStruct);
+   |     ^^^^^^^-----------^
+   |            |
+   |            argument has type `&SomeStruct`
+   |
+   = note: use `let _ = ...` to ignore the expression or result
+note: the lint level is defined here
+  --> $DIR/forgetting_references.rs:3:9
+   |
+LL | #![warn(forgetting_references)]
+   |         ^^^^^^^^^^^^^^^^^^^^^
+
+warning: calls to `std::mem::forget` with a reference instead of an owned value does nothing
+  --> $DIR/forgetting_references.rs:13:5
+   |
+LL |     forget(&owned);
+   |     ^^^^^^^------^
+   |            |
+   |            argument has type `&SomeStruct`
+   |
+   = note: use `let _ = ...` to ignore the expression or result
+
+warning: calls to `std::mem::forget` with a reference instead of an owned value does nothing
+  --> $DIR/forgetting_references.rs:14:5
+   |
+LL |     forget(&&owned);
+   |     ^^^^^^^-------^
+   |            |
+   |            argument has type `&&SomeStruct`
+   |
+   = note: use `let _ = ...` to ignore the expression or result
+
+warning: calls to `std::mem::forget` with a reference instead of an owned value does nothing
+  --> $DIR/forgetting_references.rs:15:5
+   |
+LL |     forget(&mut owned);
+   |     ^^^^^^^----------^
+   |            |
+   |            argument has type `&mut SomeStruct`
+   |
+   = note: use `let _ = ...` to ignore the expression or result
+
+warning: calls to `std::mem::forget` with a reference instead of an owned value does nothing
+  --> $DIR/forgetting_references.rs:19:5
+   |
+LL |     forget(&*reference1);
+   |     ^^^^^^^------------^
+   |            |
+   |            argument has type `&SomeStruct`
+   |
+   = note: use `let _ = ...` to ignore the expression or result
+
+warning: calls to `std::mem::forget` with a reference instead of an owned value does nothing
+  --> $DIR/forgetting_references.rs:22:5
+   |
+LL |     forget(reference2);
+   |     ^^^^^^^----------^
+   |            |
+   |            argument has type `&mut SomeStruct`
+   |
+   = note: use `let _ = ...` to ignore the expression or result
+
+warning: calls to `std::mem::forget` with a reference instead of an owned value does nothing
+  --> $DIR/forgetting_references.rs:25:5
+   |
+LL |     forget(reference3);
+   |     ^^^^^^^----------^
+   |            |
+   |            argument has type `&SomeStruct`
+   |
+   = note: use `let _ = ...` to ignore the expression or result
+
+warning: calls to `std::mem::forget` with a reference instead of an owned value does nothing
+  --> $DIR/forgetting_references.rs:30:5
+   |
+LL |     forget(&val);
+   |     ^^^^^^^----^
+   |            |
+   |            argument has type `&T`
+   |
+   = note: use `let _ = ...` to ignore the expression or result
+
+warning: calls to `std::mem::forget` with a reference instead of an owned value does nothing
+  --> $DIR/forgetting_references.rs:38:5
+   |
+LL |     std::mem::forget(&SomeStruct);
+   |     ^^^^^^^^^^^^^^^^^-----------^
+   |                      |
+   |                      argument has type `&SomeStruct`
+   |
+   = note: use `let _ = ...` to ignore the expression or result
+
+warning: 9 warnings emitted
+
diff --git a/tests/ui/lint/issue-111359.rs b/tests/ui/lint/issue-111359.rs
new file mode 100644
index 00000000000..e390c3fc565
--- /dev/null
+++ b/tests/ui/lint/issue-111359.rs
@@ -0,0 +1,27 @@
+#[deny(missing_debug_implementations)]
+#[deny(missing_copy_implementations)]
+
+mod priv_mod {
+    use std::convert::TryFrom;
+
+    pub struct BarPub;
+    //~^ ERROR type does not implement `Debug`; consider adding `#[derive(Debug)]` or a manual implementation
+    //~| ERROR type could implement `Copy`; consider adding `impl Copy`
+    struct BarPriv;
+
+    impl<'a> TryFrom<BarPriv> for u8 {
+        type Error = ();
+        fn try_from(o: BarPriv) -> Result<Self, ()> {
+            unimplemented!()
+        }
+    }
+
+    impl<'a> TryFrom<BarPub> for u8 {
+        type Error = ();
+        fn try_from(o: BarPub) -> Result<Self, ()> {
+            unimplemented!()
+        }
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/lint/issue-111359.stderr b/tests/ui/lint/issue-111359.stderr
new file mode 100644
index 00000000000..2296d8413d6
--- /dev/null
+++ b/tests/ui/lint/issue-111359.stderr
@@ -0,0 +1,26 @@
+error: type does not implement `Debug`; consider adding `#[derive(Debug)]` or a manual implementation
+  --> $DIR/issue-111359.rs:7:5
+   |
+LL |     pub struct BarPub;
+   |     ^^^^^^^^^^^^^^^^^^
+   |
+note: the lint level is defined here
+  --> $DIR/issue-111359.rs:1:8
+   |
+LL | #[deny(missing_debug_implementations)]
+   |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: type could implement `Copy`; consider adding `impl Copy`
+  --> $DIR/issue-111359.rs:7:5
+   |
+LL |     pub struct BarPub;
+   |     ^^^^^^^^^^^^^^^^^^
+   |
+note: the lint level is defined here
+  --> $DIR/issue-111359.rs:2:8
+   |
+LL | #[deny(missing_copy_implementations)]
+   |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/lint/unused/auxiliary/must-use-foreign.rs b/tests/ui/lint/unused/auxiliary/must-use-foreign.rs
new file mode 100644
index 00000000000..f773f09c382
--- /dev/null
+++ b/tests/ui/lint/unused/auxiliary/must-use-foreign.rs
@@ -0,0 +1,12 @@
+// edition:2021
+
+use std::future::Future;
+
+pub struct Manager;
+
+impl Manager {
+    #[must_use]
+    pub async fn new() -> (Self, impl Future<Output = ()>) {
+        (Manager, async {})
+    }
+}
diff --git a/tests/ui/lint/unused/must-use-foreign.rs b/tests/ui/lint/unused/must-use-foreign.rs
new file mode 100644
index 00000000000..21a11058562
--- /dev/null
+++ b/tests/ui/lint/unused/must-use-foreign.rs
@@ -0,0 +1,15 @@
+// edition:2021
+// aux-build:must-use-foreign.rs
+// check-pass
+
+extern crate must_use_foreign;
+
+use must_use_foreign::Manager;
+
+async fn async_main() {
+    Manager::new().await.1.await;
+}
+
+fn main() {
+    let _ = async_main();
+}
diff --git a/tests/ui/lint/unused/unused-async.rs b/tests/ui/lint/unused/unused-async.rs
index 4be93aa155a..6355f47f037 100644
--- a/tests/ui/lint/unused/unused-async.rs
+++ b/tests/ui/lint/unused/unused-async.rs
@@ -33,7 +33,7 @@ async fn test() {
     foo().await; //~ ERROR unused output of future returned by `foo` that must be used
     bar(); //~ ERROR unused return value of `bar` that must be used
     //~^ ERROR unused implementer of `Future` that must be used
-    bar().await; //~ ERROR unused output of future returned by `bar` that must be used
+    bar().await; // ok, it's not an async fn
     baz(); //~ ERROR unused implementer of `Future` that must be used
     baz().await; // ok
 }
diff --git a/tests/ui/lint/unused/unused-async.stderr b/tests/ui/lint/unused/unused-async.stderr
index 1c3702ba265..e93a40658f3 100644
--- a/tests/ui/lint/unused/unused-async.stderr
+++ b/tests/ui/lint/unused/unused-async.stderr
@@ -52,17 +52,6 @@ help: use `let _ = ...` to ignore the resulting value
 LL |     let _ = bar();
    |     +++++++
 
-error: unused output of future returned by `bar` that must be used
-  --> $DIR/unused-async.rs:36:5
-   |
-LL |     bar().await;
-   |     ^^^^^^^^^^^
-   |
-help: use `let _ = ...` to ignore the resulting value
-   |
-LL |     let _ = bar().await;
-   |     +++++++
-
 error: unused implementer of `Future` that must be used
   --> $DIR/unused-async.rs:37:5
    |
@@ -71,5 +60,5 @@ LL |     baz();
    |
    = note: futures do nothing unless you `.await` or poll them
 
-error: aborting due to 7 previous errors
+error: aborting due to 6 previous errors
 
diff --git a/tests/ui/liveness/liveness-unused.rs b/tests/ui/liveness/liveness-unused.rs
index 9c7be15fcc8..ba635e6638c 100644
--- a/tests/ui/liveness/liveness-unused.rs
+++ b/tests/ui/liveness/liveness-unused.rs
@@ -1,7 +1,7 @@
 #![warn(unused)]
 #![deny(unused_variables)]
 #![deny(unused_assignments)]
-#![allow(dead_code, non_camel_case_types, trivial_numeric_casts)]
+#![allow(dead_code, non_camel_case_types, trivial_numeric_casts, dropping_copy_types)]
 
 use std::ops::AddAssign;
 
diff --git a/tests/ui/macros/builtin-prelude-no-accidents.stderr b/tests/ui/macros/builtin-prelude-no-accidents.stderr
index 56af618d484..8cd9a63b808 100644
--- a/tests/ui/macros/builtin-prelude-no-accidents.stderr
+++ b/tests/ui/macros/builtin-prelude-no-accidents.stderr
@@ -4,18 +4,21 @@ error[E0433]: failed to resolve: use of undeclared crate or module `env`
 LL |     env::current_dir;
    |     ^^^ use of undeclared crate or module `env`
 
+error[E0433]: failed to resolve: use of undeclared crate or module `vec`
+  --> $DIR/builtin-prelude-no-accidents.rs:7:14
+   |
+LL |     type B = vec::Vec<u8>;
+   |              ^^^
+   |              |
+   |              use of undeclared crate or module `vec`
+   |              help: a struct with a similar name exists (notice the capitalization): `Vec`
+
 error[E0433]: failed to resolve: use of undeclared crate or module `panic`
   --> $DIR/builtin-prelude-no-accidents.rs:6:14
    |
 LL |     type A = panic::PanicInfo;
    |              ^^^^^ use of undeclared crate or module `panic`
 
-error[E0433]: failed to resolve: use of undeclared crate or module `vec`
-  --> $DIR/builtin-prelude-no-accidents.rs:7:14
-   |
-LL |     type B = vec::Vec<u8>;
-   |              ^^^ use of undeclared crate or module `vec`
-
 error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0433`.
diff --git a/tests/ui/macros/issue-111749.rs b/tests/ui/macros/issue-111749.rs
new file mode 100644
index 00000000000..6c45e4e8cd7
--- /dev/null
+++ b/tests/ui/macros/issue-111749.rs
@@ -0,0 +1,12 @@
+macro_rules! cbor_map {
+    ($key:expr) => {
+        $key.signum();
+    };
+}
+
+fn main() {
+    cbor_map! { #[test(test)] 4};
+    //~^ ERROR removing an expression is not supported in this position
+    //~| ERROR attribute must be of the form `#[test]`
+    //~| WARNING this was previously accepted by the compiler but is being phased out
+}
diff --git a/tests/ui/macros/issue-111749.stderr b/tests/ui/macros/issue-111749.stderr
new file mode 100644
index 00000000000..7db2b8e6ad1
--- /dev/null
+++ b/tests/ui/macros/issue-111749.stderr
@@ -0,0 +1,18 @@
+error: removing an expression is not supported in this position
+  --> $DIR/issue-111749.rs:8:17
+   |
+LL |     cbor_map! { #[test(test)] 4};
+   |                 ^^^^^^^^^^^^^
+
+error: attribute must be of the form `#[test]`
+  --> $DIR/issue-111749.rs:8:17
+   |
+LL |     cbor_map! { #[test(test)] 4};
+   |                 ^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #57571 <https://github.com/rust-lang/rust/issues/57571>
+   = note: `#[deny(ill_formed_attribute_input)]` on by default
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/macros/panic-temporaries-2018.rs b/tests/ui/macros/panic-temporaries-2018.rs
new file mode 100644
index 00000000000..d914df38062
--- /dev/null
+++ b/tests/ui/macros/panic-temporaries-2018.rs
@@ -0,0 +1,55 @@
+// check-pass
+// edition:2018
+
+#![allow(non_fmt_panics, unreachable_code)]
+
+use std::fmt::{self, Display};
+use std::marker::PhantomData;
+
+struct NotSend {
+    marker: PhantomData<*const u8>,
+}
+
+const NOT_SEND: NotSend = NotSend { marker: PhantomData };
+
+impl Display for NotSend {
+    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+        formatter.write_str("this value does not implement Send")
+    }
+}
+
+async fn f(_: u8) {}
+
+// Exercises this matcher in panic_2015:
+// ($fmt:expr, $($arg:tt)+) => $crate::panicking::panic_fmt(...)
+async fn panic_fmt() {
+    // Panic returns `!`, so the await is never reached, and in particular the
+    // temporaries inside the formatting machinery are not still alive at the
+    // await point.
+    let todo = "...";
+    f(panic!("not yet implemented: {}", todo)).await;
+}
+
+// Exercises ("{}", $arg:expr) => $crate::panicking::panic_display(&$arg)
+async fn panic_display() {
+    f(panic!("{}", NOT_SEND)).await;
+}
+
+// Exercises ($msg:expr) => $crate::panicking::panic_str($msg)
+async fn panic_str() {
+    f(panic!((NOT_SEND, "...").1)).await;
+}
+
+// Exercises ($msg:expr) => $crate::panicking::unreachable_display(&$msg)
+async fn unreachable_display() {
+    f(unreachable!(NOT_SEND)).await;
+}
+
+fn require_send(_: impl Send) {}
+
+fn main() {
+    require_send(panic_fmt());
+    require_send(panic_display());
+    require_send(panic_str());
+    require_send(unreachable_display());
+}
diff --git a/tests/ui/macros/panic-temporaries.rs b/tests/ui/macros/panic-temporaries.rs
new file mode 100644
index 00000000000..db65601fb73
--- /dev/null
+++ b/tests/ui/macros/panic-temporaries.rs
@@ -0,0 +1,43 @@
+// check-pass
+// edition:2021
+
+#![allow(unreachable_code)]
+
+use std::fmt::{self, Display};
+use std::marker::PhantomData;
+
+struct NotSend {
+    marker: PhantomData<*const u8>,
+}
+
+const NOT_SEND: NotSend = NotSend { marker: PhantomData };
+
+impl Display for NotSend {
+    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+        formatter.write_str("this value does not implement Send")
+    }
+}
+
+async fn f(_: u8) {}
+
+// Exercises this matcher in panic_2021:
+// ($($t:tt)+) => $crate::panicking::panic_fmt(...)
+async fn panic_fmt() {
+    // Panic returns `!`, so the await is never reached, and in particular the
+    // temporaries inside the formatting machinery are not still alive at the
+    // await point.
+    let todo = "...";
+    f(panic!("not yet implemented: {}", todo)).await;
+}
+
+// Exercises ("{}", $arg:expr) => $crate::panicking::panic_display(&$arg)
+async fn panic_display() {
+    f(panic!("{}", NOT_SEND)).await;
+}
+
+fn require_send(_: impl Send) {}
+
+fn main() {
+    require_send(panic_fmt());
+    require_send(panic_display());
+}
diff --git a/tests/ui/macros/parse-complex-macro-invoc-op.rs b/tests/ui/macros/parse-complex-macro-invoc-op.rs
index 8fef9b0ed87..10810388d20 100644
--- a/tests/ui/macros/parse-complex-macro-invoc-op.rs
+++ b/tests/ui/macros/parse-complex-macro-invoc-op.rs
@@ -4,6 +4,7 @@
 #![allow(unused_assignments)]
 #![allow(unused_variables)]
 #![allow(stable_features)]
+#![allow(dropping_copy_types)]
 
 // Test parsing binary operators after macro invocations.
 
diff --git a/tests/ui/macros/rfc-2011-nicer-assert-messages/non-consuming-methods-have-optimized-codegen.stdout b/tests/ui/macros/rfc-2011-nicer-assert-messages/non-consuming-methods-have-optimized-codegen.stdout
index ad97f7a4a75..b69b5bc3b53 100644
--- a/tests/ui/macros/rfc-2011-nicer-assert-messages/non-consuming-methods-have-optimized-codegen.stdout
+++ b/tests/ui/macros/rfc-2011-nicer-assert-messages/non-consuming-methods-have-optimized-codegen.stdout
@@ -26,7 +26,7 @@ fn arbitrary_consuming_method_for_demonstration_purposes() {
 
                 {
                     ::std::rt::panic_fmt(format_args!("Assertion failed: elem as usize\nWith captures:\n  elem = {0:?}\n",
-                            __capture0))
+                            __capture0));
                 }
             }
     };
@@ -42,7 +42,7 @@ fn addr_of() {
                 (&::core::asserting::Wrapper(__local_bind0)).try_capture(&mut __capture0);
                 {
                     ::std::rt::panic_fmt(format_args!("Assertion failed: &elem\nWith captures:\n  elem = {0:?}\n",
-                            __capture0))
+                            __capture0));
                 }
             }
     };
@@ -58,7 +58,7 @@ fn binary() {
                 (&::core::asserting::Wrapper(__local_bind0)).try_capture(&mut __capture0);
                 {
                     ::std::rt::panic_fmt(format_args!("Assertion failed: elem == 1\nWith captures:\n  elem = {0:?}\n",
-                            __capture0))
+                            __capture0));
                 }
             }
     };
@@ -71,7 +71,7 @@ fn binary() {
                 (&::core::asserting::Wrapper(__local_bind0)).try_capture(&mut __capture0);
                 {
                     ::std::rt::panic_fmt(format_args!("Assertion failed: elem >= 1\nWith captures:\n  elem = {0:?}\n",
-                            __capture0))
+                            __capture0));
                 }
             }
     };
@@ -84,7 +84,7 @@ fn binary() {
                 (&::core::asserting::Wrapper(__local_bind0)).try_capture(&mut __capture0);
                 {
                     ::std::rt::panic_fmt(format_args!("Assertion failed: elem > 0\nWith captures:\n  elem = {0:?}\n",
-                            __capture0))
+                            __capture0));
                 }
             }
     };
@@ -97,7 +97,7 @@ fn binary() {
                 (&::core::asserting::Wrapper(__local_bind0)).try_capture(&mut __capture0);
                 {
                     ::std::rt::panic_fmt(format_args!("Assertion failed: elem < 3\nWith captures:\n  elem = {0:?}\n",
-                            __capture0))
+                            __capture0));
                 }
             }
     };
@@ -110,7 +110,7 @@ fn binary() {
                 (&::core::asserting::Wrapper(__local_bind0)).try_capture(&mut __capture0);
                 {
                     ::std::rt::panic_fmt(format_args!("Assertion failed: elem <= 3\nWith captures:\n  elem = {0:?}\n",
-                            __capture0))
+                            __capture0));
                 }
             }
     };
@@ -123,7 +123,7 @@ fn binary() {
                 (&::core::asserting::Wrapper(__local_bind0)).try_capture(&mut __capture0);
                 {
                     ::std::rt::panic_fmt(format_args!("Assertion failed: elem != 3\nWith captures:\n  elem = {0:?}\n",
-                            __capture0))
+                            __capture0));
                 }
             }
     };
@@ -139,7 +139,7 @@ fn unary() {
                 (&::core::asserting::Wrapper(__local_bind0)).try_capture(&mut __capture0);
                 {
                     ::std::rt::panic_fmt(format_args!("Assertion failed: *elem\nWith captures:\n  elem = {0:?}\n",
-                            __capture0))
+                            __capture0));
                 }
             }
     };
diff --git a/tests/ui/mismatched_types/cast-rfc0401.stderr b/tests/ui/mismatched_types/cast-rfc0401.stderr
index 2a36a352c73..6b9ac3c5852 100644
--- a/tests/ui/mismatched_types/cast-rfc0401.stderr
+++ b/tests/ui/mismatched_types/cast-rfc0401.stderr
@@ -220,11 +220,7 @@ LL |     let _ = fat_v as *const dyn Foo;
    |             ^^^^^ doesn't have a size known at compile-time
    |
    = help: the trait `Sized` is not implemented for `[u8]`
-   = note: required for the cast from `[u8]` to the object type `dyn Foo`
-help: consider borrowing the value, since `&[u8]` can be coerced into `dyn Foo`
-   |
-LL |     let _ = &fat_v as *const dyn Foo;
-   |             +
+   = note: required for the cast from `*const [u8]` to `*const dyn Foo`
 
 error[E0277]: the size for values of type `str` cannot be known at compilation time
   --> $DIR/cast-rfc0401.rs:62:13
@@ -233,11 +229,7 @@ LL |     let _ = a as *const dyn Foo;
    |             ^ doesn't have a size known at compile-time
    |
    = help: the trait `Sized` is not implemented for `str`
-   = note: required for the cast from `str` to the object type `dyn Foo`
-help: consider borrowing the value, since `&str` can be coerced into `dyn Foo`
-   |
-LL |     let _ = &a as *const dyn Foo;
-   |             +
+   = note: required for the cast from `*const str` to `*const dyn Foo`
 
 error[E0606]: casting `&{float}` as `f32` is invalid
   --> $DIR/cast-rfc0401.rs:71:30
diff --git a/tests/ui/never_type/fallback-closure-wrap.fallback.stderr b/tests/ui/never_type/fallback-closure-wrap.fallback.stderr
index a0f790dba15..5b6f0235123 100644
--- a/tests/ui/never_type/fallback-closure-wrap.fallback.stderr
+++ b/tests/ui/never_type/fallback-closure-wrap.fallback.stderr
@@ -10,7 +10,7 @@ LL | |     }) as Box<dyn FnMut()>);
    |
    = note: expected unit type `()`
                    found type `!`
-   = note: required for the cast from `[closure@$DIR/fallback-closure-wrap.rs:18:40: 18:47]` to the object type `dyn FnMut()`
+   = note: required for the cast from `Box<[closure@$DIR/fallback-closure-wrap.rs:18:40: 18:47]>` to `Box<dyn FnMut()>`
 
 error: aborting due to previous error
 
diff --git a/tests/ui/never_type/never-assign-dead-code.rs b/tests/ui/never_type/never-assign-dead-code.rs
index 7bb7c87097c..39df7de5a7f 100644
--- a/tests/ui/never_type/never-assign-dead-code.rs
+++ b/tests/ui/never_type/never-assign-dead-code.rs
@@ -3,6 +3,7 @@
 // check-pass
 
 #![feature(never_type)]
+#![allow(dropping_copy_types)]
 #![warn(unused)]
 
 fn main() {
diff --git a/tests/ui/never_type/never-assign-dead-code.stderr b/tests/ui/never_type/never-assign-dead-code.stderr
index 521b82023c9..5660bde5c27 100644
--- a/tests/ui/never_type/never-assign-dead-code.stderr
+++ b/tests/ui/never_type/never-assign-dead-code.stderr
@@ -1,5 +1,5 @@
 warning: unreachable statement
-  --> $DIR/never-assign-dead-code.rs:10:5
+  --> $DIR/never-assign-dead-code.rs:11:5
    |
 LL |     let x: ! = panic!("aah");
    |                ------------- any code following this expression is unreachable
@@ -7,14 +7,14 @@ LL |     drop(x);
    |     ^^^^^^^^ unreachable statement
    |
 note: the lint level is defined here
-  --> $DIR/never-assign-dead-code.rs:6:9
+  --> $DIR/never-assign-dead-code.rs:7:9
    |
 LL | #![warn(unused)]
    |         ^^^^^^
    = note: `#[warn(unreachable_code)]` implied by `#[warn(unused)]`
 
 warning: unreachable call
-  --> $DIR/never-assign-dead-code.rs:10:5
+  --> $DIR/never-assign-dead-code.rs:11:5
    |
 LL |     drop(x);
    |     ^^^^ - any code following this expression is unreachable
@@ -22,7 +22,7 @@ LL |     drop(x);
    |     unreachable call
 
 warning: unused variable: `x`
-  --> $DIR/never-assign-dead-code.rs:9:9
+  --> $DIR/never-assign-dead-code.rs:10:9
    |
 LL |     let x: ! = panic!("aah");
    |         ^ help: if this is intentional, prefix it with an underscore: `_x`
diff --git a/tests/ui/nll/relate_tys/hr-fn-aba-as-aaa.rs b/tests/ui/nll/relate_tys/hr-fn-aba-as-aaa.rs
index 7cc0acf45f2..2e9eff59386 100644
--- a/tests/ui/nll/relate_tys/hr-fn-aba-as-aaa.rs
+++ b/tests/ui/nll/relate_tys/hr-fn-aba-as-aaa.rs
@@ -5,6 +5,8 @@
 // check-pass
 // compile-flags:-Zno-leak-check
 
+#![allow(dropping_copy_types)]
+
 fn make_it() -> for<'a, 'b> fn(&'a u32, &'b u32) -> &'a u32 {
     panic!()
 }
diff --git a/tests/ui/nll/ty-outlives/projection-body.rs b/tests/ui/nll/ty-outlives/projection-body.rs
index b03a539ebdb..722d6747102 100644
--- a/tests/ui/nll/ty-outlives/projection-body.rs
+++ b/tests/ui/nll/ty-outlives/projection-body.rs
@@ -3,6 +3,8 @@
 //
 // check-pass
 
+#![allow(dropping_references)]
+
 trait MyTrait<'a> {
     type Output;
 }
diff --git a/tests/ui/numbers-arithmetic/overflow-attribute-works-1.rs b/tests/ui/numbers-arithmetic/overflow-attribute-works-1.rs
new file mode 100644
index 00000000000..318be2a6401
--- /dev/null
+++ b/tests/ui/numbers-arithmetic/overflow-attribute-works-1.rs
@@ -0,0 +1,19 @@
+// run-pass
+// compile-flags: -C overflow_checks=true
+
+#![feature(cfg_overflow_checks)]
+
+fn main() {
+    assert!(cfg!(overflow_checks));
+    assert!(compiles_differently());
+}
+
+#[cfg(overflow_checks)]
+fn compiles_differently()->bool {
+    true
+}
+
+#[cfg(not(overflow_checks))]
+fn compiles_differently()->bool {
+    false
+}
diff --git a/tests/ui/numbers-arithmetic/overflow-attribute-works-2.rs b/tests/ui/numbers-arithmetic/overflow-attribute-works-2.rs
new file mode 100644
index 00000000000..0367d980a64
--- /dev/null
+++ b/tests/ui/numbers-arithmetic/overflow-attribute-works-2.rs
@@ -0,0 +1,19 @@
+// run-pass
+// compile-flags: -C overflow_checks=false
+
+#![feature(cfg_overflow_checks)]
+
+fn main() {
+    assert!(!cfg!(overflow_checks));
+    assert!(!compiles_differently());
+}
+
+#[cfg(overflow_checks)]
+fn compiles_differently()->bool {
+    true
+}
+
+#[cfg(not(overflow_checks))]
+fn compiles_differently()->bool {
+    false
+}
diff --git a/tests/ui/object-safety/issue-19538.stderr b/tests/ui/object-safety/issue-19538.stderr
index 8420637b3de..183245b2322 100644
--- a/tests/ui/object-safety/issue-19538.stderr
+++ b/tests/ui/object-safety/issue-19538.stderr
@@ -29,8 +29,7 @@ LL |     fn foo<T>(&self, val: T);
 LL | trait Bar: Foo { }
    |       --- this trait cannot be made into an object...
    = help: consider moving `foo` to another trait
-   = note: required for `&mut Thing` to implement `CoerceUnsized<&mut dyn Bar>`
-   = note: required by cast to type `&mut dyn Bar`
+   = note: required for the cast from `&mut Thing` to `&mut dyn Bar`
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/object-safety/object-safety-associated-consts.object_safe_for_dispatch.stderr b/tests/ui/object-safety/object-safety-associated-consts.object_safe_for_dispatch.stderr
index f44de07d5da..db3e0885a85 100644
--- a/tests/ui/object-safety/object-safety-associated-consts.object_safe_for_dispatch.stderr
+++ b/tests/ui/object-safety/object-safety-associated-consts.object_safe_for_dispatch.stderr
@@ -12,8 +12,7 @@ LL | trait Bar {
 LL |     const X: usize;
    |           ^ ...because it contains this associated `const`
    = help: consider moving `X` to another trait
-   = note: required for `&T` to implement `CoerceUnsized<&dyn Bar>`
-   = note: required by cast to type `&dyn Bar`
+   = note: required for the cast from `&T` to `&dyn Bar`
 
 error: aborting due to previous error
 
diff --git a/tests/ui/object-safety/object-safety-generics.object_safe_for_dispatch.stderr b/tests/ui/object-safety/object-safety-generics.object_safe_for_dispatch.stderr
index 9a2d472d5e7..b200b64a1f0 100644
--- a/tests/ui/object-safety/object-safety-generics.object_safe_for_dispatch.stderr
+++ b/tests/ui/object-safety/object-safety-generics.object_safe_for_dispatch.stderr
@@ -12,8 +12,7 @@ LL | trait Bar {
 LL |     fn bar<T>(&self, t: T);
    |        ^^^ ...because method `bar` has generic type parameters
    = help: consider moving `bar` to another trait
-   = note: required for `&T` to implement `CoerceUnsized<&dyn Bar>`
-   = note: required by cast to type `&dyn Bar`
+   = note: required for the cast from `&T` to `&dyn Bar`
 
 error[E0038]: the trait `Bar` cannot be made into an object
   --> $DIR/object-safety-generics.rs:26:5
@@ -29,8 +28,7 @@ LL | trait Bar {
 LL |     fn bar<T>(&self, t: T);
    |        ^^^ ...because method `bar` has generic type parameters
    = help: consider moving `bar` to another trait
-   = note: required for `&T` to implement `CoerceUnsized<&dyn Bar>`
-   = note: required by cast to type `&dyn Bar`
+   = note: required for the cast from `&T` to `&dyn Bar`
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/object-safety/object-safety-mentions-Self.object_safe_for_dispatch.stderr b/tests/ui/object-safety/object-safety-mentions-Self.object_safe_for_dispatch.stderr
index 40a298bd1a7..414614d8d0b 100644
--- a/tests/ui/object-safety/object-safety-mentions-Self.object_safe_for_dispatch.stderr
+++ b/tests/ui/object-safety/object-safety-mentions-Self.object_safe_for_dispatch.stderr
@@ -12,8 +12,7 @@ LL | trait Bar {
 LL |     fn bar(&self, x: &Self);
    |                      ^^^^^ ...because method `bar` references the `Self` type in this parameter
    = help: consider moving `bar` to another trait
-   = note: required for `&T` to implement `CoerceUnsized<&dyn Bar>`
-   = note: required by cast to type `&dyn Bar`
+   = note: required for the cast from `&T` to `&dyn Bar`
 
 error[E0038]: the trait `Baz` cannot be made into an object
   --> $DIR/object-safety-mentions-Self.rs:30:5
@@ -29,8 +28,7 @@ LL | trait Baz {
 LL |     fn baz(&self) -> Self;
    |                      ^^^^ ...because method `baz` references the `Self` type in its return type
    = help: consider moving `baz` to another trait
-   = note: required for `&T` to implement `CoerceUnsized<&dyn Baz>`
-   = note: required by cast to type `&dyn Baz`
+   = note: required for the cast from `&T` to `&dyn Baz`
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/object-safety/object-safety-no-static.object_safe_for_dispatch.stderr b/tests/ui/object-safety/object-safety-no-static.object_safe_for_dispatch.stderr
index da87b58c9e2..befcef952a8 100644
--- a/tests/ui/object-safety/object-safety-no-static.object_safe_for_dispatch.stderr
+++ b/tests/ui/object-safety/object-safety-no-static.object_safe_for_dispatch.stderr
@@ -11,8 +11,7 @@ LL | trait Foo {
    |       --- this trait cannot be made into an object...
 LL |     fn foo() {}
    |        ^^^ ...because associated function `foo` has no `self` parameter
-   = note: required for `Box<Bar>` to implement `CoerceUnsized<Box<dyn Foo>>`
-   = note: required by cast to type `Box<dyn Foo>`
+   = note: required for the cast from `Box<Bar>` to `Box<dyn Foo>`
 help: consider turning `foo` into a method by giving it a `&self` argument
    |
 LL |     fn foo(&self) {}
diff --git a/tests/ui/object-safety/object-safety-sized-2.object_safe_for_dispatch.stderr b/tests/ui/object-safety/object-safety-sized-2.object_safe_for_dispatch.stderr
index 6c29c8d5f7c..90e5c59dd02 100644
--- a/tests/ui/object-safety/object-safety-sized-2.object_safe_for_dispatch.stderr
+++ b/tests/ui/object-safety/object-safety-sized-2.object_safe_for_dispatch.stderr
@@ -11,8 +11,7 @@ LL | trait Bar
    |       --- this trait cannot be made into an object...
 LL |     where Self : Sized
    |                  ^^^^^ ...because it requires `Self: Sized`
-   = note: required for `&T` to implement `CoerceUnsized<&dyn Bar>`
-   = note: required by cast to type `&dyn Bar`
+   = note: required for the cast from `&T` to `&dyn Bar`
 
 error: aborting due to previous error
 
diff --git a/tests/ui/object-safety/object-safety-sized.object_safe_for_dispatch.stderr b/tests/ui/object-safety/object-safety-sized.object_safe_for_dispatch.stderr
index 70a44ed6101..a6c22b8747e 100644
--- a/tests/ui/object-safety/object-safety-sized.object_safe_for_dispatch.stderr
+++ b/tests/ui/object-safety/object-safety-sized.object_safe_for_dispatch.stderr
@@ -11,8 +11,7 @@ LL | trait Bar : Sized {
    |       ---   ^^^^^ ...because it requires `Self: Sized`
    |       |
    |       this trait cannot be made into an object...
-   = note: required for `&T` to implement `CoerceUnsized<&dyn Bar>`
-   = note: required by cast to type `&dyn Bar`
+   = note: required for the cast from `&T` to `&dyn Bar`
 
 error: aborting due to previous error
 
diff --git a/tests/ui/offset-of/offset-of-arg-count.rs b/tests/ui/offset-of/offset-of-arg-count.rs
index 5e66e33f8a2..31de45bc756 100644
--- a/tests/ui/offset-of/offset-of-arg-count.rs
+++ b/tests/ui/offset-of/offset-of-arg-count.rs
@@ -12,6 +12,11 @@ fn main() {
     offset_of!(S, f.,); //~ ERROR expected identifier
     offset_of!(S, f..); //~ ERROR no rules expected the token
     offset_of!(S, f..,); //~ ERROR no rules expected the token
+    offset_of!(Lt<'static>, bar); // issue #111657
+    offset_of!(Lt<'_>, bar); // issue #111678
 }
 
 struct S { f: u8, }
+struct Lt<'a> {
+    bar: &'a (),
+}
diff --git a/tests/ui/offset-of/offset-of-dst-field.rs b/tests/ui/offset-of/offset-of-dst-field.rs
index a0269ca2d12..3b8dc0b84a4 100644
--- a/tests/ui/offset-of/offset-of-dst-field.rs
+++ b/tests/ui/offset-of/offset-of-dst-field.rs
@@ -26,8 +26,24 @@ struct Gamma {
     z: Extern,
 }
 
+struct Delta<T: ?Sized> {
+    x: u8,
+    y: u16,
+    z: T,
+}
+
 fn main() {
     offset_of!(Alpha, z); //~ ERROR the size for values of type
     offset_of!(Beta, z); //~ ERROR the size for values of type
     offset_of!(Gamma, z); //~ ERROR the size for values of type
 }
+
+fn delta() {
+    offset_of!(Delta<Alpha>, z); //~ ERROR the size for values of type
+    offset_of!(Delta<Extern>, z); //~ ERROR the size for values of type
+    offset_of!(Delta<dyn Trait>, z); //~ ERROR the size for values of type
+}
+
+fn generic_with_maybe_sized<T: ?Sized>() -> usize {
+    offset_of!(Delta<T>, z) //~ ERROR the size for values of type
+}
diff --git a/tests/ui/offset-of/offset-of-dst-field.stderr b/tests/ui/offset-of/offset-of-dst-field.stderr
index e6e0f499236..128c783d5dd 100644
--- a/tests/ui/offset-of/offset-of-dst-field.stderr
+++ b/tests/ui/offset-of/offset-of-dst-field.stderr
@@ -1,5 +1,5 @@
 error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
-  --> $DIR/offset-of-dst-field.rs:30:5
+  --> $DIR/offset-of-dst-field.rs:36:5
    |
 LL |     offset_of!(Alpha, z);
    |     ^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
@@ -8,7 +8,7 @@ LL |     offset_of!(Alpha, z);
    = note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0277]: the size for values of type `(dyn Trait + 'static)` cannot be known at compilation time
-  --> $DIR/offset-of-dst-field.rs:31:5
+  --> $DIR/offset-of-dst-field.rs:37:5
    |
 LL |     offset_of!(Beta, z);
    |     ^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
@@ -17,7 +17,7 @@ LL |     offset_of!(Beta, z);
    = note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0277]: the size for values of type `Extern` cannot be known at compilation time
-  --> $DIR/offset-of-dst-field.rs:32:5
+  --> $DIR/offset-of-dst-field.rs:38:5
    |
 LL |     offset_of!(Gamma, z);
    |     ^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
@@ -25,6 +25,53 @@ LL |     offset_of!(Gamma, z);
    = help: the trait `Sized` is not implemented for `Extern`
    = note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error: aborting due to 3 previous errors
+error[E0277]: the size for values of type `Extern` cannot be known at compilation time
+  --> $DIR/offset-of-dst-field.rs:43:5
+   |
+LL |     offset_of!(Delta<Extern>, z);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `Sized` is not implemented for `Extern`
+   = note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `dyn Trait` cannot be known at compilation time
+  --> $DIR/offset-of-dst-field.rs:44:5
+   |
+LL |     offset_of!(Delta<dyn Trait>, z);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `Sized` is not implemented for `dyn Trait`
+   = note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+  --> $DIR/offset-of-dst-field.rs:42:5
+   |
+LL |     offset_of!(Delta<Alpha>, z);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+   |
+   = help: within `Alpha`, the trait `Sized` is not implemented for `[u8]`
+note: required because it appears within the type `Alpha`
+  --> $DIR/offset-of-dst-field.rs:5:8
+   |
+LL | struct Alpha {
+   |        ^^^^^
+   = note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `T` cannot be known at compilation time
+  --> $DIR/offset-of-dst-field.rs:48:5
+   |
+LL | fn generic_with_maybe_sized<T: ?Sized>() -> usize {
+   |                             - this type parameter needs to be `std::marker::Sized`
+LL |     offset_of!(Delta<T>, z)
+   |     ^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+   |
+   = note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: consider removing the `?Sized` bound to make the type parameter `Sized`
+   |
+LL - fn generic_with_maybe_sized<T: ?Sized>() -> usize {
+LL + fn generic_with_maybe_sized<T>() -> usize {
+   |
+
+error: aborting due to 7 previous errors
 
 For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/offset-of/offset-of-inference.rs b/tests/ui/offset-of/offset-of-inference.rs
new file mode 100644
index 00000000000..ba87574eae0
--- /dev/null
+++ b/tests/ui/offset-of/offset-of-inference.rs
@@ -0,0 +1,11 @@
+// Test that inference types in `offset_of!` don't ICE.
+
+#![feature(offset_of)]
+
+struct Foo<T> {
+    x: T,
+}
+
+fn main() {
+    let _ = core::mem::offset_of!(Foo<_>, x); //~ ERROR: type annotations needed
+}
diff --git a/tests/ui/offset-of/offset-of-inference.stderr b/tests/ui/offset-of/offset-of-inference.stderr
new file mode 100644
index 00000000000..2a520f6f906
--- /dev/null
+++ b/tests/ui/offset-of/offset-of-inference.stderr
@@ -0,0 +1,9 @@
+error[E0282]: type annotations needed
+  --> $DIR/offset-of-inference.rs:10:35
+   |
+LL |     let _ = core::mem::offset_of!(Foo<_>, x);
+   |                                   ^^^^^^ cannot infer type
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/tests/ui/offset-of/offset-of-output-type.rs b/tests/ui/offset-of/offset-of-output-type.rs
new file mode 100644
index 00000000000..50c2e93841f
--- /dev/null
+++ b/tests/ui/offset-of/offset-of-output-type.rs
@@ -0,0 +1,20 @@
+#![feature(offset_of)]
+
+use std::mem::offset_of;
+
+struct S {
+    v: u8,
+    w: u16,
+}
+
+
+fn main() {
+    let _: u8 = offset_of!(S, v); //~ ERROR mismatched types
+    let _: u16 = offset_of!(S, v); //~ ERROR mismatched types
+    let _: u32 = offset_of!(S, v); //~ ERROR mismatched types
+    let _: u64 = offset_of!(S, v); //~ ERROR mismatched types
+    let _: isize = offset_of!(S, v); //~ ERROR mismatched types
+    let _: usize = offset_of!(S, v);
+
+    offset_of!(S, v) //~ ERROR mismatched types
+}
diff --git a/tests/ui/offset-of/offset-of-output-type.stderr b/tests/ui/offset-of/offset-of-output-type.stderr
new file mode 100644
index 00000000000..6f8c9475029
--- /dev/null
+++ b/tests/ui/offset-of/offset-of-output-type.stderr
@@ -0,0 +1,64 @@
+error[E0308]: mismatched types
+  --> $DIR/offset-of-output-type.rs:12:17
+   |
+LL |     let _: u8 = offset_of!(S, v);
+   |            --   ^^^^^^^^^^^^^^^^ expected `u8`, found `usize`
+   |            |
+   |            expected due to this
+   |
+   = note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0308]: mismatched types
+  --> $DIR/offset-of-output-type.rs:13:18
+   |
+LL |     let _: u16 = offset_of!(S, v);
+   |            ---   ^^^^^^^^^^^^^^^^ expected `u16`, found `usize`
+   |            |
+   |            expected due to this
+   |
+   = note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0308]: mismatched types
+  --> $DIR/offset-of-output-type.rs:14:18
+   |
+LL |     let _: u32 = offset_of!(S, v);
+   |            ---   ^^^^^^^^^^^^^^^^ expected `u32`, found `usize`
+   |            |
+   |            expected due to this
+   |
+   = note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0308]: mismatched types
+  --> $DIR/offset-of-output-type.rs:15:18
+   |
+LL |     let _: u64 = offset_of!(S, v);
+   |            ---   ^^^^^^^^^^^^^^^^ expected `u64`, found `usize`
+   |            |
+   |            expected due to this
+   |
+   = note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0308]: mismatched types
+  --> $DIR/offset-of-output-type.rs:16:20
+   |
+LL |     let _: isize = offset_of!(S, v);
+   |            -----   ^^^^^^^^^^^^^^^^ expected `isize`, found `usize`
+   |            |
+   |            expected due to this
+   |
+   = note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0308]: mismatched types
+  --> $DIR/offset-of-output-type.rs:19:5
+   |
+LL | fn main() {
+   |           - expected `()` because of default return type
+...
+LL |     offset_of!(S, v)
+   |     ^^^^^^^^^^^^^^^^ expected `()`, found `usize`
+   |
+   = note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 6 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/offset-of/offset-of-private.rs b/tests/ui/offset-of/offset-of-private.rs
index 0291b7825ca..6b1a16ba62b 100644
--- a/tests/ui/offset-of/offset-of-private.rs
+++ b/tests/ui/offset-of/offset-of-private.rs
@@ -8,9 +8,21 @@ mod m {
         pub public: u8,
         private: u8,
     }
+    #[repr(C)]
+    pub struct FooTuple(pub u8, u8);
+    #[repr(C)]
+    struct Bar {
+        pub public: u8,
+        private: u8,
+    }
 }
 
 fn main() {
     offset_of!(m::Foo, public);
     offset_of!(m::Foo, private); //~ ERROR field `private` of struct `Foo` is private
+    offset_of!(m::FooTuple, 0);
+    offset_of!(m::FooTuple, 1); //~ ERROR field `1` of struct `FooTuple` is private
+    offset_of!(m::Bar, public); //~ ERROR struct `Bar` is private
+    offset_of!(m::Bar, private); //~ ERROR struct `Bar` is private
+    //~| ERROR field `private` of struct `Bar` is private
 }
diff --git a/tests/ui/offset-of/offset-of-private.stderr b/tests/ui/offset-of/offset-of-private.stderr
index 8a186dd5a02..0674b58f860 100644
--- a/tests/ui/offset-of/offset-of-private.stderr
+++ b/tests/ui/offset-of/offset-of-private.stderr
@@ -1,9 +1,46 @@
+error[E0603]: struct `Bar` is private
+  --> $DIR/offset-of-private.rs:25:19
+   |
+LL |     offset_of!(m::Bar, public);
+   |                   ^^^ private struct
+   |
+note: the struct `Bar` is defined here
+  --> $DIR/offset-of-private.rs:14:5
+   |
+LL |     struct Bar {
+   |     ^^^^^^^^^^
+
+error[E0603]: struct `Bar` is private
+  --> $DIR/offset-of-private.rs:26:19
+   |
+LL |     offset_of!(m::Bar, private);
+   |                   ^^^ private struct
+   |
+note: the struct `Bar` is defined here
+  --> $DIR/offset-of-private.rs:14:5
+   |
+LL |     struct Bar {
+   |     ^^^^^^^^^^
+
 error[E0616]: field `private` of struct `Foo` is private
-  --> $DIR/offset-of-private.rs:15:24
+  --> $DIR/offset-of-private.rs:22:24
    |
 LL |     offset_of!(m::Foo, private);
    |                        ^^^^^^^ private field
 
-error: aborting due to previous error
+error[E0616]: field `1` of struct `FooTuple` is private
+  --> $DIR/offset-of-private.rs:24:29
+   |
+LL |     offset_of!(m::FooTuple, 1);
+   |                             ^ private field
+
+error[E0616]: field `private` of struct `Bar` is private
+  --> $DIR/offset-of-private.rs:26:24
+   |
+LL |     offset_of!(m::Bar, private);
+   |                        ^^^^^^^ private field
+
+error: aborting due to 5 previous errors
 
-For more information about this error, try `rustc --explain E0616`.
+Some errors have detailed explanations: E0603, E0616.
+For more information about an error, try `rustc --explain E0603`.
diff --git a/tests/ui/offset-of/offset-of-self.rs b/tests/ui/offset-of/offset-of-self.rs
new file mode 100644
index 00000000000..dbeef0e74dc
--- /dev/null
+++ b/tests/ui/offset-of/offset-of-self.rs
@@ -0,0 +1,58 @@
+#![feature(offset_of)]
+
+use std::mem::offset_of;
+
+struct C<T> {
+    v: T,
+    w: T,
+}
+
+struct S {
+    v: u8,
+    w: u16,
+}
+
+impl S {
+    fn v_offs() -> usize {
+        offset_of!(Self, v)
+    }
+    fn v_offs_wrong_syntax() {
+        offset_of!(Self, Self::v); //~ ERROR no rules expected the token `::`
+        offset_of!(S, Self); //~ ERROR expected identifier, found keyword `Self`
+        //~| no field `Self` on type `S`
+    }
+    fn offs_in_c() -> usize {
+        offset_of!(C<Self>, w)
+    }
+    fn offs_in_c_colon() -> usize {
+        offset_of!(C::<Self>, w)
+    }
+}
+
+mod m {
+    use std::mem::offset_of;
+    fn off() {
+        offset_of!(self::S, v); //~ ERROR cannot find type `S` in module
+        offset_of!(super::S, v);
+        offset_of!(crate::S, v);
+    }
+    impl super::n::T {
+        fn v_offs_self() -> usize {
+            offset_of!(Self, v) //~ ERROR field `v` of struct `T` is private
+        }
+    }
+}
+
+mod n {
+    pub struct T { v: u8, }
+}
+
+fn main() {
+    offset_of!(self::S, v);
+    offset_of!(Self, v); //~ ERROR cannot find type `Self` in this scope
+
+    offset_of!(S, self); //~ ERROR expected identifier, found keyword `self`
+    //~| no field `self` on type `S`
+    offset_of!(S, v.self); //~ ERROR expected identifier, found keyword `self`
+    //~| no field `self` on type `u8`
+}
diff --git a/tests/ui/offset-of/offset-of-self.stderr b/tests/ui/offset-of/offset-of-self.stderr
new file mode 100644
index 00000000000..df555463f98
--- /dev/null
+++ b/tests/ui/offset-of/offset-of-self.stderr
@@ -0,0 +1,79 @@
+error: no rules expected the token `::`
+  --> $DIR/offset-of-self.rs:20:30
+   |
+LL |         offset_of!(Self, Self::v);
+   |                              ^^ no rules expected this token in macro call
+   |
+   = note: while trying to match sequence start
+
+error: expected identifier, found keyword `Self`
+  --> $DIR/offset-of-self.rs:21:23
+   |
+LL |         offset_of!(S, Self);
+   |                       ^^^^ expected identifier, found keyword
+
+error: expected identifier, found keyword `self`
+  --> $DIR/offset-of-self.rs:54:19
+   |
+LL |     offset_of!(S, self);
+   |                   ^^^^ expected identifier, found keyword
+
+error: expected identifier, found keyword `self`
+  --> $DIR/offset-of-self.rs:56:21
+   |
+LL |     offset_of!(S, v.self);
+   |                     ^^^^ expected identifier, found keyword
+
+error[E0412]: cannot find type `S` in module `self`
+  --> $DIR/offset-of-self.rs:35:26
+   |
+LL |         offset_of!(self::S, v);
+   |                          ^ not found in `self`
+   |
+help: consider importing this struct
+   |
+LL +     use S;
+   |
+help: if you import `S`, refer to it directly
+   |
+LL -         offset_of!(self::S, v);
+LL +         offset_of!(S, v);
+   |
+
+error[E0411]: cannot find type `Self` in this scope
+  --> $DIR/offset-of-self.rs:52:16
+   |
+LL | fn main() {
+   |    ---- `Self` not allowed in a function
+LL |     offset_of!(self::S, v);
+LL |     offset_of!(Self, v);
+   |                ^^^^ `Self` is only available in impls, traits, and type definitions
+
+error[E0609]: no field `Self` on type `S`
+  --> $DIR/offset-of-self.rs:21:23
+   |
+LL |         offset_of!(S, Self);
+   |                       ^^^^
+
+error[E0616]: field `v` of struct `T` is private
+  --> $DIR/offset-of-self.rs:41:30
+   |
+LL |             offset_of!(Self, v)
+   |                              ^ private field
+
+error[E0609]: no field `self` on type `S`
+  --> $DIR/offset-of-self.rs:54:19
+   |
+LL |     offset_of!(S, self);
+   |                   ^^^^
+
+error[E0609]: no field `self` on type `u8`
+  --> $DIR/offset-of-self.rs:56:21
+   |
+LL |     offset_of!(S, v.self);
+   |                     ^^^^
+
+error: aborting due to 10 previous errors
+
+Some errors have detailed explanations: E0411, E0412, E0609, E0616.
+For more information about an error, try `rustc --explain E0411`.
diff --git a/tests/ui/or-patterns/or-patterns-default-binding-modes.rs b/tests/ui/or-patterns/or-patterns-default-binding-modes.rs
index e56f9ffe23c..df6aab0e6a8 100644
--- a/tests/ui/or-patterns/or-patterns-default-binding-modes.rs
+++ b/tests/ui/or-patterns/or-patterns-default-binding-modes.rs
@@ -3,6 +3,8 @@
 // check-pass
 
 #![allow(irrefutable_let_patterns)]
+#![allow(dropping_copy_types)]
+#![allow(dropping_references)]
 
 fn main() {
     // A regression test for a mistake we made at one point:
diff --git a/tests/ui/panics/default-backtrace-ice.stderr b/tests/ui/panics/default-backtrace-ice.stderr
index ddbfc4e7f3a..815ce4dd015 100644
--- a/tests/ui/panics/default-backtrace-ice.stderr
+++ b/tests/ui/panics/default-backtrace-ice.stderr
@@ -8,6 +8,8 @@ LL | fn main() { missing_ident; }
 stack backtrace:
 (end_short_backtrace)
 (begin_short_backtrace)
+(end_short_backtrace)
+(begin_short_backtrace)
 
 error: the compiler unexpectedly panicked. this is a bug.
 
diff --git a/tests/ui/panics/short-ice-remove-middle-frames-2.rs b/tests/ui/panics/short-ice-remove-middle-frames-2.rs
new file mode 100644
index 00000000000..38a80f8b670
--- /dev/null
+++ b/tests/ui/panics/short-ice-remove-middle-frames-2.rs
@@ -0,0 +1,61 @@
+// compile-flags:-Cstrip=none
+// run-fail
+// check-run-results
+// exec-env:RUST_BACKTRACE=1
+// ignore-android FIXME #17520
+// ignore-wasm no panic support
+// ignore-openbsd no support for libbacktrace without filename
+// ignore-emscripten no panic
+// ignore-sgx Backtraces not symbolized
+// ignore-fuchsia Backtraces not symbolized
+// ignore-msvc the `__rust_{begin,end}_short_backtrace` symbols aren't reliable.
+
+/// This test case make sure that we can have multiple pairs of `__rust_{begin,end}_short_backtrace`
+
+#[inline(never)]
+fn __rust_begin_short_backtrace<T, F: FnOnce() -> T>(f: F) -> T {
+    let result = f();
+    std::hint::black_box(result)
+}
+
+#[inline(never)]
+fn __rust_end_short_backtrace<T, F: FnOnce() -> T>(f: F) -> T {
+    let result = f();
+    std::hint::black_box(result)
+}
+
+fn first() {
+    __rust_end_short_backtrace(|| second());
+}
+
+fn second() {
+    third(); // won't show up
+}
+
+fn third() {
+    fourth(); // won't show up
+}
+
+fn fourth() {
+    __rust_begin_short_backtrace(|| fifth());
+}
+
+fn fifth() {
+    __rust_end_short_backtrace(|| sixth());
+}
+
+fn sixth() {
+    seven(); // won't show up
+}
+
+fn seven() {
+    __rust_begin_short_backtrace(|| eight());
+}
+
+fn eight() {
+    panic!("debug!!!");
+}
+
+fn main() {
+    first();
+}
diff --git a/tests/ui/panics/short-ice-remove-middle-frames-2.run.stderr b/tests/ui/panics/short-ice-remove-middle-frames-2.run.stderr
new file mode 100644
index 00000000000..2592b747918
--- /dev/null
+++ b/tests/ui/panics/short-ice-remove-middle-frames-2.run.stderr
@@ -0,0 +1,11 @@
+thread 'main' panicked at 'debug!!!', $DIR/short-ice-remove-middle-frames-2.rs:56:5
+stack backtrace:
+   0: std::panicking::begin_panic
+   1: short_ice_remove_middle_frames_2::eight
+   2: short_ice_remove_middle_frames_2::seven::{{closure}}
+   3: short_ice_remove_middle_frames_2::fifth
+   4: short_ice_remove_middle_frames_2::fourth::{{closure}}
+   5: short_ice_remove_middle_frames_2::first
+   6: short_ice_remove_middle_frames_2::main
+   7: core::ops::function::FnOnce::call_once
+note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
diff --git a/tests/ui/panics/short-ice-remove-middle-frames.rs b/tests/ui/panics/short-ice-remove-middle-frames.rs
new file mode 100644
index 00000000000..c872084f033
--- /dev/null
+++ b/tests/ui/panics/short-ice-remove-middle-frames.rs
@@ -0,0 +1,57 @@
+// compile-flags:-Cstrip=none
+// run-fail
+// check-run-results
+// exec-env:RUST_BACKTRACE=1
+// ignore-android FIXME #17520
+// ignore-wasm no panic support
+// ignore-openbsd no support for libbacktrace without filename
+// ignore-emscripten no panic
+// ignore-sgx Backtraces not symbolized
+// ignore-fuchsia Backtraces not symbolized
+// ignore-msvc the `__rust_{begin,end}_short_backtrace` symbols aren't reliable.
+
+
+#[inline(never)]
+fn __rust_begin_short_backtrace<T, F: FnOnce() -> T>(f: F) -> T {
+    let result = f();
+    std::hint::black_box(result)
+}
+
+#[inline(never)]
+fn __rust_end_short_backtrace<T, F: FnOnce() -> T>(f: F) -> T {
+    let result = f();
+    std::hint::black_box(result)
+}
+
+fn first() {
+    __rust_end_short_backtrace(|| second());
+    // do not take effect since we already has a inner call of __rust_end_short_backtrace
+}
+
+fn second() {
+    __rust_end_short_backtrace(|| third());
+}
+
+fn third() {
+    fourth(); // won't show up in backtrace
+}
+
+fn fourth() {
+    fifth(); // won't show up in backtrace
+}
+
+fn fifth() {
+    __rust_begin_short_backtrace(|| sixth());
+}
+
+fn sixth() {
+    seven();
+}
+
+fn seven() {
+    panic!("debug!!!");
+}
+
+fn main() {
+    first();
+}
diff --git a/tests/ui/panics/short-ice-remove-middle-frames.run.stderr b/tests/ui/panics/short-ice-remove-middle-frames.run.stderr
new file mode 100644
index 00000000000..9c15f2e08fe
--- /dev/null
+++ b/tests/ui/panics/short-ice-remove-middle-frames.run.stderr
@@ -0,0 +1,12 @@
+thread 'main' panicked at 'debug!!!', $DIR/short-ice-remove-middle-frames.rs:52:5
+stack backtrace:
+   0: std::panicking::begin_panic
+   1: short_ice_remove_middle_frames::seven
+   2: short_ice_remove_middle_frames::sixth
+   3: short_ice_remove_middle_frames::fifth::{{closure}}
+   4: short_ice_remove_middle_frames::second
+   5: short_ice_remove_middle_frames::first::{{closure}}
+   6: short_ice_remove_middle_frames::first
+   7: short_ice_remove_middle_frames::main
+   8: core::ops::function::FnOnce::call_once
+note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
diff --git a/tests/ui/parser/dyn-trait-compatibility.stderr b/tests/ui/parser/dyn-trait-compatibility.stderr
index 653be5b3b71..e34d855a9d4 100644
--- a/tests/ui/parser/dyn-trait-compatibility.stderr
+++ b/tests/ui/parser/dyn-trait-compatibility.stderr
@@ -1,9 +1,3 @@
-error[E0433]: failed to resolve: use of undeclared crate or module `dyn`
-  --> $DIR/dyn-trait-compatibility.rs:3:11
-   |
-LL | type A1 = dyn::dyn;
-   |           ^^^ use of undeclared crate or module `dyn`
-
 error[E0412]: cannot find type `dyn` in this scope
   --> $DIR/dyn-trait-compatibility.rs:1:11
    |
@@ -46,6 +40,12 @@ error[E0412]: cannot find type `dyn` in this scope
 LL | type A3 = dyn<<dyn as dyn>::dyn>;
    |                ^^^ not found in this scope
 
+error[E0433]: failed to resolve: use of undeclared crate or module `dyn`
+  --> $DIR/dyn-trait-compatibility.rs:3:11
+   |
+LL | type A1 = dyn::dyn;
+   |           ^^^ use of undeclared crate or module `dyn`
+
 error: aborting due to 8 previous errors
 
 Some errors have detailed explanations: E0405, E0412, E0433.
diff --git a/tests/ui/parser/impl-on-unsized-typo.rs b/tests/ui/parser/impl-on-unsized-typo.rs
new file mode 100644
index 00000000000..e09c0463045
--- /dev/null
+++ b/tests/ui/parser/impl-on-unsized-typo.rs
@@ -0,0 +1,6 @@
+trait Tr {}
+
+impl<T ?Sized> Tr for T {}
+//~^ ERROR expected one of `,`, `:`, `=`, or `>`, found `?`
+
+fn main() {}
diff --git a/tests/ui/parser/impl-on-unsized-typo.stderr b/tests/ui/parser/impl-on-unsized-typo.stderr
new file mode 100644
index 00000000000..23dcc1efd68
--- /dev/null
+++ b/tests/ui/parser/impl-on-unsized-typo.stderr
@@ -0,0 +1,8 @@
+error: expected one of `,`, `:`, `=`, or `>`, found `?`
+  --> $DIR/impl-on-unsized-typo.rs:3:8
+   |
+LL | impl<T ?Sized> Tr for T {}
+   |        ^ expected one of `,`, `:`, `=`, or `>`
+
+error: aborting due to previous error
+
diff --git a/tests/ui/parser/issues/issue-111416.rs b/tests/ui/parser/issues/issue-111416.rs
new file mode 100644
index 00000000000..cfd1b6b99ba
--- /dev/null
+++ b/tests/ui/parser/issues/issue-111416.rs
@@ -0,0 +1,3 @@
+fn main() {
+    let my = monad_bind(mx, T: Try); //~ ERROR invalid `struct` delimiters or `fn` call arguments
+}
diff --git a/tests/ui/parser/issues/issue-111416.stderr b/tests/ui/parser/issues/issue-111416.stderr
new file mode 100644
index 00000000000..ddacf4d6dfc
--- /dev/null
+++ b/tests/ui/parser/issues/issue-111416.stderr
@@ -0,0 +1,18 @@
+error: invalid `struct` delimiters or `fn` call arguments
+  --> $DIR/issue-111416.rs:2:14
+   |
+LL |     let my = monad_bind(mx, T: Try);
+   |              ^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: if `monad_bind` is a struct, use braces as delimiters
+   |
+LL |     let my = monad_bind { mx, T: Try };
+   |                         ~            ~
+help: if `monad_bind` is a function, use the arguments directly
+   |
+LL -     let my = monad_bind(mx, T: Try);
+LL +     let my = monad_bind(mx, Try);
+   |
+
+error: aborting due to previous error
+
diff --git a/tests/ui/pattern/bindings-after-at/borrowck-pat-at-and-box-pass.rs b/tests/ui/pattern/bindings-after-at/borrowck-pat-at-and-box-pass.rs
index fbdefd9d36c..43b53b7cf1f 100644
--- a/tests/ui/pattern/bindings-after-at/borrowck-pat-at-and-box-pass.rs
+++ b/tests/ui/pattern/bindings-after-at/borrowck-pat-at-and-box-pass.rs
@@ -2,6 +2,9 @@
 
 // Test `@` patterns combined with `box` patterns.
 
+#![allow(dropping_references)]
+#![allow(dropping_copy_types)]
+
 #![feature(box_patterns)]
 
 #[derive(Copy, Clone)]
diff --git a/tests/ui/pattern/bindings-after-at/borrowck-pat-by-copy-bindings-in-at.rs b/tests/ui/pattern/bindings-after-at/borrowck-pat-by-copy-bindings-in-at.rs
index 0108861cfce..1df51c0edd9 100644
--- a/tests/ui/pattern/bindings-after-at/borrowck-pat-by-copy-bindings-in-at.rs
+++ b/tests/ui/pattern/bindings-after-at/borrowck-pat-by-copy-bindings-in-at.rs
@@ -2,6 +2,8 @@
 
 // Test `Copy` bindings in the rhs of `@` patterns.
 
+#![allow(dropping_copy_types)]
+
 #[derive(Copy, Clone)]
 struct C;
 
diff --git a/tests/ui/pattern/move-ref-patterns/borrowck-move-ref-pattern-pass.rs b/tests/ui/pattern/move-ref-patterns/borrowck-move-ref-pattern-pass.rs
index 5445696fdff..204cd3e6657 100644
--- a/tests/ui/pattern/move-ref-patterns/borrowck-move-ref-pattern-pass.rs
+++ b/tests/ui/pattern/move-ref-patterns/borrowck-move-ref-pattern-pass.rs
@@ -1,5 +1,7 @@
 // check-pass
 
+#![allow(dropping_references)]
+
 fn main() {}
 
 struct U;
diff --git a/tests/ui/pattern/move-ref-patterns/move-ref-patterns-closure-captures-pass.rs b/tests/ui/pattern/move-ref-patterns/move-ref-patterns-closure-captures-pass.rs
index 583f70f41aa..4de1f653db0 100644
--- a/tests/ui/pattern/move-ref-patterns/move-ref-patterns-closure-captures-pass.rs
+++ b/tests/ui/pattern/move-ref-patterns/move-ref-patterns-closure-captures-pass.rs
@@ -1,5 +1,7 @@
 // check-pass
 
+#![allow(dropping_references)]
+
 fn main() {
     struct U;
     fn accept_fn_once(_: impl FnOnce()) {}
diff --git a/tests/ui/pattern/pattern-error-continue.stderr b/tests/ui/pattern/pattern-error-continue.stderr
index e1349fb02ea..10fcccb0301 100644
--- a/tests/ui/pattern/pattern-error-continue.stderr
+++ b/tests/ui/pattern/pattern-error-continue.stderr
@@ -1,9 +1,3 @@
-error[E0433]: failed to resolve: use of undeclared type `E`
-  --> $DIR/pattern-error-continue.rs:33:9
-   |
-LL |         E::V => {}
-   |         ^ use of undeclared type `E`
-
 error[E0532]: expected tuple struct or tuple variant, found unit variant `A::D`
   --> $DIR/pattern-error-continue.rs:18:9
    |
@@ -56,6 +50,15 @@ note: function defined here
 LL | fn f(_c: char) {}
    |    ^ --------
 
+error[E0433]: failed to resolve: use of undeclared type `E`
+  --> $DIR/pattern-error-continue.rs:33:9
+   |
+LL |         E::V => {}
+   |         ^
+   |         |
+   |         use of undeclared type `E`
+   |         help: an enum with a similar name exists: `A`
+
 error: aborting due to 5 previous errors
 
 Some errors have detailed explanations: E0023, E0308, E0433, E0532.
diff --git a/tests/ui/pattern/usefulness/consts-opaque.rs b/tests/ui/pattern/usefulness/consts-opaque.rs
index ca4fcd85bb6..c10c6205a08 100644
--- a/tests/ui/pattern/usefulness/consts-opaque.rs
+++ b/tests/ui/pattern/usefulness/consts-opaque.rs
@@ -20,11 +20,12 @@ const BAR: Bar = Bar;
 #[derive(PartialEq)]
 enum Baz {
     Baz1,
-    Baz2
+    Baz2,
 }
 impl Eq for Baz {}
 const BAZ: Baz = Baz::Baz1;
 
+#[rustfmt::skip]
 fn main() {
     match FOO {
         FOO => {}
@@ -124,8 +125,16 @@ fn main() {
 
     match WRAPQUUX {
         Wrap(_) => {}
-        WRAPQUUX => {} // detected unreachable because we do inspect the `Wrap` layer
-        //~^ ERROR unreachable pattern
+        WRAPQUUX => {}
+    }
+
+    match WRAPQUUX {
+        Wrap(_) => {}
+    }
+
+    match WRAPQUUX {
+        //~^ ERROR: non-exhaustive patterns: `Wrap(_)` not covered
+        WRAPQUUX => {}
     }
 
     #[derive(PartialEq, Eq)]
@@ -138,8 +147,7 @@ fn main() {
     match WHOKNOWSQUUX {
         WHOKNOWSQUUX => {}
         WhoKnows::Yay(_) => {}
-        WHOKNOWSQUUX => {} // detected unreachable because we do inspect the `WhoKnows` layer
-        //~^ ERROR unreachable pattern
+        WHOKNOWSQUUX => {}
         WhoKnows::Nope => {}
     }
 }
diff --git a/tests/ui/pattern/usefulness/consts-opaque.stderr b/tests/ui/pattern/usefulness/consts-opaque.stderr
index 3f0b4a9f26a..e01b06ccc82 100644
--- a/tests/ui/pattern/usefulness/consts-opaque.stderr
+++ b/tests/ui/pattern/usefulness/consts-opaque.stderr
@@ -1,5 +1,5 @@
 error: to use a constant of type `Foo` in a pattern, `Foo` must be annotated with `#[derive(PartialEq, Eq)]`
-  --> $DIR/consts-opaque.rs:30:9
+  --> $DIR/consts-opaque.rs:31:9
    |
 LL |         FOO => {}
    |         ^^^
@@ -8,7 +8,7 @@ LL |         FOO => {}
    = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralEq.html for details
 
 error: to use a constant of type `Foo` in a pattern, `Foo` must be annotated with `#[derive(PartialEq, Eq)]`
-  --> $DIR/consts-opaque.rs:37:9
+  --> $DIR/consts-opaque.rs:38:9
    |
 LL |         FOO_REF => {}
    |         ^^^^^^^
@@ -17,7 +17,7 @@ LL |         FOO_REF => {}
    = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralEq.html for details
 
 warning: to use a constant of type `Foo` in a pattern, `Foo` must be annotated with `#[derive(PartialEq, Eq)]`
-  --> $DIR/consts-opaque.rs:45:9
+  --> $DIR/consts-opaque.rs:46:9
    |
 LL |         FOO_REF_REF => {}
    |         ^^^^^^^^^^^
@@ -29,7 +29,7 @@ LL |         FOO_REF_REF => {}
    = note: `#[warn(indirect_structural_match)]` on by default
 
 error: to use a constant of type `Bar` in a pattern, `Bar` must be annotated with `#[derive(PartialEq, Eq)]`
-  --> $DIR/consts-opaque.rs:53:9
+  --> $DIR/consts-opaque.rs:54:9
    |
 LL |         BAR => {} // should not be emitting unreachable warning
    |         ^^^
@@ -38,7 +38,7 @@ LL |         BAR => {} // should not be emitting unreachable warning
    = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralEq.html for details
 
 error: to use a constant of type `Bar` in a pattern, `Bar` must be annotated with `#[derive(PartialEq, Eq)]`
-  --> $DIR/consts-opaque.rs:61:9
+  --> $DIR/consts-opaque.rs:62:9
    |
 LL |         BAR => {}
    |         ^^^
@@ -47,7 +47,7 @@ LL |         BAR => {}
    = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralEq.html for details
 
 error: to use a constant of type `Bar` in a pattern, `Bar` must be annotated with `#[derive(PartialEq, Eq)]`
-  --> $DIR/consts-opaque.rs:70:9
+  --> $DIR/consts-opaque.rs:71:9
    |
 LL |         BAR => {}
    |         ^^^
@@ -56,7 +56,7 @@ LL |         BAR => {}
    = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralEq.html for details
 
 error: to use a constant of type `Bar` in a pattern, `Bar` must be annotated with `#[derive(PartialEq, Eq)]`
-  --> $DIR/consts-opaque.rs:72:9
+  --> $DIR/consts-opaque.rs:73:9
    |
 LL |         BAR => {} // should not be emitting unreachable warning
    |         ^^^
@@ -65,7 +65,7 @@ LL |         BAR => {} // should not be emitting unreachable warning
    = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralEq.html for details
 
 error: to use a constant of type `Baz` in a pattern, `Baz` must be annotated with `#[derive(PartialEq, Eq)]`
-  --> $DIR/consts-opaque.rs:80:9
+  --> $DIR/consts-opaque.rs:81:9
    |
 LL |         BAZ => {}
    |         ^^^
@@ -74,7 +74,7 @@ LL |         BAZ => {}
    = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralEq.html for details
 
 error: to use a constant of type `Baz` in a pattern, `Baz` must be annotated with `#[derive(PartialEq, Eq)]`
-  --> $DIR/consts-opaque.rs:90:9
+  --> $DIR/consts-opaque.rs:91:9
    |
 LL |         BAZ => {}
    |         ^^^
@@ -83,7 +83,7 @@ LL |         BAZ => {}
    = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralEq.html for details
 
 error: to use a constant of type `Baz` in a pattern, `Baz` must be annotated with `#[derive(PartialEq, Eq)]`
-  --> $DIR/consts-opaque.rs:97:9
+  --> $DIR/consts-opaque.rs:98:9
    |
 LL |         BAZ => {}
    |         ^^^
@@ -92,7 +92,7 @@ LL |         BAZ => {}
    = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralEq.html for details
 
 error: unreachable pattern
-  --> $DIR/consts-opaque.rs:32:9
+  --> $DIR/consts-opaque.rs:33:9
    |
 LL |         FOO => {}
    |         --- matches any value
@@ -107,7 +107,7 @@ LL | #![deny(unreachable_patterns)]
    |         ^^^^^^^^^^^^^^^^^^^^
 
 error: unreachable pattern
-  --> $DIR/consts-opaque.rs:39:9
+  --> $DIR/consts-opaque.rs:40:9
    |
 LL |         FOO_REF => {}
    |         ------- matches any value
@@ -116,7 +116,7 @@ LL |         Foo(_) => {} // should not be emitting unreachable warning
    |         ^^^^^^ unreachable pattern
 
 error: unreachable pattern
-  --> $DIR/consts-opaque.rs:53:9
+  --> $DIR/consts-opaque.rs:54:9
    |
 LL |         Bar => {}
    |         --- matches any value
@@ -124,7 +124,7 @@ LL |         BAR => {} // should not be emitting unreachable warning
    |         ^^^ unreachable pattern
 
 error: unreachable pattern
-  --> $DIR/consts-opaque.rs:56:9
+  --> $DIR/consts-opaque.rs:57:9
    |
 LL |         Bar => {}
    |         --- matches any value
@@ -133,7 +133,7 @@ LL |         _ => {}
    |         ^ unreachable pattern
 
 error: unreachable pattern
-  --> $DIR/consts-opaque.rs:63:9
+  --> $DIR/consts-opaque.rs:64:9
    |
 LL |         BAR => {}
    |         --- matches any value
@@ -142,7 +142,7 @@ LL |         Bar => {} // should not be emitting unreachable warning
    |         ^^^ unreachable pattern
 
 error: unreachable pattern
-  --> $DIR/consts-opaque.rs:65:9
+  --> $DIR/consts-opaque.rs:66:9
    |
 LL |         BAR => {}
    |         --- matches any value
@@ -151,7 +151,7 @@ LL |         _ => {}
    |         ^ unreachable pattern
 
 error: unreachable pattern
-  --> $DIR/consts-opaque.rs:72:9
+  --> $DIR/consts-opaque.rs:73:9
    |
 LL |         BAR => {}
    |         --- matches any value
@@ -160,7 +160,7 @@ LL |         BAR => {} // should not be emitting unreachable warning
    |         ^^^ unreachable pattern
 
 error: unreachable pattern
-  --> $DIR/consts-opaque.rs:75:9
+  --> $DIR/consts-opaque.rs:76:9
    |
 LL |         BAR => {}
    |         --- matches any value
@@ -169,7 +169,7 @@ LL |         _ => {} // should not be emitting unreachable warning
    |         ^ unreachable pattern
 
 error: unreachable pattern
-  --> $DIR/consts-opaque.rs:82:9
+  --> $DIR/consts-opaque.rs:83:9
    |
 LL |         BAZ => {}
    |         --- matches any value
@@ -178,7 +178,7 @@ LL |         Baz::Baz1 => {} // should not be emitting unreachable warning
    |         ^^^^^^^^^ unreachable pattern
 
 error: unreachable pattern
-  --> $DIR/consts-opaque.rs:84:9
+  --> $DIR/consts-opaque.rs:85:9
    |
 LL |         BAZ => {}
    |         --- matches any value
@@ -187,7 +187,7 @@ LL |         _ => {}
    |         ^ unreachable pattern
 
 error: unreachable pattern
-  --> $DIR/consts-opaque.rs:92:9
+  --> $DIR/consts-opaque.rs:93:9
    |
 LL |         BAZ => {}
    |         --- matches any value
@@ -196,7 +196,7 @@ LL |         _ => {}
    |         ^ unreachable pattern
 
 error: unreachable pattern
-  --> $DIR/consts-opaque.rs:99:9
+  --> $DIR/consts-opaque.rs:100:9
    |
 LL |         BAZ => {}
    |         --- matches any value
@@ -205,7 +205,7 @@ LL |         Baz::Baz2 => {} // should not be emitting unreachable warning
    |         ^^^^^^^^^ unreachable pattern
 
 error: unreachable pattern
-  --> $DIR/consts-opaque.rs:101:9
+  --> $DIR/consts-opaque.rs:102:9
    |
 LL |         BAZ => {}
    |         --- matches any value
@@ -213,19 +213,24 @@ LL |         BAZ => {}
 LL |         _ => {} // should not be emitting unreachable warning
    |         ^ unreachable pattern
 
-error: unreachable pattern
-  --> $DIR/consts-opaque.rs:127:9
+error[E0004]: non-exhaustive patterns: `Wrap(_)` not covered
+  --> $DIR/consts-opaque.rs:135:11
    |
-LL |         Wrap(_) => {}
-   |         ------- matches any value
-LL |         WRAPQUUX => {} // detected unreachable because we do inspect the `Wrap` layer
-   |         ^^^^^^^^ unreachable pattern
-
-error: unreachable pattern
-  --> $DIR/consts-opaque.rs:141:9
+LL |     match WRAPQUUX {
+   |           ^^^^^^^^ pattern `Wrap(_)` not covered
+   |
+note: `Wrap<fn(usize, usize) -> usize>` defined here
+  --> $DIR/consts-opaque.rs:117:12
+   |
+LL |     struct Wrap<T>(T);
+   |            ^^^^
+   = note: the matched value is of type `Wrap<fn(usize, usize) -> usize>`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         WRAPQUUX => {},
+LL +         Wrap(_) => todo!()
    |
-LL |         WHOKNOWSQUUX => {} // detected unreachable because we do inspect the `WhoKnows` layer
-   |         ^^^^^^^^^^^^
 
-error: aborting due to 24 previous errors; 1 warning emitted
+error: aborting due to 23 previous errors; 1 warning emitted
 
+For more information about this error, try `rustc --explain E0004`.
diff --git a/tests/ui/print_type_sizes/async.rs b/tests/ui/print_type_sizes/async.rs
index 1598b069691..f38a6e674da 100644
--- a/tests/ui/print_type_sizes/async.rs
+++ b/tests/ui/print_type_sizes/async.rs
@@ -3,6 +3,8 @@
 // build-pass
 // ignore-pass
 
+#![allow(dropping_copy_types)]
+
 async fn wait() {}
 
 pub async fn test(arg: [u8; 8192]) {
diff --git a/tests/ui/print_type_sizes/async.stdout b/tests/ui/print_type_sizes/async.stdout
index 1c6887412be..873def9031a 100644
--- a/tests/ui/print_type_sizes/async.stdout
+++ b/tests/ui/print_type_sizes/async.stdout
@@ -1,4 +1,4 @@
-print-type-size type: `[async fn body@$DIR/async.rs:8:36: 11:2]`: 16386 bytes, alignment: 1 bytes
+print-type-size type: `[async fn body@$DIR/async.rs:10:36: 13:2]`: 16386 bytes, alignment: 1 bytes
 print-type-size     discriminant: 1 bytes
 print-type-size     variant `Unresumed`: 8192 bytes
 print-type-size         upvar `.arg`: 8192 bytes
@@ -16,14 +16,14 @@ print-type-size type: `std::mem::MaybeUninit<[u8; 8192]>`: 8192 bytes, alignment
 print-type-size     variant `MaybeUninit`: 8192 bytes
 print-type-size         field `.uninit`: 0 bytes
 print-type-size         field `.value`: 8192 bytes
-print-type-size type: `[async fn body@$DIR/async.rs:6:17: 6:19]`: 1 bytes, alignment: 1 bytes
+print-type-size type: `[async fn body@$DIR/async.rs:8:17: 8:19]`: 1 bytes, alignment: 1 bytes
 print-type-size     discriminant: 1 bytes
 print-type-size     variant `Unresumed`: 0 bytes
 print-type-size     variant `Returned`: 0 bytes
 print-type-size     variant `Panicked`: 0 bytes
-print-type-size type: `std::mem::ManuallyDrop<[async fn body@$DIR/async.rs:6:17: 6:19]>`: 1 bytes, alignment: 1 bytes
+print-type-size type: `std::mem::ManuallyDrop<[async fn body@$DIR/async.rs:8:17: 8:19]>`: 1 bytes, alignment: 1 bytes
 print-type-size     field `.value`: 1 bytes
-print-type-size type: `std::mem::MaybeUninit<[async fn body@$DIR/async.rs:6:17: 6:19]>`: 1 bytes, alignment: 1 bytes
+print-type-size type: `std::mem::MaybeUninit<[async fn body@$DIR/async.rs:8:17: 8:19]>`: 1 bytes, alignment: 1 bytes
 print-type-size     variant `MaybeUninit`: 1 bytes
 print-type-size         field `.uninit`: 0 bytes
 print-type-size         field `.value`: 1 bytes
diff --git a/tests/ui/print_type_sizes/generator_discr_placement.rs b/tests/ui/print_type_sizes/generator_discr_placement.rs
index 1a85fe95bb6..6adc14f9b99 100644
--- a/tests/ui/print_type_sizes/generator_discr_placement.rs
+++ b/tests/ui/print_type_sizes/generator_discr_placement.rs
@@ -6,6 +6,7 @@
 
 // Avoid emitting panic handlers, like the rest of these tests...
 #![feature(generators)]
+#![allow(dropping_copy_types)]
 
 pub fn foo() {
     let a = || {
diff --git a/tests/ui/print_type_sizes/generator_discr_placement.stdout b/tests/ui/print_type_sizes/generator_discr_placement.stdout
index f2a11c7a33b..fe0022cf5f4 100644
--- a/tests/ui/print_type_sizes/generator_discr_placement.stdout
+++ b/tests/ui/print_type_sizes/generator_discr_placement.stdout
@@ -1,4 +1,4 @@
-print-type-size type: `[generator@$DIR/generator_discr_placement.rs:11:13: 11:15]`: 8 bytes, alignment: 4 bytes
+print-type-size type: `[generator@$DIR/generator_discr_placement.rs:12:13: 12:15]`: 8 bytes, alignment: 4 bytes
 print-type-size     discriminant: 1 bytes
 print-type-size     variant `Unresumed`: 0 bytes
 print-type-size     variant `Suspend0`: 7 bytes
diff --git a/tests/ui/regions/type-param-outlives-reempty-issue-74429-2.rs b/tests/ui/regions/type-param-outlives-reempty-issue-74429-2.rs
index a65c17e0efc..5ae5ebb450e 100644
--- a/tests/ui/regions/type-param-outlives-reempty-issue-74429-2.rs
+++ b/tests/ui/regions/type-param-outlives-reempty-issue-74429-2.rs
@@ -55,11 +55,11 @@ where
 }
 
 pub fn x<T: Copy>(a: Array<T>) {
-    // drop just avoids a must_use warning
-    drop((0..1).filter(|_| true));
+    // _ just avoids a must_use warning
+    let _ = (0..1).filter(|_| true);
     let y = a.index_axis();
     a.axis_iter().for_each(|_| {
-        drop(y);
+        let _ = y;
     });
 }
 
diff --git a/tests/ui/regions/type-param-outlives-reempty-issue-74429.rs b/tests/ui/regions/type-param-outlives-reempty-issue-74429.rs
index d463f311c34..0c1e9314441 100644
--- a/tests/ui/regions/type-param-outlives-reempty-issue-74429.rs
+++ b/tests/ui/regions/type-param-outlives-reempty-issue-74429.rs
@@ -3,6 +3,8 @@
 
 // check-pass
 
+#![allow(dropping_copy_types)]
+
 use std::marker::PhantomData;
 
 fn apply<T, F: FnOnce(T)>(_: T, _: F) {}
diff --git a/tests/ui/resolve/issue-109250.rs b/tests/ui/resolve/issue-109250.rs
new file mode 100644
index 00000000000..68e33f693ce
--- /dev/null
+++ b/tests/ui/resolve/issue-109250.rs
@@ -0,0 +1,3 @@
+fn main() {       //~ HELP consider importing
+    HashMap::new; //~ ERROR failed to resolve: use of undeclared type `HashMap`
+}
diff --git a/tests/ui/resolve/issue-109250.stderr b/tests/ui/resolve/issue-109250.stderr
new file mode 100644
index 00000000000..d5b8c08ced7
--- /dev/null
+++ b/tests/ui/resolve/issue-109250.stderr
@@ -0,0 +1,14 @@
+error[E0433]: failed to resolve: use of undeclared type `HashMap`
+  --> $DIR/issue-109250.rs:2:5
+   |
+LL |     HashMap::new;
+   |     ^^^^^^^ use of undeclared type `HashMap`
+   |
+help: consider importing this struct
+   |
+LL + use std::collections::HashMap;
+   |
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0433`.
diff --git a/tests/ui/resolve/issue-111312.rs b/tests/ui/resolve/issue-111312.rs
new file mode 100644
index 00000000000..acea37b358b
--- /dev/null
+++ b/tests/ui/resolve/issue-111312.rs
@@ -0,0 +1,11 @@
+// edition: 2021
+
+trait Has {
+    fn has() {}
+}
+
+trait HasNot {}
+
+fn main() {
+    HasNot::has(); //~ ERROR
+}
diff --git a/tests/ui/resolve/issue-111312.stderr b/tests/ui/resolve/issue-111312.stderr
new file mode 100644
index 00000000000..4c864029c98
--- /dev/null
+++ b/tests/ui/resolve/issue-111312.stderr
@@ -0,0 +1,15 @@
+error[E0599]: no function or associated item named `has` found for trait `HasNot`
+  --> $DIR/issue-111312.rs:10:13
+   |
+LL |     HasNot::has();
+   |             ^^^ function or associated item not found in `HasNot`
+   |
+note: `Has` defines an item `has`
+  --> $DIR/issue-111312.rs:3:1
+   |
+LL | trait Has {
+   | ^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/tests/ui/resolve/issue-111727.rs b/tests/ui/resolve/issue-111727.rs
new file mode 100644
index 00000000000..36f3081211d
--- /dev/null
+++ b/tests/ui/resolve/issue-111727.rs
@@ -0,0 +1,5 @@
+// edition: 2021
+
+fn main() {
+    std::any::Any::create(); //~ ERROR
+}
diff --git a/tests/ui/resolve/issue-111727.stderr b/tests/ui/resolve/issue-111727.stderr
new file mode 100644
index 00000000000..bd748211ed3
--- /dev/null
+++ b/tests/ui/resolve/issue-111727.stderr
@@ -0,0 +1,9 @@
+error[E0599]: no function or associated item named `create` found for trait `Any`
+  --> $DIR/issue-111727.rs:4:20
+   |
+LL |     std::any::Any::create();
+   |                    ^^^^^^ function or associated item not found in `Any`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/tests/ui/resolve/issue-50599.rs b/tests/ui/resolve/issue-50599.rs
index 72238a59198..00588735b9a 100644
--- a/tests/ui/resolve/issue-50599.rs
+++ b/tests/ui/resolve/issue-50599.rs
@@ -2,5 +2,4 @@ fn main() {
     const N: u32 = 1_000;
     const M: usize = (f64::from(N) * std::f64::LOG10_2) as usize; //~ ERROR cannot find value
     let mut digits = [0u32; M];
-    //~^ constant
 }
diff --git a/tests/ui/resolve/issue-50599.stderr b/tests/ui/resolve/issue-50599.stderr
index d7419b64fac..d58b6ca5b5c 100644
--- a/tests/ui/resolve/issue-50599.stderr
+++ b/tests/ui/resolve/issue-50599.stderr
@@ -16,12 +16,6 @@ LL -     const M: usize = (f64::from(N) * std::f64::LOG10_2) as usize;
 LL +     const M: usize = (f64::from(N) * LOG10_2) as usize;
    |
 
-note: erroneous constant used
-  --> $DIR/issue-50599.rs:4:29
-   |
-LL |     let mut digits = [0u32; M];
-   |                             ^
-
 error: aborting due to previous error
 
 For more information about this error, try `rustc --explain E0425`.
diff --git a/tests/ui/resolve/resolve-variant-assoc-item.stderr b/tests/ui/resolve/resolve-variant-assoc-item.stderr
index 4be1019968b..ed157197d17 100644
--- a/tests/ui/resolve/resolve-variant-assoc-item.stderr
+++ b/tests/ui/resolve/resolve-variant-assoc-item.stderr
@@ -3,12 +3,26 @@ error[E0433]: failed to resolve: `V` is a variant, not a module
    |
 LL |     E::V::associated_item;
    |        ^ `V` is a variant, not a module
+   |
+help: there is an enum variant `E::V`; try using the variant's enum
+   |
+LL |     E;
+   |     ~
 
 error[E0433]: failed to resolve: `V` is a variant, not a module
   --> $DIR/resolve-variant-assoc-item.rs:6:5
    |
 LL |     V::associated_item;
    |     ^ `V` is a variant, not a module
+   |
+help: there is an enum variant `E::V`; try using the variant's enum
+   |
+LL |     E;
+   |     ~
+help: an enum with a similar name exists
+   |
+LL |     E::associated_item;
+   |     ~
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/rfc-2008-non-exhaustive/borrowck-exhaustive.rs b/tests/ui/rfc-2008-non-exhaustive/borrowck-exhaustive.rs
index be775b37f7b..b9ff24c7624 100644
--- a/tests/ui/rfc-2008-non-exhaustive/borrowck-exhaustive.rs
+++ b/tests/ui/rfc-2008-non-exhaustive/borrowck-exhaustive.rs
@@ -3,6 +3,8 @@
 
 // check-pass
 
+#![allow(dropping_references)]
+
 // aux-build:monovariants.rs
 extern crate monovariants;
 
diff --git a/tests/ui/rfc-2361-dbg-macro/dbg-macro-expected-behavior.rs b/tests/ui/rfc-2361-dbg-macro/dbg-macro-expected-behavior.rs
index 04d924a9aed..542be3942b7 100644
--- a/tests/ui/rfc-2361-dbg-macro/dbg-macro-expected-behavior.rs
+++ b/tests/ui/rfc-2361-dbg-macro/dbg-macro-expected-behavior.rs
@@ -4,6 +4,8 @@
 // Tests ensuring that `dbg!(expr)` has the expected run-time behavior.
 // as well as some compile time properties we expect.
 
+#![allow(dropping_copy_types)]
+
 #[derive(Copy, Clone, Debug)]
 struct Unit;
 
diff --git a/tests/ui/rfc-2361-dbg-macro/dbg-macro-expected-behavior.run.stderr b/tests/ui/rfc-2361-dbg-macro/dbg-macro-expected-behavior.run.stderr
index 49d72158e92..a20a6062c13 100644
--- a/tests/ui/rfc-2361-dbg-macro/dbg-macro-expected-behavior.run.stderr
+++ b/tests/ui/rfc-2361-dbg-macro/dbg-macro-expected-behavior.run.stderr
@@ -1,28 +1,28 @@
-[$DIR/dbg-macro-expected-behavior.rs:20] Unit = Unit
-[$DIR/dbg-macro-expected-behavior.rs:21] a = Unit
-[$DIR/dbg-macro-expected-behavior.rs:27] Point { x: 42, y: 24 } = Point {
+[$DIR/dbg-macro-expected-behavior.rs:22] Unit = Unit
+[$DIR/dbg-macro-expected-behavior.rs:23] a = Unit
+[$DIR/dbg-macro-expected-behavior.rs:29] Point { x: 42, y: 24 } = Point {
     x: 42,
     y: 24,
 }
-[$DIR/dbg-macro-expected-behavior.rs:28] b = Point {
+[$DIR/dbg-macro-expected-behavior.rs:30] b = Point {
     x: 42,
     y: 24,
 }
-[$DIR/dbg-macro-expected-behavior.rs:36]
-[$DIR/dbg-macro-expected-behavior.rs:40] &a = NoCopy(
+[$DIR/dbg-macro-expected-behavior.rs:38]
+[$DIR/dbg-macro-expected-behavior.rs:42] &a = NoCopy(
     1337,
 )
-[$DIR/dbg-macro-expected-behavior.rs:40] dbg!(& a) = NoCopy(
+[$DIR/dbg-macro-expected-behavior.rs:42] dbg!(& a) = NoCopy(
     1337,
 )
-[$DIR/dbg-macro-expected-behavior.rs:45] f(&42) = 42
+[$DIR/dbg-macro-expected-behavior.rs:47] f(&42) = 42
 before
-[$DIR/dbg-macro-expected-behavior.rs:50] { foo += 1; eprintln!("before"); 7331 } = 7331
-[$DIR/dbg-macro-expected-behavior.rs:58] ("Yeah",) = (
+[$DIR/dbg-macro-expected-behavior.rs:52] { foo += 1; eprintln!("before"); 7331 } = 7331
+[$DIR/dbg-macro-expected-behavior.rs:60] ("Yeah",) = (
     "Yeah",
 )
-[$DIR/dbg-macro-expected-behavior.rs:61] 1 = 1
-[$DIR/dbg-macro-expected-behavior.rs:61] 2 = 2
-[$DIR/dbg-macro-expected-behavior.rs:65] 1u8 = 1
-[$DIR/dbg-macro-expected-behavior.rs:65] 2u32 = 2
-[$DIR/dbg-macro-expected-behavior.rs:65] "Yeah" = "Yeah"
+[$DIR/dbg-macro-expected-behavior.rs:63] 1 = 1
+[$DIR/dbg-macro-expected-behavior.rs:63] 2 = 2
+[$DIR/dbg-macro-expected-behavior.rs:67] 1u8 = 1
+[$DIR/dbg-macro-expected-behavior.rs:67] 2u32 = 2
+[$DIR/dbg-macro-expected-behavior.rs:67] "Yeah" = "Yeah"
diff --git a/tests/ui/rust-2018/remove-extern-crate.fixed b/tests/ui/rust-2018/remove-extern-crate.fixed
index 15e0ccc5256..209b91af1dd 100644
--- a/tests/ui/rust-2018/remove-extern-crate.fixed
+++ b/tests/ui/rust-2018/remove-extern-crate.fixed
@@ -5,6 +5,7 @@
 // compile-flags:--extern remove_extern_crate
 
 #![warn(rust_2018_idioms)]
+#![allow(dropping_copy_types)]
 
  //~ WARNING unused extern crate
 // Shouldn't suggest changing to `use`, as `another_name`
diff --git a/tests/ui/rust-2018/remove-extern-crate.rs b/tests/ui/rust-2018/remove-extern-crate.rs
index aec0bc7c374..ef3c2db696a 100644
--- a/tests/ui/rust-2018/remove-extern-crate.rs
+++ b/tests/ui/rust-2018/remove-extern-crate.rs
@@ -5,6 +5,7 @@
 // compile-flags:--extern remove_extern_crate
 
 #![warn(rust_2018_idioms)]
+#![allow(dropping_copy_types)]
 
 extern crate core; //~ WARNING unused extern crate
 // Shouldn't suggest changing to `use`, as `another_name`
diff --git a/tests/ui/rust-2018/remove-extern-crate.stderr b/tests/ui/rust-2018/remove-extern-crate.stderr
index d07358e471b..f752cac8ed6 100644
--- a/tests/ui/rust-2018/remove-extern-crate.stderr
+++ b/tests/ui/rust-2018/remove-extern-crate.stderr
@@ -1,5 +1,5 @@
 warning: unused extern crate
-  --> $DIR/remove-extern-crate.rs:9:1
+  --> $DIR/remove-extern-crate.rs:10:1
    |
 LL | extern crate core;
    | ^^^^^^^^^^^^^^^^^^ help: remove it
@@ -12,7 +12,7 @@ LL | #![warn(rust_2018_idioms)]
    = note: `#[warn(unused_extern_crates)]` implied by `#[warn(rust_2018_idioms)]`
 
 warning: `extern crate` is not idiomatic in the new edition
-  --> $DIR/remove-extern-crate.rs:33:5
+  --> $DIR/remove-extern-crate.rs:34:5
    |
 LL |     extern crate core;
    |     ^^^^^^^^^^^^^^^^^^
@@ -23,7 +23,7 @@ LL |     use core;
    |     ~~~
 
 warning: `extern crate` is not idiomatic in the new edition
-  --> $DIR/remove-extern-crate.rs:43:5
+  --> $DIR/remove-extern-crate.rs:44:5
    |
 LL |     pub extern crate core;
    |     ^^^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/self/arbitrary-self-types-not-object-safe.curr.stderr b/tests/ui/self/arbitrary-self-types-not-object-safe.curr.stderr
index 0ec0d4be5f2..13591f5b635 100644
--- a/tests/ui/self/arbitrary-self-types-not-object-safe.curr.stderr
+++ b/tests/ui/self/arbitrary-self-types-not-object-safe.curr.stderr
@@ -31,8 +31,7 @@ LL | trait Foo {
    |       --- this trait cannot be made into an object...
 LL |     fn foo(self: &Rc<Self>) -> usize;
    |                  ^^^^^^^^^ ...because method `foo`'s `self` parameter cannot be dispatched on
-   = note: required for `Rc<usize>` to implement `CoerceUnsized<Rc<dyn Foo>>`
-   = note: required by cast to type `Rc<dyn Foo>`
+   = note: required for the cast from `Rc<usize>` to `Rc<dyn Foo>`
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/self/arbitrary-self-types-not-object-safe.object_safe_for_dispatch.stderr b/tests/ui/self/arbitrary-self-types-not-object-safe.object_safe_for_dispatch.stderr
index b494b448e2e..593f705353a 100644
--- a/tests/ui/self/arbitrary-self-types-not-object-safe.object_safe_for_dispatch.stderr
+++ b/tests/ui/self/arbitrary-self-types-not-object-safe.object_safe_for_dispatch.stderr
@@ -14,8 +14,7 @@ LL | trait Foo {
    |       --- this trait cannot be made into an object...
 LL |     fn foo(self: &Rc<Self>) -> usize;
    |                  ^^^^^^^^^ ...because method `foo`'s `self` parameter cannot be dispatched on
-   = note: required for `Rc<usize>` to implement `CoerceUnsized<Rc<dyn Foo>>`
-   = note: required by cast to type `Rc<dyn Foo>`
+   = note: required for the cast from `Rc<usize>` to `Rc<dyn Foo>`
 
 error: aborting due to previous error
 
diff --git a/tests/ui/self/self-ctor-inner-const.rs b/tests/ui/self/self-ctor-inner-const.rs
deleted file mode 100644
index b015397a5bc..00000000000
--- a/tests/ui/self/self-ctor-inner-const.rs
+++ /dev/null
@@ -1,17 +0,0 @@
-// Verify that we ban usage of `Self` as constructor from inner items.
-
-struct S0<T>(T);
-
-impl<T> S0<T> {
-    fn foo() {
-        const C: S0<u8> = Self(0);
-        //~^ ERROR can't use generic parameters from outer function
-        fn bar() -> Self {
-            //~^ ERROR can't use generic parameters from outer function
-            Self(0)
-            //~^ ERROR can't use generic parameters from outer function
-        }
-    }
-}
-
-fn main() {}
diff --git a/tests/ui/self/self-ctor-inner-const.stderr b/tests/ui/self/self-ctor-inner-const.stderr
deleted file mode 100644
index 7287c64c659..00000000000
--- a/tests/ui/self/self-ctor-inner-const.stderr
+++ /dev/null
@@ -1,33 +0,0 @@
-error[E0401]: can't use generic parameters from outer function
-  --> $DIR/self-ctor-inner-const.rs:7:27
-   |
-LL |         const C: S0<u8> = Self(0);
-   |                           ^^^^
-   |                           |
-   |                           use of generic parameter from outer function
-   |                           can't use `Self` here
-
-error[E0401]: can't use generic parameters from outer function
-  --> $DIR/self-ctor-inner-const.rs:9:21
-   |
-LL | impl<T> S0<T> {
-   | ---- `Self` type implicitly declared here, by this `impl`
-...
-LL |         fn bar() -> Self {
-   |                     ^^^^
-   |                     |
-   |                     use of generic parameter from outer function
-   |                     use a type here instead
-
-error[E0401]: can't use generic parameters from outer function
-  --> $DIR/self-ctor-inner-const.rs:11:13
-   |
-LL |             Self(0)
-   |             ^^^^
-   |             |
-   |             use of generic parameter from outer function
-   |             can't use `Self` here
-
-error: aborting due to 3 previous errors
-
-For more information about this error, try `rustc --explain E0401`.
diff --git a/tests/ui/self/self-ctor-nongeneric.rs b/tests/ui/self/self-ctor-nongeneric.rs
new file mode 100644
index 00000000000..0ae7f8da4b4
--- /dev/null
+++ b/tests/ui/self/self-ctor-nongeneric.rs
@@ -0,0 +1,15 @@
+// `Self` as a constructor is currently allowed when the outer item is not generic.
+// check-pass
+
+struct S0(usize);
+
+impl S0 {
+    fn foo() {
+        const C: S0 = Self(0);
+        fn bar() -> S0 {
+            Self(0)
+        }
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/statics/issue-91050-1.rs b/tests/ui/statics/issue-91050-1.rs
index 403a41462ef..c6268dba567 100644
--- a/tests/ui/statics/issue-91050-1.rs
+++ b/tests/ui/statics/issue-91050-1.rs
@@ -12,6 +12,8 @@
 //
 // In regular builds, the bad cast was UB, like "Invalid LLVMRustVisibility value!"
 
+#![allow(dropping_copy_types)]
+
 pub mod before {
     #[no_mangle]
     pub static GLOBAL1: [u8; 1] = [1];
diff --git a/tests/ui/suggestions/derive-macro-missing-bounds.stderr b/tests/ui/suggestions/derive-macro-missing-bounds.stderr
index c3f305c1770..bffcb1af487 100644
--- a/tests/ui/suggestions/derive-macro-missing-bounds.stderr
+++ b/tests/ui/suggestions/derive-macro-missing-bounds.stderr
@@ -36,7 +36,7 @@ LL |     impl<T: Debug + Trait> Debug for Inner<T> {
    |                     unsatisfied trait bound introduced here
    = note: 1 redundant requirement hidden
    = note: required for `&c::Inner<T>` to implement `Debug`
-   = note: required for the cast from `&c::Inner<T>` to the object type `dyn Debug`
+   = note: required for the cast from `&&c::Inner<T>` to `&dyn Debug`
    = note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info)
 help: consider restricting type parameter `T`
    |
@@ -58,7 +58,7 @@ LL |     impl<T> Debug for Inner<T> where T: Debug, T: Trait {
    |             ^^^^^     ^^^^^^^^                    ----- unsatisfied trait bound introduced here
    = note: 1 redundant requirement hidden
    = note: required for `&d::Inner<T>` to implement `Debug`
-   = note: required for the cast from `&d::Inner<T>` to the object type `dyn Debug`
+   = note: required for the cast from `&&d::Inner<T>` to `&dyn Debug`
    = note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info)
 help: consider restricting type parameter `T`
    |
@@ -80,7 +80,7 @@ LL |     impl<T> Debug for Inner<T> where T: Debug + Trait {
    |             ^^^^^     ^^^^^^^^                  ----- unsatisfied trait bound introduced here
    = note: 1 redundant requirement hidden
    = note: required for `&e::Inner<T>` to implement `Debug`
-   = note: required for the cast from `&e::Inner<T>` to the object type `dyn Debug`
+   = note: required for the cast from `&&e::Inner<T>` to `&dyn Debug`
    = note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info)
 help: consider restricting type parameter `T`
    |
@@ -102,7 +102,7 @@ LL |     impl<T: Debug> Debug for Inner<T> where T: Trait {
    |                    ^^^^^     ^^^^^^^^          ----- unsatisfied trait bound introduced here
    = note: 1 redundant requirement hidden
    = note: required for `&f::Inner<T>` to implement `Debug`
-   = note: required for the cast from `&f::Inner<T>` to the object type `dyn Debug`
+   = note: required for the cast from `&&f::Inner<T>` to `&dyn Debug`
    = note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info)
 help: consider restricting type parameter `T`
    |
diff --git a/tests/ui/suggestions/issue-109854.rs b/tests/ui/suggestions/issue-109854.rs
new file mode 100644
index 00000000000..dd4542dd71f
--- /dev/null
+++ b/tests/ui/suggestions/issue-109854.rs
@@ -0,0 +1,12 @@
+fn generate_setter() {
+    String::with_capacity(
+    //~^ ERROR this function takes 1 argument but 3 arguments were supplied
+    generate_setter,
+    r#"
+pub(crate) struct Person<T: Clone> {}
+"#,
+     r#""#,
+    );
+}
+
+fn main() {}
diff --git a/tests/ui/suggestions/issue-109854.stderr b/tests/ui/suggestions/issue-109854.stderr
new file mode 100644
index 00000000000..621a3897165
--- /dev/null
+++ b/tests/ui/suggestions/issue-109854.stderr
@@ -0,0 +1,31 @@
+error[E0061]: this function takes 1 argument but 3 arguments were supplied
+  --> $DIR/issue-109854.rs:2:5
+   |
+LL |       String::with_capacity(
+   |       ^^^^^^^^^^^^^^^^^^^^^
+...
+LL | /     r#"
+LL | | pub(crate) struct Person<T: Clone> {}
+LL | | "#,
+   | |__- unexpected argument of type `&'static str`
+LL |        r#""#,
+   |        ----- unexpected argument of type `&'static str`
+   |
+note: expected `usize`, found fn item
+  --> $DIR/issue-109854.rs:4:5
+   |
+LL |     generate_setter,
+   |     ^^^^^^^^^^^^^^^
+   = note: expected type `usize`
+           found fn item `fn() {generate_setter}`
+note: associated function defined here
+  --> $SRC_DIR/alloc/src/string.rs:LL:COL
+help: remove the extra arguments
+   |
+LL -     generate_setter,
+LL +     /* usize */,
+   |
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0061`.
diff --git a/tests/ui/suggestions/issue-94171.rs b/tests/ui/suggestions/issue-94171.rs
new file mode 100644
index 00000000000..cbb9f9cec72
--- /dev/null
+++ b/tests/ui/suggestions/issue-94171.rs
@@ -0,0 +1,5 @@
+fn L(]{match
+(; {`
+//~^^ ERROR mismatched closing delimiter
+//~^^ ERROR unknown start of token
+//~ ERROR this file contains an unclosed delimiter
diff --git a/tests/ui/suggestions/issue-94171.stderr b/tests/ui/suggestions/issue-94171.stderr
new file mode 100644
index 00000000000..b3440e46e8a
--- /dev/null
+++ b/tests/ui/suggestions/issue-94171.stderr
@@ -0,0 +1,36 @@
+error: unknown start of token: `
+  --> $DIR/issue-94171.rs:2:5
+   |
+LL | (; {`
+   |     ^
+   |
+help: Unicode character '`' (Grave Accent) looks like ''' (Single Quote), but it is not
+   |
+LL | (; {'
+   |     ~
+
+error: mismatched closing delimiter: `]`
+  --> $DIR/issue-94171.rs:1:5
+   |
+LL | fn L(]{match
+   |     ^^ mismatched closing delimiter
+   |     |
+   |     unclosed delimiter
+
+error: this file contains an unclosed delimiter
+  --> $DIR/issue-94171.rs:5:52
+   |
+LL | fn L(]{match
+   |      -- unclosed delimiter
+   |      |
+   |      missing open `[` for this delimiter
+LL | (; {`
+   | -  - unclosed delimiter
+   | |
+   | unclosed delimiter
+...
+LL |
+   |                                                    ^
+
+error: aborting due to 3 previous errors
+
diff --git a/tests/ui/suggestions/issue-99597.rs b/tests/ui/suggestions/issue-99597.rs
new file mode 100644
index 00000000000..8ba9e1fdd62
--- /dev/null
+++ b/tests/ui/suggestions/issue-99597.rs
@@ -0,0 +1,15 @@
+#![allow(dead_code)]
+
+trait T1 { }
+
+trait T2 {
+    fn test(&self) { }
+}
+
+fn go(s: &impl T1) {
+    //~^ SUGGESTION (
+    s.test();
+    //~^ ERROR no method named `test`
+}
+
+fn main() { }
diff --git a/tests/ui/suggestions/issue-99597.stderr b/tests/ui/suggestions/issue-99597.stderr
new file mode 100644
index 00000000000..bdf2a07c143
--- /dev/null
+++ b/tests/ui/suggestions/issue-99597.stderr
@@ -0,0 +1,15 @@
+error[E0599]: no method named `test` found for reference `&impl T1` in the current scope
+  --> $DIR/issue-99597.rs:11:7
+   |
+LL |     s.test();
+   |       ^^^^ method not found in `&impl T1`
+   |
+   = help: items from traits can only be used if the type parameter is bounded by the trait
+help: the following trait defines an item `test`, perhaps you need to restrict type parameter `impl T1` with it:
+   |
+LL | fn go(s: &(impl T1 + T2)) {
+   |           +        +++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/tests/ui/suggestions/suggest-borrow-to-dyn-object.rs b/tests/ui/suggestions/suggest-borrow-to-dyn-object.rs
deleted file mode 100644
index 120fc538307..00000000000
--- a/tests/ui/suggestions/suggest-borrow-to-dyn-object.rs
+++ /dev/null
@@ -1,16 +0,0 @@
-use std::ffi::{OsStr, OsString};
-use std::path::Path;
-
-fn check(p: &dyn AsRef<Path>) {
-    let m = std::fs::metadata(&p);
-    println!("{:?}", &m);
-}
-
-fn main() {
-    let s: OsString = ".".into();
-    let s: &OsStr = &s;
-    check(s);
-    //~^ ERROR the size for values of type `[u8]` cannot be known at compilation time
-    //~| HELP within `OsStr`, the trait `Sized` is not implemented for `[u8]`
-    //~| HELP consider borrowing the value, since `&OsStr` can be coerced into `dyn AsRef<Path>`
-}
diff --git a/tests/ui/suggestions/suggest-borrow-to-dyn-object.stderr b/tests/ui/suggestions/suggest-borrow-to-dyn-object.stderr
deleted file mode 100644
index 365c1016eb3..00000000000
--- a/tests/ui/suggestions/suggest-borrow-to-dyn-object.stderr
+++ /dev/null
@@ -1,18 +0,0 @@
-error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
-  --> $DIR/suggest-borrow-to-dyn-object.rs:12:11
-   |
-LL |     check(s);
-   |           ^ doesn't have a size known at compile-time
-   |
-   = help: within `OsStr`, the trait `Sized` is not implemented for `[u8]`
-note: required because it appears within the type `OsStr`
-  --> $SRC_DIR/std/src/ffi/os_str.rs:LL:COL
-   = note: required for the cast from `OsStr` to the object type `dyn AsRef<Path>`
-help: consider borrowing the value, since `&OsStr` can be coerced into `dyn AsRef<Path>`
-   |
-LL |     check(&s);
-   |           +
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/track-diagnostics/track6.rs b/tests/ui/track-diagnostics/track6.rs
index 307e3101849..fc6f5f23d92 100644
--- a/tests/ui/track-diagnostics/track6.rs
+++ b/tests/ui/track-diagnostics/track6.rs
@@ -1,6 +1,9 @@
 // compile-flags: -Z track-diagnostics
 // error-pattern: created at
 
+// Normalize the emitted location so this doesn't need
+// updating everytime someone adds or removes a line.
+// normalize-stderr-test ".rs:\d+:\d+" -> ".rs:LL:CC"
 
 
 pub trait Foo {
diff --git a/tests/ui/track-diagnostics/track6.stderr b/tests/ui/track-diagnostics/track6.stderr
index 1c7537633ff..89438aea9ad 100644
--- a/tests/ui/track-diagnostics/track6.stderr
+++ b/tests/ui/track-diagnostics/track6.stderr
@@ -1,9 +1,9 @@
 error[E0658]: specialization is unstable
-  --> $DIR/track6.rs:11:5
+  --> $DIR/track6.rs:LL:CC
    |
 LL |     default fn bar() {}
    |     ^^^^^^^^^^^^^^^^^^^
--Ztrack-diagnostics: created at $COMPILER_DIR/rustc_session/src/parse.rs:93:5
+-Ztrack-diagnostics: created at $COMPILER_DIR/rustc_session/src/parse.rs:LL:CC
    |
    = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
    = help: add `#![feature(specialization)]` to the crate attributes to enable
diff --git a/tests/ui/traits/coercion-generic-bad.stderr b/tests/ui/traits/coercion-generic-bad.stderr
index 93d6770eb47..e7e8a796796 100644
--- a/tests/ui/traits/coercion-generic-bad.stderr
+++ b/tests/ui/traits/coercion-generic-bad.stderr
@@ -5,7 +5,7 @@ LL |     let s: Box<dyn Trait<isize>> = Box::new(Struct { person: "Fred" });
    |                                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait<isize>` is not implemented for `Struct`
    |
    = help: the trait `Trait<&'static str>` is implemented for `Struct`
-   = note: required for the cast from `Struct` to the object type `dyn Trait<isize>`
+   = note: required for the cast from `Box<Struct>` to `Box<dyn Trait<isize>>`
 
 error: aborting due to previous error
 
diff --git a/tests/ui/traits/copy-guessing.rs b/tests/ui/traits/copy-guessing.rs
index f031dd9ca48..af25010e3bd 100644
--- a/tests/ui/traits/copy-guessing.rs
+++ b/tests/ui/traits/copy-guessing.rs
@@ -1,5 +1,6 @@
-// run-pass
 #![allow(dead_code)]
+#![allow(dropping_copy_types)]
+
 // "guessing" in trait selection can affect `copy_or_move`. Check that this
 // is correctly handled. I am not sure what is the "correct" behaviour,
 // but we should at least not ICE.
@@ -17,6 +18,7 @@ fn assert_impls_fn<R,T: Fn()->R>(_: &T){}
 
 fn main() {
     let n = None;
+    //~^ ERROR type annotations needed for `Option<T>`
     let e = S(&n);
     let f = || {
         // S being copy is critical for this to work
diff --git a/tests/ui/traits/copy-guessing.stderr b/tests/ui/traits/copy-guessing.stderr
new file mode 100644
index 00000000000..568b7e5a64a
--- /dev/null
+++ b/tests/ui/traits/copy-guessing.stderr
@@ -0,0 +1,14 @@
+error[E0282]: type annotations needed for `Option<T>`
+  --> $DIR/copy-guessing.rs:20:9
+   |
+LL |     let n = None;
+   |         ^
+   |
+help: consider giving `n` an explicit type, where the type for type parameter `T` is specified
+   |
+LL |     let n: Option<T> = None;
+   |          +++++++++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/tests/ui/traits/cycle-cache-err-60010.stderr b/tests/ui/traits/cycle-cache-err-60010.stderr
index 2ff16b4af38..aee41c43aef 100644
--- a/tests/ui/traits/cycle-cache-err-60010.stderr
+++ b/tests/ui/traits/cycle-cache-err-60010.stderr
@@ -1,9 +1,25 @@
-error[E0275]: overflow evaluating the requirement `RootDatabase: RefUnwindSafe`
+error[E0275]: overflow evaluating the requirement `SalsaStorage: RefUnwindSafe`
   --> $DIR/cycle-cache-err-60010.rs:27:13
    |
 LL |     _parse: <ParseQuery as Query<RootDatabase>>::Data,
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
+note: required because it appears within the type `PhantomData<SalsaStorage>`
+  --> $SRC_DIR/core/src/marker.rs:LL:COL
+note: required because it appears within the type `Unique<SalsaStorage>`
+  --> $SRC_DIR/core/src/ptr/unique.rs:LL:COL
+note: required because it appears within the type `Box<SalsaStorage>`
+  --> $SRC_DIR/alloc/src/boxed.rs:LL:COL
+note: required because it appears within the type `Runtime<RootDatabase>`
+  --> $DIR/cycle-cache-err-60010.rs:23:8
+   |
+LL | struct Runtime<DB: Database> {
+   |        ^^^^^^^
+note: required because it appears within the type `RootDatabase`
+  --> $DIR/cycle-cache-err-60010.rs:20:8
+   |
+LL | struct RootDatabase {
+   |        ^^^^^^^^^^^^
 note: required for `RootDatabase` to implement `SourceDatabase`
   --> $DIR/cycle-cache-err-60010.rs:44:9
    |
diff --git a/tests/ui/traits/impl-evaluation-order.rs b/tests/ui/traits/impl-evaluation-order.rs
index 57809d89aa6..2ce0b6b0df8 100644
--- a/tests/ui/traits/impl-evaluation-order.rs
+++ b/tests/ui/traits/impl-evaluation-order.rs
@@ -6,6 +6,8 @@
 
 // check-pass
 
+#![allow(dropping_copy_types)]
+
 trait A {
     type B;
 }
diff --git a/tests/ui/traits/issue-106072.rs b/tests/ui/traits/issue-106072.rs
index 7064a39d21e..b174669545a 100644
--- a/tests/ui/traits/issue-106072.rs
+++ b/tests/ui/traits/issue-106072.rs
@@ -1,5 +1,4 @@
 #[derive(Clone)] //~  trait objects must include the `dyn` keyword
-                 //~| trait objects must include the `dyn` keyword
 struct Foo;
 trait Foo {} //~ the name `Foo` is defined multiple times
 fn main() {}
diff --git a/tests/ui/traits/issue-106072.stderr b/tests/ui/traits/issue-106072.stderr
index f9b7b814663..1037603ceb7 100644
--- a/tests/ui/traits/issue-106072.stderr
+++ b/tests/ui/traits/issue-106072.stderr
@@ -1,5 +1,5 @@
 error[E0428]: the name `Foo` is defined multiple times
-  --> $DIR/issue-106072.rs:4:1
+  --> $DIR/issue-106072.rs:3:1
    |
 LL | struct Foo;
    | ----------- previous definition of the type `Foo` here
@@ -16,15 +16,7 @@ LL | #[derive(Clone)]
    |
    = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error[E0782]: trait objects must include the `dyn` keyword
-  --> $DIR/issue-106072.rs:1:10
-   |
-LL | #[derive(Clone)]
-   |          ^^^^^
-   |
-   = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info)
-
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
 
 Some errors have detailed explanations: E0428, E0782.
 For more information about an error, try `rustc --explain E0428`.
diff --git a/tests/ui/traits/issue-20692.stderr b/tests/ui/traits/issue-20692.stderr
index 2028994cdaa..30e3c9da1a0 100644
--- a/tests/ui/traits/issue-20692.stderr
+++ b/tests/ui/traits/issue-20692.stderr
@@ -27,8 +27,7 @@ LL | trait Array: Sized + Copy {}
    |       |      |
    |       |      ...because it requires `Self: Sized`
    |       this trait cannot be made into an object...
-   = note: required for `&T` to implement `CoerceUnsized<&dyn Array>`
-   = note: required by cast to type `&dyn Array`
+   = note: required for the cast from `&T` to `&dyn Array`
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/traits/issue-38604.stderr b/tests/ui/traits/issue-38604.stderr
index 50d6fb05465..d5327602430 100644
--- a/tests/ui/traits/issue-38604.stderr
+++ b/tests/ui/traits/issue-38604.stderr
@@ -25,8 +25,7 @@ LL | trait Foo where u32: Q<Self> {
    |       ---            ^^^^^^^ ...because it uses `Self` as a type parameter
    |       |
    |       this trait cannot be made into an object...
-   = note: required for `Box<()>` to implement `CoerceUnsized<Box<dyn Foo>>`
-   = note: required by cast to type `Box<dyn Foo>`
+   = note: required for the cast from `Box<()>` to `Box<dyn Foo>`
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/traits/issue-7013.stderr b/tests/ui/traits/issue-7013.stderr
index 9ac5c4725ab..1c0e8bcf185 100644
--- a/tests/ui/traits/issue-7013.stderr
+++ b/tests/ui/traits/issue-7013.stderr
@@ -12,7 +12,7 @@ note: required because it appears within the type `B`
    |
 LL | struct B {
    |        ^
-   = note: required for the cast from `B` to the object type `dyn Foo + Send`
+   = note: required for the cast from `Box<B>` to `Box<dyn Foo + Send>`
 
 error: aborting due to previous error
 
diff --git a/tests/ui/traits/map-types.stderr b/tests/ui/traits/map-types.stderr
index f685c50b07d..4315056f206 100644
--- a/tests/ui/traits/map-types.stderr
+++ b/tests/ui/traits/map-types.stderr
@@ -5,7 +5,7 @@ LL |     let y: Box<dyn Map<usize, isize>> = Box::new(x);
    |                                         ^^^^^^^^^^^ the trait `Map<usize, isize>` is not implemented for `Box<dyn Map<isize, isize>>`
    |
    = help: the trait `Map<K, V>` is implemented for `HashMap<K, V>`
-   = note: required for the cast from `Box<dyn Map<isize, isize>>` to the object type `dyn Map<usize, isize>`
+   = note: required for the cast from `Box<Box<dyn Map<isize, isize>>>` to `Box<dyn Map<usize, isize>>`
 
 error: aborting due to previous error
 
diff --git a/tests/ui/traits/new-solver/auto-with-drop_tracking_mir.fail.stderr b/tests/ui/traits/new-solver/auto-with-drop_tracking_mir.fail.stderr
index 6a926534e07..4aefdd6bb07 100644
--- a/tests/ui/traits/new-solver/auto-with-drop_tracking_mir.fail.stderr
+++ b/tests/ui/traits/new-solver/auto-with-drop_tracking_mir.fail.stderr
@@ -1,5 +1,5 @@
 error[E0277]: `impl Future<Output = ()>` cannot be sent between threads safely
-  --> $DIR/auto-with-drop_tracking_mir.rs:24:13
+  --> $DIR/auto-with-drop_tracking_mir.rs:25:13
    |
 LL |     is_send(foo());
    |     ------- ^^^^^ `impl Future<Output = ()>` cannot be sent between threads safely
@@ -8,7 +8,7 @@ LL |     is_send(foo());
    |
    = help: the trait `Send` is not implemented for `impl Future<Output = ()>`
 note: required by a bound in `is_send`
-  --> $DIR/auto-with-drop_tracking_mir.rs:23:24
+  --> $DIR/auto-with-drop_tracking_mir.rs:24:24
    |
 LL |     fn is_send(_: impl Send) {}
    |                        ^^^^ required by this bound in `is_send`
diff --git a/tests/ui/traits/new-solver/auto-with-drop_tracking_mir.rs b/tests/ui/traits/new-solver/auto-with-drop_tracking_mir.rs
index a5db7c4636b..e311a4af2f4 100644
--- a/tests/ui/traits/new-solver/auto-with-drop_tracking_mir.rs
+++ b/tests/ui/traits/new-solver/auto-with-drop_tracking_mir.rs
@@ -14,6 +14,7 @@ async fn foo() {
     #[cfg(fail)]
     let x = &NotSync;
     bar().await;
+    #[allow(dropping_references)]
     drop(x);
 }
 
diff --git a/tests/ui/traits/new-solver/normalize-rcvr-for-inherent.rs b/tests/ui/traits/new-solver/normalize-rcvr-for-inherent.rs
new file mode 100644
index 00000000000..d70534feb07
--- /dev/null
+++ b/tests/ui/traits/new-solver/normalize-rcvr-for-inherent.rs
@@ -0,0 +1,25 @@
+// compile-flags: -Ztrait-solver=next
+// check-pass
+
+// Verify that we can assemble inherent impl candidates on a possibly
+// unnormalized self type.
+
+trait Foo {
+    type Assoc;
+}
+impl Foo for i32 {
+    type Assoc = Bar;
+}
+
+struct Bar;
+impl Bar {
+    fn method(&self) {}
+}
+
+fn build<T: Foo>(_: T) -> T::Assoc {
+    todo!()
+}
+
+fn main() {
+    build(1i32).method();
+}
diff --git a/tests/ui/traits/new-solver/structural-resolve-field.rs b/tests/ui/traits/new-solver/structural-resolve-field.rs
new file mode 100644
index 00000000000..01899c9ad64
--- /dev/null
+++ b/tests/ui/traits/new-solver/structural-resolve-field.rs
@@ -0,0 +1,13 @@
+// compile-flags: -Ztrait-solver=next
+// check-pass
+
+#[derive(Default)]
+struct Foo {
+    x: i32,
+}
+
+fn main() {
+    let mut xs = <[Foo; 1]>::default();
+    xs[0].x = 1;
+    (&mut xs[0]).x = 2;
+}
diff --git a/tests/ui/traits/new-solver/temporary-ambiguity.rs b/tests/ui/traits/new-solver/temporary-ambiguity.rs
index 18ee0545700..c6c11a1a1de 100644
--- a/tests/ui/traits/new-solver/temporary-ambiguity.rs
+++ b/tests/ui/traits/new-solver/temporary-ambiguity.rs
@@ -18,5 +18,5 @@ fn main() {
     let w = Wrapper(x);
     needs_foo(w);
     x = 1;
-    drop(x);
+    let _ = x;
 }
diff --git a/tests/ui/traits/non_lifetime_binders/supertrait-object-safety.stderr b/tests/ui/traits/non_lifetime_binders/supertrait-object-safety.stderr
index 47fa29b6648..d56519223f4 100644
--- a/tests/ui/traits/non_lifetime_binders/supertrait-object-safety.stderr
+++ b/tests/ui/traits/non_lifetime_binders/supertrait-object-safety.stderr
@@ -20,8 +20,7 @@ LL | trait Foo: for<T> Bar<T> {}
    |       ---  ^^^^^^^^^^^^^ ...because where clause cannot reference non-lifetime `for<...>` variables
    |       |
    |       this trait cannot be made into an object...
-   = note: required for `&()` to implement `CoerceUnsized<&dyn Foo>`
-   = note: required by cast to type `&dyn Foo`
+   = note: required for the cast from `&()` to `&dyn Foo`
 
 error[E0038]: the trait `Foo` cannot be made into an object
   --> $DIR/supertrait-object-safety.rs:19:12
diff --git a/tests/ui/traits/non_lifetime_binders/universe-error1.rs b/tests/ui/traits/non_lifetime_binders/universe-error1.rs
new file mode 100644
index 00000000000..eadee6b711e
--- /dev/null
+++ b/tests/ui/traits/non_lifetime_binders/universe-error1.rs
@@ -0,0 +1,18 @@
+#![feature(non_lifetime_binders)]
+//~^ WARN the feature `non_lifetime_binders` is incomplete
+
+trait Other<U: ?Sized> {}
+
+impl<U: ?Sized> Other<U> for U {}
+
+#[rustfmt::skip]
+fn foo<U: ?Sized>()
+where
+    for<T> T: Other<U> {}
+
+fn bar() {
+    foo::<_>();
+    //~^ ERROR the trait bound `T: Other<_>` is not satisfied
+}
+
+fn main() {}
diff --git a/tests/ui/traits/non_lifetime_binders/universe-error1.stderr b/tests/ui/traits/non_lifetime_binders/universe-error1.stderr
new file mode 100644
index 00000000000..bfcad72e352
--- /dev/null
+++ b/tests/ui/traits/non_lifetime_binders/universe-error1.stderr
@@ -0,0 +1,27 @@
+warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/universe-error1.rs:1:12
+   |
+LL | #![feature(non_lifetime_binders)]
+   |            ^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+error[E0277]: the trait bound `T: Other<_>` is not satisfied
+  --> $DIR/universe-error1.rs:14:11
+   |
+LL |     foo::<_>();
+   |           ^ the trait `Other<_>` is not implemented for `T`
+   |
+note: required by a bound in `foo`
+  --> $DIR/universe-error1.rs:11:15
+   |
+LL | fn foo<U: ?Sized>()
+   |    --- required by a bound in this function
+LL | where
+LL |     for<T> T: Other<U> {}
+   |               ^^^^^^^^ required by this bound in `foo`
+
+error: aborting due to previous error; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/object/safety.stderr b/tests/ui/traits/object/safety.stderr
index dc18adeafc7..a51b6975938 100644
--- a/tests/ui/traits/object/safety.stderr
+++ b/tests/ui/traits/object/safety.stderr
@@ -11,8 +11,7 @@ LL | trait Tr {
    |       -- this trait cannot be made into an object...
 LL |     fn foo();
    |        ^^^ ...because associated function `foo` has no `self` parameter
-   = note: required for `&St` to implement `CoerceUnsized<&dyn Tr>`
-   = note: required by cast to type `&dyn Tr`
+   = note: required for the cast from `&St` to `&dyn Tr`
 help: consider turning `foo` into a method by giving it a `&self` argument
    |
 LL |     fn foo(&self);
diff --git a/tests/ui/traits/solver-cycles/cycle-via-builtin-auto-trait-impl.rs b/tests/ui/traits/solver-cycles/cycle-via-builtin-auto-trait-impl.rs
new file mode 100644
index 00000000000..d37943b929a
--- /dev/null
+++ b/tests/ui/traits/solver-cycles/cycle-via-builtin-auto-trait-impl.rs
@@ -0,0 +1,34 @@
+//~ ERROR overflow
+// A regression test for #111729 checking that we correctly
+// track recursion depth for obligations returned by confirmation.
+use std::panic::RefUnwindSafe;
+
+trait Database {
+    type Storage;
+}
+trait Query<DB> {
+    type Data;
+}
+struct ParseQuery;
+struct RootDatabase {
+    _runtime: Runtime<RootDatabase>,
+}
+
+impl<T: RefUnwindSafe> Database for T {
+    type Storage = SalsaStorage;
+}
+impl Database for RootDatabase {
+    type Storage = SalsaStorage;
+}
+
+struct Runtime<DB: Database> {
+    _storage: Box<DB::Storage>,
+}
+struct SalsaStorage {
+    _parse: <ParseQuery as Query<RootDatabase>>::Data,
+}
+
+impl<DB: Database> Query<DB> for ParseQuery {
+    type Data = RootDatabase;
+}
+fn main() {}
diff --git a/tests/ui/traits/solver-cycles/cycle-via-builtin-auto-trait-impl.stderr b/tests/ui/traits/solver-cycles/cycle-via-builtin-auto-trait-impl.stderr
new file mode 100644
index 00000000000..8f9ce3ef1e9
--- /dev/null
+++ b/tests/ui/traits/solver-cycles/cycle-via-builtin-auto-trait-impl.stderr
@@ -0,0 +1,24 @@
+error[E0275]: overflow evaluating the requirement `Runtime<RootDatabase>: RefUnwindSafe`
+   |
+   = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`cycle_via_builtin_auto_trait_impl`)
+note: required because it appears within the type `RootDatabase`
+  --> $DIR/cycle-via-builtin-auto-trait-impl.rs:13:8
+   |
+LL | struct RootDatabase {
+   |        ^^^^^^^^^^^^
+note: required for `RootDatabase` to implement `Database`
+  --> $DIR/cycle-via-builtin-auto-trait-impl.rs:17:24
+   |
+LL | impl<T: RefUnwindSafe> Database for T {
+   |         -------------  ^^^^^^^^     ^
+   |         |
+   |         unsatisfied trait bound introduced here
+note: required because it appears within the type `Runtime<RootDatabase>`
+  --> $DIR/cycle-via-builtin-auto-trait-impl.rs:24:8
+   |
+LL | struct Runtime<DB: Database> {
+   |        ^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0275`.
diff --git a/tests/ui/traits/test-2.stderr b/tests/ui/traits/test-2.stderr
index 6c0e8b8af4b..74a0fc42708 100644
--- a/tests/ui/traits/test-2.stderr
+++ b/tests/ui/traits/test-2.stderr
@@ -76,8 +76,7 @@ LL | trait bar { fn dup(&self) -> Self; fn blah<X>(&self); }
    |       this trait cannot be made into an object...
    = help: consider moving `dup` to another trait
    = help: consider moving `blah` to another trait
-   = note: required for `Box<{integer}>` to implement `CoerceUnsized<Box<dyn bar>>`
-   = note: required by cast to type `Box<dyn bar>`
+   = note: required for the cast from `Box<{integer}>` to `Box<dyn bar>`
 
 error: aborting due to 5 previous errors
 
diff --git a/tests/ui/traits/trait-upcasting/type-checking-test-1.stderr b/tests/ui/traits/trait-upcasting/type-checking-test-1.stderr
index fe269d8e99b..82b4e9bd72a 100644
--- a/tests/ui/traits/trait-upcasting/type-checking-test-1.stderr
+++ b/tests/ui/traits/trait-upcasting/type-checking-test-1.stderr
@@ -15,7 +15,7 @@ error[E0277]: the trait bound `&dyn Foo: Bar<_>` is not satisfied
 LL |     let _ = x as &dyn Bar<_>; // Ambiguous
    |             ^ the trait `Bar<_>` is not implemented for `&dyn Foo`
    |
-   = note: required for the cast from `&dyn Foo` to the object type `dyn Bar<_>`
+   = note: required for the cast from `&&dyn Foo` to `&dyn Bar<_>`
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/traits/trait-upcasting/type-checking-test-2.stderr b/tests/ui/traits/trait-upcasting/type-checking-test-2.stderr
index ef007d5cb90..856303ef4dd 100644
--- a/tests/ui/traits/trait-upcasting/type-checking-test-2.stderr
+++ b/tests/ui/traits/trait-upcasting/type-checking-test-2.stderr
@@ -15,7 +15,7 @@ error[E0277]: the trait bound `&dyn Foo<i32>: Bar<u32>` is not satisfied
 LL |     let _ = x as &dyn Bar<u32>; // Error
    |             ^ the trait `Bar<u32>` is not implemented for `&dyn Foo<i32>`
    |
-   = note: required for the cast from `&dyn Foo<i32>` to the object type `dyn Bar<u32>`
+   = note: required for the cast from `&&dyn Foo<i32>` to `&dyn Bar<u32>`
 
 error[E0605]: non-primitive cast: `&dyn Foo<u32>` as `&dyn Bar<_>`
   --> $DIR/type-checking-test-2.rs:25:13
@@ -34,7 +34,7 @@ error[E0277]: the trait bound `&dyn Foo<u32>: Bar<_>` is not satisfied
 LL |     let a = x as &dyn Bar<_>; // Ambiguous
    |             ^ the trait `Bar<_>` is not implemented for `&dyn Foo<u32>`
    |
-   = note: required for the cast from `&dyn Foo<u32>` to the object type `dyn Bar<_>`
+   = note: required for the cast from `&&dyn Foo<u32>` to `&dyn Bar<_>`
 
 error: aborting due to 4 previous errors
 
diff --git a/tests/ui/trivial-bounds/trivial-bounds-inconsistent-copy.rs b/tests/ui/trivial-bounds/trivial-bounds-inconsistent-copy.rs
index 3416503b851..f98c3164d7e 100644
--- a/tests/ui/trivial-bounds/trivial-bounds-inconsistent-copy.rs
+++ b/tests/ui/trivial-bounds/trivial-bounds-inconsistent-copy.rs
@@ -1,6 +1,8 @@
 // check-pass
 // Check tautalogically false `Copy` bounds
+
 #![feature(trivial_bounds)]
+#![allow(dropping_references, dropping_copy_types)]
 
 fn copy_string(t: String) -> String where String: Copy { //~ WARNING trivial_bounds
     is_copy(&t);
diff --git a/tests/ui/trivial-bounds/trivial-bounds-inconsistent-copy.stderr b/tests/ui/trivial-bounds/trivial-bounds-inconsistent-copy.stderr
index 1e26623899b..deeb352a2a8 100644
--- a/tests/ui/trivial-bounds/trivial-bounds-inconsistent-copy.stderr
+++ b/tests/ui/trivial-bounds/trivial-bounds-inconsistent-copy.stderr
@@ -1,5 +1,5 @@
 warning: trait bound String: Copy does not depend on any type or lifetime parameters
-  --> $DIR/trivial-bounds-inconsistent-copy.rs:5:51
+  --> $DIR/trivial-bounds-inconsistent-copy.rs:7:51
    |
 LL | fn copy_string(t: String) -> String where String: Copy {
    |                                                   ^^^^
@@ -7,19 +7,19 @@ LL | fn copy_string(t: String) -> String where String: Copy {
    = note: `#[warn(trivial_bounds)]` on by default
 
 warning: trait bound String: Copy does not depend on any type or lifetime parameters
-  --> $DIR/trivial-bounds-inconsistent-copy.rs:12:56
+  --> $DIR/trivial-bounds-inconsistent-copy.rs:14:56
    |
 LL | fn copy_out_string(t: &String) -> String where String: Copy {
    |                                                        ^^^^
 
 warning: trait bound String: Copy does not depend on any type or lifetime parameters
-  --> $DIR/trivial-bounds-inconsistent-copy.rs:16:55
+  --> $DIR/trivial-bounds-inconsistent-copy.rs:18:55
    |
 LL | fn copy_string_with_param<T>(x: String) where String: Copy {
    |                                                       ^^^^
 
 warning: trait bound for<'b> &'b mut i32: Copy does not depend on any type or lifetime parameters
-  --> $DIR/trivial-bounds-inconsistent-copy.rs:22:76
+  --> $DIR/trivial-bounds-inconsistent-copy.rs:24:76
    |
 LL | fn copy_mut<'a>(t: &&'a mut i32) -> &'a mut i32 where for<'b> &'b mut i32: Copy {
    |                                                                            ^^^^
diff --git a/tests/ui/type-alias-impl-trait/associated-type-impl-trait-lifetime.rs b/tests/ui/type-alias-impl-trait/associated-type-impl-trait-lifetime.rs
index 551815d021a..58eaa9c2c42 100644
--- a/tests/ui/type-alias-impl-trait/associated-type-impl-trait-lifetime.rs
+++ b/tests/ui/type-alias-impl-trait/associated-type-impl-trait-lifetime.rs
@@ -5,15 +5,16 @@
 trait Trait {
     type Opaque1;
     type Opaque2;
-    fn constrain(self);
+    fn constrain(self) -> (Self::Opaque1, Self::Opaque2);
 }
 
 impl<'a> Trait for &'a () {
     type Opaque1 = impl Sized;
     type Opaque2 = impl Sized + 'a;
-    fn constrain(self) {
-        let _: Self::Opaque1 = ();
-        let _: Self::Opaque2 = self;
+    fn constrain(self) -> (Self::Opaque1, Self::Opaque2) {
+        let a: Self::Opaque1 = ();
+        let b: Self::Opaque2 = self;
+        (a, b)
     }
 }
 
diff --git a/tests/ui/type-alias-impl-trait/invalid_impl_trait_in_assoc_ty.rs b/tests/ui/type-alias-impl-trait/invalid_impl_trait_in_assoc_ty.rs
new file mode 100644
index 00000000000..93c52126d69
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/invalid_impl_trait_in_assoc_ty.rs
@@ -0,0 +1,16 @@
+#![feature(impl_trait_in_assoc_type)]
+
+trait Foo {
+    type Foo;
+    fn bar();
+}
+
+impl Foo for () {
+    type Foo = impl std::fmt::Debug;
+    fn bar() {
+        let x: Self::Foo = ();
+        //~^ ERROR: mismatched types
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/invalid_impl_trait_in_assoc_ty.stderr b/tests/ui/type-alias-impl-trait/invalid_impl_trait_in_assoc_ty.stderr
new file mode 100644
index 00000000000..2beed73cb85
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/invalid_impl_trait_in_assoc_ty.stderr
@@ -0,0 +1,22 @@
+error[E0308]: mismatched types
+  --> $DIR/invalid_impl_trait_in_assoc_ty.rs:11:28
+   |
+LL |     type Foo = impl std::fmt::Debug;
+   |                -------------------- the expected opaque type
+LL |     fn bar() {
+LL |         let x: Self::Foo = ();
+   |                ---------   ^^ expected opaque type, found `()`
+   |                |
+   |                expected due to this
+   |
+   = note: expected opaque type `<() as Foo>::Foo`
+                found unit type `()`
+note: this item must have the opaque type in its signature in order to be able to register hidden types
+  --> $DIR/invalid_impl_trait_in_assoc_ty.rs:10:5
+   |
+LL |     fn bar() {
+   |     ^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/type-alias-impl-trait/issue-98604.stderr b/tests/ui/type-alias-impl-trait/issue-98604.stderr
index fa16d321890..af758d8099f 100644
--- a/tests/ui/type-alias-impl-trait/issue-98604.stderr
+++ b/tests/ui/type-alias-impl-trait/issue-98604.stderr
@@ -4,7 +4,7 @@ error[E0271]: expected `test` to be a fn item that returns `Pin<Box<dyn Future<O
 LL |     Box::new(test) as AsyncFnPtr;
    |     ^^^^^^^^^^^^^^ expected `Pin<Box<dyn Future<Output = ()>>>`, found future
    |
-   = note: required for the cast from `fn() -> impl Future<Output = ()> {test}` to the object type `dyn Fn() -> Pin<Box<(dyn Future<Output = ()> + 'static)>>`
+   = note: required for the cast from `Box<fn() -> impl Future<Output = ()> {test}>` to `Box<(dyn Fn() -> Pin<Box<(dyn Future<Output = ()> + 'static)>> + 'static)>`
 
 error: aborting due to previous error
 
diff --git a/tests/ui/type-alias-impl-trait/issue-98608.stderr b/tests/ui/type-alias-impl-trait/issue-98608.stderr
index 506d40cb776..9b651008371 100644
--- a/tests/ui/type-alias-impl-trait/issue-98608.stderr
+++ b/tests/ui/type-alias-impl-trait/issue-98608.stderr
@@ -9,7 +9,7 @@ LL |     let b: Box<dyn Fn() -> Box<u8>> = Box::new(hi);
    |
    = note:   expected struct `Box<u8>`
            found opaque type `impl Sized`
-   = note: required for the cast from `fn() -> impl Sized {hi}` to the object type `dyn Fn() -> Box<u8>`
+   = note: required for the cast from `Box<fn() -> impl Sized {hi}>` to `Box<dyn Fn() -> Box<u8>>`
 
 error: aborting due to previous error
 
diff --git a/tests/ui/type/issue-58355.stderr b/tests/ui/type/issue-58355.stderr
index 6f89a7b0049..67078bcfe89 100644
--- a/tests/ui/type/issue-58355.stderr
+++ b/tests/ui/type/issue-58355.stderr
@@ -6,7 +6,7 @@ LL |     x = Some(Box::new(callback));
    |
    = help: within `fn() -> dyn ToString`, the trait `Sized` is not implemented for `dyn ToString`
    = note: required because it appears within the type `fn() -> dyn ToString`
-   = note: required for the cast from `fn() -> dyn ToString` to the object type `dyn Fn() -> (dyn ToString + 'static)`
+   = note: required for the cast from `Box<fn() -> dyn ToString>` to `Box<dyn Fn() -> (dyn ToString + 'static)>`
 
 error: aborting due to previous error
 
diff --git a/tests/ui/type/type-dependent-def-issue-49241.rs b/tests/ui/type/type-dependent-def-issue-49241.rs
index caf5bade5c7..4b6bc6124db 100644
--- a/tests/ui/type/type-dependent-def-issue-49241.rs
+++ b/tests/ui/type/type-dependent-def-issue-49241.rs
@@ -2,5 +2,4 @@ fn main() {
     let v = vec![0];
     const l: usize = v.count(); //~ ERROR attempt to use a non-constant value in a constant
     let s: [u32; l] = v.into_iter().collect();
-    //~^ constant
 }
diff --git a/tests/ui/type/type-dependent-def-issue-49241.stderr b/tests/ui/type/type-dependent-def-issue-49241.stderr
index af16a6e8f84..64c7687f7a8 100644
--- a/tests/ui/type/type-dependent-def-issue-49241.stderr
+++ b/tests/ui/type/type-dependent-def-issue-49241.stderr
@@ -6,12 +6,6 @@ LL |     const l: usize = v.count();
    |     |
    |     help: consider using `let` instead of `const`: `let l`
 
-note: erroneous constant used
-  --> $DIR/type-dependent-def-issue-49241.rs:4:18
-   |
-LL |     let s: [u32; l] = v.into_iter().collect();
-   |                  ^
-
 error: aborting due to previous error
 
 For more information about this error, try `rustc --explain E0435`.
diff --git a/tests/ui/type/type-path-err-node-types.stderr b/tests/ui/type/type-path-err-node-types.stderr
index 1aed1dbe4ba..8b12aa1a393 100644
--- a/tests/ui/type/type-path-err-node-types.stderr
+++ b/tests/ui/type/type-path-err-node-types.stderr
@@ -1,9 +1,3 @@
-error[E0433]: failed to resolve: use of undeclared type `NonExistent`
-  --> $DIR/type-path-err-node-types.rs:15:5
-   |
-LL |     NonExistent::Assoc::<u8>;
-   |     ^^^^^^^^^^^ use of undeclared type `NonExistent`
-
 error[E0412]: cannot find type `Nonexistent` in this scope
   --> $DIR/type-path-err-node-types.rs:7:12
    |
@@ -22,6 +16,12 @@ error[E0425]: cannot find value `nonexistent` in this scope
 LL |     nonexistent.nonexistent::<u8>();
    |     ^^^^^^^^^^^ not found in this scope
 
+error[E0433]: failed to resolve: use of undeclared type `NonExistent`
+  --> $DIR/type-path-err-node-types.rs:15:5
+   |
+LL |     NonExistent::Assoc::<u8>;
+   |     ^^^^^^^^^^^ use of undeclared type `NonExistent`
+
 error[E0282]: type annotations needed
   --> $DIR/type-path-err-node-types.rs:23:14
    |
diff --git a/tests/ui/underscore-imports/issue-110164.rs b/tests/ui/underscore-imports/issue-110164.rs
new file mode 100644
index 00000000000..6fd13414500
--- /dev/null
+++ b/tests/ui/underscore-imports/issue-110164.rs
@@ -0,0 +1,19 @@
+use self::*;
+//~^ ERROR unresolved import `self::*`
+use crate::*;
+//~^ ERROR unresolved import `crate::*`
+use _::a;
+//~^ ERROR expected identifier, found reserved identifier `_`
+//~| ERROR unresolved import `_`
+use _::*;
+//~^ ERROR expected identifier, found reserved identifier `_`
+//~| ERROR unresolved import `_`
+
+fn main() {
+    use _::a;
+    //~^ ERROR expected identifier, found reserved identifier `_`
+    //~| ERROR unresolved import `_`
+    use _::*;
+    //~^ ERROR expected identifier, found reserved identifier `_`
+    //~| ERROR unresolved import `_`
+}
diff --git a/tests/ui/underscore-imports/issue-110164.stderr b/tests/ui/underscore-imports/issue-110164.stderr
new file mode 100644
index 00000000000..5016c41e8a5
--- /dev/null
+++ b/tests/ui/underscore-imports/issue-110164.stderr
@@ -0,0 +1,71 @@
+error: expected identifier, found reserved identifier `_`
+  --> $DIR/issue-110164.rs:5:5
+   |
+LL | use _::a;
+   |     ^ expected identifier, found reserved identifier
+
+error: expected identifier, found reserved identifier `_`
+  --> $DIR/issue-110164.rs:8:5
+   |
+LL | use _::*;
+   |     ^ expected identifier, found reserved identifier
+
+error: expected identifier, found reserved identifier `_`
+  --> $DIR/issue-110164.rs:13:9
+   |
+LL |     use _::a;
+   |         ^ expected identifier, found reserved identifier
+
+error: expected identifier, found reserved identifier `_`
+  --> $DIR/issue-110164.rs:16:9
+   |
+LL |     use _::*;
+   |         ^ expected identifier, found reserved identifier
+
+error[E0432]: unresolved import `self::*`
+  --> $DIR/issue-110164.rs:1:5
+   |
+LL | use self::*;
+   |     ^^^^^^^ cannot glob-import a module into itself
+
+error[E0432]: unresolved import `crate::*`
+  --> $DIR/issue-110164.rs:3:5
+   |
+LL | use crate::*;
+   |     ^^^^^^^^ cannot glob-import a module into itself
+
+error[E0432]: unresolved import `_`
+  --> $DIR/issue-110164.rs:8:5
+   |
+LL | use _::*;
+   |     ^ maybe a missing crate `_`?
+   |
+   = help: consider adding `extern crate _` to use the `_` crate
+
+error[E0432]: unresolved import `_`
+  --> $DIR/issue-110164.rs:5:5
+   |
+LL | use _::a;
+   |     ^ maybe a missing crate `_`?
+   |
+   = help: consider adding `extern crate _` to use the `_` crate
+
+error[E0432]: unresolved import `_`
+  --> $DIR/issue-110164.rs:13:9
+   |
+LL |     use _::a;
+   |         ^ maybe a missing crate `_`?
+   |
+   = help: consider adding `extern crate _` to use the `_` crate
+
+error[E0432]: unresolved import `_`
+  --> $DIR/issue-110164.rs:16:9
+   |
+LL |     use _::*;
+   |         ^ maybe a missing crate `_`?
+   |
+   = help: consider adding `extern crate _` to use the `_` crate
+
+error: aborting due to 10 previous errors
+
+For more information about this error, try `rustc --explain E0432`.
diff --git a/tests/ui/unsized-locals/align.rs b/tests/ui/unsized-locals/align.rs
new file mode 100644
index 00000000000..01be8f3bb9c
--- /dev/null
+++ b/tests/ui/unsized-locals/align.rs
@@ -0,0 +1,30 @@
+// Test that unsized locals uphold alignment requirements.
+// Regression test for #71416.
+// run-pass
+#![feature(unsized_locals)]
+#![allow(incomplete_features)]
+use std::any::Any;
+
+#[repr(align(256))]
+#[allow(dead_code)]
+struct A {
+    v: u8
+}
+
+impl A {
+    fn f(&self) -> *const A {
+        assert_eq!(self as *const A as usize % 256, 0);
+        self
+    }
+}
+
+fn mk() -> Box<dyn Any> {
+    Box::new(A { v: 4 })
+}
+
+fn main() {
+    let x = *mk();
+    let dwncst = x.downcast_ref::<A>().unwrap();
+    let addr = dwncst.f();
+    assert_eq!(addr as usize % 256, 0);
+}
diff --git a/tests/ui/unsized/unsized-fn-param.stderr b/tests/ui/unsized/unsized-fn-param.stderr
index b4772605432..0de3dbbb557 100644
--- a/tests/ui/unsized/unsized-fn-param.stderr
+++ b/tests/ui/unsized/unsized-fn-param.stderr
@@ -5,8 +5,8 @@ LL |     foo11("bar", &"baz");
    |           ^^^^^ doesn't have a size known at compile-time
    |
    = help: the trait `Sized` is not implemented for `str`
-   = note: required for the cast from `str` to the object type `dyn AsRef<Path>`
-help: consider borrowing the value, since `&str` can be coerced into `dyn AsRef<Path>`
+   = note: required for the cast from `&'static str` to `&dyn AsRef<Path>`
+help: consider borrowing the value, since `&&'static str` can be coerced into `&dyn AsRef<Path>`
    |
 LL |     foo11(&"bar", &"baz");
    |           +
@@ -18,8 +18,8 @@ LL |     foo12(&"bar", "baz");
    |                   ^^^^^ doesn't have a size known at compile-time
    |
    = help: the trait `Sized` is not implemented for `str`
-   = note: required for the cast from `str` to the object type `dyn AsRef<Path>`
-help: consider borrowing the value, since `&str` can be coerced into `dyn AsRef<Path>`
+   = note: required for the cast from `&'static str` to `&dyn AsRef<Path>`
+help: consider borrowing the value, since `&&'static str` can be coerced into `&dyn AsRef<Path>`
    |
 LL |     foo12(&"bar", &"baz");
    |                   +
@@ -31,8 +31,8 @@ LL |     foo21("bar", &"baz");
    |           ^^^^^ doesn't have a size known at compile-time
    |
    = help: the trait `Sized` is not implemented for `str`
-   = note: required for the cast from `str` to the object type `dyn AsRef<str>`
-help: consider borrowing the value, since `&str` can be coerced into `dyn AsRef<str>`
+   = note: required for the cast from `&'static str` to `&dyn AsRef<str>`
+help: consider borrowing the value, since `&&'static str` can be coerced into `&dyn AsRef<str>`
    |
 LL |     foo21(&"bar", &"baz");
    |           +
@@ -44,8 +44,8 @@ LL |     foo22(&"bar", "baz");
    |                   ^^^^^ doesn't have a size known at compile-time
    |
    = help: the trait `Sized` is not implemented for `str`
-   = note: required for the cast from `str` to the object type `dyn AsRef<str>`
-help: consider borrowing the value, since `&str` can be coerced into `dyn AsRef<str>`
+   = note: required for the cast from `&'static str` to `&dyn AsRef<str>`
+help: consider borrowing the value, since `&&'static str` can be coerced into `&dyn AsRef<str>`
    |
 LL |     foo22(&"bar", &"baz");
    |                   +
diff --git a/tests/ui/use/use-self-type.stderr b/tests/ui/use/use-self-type.stderr
index e6153941151..3da04a851f6 100644
--- a/tests/ui/use/use-self-type.stderr
+++ b/tests/ui/use/use-self-type.stderr
@@ -8,7 +8,7 @@ error[E0432]: unresolved import `Self`
   --> $DIR/use-self-type.rs:6:13
    |
 LL |         use Self::f;
-   |             ^^^^ `Self` is only available in impls, traits, and type definitions
+   |             ^^^^ `Self` cannot be used in imports
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/weird-exprs.rs b/tests/ui/weird-exprs.rs
index d65703ef5ca..c4fa850a4f9 100644
--- a/tests/ui/weird-exprs.rs
+++ b/tests/ui/weird-exprs.rs
@@ -5,13 +5,16 @@
 
 #![allow(non_camel_case_types)]
 #![allow(dead_code)]
+#![allow(redundant_semicolons)]
 #![allow(unreachable_code)]
 #![allow(unused_braces, unused_must_use, unused_parens)]
 #![allow(uncommon_codepoints, confusable_idents)]
+#![allow(unused_imports)]
 #![allow(unreachable_patterns)]
 
 #![recursion_limit = "256"]
 
+extern crate core;
 use std::cell::Cell;
 use std::mem::swap;
 
@@ -204,6 +207,30 @@ fn closure_matching() {
     assert!(matches!(x(..), |_| Some(4)));
 }
 
+fn semisemisemisemisemi() {
+    ;;;;;;; ;;;;;;; ;;;    ;;; ;;
+    ;;      ;;      ;;;;  ;;;; ;;
+    ;;;;;;; ;;;;;   ;; ;;;; ;; ;;
+         ;; ;;      ;;  ;;  ;; ;;
+    ;;;;;;; ;;;;;;; ;;      ;; ;;
+}
+
+fn useful_syntax() {
+    use {{std::{{collections::{{HashMap}}}}}};
+    use ::{{{{core}, {std}}}};
+    use {{::{{core as core2}}}};
+}
+
+fn infcx() {
+    pub mod cx {
+        pub mod cx {
+            pub use super::cx;
+            pub struct Cx;
+        }
+    }
+    let _cx: cx::cx::Cx = cx::cx::cx::cx::cx::Cx;
+}
+
 pub fn main() {
     strange();
     funny();
@@ -227,4 +254,7 @@ pub fn main() {
     function();
     bathroom_stall();
     closure_matching();
+    semisemisemisemisemi();
+    useful_syntax();
+    infcx();
 }
diff --git a/tests/ui/wf/wf-convert-unsafe-trait-obj-box.stderr b/tests/ui/wf/wf-convert-unsafe-trait-obj-box.stderr
index 6cf4f33f947..40a25c7df6b 100644
--- a/tests/ui/wf/wf-convert-unsafe-trait-obj-box.stderr
+++ b/tests/ui/wf/wf-convert-unsafe-trait-obj-box.stderr
@@ -11,8 +11,7 @@ LL | trait Trait: Sized {}
    |       -----  ^^^^^ ...because it requires `Self: Sized`
    |       |
    |       this trait cannot be made into an object...
-   = note: required for `Box<S>` to implement `CoerceUnsized<Box<dyn Trait>>`
-   = note: required by cast to type `Box<dyn Trait>`
+   = note: required for the cast from `Box<S>` to `Box<dyn Trait>`
 
 error[E0038]: the trait `Trait` cannot be made into an object
   --> $DIR/wf-convert-unsafe-trait-obj-box.rs:17:15
@@ -27,8 +26,7 @@ LL | trait Trait: Sized {}
    |       -----  ^^^^^ ...because it requires `Self: Sized`
    |       |
    |       this trait cannot be made into an object...
-   = note: required for `Box<S>` to implement `CoerceUnsized<Box<dyn Trait>>`
-   = note: required by cast to type `Box<(dyn Trait + 'static)>`
+   = note: required for the cast from `Box<S>` to `Box<(dyn Trait + 'static)>`
 
 error[E0038]: the trait `Trait` cannot be made into an object
   --> $DIR/wf-convert-unsafe-trait-obj-box.rs:15:5
@@ -43,8 +41,7 @@ LL | trait Trait: Sized {}
    |       -----  ^^^^^ ...because it requires `Self: Sized`
    |       |
    |       this trait cannot be made into an object...
-   = note: required for `Box<S>` to implement `CoerceUnsized<Box<dyn Trait>>`
-   = note: required by cast to type `Box<dyn Trait>`
+   = note: required for the cast from `Box<S>` to `Box<dyn Trait>`
 
 error: aborting due to 3 previous errors
 
diff --git a/tests/ui/wf/wf-convert-unsafe-trait-obj.stderr b/tests/ui/wf/wf-convert-unsafe-trait-obj.stderr
index c9bd4549aaf..e2c71df2feb 100644
--- a/tests/ui/wf/wf-convert-unsafe-trait-obj.stderr
+++ b/tests/ui/wf/wf-convert-unsafe-trait-obj.stderr
@@ -11,8 +11,7 @@ LL | trait Trait: Sized {}
    |       -----  ^^^^^ ...because it requires `Self: Sized`
    |       |
    |       this trait cannot be made into an object...
-   = note: required for `&S` to implement `CoerceUnsized<&dyn Trait>`
-   = note: required by cast to type `&dyn Trait`
+   = note: required for the cast from `&S` to `&dyn Trait`
 
 error[E0038]: the trait `Trait` cannot be made into an object
   --> $DIR/wf-convert-unsafe-trait-obj.rs:17:17
@@ -27,8 +26,7 @@ LL | trait Trait: Sized {}
    |       -----  ^^^^^ ...because it requires `Self: Sized`
    |       |
    |       this trait cannot be made into an object...
-   = note: required for `&S` to implement `CoerceUnsized<&dyn Trait>`
-   = note: required by cast to type `&dyn Trait`
+   = note: required for the cast from `&S` to `&dyn Trait`
 
 error[E0038]: the trait `Trait` cannot be made into an object
   --> $DIR/wf-convert-unsafe-trait-obj.rs:15:5
@@ -43,8 +41,7 @@ LL | trait Trait: Sized {}
    |       -----  ^^^^^ ...because it requires `Self: Sized`
    |       |
    |       this trait cannot be made into an object...
-   = note: required for `&S` to implement `CoerceUnsized<&dyn Trait>`
-   = note: required by cast to type `&dyn Trait`
+   = note: required for the cast from `&S` to `&dyn Trait`
 
 error: aborting due to 3 previous errors
 
diff --git a/tests/ui/wf/wf-unsafe-trait-obj-match.stderr b/tests/ui/wf/wf-unsafe-trait-obj-match.stderr
index d2b41630976..66504e44060 100644
--- a/tests/ui/wf/wf-unsafe-trait-obj-match.stderr
+++ b/tests/ui/wf/wf-unsafe-trait-obj-match.stderr
@@ -25,8 +25,7 @@ LL | trait Trait: Sized {}
    |       -----  ^^^^^ ...because it requires `Self: Sized`
    |       |
    |       this trait cannot be made into an object...
-   = note: required for `&S` to implement `CoerceUnsized<&dyn Trait>`
-   = note: required by cast to type `&dyn Trait`
+   = note: required for the cast from `&S` to `&dyn Trait`
 
 error[E0038]: the trait `Trait` cannot be made into an object
   --> $DIR/wf-unsafe-trait-obj-match.rs:25:25
@@ -45,8 +44,7 @@ LL | trait Trait: Sized {}
    |       -----  ^^^^^ ...because it requires `Self: Sized`
    |       |
    |       this trait cannot be made into an object...
-   = note: required for `&R` to implement `CoerceUnsized<&dyn Trait>`
-   = note: required by cast to type `&dyn Trait`
+   = note: required for the cast from `&R` to `&dyn Trait`
 
 error: aborting due to 3 previous errors
 
diff --git a/triagebot.toml b/triagebot.toml
index 54c8b2060c5..d7cd3ea1275 100644
--- a/triagebot.toml
+++ b/triagebot.toml
@@ -371,31 +371,6 @@ cc = ["@GuillaumeGomez"]
 message = "Some changes might have occurred in exhaustiveness checking"
 cc = ["@Nadrieril"]
 
-[mentions."library"]
-message = """
-Hey! It looks like you've submitted a new PR for the library teams!
-
-If this PR contains changes to any `rust-lang/rust` public library APIs then \
-please comment with `@rustbot label +T-libs-api -T-libs` to tag it \
-appropriately. If this PR contains changes to any unstable APIs please edit \
-the PR description to add a link to the relevant [API Change \
-Proposal](https://std-dev-guide.rust-lang.org/feature-lifecycle/api-change-proposals.html) \
-or [create one](https://github.com/rust-lang/libs-team/issues/new?assignees=&labels=api-change-proposal%2C+T-libs-api&template=api-change-proposal.md&title=%28My+API+Change+Proposal%29) \
-if you haven't already. If you're unsure where your change falls no worries, \
-just leave it as is and the reviewer will take a look and make a decision to \
-forward on if necessary.
-
-Examples of `T-libs-api` changes:
-
-* Stabilizing library features
-* Introducing insta-stable changes such as new implementations of existing \
-  stable traits on existing stable types
-* Introducing new or changing existing unstable library APIs (excluding \
-  permanently unstable features / features without a tracking issue)
-* Changing public documentation in ways that create new stability guarantees
-* Changing observable runtime behavior of library APIs
-"""
-
 [mentions."src/librustdoc/clean/types.rs"]
 cc = ["@camelid"]
 
@@ -507,11 +482,11 @@ compiler-team = [
     "@petrochenkov",
     "@davidtwco",
     "@oli-obk",
-    "@lcnr",
     "@wesleywiser",
 ]
 compiler-team-contributors = [
     "@compiler-errors",
+    "@eholk",
     "@jackh726",
     "@TaKO8Ki",
     "@WaffleLapkin",
@@ -532,6 +507,7 @@ bootstrap = [
     "@Mark-Simulacrum",
     "@albertlarsan68",
     "@ozkanonur",
+    "@clubby789",
 ]
 infra-ci = [
     "@Mark-Simulacrum",
@@ -616,6 +592,7 @@ style-team = [
 "/compiler/rustc_llvm" =                     ["@cuviper"]
 "/compiler/rustc_middle/src/mir" =           ["compiler", "mir"]
 "/compiler/rustc_middle/src/traits" =        ["compiler", "types"]
+"/compiler/rustc_middle/src/ty" =            ["compiler", "types"]
 "/compiler/rustc_const_eval/src/interpret" = ["compiler", "mir"]
 "/compiler/rustc_const_eval/src/transform" = ["compiler", "mir-opt"]
 "/compiler/rustc_mir_build/src/build" =      ["compiler", "mir"]